@joewinke/jatui 0.27.1 → 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.
Files changed (46) hide show
  1. package/CLAUDE.md +37 -0
  2. package/dist/assets/sounds/README.md +27 -14
  3. package/dist/assets/sounds/attention.d.ts +1 -0
  4. package/dist/assets/sounds/attention.js +4 -0
  5. package/dist/assets/sounds/chime.d.ts +1 -0
  6. package/dist/assets/sounds/chime.js +4 -0
  7. package/dist/assets/sounds/error-soft.d.ts +1 -0
  8. package/dist/assets/sounds/error-soft.js +4 -0
  9. package/dist/assets/sounds/select.d.ts +1 -0
  10. package/dist/assets/sounds/select.js +4 -0
  11. package/dist/assets/sounds/tick.d.ts +1 -0
  12. package/dist/assets/sounds/tick.js +4 -0
  13. package/dist/index.d.ts +4 -1
  14. package/dist/index.js +10 -2
  15. package/dist/motion/easing.d.ts +14 -0
  16. package/dist/motion/easing.js +67 -0
  17. package/dist/motion/index.d.ts +17 -0
  18. package/dist/motion/index.js +11 -0
  19. package/dist/motion/level.d.ts +88 -0
  20. package/dist/motion/level.js +132 -0
  21. package/dist/motion/store.d.ts +40 -0
  22. package/dist/motion/store.js +132 -0
  23. package/dist/motion/transitions.d.ts +72 -0
  24. package/dist/motion/transitions.js +112 -0
  25. package/dist/sound/SoundSettings.svelte +209 -0
  26. package/dist/sound/SoundSettings.svelte.d.ts +18 -0
  27. package/dist/sound/backend.d.ts +24 -0
  28. package/dist/sound/backend.js +96 -0
  29. package/dist/sound/index.d.ts +20 -0
  30. package/dist/sound/index.js +14 -0
  31. package/dist/sound/level.d.ts +42 -0
  32. package/dist/sound/level.js +63 -0
  33. package/dist/sound/names.d.ts +62 -0
  34. package/dist/sound/names.js +196 -0
  35. package/dist/sound/player.d.ts +73 -0
  36. package/dist/sound/player.js +158 -0
  37. package/dist/sound/policy.d.ts +36 -0
  38. package/dist/sound/policy.js +56 -0
  39. package/dist/sound/preferences.d.ts +76 -0
  40. package/dist/sound/preferences.js +152 -0
  41. package/dist/styles/motion.css +88 -9
  42. package/dist/transitions/glide.d.ts +18 -6
  43. package/dist/transitions/glide.js +26 -31
  44. package/dist/utils/sound.d.ts +6 -0
  45. package/dist/utils/sound.js +12 -54
  46. package/package.json +1 -1
package/CLAUDE.md CHANGED
@@ -227,6 +227,43 @@ const rec = createAudioRecorder({
227
227
  // Methods: start() stop() pause() resume() cancel() reset() destroy()
228
228
  ```
229
229
 
230
+ ### Sound (first-class sibling of motion)
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`, 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
+
234
+ | Component | Purpose | Key Props |
235
+ |-----------|---------|-----------|
236
+ | `SoundSettings` | Drop-in settings section over the store: master switch, volume, per-category rows (calls row + volume stay live when the master switch is off), quiet hours, preview buttons. | `preferences?`, `player?`, `categories?: SoundCategory[]`, `showQuietHours?`, `title?`, `class?` |
237
+
238
+ ```typescript
239
+ import {
240
+ playSound, // playSound('confirm') → SoundHandle { stop, playing, blocked } — never throws
241
+ getSoundPlayer, // .register(name, src, spec?) · .play · .preload · .stopAll
242
+ getSoundPreferences, // .get · .set(patch) · .setCategory · .reset · .subscribe (localStorage 'jatui-sound-prefs', cross-tab)
243
+ createSoundPreferences, createSoundPlayer, // isolated instances (tests, demos)
244
+ decideSound, // the pure policy, for custom players
245
+ SOUND_NAMES, SOUND_SPECS, SOUND_CATEGORIES
246
+ } from "jatui"
247
+ // handle.blocked: 'disabled' | 'category-muted' | 'hidden' | 'quiet-hours' | 'quiet' | 'silent'
248
+ // { preview: true } bypasses every check but master volume — only behind a "test sound" button.
249
+ // Legacy registerSound / isSoundEnabled / setSoundEnabled still exported and route through the store.
250
+ ```
251
+
252
+ ### Motion level
253
+
254
+ Motion is a token layer (`styles/motion.css`: `--motion-glide`/`spring`/`standard` curves; `--motion-instant`/`fast`/`enter`/`move` durations). `data-motion="calm|standard|lively"` on `<html>` or any subtree rescales durations (×0.75/×1/×1.25) and travel (8/16/24px); `calm` also flattens springs and stops `.jatui-motion-ambient` (mark decorative loops with it). `prefers-reduced-motion` wins at every level. An unknown value resolves to `standard`. Scheme + rules: `docs/motion.md`.
255
+
256
+ ```typescript
257
+ import {
258
+ motionFade, motionScale, motionSlide, glide, // token-built transitions (use instead of svelte/transition fade/scale/slide/fly)
259
+ setMotionLevel, // setMotionLevel('calm') · setMotionLevel('lively', heroEl) · setMotionLevel(null)
260
+ createMotionLevelStore, // persisted store: $motion.level / .reduced / .effective
261
+ getMotionContext, motionDuration, motionEasing // read the level from JS
262
+ } from "jatui"
263
+ // Transition params: duration = token ('instant'|'fast'|'enter'|'move') or standard-level ms (scaled by the level);
264
+ // easing = token ('glide'|'spring'|'standard') or fn; level pins it instead of reading the DOM.
265
+ ```
266
+
230
267
  ### PDF
231
268
 
232
269
  | Component | Purpose | Key Props |
@@ -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,24 +29,32 @@ 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
30
39
 
31
- ```typescript
32
- import { registerSound, play, setSoundEnabled, isSoundEnabled } from '$lib/utils/sound';
33
- import { successSound } from '$lib/assets/sounds/success';
34
- import { errorSound } from '$lib/assets/sounds/error';
35
-
36
- // Register on app init (after first user gesture)
37
- await registerSound('success', successSound);
38
- await registerSound('error', errorSound);
40
+ Don't import these clips directly. Play them by **semantic name** through the
41
+ sound player, which loads them lazily and applies the user's preferences
42
+ (on/off, volume, categories, quiet hours). See `docs/sound.md`.
43
+
44
+ | Semantic name | Clip |
45
+ |---------------|------|
46
+ | `confirm` | success |
47
+ | `error` | error |
48
+ | `notify`, `message` | notify |
49
+ | `send` | send |
50
+ | `toggle` | toggle |
51
+ | `tap` | pop |
52
+ | `tick`, `select`, `chime`, `attention` | the clip of the same name |
53
+ | (variant) `SOUND_CLIP_VARIANTS['error-soft']` | error-soft |
54
+ | `incoming-call` | notify, replayed every 1.2 s (register a real ringer file instead) |
39
55
 
40
- // Play
41
- play('success'); // default volume 0.15
42
- play('error', { volume: 0.2 });
56
+ ```typescript
57
+ import { playSound } from 'jatui';
43
58
 
44
- // Toggle
45
- setSoundEnabled(true);
46
- isSoundEnabled(); // → true
59
+ playSound('confirm');
47
60
  ```
@@ -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,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";
@@ -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/index.d.ts CHANGED
@@ -205,7 +205,10 @@ export { glide } from './transitions/glide';
205
205
  export type { GlideOrigin, GlideParams } from './transitions/glide';
206
206
  export { themeWipe } from './utils/themeWipe';
207
207
  export { viewTransition } from './utils/viewTransition';
208
- export { play as playSound, registerSound, isSoundEnabled, setSoundEnabled } from './utils/sound';
208
+ export { MOTION_LEVELS, DEFAULT_MOTION_LEVEL, MOTION_LEVEL_ATTR, MOTION_DURATIONS, MOTION_LEVEL_SCALE, MOTION_LEVEL_TRAVEL, MOTION_EASING_POINTS, isMotionLevel, parseMotionLevel, prefersReducedMotion, resolveMotionLevel, motionContextFor, getMotionContext, motionDuration, effectiveEasing, setMotionLevel, cubicBezier, motionEasing, motionFade, motionScale, motionSlide, resolveMotionTiming, createMotionLevelStore } from './motion';
209
+ export type { MotionLevel, MotionDurationToken, MotionEasingToken, MotionContext, EasingFn, MotionTransitionParams, MotionTransitionConfig, MotionFadeParams, MotionScaleParams, MotionSlideParams, ResolvedMotionTiming, MotionState, MotionLevelStore, MotionLevelStoreOptions } from './motion';
210
+ export { registerSound, isSoundEnabled, setSoundEnabled } from './utils/sound';
211
+ export * from './sound';
209
212
  export { copyText, readClipboardText } from './utils/clipboard';
210
213
  export { splitText } from './utils/splitText';
211
214
  export type { SplitBy, SplitTextOptions, SplitTextResult } from './utils/splitText';
package/dist/index.js CHANGED
@@ -245,8 +245,16 @@ export { glide } from './transitions/glide';
245
245
  // View Transitions kit
246
246
  export { themeWipe } from './utils/themeWipe';
247
247
  export { viewTransition } from './utils/viewTransition';
248
- // Sound kit (functional feedback, opt-in)
249
- export { play as playSound, registerSound, isSoundEnabled, setSoundEnabled } from './utils/sound';
248
+ // Motion level kit (jatui-j6833): data-motion="calm|standard|lively" scales
249
+ // the --motion-* tokens per surface (styles/motion.css); these helpers,
250
+ // transitions and the store read the same level. Scheme: docs/motion.md.
251
+ export { MOTION_LEVELS, DEFAULT_MOTION_LEVEL, MOTION_LEVEL_ATTR, MOTION_DURATIONS, MOTION_LEVEL_SCALE, MOTION_LEVEL_TRAVEL, MOTION_EASING_POINTS, isMotionLevel, parseMotionLevel, prefersReducedMotion, resolveMotionLevel, motionContextFor, getMotionContext, motionDuration, effectiveEasing, setMotionLevel, cubicBezier, motionEasing, motionFade, motionScale, motionSlide, resolveMotionTiming, createMotionLevelStore } from './motion';
252
+ // Sound kit (jatui-kf62q): one preferences store (off by default, master
253
+ // volume, per-category mute, quiet hours, reduced-motion-aware), semantic
254
+ // sound names, a pure policy and SoundSettings. Discipline: docs/sound.md.
255
+ // playSound comes from ./sound; the legacy flag helpers route through it.
256
+ export { registerSound, isSoundEnabled, setSoundEnabled } from './utils/sound';
257
+ export * from './sound';
250
258
  // Clipboard (secure-context aware: execCommand fallback for plain-HTTP origins)
251
259
  export { copyText, readClipboardText } from './utils/clipboard';
252
260
  // Text utilities
@@ -0,0 +1,14 @@
1
+ /**
2
+ * JS easing functions for the `--motion-*` curves, so Svelte transitions
3
+ * (which interpolate in JS and emit keyframes) move on the same curves the
4
+ * CSS tokens describe. No dependency: a small cubic-bezier solver.
5
+ */
6
+ import { type MotionEasingToken } from './level';
7
+ export type EasingFn = (t: number) => number;
8
+ /**
9
+ * CSS `cubic-bezier(x1, y1, x2, y2)` as a function of progress t ∈ [0, 1].
10
+ * Newton–Raphson with a bisection fallback; y may overshoot [0, 1] (springs).
11
+ */
12
+ export declare function cubicBezier(x1: number, y1: number, x2: number, y2: number): EasingFn;
13
+ /** The JS easing for a `--motion-*` easing token. */
14
+ export declare function motionEasing(token: MotionEasingToken): EasingFn;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * JS easing functions for the `--motion-*` curves, so Svelte transitions
3
+ * (which interpolate in JS and emit keyframes) move on the same curves the
4
+ * CSS tokens describe. No dependency: a small cubic-bezier solver.
5
+ */
6
+ import { MOTION_EASING_POINTS } from './level';
7
+ /**
8
+ * CSS `cubic-bezier(x1, y1, x2, y2)` as a function of progress t ∈ [0, 1].
9
+ * Newton–Raphson with a bisection fallback; y may overshoot [0, 1] (springs).
10
+ */
11
+ export function cubicBezier(x1, y1, x2, y2) {
12
+ const cx = 3 * x1;
13
+ const bx = 3 * (x2 - x1) - cx;
14
+ const ax = 1 - cx - bx;
15
+ const cy = 3 * y1;
16
+ const by = 3 * (y2 - y1) - cy;
17
+ const ay = 1 - cy - by;
18
+ const sampleX = (s) => ((ax * s + bx) * s + cx) * s;
19
+ const sampleY = (s) => ((ay * s + by) * s + cy) * s;
20
+ const slopeX = (s) => (3 * ax * s + 2 * bx) * s + cx;
21
+ function solveX(x) {
22
+ let s = x;
23
+ for (let i = 0; i < 8; i++) {
24
+ const err = sampleX(s) - x;
25
+ if (Math.abs(err) < 1e-6)
26
+ return s;
27
+ const d = slopeX(s);
28
+ if (Math.abs(d) < 1e-6)
29
+ break;
30
+ s -= err / d;
31
+ }
32
+ let lo = 0;
33
+ let hi = 1;
34
+ s = x;
35
+ while (lo < hi) {
36
+ const v = sampleX(s);
37
+ if (Math.abs(v - x) < 1e-6)
38
+ return s;
39
+ if (x > v)
40
+ lo = s;
41
+ else
42
+ hi = s;
43
+ s = (lo + hi) / 2;
44
+ if (hi - lo < 1e-7)
45
+ break;
46
+ }
47
+ return s;
48
+ }
49
+ return (t) => {
50
+ if (t <= 0)
51
+ return 0;
52
+ if (t >= 1)
53
+ return 1;
54
+ return sampleY(solveX(t));
55
+ };
56
+ }
57
+ const cache = new Map();
58
+ /** The JS easing for a `--motion-*` easing token. */
59
+ export function motionEasing(token) {
60
+ let fn = cache.get(token);
61
+ if (!fn) {
62
+ const [x1, y1, x2, y2] = MOTION_EASING_POINTS[token];
63
+ fn = cubicBezier(x1, y1, x2, y2);
64
+ cache.set(token, fn);
65
+ }
66
+ return fn;
67
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * jatui motion kit — the motion level scheme, token easings, level-aware
3
+ * transitions and the scroll-reveal action, in one import.
4
+ * Scheme + level semantics: docs/motion.md.
5
+ */
6
+ export { MOTION_LEVELS, DEFAULT_MOTION_LEVEL, MOTION_LEVEL_ATTR, MOTION_DURATIONS, MOTION_LEVEL_SCALE, MOTION_LEVEL_TRAVEL, MOTION_EASING_POINTS, isMotionLevel, parseMotionLevel, prefersReducedMotion, resolveMotionLevel, motionContextFor, getMotionContext, motionDuration, effectiveEasing, setMotionLevel } from './level';
7
+ export type { MotionLevel, MotionDurationToken, MotionEasingToken, MotionContext } from './level';
8
+ export { cubicBezier, motionEasing } from './easing';
9
+ export type { EasingFn } from './easing';
10
+ export { motionFade, motionScale, motionSlide, resolveMotionTiming } from './transitions';
11
+ export type { MotionTransitionParams, MotionTransitionConfig, MotionFadeParams, MotionScaleParams, MotionSlideParams, ResolvedMotionTiming } from './transitions';
12
+ export { createMotionLevelStore } from './store';
13
+ export type { MotionState, MotionLevelStore, MotionLevelStoreOptions } from './store';
14
+ export { glide } from '../transitions/glide';
15
+ export type { GlideOrigin, GlideParams } from '../transitions/glide';
16
+ export { reveal, REVEAL_HIDDEN_CLASS, REVEAL_BASE_CLASS } from '../actions/reveal';
17
+ export type { RevealOptions, RevealVariant } from '../actions/reveal';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * jatui motion kit — the motion level scheme, token easings, level-aware
3
+ * transitions and the scroll-reveal action, in one import.
4
+ * Scheme + level semantics: docs/motion.md.
5
+ */
6
+ export { MOTION_LEVELS, DEFAULT_MOTION_LEVEL, MOTION_LEVEL_ATTR, MOTION_DURATIONS, MOTION_LEVEL_SCALE, MOTION_LEVEL_TRAVEL, MOTION_EASING_POINTS, isMotionLevel, parseMotionLevel, prefersReducedMotion, resolveMotionLevel, motionContextFor, getMotionContext, motionDuration, effectiveEasing, setMotionLevel } from './level';
7
+ export { cubicBezier, motionEasing } from './easing';
8
+ export { motionFade, motionScale, motionSlide, resolveMotionTiming } from './transitions';
9
+ export { createMotionLevelStore } from './store';
10
+ export { glide } from '../transitions/glide';
11
+ export { reveal, REVEAL_HIDDEN_CLASS, REVEAL_BASE_CLASS } from '../actions/reveal';
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Motion level — a per-surface dial for how much the UI moves.
3
+ *
4
+ * A host sets `data-motion="calm|standard|lively"` on `<html>` or on any
5
+ * subtree. `styles/motion.css` rescales the `--motion-*` duration and travel
6
+ * tokens under that attribute, and the JS side (transitions, `use:reveal`)
7
+ * reads the same level through `getMotionContext(node)` so CSS and JS motion
8
+ * agree. The nearest `[data-motion]` ancestor wins; no attribute = standard.
9
+ *
10
+ * calm durations × 0.75, travel 8px, springs flattened to glide,
11
+ * ambient/decorative motion OFF. Dense tools, dashboards.
12
+ * standard the tokens as written. The default.
13
+ * lively durations × 1.25, travel 24px. Marketing, onboarding, empty
14
+ * states — surfaces whose job is to feel alive.
15
+ *
16
+ * `prefers-reduced-motion: reduce` always wins over every level: durations
17
+ * and travel collapse to 0, springs and ambient motion are off. A level can
18
+ * never opt a reduced-motion user back into motion.
19
+ *
20
+ * The numbers here MUST match styles/motion.css — tests/unit/motionLevel.test.ts
21
+ * parses the stylesheet and fails on drift.
22
+ */
23
+ export type MotionLevel = 'calm' | 'standard' | 'lively';
24
+ /** Duration tokens, named after their `--motion-<name>` custom property. */
25
+ export type MotionDurationToken = 'instant' | 'fast' | 'enter' | 'move';
26
+ /** Easing tokens, named after their `--motion-<name>` custom property. */
27
+ export type MotionEasingToken = 'glide' | 'spring' | 'standard';
28
+ export declare const MOTION_LEVELS: readonly MotionLevel[];
29
+ export declare const DEFAULT_MOTION_LEVEL: MotionLevel;
30
+ /** The attribute a host sets on `<html>` or any subtree. */
31
+ export declare const MOTION_LEVEL_ATTR = "data-motion";
32
+ /** Standard-level durations in ms — the `--motion-*-base` tokens. */
33
+ export declare const MOTION_DURATIONS: Readonly<Record<MotionDurationToken, number>>;
34
+ /** Duration multiplier per level — `--motion-scale`. */
35
+ export declare const MOTION_LEVEL_SCALE: Readonly<Record<MotionLevel, number>>;
36
+ /** Entrance travel distance in px per level — `--motion-travel`. */
37
+ export declare const MOTION_LEVEL_TRAVEL: Readonly<Record<MotionLevel, number>>;
38
+ /** Cubic-bezier control points for the easing tokens (same as motion.css). */
39
+ export declare const MOTION_EASING_POINTS: Readonly<Record<MotionEasingToken, readonly [number, number, number, number]>>;
40
+ /** Everything a piece of motion needs to know about where it is running. */
41
+ export interface MotionContext {
42
+ /** The level the surface asked for (nearest `[data-motion]`, else standard). */
43
+ level: MotionLevel;
44
+ /** `prefers-reduced-motion: reduce` — overrides the level when true. */
45
+ reduced: boolean;
46
+ /** Duration multiplier: the level's scale, or 0 when reduced. */
47
+ scale: number;
48
+ /** Travel distance in px: the level's travel, or 0 when reduced. */
49
+ travel: number;
50
+ /** Whether ambient/decorative motion may run (standard + lively, never reduced). */
51
+ ambient: boolean;
52
+ /** Whether spring (overshoot) easing may run (standard + lively, never reduced). */
53
+ spring: boolean;
54
+ }
55
+ export declare function isMotionLevel(value: unknown): value is MotionLevel;
56
+ /** Coerce any attribute/storage value to a level; unknown values become the default. */
57
+ export declare function parseMotionLevel(value: unknown, fallback?: MotionLevel): MotionLevel;
58
+ /** True when the user asked the OS for reduced motion. SSR-safe (false). */
59
+ export declare function prefersReducedMotion(): boolean;
60
+ /**
61
+ * The level in force for `node`: its nearest `[data-motion]` ancestor
62
+ * (inclusive), else `<html>`'s, else standard. A `[data-motion]` with an
63
+ * unknown value counts as standard rather than being skipped, so a typo
64
+ * fails visibly-safe instead of silently inheriting `lively` from above.
65
+ */
66
+ export declare function resolveMotionLevel(node?: Element | null): MotionLevel;
67
+ /** Build a context from a level + reduced flag (pure — no DOM). */
68
+ export declare function motionContextFor(level: MotionLevel, reduced?: boolean): MotionContext;
69
+ /** The motion context in force for `node` (or the document when omitted). */
70
+ export declare function getMotionContext(node?: Element | null): MotionContext;
71
+ /**
72
+ * A token duration (or a standard-level ms value) scaled for a context.
73
+ * Returns 0 under reduced motion.
74
+ *
75
+ * motionDuration('enter', ctx) // 200 standard, 150 calm, 250 lively
76
+ * motionDuration(400, ctx) // 300 calm
77
+ */
78
+ export declare function motionDuration(token: MotionDurationToken | number, ctx: MotionContext): number;
79
+ /**
80
+ * The easing token actually allowed in a context: spring degrades to glide
81
+ * wherever springs are off (calm, reduced). Other tokens pass through.
82
+ */
83
+ export declare function effectiveEasing(token: MotionEasingToken, ctx: MotionContext): MotionEasingToken;
84
+ /**
85
+ * Set the level on a surface (default `<html>`). Passing `null` removes the
86
+ * attribute so the surface inherits again. No-op without a DOM.
87
+ */
88
+ export declare function setMotionLevel(level: MotionLevel | null, target?: Element | null): void;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Motion level — a per-surface dial for how much the UI moves.
3
+ *
4
+ * A host sets `data-motion="calm|standard|lively"` on `<html>` or on any
5
+ * subtree. `styles/motion.css` rescales the `--motion-*` duration and travel
6
+ * tokens under that attribute, and the JS side (transitions, `use:reveal`)
7
+ * reads the same level through `getMotionContext(node)` so CSS and JS motion
8
+ * agree. The nearest `[data-motion]` ancestor wins; no attribute = standard.
9
+ *
10
+ * calm durations × 0.75, travel 8px, springs flattened to glide,
11
+ * ambient/decorative motion OFF. Dense tools, dashboards.
12
+ * standard the tokens as written. The default.
13
+ * lively durations × 1.25, travel 24px. Marketing, onboarding, empty
14
+ * states — surfaces whose job is to feel alive.
15
+ *
16
+ * `prefers-reduced-motion: reduce` always wins over every level: durations
17
+ * and travel collapse to 0, springs and ambient motion are off. A level can
18
+ * never opt a reduced-motion user back into motion.
19
+ *
20
+ * The numbers here MUST match styles/motion.css — tests/unit/motionLevel.test.ts
21
+ * parses the stylesheet and fails on drift.
22
+ */
23
+ export const MOTION_LEVELS = ['calm', 'standard', 'lively'];
24
+ export const DEFAULT_MOTION_LEVEL = 'standard';
25
+ /** The attribute a host sets on `<html>` or any subtree. */
26
+ export const MOTION_LEVEL_ATTR = 'data-motion';
27
+ /** Standard-level durations in ms — the `--motion-*-base` tokens. */
28
+ export const MOTION_DURATIONS = {
29
+ instant: 80,
30
+ fast: 150,
31
+ enter: 200,
32
+ move: 300
33
+ };
34
+ /** Duration multiplier per level — `--motion-scale`. */
35
+ export const MOTION_LEVEL_SCALE = {
36
+ calm: 0.75,
37
+ standard: 1,
38
+ lively: 1.25
39
+ };
40
+ /** Entrance travel distance in px per level — `--motion-travel`. */
41
+ export const MOTION_LEVEL_TRAVEL = {
42
+ calm: 8,
43
+ standard: 16,
44
+ lively: 24
45
+ };
46
+ /** Cubic-bezier control points for the easing tokens (same as motion.css). */
47
+ export const MOTION_EASING_POINTS = {
48
+ glide: [0.16, 1, 0.3, 1],
49
+ spring: [0.34, 1.56, 0.64, 1],
50
+ standard: [0.2, 0, 0, 1]
51
+ };
52
+ export function isMotionLevel(value) {
53
+ return typeof value === 'string' && MOTION_LEVELS.includes(value);
54
+ }
55
+ /** Coerce any attribute/storage value to a level; unknown values become the default. */
56
+ export function parseMotionLevel(value, fallback = DEFAULT_MOTION_LEVEL) {
57
+ if (typeof value !== 'string')
58
+ return fallback;
59
+ const v = value.trim().toLowerCase();
60
+ return isMotionLevel(v) ? v : fallback;
61
+ }
62
+ /** True when the user asked the OS for reduced motion. SSR-safe (false). */
63
+ export function prefersReducedMotion() {
64
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function')
65
+ return false;
66
+ try {
67
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * The level in force for `node`: its nearest `[data-motion]` ancestor
75
+ * (inclusive), else `<html>`'s, else standard. A `[data-motion]` with an
76
+ * unknown value counts as standard rather than being skipped, so a typo
77
+ * fails visibly-safe instead of silently inheriting `lively` from above.
78
+ */
79
+ export function resolveMotionLevel(node) {
80
+ const el = (node ?? (typeof document !== 'undefined' ? document.documentElement : null));
81
+ if (!el || typeof el.closest !== 'function')
82
+ return DEFAULT_MOTION_LEVEL;
83
+ const host = el.closest(`[${MOTION_LEVEL_ATTR}]`);
84
+ return host ? parseMotionLevel(host.getAttribute(MOTION_LEVEL_ATTR)) : DEFAULT_MOTION_LEVEL;
85
+ }
86
+ /** Build a context from a level + reduced flag (pure — no DOM). */
87
+ export function motionContextFor(level, reduced = false) {
88
+ const lively = level !== 'calm';
89
+ return {
90
+ level,
91
+ reduced,
92
+ scale: reduced ? 0 : MOTION_LEVEL_SCALE[level],
93
+ travel: reduced ? 0 : MOTION_LEVEL_TRAVEL[level],
94
+ ambient: !reduced && lively,
95
+ spring: !reduced && lively
96
+ };
97
+ }
98
+ /** The motion context in force for `node` (or the document when omitted). */
99
+ export function getMotionContext(node) {
100
+ return motionContextFor(resolveMotionLevel(node), prefersReducedMotion());
101
+ }
102
+ /**
103
+ * A token duration (or a standard-level ms value) scaled for a context.
104
+ * Returns 0 under reduced motion.
105
+ *
106
+ * motionDuration('enter', ctx) // 200 standard, 150 calm, 250 lively
107
+ * motionDuration(400, ctx) // 300 calm
108
+ */
109
+ export function motionDuration(token, ctx) {
110
+ const base = typeof token === 'number' ? token : MOTION_DURATIONS[token];
111
+ return Math.round(Math.max(0, base) * ctx.scale);
112
+ }
113
+ /**
114
+ * The easing token actually allowed in a context: spring degrades to glide
115
+ * wherever springs are off (calm, reduced). Other tokens pass through.
116
+ */
117
+ export function effectiveEasing(token, ctx) {
118
+ return token === 'spring' && !ctx.spring ? 'glide' : token;
119
+ }
120
+ /**
121
+ * Set the level on a surface (default `<html>`). Passing `null` removes the
122
+ * attribute so the surface inherits again. No-op without a DOM.
123
+ */
124
+ export function setMotionLevel(level, target) {
125
+ const el = target ?? (typeof document !== 'undefined' ? document.documentElement : null);
126
+ if (!el)
127
+ return;
128
+ if (level === null)
129
+ el.removeAttribute(MOTION_LEVEL_ATTR);
130
+ else
131
+ el.setAttribute(MOTION_LEVEL_ATTR, level);
132
+ }