@joewinke/jatui 0.46.0 → 0.47.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 +46 -0
- package/dist/ambience/README.md +131 -0
- package/dist/ambience/breath.d.ts +22 -0
- package/dist/ambience/breath.js +43 -0
- package/dist/ambience/default.d.ts +24 -0
- package/dist/ambience/default.js +34 -0
- package/dist/ambience/engine.d.ts +21 -0
- package/dist/ambience/engine.js +313 -0
- package/dist/ambience/index.d.ts +23 -0
- package/dist/ambience/index.js +27 -0
- package/dist/ambience/master.d.ts +49 -0
- package/dist/ambience/master.js +83 -0
- package/dist/ambience/persist.d.ts +11 -0
- package/dist/ambience/persist.js +24 -0
- package/dist/ambience/registry.d.ts +11 -0
- package/dist/ambience/registry.js +16 -0
- package/dist/ambience/scapes/focus.d.ts +55 -0
- package/dist/ambience/scapes/focus.js +245 -0
- package/dist/ambience/scapes/hibiscus.d.ts +103 -0
- package/dist/ambience/scapes/hibiscus.js +345 -0
- package/dist/ambience/scapes/nature.d.ts +36 -0
- package/dist/ambience/scapes/nature.js +325 -0
- package/dist/ambience/scapes/noise.d.ts +77 -0
- package/dist/ambience/scapes/noise.js +226 -0
- package/dist/ambience/scapes/playlist.d.ts +129 -0
- package/dist/ambience/scapes/playlist.js +569 -0
- package/dist/ambience/types.d.ts +80 -0
- package/dist/ambience/types.js +9 -0
- package/dist/components/AmbienceToggle.svelte +599 -0
- package/dist/components/AmbienceToggle.svelte.d.ts +74 -0
- package/dist/components/VideoPlayer.svelte +73 -6
- package/dist/components/VideoPlayer.svelte.d.ts +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9 -0
- package/dist/video/keys.d.ts +4 -3
- package/dist/video/keys.js +5 -4
- package/dist/video/settings/remembered.d.ts +9 -0
- package/dist/video/settings/remembered.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AmbienceToggle — the audio twin of ThemeToggle (jatui-b7qvr): one small
|
|
3
|
+
* speaker button for the app shell over the headless ambience engine
|
|
4
|
+
* (`createAmbience()` from `src/lib/ambience/`).
|
|
5
|
+
*
|
|
6
|
+
* Interaction contract:
|
|
7
|
+
* - Click (or Space/Enter) = play / stop the last scape. A gesture-gated
|
|
8
|
+
* engine call, made synchronously inside the click handler.
|
|
9
|
+
* - The scape menu (menu button pattern) opens with ArrowDown/ArrowUp,
|
|
10
|
+
* a press-and-hold (~450 ms) or a right-click (Android/Chrome fire
|
|
11
|
+
* contextmenu on touch holds; iOS may cancel the pointer instead —
|
|
12
|
+
* the keyboard path always works). It lists every
|
|
13
|
+
* registered scape grouped meditation / focus / noise / nature / music
|
|
14
|
+
* (`menuitemradio` items, current scape checked), carries a volume
|
|
15
|
+
* slider wired to `engine.setVolume`, and shows each scape's
|
|
16
|
+
* `description` as its secondary line — playlist scapes put their
|
|
17
|
+
* track attribution there.
|
|
18
|
+
*
|
|
19
|
+
* A11y: the trigger is `aria-pressed` while playing and carries the full
|
|
20
|
+
* menu-button wiring (`aria-expanded` / `aria-haspopup` / `aria-controls`).
|
|
21
|
+
* An sr-only description teaches the menu gestures, and an `aria-live`
|
|
22
|
+
* status line announces state changes ("Ambience: Hibiscus, playing").
|
|
23
|
+
* The speaker glyph morphs off↔on on the motion tokens and, while playing,
|
|
24
|
+
* breathes with `engine.onBreath` — ambient motion, so it is static under
|
|
25
|
+
* `prefers-reduced-motion` and `data-motion="calm"`.
|
|
26
|
+
*
|
|
27
|
+
* Token-only theming (DaisyUI + `--jatui-*` + `--motion-*`). SSR-safe: the
|
|
28
|
+
* engine is lazy and nothing here touches `window` at import.
|
|
29
|
+
*/
|
|
30
|
+
import type { Ambience, Scape, ScapeGroup } from '../ambience/types';
|
|
31
|
+
/** Canonical menu group order (the Scape contract's groups). */
|
|
32
|
+
export declare const AMBIENCE_GROUP_ORDER: readonly ScapeGroup[];
|
|
33
|
+
/** Human labels for the canonical groups. */
|
|
34
|
+
export declare const GROUP_LABELS: Readonly<Record<ScapeGroup, string>>;
|
|
35
|
+
/** One grouped section of the scape menu. */
|
|
36
|
+
export interface AmbienceScapeGroup {
|
|
37
|
+
group: ScapeGroup;
|
|
38
|
+
label: string;
|
|
39
|
+
scapes: Scape[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Group scapes for the menu: canonical group order, registration order
|
|
43
|
+
* within a group, empty groups omitted. A group outside the union (a
|
|
44
|
+
* registry from a newer engine) still renders, after the known ones, in
|
|
45
|
+
* first-seen order — a menu never silently drops a registered scape.
|
|
46
|
+
*/
|
|
47
|
+
export declare function groupScapes(scapes: Scape[]): AmbienceScapeGroup[];
|
|
48
|
+
/**
|
|
49
|
+
* The live label — "Ambience: Hibiscus, playing" while sounding,
|
|
50
|
+
* "Ambience: Hibiscus, stopped" once a scape has been selected but is not
|
|
51
|
+
* playing, "Ambience: off" before anything was selected.
|
|
52
|
+
*/
|
|
53
|
+
export declare function ambienceLiveLabel(currentLabel: string | null, playing: boolean): string;
|
|
54
|
+
/** Transient failure label — a rejected engine.play() (gesture probe,
|
|
55
|
+
* context suspend, unknown scape) must never surface as an unhandled
|
|
56
|
+
* rejection OR as silence: the trigger visibly fails to respond, so the
|
|
57
|
+
* sr-only status explains it. Cleared by the next successful play. */
|
|
58
|
+
export declare const PLAY_ERROR_LABEL = "Ambience: couldn't start \u2014 tap again";
|
|
59
|
+
/**
|
|
60
|
+
* Glyph scale for a breath value (0..1): the speaker grows on the inhale
|
|
61
|
+
* and settles on the exhale — 6% total, clamped against out-of-range input.
|
|
62
|
+
*/
|
|
63
|
+
export declare function breathScale(value: number): number;
|
|
64
|
+
type $$ComponentProps = {
|
|
65
|
+
/** The engine instance (from `createAmbience()`). The component never creates one, and never kills it — the host owns the engine's lifecycle. */
|
|
66
|
+
engine: Ambience;
|
|
67
|
+
/** Smaller app-shell footprint: 40px trigger with an 18px glyph (default 44px / 20px). Never below the 40px touch floor. */
|
|
68
|
+
compact?: boolean;
|
|
69
|
+
/** Which way the menu opens from the trigger. Auto-flips vertically when the viewport has no room on that side. */
|
|
70
|
+
placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
|
|
71
|
+
};
|
|
72
|
+
declare const AmbienceToggle: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
73
|
+
type AmbienceToggle = ReturnType<typeof AmbienceToggle>;
|
|
74
|
+
export default AmbienceToggle;
|
|
@@ -265,10 +265,12 @@
|
|
|
265
265
|
SETTINGS_WRITE_DELAY_MS,
|
|
266
266
|
VIDEO_SETTINGS,
|
|
267
267
|
REMEMBERED_MUTED,
|
|
268
|
+
REMEMBERED_TRANSCRIPT,
|
|
268
269
|
REMEMBERED_VOLUME,
|
|
269
270
|
type SettingAvailability,
|
|
270
271
|
type SettingsSession,
|
|
271
272
|
type SettingValue,
|
|
273
|
+
type TranscriptLayout,
|
|
272
274
|
type VideoSettingsStore
|
|
273
275
|
} from '../video/settings';
|
|
274
276
|
import SettingsPanel from '../video/settings/SettingsPanel.svelte';
|
|
@@ -458,6 +460,15 @@
|
|
|
458
460
|
talkTime?: VideoSpeakerTalkTime[];
|
|
459
461
|
/** Seek here once metadata lands (a queued seek never fires on a later source). */
|
|
460
462
|
startAt?: number | null;
|
|
463
|
+
/**
|
|
464
|
+
* Where the transcript sits when the viewer has not chosen otherwise —
|
|
465
|
+
* `'below'` the player, or beside it (`'side'`) on wide viewports. The
|
|
466
|
+
* viewer's Shift+T cycles the layout: side / below / hidden (E24,
|
|
467
|
+
* jatui-kgsxf) and the choice is remembered per viewer under the
|
|
468
|
+
* `player.transcript` setting — through `settingsStore` when one is
|
|
469
|
+
* given, else this browser's localStorage (every access guarded). A
|
|
470
|
+
* remembered choice wins over this prop.
|
|
471
|
+
*/
|
|
461
472
|
transcriptPosition?: 'below' | 'side';
|
|
462
473
|
/**
|
|
463
474
|
* CSS length bounding the transcript pane's height — it scrolls inside
|
|
@@ -924,7 +935,14 @@
|
|
|
924
935
|
let baseRate = $state(1);
|
|
925
936
|
|
|
926
937
|
// ── Transcript + help overlays ──────────────────────────────────────────
|
|
927
|
-
|
|
938
|
+
/**
|
|
939
|
+
* The viewer's transcript layout (E24, jatui-kgsxf): the host's
|
|
940
|
+
* `transcriptPosition` prop is the default; a remembered choice wins over
|
|
941
|
+
* it. The side layout is the beside-the-video grid, below the pane under
|
|
942
|
+
* the player, hidden — no pane at all.
|
|
943
|
+
*/
|
|
944
|
+
let transcriptChoice = $state<TranscriptLayout | null>(null);
|
|
945
|
+
const transcriptLayout = $derived(transcriptChoice ?? transcriptPosition);
|
|
928
946
|
let keysOpen = $state(false);
|
|
929
947
|
|
|
930
948
|
// ── Transcript search (jatui-xmtnv) ────────────────────────────────
|
|
@@ -2386,6 +2404,54 @@
|
|
|
2386
2404
|
flashOsd(next ? 'Theater mode' : 'Default view');
|
|
2387
2405
|
}
|
|
2388
2406
|
|
|
2407
|
+
// ── Transcript layout cycle (E24, jatui-kgsxf) ─────────────────────────
|
|
2408
|
+
// The extension's T cycles three layouts: beside the video, below, hidden
|
|
2409
|
+
// (library.js:6137, 9346). The host's `transcriptPosition` prop is the
|
|
2410
|
+
// default; a remembered choice wins over it, and survives a reload — the
|
|
2411
|
+
// same store split as the media state (the host's `settingsStore`, else
|
|
2412
|
+
// this browser's localStorage), `settings/remembered.ts` holds the id and
|
|
2413
|
+
// the never-throws coercion.
|
|
2414
|
+
const TRANSCRIPT_CYCLE = ['side', 'below', 'hidden'] as const;
|
|
2415
|
+
const localTranscriptStore = localSettingsStore();
|
|
2416
|
+
let transcriptTouched = false;
|
|
2417
|
+
|
|
2418
|
+
function cycleTranscript() {
|
|
2419
|
+
if (sortedSegments.length === 0) return;
|
|
2420
|
+
const idx = TRANSCRIPT_CYCLE.indexOf(transcriptLayout);
|
|
2421
|
+
const next = TRANSCRIPT_CYCLE[(idx + 1) % TRANSCRIPT_CYCLE.length];
|
|
2422
|
+
transcriptChoice = next;
|
|
2423
|
+
rememberTranscriptLayout(next);
|
|
2424
|
+
flashOsd(
|
|
2425
|
+
next === 'side' ? 'Transcript beside' : next === 'below' ? 'Transcript below' : 'Transcript hidden'
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
/** A viewer choice from outside the panel (Shift+T) — saved like one. */
|
|
2430
|
+
function rememberTranscriptLayout(v: TranscriptLayout) {
|
|
2431
|
+
transcriptTouched = true;
|
|
2432
|
+
writeRemembered(settingsStore ?? localTranscriptStore, REMEMBERED_TRANSCRIPT.id, v);
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
// The load-time read, once per store identity: a junk or throwing store
|
|
2436
|
+
// reads as nothing stored, and a choice made before the read resolves wins
|
|
2437
|
+
// (the settings session's rule, mirrored here).
|
|
2438
|
+
$effect(() => {
|
|
2439
|
+
const store = settingsStore ?? localTranscriptStore;
|
|
2440
|
+
let cancelled = false;
|
|
2441
|
+
untrack(() => {
|
|
2442
|
+
void Promise.resolve(store.get(REMEMBERED_TRANSCRIPT.id))
|
|
2443
|
+
.then((raw) => {
|
|
2444
|
+
if (cancelled || transcriptTouched) return;
|
|
2445
|
+
const v = REMEMBERED_TRANSCRIPT.coerce(raw);
|
|
2446
|
+
if (v !== undefined) transcriptChoice = v;
|
|
2447
|
+
})
|
|
2448
|
+
.catch(() => {});
|
|
2449
|
+
});
|
|
2450
|
+
return () => {
|
|
2451
|
+
cancelled = true;
|
|
2452
|
+
};
|
|
2453
|
+
});
|
|
2454
|
+
|
|
2389
2455
|
// ── Remembered volume & mute (E12, jatui-xz6so) ──────────────────────
|
|
2390
2456
|
// Extension library.js:5768 — the volume level and the mute choice survive
|
|
2391
2457
|
// a reload, persisted through the same store the settings registry writes
|
|
@@ -3160,8 +3226,7 @@
|
|
|
3160
3226
|
case 'T':
|
|
3161
3227
|
if (sortedSegments.length > 0) {
|
|
3162
3228
|
e.preventDefault();
|
|
3163
|
-
|
|
3164
|
-
flashOsd(transcriptVisible ? 'Transcript shown' : 'Transcript hidden');
|
|
3229
|
+
cycleTranscript();
|
|
3165
3230
|
}
|
|
3166
3231
|
return;
|
|
3167
3232
|
case '/':
|
|
@@ -3317,7 +3382,9 @@
|
|
|
3317
3382
|
* it focus once it mounts — the effect below lands it. */
|
|
3318
3383
|
function openSearch() {
|
|
3319
3384
|
if (sortedSegments.length === 0) return;
|
|
3320
|
-
|
|
3385
|
+
// Showing the pane for the search is transient — the viewer's own
|
|
3386
|
+
// layout choice (possibly hidden) is not overwritten.
|
|
3387
|
+
if (transcriptLayout === 'hidden') transcriptChoice = transcriptPosition;
|
|
3321
3388
|
searchOpen = true;
|
|
3322
3389
|
searchMatchIdx = -1;
|
|
3323
3390
|
}
|
|
@@ -3447,7 +3514,7 @@
|
|
|
3447
3514
|
<div
|
|
3448
3515
|
class="vp-root {className}"
|
|
3449
3516
|
bind:this={rootEl}
|
|
3450
|
-
class:vp-side={
|
|
3517
|
+
class:vp-side={transcriptLayout === 'side' && !theaterOn && sortedSegments.length > 0}
|
|
3451
3518
|
class:vp-theater={theaterOn}
|
|
3452
3519
|
data-theater={theaterAvailable ? String(theaterOn) : undefined}
|
|
3453
3520
|
class:vp-rail-side={railOn}
|
|
@@ -4097,7 +4164,7 @@
|
|
|
4097
4164
|
<div class="vp-below-stage">{@render belowStage()}</div>
|
|
4098
4165
|
{/if}
|
|
4099
4166
|
|
|
4100
|
-
{#if sortedSegments.length > 0 &&
|
|
4167
|
+
{#if sortedSegments.length > 0 && transcriptLayout !== 'hidden'}
|
|
4101
4168
|
<!-- Height-bounded (jatui-ap4oz): the pane scrolls itself and never
|
|
4102
4169
|
the page, so the video stays in frame. Below the player the bound
|
|
4103
4170
|
is `transcriptMaxHeight` (default min(40vh, 28rem)); beside it, the
|
|
@@ -167,6 +167,15 @@ type $$ComponentProps = {
|
|
|
167
167
|
talkTime?: VideoSpeakerTalkTime[];
|
|
168
168
|
/** Seek here once metadata lands (a queued seek never fires on a later source). */
|
|
169
169
|
startAt?: number | null;
|
|
170
|
+
/**
|
|
171
|
+
* Where the transcript sits when the viewer has not chosen otherwise —
|
|
172
|
+
* `'below'` the player, or beside it (`'side'`) on wide viewports. The
|
|
173
|
+
* viewer's Shift+T cycles the layout: side / below / hidden (E24,
|
|
174
|
+
* jatui-kgsxf) and the choice is remembered per viewer under the
|
|
175
|
+
* `player.transcript` setting — through `settingsStore` when one is
|
|
176
|
+
* given, else this browser's localStorage (every access guarded). A
|
|
177
|
+
* remembered choice wins over this prop.
|
|
178
|
+
*/
|
|
170
179
|
transcriptPosition?: 'below' | 'side';
|
|
171
180
|
/**
|
|
172
181
|
* CSS length bounding the transcript pane's height — it scrolls inside
|
package/dist/index.d.ts
CHANGED
|
@@ -405,3 +405,9 @@ export * from './data/grid/index';
|
|
|
405
405
|
export { default as ImageReveal } from './components/ImageReveal.svelte';
|
|
406
406
|
export { imageRevealPhase, imageRevealBusy, imageRevealInitials, imageRevealSize, imageRevealTone, IMAGE_REVEAL_SIZES, IMAGE_REVEAL_RADIUS } from './components/imageReveal';
|
|
407
407
|
export type { ImageRevealPhase, ImageRevealShape, ImageRevealSizeName, ImageRevealToneName, ImageRevealState } from './components/imageReveal';
|
|
408
|
+
export { default as AmbienceToggle, AMBIENCE_GROUP_ORDER } from './components/AmbienceToggle.svelte';
|
|
409
|
+
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves } from './ambience';
|
|
410
|
+
export type { DefaultAmbienceOptions } from './ambience';
|
|
411
|
+
export type { Ambience, AmbienceOptions, AmbienceState, BreathState, Scape, ScapeContext, ScapeGroup, ScapeInstance } from './ambience';
|
|
412
|
+
export { createPlaylistScape } from './ambience';
|
|
413
|
+
export type { PlaylistScape, PlaylistScapeOptions, PlaylistManifest, PlaylistState, PlaylistStatus, PlaylistTrack } from './ambience';
|
package/dist/index.js
CHANGED
|
@@ -451,3 +451,12 @@ export { default as SettingsRow } from './components/settings/SettingsRow.svelte
|
|
|
451
451
|
export * from './data/grid/index';
|
|
452
452
|
export { default as ImageReveal } from './components/ImageReveal.svelte';
|
|
453
453
|
export { imageRevealPhase, imageRevealBusy, imageRevealInitials, imageRevealSize, imageRevealTone, IMAGE_REVEAL_SIZES, IMAGE_REVEAL_RADIUS } from './components/imageReveal';
|
|
454
|
+
// Ambience — generative background-sound engine (headless) + the app-shell
|
|
455
|
+
// AmbienceToggle. Mount the engine once at the root layout so sound survives
|
|
456
|
+
// navigation; createDefaultAmbience() pre-registers every shipped scape
|
|
457
|
+
// (hibiscus, focus, brown/pink/white noise, rain, waves).
|
|
458
|
+
export { default as AmbienceToggle, AMBIENCE_GROUP_ORDER } from './components/AmbienceToggle.svelte';
|
|
459
|
+
export { createAmbience, createDefaultAmbience, DEFAULT_SCAPES, BreathClock, BREATHS_PER_MINUTE, MASTER, ScapeRegistry, hibiscusScape, focusScape, noiseScapes, brownNoiseScape, pinkNoiseScape, whiteNoiseScape, rain, waves } from './ambience';
|
|
460
|
+
// Playlist scape (phase 2) — per-host, never in DEFAULT_SCAPES: build with
|
|
461
|
+
// createPlaylistScape() and register on the engine yourself.
|
|
462
|
+
export { createPlaylistScape } from './ambience';
|
package/dist/video/keys.d.ts
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Map parity is with extension-library's theater handler (FEATURES.md):
|
|
7
7
|
* Space play/pause, ←/→ seek, ↑/↓ volume, M mute, −/= speed, Backspace reset
|
|
8
|
-
* speed, </> frame step, [/] chapter jumps, B bookmark, Shift+T transcript
|
|
9
|
-
* (t is theater mode
|
|
10
|
-
* shortcuts, Home/End, and `/` transcript search (the pane has
|
|
8
|
+
* speed, </> frame step, [/] chapter jumps, B bookmark, Shift+T transcript layout
|
|
9
|
+
* cycle (side / below / hidden — jatui-kgsxf), t is theater mode (YouTube's key
|
|
10
|
+
* — jatui-ee2ty), ? shortcuts, Home/End, and `/` transcript search (the pane has
|
|
11
|
+
* none yet).
|
|
11
12
|
* Deliberately NOT ported: F/M (favourite/file-under — library-app verbs,
|
|
12
13
|
* not player verbs). N (night cycle) landed with the night module
|
|
13
14
|
* (mos-5lzns.33) and `,` (settings) with the settings panel
|
package/dist/video/keys.js
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Map parity is with extension-library's theater handler (FEATURES.md):
|
|
7
7
|
* Space play/pause, ←/→ seek, ↑/↓ volume, M mute, −/= speed, Backspace reset
|
|
8
|
-
* speed, </> frame step, [/] chapter jumps, B bookmark, Shift+T transcript
|
|
9
|
-
* (t is theater mode
|
|
10
|
-
* shortcuts, Home/End, and `/` transcript search (the pane has
|
|
8
|
+
* speed, </> frame step, [/] chapter jumps, B bookmark, Shift+T transcript layout
|
|
9
|
+
* cycle (side / below / hidden — jatui-kgsxf), t is theater mode (YouTube's key
|
|
10
|
+
* — jatui-ee2ty), ? shortcuts, Home/End, and `/` transcript search (the pane has
|
|
11
|
+
* none yet).
|
|
11
12
|
* Deliberately NOT ported: F/M (favourite/file-under — library-app verbs,
|
|
12
13
|
* not player verbs). N (night cycle) landed with the night module
|
|
13
14
|
* (mos-5lzns.33) and `,` (settings) with the settings panel
|
|
@@ -33,7 +34,7 @@ export const PLAYER_KEYS = [
|
|
|
33
34
|
{ keys: 'B', description: 'Bookmark at the current time', when: 'bookmarks' },
|
|
34
35
|
// t = theater, YouTube's key; the transcript moved to Shift+T (jatui-ee2ty).
|
|
35
36
|
{ keys: 't', description: 'Theater mode on / off', when: 'theater' },
|
|
36
|
-
{ keys: 'Shift+T', description: '
|
|
37
|
+
{ keys: 'Shift+T', description: 'Cycle transcript layout: side / below / hidden', when: 'transcript' },
|
|
37
38
|
{ keys: '/', description: 'Search transcript', when: 'transcript' },
|
|
38
39
|
// Shift+wheel over the transcript pane steps PLAYBACK line by line —
|
|
39
40
|
// a plain wheel there scrolls the pane natively and is never claimed.
|
|
@@ -26,5 +26,14 @@ export interface RememberedSpec<T> {
|
|
|
26
26
|
}
|
|
27
27
|
/** The playback level, 0–1 on the player's 0.05 gesture grid. */
|
|
28
28
|
export declare const REMEMBERED_VOLUME: RememberedSpec<number>;
|
|
29
|
+
/**
|
|
30
|
+
* The transcript layout (E24, jatui-kgsxf) — the extension's T cycles three
|
|
31
|
+
* layouts: beside the video, below it, hidden (library.js:6137, 9346). The
|
|
32
|
+
* host's `transcriptPosition` prop is the default; a remembered choice wins
|
|
33
|
+
* over it, and survives a reload. `default` here is only the fallback when a
|
|
34
|
+
* store holds nothing usable — the host's prop is the real default.
|
|
35
|
+
*/
|
|
36
|
+
export type TranscriptLayout = 'side' | 'below' | 'hidden';
|
|
37
|
+
export declare const REMEMBERED_TRANSCRIPT: RememberedSpec<TranscriptLayout>;
|
|
29
38
|
/** Whether playback starts muted. */
|
|
30
39
|
export declare const REMEMBERED_MUTED: RememberedSpec<boolean>;
|
|
@@ -30,6 +30,15 @@ export const REMEMBERED_VOLUME = {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
+
export const REMEMBERED_TRANSCRIPT = {
|
|
34
|
+
id: 'player.transcript',
|
|
35
|
+
default: 'below',
|
|
36
|
+
coerce(raw) {
|
|
37
|
+
if (raw === 'side' || raw === 'below' || raw === 'hidden')
|
|
38
|
+
return raw;
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
33
42
|
/** Whether playback starts muted. */
|
|
34
43
|
export const REMEMBERED_MUTED = {
|
|
35
44
|
id: 'player.muted',
|