@gentomiyano/optimized-web-audio-player 0.1.0 → 0.2.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 (47) hide show
  1. package/README.md +177 -159
  2. package/dist/config/index.d.ts +1 -1
  3. package/dist/config/index.js +1 -0
  4. package/dist/config/index.js.map +1 -1
  5. package/dist/consumer/index.d.ts +1 -1
  6. package/dist/consumer/index.js.map +1 -1
  7. package/dist/contracts/index.d.ts +2 -2
  8. package/dist/index.d.ts +2 -2
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/media-delivery/index.d.ts +1 -1
  12. package/dist/media-delivery/index.js.map +1 -1
  13. package/dist/{media-element-C9dis4aG.d.ts → media-element-DyMO-PhK.d.ts} +1 -1
  14. package/dist/{player-DE9Vqztu.d.ts → player-BxNFzRq4.d.ts} +53 -1
  15. package/dist/ports/index.d.ts +2 -2
  16. package/dist/react/index.d.ts +14 -3
  17. package/dist/react/index.js +193 -12
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/testing/index.d.ts +1 -1
  20. package/dist/testing/index.js +1 -0
  21. package/dist/testing/index.js.map +1 -1
  22. package/dist/ui/index.d.ts +10 -2
  23. package/dist/ui/index.js +227 -56
  24. package/dist/ui/index.js.map +1 -1
  25. package/dist/ui/player-tokens.css +572 -572
  26. package/dist/ui/player-views.css +713 -654
  27. package/dist/ui/styles.css +2 -2
  28. package/package.json +12 -2
  29. package/dist/consumer-smoke/node_modules/.modules.yaml +0 -30
  30. package/dist/consumer-smoke/node_modules/.package-map.json +0 -1
  31. package/dist/consumer-smoke/node_modules/.pnpm/lock.yaml +0 -57
  32. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/LICENSE +0 -21
  33. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/README.md +0 -9
  34. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js +0 -414
  35. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_mock.production.js +0 -406
  36. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js +0 -150
  37. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.js +0 -140
  38. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.development.js +0 -364
  39. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.development.js +0 -350
  40. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.native.production.js +0 -330
  41. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.production.js +0 -340
  42. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.js +0 -7
  43. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/index.native.js +0 -7
  44. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/package.json +0 -27
  45. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_mock.js +0 -7
  46. package/dist/consumer-smoke/node_modules/.pnpm/scheduler@0.27.0/node_modules/scheduler/unstable_post_task.js +0 -7
  47. package/dist/consumer-smoke/node_modules/.pnpm-workspace-state-v1.json +0 -29
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/defaults.ts","../src/config/validation.ts","../src/config/initial-state.ts","../src/media-delivery/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { PlayerExperienceConfig } from \"../contracts/player\";\n\nexport const PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION = 2 as const;\n\nexport const PLAYER_EXPERIENCE_CONFIG_LIMITS = Object.freeze({\n fadeMs: Object.freeze({ min: 0, max: 10_000 }),\n previousRestartThresholdSec: Object.freeze({ min: 0, max: 60 }),\n waveformOpacity: Object.freeze({ min: 0, max: 1 }),\n initialVolume: Object.freeze({ min: 0, max: 1 }),\n podcastSkipSec: Object.freeze({ minExclusive: 0, max: 3_600 }),\n});\n\nexport const PREVIEW_PLAYER_EXPERIENCE_CONFIG: Readonly<PlayerExperienceConfig> =\n Object.freeze({\n playFadeInMs: 300,\n pauseFadeOutMs: 600,\n trackChangeFadeOutMs: 300,\n trackChangeFadeInMs: 300,\n seekFadeMs: 120,\n fadeCurve: \"ease-out\",\n previousRestartThresholdSec: 3,\n seekCommitMode: \"on-release\",\n waveformPlayedStateEnabled: true,\n waveformOpacity: 0.72,\n initialShuffleEnabled: false,\n initialRepeatMode: \"off\",\n initialVolume: 0.8,\n persistMode: \"none\",\n podcastBackSec: 15,\n podcastForwardSec: 30,\n podcastPreviousMode: \"previous-episode\",\n });\n","import type {\n FadeCurve,\n PersistMode,\n PlayerExperienceConfig,\n PodcastPreviousMode,\n RepeatMode,\n SeekCommitMode,\n} from \"../contracts/player\";\nimport type { PlayerExperienceConfigValidationResult } from \"../contracts/config\";\nimport {\n PLAYER_EXPERIENCE_CONFIG_LIMITS,\n PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION,\n PREVIEW_PLAYER_EXPERIENCE_CONFIG,\n} from \"./defaults\";\n\nconst CONFIG_KEYS = [\n \"playFadeInMs\",\n \"pauseFadeOutMs\",\n \"trackChangeFadeOutMs\",\n \"trackChangeFadeInMs\",\n \"seekFadeMs\",\n \"fadeCurve\",\n \"previousRestartThresholdSec\",\n \"seekCommitMode\",\n \"waveformPlayedStateEnabled\",\n \"waveformOpacity\",\n \"initialShuffleEnabled\",\n \"initialRepeatMode\",\n \"initialVolume\",\n \"persistMode\",\n \"podcastBackSec\",\n \"podcastForwardSec\",\n \"podcastPreviousMode\",\n] as const satisfies readonly (keyof PlayerExperienceConfig)[];\n\nconst FADE_CURVES = new Set<FadeCurve>([\n \"linear\",\n \"ease-in\",\n \"ease-out\",\n \"equal-power\",\n]);\nconst SEEK_COMMIT_MODES = new Set<SeekCommitMode>([\"live\", \"on-release\"]);\nconst REPEAT_MODES = new Set<RepeatMode>([\"off\", \"all\", \"one\"]);\nconst PERSIST_MODES = new Set<PersistMode>([\"none\", \"session\", \"local\"]);\nconst PODCAST_PREVIOUS_MODES = new Set<PodcastPreviousMode>([\n \"previous-episode\",\n \"restart-episode\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateFiniteRange(\n value: unknown,\n path: string,\n min: number,\n max: number,\n errors: string[],\n): value is number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value < min ||\n value > max\n ) {\n errors.push(\n `${path} must be a finite number between ${String(min)} and ${String(max)}.`,\n );\n return false;\n }\n return true;\n}\n\nfunction validateBoolean(\n value: unknown,\n path: string,\n errors: string[],\n): value is boolean {\n if (typeof value !== \"boolean\") {\n errors.push(`${path} must be a boolean.`);\n return false;\n }\n return true;\n}\n\nfunction validateConfigRecord(\n value: unknown,\n options: { readonly partial: boolean },\n): PlayerExperienceConfigValidationResult {\n if (!isRecord(value)) {\n return { ok: false, errors: [\"config must be an object.\"] };\n }\n\n const errors: string[] = [];\n const allowedKeys = new Set<string>(CONFIG_KEYS);\n\n for (const key of Object.keys(value)) {\n if (!allowedKeys.has(key)) {\n errors.push(`config.${key} is not supported.`);\n }\n }\n\n if (!options.partial) {\n for (const key of CONFIG_KEYS) {\n if (!Object.hasOwn(value, key)) {\n errors.push(`config.${key} is required.`);\n }\n }\n }\n\n const has = (key: keyof PlayerExperienceConfig): boolean =>\n Object.hasOwn(value, key);\n const fadeLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.fadeMs;\n\n for (const key of [\n \"playFadeInMs\",\n \"pauseFadeOutMs\",\n \"trackChangeFadeOutMs\",\n \"trackChangeFadeInMs\",\n \"seekFadeMs\",\n ] as const) {\n if (has(key)) {\n validateFiniteRange(value[key], `config.${key}`, fadeLimits.min, fadeLimits.max, errors);\n }\n }\n\n const thresholdLimits =\n PLAYER_EXPERIENCE_CONFIG_LIMITS.previousRestartThresholdSec;\n if (has(\"previousRestartThresholdSec\")) {\n validateFiniteRange(\n value.previousRestartThresholdSec,\n \"config.previousRestartThresholdSec\",\n thresholdLimits.min,\n thresholdLimits.max,\n errors,\n );\n }\n\n const volumeLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.initialVolume;\n if (has(\"initialVolume\")) {\n validateFiniteRange(\n value.initialVolume,\n \"config.initialVolume\",\n volumeLimits.min,\n volumeLimits.max,\n errors,\n );\n }\n\n const waveformOpacityLimits =\n PLAYER_EXPERIENCE_CONFIG_LIMITS.waveformOpacity;\n if (has(\"waveformOpacity\")) {\n validateFiniteRange(\n value.waveformOpacity,\n \"config.waveformOpacity\",\n waveformOpacityLimits.min,\n waveformOpacityLimits.max,\n errors,\n );\n }\n\n for (const key of [\n \"waveformPlayedStateEnabled\",\n \"initialShuffleEnabled\",\n ] as const) {\n if (has(key)) {\n validateBoolean(value[key], `config.${key}`, errors);\n }\n }\n\n const skipLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.podcastSkipSec;\n for (const key of [\"podcastBackSec\", \"podcastForwardSec\"] as const) {\n if (has(key)) {\n const candidate = value[key];\n const valid = validateFiniteRange(\n candidate,\n `config.${key}`,\n skipLimits.minExclusive,\n skipLimits.max,\n errors,\n );\n if (valid && candidate <= skipLimits.minExclusive) {\n errors.push(`config.${key} must be greater than 0.`);\n }\n }\n }\n\n if (has(\"fadeCurve\") && !FADE_CURVES.has(value.fadeCurve as FadeCurve)) {\n errors.push(\"config.fadeCurve is not supported.\");\n }\n if (\n has(\"seekCommitMode\") &&\n !SEEK_COMMIT_MODES.has(value.seekCommitMode as SeekCommitMode)\n ) {\n errors.push(\"config.seekCommitMode is not supported.\");\n }\n if (\n has(\"initialRepeatMode\") &&\n !REPEAT_MODES.has(value.initialRepeatMode as RepeatMode)\n ) {\n errors.push(\"config.initialRepeatMode is not supported.\");\n }\n if (has(\"persistMode\") && !PERSIST_MODES.has(value.persistMode as PersistMode)) {\n errors.push(\"config.persistMode is not supported.\");\n }\n if (\n has(\"podcastPreviousMode\") &&\n !PODCAST_PREVIOUS_MODES.has(\n value.podcastPreviousMode as PodcastPreviousMode,\n )\n ) {\n errors.push(\"config.podcastPreviousMode is not supported.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors: Object.freeze(errors) };\n }\n\n const merged = options.partial\n ? { ...PREVIEW_PLAYER_EXPERIENCE_CONFIG, ...value }\n : value;\n\n return {\n ok: true,\n errors: [],\n value: Object.freeze({ ...merged }) as Readonly<PlayerExperienceConfig>,\n };\n}\n\nexport function validatePlayerExperienceConfig(\n value: unknown,\n): PlayerExperienceConfigValidationResult {\n return validateConfigRecord(value, { partial: false });\n}\n\nexport function validatePlayerExperienceConfigOverride(\n value: unknown,\n): PlayerExperienceConfigValidationResult {\n return validateConfigRecord(value, { partial: true });\n}\n\nexport function resolvePlayerExperienceConfig(\n override?: Partial<PlayerExperienceConfig>,\n): PlayerExperienceConfigValidationResult {\n return validatePlayerExperienceConfigOverride(override ?? {});\n}\n\nexport function parsePlayerExperienceConfigJson(\n json: string,\n): PlayerExperienceConfigValidationResult {\n let parsed: unknown;\n\n try {\n parsed = JSON.parse(json) as unknown;\n } catch {\n return { ok: false, errors: [\"Config JSON is not valid JSON.\"] };\n }\n\n if (!isRecord(parsed)) {\n return { ok: false, errors: [\"Config JSON envelope must be an object.\"] };\n }\n\n const envelopeKeys = Object.keys(parsed);\n const errors: string[] = [];\n\n for (const key of envelopeKeys) {\n if (key !== \"schemaVersion\" && key !== \"config\") {\n errors.push(`envelope.${key} is not supported.`);\n }\n }\n if (!Object.hasOwn(parsed, \"schemaVersion\")) {\n errors.push(\"envelope.schemaVersion is required.\");\n } else if (\n parsed.schemaVersion !== PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION\n ) {\n errors.push(\"envelope.schemaVersion is not supported.\");\n }\n if (!Object.hasOwn(parsed, \"config\")) {\n errors.push(\"envelope.config is required.\");\n }\n\n if (errors.length > 0) {\n return { ok: false, errors: Object.freeze(errors) };\n }\n\n return validatePlayerExperienceConfig(parsed.config);\n}\n\nexport function serializePlayerExperienceConfig(\n config: PlayerExperienceConfig,\n): string {\n const result = validatePlayerExperienceConfig(config);\n\n if (!result.ok) {\n throw new TypeError(result.errors.join(\" \"));\n }\n\n return JSON.stringify(\n {\n schemaVersion: PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION,\n config: result.value,\n },\n null,\n 2,\n );\n}\n","import type {\n PlayerExperienceConfig,\n PlayerState,\n} from \"../contracts/player\";\nimport { resolvePlayerExperienceConfig } from \"./validation\";\n\nexport function createInitialPlayerState(\n experienceConfig?: Partial<PlayerExperienceConfig>,\n): Readonly<PlayerState> {\n const resolved = resolvePlayerExperienceConfig(experienceConfig);\n\n if (!resolved.ok) {\n throw new TypeError(resolved.errors.join(\" \"));\n }\n\n return Object.freeze({\n currentItem: null,\n currentItemId: null,\n currentQueueItemId: null,\n mediaKind: null,\n status: \"idle\",\n currentTimeSec: 0,\n durationSec: null,\n volume: resolved.value.initialVolume,\n muted: false,\n shuffleEnabled: resolved.value.initialShuffleEnabled,\n repeatMode: resolved.value.initialRepeatMode,\n queue: Object.freeze([]),\n currentQueueIndex: null,\n canSeek: false,\n canGoPrevious: false,\n canGoNext: false,\n needsUserGesture: false,\n lastTransitionCause: null,\n error: null,\n experienceConfig: resolved.value,\n });\n}\n","import type {\n MediaUploadEvidence,\n MediaUploadValidationResult,\n SupportedUploadFormat,\n UploadValidationError,\n WaveformPeaksV1,\n} from \"./contracts\";\n\nconst EXTENSION_FORMATS = new Map<string, SupportedUploadFormat>([\n [\".wav\", \"wav\"],\n [\".mp3\", \"mp3\"],\n]);\n\nconst MIME_FORMATS = new Map<string, SupportedUploadFormat>([\n [\"audio/wave\", \"wav\"],\n [\"audio/wav\", \"wav\"],\n [\"audio/x-wav\", \"wav\"],\n [\"audio/vnd.wave\", \"wav\"],\n [\"audio/mpeg\", \"mp3\"],\n [\"audio/mp3\", \"mp3\"],\n]);\n\nfunction normalizeExtension(extension: string): string {\n const normalized = extension.trim().toLowerCase();\n return normalized.startsWith(\".\") ? normalized : `.${normalized}`;\n}\n\nfunction normalizeMimeType(mimeType: string): string {\n return mimeType.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\n}\n\nexport function validateMediaUploadEvidence(\n evidence: MediaUploadEvidence,\n): MediaUploadValidationResult {\n const extension = normalizeExtension(evidence.extension);\n const mimeType = normalizeMimeType(evidence.declaredMimeType);\n const extensionFormat = EXTENSION_FORMATS.get(extension);\n const mimeFormat = MIME_FORMATS.get(mimeType);\n const headerFormat =\n evidence.detectedHeaderFormat === \"unknown\"\n ? undefined\n : evidence.detectedHeaderFormat;\n const errors: UploadValidationError[] = [];\n\n if (extensionFormat === undefined) {\n errors.push({\n code: \"unsupported-extension\",\n field: \"extension\",\n });\n }\n if (mimeFormat === undefined) {\n errors.push({\n code: \"unsupported-mime-type\",\n field: \"declaredMimeType\",\n });\n }\n if (headerFormat === undefined) {\n errors.push({\n code: \"unrecognized-header\",\n field: \"detectedHeaderFormat\",\n });\n }\n if (\n extensionFormat !== undefined &&\n headerFormat !== undefined &&\n extensionFormat !== headerFormat\n ) {\n errors.push({\n code: \"extension-header-mismatch\",\n field: \"extension\",\n });\n }\n if (\n mimeFormat !== undefined &&\n headerFormat !== undefined &&\n mimeFormat !== headerFormat\n ) {\n errors.push({\n code: \"mime-header-mismatch\",\n field: \"declaredMimeType\",\n });\n }\n\n if (\n errors.length > 0 ||\n extensionFormat === undefined ||\n mimeFormat === undefined ||\n headerFormat === undefined\n ) {\n return Object.freeze({\n ok: false,\n errors: Object.freeze(errors),\n });\n }\n\n return Object.freeze({\n ok: true,\n value: Object.freeze({\n format: headerFormat,\n extension: headerFormat === \"wav\" ? \".wav\" : \".mp3\",\n mimeType: headerFormat === \"wav\" ? \"audio/wave\" : \"audio/mpeg\",\n }),\n errors: [] as const,\n });\n}\n\nexport function validateWaveformPeaks(\n waveform: WaveformPeaksV1,\n): readonly string[] {\n const errors: string[] = [];\n\n if (waveform.peaks.length === 0) {\n errors.push(\"waveform.peaks must contain at least one value.\");\n }\n\n waveform.peaks.forEach((peak, index) => {\n if (!Number.isFinite(peak) || peak < 0 || peak > 1) {\n errors.push(\n `waveform.peaks[${String(index)}] must be a finite number between 0 and 1.`,\n );\n }\n });\n\n return Object.freeze(errors);\n}\n"]}
1
+ {"version":3,"sources":["../src/config/defaults.ts","../src/config/validation.ts","../src/config/initial-state.ts","../src/media-delivery/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { PlayerExperienceConfig } from \"../contracts/player\";\r\n\r\nexport const PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION = 2 as const;\r\n\r\nexport const PLAYER_EXPERIENCE_CONFIG_LIMITS = Object.freeze({\r\n fadeMs: Object.freeze({ min: 0, max: 10_000 }),\r\n previousRestartThresholdSec: Object.freeze({ min: 0, max: 60 }),\r\n waveformOpacity: Object.freeze({ min: 0, max: 1 }),\r\n initialVolume: Object.freeze({ min: 0, max: 1 }),\r\n podcastSkipSec: Object.freeze({ minExclusive: 0, max: 3_600 }),\r\n});\r\n\r\nexport const PREVIEW_PLAYER_EXPERIENCE_CONFIG: Readonly<PlayerExperienceConfig> =\r\n Object.freeze({\r\n playFadeInMs: 300,\r\n pauseFadeOutMs: 600,\r\n trackChangeFadeOutMs: 300,\r\n trackChangeFadeInMs: 300,\r\n seekFadeMs: 120,\r\n fadeCurve: \"ease-out\",\r\n previousRestartThresholdSec: 3,\r\n seekCommitMode: \"on-release\",\r\n waveformPlayedStateEnabled: true,\r\n waveformOpacity: 0.72,\r\n initialShuffleEnabled: false,\r\n initialRepeatMode: \"off\",\r\n initialVolume: 0.8,\r\n persistMode: \"none\",\r\n podcastBackSec: 15,\r\n podcastForwardSec: 30,\r\n podcastPreviousMode: \"previous-episode\",\r\n });\r\n","import type {\r\n FadeCurve,\r\n PersistMode,\r\n PlayerExperienceConfig,\r\n PodcastPreviousMode,\r\n RepeatMode,\r\n SeekCommitMode,\r\n} from \"../contracts/player\";\r\nimport type { PlayerExperienceConfigValidationResult } from \"../contracts/config\";\r\nimport {\r\n PLAYER_EXPERIENCE_CONFIG_LIMITS,\r\n PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION,\r\n PREVIEW_PLAYER_EXPERIENCE_CONFIG,\r\n} from \"./defaults\";\r\n\r\nconst CONFIG_KEYS = [\r\n \"playFadeInMs\",\r\n \"pauseFadeOutMs\",\r\n \"trackChangeFadeOutMs\",\r\n \"trackChangeFadeInMs\",\r\n \"seekFadeMs\",\r\n \"fadeCurve\",\r\n \"previousRestartThresholdSec\",\r\n \"seekCommitMode\",\r\n \"waveformPlayedStateEnabled\",\r\n \"waveformOpacity\",\r\n \"initialShuffleEnabled\",\r\n \"initialRepeatMode\",\r\n \"initialVolume\",\r\n \"persistMode\",\r\n \"podcastBackSec\",\r\n \"podcastForwardSec\",\r\n \"podcastPreviousMode\",\r\n] as const satisfies readonly (keyof PlayerExperienceConfig)[];\r\n\r\nconst FADE_CURVES = new Set<FadeCurve>([\r\n \"linear\",\r\n \"ease-in\",\r\n \"ease-out\",\r\n \"equal-power\",\r\n]);\r\nconst SEEK_COMMIT_MODES = new Set<SeekCommitMode>([\"live\", \"on-release\"]);\r\nconst REPEAT_MODES = new Set<RepeatMode>([\"off\", \"all\", \"one\"]);\r\nconst PERSIST_MODES = new Set<PersistMode>([\"none\", \"session\", \"local\"]);\r\nconst PODCAST_PREVIOUS_MODES = new Set<PodcastPreviousMode>([\r\n \"previous-episode\",\r\n \"restart-episode\",\r\n]);\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction validateFiniteRange(\r\n value: unknown,\r\n path: string,\r\n min: number,\r\n max: number,\r\n errors: string[],\r\n): value is number {\r\n if (\r\n typeof value !== \"number\" ||\r\n !Number.isFinite(value) ||\r\n value < min ||\r\n value > max\r\n ) {\r\n errors.push(\r\n `${path} must be a finite number between ${String(min)} and ${String(max)}.`,\r\n );\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\nfunction validateBoolean(\r\n value: unknown,\r\n path: string,\r\n errors: string[],\r\n): value is boolean {\r\n if (typeof value !== \"boolean\") {\r\n errors.push(`${path} must be a boolean.`);\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\nfunction validateConfigRecord(\r\n value: unknown,\r\n options: { readonly partial: boolean },\r\n): PlayerExperienceConfigValidationResult {\r\n if (!isRecord(value)) {\r\n return { ok: false, errors: [\"config must be an object.\"] };\r\n }\r\n\r\n const errors: string[] = [];\r\n const allowedKeys = new Set<string>(CONFIG_KEYS);\r\n\r\n for (const key of Object.keys(value)) {\r\n if (!allowedKeys.has(key)) {\r\n errors.push(`config.${key} is not supported.`);\r\n }\r\n }\r\n\r\n if (!options.partial) {\r\n for (const key of CONFIG_KEYS) {\r\n if (!Object.hasOwn(value, key)) {\r\n errors.push(`config.${key} is required.`);\r\n }\r\n }\r\n }\r\n\r\n const has = (key: keyof PlayerExperienceConfig): boolean =>\r\n Object.hasOwn(value, key);\r\n const fadeLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.fadeMs;\r\n\r\n for (const key of [\r\n \"playFadeInMs\",\r\n \"pauseFadeOutMs\",\r\n \"trackChangeFadeOutMs\",\r\n \"trackChangeFadeInMs\",\r\n \"seekFadeMs\",\r\n ] as const) {\r\n if (has(key)) {\r\n validateFiniteRange(value[key], `config.${key}`, fadeLimits.min, fadeLimits.max, errors);\r\n }\r\n }\r\n\r\n const thresholdLimits =\r\n PLAYER_EXPERIENCE_CONFIG_LIMITS.previousRestartThresholdSec;\r\n if (has(\"previousRestartThresholdSec\")) {\r\n validateFiniteRange(\r\n value.previousRestartThresholdSec,\r\n \"config.previousRestartThresholdSec\",\r\n thresholdLimits.min,\r\n thresholdLimits.max,\r\n errors,\r\n );\r\n }\r\n\r\n const volumeLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.initialVolume;\r\n if (has(\"initialVolume\")) {\r\n validateFiniteRange(\r\n value.initialVolume,\r\n \"config.initialVolume\",\r\n volumeLimits.min,\r\n volumeLimits.max,\r\n errors,\r\n );\r\n }\r\n\r\n const waveformOpacityLimits =\r\n PLAYER_EXPERIENCE_CONFIG_LIMITS.waveformOpacity;\r\n if (has(\"waveformOpacity\")) {\r\n validateFiniteRange(\r\n value.waveformOpacity,\r\n \"config.waveformOpacity\",\r\n waveformOpacityLimits.min,\r\n waveformOpacityLimits.max,\r\n errors,\r\n );\r\n }\r\n\r\n for (const key of [\r\n \"waveformPlayedStateEnabled\",\r\n \"initialShuffleEnabled\",\r\n ] as const) {\r\n if (has(key)) {\r\n validateBoolean(value[key], `config.${key}`, errors);\r\n }\r\n }\r\n\r\n const skipLimits = PLAYER_EXPERIENCE_CONFIG_LIMITS.podcastSkipSec;\r\n for (const key of [\"podcastBackSec\", \"podcastForwardSec\"] as const) {\r\n if (has(key)) {\r\n const candidate = value[key];\r\n const valid = validateFiniteRange(\r\n candidate,\r\n `config.${key}`,\r\n skipLimits.minExclusive,\r\n skipLimits.max,\r\n errors,\r\n );\r\n if (valid && candidate <= skipLimits.minExclusive) {\r\n errors.push(`config.${key} must be greater than 0.`);\r\n }\r\n }\r\n }\r\n\r\n if (has(\"fadeCurve\") && !FADE_CURVES.has(value.fadeCurve as FadeCurve)) {\r\n errors.push(\"config.fadeCurve is not supported.\");\r\n }\r\n if (\r\n has(\"seekCommitMode\") &&\r\n !SEEK_COMMIT_MODES.has(value.seekCommitMode as SeekCommitMode)\r\n ) {\r\n errors.push(\"config.seekCommitMode is not supported.\");\r\n }\r\n if (\r\n has(\"initialRepeatMode\") &&\r\n !REPEAT_MODES.has(value.initialRepeatMode as RepeatMode)\r\n ) {\r\n errors.push(\"config.initialRepeatMode is not supported.\");\r\n }\r\n if (has(\"persistMode\") && !PERSIST_MODES.has(value.persistMode as PersistMode)) {\r\n errors.push(\"config.persistMode is not supported.\");\r\n }\r\n if (\r\n has(\"podcastPreviousMode\") &&\r\n !PODCAST_PREVIOUS_MODES.has(\r\n value.podcastPreviousMode as PodcastPreviousMode,\r\n )\r\n ) {\r\n errors.push(\"config.podcastPreviousMode is not supported.\");\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { ok: false, errors: Object.freeze(errors) };\r\n }\r\n\r\n const merged = options.partial\r\n ? { ...PREVIEW_PLAYER_EXPERIENCE_CONFIG, ...value }\r\n : value;\r\n\r\n return {\r\n ok: true,\r\n errors: [],\r\n value: Object.freeze({ ...merged }) as Readonly<PlayerExperienceConfig>,\r\n };\r\n}\r\n\r\nexport function validatePlayerExperienceConfig(\r\n value: unknown,\r\n): PlayerExperienceConfigValidationResult {\r\n return validateConfigRecord(value, { partial: false });\r\n}\r\n\r\nexport function validatePlayerExperienceConfigOverride(\r\n value: unknown,\r\n): PlayerExperienceConfigValidationResult {\r\n return validateConfigRecord(value, { partial: true });\r\n}\r\n\r\nexport function resolvePlayerExperienceConfig(\r\n override?: Partial<PlayerExperienceConfig>,\r\n): PlayerExperienceConfigValidationResult {\r\n return validatePlayerExperienceConfigOverride(override ?? {});\r\n}\r\n\r\nexport function parsePlayerExperienceConfigJson(\r\n json: string,\r\n): PlayerExperienceConfigValidationResult {\r\n let parsed: unknown;\r\n\r\n try {\r\n parsed = JSON.parse(json) as unknown;\r\n } catch {\r\n return { ok: false, errors: [\"Config JSON is not valid JSON.\"] };\r\n }\r\n\r\n if (!isRecord(parsed)) {\r\n return { ok: false, errors: [\"Config JSON envelope must be an object.\"] };\r\n }\r\n\r\n const envelopeKeys = Object.keys(parsed);\r\n const errors: string[] = [];\r\n\r\n for (const key of envelopeKeys) {\r\n if (key !== \"schemaVersion\" && key !== \"config\") {\r\n errors.push(`envelope.${key} is not supported.`);\r\n }\r\n }\r\n if (!Object.hasOwn(parsed, \"schemaVersion\")) {\r\n errors.push(\"envelope.schemaVersion is required.\");\r\n } else if (\r\n parsed.schemaVersion !== PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION\r\n ) {\r\n errors.push(\"envelope.schemaVersion is not supported.\");\r\n }\r\n if (!Object.hasOwn(parsed, \"config\")) {\r\n errors.push(\"envelope.config is required.\");\r\n }\r\n\r\n if (errors.length > 0) {\r\n return { ok: false, errors: Object.freeze(errors) };\r\n }\r\n\r\n return validatePlayerExperienceConfig(parsed.config);\r\n}\r\n\r\nexport function serializePlayerExperienceConfig(\r\n config: PlayerExperienceConfig,\r\n): string {\r\n const result = validatePlayerExperienceConfig(config);\r\n\r\n if (!result.ok) {\r\n throw new TypeError(result.errors.join(\" \"));\r\n }\r\n\r\n return JSON.stringify(\r\n {\r\n schemaVersion: PLAYER_EXPERIENCE_CONFIG_SCHEMA_VERSION,\r\n config: result.value,\r\n },\r\n null,\r\n 2,\r\n );\r\n}\r\n","import type {\r\n PlayerExperienceConfig,\r\n PlayerState,\r\n} from \"../contracts/player\";\r\nimport { resolvePlayerExperienceConfig } from \"./validation\";\r\n\r\nexport function createInitialPlayerState(\r\n experienceConfig?: Partial<PlayerExperienceConfig>,\r\n): Readonly<PlayerState> {\r\n const resolved = resolvePlayerExperienceConfig(experienceConfig);\r\n\r\n if (!resolved.ok) {\r\n throw new TypeError(resolved.errors.join(\" \"));\r\n }\r\n\r\n return Object.freeze({\r\n currentItem: null,\r\n currentItemId: null,\r\n currentQueueItemId: null,\r\n mediaKind: null,\r\n status: \"idle\",\r\n currentTimeSec: 0,\r\n durationSec: null,\r\n volume: resolved.value.initialVolume,\r\n muted: false,\r\n shuffleEnabled: resolved.value.initialShuffleEnabled,\r\n repeatMode: resolved.value.initialRepeatMode,\r\n queue: Object.freeze([]),\r\n activeContext: null,\r\n currentQueueIndex: null,\r\n canSeek: false,\r\n canGoPrevious: false,\r\n canGoNext: false,\r\n needsUserGesture: false,\r\n lastTransitionCause: null,\r\n error: null,\r\n experienceConfig: resolved.value,\r\n });\r\n}\r\n","import type {\r\n MediaUploadEvidence,\r\n MediaUploadValidationResult,\r\n SupportedUploadFormat,\r\n UploadValidationError,\r\n WaveformPeaksV1,\r\n} from \"./contracts\";\r\n\r\nconst EXTENSION_FORMATS = new Map<string, SupportedUploadFormat>([\r\n [\".wav\", \"wav\"],\r\n [\".mp3\", \"mp3\"],\r\n]);\r\n\r\nconst MIME_FORMATS = new Map<string, SupportedUploadFormat>([\r\n [\"audio/wave\", \"wav\"],\r\n [\"audio/wav\", \"wav\"],\r\n [\"audio/x-wav\", \"wav\"],\r\n [\"audio/vnd.wave\", \"wav\"],\r\n [\"audio/mpeg\", \"mp3\"],\r\n [\"audio/mp3\", \"mp3\"],\r\n]);\r\n\r\nfunction normalizeExtension(extension: string): string {\r\n const normalized = extension.trim().toLowerCase();\r\n return normalized.startsWith(\".\") ? normalized : `.${normalized}`;\r\n}\r\n\r\nfunction normalizeMimeType(mimeType: string): string {\r\n return mimeType.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\r\n}\r\n\r\nexport function validateMediaUploadEvidence(\r\n evidence: MediaUploadEvidence,\r\n): MediaUploadValidationResult {\r\n const extension = normalizeExtension(evidence.extension);\r\n const mimeType = normalizeMimeType(evidence.declaredMimeType);\r\n const extensionFormat = EXTENSION_FORMATS.get(extension);\r\n const mimeFormat = MIME_FORMATS.get(mimeType);\r\n const headerFormat =\r\n evidence.detectedHeaderFormat === \"unknown\"\r\n ? undefined\r\n : evidence.detectedHeaderFormat;\r\n const errors: UploadValidationError[] = [];\r\n\r\n if (extensionFormat === undefined) {\r\n errors.push({\r\n code: \"unsupported-extension\",\r\n field: \"extension\",\r\n });\r\n }\r\n if (mimeFormat === undefined) {\r\n errors.push({\r\n code: \"unsupported-mime-type\",\r\n field: \"declaredMimeType\",\r\n });\r\n }\r\n if (headerFormat === undefined) {\r\n errors.push({\r\n code: \"unrecognized-header\",\r\n field: \"detectedHeaderFormat\",\r\n });\r\n }\r\n if (\r\n extensionFormat !== undefined &&\r\n headerFormat !== undefined &&\r\n extensionFormat !== headerFormat\r\n ) {\r\n errors.push({\r\n code: \"extension-header-mismatch\",\r\n field: \"extension\",\r\n });\r\n }\r\n if (\r\n mimeFormat !== undefined &&\r\n headerFormat !== undefined &&\r\n mimeFormat !== headerFormat\r\n ) {\r\n errors.push({\r\n code: \"mime-header-mismatch\",\r\n field: \"declaredMimeType\",\r\n });\r\n }\r\n\r\n if (\r\n errors.length > 0 ||\r\n extensionFormat === undefined ||\r\n mimeFormat === undefined ||\r\n headerFormat === undefined\r\n ) {\r\n return Object.freeze({\r\n ok: false,\r\n errors: Object.freeze(errors),\r\n });\r\n }\r\n\r\n return Object.freeze({\r\n ok: true,\r\n value: Object.freeze({\r\n format: headerFormat,\r\n extension: headerFormat === \"wav\" ? \".wav\" : \".mp3\",\r\n mimeType: headerFormat === \"wav\" ? \"audio/wave\" : \"audio/mpeg\",\r\n }),\r\n errors: [] as const,\r\n });\r\n}\r\n\r\nexport function validateWaveformPeaks(\r\n waveform: WaveformPeaksV1,\r\n): readonly string[] {\r\n const errors: string[] = [];\r\n\r\n if (waveform.peaks.length === 0) {\r\n errors.push(\"waveform.peaks must contain at least one value.\");\r\n }\r\n\r\n waveform.peaks.forEach((peak, index) => {\r\n if (!Number.isFinite(peak) || peak < 0 || peak > 1) {\r\n errors.push(\r\n `waveform.peaks[${String(index)}] must be a finite number between 0 and 1.`,\r\n );\r\n }\r\n });\r\n\r\n return Object.freeze(errors);\r\n}\r\n"]}
@@ -1,4 +1,4 @@
1
- import { s as PlayerMediaSource, r as PlayerMediaItem } from '../player-DE9Vqztu.js';
1
+ import { w as PlayerMediaSource, v as PlayerMediaItem } from '../player-BxNFzRq4.js';
2
2
 
3
3
  declare const MEDIA_DELIVERY_CONTRACT_VERSION: 1;
4
4
  type SupportedUploadFormat = "wav" | "mp3";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/media-delivery/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n MediaUploadEvidence,\n MediaUploadValidationResult,\n SupportedUploadFormat,\n UploadValidationError,\n WaveformPeaksV1,\n} from \"./contracts\";\n\nconst EXTENSION_FORMATS = new Map<string, SupportedUploadFormat>([\n [\".wav\", \"wav\"],\n [\".mp3\", \"mp3\"],\n]);\n\nconst MIME_FORMATS = new Map<string, SupportedUploadFormat>([\n [\"audio/wave\", \"wav\"],\n [\"audio/wav\", \"wav\"],\n [\"audio/x-wav\", \"wav\"],\n [\"audio/vnd.wave\", \"wav\"],\n [\"audio/mpeg\", \"mp3\"],\n [\"audio/mp3\", \"mp3\"],\n]);\n\nfunction normalizeExtension(extension: string): string {\n const normalized = extension.trim().toLowerCase();\n return normalized.startsWith(\".\") ? normalized : `.${normalized}`;\n}\n\nfunction normalizeMimeType(mimeType: string): string {\n return mimeType.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\n}\n\nexport function validateMediaUploadEvidence(\n evidence: MediaUploadEvidence,\n): MediaUploadValidationResult {\n const extension = normalizeExtension(evidence.extension);\n const mimeType = normalizeMimeType(evidence.declaredMimeType);\n const extensionFormat = EXTENSION_FORMATS.get(extension);\n const mimeFormat = MIME_FORMATS.get(mimeType);\n const headerFormat =\n evidence.detectedHeaderFormat === \"unknown\"\n ? undefined\n : evidence.detectedHeaderFormat;\n const errors: UploadValidationError[] = [];\n\n if (extensionFormat === undefined) {\n errors.push({\n code: \"unsupported-extension\",\n field: \"extension\",\n });\n }\n if (mimeFormat === undefined) {\n errors.push({\n code: \"unsupported-mime-type\",\n field: \"declaredMimeType\",\n });\n }\n if (headerFormat === undefined) {\n errors.push({\n code: \"unrecognized-header\",\n field: \"detectedHeaderFormat\",\n });\n }\n if (\n extensionFormat !== undefined &&\n headerFormat !== undefined &&\n extensionFormat !== headerFormat\n ) {\n errors.push({\n code: \"extension-header-mismatch\",\n field: \"extension\",\n });\n }\n if (\n mimeFormat !== undefined &&\n headerFormat !== undefined &&\n mimeFormat !== headerFormat\n ) {\n errors.push({\n code: \"mime-header-mismatch\",\n field: \"declaredMimeType\",\n });\n }\n\n if (\n errors.length > 0 ||\n extensionFormat === undefined ||\n mimeFormat === undefined ||\n headerFormat === undefined\n ) {\n return Object.freeze({\n ok: false,\n errors: Object.freeze(errors),\n });\n }\n\n return Object.freeze({\n ok: true,\n value: Object.freeze({\n format: headerFormat,\n extension: headerFormat === \"wav\" ? \".wav\" : \".mp3\",\n mimeType: headerFormat === \"wav\" ? \"audio/wave\" : \"audio/mpeg\",\n }),\n errors: [] as const,\n });\n}\n\nexport function validateWaveformPeaks(\n waveform: WaveformPeaksV1,\n): readonly string[] {\n const errors: string[] = [];\n\n if (waveform.peaks.length === 0) {\n errors.push(\"waveform.peaks must contain at least one value.\");\n }\n\n waveform.peaks.forEach((peak, index) => {\n if (!Number.isFinite(peak) || peak < 0 || peak > 1) {\n errors.push(\n `waveform.peaks[${String(index)}] must be a finite number between 0 and 1.`,\n );\n }\n });\n\n return Object.freeze(errors);\n}\n"]}
1
+ {"version":3,"sources":["../../src/media-delivery/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\r\n MediaUploadEvidence,\r\n MediaUploadValidationResult,\r\n SupportedUploadFormat,\r\n UploadValidationError,\r\n WaveformPeaksV1,\r\n} from \"./contracts\";\r\n\r\nconst EXTENSION_FORMATS = new Map<string, SupportedUploadFormat>([\r\n [\".wav\", \"wav\"],\r\n [\".mp3\", \"mp3\"],\r\n]);\r\n\r\nconst MIME_FORMATS = new Map<string, SupportedUploadFormat>([\r\n [\"audio/wave\", \"wav\"],\r\n [\"audio/wav\", \"wav\"],\r\n [\"audio/x-wav\", \"wav\"],\r\n [\"audio/vnd.wave\", \"wav\"],\r\n [\"audio/mpeg\", \"mp3\"],\r\n [\"audio/mp3\", \"mp3\"],\r\n]);\r\n\r\nfunction normalizeExtension(extension: string): string {\r\n const normalized = extension.trim().toLowerCase();\r\n return normalized.startsWith(\".\") ? normalized : `.${normalized}`;\r\n}\r\n\r\nfunction normalizeMimeType(mimeType: string): string {\r\n return mimeType.split(\";\", 1)[0]?.trim().toLowerCase() ?? \"\";\r\n}\r\n\r\nexport function validateMediaUploadEvidence(\r\n evidence: MediaUploadEvidence,\r\n): MediaUploadValidationResult {\r\n const extension = normalizeExtension(evidence.extension);\r\n const mimeType = normalizeMimeType(evidence.declaredMimeType);\r\n const extensionFormat = EXTENSION_FORMATS.get(extension);\r\n const mimeFormat = MIME_FORMATS.get(mimeType);\r\n const headerFormat =\r\n evidence.detectedHeaderFormat === \"unknown\"\r\n ? undefined\r\n : evidence.detectedHeaderFormat;\r\n const errors: UploadValidationError[] = [];\r\n\r\n if (extensionFormat === undefined) {\r\n errors.push({\r\n code: \"unsupported-extension\",\r\n field: \"extension\",\r\n });\r\n }\r\n if (mimeFormat === undefined) {\r\n errors.push({\r\n code: \"unsupported-mime-type\",\r\n field: \"declaredMimeType\",\r\n });\r\n }\r\n if (headerFormat === undefined) {\r\n errors.push({\r\n code: \"unrecognized-header\",\r\n field: \"detectedHeaderFormat\",\r\n });\r\n }\r\n if (\r\n extensionFormat !== undefined &&\r\n headerFormat !== undefined &&\r\n extensionFormat !== headerFormat\r\n ) {\r\n errors.push({\r\n code: \"extension-header-mismatch\",\r\n field: \"extension\",\r\n });\r\n }\r\n if (\r\n mimeFormat !== undefined &&\r\n headerFormat !== undefined &&\r\n mimeFormat !== headerFormat\r\n ) {\r\n errors.push({\r\n code: \"mime-header-mismatch\",\r\n field: \"declaredMimeType\",\r\n });\r\n }\r\n\r\n if (\r\n errors.length > 0 ||\r\n extensionFormat === undefined ||\r\n mimeFormat === undefined ||\r\n headerFormat === undefined\r\n ) {\r\n return Object.freeze({\r\n ok: false,\r\n errors: Object.freeze(errors),\r\n });\r\n }\r\n\r\n return Object.freeze({\r\n ok: true,\r\n value: Object.freeze({\r\n format: headerFormat,\r\n extension: headerFormat === \"wav\" ? \".wav\" : \".mp3\",\r\n mimeType: headerFormat === \"wav\" ? \"audio/wave\" : \"audio/mpeg\",\r\n }),\r\n errors: [] as const,\r\n });\r\n}\r\n\r\nexport function validateWaveformPeaks(\r\n waveform: WaveformPeaksV1,\r\n): readonly string[] {\r\n const errors: string[] = [];\r\n\r\n if (waveform.peaks.length === 0) {\r\n errors.push(\"waveform.peaks must contain at least one value.\");\r\n }\r\n\r\n waveform.peaks.forEach((peak, index) => {\r\n if (!Number.isFinite(peak) || peak < 0 || peak > 1) {\r\n errors.push(\r\n `waveform.peaks[${String(index)}] must be a finite number between 0 and 1.`,\r\n );\r\n }\r\n });\r\n\r\n return Object.freeze(errors);\r\n}\r\n"]}
@@ -1,4 +1,4 @@
1
- import { j as PlayerError, s as PlayerMediaSource } from './player-DE9Vqztu.js';
1
+ import { n as PlayerError, w as PlayerMediaSource } from './player-BxNFzRq4.js';
2
2
 
3
3
  type PlayerMediaEventType = "loadstart" | "loadedmetadata" | "canplay" | "play" | "playing" | "pause" | "waiting" | "stalled" | "seeking" | "seeked" | "timeupdate" | "ended" | "error" | "durationchange" | "volumechange";
4
4
  interface PlayerMediaEvent {
@@ -60,6 +60,27 @@ interface QueueItem {
60
60
  readonly queueItemId: string;
61
61
  readonly item: PlayerMediaItem;
62
62
  }
63
+ type PlaybackContextMode = "manual-history" | "ordered-queue";
64
+ interface PlaybackContextState {
65
+ /** Stable consumer-owned identifier; Core does not interpret it. */
66
+ readonly id: string;
67
+ readonly mode: PlaybackContextMode;
68
+ readonly label?: string;
69
+ readonly queue: readonly QueueItem[];
70
+ readonly currentQueueItemId: string | null;
71
+ }
72
+ type PlaybackContextInput = {
73
+ readonly id: string;
74
+ readonly mode: "manual-history";
75
+ readonly label?: string;
76
+ /** Manual history ignores unplayed entries and records explicit plays. */
77
+ readonly queue?: readonly QueueItem[];
78
+ } | {
79
+ readonly id: string;
80
+ readonly mode: "ordered-queue";
81
+ readonly label?: string;
82
+ readonly queue: readonly QueueItem[];
83
+ };
63
84
  type PlayerErrorCode = "autoplay-blocked" | "network" | "cors" | "decode" | "unsupported" | "audio-context" | "unknown";
64
85
  interface PlayerError {
65
86
  readonly code: PlayerErrorCode;
@@ -79,6 +100,7 @@ interface PlayerState {
79
100
  readonly shuffleEnabled: boolean;
80
101
  readonly repeatMode: RepeatMode;
81
102
  readonly queue: readonly QueueItem[];
103
+ readonly activeContext: PlaybackContextState | null;
82
104
  readonly currentQueueIndex: number | null;
83
105
  readonly canSeek: boolean;
84
106
  readonly canGoPrevious: boolean;
@@ -95,6 +117,33 @@ interface PlayerState {
95
117
  interface SetQueueOptions {
96
118
  readonly startQueueItemId?: string;
97
119
  readonly autoplay?: boolean;
120
+ /** Forces source assignment and load even when occurrence and source match. */
121
+ readonly reload?: boolean;
122
+ }
123
+ interface ActivatePlaybackContextOptions {
124
+ readonly contextId: string;
125
+ readonly mode: PlaybackContextMode;
126
+ readonly label?: string;
127
+ readonly queue?: readonly QueueItem[];
128
+ readonly startQueueItemId: string;
129
+ readonly autoplay?: boolean;
130
+ /** Forces source assignment and load for the selected occurrence. */
131
+ readonly reload?: boolean;
132
+ }
133
+ interface BoundPlayerViewState {
134
+ readonly queueItemId: string;
135
+ readonly item: PlayerMediaItem;
136
+ readonly isActive: boolean;
137
+ readonly status: PlaybackStatus;
138
+ readonly currentTimeSec: number;
139
+ readonly durationSec: number | null;
140
+ readonly canSeek: boolean;
141
+ readonly isPlaying: boolean;
142
+ }
143
+ interface BoundPlayerCommands {
144
+ play(): Promise<PlayerCommandResult>;
145
+ togglePlayback(): Promise<PlayerCommandResult>;
146
+ seekTo(seconds: number): void;
98
147
  }
99
148
  interface PauseOptions {
100
149
  /** When omitted, Core applies the configured pause fade. */
@@ -113,6 +162,9 @@ interface PlayerCommandResult {
113
162
  interface PlayerCommands {
114
163
  load(item: PlayerMediaItem): Promise<PlayerCommandResult>;
115
164
  setQueue(queue: readonly QueueItem[], options?: SetQueueOptions): Promise<PlayerCommandResult>;
165
+ activateContext(options: ActivatePlaybackContextOptions): Promise<PlayerCommandResult>;
166
+ /** Appends without selecting or reloading the active media occurrence. */
167
+ appendToManualHistory(contextId: string, item: QueueItem): void;
116
168
  play(): Promise<PlayerCommandResult>;
117
169
  pause(options?: PauseOptions): Promise<void>;
118
170
  stop(options?: StopOptions): Promise<void>;
@@ -209,4 +261,4 @@ interface PlayerDebugController {
209
261
  exportProductionConfigJson(): string;
210
262
  }
211
263
 
212
- export type { StopOptions as A, FadeCurve as F, MediaKind as M, PauseOptions as P, QueueItem as Q, RepeatMode as R, SeekCommitMode as S, PersistMode as a, PlaybackStatus as b, PlaybackTransitionCause as c, PlayerAppearance as d, PlayerCommandResult as e, PlayerCommands as f, PlayerConfigImportResult as g, PlayerDebugController as h, PlayerDebugSnapshot as i, PlayerError as j, PlayerErrorCode as k, PlayerExperienceConfig as l, PlayerExperienceConfigEnvelope as m, PlayerExperienceConfigStore as n, PlayerExperiencePreset as o, PlayerHostConfig as p, PlayerMediaAdapter as q, PlayerMediaItem as r, PlayerMediaSource as s, PlayerMediaSyncReason as t, PlayerState as u, PlayerStore as v, PlayerViewProps as w, PlayerWaveform as x, PodcastPreviousMode as y, SetQueueOptions as z };
264
+ export type { ActivatePlaybackContextOptions as A, BoundPlayerCommands as B, PlayerViewProps as C, PlayerWaveform as D, PodcastPreviousMode as E, FadeCurve as F, SetQueueOptions as G, StopOptions as H, MediaKind as M, PauseOptions as P, QueueItem as Q, RepeatMode as R, SeekCommitMode as S, BoundPlayerViewState as a, PersistMode as b, PlaybackContextInput as c, PlaybackContextMode as d, PlaybackContextState as e, PlaybackStatus as f, PlaybackTransitionCause as g, PlayerAppearance as h, PlayerCommandResult as i, PlayerCommands as j, PlayerConfigImportResult as k, PlayerDebugController as l, PlayerDebugSnapshot as m, PlayerError as n, PlayerErrorCode as o, PlayerExperienceConfig as p, PlayerExperienceConfigEnvelope as q, PlayerExperienceConfigStore as r, PlayerExperiencePreset as s, PlayerHostConfig as t, PlayerMediaAdapter as u, PlayerMediaItem as v, PlayerMediaSource as w, PlayerMediaSyncReason as x, PlayerState as y, PlayerStore as z };
@@ -1,5 +1,5 @@
1
- import { F as FadeCurve } from '../player-DE9Vqztu.js';
2
- export { M as MediaElementPort, a as MediaElementStateSnapshot, P as PlayerMediaEvent, b as PlayerMediaEventListener, c as PlayerMediaEventType } from '../media-element-C9dis4aG.js';
1
+ import { F as FadeCurve } from '../player-BxNFzRq4.js';
2
+ export { M as MediaElementPort, a as MediaElementStateSnapshot, P as PlayerMediaEvent, b as PlayerMediaEventListener, c as PlayerMediaEventType } from '../media-element-DyMO-PhK.js';
3
3
 
4
4
  interface GainTransition {
5
5
  readonly durationMs: number;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { f as PlayerCommands, t as PlayerMediaSyncReason, Q as QueueItem, l as PlayerExperienceConfig, v as PlayerStore, n as PlayerExperienceConfigStore, u as PlayerState } from '../player-DE9Vqztu.js';
4
- import { c as PlayerMediaEventType, a as MediaElementStateSnapshot } from '../media-element-C9dis4aG.js';
3
+ import { j as PlayerCommands, x as PlayerMediaSyncReason, Q as QueueItem, p as PlayerExperienceConfig, z as PlayerStore, r as PlayerExperienceConfigStore, y as PlayerState, c as PlaybackContextInput, a as BoundPlayerViewState, B as BoundPlayerCommands } from '../player-BxNFzRq4.js';
4
+ import { c as PlayerMediaEventType, a as MediaElementStateSnapshot } from '../media-element-DyMO-PhK.js';
5
5
 
6
6
  type PlayerAudioMode = "auto" | "web-audio" | "html-media";
7
7
  type ResolvedPlayerAudioMode = "web-audio" | "html-media";
@@ -83,4 +83,15 @@ interface UsePlayerResult {
83
83
  }
84
84
  declare function usePlayer(): UsePlayerResult;
85
85
 
86
- export { MiniPlayerHost, type MiniPlayerHostProps, PlayerProvider, type PlayerProviderProps, type PlayerRuntimeContextValue, type PlayerRuntimeDiagnosticEvent, type PlayerRuntimeDiagnosticListener, type PlayerRuntimeDiagnosticPayload, type UsePlayerResult, usePlayer };
86
+ interface UseBoundPlayerOptions {
87
+ readonly context: PlaybackContextInput;
88
+ readonly queueItem: QueueItem;
89
+ }
90
+ interface UseBoundPlayerResult {
91
+ readonly state: Readonly<BoundPlayerViewState>;
92
+ readonly commands: BoundPlayerCommands;
93
+ }
94
+ declare function deriveBoundPlayerViewState(playerState: Readonly<PlayerState>, contextId: string, queueItem: QueueItem): Readonly<BoundPlayerViewState>;
95
+ declare function useBoundPlayer({ context, queueItem, }: UseBoundPlayerOptions): UseBoundPlayerResult;
96
+
97
+ export { MiniPlayerHost, type MiniPlayerHostProps, PlayerProvider, type PlayerProviderProps, type PlayerRuntimeContextValue, type PlayerRuntimeDiagnosticEvent, type PlayerRuntimeDiagnosticListener, type PlayerRuntimeDiagnosticPayload, type UseBoundPlayerOptions, type UseBoundPlayerResult, type UsePlayerResult, deriveBoundPlayerViewState, useBoundPlayer, usePlayer };
@@ -1,4 +1,4 @@
1
- import { createContext, useRef, useState, useEffect, useSyncExternalStore, useContext } from 'react';
1
+ import { createContext, useRef, useState, useEffect, useSyncExternalStore, useMemo, useContext } from 'react';
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
 
4
4
  // src/react/player-provider.tsx
@@ -845,6 +845,7 @@ function createInitialPlayerState(experienceConfig) {
845
845
  shuffleEnabled: resolved.value.initialShuffleEnabled,
846
846
  repeatMode: resolved.value.initialRepeatMode,
847
847
  queue: Object.freeze([]),
848
+ activeContext: null,
848
849
  currentQueueIndex: null,
849
850
  canSeek: false,
850
851
  canGoPrevious: false,
@@ -995,16 +996,32 @@ function deriveCurrentIndex(queue, queueItemId) {
995
996
  const index = queue.findIndex((entry) => entry.queueItemId === queueItemId);
996
997
  return index < 0 ? null : index;
997
998
  }
999
+ function synchronizeActiveContext(context, queue, currentQueueItemId) {
1000
+ if (context === null) {
1001
+ return null;
1002
+ }
1003
+ return Object.freeze({
1004
+ ...context,
1005
+ queue,
1006
+ currentQueueItemId
1007
+ });
1008
+ }
998
1009
  function createPlayerSnapshot(previous, patch) {
999
1010
  const queue = patch.queue === void 0 ? previous.queue : freezeQueue(patch.queue);
1000
1011
  const currentQueueItemId = patch.currentQueueItemId === void 0 ? previous.currentQueueItemId : patch.currentQueueItemId;
1001
1012
  const currentQueueIndex = deriveCurrentIndex(queue, currentQueueItemId);
1002
1013
  const repeatMode = patch.repeatMode ?? previous.repeatMode;
1003
1014
  const currentItem = patch.currentItem === void 0 ? previous.currentItem : patch.currentItem;
1015
+ const activeContext = synchronizeActiveContext(
1016
+ patch.activeContext === void 0 ? previous.activeContext : patch.activeContext,
1017
+ queue,
1018
+ currentQueueItemId
1019
+ );
1004
1020
  return Object.freeze({
1005
1021
  ...previous,
1006
1022
  ...patch,
1007
1023
  queue,
1024
+ activeContext,
1008
1025
  currentQueueItemId,
1009
1026
  currentQueueIndex,
1010
1027
  canGoPrevious: patch.canGoPrevious ?? currentItem !== null,
@@ -1065,6 +1082,9 @@ function clampVolume2(value) {
1065
1082
  }
1066
1083
  return Math.min(Math.max(value, 0), 1);
1067
1084
  }
1085
+ function sourcesMatch(left, right) {
1086
+ return left.url === right.url && left.mimeType === right.mimeType;
1087
+ }
1068
1088
  var CorePlayerStore = class {
1069
1089
  commands;
1070
1090
  experience;
@@ -1117,6 +1137,10 @@ var CorePlayerStore = class {
1117
1137
  const commands = {
1118
1138
  load: (item) => this.#load(item),
1119
1139
  setQueue: (queue, commandOptions) => this.#setQueue(queue, commandOptions),
1140
+ activateContext: (commandOptions) => this.#activateContext(commandOptions),
1141
+ appendToManualHistory: (contextId, item) => {
1142
+ this.#appendToManualHistory(contextId, item);
1143
+ },
1120
1144
  play: () => this.#play(),
1121
1145
  pause: (commandOptions) => this.#pause(commandOptions),
1122
1146
  stop: (commandOptions) => this.#stop(commandOptions),
@@ -1279,7 +1303,7 @@ var CorePlayerStore = class {
1279
1303
  async #load(item) {
1280
1304
  return this.#setQueue([createLoadedQueueItem(item)]);
1281
1305
  }
1282
- async #setQueue(queue, options = {}) {
1306
+ async #setQueue(queue, options = {}, activeContext) {
1283
1307
  if (this.#destroyed) {
1284
1308
  return failed(DESTROYED_ERROR);
1285
1309
  }
@@ -1291,15 +1315,23 @@ var CorePlayerStore = class {
1291
1315
  return OK_RESULT;
1292
1316
  }
1293
1317
  const normalizedQueue = freezeQueue(queue);
1294
- const startQueueItemId = options.startQueueItemId ?? normalizedQueue[0]?.queueItemId;
1318
+ const currentQueueItemId = this.#state.currentQueueItemId;
1319
+ const currentStillExists = currentQueueItemId !== null && findQueueIndex(normalizedQueue, currentQueueItemId) !== null;
1320
+ const startQueueItemId = options.startQueueItemId ?? (currentStillExists ? currentQueueItemId : normalizedQueue[0]?.queueItemId);
1295
1321
  const startIndex = startQueueItemId === void 0 ? null : findQueueIndex(normalizedQueue, startQueueItemId);
1296
1322
  if (startIndex === null) {
1297
1323
  return failed(INVALID_QUEUE_ERROR);
1298
1324
  }
1299
- const version = this.#beginCommand(
1300
- options.autoplay === true ? "playing" : "paused"
1301
- );
1302
- const playbackQueue = this.#state.shuffleEnabled && startQueueItemId !== void 0 ? shuffleQueueAroundCurrent(
1325
+ const selected = normalizedQueue[startIndex];
1326
+ if (selected === void 0) {
1327
+ return failed(INVALID_QUEUE_ERROR);
1328
+ }
1329
+ const preservePlayback = options.reload !== true && currentQueueItemId === selected.queueItemId && this.#state.currentItem !== null && sourcesMatch(this.#state.currentItem.source, selected.item.source);
1330
+ const targetContext = activeContext ?? this.#state.activeContext;
1331
+ const manualHistory = targetContext?.mode === "manual-history";
1332
+ const shuffleEnabled = manualHistory ? false : this.#state.shuffleEnabled;
1333
+ const repeatMode = manualHistory && this.#state.repeatMode === "all" ? "off" : this.#state.repeatMode;
1334
+ const playbackQueue = shuffleEnabled && startQueueItemId !== void 0 ? shuffleQueueAroundCurrent(
1303
1335
  normalizedQueue,
1304
1336
  startQueueItemId,
1305
1337
  this.#random
@@ -1307,18 +1339,97 @@ var CorePlayerStore = class {
1307
1339
  this.#playbackOrderQueueItemIds = Object.freeze(
1308
1340
  playbackQueue.map((entry) => entry.queueItemId)
1309
1341
  );
1310
- this.#playbackOrderCursor = this.#state.shuffleEnabled ? 0 : startIndex;
1342
+ this.#playbackOrderCursor = shuffleEnabled ? 0 : startIndex;
1311
1343
  this.#setState({
1312
1344
  queue: normalizedQueue,
1313
- repeatMode: this.#state.repeatMode,
1345
+ ...activeContext === void 0 ? {} : { activeContext },
1346
+ currentItem: preservePlayback ? selected.item : this.#state.currentItem,
1347
+ currentItemId: preservePlayback ? selected.item.id : this.#state.currentItemId,
1348
+ shuffleEnabled,
1349
+ repeatMode,
1314
1350
  error: null
1315
1351
  });
1352
+ if (preservePlayback) {
1353
+ if (options.autoplay === true && this.#state.status !== "playing") {
1354
+ return this.#play();
1355
+ }
1356
+ return OK_RESULT;
1357
+ }
1358
+ const version = this.#beginCommand(
1359
+ options.autoplay === true ? "playing" : "paused"
1360
+ );
1316
1361
  return this.#selectQueueIndex(
1317
1362
  version,
1318
1363
  startIndex,
1319
1364
  options.autoplay === true
1320
1365
  );
1321
1366
  }
1367
+ async #activateContext(options) {
1368
+ if (this.#destroyed) {
1369
+ return failed(DESTROYED_ERROR);
1370
+ }
1371
+ if (options.contextId.trim().length === 0) {
1372
+ return failed(INVALID_QUEUE_ERROR);
1373
+ }
1374
+ const suppliedQueue = options.queue ?? (this.#state.activeContext?.id === options.contextId ? this.#state.queue : void 0);
1375
+ if (suppliedQueue === void 0 || !hasUniqueQueueItemIds(suppliedQueue)) {
1376
+ return failed(INVALID_QUEUE_ERROR);
1377
+ }
1378
+ const startIndex = findQueueIndex(
1379
+ suppliedQueue,
1380
+ options.startQueueItemId
1381
+ );
1382
+ if (startIndex === null) {
1383
+ return failed(INVALID_QUEUE_ERROR);
1384
+ }
1385
+ const startItem = suppliedQueue[startIndex];
1386
+ if (startItem === void 0) {
1387
+ return failed(INVALID_QUEUE_ERROR);
1388
+ }
1389
+ let queue;
1390
+ if (options.mode === "manual-history") {
1391
+ const sameManualContext = this.#state.activeContext?.id === options.contextId && this.#state.activeContext.mode === "manual-history";
1392
+ const history = sameManualContext ? [...this.#state.queue] : [];
1393
+ const existingIndex = findQueueIndex(history, startItem.queueItemId);
1394
+ if (existingIndex === null) {
1395
+ history.push(startItem);
1396
+ } else {
1397
+ history[existingIndex] = startItem;
1398
+ }
1399
+ queue = freezeQueue(history);
1400
+ } else {
1401
+ queue = freezeQueue(suppliedQueue);
1402
+ }
1403
+ const previousContext = this.#state.activeContext;
1404
+ const context = Object.freeze({
1405
+ id: options.contextId,
1406
+ mode: options.mode,
1407
+ ...options.label === void 0 && previousContext?.id === options.contextId ? previousContext.label === void 0 ? {} : { label: previousContext.label } : options.label === void 0 ? {} : { label: options.label },
1408
+ queue,
1409
+ currentQueueItemId: options.startQueueItemId
1410
+ });
1411
+ return this.#setQueue(
1412
+ queue,
1413
+ {
1414
+ startQueueItemId: options.startQueueItemId,
1415
+ ...options.autoplay === void 0 ? {} : { autoplay: options.autoplay },
1416
+ ...options.reload === void 0 ? {} : { reload: options.reload }
1417
+ },
1418
+ context
1419
+ );
1420
+ }
1421
+ #appendToManualHistory(contextId, item) {
1422
+ const context = this.#state.activeContext;
1423
+ if (this.#destroyed || context?.id !== contextId || context.mode !== "manual-history" || findQueueIndex(this.#state.queue, item.queueItemId) !== null) {
1424
+ return;
1425
+ }
1426
+ const queue = freezeQueue([...this.#state.queue, item]);
1427
+ this.#playbackOrderQueueItemIds = Object.freeze(
1428
+ queue.map((entry) => entry.queueItemId)
1429
+ );
1430
+ this.#playbackOrderCursor = this.#state.currentQueueItemId === null ? -1 : findQueueIndex(queue, this.#state.currentQueueItemId) ?? -1;
1431
+ this.#setState({ queue });
1432
+ }
1322
1433
  async #selectQueueIndex(version, index, autoplay) {
1323
1434
  const selected = this.#state.queue[index];
1324
1435
  if (selected === void 0) {
@@ -1591,7 +1702,7 @@ var CorePlayerStore = class {
1591
1702
  this.#setState({ muted });
1592
1703
  }
1593
1704
  #setShuffle(enabled) {
1594
- if (this.#destroyed || enabled === this.#state.shuffleEnabled) {
1705
+ if (this.#destroyed || enabled && this.#state.activeContext?.mode === "manual-history" || enabled === this.#state.shuffleEnabled) {
1595
1706
  return;
1596
1707
  }
1597
1708
  const currentQueueItemId = this.#state.currentQueueItemId;
@@ -1616,7 +1727,9 @@ var CorePlayerStore = class {
1616
1727
  if (this.#destroyed) {
1617
1728
  return;
1618
1729
  }
1619
- this.#setState({ repeatMode: mode });
1730
+ this.#setState({
1731
+ repeatMode: this.#state.activeContext?.mode === "manual-history" && mode === "all" ? "off" : mode
1732
+ });
1620
1733
  }
1621
1734
  async #next() {
1622
1735
  if (this.#destroyed) {
@@ -1715,6 +1828,7 @@ var CorePlayerStore = class {
1715
1828
  currentTimeSec: 0,
1716
1829
  durationSec: null,
1717
1830
  queue: Object.freeze([]),
1831
+ activeContext: null,
1718
1832
  canSeek: false,
1719
1833
  needsUserGesture: false,
1720
1834
  error: null
@@ -1884,6 +1998,14 @@ var CorePlayerStore = class {
1884
1998
  );
1885
1999
  return;
1886
2000
  }
2001
+ if (this.#state.activeContext?.mode === "manual-history") {
2002
+ this.#desiredPlayback = "paused";
2003
+ this.#setState({
2004
+ status: "ended",
2005
+ currentTimeSec: readFiniteDuration(this.#media) ?? readFiniteCurrentTime(this.#media)
2006
+ });
2007
+ return;
2008
+ }
1887
2009
  const nextPlaybackIndex = this.#getNextPlaybackIndex(
1888
2010
  currentQueueItemId
1889
2011
  );
@@ -1985,6 +2107,17 @@ function createGestureAwareCommands(commands, gain, activationOptions = {}) {
1985
2107
  }
1986
2108
  return commands.setQueue(queue, commandOptions);
1987
2109
  },
2110
+ activateContext(commandOptions) {
2111
+ reportCommand(activationOptions, "activateContext");
2112
+ if (commandOptions.autoplay === true) {
2113
+ activate(gain, activationOptions);
2114
+ }
2115
+ return commands.activateContext(commandOptions);
2116
+ },
2117
+ appendToManualHistory(contextId, item) {
2118
+ reportCommand(activationOptions, "appendToManualHistory");
2119
+ commands.appendToManualHistory(contextId, item);
2120
+ },
1988
2121
  play() {
1989
2122
  reportCommand(activationOptions, "play");
1990
2123
  activate(gain, activationOptions);
@@ -2387,7 +2520,55 @@ function usePlayer() {
2387
2520
  mediaSessionActionsEnabled: context.mediaSessionActionsEnabled
2388
2521
  };
2389
2522
  }
2523
+ function deriveBoundPlayerViewState(playerState, contextId, queueItem) {
2524
+ const isActive = playerState.activeContext?.id === contextId && playerState.currentQueueItemId === queueItem.queueItemId;
2525
+ return Object.freeze({
2526
+ queueItemId: queueItem.queueItemId,
2527
+ item: isActive ? playerState.currentItem ?? queueItem.item : queueItem.item,
2528
+ isActive,
2529
+ status: isActive ? playerState.status : "paused",
2530
+ currentTimeSec: isActive ? playerState.currentTimeSec : 0,
2531
+ durationSec: isActive ? playerState.durationSec : queueItem.item.durationHintSec ?? null,
2532
+ canSeek: isActive && playerState.canSeek,
2533
+ isPlaying: isActive && playerState.status === "playing"
2534
+ });
2535
+ }
2536
+ function useBoundPlayer({
2537
+ context,
2538
+ queueItem
2539
+ }) {
2540
+ const player = usePlayer();
2541
+ const state = useMemo(
2542
+ () => deriveBoundPlayerViewState(player.state, context.id, queueItem),
2543
+ [context.id, player.state, queueItem]
2544
+ );
2545
+ const commands = useMemo(() => {
2546
+ const play = () => player.commands.activateContext({
2547
+ contextId: context.id,
2548
+ mode: context.mode,
2549
+ ...context.label === void 0 ? {} : { label: context.label },
2550
+ queue: context.mode === "manual-history" ? [queueItem] : context.queue,
2551
+ startQueueItemId: queueItem.queueItemId,
2552
+ autoplay: true
2553
+ });
2554
+ return Object.freeze({
2555
+ play,
2556
+ togglePlayback() {
2557
+ if (player.state.activeContext?.id === context.id && player.state.currentQueueItemId === queueItem.queueItemId) {
2558
+ return player.commands.togglePlayback();
2559
+ }
2560
+ return play();
2561
+ },
2562
+ seekTo(seconds) {
2563
+ if (player.state.activeContext?.id === context.id && player.state.currentQueueItemId === queueItem.queueItemId && player.state.canSeek) {
2564
+ player.commands.seekTo(seconds);
2565
+ }
2566
+ }
2567
+ });
2568
+ }, [context, player.commands, player.state, queueItem]);
2569
+ return { state, commands };
2570
+ }
2390
2571
 
2391
- export { MiniPlayerHost, PlayerProvider, usePlayer };
2572
+ export { MiniPlayerHost, PlayerProvider, deriveBoundPlayerViewState, useBoundPlayer, usePlayer };
2392
2573
  //# sourceMappingURL=index.js.map
2393
2574
  //# sourceMappingURL=index.js.map