@joewinke/jatui 0.28.0 → 0.29.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/CLAUDE.md +1 -1
- package/dist/assets/sounds/README.md +11 -0
- package/dist/assets/sounds/attention.d.ts +1 -0
- package/dist/assets/sounds/attention.js +4 -0
- package/dist/assets/sounds/chime.d.ts +1 -0
- package/dist/assets/sounds/chime.js +4 -0
- package/dist/assets/sounds/error-soft.d.ts +1 -0
- package/dist/assets/sounds/error-soft.js +4 -0
- package/dist/assets/sounds/select.d.ts +1 -0
- package/dist/assets/sounds/select.js +4 -0
- package/dist/assets/sounds/tick.d.ts +1 -0
- package/dist/assets/sounds/tick.js +4 -0
- package/dist/sound/backend.d.ts +2 -0
- package/dist/sound/backend.js +2 -1
- package/dist/sound/index.d.ts +4 -2
- package/dist/sound/index.js +3 -2
- package/dist/sound/level.d.ts +42 -0
- package/dist/sound/level.js +63 -0
- package/dist/sound/names.d.ts +24 -1
- package/dist/sound/names.js +75 -0
- package/dist/sound/player.d.ts +14 -1
- package/dist/sound/player.js +18 -1
- package/dist/sound/policy.d.ts +3 -1
- package/dist/sound/preferences.d.ts +8 -2
- package/dist/sound/preferences.js +10 -3
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -229,7 +229,7 @@ const rec = createAudioRecorder({
|
|
|
229
229
|
|
|
230
230
|
### Sound (first-class sibling of motion)
|
|
231
231
|
|
|
232
|
-
One preferences store every app sound goes through. UI + notification sounds are **off by default** (opt-in); the `incoming-call` ringer is **opt-out** (plays out of the box, muted via `categories.calls`). Semantic names (`confirm`, `error`, `notify`, `message`, `send`, `toggle`, `tap`, `incoming-call`) map to bundled CC0 clips or a host's own file. Policy per category: background tab, quiet hours and the quiet/reduced-motion mode silence `ui`/`notifications`; calls always ring. Discipline doc: `docs/sound.md`.
|
|
232
|
+
One preferences store every app sound goes through. UI + notification sounds are **off by default** (opt-in); the `incoming-call` ringer is **opt-out** (plays out of the box, muted via `categories.calls`). Semantic names (`confirm`, `error`, `notify`, `message`, `send`, `toggle`, `tap`, `incoming-call`, plus the booking-delight set `tick` 0.03 / `select` 0.08 / `chime` 0.12 / `attention` 0.10) map to bundled CC0 clips or a host's own file (`SOUND_CLIP_VARIANTS['error-soft']` is a gentler `error`). Policy per category: background tab, quiet hours and the quiet/reduced-motion mode silence `ui`/`notifications`; calls always ring. **Throttle:** per-name `minIntervalMs` (tick 80 ms, select 120 ms) drops — never queues — a play inside the window (`blocked: 'throttled'`); per-call `minIntervalMs` overrides. **Pitch:** `playSound('tick', { pitch: pentatonicPitch(i) })` (semitones → `playbackRate`; `playbackRate` also accepted). `tick` is the one hover sound — call it only on pointer-fine devices. **Site level:** host stamps `<html data-sound="off|subtle">` (like `data-motion`; `setSoundLevel` / `resolveSoundLevel` / `soundLevelDefaults`); `subtle` only starts UI sound on for a visitor with no saved preference — a saved preference (the panel mute) always wins, and `decideSound` is unchanged. Discipline doc: `docs/sound.md`.
|
|
233
233
|
|
|
234
234
|
| Component | Purpose | Key Props |
|
|
235
235
|
|-----------|---------|-----------|
|
|
@@ -12,6 +12,11 @@ CC0-licensed UI sound clips sourced from Kenney's Interface Sounds pack, pre-enc
|
|
|
12
12
|
| `toggle.ts` | toggle-001 | ~0.14s | Toggle switch or checkbox state change |
|
|
13
13
|
| `send.ts` | switch-on | ~0.36s | Message sent or form submitted |
|
|
14
14
|
| `pop.ts` | click-soft | ~0.007s | Subtle click or button tap |
|
|
15
|
+
| `tick.ts` | tick | ~0.05s | Pointer/focus crossed onto a choice (jatui-synthesized) |
|
|
16
|
+
| `select.ts` | select | ~0.10s | A choice was made (jatui-synthesized) |
|
|
17
|
+
| `chime.ts` | chime | ~0.72s | A big thing went right (jatui-synthesized) |
|
|
18
|
+
| `attention.ts` | attention | ~0.39s | Read this before you continue (jatui-synthesized) |
|
|
19
|
+
| `error-soft.ts` | error-soft | ~0.32s | Soft failure tone, variant for `error` (jatui-synthesized) |
|
|
15
20
|
|
|
16
21
|
## Provenance
|
|
17
22
|
|
|
@@ -24,6 +29,10 @@ CC0-licensed UI sound clips sourced from Kenney's Interface Sounds pack, pre-enc
|
|
|
24
29
|
| switch-on | https://github.com/kapishdima/soundcn/blob/main/registry/soundcn/sounds/switch-on/switch-on.ts | CC0 |
|
|
25
30
|
| click-soft | https://github.com/kapishdima/soundcn/blob/main/registry/soundcn/sounds/click-soft/click-soft.ts | CC0 |
|
|
26
31
|
|
|
32
|
+
The five jatui-synthesized clips are CC0 by construction: rendered offline from
|
|
33
|
+
the booking-delight prototype's WebAudio recipes by `scripts/render-sound-clips.mjs`
|
|
34
|
+
(WAV → MP3 @ 64kbps mono 44.1kHz → base64). Re-run it to change one.
|
|
35
|
+
|
|
27
36
|
Original pack: **Kenney Interface Sounds** — https://kenney.nl/assets/interface-sounds (CC0 / Public Domain)
|
|
28
37
|
|
|
29
38
|
## Usage
|
|
@@ -40,6 +49,8 @@ sound player, which loads them lazily and applies the user's preferences
|
|
|
40
49
|
| `send` | send |
|
|
41
50
|
| `toggle` | toggle |
|
|
42
51
|
| `tap` | pop |
|
|
52
|
+
| `tick`, `select`, `chime`, `attention` | the clip of the same name |
|
|
53
|
+
| (variant) `SOUND_CLIP_VARIANTS['error-soft']` | error-soft |
|
|
43
54
|
| `incoming-call` | notify, replayed every 1.2 s (register a real ringer file instead) |
|
|
44
55
|
|
|
45
56
|
```typescript
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const attentionSound = "data:audio/mpeg;base64,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";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Source: rendered by jatui from the booking-delight prototype's WebAudio recipe (triangle 660 -> 494 Hz, low-passed at 1.8 kHz)
|
|
2
|
+
// License: CC0 — synthesized, no third-party audio (jatui-98a2r)
|
|
3
|
+
// Read this before you continue
|
|
4
|
+
export const attentionSound = "data:audio/mpeg;base64,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";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const chimeSound = "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYzLjEuMTAxAAAAAAAAAAAAAAD/+1DAAAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAB0AABh8ABAQEBkZGSIiIiIqKiozMzMzOzs7RERERExMTFVVVVVdXV1mZmZubm5ud3d3f39/f4iIiJGRkZGZmZmioqKiqqqqs7Ozu7u7u8TExMzMzMzV1dXd3d3d5ubm7u7u7vf39////wAAAABMYXZjNjMuMS4AAAAAAAAAAAAAAAAkA7sAAAAAAAAYfPKBrqkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//tQxAAACPBixjTHgAGIkqkDObAABCk3v+UWEgR1ZIAgIjpLEd5D3I/DQWEWQcQsHOAmEkGGAbgOZ9iuBIEAWxCJU+z2YFZE3Sjw4D4OFwfEAYIf8TwQdrP/9/6v9TeLJpAEDd6ugwqTTC4qMHDH/NAokzCGz0E8M5lj8UUBUDQmmAAtvnUgzRy8GgBhBqByJv8MP9PB/XHlFiGoejXf//l1WX4UlWzjjj////zncL+6tYGvLqQgVBVn37oiJVpxlAAEBbbbDfuUv7SqrLmeZv/7UsQIgErIQ0O9zQARaAkigb/5CXTDlUjDY2MmoQ/SvDlxdMMAVXCDy7YxGo12ZZSwALwDadjKhE+pTGbIihrgIOiUsHCwNDwVWGr/A0Kenu2V/W39v///+3//7IkABhuNOJpZAZ/EAwEVMBMCRDBMx3c0QbXpMI7F2zDSIGMIMQkwdgmDBeA8MF8AseB0CAKgSAWYCgDxgagmmEQGkCk1zmSdTMQYGgwJwCS9DB34l8spwyr//7YJARg4QmLSIZUK5oxLmw3QdI3ZheIugath//tSxA4ADNhPEg5/ygGPkmx0/Jl7VZGdCh9BlFClmIGD4GBaiMC4wJANzAfAkMAgCFhAXAHAAERgQg0mH0aydcIrBjGgsGDEBGYEoBQCAVLpK5daiuUuX///////R/+m7RoAIjbbbANKcP0cY7B0MaHtjSrGPAFLKQfeNQI/lW3qMTc/clDkY9qYWLsv1TnWS8SGACAUsik2ytTSQv/D8bl8w7k5SQYAJAaf7k1mQ0YehPmkM8QP6nadJP/WjPgb95//nbbagqypI2gA4UPtdgj/+1LEBoBL8HdrrOkvOVoKZZ2PdUlpzcWSqrLiLdW4zVHA5stSFtDH7JPppF5gBxnQzwuq+0PbjPMrVt9S8pjEjrTSwCYyupW7sZjMtEIIu3rE00O1K0KLgINJYoXTDTeJWPkl/rH/sgAFA///5VALIlhS8IGUepmCiEUZUCbhjigfGFAAMY1YmB5vj8GqRAmN5HGBgWgkCkBK5nZi4ICUy9AoiAZ7H7ZwgnMEA2MYJ3MJgQAgBAIslY5ZbE+OID///gtoibqPQGAKCALQcEeYbv/7UsQJg0wgVxwvb9BZbAqkCa/1SQShyUssBEHpgUjyGMD1+b5eLhjfBPGcoBSYd4BwCDZATMEFIcDLCmIPB6F4BilUSzEB5gHACGCiCGZr6phhNgbmAyBiChoCzjhyivgGCQw///6KBmCopAUMCD4NrCMFXMKqKTzASAQkwJ8CMMJuFtTUIgOw3rQo2SQsxfGYwiC0wPBAwAAFH5PgIC8yMH9dktkbeJxmEQAnalXmKwDAAEDFcE2EyS7cvtX//1AenbWwAO/D9+IOQ7lK1td7//tSxAmADJSRea1g0vFmEmw1oZsDNPgPrIJd8w/Oog7ksOtCNUEC4cxo9l9qVv/D/6+Xa6YiIYm9qTQEUcFJilv1F1ftIg5/5I/Efh+qsgWA6IZyekEO2HpidYWDEQDXxPUcD0u/RbbGAGAlbaAJl2WcuLOOEsM06u7UNSLiuoT1BoeZvyjcZWCpqRFCyxeJm2Osu7x58h/HCXQCQLRaDFaa6OpTKN+HBVkUfLkUWqq02n4igoVkd0XFdwb8LpvzKgMAAAD6i7yT0BLbGABgqCX/+1LECAHKSGUvAPulQTILplHfccGYTRSYJBJMHIAIwgRgTRlHEHg+TAMBZMmqEgwXwIQcAi638l9GWZ/96mU3gw+2292myCoBmEEPmpAVpeO3GKS3YrcAVI///9RF0qWMxpnIBA4ywTQHGMYShIYFMqcDIAYBYBBg2APGFGs2YJAAgsB2aQPIILSiy3rdxqpi4FUuTsxhgZg6emcgSyyN0mAYMgGAAAD///3MROOPeywuOYcDR6uiGvg8YCQFphgBiGtQL2YRYExgehBmKXL8Yf/7UsQWgcpQXSkOe4xJTAwkAC904RoEoCECP7EHLYAXwu63qutgxiOY5YXtKFTmJueY8CKSD9xikDFvsOJlz7L5IQCiEHUw4ESTAeAnMJUIEGoKGPyYyYF4H5hYhGGitumYbAGRg6ApdhY7OGJgwAZZnhnKFDzAwZHLm0+W0TXMPIvMWwPFgEbeHKSvgOr60zATsrFQ2AQCJgYgjGPAXMYmIAxhsAnGISI0cP4hRhyAmmFSAYbAOrhh8gFkRgKwWoQzdtQ4HS/DPCncAwYWW0li//tSxCGDyoBlHgB7g4FAjKNAD3BweUhYsYu0oOw5EAHnllSvq7z69ShlUPNmL9mBUBYZVJKRiNAGCwlZg7oymXSdwYMgDhioAHHEF1GYlwBg0hyYUEQHV46ykJZnztiHzG5QafH2aQKroxRTSuKowvfLKl3V3lX6nn5a8l8IgAxCBAKBSmHwqOYKARpgtB5GJMYKdCwVxhkg2GCgDCdvf6xiggMgY4BgXSQYPGEiafDvLT+mUB+1CWMXf1QIxA5QemkmYVY1vV3n1qV/mupehcD/+1LELQPKNGUWAPuFQUkMooAPcHAIAALmBWDgZKRsRiqg9GE+KiYdx/xtMH1mH2AwYMoOp5rdZgon0SOQ8GU8mzOmRAamx/8XSMnhx75l0IypUYOLJz0AK9i3NY5XePzqSuxK1yAEAMwKAPjKDJKMQgDowZAjDC7OqNx0fkwnAezE3C6PB+8gxJwHDQAEIKhYBW81xTSU1v3k8IY0wnleGV5AgMAfU4tNj3HVX8J+EOssESgDiICQAhSmHMn+YCgRJgFhQmIyWmcUprgQOSYcAP/7UsQ5A8mwYxQAe2OBNYxiAA9scNJ9eYQmJ4AmEQQ0SkwEtxiahs1vn7eoMW7VV9qFhQowH3gTk1t95lVX/KZj0MtdV0DgBTArA+MgAsYWJXMFoTwwMj/TS2KqCoFhhVA6HsnKcYeICwYgoRObA7kuFIu7xuQWYgAUu5bKWxErgB0aI3D5lv/s////6vmZMEPKBEwywB+YFQHBkMj+GHUCUYPohZiBBRG6YN2YbIKRgmBvnhU2iYaQGZoxAOCp1OLPXbWP/uYBoPDkurwQM5gm//tSxEmDyeBZEAB7Y4EqiuIBD2lQVQiNC0//Wv///mVLGn2ZCMgMKDGY9diYfBiDCmEPIGjNfg0E0xBw0jxHVwMM8Dg1AkHDkrW2k1yrlz9VyQFnui3HBHkDQVcE//////0///T9267/2X/qrEoZa6roIAJh8THgPMbnBxgeBjmFiHMbMoVRhCAHgEHs61jeTCQAlBQDSlrrS2/vLn/+CMuHL+cwKglCwGVsE9+r/////9HV///11bW6q5iAAACA3Y25ZKZGTvS9LwyFI4mEwlH/+1LEWoPJ1FcODvtOAUGK4cAOeGAYwROcy3MQWCEwWC4+5JoBBczmNVcl2fZY522EMO7oX19PS++77rv//d+7/9f/f6367Sxp2mQjIAAoCOYHxVJgYAXmACEaYTA1Jp8BBGDiCYYPgZZyQAcGDIBuZJCElh0M1uWsecrZ0tzne4DMkwfz7G//9t3/3e77///FP0amrv//3rlNSwy4SVJgKDRocohkaCxgqLRiU2h482pglgCmDCEAb3Ix5ghgRFmVhnZjS3Z/1bAnAVA0f/+m7//7UsRpAAi4VR2g9gkBQAqhgB9kqO8Zr12+j/0X/rZ/6QKAM9q747R1IbQEGPZFAIRAYHpgOZBsOMpekwbCM9URwsjAVDc2r/r4fh0e5G9DeN9P16v03s//bZ6vs/Wj/12AYxEAATzlEjcn1Ut0D4jBu4KLwJDTdRhWFDw+NlfYYlFRX/X4ZBpu9v//0e/Z7X///x3/6f/RMg6mAAi/fjb3HPyphyQkPnGSQOBhk01k5yiqDG07f/vjS33DrAKqCZn9n/3fr/u59X6KfT//9KoJ//tSxHwBCQBVDA76bkD+iuLwHrUgxUMABF2+slk5nneFPKDCRtGvNMA517noPrZoJu4LNox32V3dWr3Pr//M/Wjemfo6P/+1YAALeV5OIVWAiAEgyFg4GmBBqAH4YXYKeZheFp1JUgJANrEbpKcEM8UerTvyFU5oV+qvLrb/a2tN1aqK3VXHVPMoSgZ/3XdBSmAASZ+1ZQGXPyg8fr4LehGDBhuJxw6ChhABYBD449t0CAMzOOUNTM1fSMIx2/LWMRz7PtWln+VZW+/3dKAEN5r/+1LElgAG3Fcn4O1I4N0LJjwdGVTc46hux4V6v/r0YjldiNoCDJEvB4TAUFJgOf5nycQOCAweDE4U3AwJAVpETmLpGdGd07eO7yaXSq1M7gmV0awlaEk0ruKg3daMdal3kJ/i7WZBkypbbKEJnkpWgkxjRmkdfUg5U0ReIcBIw+TBgBMMhYw0oT7gqBwTGEQIGsuNgoJGnxSfBMWKAJxB5NMg9SkVxZZ0UidNg5SzoRauB9t0mylqU+Y7UqPWEjTS9Ld9Q0ks0/VQvYYhvO+VJv/7UsS8gAZ4MSng40hhIwahoB51ECgNNDKPR8NARmMCAXMICqNaCvDguMHwjM5MuAwXroh+WU9Qy4agky4oBbe+KvYSbRSudNnixOHkARW6Fp9hZhIBxaq4mVINe9Sy2LjJUwlCgRcg6ASjhzgDrPJPOiQg4gAARZFEoyxkepWtA0VgCBRA8wN+PrQUTTAMDjCOIwwCH/pAsF1VoQJV623jT5vXcQGhJbYwgMWHDSRUeJamsjL0OXKbnhqOa1Wo6XLAYRPFqXi8u7jgEl8cUagC//tSxNwDCSg3CkHrqEFeiyDAHokgMCSvv01MNdgxAsgSpf0IBhg8anJygPAyvsw3hwWBeBLYZcfIsvPzooLJFGLaRSH2xOWsHLpHTqqmixhaYrgIkeUH0voTL7uSKULpCB9LHvQwwxyWoQhgogiFSgwXQBrJwrCaUmEteNANisZR+II035cZELBgZHQmNA439FfvZ4N9NCK9YRFKtY+mQk9QNOANVhbYlOie+R1XvdWnRdMR8qZ2hvP3WM7yi/6z/G8ZZ99LH6Z/i+lj+GUU2Br/+1LE6YPLFDMGAPOmwYUG4IAtdQgAshMCql/9p4CIjCeErYAbWcJDIoLBg4gJRIDI3mveENBOBLeA6zPy4vsvVj6uxRrmf89zFm4nLZb/r+q37m8V5vv+8u4GppiVbu6ifnu/XNu9mbQ4R/P47VHu0zbbr84T/rADRgAJZVVEyM07IIm6kMlmqX45CGGLrr+NNRlPCf4iZOBQqwmKCjjIQCOws9LHCYWciH7cSOMQ+mCOEXkBZl1KjGH3iiWFjTxneLnwImYSTQoQNTORGpqbFv/7UsTqgQukMQkg76iBc4Yg1D51EF1n1rrc8PZa/RioOFYNLsGBQ4JcIvyXqN714oBUHWr2RE+WchTysyilsc7pDL6SHfOVCJGK+U0bi49ycj/LelwyPqZ1uT/z8tk/yPM79v8r2se3nZ8DGXefwiT/O+TnJnIQqYrhhyFKFm4cIBwwYqWL8a2Izk0EweREk9D1TYk97vnuhOdHJexSPQvzaLafVFv3az5iUtrTerG1MpJNGKk/eifZyfSztLUv9E9db1MwN2/e/nKaykH7YFp9//tSxOuBDNA3BKHvqklxhmCAHXEJ693gOsZ9a+yhmwjqGrlOwKE4DGGnQg+feURkzQQl1Kv8fcE6mB8dO+fZbluau6TTlb94nteEHbFu9kQYZ1h8yV0HPR6u+X9GaDV+pIW/dH/82iBuCgfMiVY/aGOXwOpS11APC6gkCbDTGoColDxAKGoC7Nm7nbSLFZ6zBnCZ/OMY/KL8an/t+pHhIJti37M08+bjmGcO2M9/8SoDCxa53LNfjTKzve8ZZtUz3wpfredNjS31JeGRgrpN6Yj/+1LE6AALcDEJIOuKQY+xYEAeDSD7wxUgADKK3TI4gYONNo6AqRGihbso/HfvTFp3u/5TfpFnf3zad3O51/L2iZmdP/JWKa+8yp5rGSs6HDn/DlL3pcLz+d/KnlOln05YF/pfX1ywE/KP3AULc9hapGw9sR51HLW+dRAAAlfg2bgDgb7jpK5Lc0BZqoQ8rsnUKrUQKvqR5RbT/yrH/kx2LTpec1zM+NzziyQ7n5lm//HyWdf1PxP9X9ZNipDUpKZRmz+rk04ef21bKqxLTUjwmv/7UsTmA8sZUQQA7ErJcIXgQBHsWT7TxBrfrfv6lir+qWUYedqtRIqkAjZVJ4ZYQQvMxMH0P+ohWKkptrEluZukd7X6Ov1v3/X2/8vgo7v90w4H/lPXexLx63VmsH5c5/7bvMv97tSNGcdYyTLf7TXnIv4+7FtputcVQAAEXPv6ymDRu7eh311mkn+KwKxekiZFCHP8Gr3/29q/CJds43jRXXI18tv96psmZl3nFvuR/8B5y9+jmWffKH06fyfkV+NYhd7JTMtviXa5v3fzh9aX//tSxOmBC8AxBKDjagmGJWBUHY1ZvkWRFjhqbEJTo8hiZR4qCBQHTteA9KLLD3/+3ghz3sPUiL1zMuznVveZE/khkZA4Zsqaqfpl9T/ff65mXe0rvTlNiMNt83KUtlZ+T2o7R649vrJzbxwnX/5n2ncy7g+ddfYWRzCiKAWBEWuKxMpmS0yPvsxC81noxJDb/dH537D6xl+Qemc2Ry8/KlqUOG7Qgh9i6TmZ7baWpITkZT6yEWNpoVmWxqRkWpHfU1yze8I00BCWY37z+iaMZqj/+1LE54HMoV8CoexqiVkF4IBsaUmezhW7GiraeeExldpmChoFDSNlAPFxdgBA44s0WmiOldCD1BiUzRMyOLTnRaaZ55ExybtqVzS2GUK6V3vv8IiOE1m3rrHLpZ51bzpFNBBGBVNwak3dy82JvynQLdF4av/+KFiRn8boXyGllQygDKZ5rMla6ewxGQUhCcxLitNarEW01ETRXvMU3EtA0aaaeeEgj2StfH3xL1xtPVvfSX9usjTGFgONHE1KjqriI/qea+r67uN8y7sbBYRq2P/7UsTngcu5oQKh6GxRZyFgQB0NifNel1v27//T3mYhsieziTg/D2hSYPeY+tCFv+eaIxGynKbQZwIoCmpbOy46ZuBsPTyDaeaf7+vr4ubrnuPid4DBYxLeRo5+V4jqv5m43v2ha2pj8G0h8Ulty3/6dXf/9/Ux1bOMskVF7oRqaZ+6SLb6/7/4rmJHRsL2SWcAwLm2XGpLcJSj0gQfSxIz2BGYYEyua3BXLlZQ47TvAHIDCURTFxTDSysMSNBQUFQ2pNSakspNSnVhr1UVVzcv//tSxOmDy/GJAADobEmKJKBALQ1R69WTMrF+yTGf6XpVv20f/L1mdWVBWn////0KVjAQNBUKu9X0EBEAIhOI2HmURCcKIzB8SgkIIqE0TR4JZ4bMkxCRDRdAbc0ysqmouw9mSqQqCZkJC4qkyLf////////9Yo3FRa9Yo3FaTEFNRTQuMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+1LE5oPOVYT6AukMSaUv30A9IYiqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7UsTWgwtBcvonjFTRDgtXCJYliKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Source: rendered by jatui from the booking-delight prototype's WebAudio recipe (C6 E6 G6 bell arpeggio, 60 ms apart, 600 ms tail)
|
|
2
|
+
// License: CC0 — synthesized, no third-party audio (jatui-98a2r)
|
|
3
|
+
// A big thing just went right (visit booked)
|
|
4
|
+
export const chimeSound = "data:audio/mpeg;base64,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";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const errorSoftSound = "data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+1LEwIOJzBMEAOTASRYXIEWBiTiqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7UsS6A8YgEPpkpSAAAAA0gAAABKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Source: rendered by jatui from the booking-delight prototype's WebAudio recipe (sine 392 -> 330 Hz, 120 ms each)
|
|
2
|
+
// License: CC0 — synthesized, no third-party audio (jatui-98a2r)
|
|
3
|
+
// Soft failure tone (alternative to the error buzz)
|
|
4
|
+
export const errorSoftSound = "data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr/+1LEwIOJzBMEAOTASRYXIEWBiTiqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqv/7UsS6A8YgEPpkpSAAAAA0gAAABKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const selectSound = "data:audio/mpeg;base64,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";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Source: rendered by jatui from the booking-delight prototype's WebAudio recipe (90 ms marimba pluck, 880 Hz + 2.76f partial)
|
|
2
|
+
// License: CC0 — synthesized, no third-party audio (jatui-98a2r)
|
|
3
|
+
// A choice was made
|
|
4
|
+
export const selectSound = "data:audio/mpeg;base64,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";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const tickSound = "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYzLjEuMTAxAAAAAAAAAAAAAAD/+1DAAAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAMAAANCAH9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////////////////////////////wAAAABMYXZjNjMuMS4AAAAAAAAAAAAAAAAkAl8AAAAAAAADQpf8lC4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//tQxAAACRRO2hWMAAGQFaoDN1AAh+/EH8hy7DbK0JYKA1ELhMpwcNhRgMAmMBMyBICIZlOCjteBgDEBNSCncfx/Icqw2/8/Xt9qWGAfPggGSgIFw//5SJ/8p//8nlVQoBIC+0vl8TCwAYWLS2CICYIZIPnIt6cRpy8GCCBga4BgGJwKBhoJhzlFdADAwEC+QeiOE4Tyewo4t4uQh5GmJ5JvIKSRBCgWVLUp/z58uGZqfRX/80FTYJsX+GwgTAn/oNLKmtdxdEuCqQIAGAoChv/7UsQHAQqUPQ4d7oABYYahpD5o2ACgNmDoGOYfAd5g+BWGQidsa2MFx7E/3HSi1EeZReYnL8b0v0bfq8Z6kMYLhSYnCeYaAWDQQEgFR6WsBg6VHhr0f//3s/99AEqytefFDSl/XeZamEAgCYREhjSEn4seZaThurx/RRqCJd5lL7TNYmZGlnot4s2LIuKEFbdTXsWeytBpCosZmUrpRdctsDLpuWKSjvFzYxT10GbCwslNSwSPPtM+7diZo+A4WQpTsAkES25sgadIAggIRD2Y//tSxA6BC9mfACNgSoEkhd+kN6SgjEIR3TRERVBfIra7VarGMzKnstDOrysUznrt6p93aqqQzys6l5dfUrYIK7c9B/M9dKqvXIH3Vxylm/+pTJ8SLvgfQAC/Zh6qFevWF8+fbyOUDCchCgRZVQ4WBoFQVdEIKlXSp3grBWSWAQ0s6s7sBUFeJQVzpUFiuCv/4iEwNB2Jfg11B2s7/9R4RUxBTUU0LjBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Source: rendered by jatui from the booking-delight prototype's WebAudio recipe (35 ms sine blip at 1318.5 Hz, 8% pitch drop)
|
|
2
|
+
// License: CC0 — synthesized, no third-party audio (jatui-98a2r)
|
|
3
|
+
// Pointer or focus crossed onto a choice
|
|
4
|
+
export const tickSound = "data:audio/mpeg;base64,SUQzBAAAAAAAIlRTU0UAAAAOAAADTGF2ZjYzLjEuMTAxAAAAAAAAAAAAAAD/+1DAAAAAAAAAAAAAAAAAAAAAAABJbmZvAAAADwAAAAMAAANCAH9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v////////////////////////////////////////////wAAAABMYXZjNjMuMS4AAAAAAAAAAAAAAAAkAl8AAAAAAAADQpf8lC4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//tQxAAACRRO2hWMAAGQFaoDN1AAh+/EH8hy7DbK0JYKA1ELhMpwcNhRgMAmMBMyBICIZlOCjteBgDEBNSCncfx/Icqw2/8/Xt9qWGAfPggGSgIFw//5SJ/8p//8nlVQoBIC+0vl8TCwAYWLS2CICYIZIPnIt6cRpy8GCCBga4BgGJwKBhoJhzlFdADAwEC+QeiOE4Tyewo4t4uQh5GmJ5JvIKSRBCgWVLUp/z58uGZqfRX/80FTYJsX+GwgTAn/oNLKmtdxdEuCqQIAGAoChv/7UsQHAQqUPQ4d7oABYYahpD5o2ACgNmDoGOYfAd5g+BWGQidsa2MFx7E/3HSi1EeZReYnL8b0v0bfq8Z6kMYLhSYnCeYaAWDQQEgFR6WsBg6VHhr0f//3s/99AEqytefFDSl/XeZamEAgCYREhjSEn4seZaThurx/RRqCJd5lL7TNYmZGlnot4s2LIuKEFbdTXsWeytBpCosZmUrpRdctsDLpuWKSjvFzYxT10GbCwslNSwSPPtM+7diZo+A4WQpTsAkES25sgadIAggIRD2Y//tSxA6BC9mfACNgSoEkhd+kN6SgjEIR3TRERVBfIra7VarGMzKnstDOrysUznrt6p93aqqQzys6l5dfUrYIK7c9B/M9dKqvXIH3Vxylm/+pTJ8SLvgfQAC/Zh6qFevWF8+fbyOUDCchCgRZVQ4WBoFQVdEIKlXSp3grBWSWAQ0s6s7sBUFeJQVzpUFiuCv/4iEwNB2Jfg11B2s7/9R4RUxBTUU0LjBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=";
|
package/dist/sound/backend.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface StartOptions {
|
|
|
11
11
|
loop: boolean;
|
|
12
12
|
/** Gap between repeats when looping; 0 = seamless. */
|
|
13
13
|
loopGapMs: number;
|
|
14
|
+
/** Playback rate (1 = as recorded; 2 = an octave up and twice as short). */
|
|
15
|
+
playbackRate?: number;
|
|
14
16
|
/** Called once when a non-looping voice finishes on its own. */
|
|
15
17
|
onEnded?: () => void;
|
|
16
18
|
}
|
package/dist/sound/backend.js
CHANGED
|
@@ -40,7 +40,7 @@ export function createWebAudioBackend() {
|
|
|
40
40
|
return null; // codec unsupported / network error — stay silent
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
|
-
start(clip, { gain, loop, loopGapMs, onEnded }) {
|
|
43
|
+
start(clip, { gain, loop, loopGapMs, playbackRate = 1, onEnded }) {
|
|
44
44
|
const audio = context();
|
|
45
45
|
if (!audio || !clip)
|
|
46
46
|
return null;
|
|
@@ -58,6 +58,7 @@ export function createWebAudioBackend() {
|
|
|
58
58
|
return;
|
|
59
59
|
source = audio.createBufferSource();
|
|
60
60
|
source.buffer = clip;
|
|
61
|
+
source.playbackRate.value = playbackRate;
|
|
61
62
|
source.loop = loop && loopGapMs <= 0;
|
|
62
63
|
source.connect(out);
|
|
63
64
|
source.onended = () => {
|
package/dist/sound/index.d.ts
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
* mapped to bundled CC0 clips (or a host's own files), a pure policy function,
|
|
6
6
|
* and a drop-in SoundSettings section. Discipline: docs/sound.md.
|
|
7
7
|
*/
|
|
8
|
-
export { SOUND_CATEGORIES, SOUND_NAMES, SOUND_SPECS, CUSTOM_SOUND_SPEC, BUILTIN_CLIPS, isSoundName, soundSpecFor } from './names';
|
|
8
|
+
export { SOUND_CATEGORIES, SOUND_NAMES, SOUND_SPECS, CUSTOM_SOUND_SPEC, BUILTIN_CLIPS, SOUND_CLIP_VARIANTS, PENTATONIC_STEPS, isSoundName, soundSpecFor, pentatonicPitch } from './names';
|
|
9
9
|
export type { SoundCategory, SoundName, SoundSpec } from './names';
|
|
10
10
|
export { DEFAULT_SOUND_PREFERENCES, SOUND_PREFS_STORAGE_KEY, LEGACY_SOUND_ENABLED_KEY, createSoundPreferences, getSoundPreferences, setSoundPreferences, normalizeSoundPreferences } from './preferences';
|
|
11
11
|
export type { SoundPreferences, SoundPreferencesPatch, SoundPreferencesStore, SoundPreferencesStorage, SoundQuietMode, QuietHours, CreateSoundPreferencesOptions } from './preferences';
|
|
12
|
+
export { SOUND_LEVELS, DEFAULT_SOUND_LEVEL, SOUND_LEVEL_ATTR, isSoundLevel, parseSoundLevel, resolveSoundLevel, setSoundLevel, soundLevelDefaults } from './level';
|
|
13
|
+
export type { SoundLevel } from './level';
|
|
12
14
|
export { decideSound, inQuietHours, readSoundEnvironment } from './policy';
|
|
13
15
|
export type { SoundEnvironment, SoundRequest, SoundDecision, SoundBlockReason } from './policy';
|
|
14
|
-
export { createSoundPlayer, getSoundPlayer, setSoundPlayer, playSound } from './player';
|
|
16
|
+
export { createSoundPlayer, getSoundPlayer, setSoundPlayer, playSound, rateFor as soundPlaybackRate } from './player';
|
|
15
17
|
export type { SoundId, SoundPlayer, SoundHandle, PlaySoundOptions, CreateSoundPlayerOptions } from './player';
|
|
16
18
|
export { createWebAudioBackend } from './backend';
|
|
17
19
|
export type { SoundBackend, SoundVoice, StartOptions as SoundStartOptions } from './backend';
|
package/dist/sound/index.js
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* mapped to bundled CC0 clips (or a host's own files), a pure policy function,
|
|
6
6
|
* and a drop-in SoundSettings section. Discipline: docs/sound.md.
|
|
7
7
|
*/
|
|
8
|
-
export { SOUND_CATEGORIES, SOUND_NAMES, SOUND_SPECS, CUSTOM_SOUND_SPEC, BUILTIN_CLIPS, isSoundName, soundSpecFor } from './names';
|
|
8
|
+
export { SOUND_CATEGORIES, SOUND_NAMES, SOUND_SPECS, CUSTOM_SOUND_SPEC, BUILTIN_CLIPS, SOUND_CLIP_VARIANTS, PENTATONIC_STEPS, isSoundName, soundSpecFor, pentatonicPitch } from './names';
|
|
9
9
|
export { DEFAULT_SOUND_PREFERENCES, SOUND_PREFS_STORAGE_KEY, LEGACY_SOUND_ENABLED_KEY, createSoundPreferences, getSoundPreferences, setSoundPreferences, normalizeSoundPreferences } from './preferences';
|
|
10
|
+
export { SOUND_LEVELS, DEFAULT_SOUND_LEVEL, SOUND_LEVEL_ATTR, isSoundLevel, parseSoundLevel, resolveSoundLevel, setSoundLevel, soundLevelDefaults } from './level';
|
|
10
11
|
export { decideSound, inQuietHours, readSoundEnvironment } from './policy';
|
|
11
|
-
export { createSoundPlayer, getSoundPlayer, setSoundPlayer, playSound } from './player';
|
|
12
|
+
export { createSoundPlayer, getSoundPlayer, setSoundPlayer, playSound, rateFor as soundPlaybackRate } from './player';
|
|
12
13
|
export { createWebAudioBackend } from './backend';
|
|
13
14
|
export { default as SoundSettings } from './SoundSettings.svelte';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site sound level — the host's say in whether UI sound starts on.
|
|
3
|
+
*
|
|
4
|
+
* A host stamps `data-sound="off|subtle"` on `<html>` (or any subtree) the
|
|
5
|
+
* same way it stamps `data-motion`, usually from per-site config. The level
|
|
6
|
+
* only changes the DEFAULT for a visitor with no saved preference:
|
|
7
|
+
*
|
|
8
|
+
* off the library default — UI + notification sounds start off.
|
|
9
|
+
* subtle they start on (`enabled: true`) for a visitor who never chose.
|
|
10
|
+
*
|
|
11
|
+
* A saved visitor preference (the panel mute, SoundSettings) always wins,
|
|
12
|
+
* because `createSoundPreferences` applies `defaults` only when nothing is
|
|
13
|
+
* saved. The level never touches volume, categories, quiet hours or the
|
|
14
|
+
* `decideSound` policy — hidden tabs, quiet hours and `quiet: auto` (reduced
|
|
15
|
+
* motion) still silence what they silence.
|
|
16
|
+
*/
|
|
17
|
+
import type { SoundPreferencesPatch } from './preferences';
|
|
18
|
+
export type SoundLevel = 'off' | 'subtle';
|
|
19
|
+
export declare const SOUND_LEVELS: readonly SoundLevel[];
|
|
20
|
+
export declare const DEFAULT_SOUND_LEVEL: SoundLevel;
|
|
21
|
+
/** The attribute a host sets on `<html>` or any subtree. */
|
|
22
|
+
export declare const SOUND_LEVEL_ATTR = "data-sound";
|
|
23
|
+
export declare function isSoundLevel(value: unknown): value is SoundLevel;
|
|
24
|
+
/** Coerce any attribute/config value to a level; unknown values become `off`. */
|
|
25
|
+
export declare function parseSoundLevel(value: unknown, fallback?: SoundLevel): SoundLevel;
|
|
26
|
+
/**
|
|
27
|
+
* The level in force for `node`: its nearest `[data-sound]` ancestor
|
|
28
|
+
* (inclusive), else `<html>`'s, else `off`. An unknown value counts as `off`
|
|
29
|
+
* — a typo fails silent, never loud. SSR-safe (`off`).
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveSoundLevel(node?: Element | null): SoundLevel;
|
|
32
|
+
/**
|
|
33
|
+
* Set the level on a surface (default `<html>`). `null` removes the attribute.
|
|
34
|
+
* No-op without a DOM. Set it before the first sound plays: the shared
|
|
35
|
+
* preferences store reads the level once, when it is created.
|
|
36
|
+
*/
|
|
37
|
+
export declare function setSoundLevel(level: SoundLevel | null, target?: Element | null): void;
|
|
38
|
+
/**
|
|
39
|
+
* The preference defaults a level implies, for `createSoundPreferences({ defaults })`.
|
|
40
|
+
* A panel scoping its own store to a subtree passes `soundLevelDefaults(resolveSoundLevel(panelEl))`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function soundLevelDefaults(level: SoundLevel): SoundPreferencesPatch;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site sound level — the host's say in whether UI sound starts on.
|
|
3
|
+
*
|
|
4
|
+
* A host stamps `data-sound="off|subtle"` on `<html>` (or any subtree) the
|
|
5
|
+
* same way it stamps `data-motion`, usually from per-site config. The level
|
|
6
|
+
* only changes the DEFAULT for a visitor with no saved preference:
|
|
7
|
+
*
|
|
8
|
+
* off the library default — UI + notification sounds start off.
|
|
9
|
+
* subtle they start on (`enabled: true`) for a visitor who never chose.
|
|
10
|
+
*
|
|
11
|
+
* A saved visitor preference (the panel mute, SoundSettings) always wins,
|
|
12
|
+
* because `createSoundPreferences` applies `defaults` only when nothing is
|
|
13
|
+
* saved. The level never touches volume, categories, quiet hours or the
|
|
14
|
+
* `decideSound` policy — hidden tabs, quiet hours and `quiet: auto` (reduced
|
|
15
|
+
* motion) still silence what they silence.
|
|
16
|
+
*/
|
|
17
|
+
export const SOUND_LEVELS = ['off', 'subtle'];
|
|
18
|
+
export const DEFAULT_SOUND_LEVEL = 'off';
|
|
19
|
+
/** The attribute a host sets on `<html>` or any subtree. */
|
|
20
|
+
export const SOUND_LEVEL_ATTR = 'data-sound';
|
|
21
|
+
export function isSoundLevel(value) {
|
|
22
|
+
return typeof value === 'string' && SOUND_LEVELS.includes(value);
|
|
23
|
+
}
|
|
24
|
+
/** Coerce any attribute/config value to a level; unknown values become `off`. */
|
|
25
|
+
export function parseSoundLevel(value, fallback = DEFAULT_SOUND_LEVEL) {
|
|
26
|
+
if (typeof value !== 'string')
|
|
27
|
+
return fallback;
|
|
28
|
+
const v = value.trim().toLowerCase();
|
|
29
|
+
return isSoundLevel(v) ? v : fallback;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The level in force for `node`: its nearest `[data-sound]` ancestor
|
|
33
|
+
* (inclusive), else `<html>`'s, else `off`. An unknown value counts as `off`
|
|
34
|
+
* — a typo fails silent, never loud. SSR-safe (`off`).
|
|
35
|
+
*/
|
|
36
|
+
export function resolveSoundLevel(node) {
|
|
37
|
+
const el = (node ?? (typeof document !== 'undefined' ? document.documentElement : null));
|
|
38
|
+
if (!el || typeof el.closest !== 'function')
|
|
39
|
+
return DEFAULT_SOUND_LEVEL;
|
|
40
|
+
const host = el.closest(`[${SOUND_LEVEL_ATTR}]`);
|
|
41
|
+
return host ? parseSoundLevel(host.getAttribute(SOUND_LEVEL_ATTR)) : DEFAULT_SOUND_LEVEL;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set the level on a surface (default `<html>`). `null` removes the attribute.
|
|
45
|
+
* No-op without a DOM. Set it before the first sound plays: the shared
|
|
46
|
+
* preferences store reads the level once, when it is created.
|
|
47
|
+
*/
|
|
48
|
+
export function setSoundLevel(level, target) {
|
|
49
|
+
const el = target ?? (typeof document !== 'undefined' ? document.documentElement : null);
|
|
50
|
+
if (!el)
|
|
51
|
+
return;
|
|
52
|
+
if (level === null)
|
|
53
|
+
el.removeAttribute(SOUND_LEVEL_ATTR);
|
|
54
|
+
else
|
|
55
|
+
el.setAttribute(SOUND_LEVEL_ATTR, level);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The preference defaults a level implies, for `createSoundPreferences({ defaults })`.
|
|
59
|
+
* A panel scoping its own store to a subtree passes `soundLevelDefaults(resolveSoundLevel(panelEl))`.
|
|
60
|
+
*/
|
|
61
|
+
export function soundLevelDefaults(level) {
|
|
62
|
+
return level === 'subtle' ? { enabled: true } : {};
|
|
63
|
+
}
|
package/dist/sound/names.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export type SoundCategory = 'ui' | 'notifications' | 'calls';
|
|
12
12
|
export declare const SOUND_CATEGORIES: readonly SoundCategory[];
|
|
13
|
-
export type SoundName = 'confirm' | 'error' | 'notify' | 'message' | 'send' | 'toggle' | 'tap' | 'incoming-call';
|
|
13
|
+
export type SoundName = 'confirm' | 'error' | 'notify' | 'message' | 'send' | 'toggle' | 'tap' | 'tick' | 'select' | 'chime' | 'attention' | 'incoming-call';
|
|
14
14
|
export declare const SOUND_NAMES: readonly SoundName[];
|
|
15
15
|
export interface SoundSpec {
|
|
16
16
|
category: SoundCategory;
|
|
@@ -25,6 +25,11 @@ export interface SoundSpec {
|
|
|
25
25
|
* ringer file); >0 replays a short clip on an interval (the built-in ring).
|
|
26
26
|
*/
|
|
27
27
|
loopGapMs: number;
|
|
28
|
+
/**
|
|
29
|
+
* Throttle floor in ms: a play within this long of the last one that
|
|
30
|
+
* actually sounded is DROPPED (never queued). 0 = no throttle.
|
|
31
|
+
*/
|
|
32
|
+
minIntervalMs: number;
|
|
28
33
|
description: string;
|
|
29
34
|
}
|
|
30
35
|
export declare const SOUND_SPECS: Record<SoundName, SoundSpec>;
|
|
@@ -37,3 +42,21 @@ export declare function soundSpecFor(name: string): SoundSpec;
|
|
|
37
42
|
* that never play a sound never ship the base64 payloads in their entry chunk.
|
|
38
43
|
*/
|
|
39
44
|
export declare const BUILTIN_CLIPS: Record<SoundName, () => Promise<string>>;
|
|
45
|
+
/**
|
|
46
|
+
* Alternative bundled clips a host can point a name at:
|
|
47
|
+
*
|
|
48
|
+
* await getSoundPlayer().register('error', await SOUND_CLIP_VARIANTS['error-soft'](), { volume: 0.08 })
|
|
49
|
+
*
|
|
50
|
+
* `error-soft` is two low sine tones (392 → 330 Hz) with no buzz — for
|
|
51
|
+
* surfaces where the stock error buzz is too harsh (booking flows).
|
|
52
|
+
*/
|
|
53
|
+
export declare const SOUND_CLIP_VARIANTS: {
|
|
54
|
+
'error-soft': () => Promise<string>;
|
|
55
|
+
};
|
|
56
|
+
/** Semitone offsets of a rising major pentatonic — one per step of a 7-item strip. */
|
|
57
|
+
export declare const PENTATONIC_STEPS: readonly number[];
|
|
58
|
+
/**
|
|
59
|
+
* Semitone offset for item `index` on a rising pentatonic (wraps up an octave
|
|
60
|
+
* past the table), for `playSound('tick', { pitch: pentatonicPitch(i) })`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function pentatonicPitch(index: number): number;
|
package/dist/sound/names.js
CHANGED
|
@@ -17,6 +17,10 @@ export const SOUND_NAMES = [
|
|
|
17
17
|
'send',
|
|
18
18
|
'toggle',
|
|
19
19
|
'tap',
|
|
20
|
+
'tick',
|
|
21
|
+
'select',
|
|
22
|
+
'chime',
|
|
23
|
+
'attention',
|
|
20
24
|
'incoming-call'
|
|
21
25
|
];
|
|
22
26
|
export const SOUND_SPECS = {
|
|
@@ -26,6 +30,7 @@ export const SOUND_SPECS = {
|
|
|
26
30
|
essential: false,
|
|
27
31
|
loop: false,
|
|
28
32
|
loopGapMs: 0,
|
|
33
|
+
minIntervalMs: 0,
|
|
29
34
|
description: 'An important action succeeded (saved, paid, published)'
|
|
30
35
|
},
|
|
31
36
|
error: {
|
|
@@ -34,6 +39,7 @@ export const SOUND_SPECS = {
|
|
|
34
39
|
essential: true,
|
|
35
40
|
loop: false,
|
|
36
41
|
loopGapMs: 0,
|
|
42
|
+
minIntervalMs: 0,
|
|
37
43
|
description: 'An action failed'
|
|
38
44
|
},
|
|
39
45
|
notify: {
|
|
@@ -42,6 +48,7 @@ export const SOUND_SPECS = {
|
|
|
42
48
|
essential: false,
|
|
43
49
|
loop: false,
|
|
44
50
|
loopGapMs: 0,
|
|
51
|
+
minIntervalMs: 0,
|
|
45
52
|
description: 'Something happened the user did not cause'
|
|
46
53
|
},
|
|
47
54
|
message: {
|
|
@@ -50,6 +57,7 @@ export const SOUND_SPECS = {
|
|
|
50
57
|
essential: false,
|
|
51
58
|
loop: false,
|
|
52
59
|
loopGapMs: 0,
|
|
60
|
+
minIntervalMs: 0,
|
|
53
61
|
description: 'A message arrived from another person'
|
|
54
62
|
},
|
|
55
63
|
send: {
|
|
@@ -58,6 +66,7 @@ export const SOUND_SPECS = {
|
|
|
58
66
|
essential: false,
|
|
59
67
|
loop: false,
|
|
60
68
|
loopGapMs: 0,
|
|
69
|
+
minIntervalMs: 0,
|
|
61
70
|
description: 'The user sent a message or submitted a form'
|
|
62
71
|
},
|
|
63
72
|
toggle: {
|
|
@@ -66,6 +75,7 @@ export const SOUND_SPECS = {
|
|
|
66
75
|
essential: false,
|
|
67
76
|
loop: false,
|
|
68
77
|
loopGapMs: 0,
|
|
78
|
+
minIntervalMs: 0,
|
|
69
79
|
description: 'A switch changed state'
|
|
70
80
|
},
|
|
71
81
|
tap: {
|
|
@@ -74,14 +84,52 @@ export const SOUND_SPECS = {
|
|
|
74
84
|
essential: false,
|
|
75
85
|
loop: false,
|
|
76
86
|
loopGapMs: 0,
|
|
87
|
+
minIntervalMs: 0,
|
|
77
88
|
description: 'A deliberate, low-frequency press'
|
|
78
89
|
},
|
|
90
|
+
tick: {
|
|
91
|
+
category: 'ui',
|
|
92
|
+
volume: 0.03,
|
|
93
|
+
essential: false,
|
|
94
|
+
loop: false,
|
|
95
|
+
loopGapMs: 0,
|
|
96
|
+
minIntervalMs: 80,
|
|
97
|
+
description: 'The pointer or keyboard focus crossed onto a choice (pointer-fine only, pitch by position)'
|
|
98
|
+
},
|
|
99
|
+
select: {
|
|
100
|
+
category: 'ui',
|
|
101
|
+
volume: 0.08,
|
|
102
|
+
essential: false,
|
|
103
|
+
loop: false,
|
|
104
|
+
loopGapMs: 0,
|
|
105
|
+
minIntervalMs: 120,
|
|
106
|
+
description: 'The user chose something (a card, a day, a time, an answer)'
|
|
107
|
+
},
|
|
108
|
+
chime: {
|
|
109
|
+
category: 'ui',
|
|
110
|
+
volume: 0.12,
|
|
111
|
+
essential: false,
|
|
112
|
+
loop: false,
|
|
113
|
+
loopGapMs: 0,
|
|
114
|
+
minIntervalMs: 0,
|
|
115
|
+
description: 'A big thing just went right (the visit is booked) — rarer and warmer than confirm'
|
|
116
|
+
},
|
|
117
|
+
attention: {
|
|
118
|
+
category: 'ui',
|
|
119
|
+
volume: 0.1,
|
|
120
|
+
essential: false,
|
|
121
|
+
loop: false,
|
|
122
|
+
loopGapMs: 0,
|
|
123
|
+
minIntervalMs: 0,
|
|
124
|
+
description: 'Read this before you continue — calm, never an alarm'
|
|
125
|
+
},
|
|
79
126
|
'incoming-call': {
|
|
80
127
|
category: 'calls',
|
|
81
128
|
volume: 0.5,
|
|
82
129
|
essential: true,
|
|
83
130
|
loop: true,
|
|
84
131
|
loopGapMs: 1200,
|
|
132
|
+
minIntervalMs: 0,
|
|
85
133
|
description: 'Someone is calling — rings until answered or declined'
|
|
86
134
|
}
|
|
87
135
|
};
|
|
@@ -92,6 +140,7 @@ export const CUSTOM_SOUND_SPEC = {
|
|
|
92
140
|
essential: false,
|
|
93
141
|
loop: false,
|
|
94
142
|
loopGapMs: 0,
|
|
143
|
+
minIntervalMs: 0,
|
|
95
144
|
description: 'Host-registered sound'
|
|
96
145
|
};
|
|
97
146
|
/** Pre-semantic clip names (utils/sound.ts era) mapped to their semantic spec. */
|
|
@@ -117,5 +166,31 @@ export const BUILTIN_CLIPS = {
|
|
|
117
166
|
send: () => import('../assets/sounds/send').then((m) => m.sendSound),
|
|
118
167
|
toggle: () => import('../assets/sounds/toggle').then((m) => m.toggleSound),
|
|
119
168
|
tap: () => import('../assets/sounds/pop').then((m) => m.popSound),
|
|
169
|
+
tick: () => import('../assets/sounds/tick').then((m) => m.tickSound),
|
|
170
|
+
select: () => import('../assets/sounds/select').then((m) => m.selectSound),
|
|
171
|
+
chime: () => import('../assets/sounds/chime').then((m) => m.chimeSound),
|
|
172
|
+
attention: () => import('../assets/sounds/attention').then((m) => m.attentionSound),
|
|
120
173
|
'incoming-call': () => import('../assets/sounds/notify').then((m) => m.notifySound)
|
|
121
174
|
};
|
|
175
|
+
/**
|
|
176
|
+
* Alternative bundled clips a host can point a name at:
|
|
177
|
+
*
|
|
178
|
+
* await getSoundPlayer().register('error', await SOUND_CLIP_VARIANTS['error-soft'](), { volume: 0.08 })
|
|
179
|
+
*
|
|
180
|
+
* `error-soft` is two low sine tones (392 → 330 Hz) with no buzz — for
|
|
181
|
+
* surfaces where the stock error buzz is too harsh (booking flows).
|
|
182
|
+
*/
|
|
183
|
+
export const SOUND_CLIP_VARIANTS = {
|
|
184
|
+
'error-soft': () => import('../assets/sounds/error-soft').then((m) => m.errorSoftSound)
|
|
185
|
+
};
|
|
186
|
+
/** Semitone offsets of a rising major pentatonic — one per step of a 7-item strip. */
|
|
187
|
+
export const PENTATONIC_STEPS = [0, 2, 4, 7, 9, 12, 14];
|
|
188
|
+
/**
|
|
189
|
+
* Semitone offset for item `index` on a rising pentatonic (wraps up an octave
|
|
190
|
+
* past the table), for `playSound('tick', { pitch: pentatonicPitch(i) })`.
|
|
191
|
+
*/
|
|
192
|
+
export function pentatonicPitch(index) {
|
|
193
|
+
const i = Math.max(0, Math.floor(index));
|
|
194
|
+
const n = 5; // notes per octave — the table's last two entries are the next octave
|
|
195
|
+
return PENTATONIC_STEPS[i % n] + 12 * Math.floor(i / n);
|
|
196
|
+
}
|
package/dist/sound/player.d.ts
CHANGED
|
@@ -24,9 +24,18 @@ export interface PlaySoundOptions {
|
|
|
24
24
|
category?: SoundCategory;
|
|
25
25
|
essential?: boolean;
|
|
26
26
|
loop?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Pitch offset in semitones, applied through `playbackRate` (so it also
|
|
29
|
+
* shortens/lengthens the clip). `pentatonicPitch(i)` gives a rising scale.
|
|
30
|
+
*/
|
|
31
|
+
pitch?: number;
|
|
32
|
+
/** Explicit playback rate; multiplied with `pitch` when both are given. */
|
|
33
|
+
playbackRate?: number;
|
|
34
|
+
/** Throttle floor in ms for this play, replacing the spec's `minIntervalMs`. */
|
|
35
|
+
minIntervalMs?: number;
|
|
27
36
|
/**
|
|
28
37
|
* Explicit user test (a "Preview" button in settings): bypasses every gate
|
|
29
|
-
* except master volume. Never use it for app-triggered sounds.
|
|
38
|
+
* except master volume (and the throttle). Never use it for app-triggered sounds.
|
|
30
39
|
*/
|
|
31
40
|
preview?: boolean;
|
|
32
41
|
}
|
|
@@ -50,8 +59,12 @@ export interface CreateSoundPlayerOptions {
|
|
|
50
59
|
preferences?: SoundPreferencesStore;
|
|
51
60
|
environment?: () => SoundEnvironment;
|
|
52
61
|
backend?: SoundBackend;
|
|
62
|
+
/** Monotonic ms clock for the throttle (test seam). Defaults to `performance.now`. */
|
|
63
|
+
now?: () => number;
|
|
53
64
|
}
|
|
54
65
|
export declare function createSoundPlayer(options?: CreateSoundPlayerOptions): SoundPlayer;
|
|
66
|
+
/** Effective playback rate for a play: `playbackRate × 2^(pitch/12)`, clamped to a sane range. */
|
|
67
|
+
export declare function rateFor(opts: Pick<PlaySoundOptions, 'pitch' | 'playbackRate'>): number;
|
|
55
68
|
/** The app-wide player, bound to the shared preferences store. */
|
|
56
69
|
export declare function getSoundPlayer(): SoundPlayer;
|
|
57
70
|
/** Test seam: replace (or with no argument, drop) the shared player. */
|
package/dist/sound/player.js
CHANGED
|
@@ -22,6 +22,9 @@ export function createSoundPlayer(options = {}) {
|
|
|
22
22
|
let backend = options.backend ?? null;
|
|
23
23
|
const entries = new Map();
|
|
24
24
|
const active = new Set();
|
|
25
|
+
const now = options.now ?? (() => globalThis.performance?.now() ?? Date.now());
|
|
26
|
+
// Last time each name actually sounded — the throttle drops, never queues.
|
|
27
|
+
const lastPlayed = new Map();
|
|
25
28
|
const audio = () => (backend ??= createWebAudioBackend());
|
|
26
29
|
function clipFor(name) {
|
|
27
30
|
let entry = entries.get(name);
|
|
@@ -61,7 +64,8 @@ export function createSoundPlayer(options = {}) {
|
|
|
61
64
|
volume: opts.volume ?? base.volume,
|
|
62
65
|
category: opts.category ?? base.category,
|
|
63
66
|
essential: opts.essential ?? base.essential,
|
|
64
|
-
loop: opts.loop ?? base.loop
|
|
67
|
+
loop: opts.loop ?? base.loop,
|
|
68
|
+
minIntervalMs: opts.minIntervalMs ?? base.minIntervalMs ?? 0
|
|
65
69
|
};
|
|
66
70
|
const p = prefs.get();
|
|
67
71
|
let gain;
|
|
@@ -75,7 +79,14 @@ export function createSoundPlayer(options = {}) {
|
|
|
75
79
|
if (!d.play)
|
|
76
80
|
return silent(d.reason);
|
|
77
81
|
gain = d.gain;
|
|
82
|
+
const t = now();
|
|
83
|
+
const last = lastPlayed.get(name);
|
|
84
|
+
if (spec.minIntervalMs > 0 && last !== undefined && t - last < spec.minIntervalMs) {
|
|
85
|
+
return silent('throttled');
|
|
86
|
+
}
|
|
87
|
+
lastPlayed.set(name, t);
|
|
78
88
|
}
|
|
89
|
+
const playbackRate = rateFor(opts);
|
|
79
90
|
let voice = null;
|
|
80
91
|
let playing = true;
|
|
81
92
|
const record = {
|
|
@@ -103,6 +114,7 @@ export function createSoundPlayer(options = {}) {
|
|
|
103
114
|
gain,
|
|
104
115
|
loop: spec.loop,
|
|
105
116
|
loopGapMs: spec.loopGapMs,
|
|
117
|
+
playbackRate,
|
|
106
118
|
onEnded: () => record.handle.stop()
|
|
107
119
|
})
|
|
108
120
|
: null;
|
|
@@ -125,6 +137,11 @@ export function createSoundPlayer(options = {}) {
|
|
|
125
137
|
}
|
|
126
138
|
};
|
|
127
139
|
}
|
|
140
|
+
/** Effective playback rate for a play: `playbackRate × 2^(pitch/12)`, clamped to a sane range. */
|
|
141
|
+
export function rateFor(opts) {
|
|
142
|
+
const rate = (opts.playbackRate ?? 1) * Math.pow(2, (opts.pitch ?? 0) / 12);
|
|
143
|
+
return Number.isFinite(rate) && rate > 0 ? Math.min(8, Math.max(0.125, rate)) : 1;
|
|
144
|
+
}
|
|
128
145
|
let shared = null;
|
|
129
146
|
/** The app-wide player, bound to the shared preferences store. */
|
|
130
147
|
export function getSoundPlayer() {
|
package/dist/sound/policy.d.ts
CHANGED
|
@@ -18,7 +18,9 @@ export interface SoundRequest {
|
|
|
18
18
|
/** Base gain 0–1 (the spec volume or the caller's override). */
|
|
19
19
|
volume: number;
|
|
20
20
|
}
|
|
21
|
-
export type SoundBlockReason = 'disabled' | 'category-muted' | 'hidden' | 'quiet-hours' | 'quiet' | 'silent'
|
|
21
|
+
export type SoundBlockReason = 'disabled' | 'category-muted' | 'hidden' | 'quiet-hours' | 'quiet' | 'silent'
|
|
22
|
+
/** Dropped by the per-name throttle (set by the player, never by decideSound). */
|
|
23
|
+
| 'throttled';
|
|
22
24
|
export type SoundDecision = {
|
|
23
25
|
play: true;
|
|
24
26
|
gain: number;
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* across tabs via the `storage` event, and tolerant of corrupt/partial JSON.
|
|
8
8
|
*
|
|
9
9
|
* UI and notification sounds are OFF by default (opt-in); calls are ON by
|
|
10
|
-
* default (opt-out) so an incoming call rings out of the box. A
|
|
10
|
+
* default (opt-out) so an incoming call rings out of the box. A host can flip
|
|
11
|
+
* the UI default per site with `<html data-sound="subtle">` (level.ts); a
|
|
12
|
+
* saved visitor preference always wins over it. A device that set the pre-0.28 boolean
|
|
11
13
|
* (`jatui-sound-enabled`) is migrated on first read.
|
|
12
14
|
*/
|
|
13
15
|
import { type SoundCategory } from './names';
|
|
@@ -64,7 +66,11 @@ export interface CreateSoundPreferencesOptions {
|
|
|
64
66
|
defaults?: SoundPreferencesPatch;
|
|
65
67
|
}
|
|
66
68
|
export declare function createSoundPreferences(options?: CreateSoundPreferencesOptions): SoundPreferencesStore;
|
|
67
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* The app-wide store (lazy, so SSR imports never touch storage). Its defaults
|
|
71
|
+
* come from the site sound level on `<html data-sound>` at creation time, so
|
|
72
|
+
* `subtle` starts UI sound on for a visitor with nothing saved (see level.ts).
|
|
73
|
+
*/
|
|
68
74
|
export declare function getSoundPreferences(): SoundPreferencesStore;
|
|
69
75
|
/** Test seam: replace (or with no argument, drop) the shared store. */
|
|
70
76
|
export declare function setSoundPreferences(store: SoundPreferencesStore | null): void;
|
|
@@ -7,10 +7,13 @@
|
|
|
7
7
|
* across tabs via the `storage` event, and tolerant of corrupt/partial JSON.
|
|
8
8
|
*
|
|
9
9
|
* UI and notification sounds are OFF by default (opt-in); calls are ON by
|
|
10
|
-
* default (opt-out) so an incoming call rings out of the box. A
|
|
10
|
+
* default (opt-out) so an incoming call rings out of the box. A host can flip
|
|
11
|
+
* the UI default per site with `<html data-sound="subtle">` (level.ts); a
|
|
12
|
+
* saved visitor preference always wins over it. A device that set the pre-0.28 boolean
|
|
11
13
|
* (`jatui-sound-enabled`) is migrated on first read.
|
|
12
14
|
*/
|
|
13
15
|
import { SOUND_CATEGORIES } from './names';
|
|
16
|
+
import { resolveSoundLevel, soundLevelDefaults } from './level';
|
|
14
17
|
export const SOUND_PREFS_STORAGE_KEY = 'jatui-sound-prefs';
|
|
15
18
|
/** The pre-semantic boolean key from utils/sound.ts — read once to migrate. */
|
|
16
19
|
export const LEGACY_SOUND_ENABLED_KEY = 'jatui-sound-enabled';
|
|
@@ -134,9 +137,13 @@ export function createSoundPreferences(options = {}) {
|
|
|
134
137
|
};
|
|
135
138
|
}
|
|
136
139
|
let shared = null;
|
|
137
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* The app-wide store (lazy, so SSR imports never touch storage). Its defaults
|
|
142
|
+
* come from the site sound level on `<html data-sound>` at creation time, so
|
|
143
|
+
* `subtle` starts UI sound on for a visitor with nothing saved (see level.ts).
|
|
144
|
+
*/
|
|
138
145
|
export function getSoundPreferences() {
|
|
139
|
-
return (shared ??= createSoundPreferences());
|
|
146
|
+
return (shared ??= createSoundPreferences({ defaults: soundLevelDefaults(resolveSoundLevel()) }));
|
|
140
147
|
}
|
|
141
148
|
/** Test seam: replace (or with no argument, drop) the shared store. */
|
|
142
149
|
export function setSoundPreferences(store) {
|