Docs UI (#48)
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte-podcast': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve example components
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'svelte-podcast': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
improve progress component style overrides
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "svelte-podcast",
|
"name": "svelte-podcast",
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Ollie Taylor",
|
"author": "Ollie Taylor (https://olliejt.com)",
|
||||||
"homepage": "https://github.com/OllieJT/svelte-podcast/blob/main/README.md",
|
"homepage": "https://github.com/OllieJT/svelte-podcast/blob/main/README.md",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/OllieJT/svelte-podcast/issues"
|
"url": "https://github.com/OllieJT/svelte-podcast/issues"
|
||||||
|
|||||||
@@ -1,444 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { Pause, Play } from '@inqling/svelte-icons/heroicon-20-solid';
|
|
||||||
import { AudioPlayer, user_preferences } from 'svelte-podcast';
|
|
||||||
import { A11yIcon, Skip, Spinner, Timestamp } from './utility';
|
|
||||||
|
|
||||||
/** @type {string | undefined} */
|
|
||||||
export let src;
|
|
||||||
|
|
||||||
/** @type {import('svelte-podcast/audio').AudioMetadata} */
|
|
||||||
export let metadata = {};
|
|
||||||
|
|
||||||
export let hide_duration = false;
|
|
||||||
export let hide_current_time = false;
|
|
||||||
export let hide_playback_rate = false;
|
|
||||||
export let hide_skip_back = false;
|
|
||||||
export let hide_skip_forward = false;
|
|
||||||
|
|
||||||
export let skip_back = 30;
|
|
||||||
export let skip_forward = 10;
|
|
||||||
|
|
||||||
export let playback_rate_values = [1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:head>
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--svpod--font: ui-sans-serif, system-ui, -apple-system,
|
|
||||||
BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
|
||||||
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
|
||||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
|
||||||
|
|
||||||
--svpod--surface--darker: rgb(0, 0, 0);
|
|
||||||
--svpod--surface--base: rgb(40, 40, 40);
|
|
||||||
--svpod--surface--lighter: rgb(60, 60, 60);
|
|
||||||
|
|
||||||
--svpod--content--darker: rgb(150, 150, 150);
|
|
||||||
--svpod--content--base: rgb(200, 200, 200);
|
|
||||||
--svpod--content--lighter: rgb(255, 255, 255);
|
|
||||||
|
|
||||||
--svpod--accent--darker: rgb(75, 15, 0);
|
|
||||||
--svpod--accent--base: rgb(180, 40, 0);
|
|
||||||
--svpod--accent--lighter: rgb(255, 55, 25);
|
|
||||||
|
|
||||||
--bg: var(--svpod--surface--darker);
|
|
||||||
--fg: var(--svpod--content--darker);
|
|
||||||
|
|
||||||
--svpod--radius--rounded: 9999px;
|
|
||||||
|
|
||||||
/* element : timeline */
|
|
||||||
|
|
||||||
--svpod--timeline-track--shape--height: 20px;
|
|
||||||
--svpod--timeline-track--shape--radius: 0;
|
|
||||||
--svpod--timeline-track--shape--border: 0;
|
|
||||||
|
|
||||||
--svpod--timeline-thumb--shape--width: 8px;
|
|
||||||
--svpod--timeline-thumb--shape--height: 32px;
|
|
||||||
--svpod--timeline-thumb--shape--radius: 6px;
|
|
||||||
--svpod--timeline-thumb--shape--border: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--reset {
|
|
||||||
text-transform: none;
|
|
||||||
font-style: normal;
|
|
||||||
text-indent: 0;
|
|
||||||
text-shadow: none;
|
|
||||||
text-align: left;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--a11y-hidden {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
white-space: nowrap;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--button,
|
|
||||||
.svpod--icon-button {
|
|
||||||
--fg: var(--svpod--content--base);
|
|
||||||
--bg: var(--svpod--surface--base);
|
|
||||||
position: relative;
|
|
||||||
line-height: 1em;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 8px;
|
|
||||||
font-size: 16px;
|
|
||||||
border: 0px solid transparent;
|
|
||||||
border-radius: var(--svpod--radius--rounded);
|
|
||||||
background-color: var(--bg);
|
|
||||||
color: var(--fg);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.svpod--button:hover,
|
|
||||||
.svpod--icon-button:hover {
|
|
||||||
--fg: var(--svpod--content--lighter);
|
|
||||||
--bg: var(--svpod--surface--lighter);
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--button {
|
|
||||||
padding: 4px calc(1em);
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--icon-button {
|
|
||||||
padding: 8px;
|
|
||||||
min-width: 48px;
|
|
||||||
min-height: 48px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<AudioPlayer {src} {metadata} let:Player let:action let:attributes>
|
|
||||||
<div
|
|
||||||
{...$$restProps}
|
|
||||||
class="svpod--container svpod--reset"
|
|
||||||
data-loaded={attributes.is_loaded ? 'true' : 'false'}
|
|
||||||
>
|
|
||||||
{#if !hide_skip_back}
|
|
||||||
<button
|
|
||||||
on:click={() => action.skip_back(skip_back)}
|
|
||||||
class="svpod--reset svpod--toggle-pause"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<Skip value={skip_back} type="backward" />
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- toggle play -->
|
|
||||||
{#if attributes.is_loaded}
|
|
||||||
<button
|
|
||||||
on:click={() => action.toggle()}
|
|
||||||
class="svpod--reset svpod--toggle-pause"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<A11yIcon
|
|
||||||
icon={attributes.is_paused ? Play : Pause}
|
|
||||||
label={attributes.is_paused ? 'Play' : 'Pause'}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<div class="svpod--reset svpod--toggle-pause">
|
|
||||||
<A11yIcon icon={Spinner} label="Waiting for audio..." />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if !hide_skip_forward}
|
|
||||||
<button
|
|
||||||
on:click={() => action.skip_forward(skip_forward)}
|
|
||||||
class="svpod--reset svpod--toggle-pause"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<Skip value={skip_forward} type="forward" />
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if !hide_current_time}
|
|
||||||
<div class="svpod--timestamp">
|
|
||||||
<Timestamp
|
|
||||||
value={attributes.current_time}
|
|
||||||
force_hours={attributes.duration >= 3600}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="svpod--timeline">
|
|
||||||
<Player.AudioProgress />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if !hide_duration}
|
|
||||||
<div class="svpod--timestamp">
|
|
||||||
<Timestamp value={attributes.duration} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if !hide_playback_rate}
|
|
||||||
<select
|
|
||||||
class="svpod--playback-rate"
|
|
||||||
value={$user_preferences.playback_rate}
|
|
||||||
on:change={(e) => {
|
|
||||||
const value = parseFloat(e.currentTarget.value);
|
|
||||||
action.set_playback_rate(value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#each playback_rate_values as value}
|
|
||||||
<option {value}>
|
|
||||||
{#if Number.isInteger(value)}
|
|
||||||
{value}.0
|
|
||||||
{:else}
|
|
||||||
{value}
|
|
||||||
{/if}
|
|
||||||
</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</AudioPlayer>
|
|
||||||
|
|
||||||
<style lang="postcss">
|
|
||||||
.svpod--container {
|
|
||||||
--fg: var(--svpod--content--base);
|
|
||||||
--bg: var(--svpod--surface--darker);
|
|
||||||
|
|
||||||
--padding: 2px;
|
|
||||||
--radius: 0.5em;
|
|
||||||
--inner-radius: calc(var(--radius) - var(--padding));
|
|
||||||
|
|
||||||
--svpod--timeline-track--shape--height: 3em;
|
|
||||||
--svpod--timeline-track--shape--radius: var(--inner-radius);
|
|
||||||
--svpod--timeline-track--shape--border: 2px;
|
|
||||||
|
|
||||||
--svpod--timeline-thumb--shape--height: var(
|
|
||||||
--svpod--timeline-track--shape--height
|
|
||||||
);
|
|
||||||
--svpod--timeline-thumb--shape--width: 3px;
|
|
||||||
--svpod--timeline-thumb--shape--radius: 1px;
|
|
||||||
--svpod--timeline-thumb--shape--border: 0px;
|
|
||||||
|
|
||||||
background-color: var(--bg);
|
|
||||||
color: var(--fg);
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: stretch;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1em;
|
|
||||||
min-width: 320px;
|
|
||||||
max-width: 100%;
|
|
||||||
border-radius: var(--radius);
|
|
||||||
font-weight: 600;
|
|
||||||
padding: var(--padding);
|
|
||||||
gap: var(--padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
div.svpod--timeline {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: stretch;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
font-size: 1em;
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--toggle-pause {
|
|
||||||
align-items: center;
|
|
||||||
border: none;
|
|
||||||
display: flex;
|
|
||||||
font-size: 1em;
|
|
||||||
height: 3em;
|
|
||||||
justify-content: center;
|
|
||||||
width: 3em;
|
|
||||||
border-radius: var(--inner-radius);
|
|
||||||
}
|
|
||||||
button.svpod--toggle-pause {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.svpod--toggle-pause :global(svg) {
|
|
||||||
width: 1.5em;
|
|
||||||
height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.svpod--timestamp {
|
|
||||||
background-color: var(--bg);
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 4px;
|
|
||||||
font-size: 1em;
|
|
||||||
line-height: 1em;
|
|
||||||
pointer-events: none;
|
|
||||||
border-radius: var(--inner-radius);
|
|
||||||
width: max-content;
|
|
||||||
flex-grow: 0;
|
|
||||||
text-align: center;
|
|
||||||
padding: 0 0.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
select.svpod--playback-rate {
|
|
||||||
background-color: var(--bg);
|
|
||||||
appearance: none;
|
|
||||||
padding: 0 0.75em;
|
|
||||||
color: var(--fg);
|
|
||||||
overflow: hidden;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
font-size: 0.8em;
|
|
||||||
line-height: 1em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: center;
|
|
||||||
min-width: 48px;
|
|
||||||
outline-color: var(--svpod--accent--lighter);
|
|
||||||
cursor: pointer;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: var(--inner-radius);
|
|
||||||
}
|
|
||||||
select.svpod--playback-rate,
|
|
||||||
select.svpod--playback-rate:hover,
|
|
||||||
select.svpod--playback-rate:focus {
|
|
||||||
border: none;
|
|
||||||
shadow: none;
|
|
||||||
}
|
|
||||||
select.svpod--playback-rate:focus {
|
|
||||||
--fg: var(--svpod--accent--lighter);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.svpod--toggle-pause,
|
|
||||||
select.svpod--playback-rate {
|
|
||||||
background-color: var(--bg);
|
|
||||||
color: var(--fg);
|
|
||||||
}
|
|
||||||
button.svpod--toggle-pause:hover,
|
|
||||||
select.svpod--playback-rate:hover {
|
|
||||||
--bg: var(--svpod--surface--base);
|
|
||||||
--fg: var(--svpod--content--lighter);
|
|
||||||
background-color: var(--bg);
|
|
||||||
color: var(--fg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.svpod--timeline {
|
|
||||||
:global(input[type='range']) {
|
|
||||||
--track--shape--height: calc(
|
|
||||||
var(--svpod--timeline-track--shape--height)
|
|
||||||
);
|
|
||||||
--thumb-border-offset: calc(
|
|
||||||
var(--svpod--timeline-thumb--shape--border) * 2
|
|
||||||
);
|
|
||||||
--thumb--shape--height: calc(
|
|
||||||
var(--svpod--timeline-thumb--shape--height) -
|
|
||||||
var(--thumb-border-offset)
|
|
||||||
);
|
|
||||||
|
|
||||||
--svpod--timeline-track--bg: var(--svpod--surface--base);
|
|
||||||
--svpod--timeline-track--border: var(--bg);
|
|
||||||
|
|
||||||
--svpod--timeline-thumb--bg: var(--svpod--content--base);
|
|
||||||
--svpod--timeline-thumb--border: var(--bg);
|
|
||||||
|
|
||||||
font-size: 1em;
|
|
||||||
|
|
||||||
--borders: calc(var(--svpod--timeline-thumb--shape--border) * 2);
|
|
||||||
--no-shadow: 0px 0px 0px transparent;
|
|
||||||
|
|
||||||
height: calc(var(--thumb--shape--height) + var(--borders));
|
|
||||||
appearance: none;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
:global(input[type='range']:hover) {
|
|
||||||
--svpod--timeline-track--bg: var(--svpod--accent--darker);
|
|
||||||
--svpod--timeline-track--border: var(--svpod--accent--base);
|
|
||||||
--svpod--timeline-thumb--bg: var(--svpod--accent--lighter);
|
|
||||||
}
|
|
||||||
:global(input[type='range']:focus) {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-webkit-slider-runnable-track) {
|
|
||||||
width: 100%;
|
|
||||||
height: var(--track--shape--height);
|
|
||||||
cursor: pointer;
|
|
||||||
animate: 0.2s;
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
background: var(--svpod--timeline-track--bg);
|
|
||||||
border-radius: var(--svpod--timeline-track--shape--radius);
|
|
||||||
border: var(--svpod--timeline-track--shape--border) solid
|
|
||||||
var(--svpod--timeline-track--border);
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-webkit-slider-thumb) {
|
|
||||||
--offset: calc(var(--svpod--timeline-track--shape--border) * -1);
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
border: var(--svpod--timeline-thumb--shape--border) solid
|
|
||||||
var(--svpod--timeline-thumb--border);
|
|
||||||
height: var(--thumb--shape--height);
|
|
||||||
width: var(--svpod--timeline-thumb--shape--width);
|
|
||||||
border-radius: var(--svpod--timeline-thumb--shape--radius);
|
|
||||||
background: var(--svpod--timeline-thumb--bg);
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
margin-top: var(--offset);
|
|
||||||
}
|
|
||||||
:global(input[type='range']:focus::-webkit-slider-runnable-track) {
|
|
||||||
background: var(--svpod--timeline-track--bg);
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-moz-range-track) {
|
|
||||||
width: 100%;
|
|
||||||
height: var(--track--shape--height);
|
|
||||||
cursor: pointer;
|
|
||||||
animate: 0.2s;
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
background: var(--svpod--timeline-track--bg);
|
|
||||||
border-radius: var(--svpod--timeline-track--shape--radius);
|
|
||||||
border: var(--svpod--timeline-track--shape--border) solid
|
|
||||||
var(--svpod--timeline-track--border);
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-moz-range-thumb) {
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
border: var(--svpod--timeline-thumb--shape--border) solid
|
|
||||||
var(--svpod--timeline-thumb--border);
|
|
||||||
height: var(--thumb--shape--height);
|
|
||||||
width: var(--svpod--timeline-thumb--shape--width);
|
|
||||||
border-radius: var(--svpod--timeline-thumb--shape--radius);
|
|
||||||
background: var(--svpod--timeline-thumb--bg);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-ms-track) {
|
|
||||||
width: 100%;
|
|
||||||
height: var(--track--shape--height);
|
|
||||||
cursor: pointer;
|
|
||||||
animate: 0.2s;
|
|
||||||
background: transparent;
|
|
||||||
border-color: transparent;
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-ms-fill-lower),
|
|
||||||
:global(input[type='range']::-ms-fill-upper) {
|
|
||||||
background: var(--svpod--timeline-track--bg);
|
|
||||||
border: var(--svpod--timeline-track--shape--border) solid
|
|
||||||
var(--svpod--timeline-track--border);
|
|
||||||
border-radius: calc(var(--svpod--timeline-track--shape--radius) * 2);
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
}
|
|
||||||
:global(input[type='range']::-ms-thumb) {
|
|
||||||
margin-top: 1px;
|
|
||||||
box-shadow: var(--no-shadow);
|
|
||||||
border: var(--svpod--timeline-thumb--shape--border) solid
|
|
||||||
var(--svpod--timeline-thumb--border);
|
|
||||||
height: var(--thumb--shape--height);
|
|
||||||
width: var(--svpod--timeline-thumb--shape--width);
|
|
||||||
border-radius: var(--svpod--timeline-thumb--shape--radius);
|
|
||||||
background: var(--svpod--timeline-thumb--bg);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
:global(input[type='range']:focus::-ms-fill-lower),
|
|
||||||
:global(input[type='range']:focus::-ms-fill-upper) {
|
|
||||||
background: var(--svpod--timeline-track--bg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<script>
|
|
||||||
/** @type {import('@inqling/svelte-icons').SvelteIcon} */
|
|
||||||
export let icon;
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
export let label;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:component this={icon} />
|
|
||||||
<span class="svpod--a11y-hidden">{label}</span>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export { default as A11yIcon } from './a11y-icon.svelte';
|
|
||||||
export { default as Skip } from './skip.svelte';
|
|
||||||
export { default as Spinner } from './spinner.svelte';
|
|
||||||
export { default as Timestamp } from './timestamp.svelte';
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
<script>
|
|
||||||
/** @type {number} [size = 24] */
|
|
||||||
export let size = 24;
|
|
||||||
|
|
||||||
/** @type {number} */
|
|
||||||
export let value;
|
|
||||||
|
|
||||||
/** @type {'forward' | 'backward'} */
|
|
||||||
export let type;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="svpod--skip-container" style="font-size:{size}px">
|
|
||||||
<span class="svpod--skip-label">
|
|
||||||
<span class="svpod--a11y-hidden">skip {type}</span>
|
|
||||||
{value}
|
|
||||||
<span class="svpod--a11y-hidden">seconds</span>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="svpod--skip-mask"
|
|
||||||
class:svpod--skip-mask--right={type === 'backward'}
|
|
||||||
class:svpod--skip-mask--left={type === 'backward'}
|
|
||||||
/>
|
|
||||||
<div class="svpod--skip-icon">
|
|
||||||
{#if type === 'forward'}
|
|
||||||
<!-- forward -->
|
|
||||||
<svg
|
|
||||||
width={size}
|
|
||||||
height={size}
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
style="font-size:{size}px"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M15.5922 0.913446C14.1363 0.310389 12.5759 -1.8792e-08 11 0L11 2C12.3132 2 13.6136 2.25866 14.8268 2.7612C16.0401 3.26375 17.1425 4.00035 18.0711 4.92893C18.9997 5.85752 19.7362 6.95991 20.2388 8.17317C20.6133 9.07731 20.8524 10.0298 20.9499 11H22.9583C22.8551 9.76677 22.5617 8.55484 22.0866 7.4078C21.4835 5.95189 20.5996 4.62902 19.4853 3.51472C18.371 2.40042 17.0481 1.5165 15.5922 0.913446Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M22.9583 13C22.9338 13.2923 22.8987 13.5835 22.853 13.8728L20.9082 13.3517C20.9242 13.2348 20.9381 13.1175 20.9499 13H22.9583Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M20.4408 15.297L22.3771 15.8159C22.2894 16.0775 22.1925 16.3365 22.0866 16.5922C22.078 16.6128 22.0694 16.6334 22.0608 16.6539L20.3123 15.6444C20.3573 15.5293 20.4002 15.4135 20.4408 15.297Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M19.3994 17.4268L21.1333 18.4278C20.9675 18.6892 20.7916 18.944 20.6061 19.1919L19.1744 17.7602C19.2516 17.6505 19.3267 17.5394 19.3994 17.4268Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M17.8609 19.2751L19.2757 20.6899C19.0399 20.9144 18.7954 21.1289 18.5429 21.333L17.5281 19.5752C17.6412 19.4778 17.7521 19.3777 17.8609 19.2751Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M15.8834 20.7265L16.8835 22.4587C16.5838 22.6273 16.2766 22.7831 15.9628 22.9257L15.4366 20.9619C15.5876 20.8872 15.7366 20.8087 15.8834 20.7265Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M13.5553 21.668L14.0729 23.5999C13.7189 23.6937 13.3609 23.7712 13 23.8322V21.798C13.1862 21.7599 13.3714 21.7166 13.5553 21.668Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{:else}
|
|
||||||
<!-- back -->
|
|
||||||
<svg
|
|
||||||
width={size}
|
|
||||||
height={size}
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
style="font-size:{size}px"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M11.0003 21.9499V23.9583C10.6215 23.9266 10.2447 23.877 9.87115 23.8096L10.391 21.8697C10.5931 21.9026 10.7963 21.9294 11.0003 21.9499Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M7.8915 21.1169C7.98478 21.159 8.07876 21.1996 8.17342 21.2388C8.26813 21.278 8.36337 21.3158 8.45911 21.352L7.9393 23.292C7.7608 23.2278 7.58367 23.1593 7.40805 23.0866C7.23249 23.0138 7.05886 22.937 6.8873 22.8562L7.8915 21.1169Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M5.67173 19.7427C5.8305 19.8725 5.99315 19.9973 6.15943 20.1169L5.15524 21.8563C4.84345 21.6397 4.54188 21.4084 4.25159 21.1629L5.67173 19.7427Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3.88341 17.841C4.00303 18.0072 4.12778 18.1698 4.25752 18.3285L2.83737 19.7487C2.59192 19.4584 2.36059 19.1569 2.14409 18.8452L3.88341 17.841Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M2.64825 15.5412C2.68449 15.6369 2.72223 15.7321 2.76146 15.8268C2.80069 15.9215 2.84134 16.0156 2.88341 16.1089L1.14409 17.1131C1.06327 16.9415 0.986441 16.7678 0.913699 16.5922C0.840963 16.4166 0.772485 16.2395 0.708295 16.061L2.64825 15.5412Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M2.05038 13C2.07088 13.204 2.09764 13.4072 2.1306 13.6093L0.19065 14.1291C0.123306 13.7556 0.0736704 13.3788 0.0419922 13H2.05038Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M2.05038 11C2.14788 10.0298 2.38695 9.07731 2.76146 8.17317C3.26401 6.95991 4.0006 5.85752 4.92919 4.92893C5.85777 4.00035 6.96016 3.26375 8.17342 2.7612C9.38667 2.25866 10.687 2 12.0003 2V0C10.4244 1.8792e-08 8.86396 0.310389 7.40805 0.913446C5.95215 1.5165 4.62928 2.40042 3.51497 3.51472C2.40067 4.62902 1.51676 5.95189 0.913699 7.4078C0.438578 8.55484 0.145121 9.76677 0.0419922 11H2.05038Z"
|
|
||||||
fill="currentColor"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
div.svpod--skip-container {
|
|
||||||
display: inline-flex;
|
|
||||||
position: relative;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 1.5em;
|
|
||||||
height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.svpod--skip-icon,
|
|
||||||
span.svpod--skip-mask {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.svpod--skip-mask {
|
|
||||||
z-index: 1;
|
|
||||||
background: linear-gradient(0deg, var(--bg), transparent);
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.svpod--skip-icon {
|
|
||||||
z-index: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: var(--svpod--content--base);
|
|
||||||
}
|
|
||||||
|
|
||||||
span.svpod--skip-label {
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
font-size: 0.5em;
|
|
||||||
line-height: 1em;
|
|
||||||
color: var(--svpod--content--lighter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes Spin {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { seconds_to_timestamp } from 'svelte-podcast/utility';
|
|
||||||
|
|
||||||
/** @type {number} */
|
|
||||||
export let value;
|
|
||||||
|
|
||||||
/** @type {boolean} */
|
|
||||||
export let force_hours = false;
|
|
||||||
|
|
||||||
$: timestamp = seconds_to_timestamp(value, force_hours);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<span style="width:{timestamp.length}ch">{timestamp}</span>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
span {
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
font-size: 0.8em;
|
|
||||||
display: block;
|
|
||||||
width: 8ch;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export { default as Pause } from '@inqling/svelte-icons/heroicon-20-solid/pause.svelte';
|
||||||
|
export { default as Play } from '@inqling/svelte-icons/heroicon-20-solid/play.svelte';
|
||||||
|
export { default as SkipBack } from './skip-backward.svelte';
|
||||||
|
export { default as SkipForward } from './skip-forward.svelte';
|
||||||
|
export { default as LoadingSpinner } from './spinner.svelte';
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<script>
|
||||||
|
/** @type {number} [size = 24] */
|
||||||
|
export let size = 24;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="font-size:{size}px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M11.0003 21.9499V23.9583C10.6215 23.9266 10.2447 23.877 9.87115 23.8096L10.391 21.8697C10.5931 21.9026 10.7963 21.9294 11.0003 21.9499Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M7.8915 21.1169C7.98478 21.159 8.07876 21.1996 8.17342 21.2388C8.26813 21.278 8.36337 21.3158 8.45911 21.352L7.9393 23.292C7.7608 23.2278 7.58367 23.1593 7.40805 23.0866C7.23249 23.0138 7.05886 22.937 6.8873 22.8562L7.8915 21.1169Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.67173 19.7427C5.8305 19.8725 5.99315 19.9973 6.15943 20.1169L5.15524 21.8563C4.84345 21.6397 4.54188 21.4084 4.25159 21.1629L5.67173 19.7427Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.88341 17.841C4.00303 18.0072 4.12778 18.1698 4.25752 18.3285L2.83737 19.7487C2.59192 19.4584 2.36059 19.1569 2.14409 18.8452L3.88341 17.841Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M2.64825 15.5412C2.68449 15.6369 2.72223 15.7321 2.76146 15.8268C2.80069 15.9215 2.84134 16.0156 2.88341 16.1089L1.14409 17.1131C1.06327 16.9415 0.986441 16.7678 0.913699 16.5922C0.840963 16.4166 0.772485 16.2395 0.708295 16.061L2.64825 15.5412Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M2.05038 13C2.07088 13.204 2.09764 13.4072 2.1306 13.6093L0.19065 14.1291C0.123306 13.7556 0.0736704 13.3788 0.0419922 13H2.05038Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M2.05038 11C2.14788 10.0298 2.38695 9.07731 2.76146 8.17317C3.26401 6.95991 4.0006 5.85752 4.92919 4.92893C5.85777 4.00035 6.96016 3.26375 8.17342 2.7612C9.38667 2.25866 10.687 2 12.0003 2V0C10.4244 1.8792e-08 8.86396 0.310389 7.40805 0.913446C5.95215 1.5165 4.62928 2.40042 3.51497 3.51472C2.40067 4.62902 1.51676 5.95189 0.913699 7.4078C0.438578 8.55484 0.145121 9.76677 0.0419922 11H2.05038Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<script>
|
||||||
|
/** @type {number} [size = 24] */
|
||||||
|
export let size = 24;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="font-size:{size}px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M15.5922 0.913446C14.1363 0.310389 12.5759 -1.8792e-08 11 0L11 2C12.3132 2 13.6136 2.25866 14.8268 2.7612C16.0401 3.26375 17.1425 4.00035 18.0711 4.92893C18.9997 5.85752 19.7362 6.95991 20.2388 8.17317C20.6133 9.07731 20.8524 10.0298 20.9499 11H22.9583C22.8551 9.76677 22.5617 8.55484 22.0866 7.4078C21.4835 5.95189 20.5996 4.62902 19.4853 3.51472C18.371 2.40042 17.0481 1.5165 15.5922 0.913446Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M22.9583 13C22.9338 13.2923 22.8987 13.5835 22.853 13.8728L20.9082 13.3517C20.9242 13.2348 20.9381 13.1175 20.9499 13H22.9583Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M20.4408 15.297L22.3771 15.8159C22.2894 16.0775 22.1925 16.3365 22.0866 16.5922C22.078 16.6128 22.0694 16.6334 22.0608 16.6539L20.3123 15.6444C20.3573 15.5293 20.4002 15.4135 20.4408 15.297Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M19.3994 17.4268L21.1333 18.4278C20.9675 18.6892 20.7916 18.944 20.6061 19.1919L19.1744 17.7602C19.2516 17.6505 19.3267 17.5394 19.3994 17.4268Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M17.8609 19.2751L19.2757 20.6899C19.0399 20.9144 18.7954 21.1289 18.5429 21.333L17.5281 19.5752C17.6412 19.4778 17.7521 19.3777 17.8609 19.2751Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M15.8834 20.7265L16.8835 22.4587C16.5838 22.6273 16.2766 22.7831 15.9628 22.9257L15.4366 20.9619C15.5876 20.8872 15.7366 20.8087 15.8834 20.7265Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M13.5553 21.668L14.0729 23.5999C13.7189 23.6937 13.3609 23.7712 13 23.8322V21.798C13.1862 21.7599 13.3714 21.7166 13.5553 21.668Z"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
<script>
|
||||||
|
import {
|
||||||
|
LoadingSpinner,
|
||||||
|
Pause,
|
||||||
|
Play,
|
||||||
|
SkipBack,
|
||||||
|
SkipForward,
|
||||||
|
} from '$src/components/icon';
|
||||||
|
import { AudioPlayer, user_preferences } from 'svelte-podcast';
|
||||||
|
|
||||||
|
/** @type {string | undefined} */
|
||||||
|
export let src;
|
||||||
|
export let skip_back = 30;
|
||||||
|
export let skip_forward = 10;
|
||||||
|
|
||||||
|
/** @type {import('svelte-podcast/audio').AudioMetadata} */
|
||||||
|
export let metadata = {};
|
||||||
|
|
||||||
|
export let playback_rate_values = [1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--svpod-surface-darker: rgb(0, 0, 0);
|
||||||
|
--svpod-surface-base: rgb(40, 40, 40);
|
||||||
|
--svpod-surface-lighter: rgb(60, 60, 60);
|
||||||
|
|
||||||
|
--svpod-content-darker: rgb(150, 150, 150);
|
||||||
|
--svpod-content-base: rgb(200, 200, 200);
|
||||||
|
--svpod-content-lighter: rgb(255, 255, 255);
|
||||||
|
|
||||||
|
--svpod-accent-darker: rgb(75, 15, 0);
|
||||||
|
--svpod-accent-base: rgb(180, 40, 0);
|
||||||
|
--svpod-accent-lighter: rgb(255, 55, 25);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<AudioPlayer {src} {metadata} let:Player let:action let:attributes>
|
||||||
|
<div
|
||||||
|
class="svpod-container {$$restProps.class}"
|
||||||
|
data-loaded={attributes.is_loaded ? 'true' : 'false'}
|
||||||
|
>
|
||||||
|
<!-- Player Action: Skip back -->
|
||||||
|
<button
|
||||||
|
on:click={() => action.skip_back(skip_back)}
|
||||||
|
class="svpod-skip"
|
||||||
|
type="button"
|
||||||
|
aria-label="Skip back {skip_back} seconds"
|
||||||
|
>
|
||||||
|
<div class="svpod-skip-label">
|
||||||
|
<span>
|
||||||
|
{skip_back}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="svpod-skip-icon">
|
||||||
|
<SkipBack />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Player Action: Toggle play / pause -->
|
||||||
|
{#if attributes.is_loaded}
|
||||||
|
<button
|
||||||
|
on:click={() => action.toggle()}
|
||||||
|
class="svpod-toggle"
|
||||||
|
type="button"
|
||||||
|
aria-label={attributes.is_paused ? 'Play' : 'Pause'}
|
||||||
|
>
|
||||||
|
<svelte:component this={attributes.is_paused ? Play : Pause} />
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<div class="svpod-toggle">
|
||||||
|
<LoadingSpinner />
|
||||||
|
<span class="svpod--a11y">Waiting for audio...</span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- Player Action: Skip forward -->
|
||||||
|
<button
|
||||||
|
on:click={() => action.skip_forward(skip_forward)}
|
||||||
|
class="svpod-skip"
|
||||||
|
type="button"
|
||||||
|
aria-label="Skip forward {skip_forward} seconds"
|
||||||
|
>
|
||||||
|
<div class="svpod-skip-label">
|
||||||
|
<span>
|
||||||
|
{skip_forward}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="svpod-skip-icon">
|
||||||
|
<SkipForward />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Player Data: Current timestamp -->
|
||||||
|
<div class="svpod-timestamp" class:active={!attributes.is_paused}>
|
||||||
|
<span style="width:{attributes.timestamp_end.length}ch">
|
||||||
|
{attributes.timestamp_current}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Player Component: Timeline -->
|
||||||
|
<div class="svpod--timeline">
|
||||||
|
<Player.Progress />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Player Data: Total duration timestamp -->
|
||||||
|
<div class="svpod-timestamp">
|
||||||
|
<span style="width:{attributes.timestamp_end.length}ch">
|
||||||
|
{attributes.timestamp_end}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Player Action: Select playback speed -->
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="svpod-playback"
|
||||||
|
value={$user_preferences.playback_rate}
|
||||||
|
on:change={(e) => {
|
||||||
|
const value = parseFloat(e.currentTarget.value);
|
||||||
|
action.set_playback_rate(value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#each playback_rate_values as value}
|
||||||
|
<option {value}>
|
||||||
|
{#if Number.isInteger(value)}
|
||||||
|
{value}.0
|
||||||
|
{:else}
|
||||||
|
{value}
|
||||||
|
{/if}
|
||||||
|
</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</AudioPlayer>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
* {
|
||||||
|
/* css-reset */
|
||||||
|
text-transform: none;
|
||||||
|
font-style: normal;
|
||||||
|
text-indent: 0;
|
||||||
|
text-shadow: none;
|
||||||
|
text-align: left;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.svpod--a11y {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-container {
|
||||||
|
--size: 48px;
|
||||||
|
--column: var(--size);
|
||||||
|
--row: var(--size);
|
||||||
|
--text: calc(var(--size) / 3);
|
||||||
|
|
||||||
|
--padding: 2px;
|
||||||
|
--radius: 12px;
|
||||||
|
--inner-radius: calc(var(--radius) - var(--padding));
|
||||||
|
|
||||||
|
--bg: var(--svpod-surface-darker);
|
||||||
|
--fg: var(--svpod-content-base);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns:
|
||||||
|
var(--column)
|
||||||
|
var(--column)
|
||||||
|
var(--column)
|
||||||
|
max-content
|
||||||
|
auto
|
||||||
|
max-content
|
||||||
|
var(--column);
|
||||||
|
grid-template-rows: var(--column);
|
||||||
|
user-select: none;
|
||||||
|
background-color: var(--bg);
|
||||||
|
|
||||||
|
padding: var(--padding);
|
||||||
|
gap: var(--padding);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
background-color: var(--bg);
|
||||||
|
color: var(--fg);
|
||||||
|
border-radius: var(--inner-radius);
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.8em;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--fg: var(--svpod-content-lighter);
|
||||||
|
--bg: var(--svpod-surface-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 2px solid var(--svpod-accent-lighter);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-skip {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
align-content: stretch;
|
||||||
|
justify-content: stretch;
|
||||||
|
|
||||||
|
.svpod-skip-icon {
|
||||||
|
position: absolute;
|
||||||
|
inset: 4px;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
:global(svg) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-skip-label {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
z-index: 30;
|
||||||
|
background: linear-gradient(0deg, var(--bg), transparent);
|
||||||
|
|
||||||
|
span {
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-toggle {
|
||||||
|
--fg: var(--svpod-content-lighter);
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--fg: var(--svpod-accent-lighter);
|
||||||
|
--bg: var(--svpod-accent-darker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-playback {
|
||||||
|
appearance: none;
|
||||||
|
background-image: none;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
text-align-last: center;
|
||||||
|
padding: 0 0.5em;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod-timestamp {
|
||||||
|
display: grid;
|
||||||
|
place-content: center;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.25em 1em;
|
||||||
|
color: var(--fg);
|
||||||
|
background-color: var(--bg);
|
||||||
|
border-radius: var(--inner-radius);
|
||||||
|
place-self: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
--fg: var(--svpod-accent-lighter);
|
||||||
|
--bg: var(--svpod-accent-darker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.svpod--timeline {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: stretch;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
font-size: 1em;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
--progress-height: var(--size);
|
||||||
|
|
||||||
|
--progress-fg: var(--svpod-content-base);
|
||||||
|
--progress-bg: var(--svpod-surface-base);
|
||||||
|
--progress-border: var(--svpod-surface-base);
|
||||||
|
|
||||||
|
--progress-active-fg: var(--svpod-accent-lighter);
|
||||||
|
--progress-active-bg: var(--svpod-accent-darker);
|
||||||
|
--progress-active-border: var(--svpod-accent-base);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { assets } from '$app/paths';
|
import { assets } from '$app/paths';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { circIn, circOut } from 'svelte/easing';
|
import { circOut } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,12 +77,13 @@
|
|||||||
x: -320,
|
x: -320,
|
||||||
duration: 300,
|
duration: 300,
|
||||||
easing: circOut,
|
easing: circOut,
|
||||||
opacity: 0,
|
opacity: 1,
|
||||||
}}
|
}}
|
||||||
out:fly={{
|
out:fly={{
|
||||||
x: -320,
|
x: -320,
|
||||||
duration: 300,
|
duration: 300,
|
||||||
easing: circIn,
|
easing: circOut,
|
||||||
|
opacity: 1,
|
||||||
}}
|
}}
|
||||||
class={clsx(
|
class={clsx(
|
||||||
'pointer-events-auto flex grow origin-left flex-col gap-y-5 overflow-y-auto bg-white px-6',
|
'pointer-events-auto flex grow origin-left flex-col gap-y-5 overflow-y-auto bg-white px-6',
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<slot
|
<slot
|
||||||
Player={{ AudioProgress }}
|
Player={{ Progress: AudioProgress }}
|
||||||
action={{
|
action={{
|
||||||
set_playback_rate: user_preferences.set_playback_rate,
|
set_playback_rate: user_preferences.set_playback_rate,
|
||||||
set_volume: user_preferences.set_volume,
|
set_volume: user_preferences.set_volume,
|
||||||
|
|||||||
@@ -68,3 +68,146 @@
|
|||||||
readonly
|
readonly
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
/* initial player progress colors */
|
||||||
|
--progress-bg: rgb(0, 0, 0);
|
||||||
|
--progress-fg: rgb(155, 155, 155);
|
||||||
|
--progress-border: rgb(105, 105, 105);
|
||||||
|
--progress-active-bg: rgb(55, 55, 55);
|
||||||
|
--progress-active-fg: rgb(255, 255, 255);
|
||||||
|
--progress-active-border: rgb(155, 155, 155);
|
||||||
|
|
||||||
|
/* initial player progress shape */
|
||||||
|
--progress-radius: 4px;
|
||||||
|
--progress-thumb-width: 2px;
|
||||||
|
--progress-height: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
input[type='range'] {
|
||||||
|
--thumb-border-offset: calc(var(--thumb-border-size) * 2);
|
||||||
|
--thumb-shape-height: calc(
|
||||||
|
var(--progress-height) - var(--thumb-border-offset)
|
||||||
|
);
|
||||||
|
|
||||||
|
--track-bg: var(--progress-bg);
|
||||||
|
--track-border-color: var(--progress-border);
|
||||||
|
--track-border-size: 1px;
|
||||||
|
--track-radius: var(--progress-radius);
|
||||||
|
|
||||||
|
--thumb--bg: var(--progress-fg);
|
||||||
|
--thumb-border-color: var(--progress-border);
|
||||||
|
--thumb-border-size: 0px;
|
||||||
|
--thumb--radius: var(--progress-radius);
|
||||||
|
--thumb-width: var(--progress-thumb-width);
|
||||||
|
|
||||||
|
font-size: 1em;
|
||||||
|
|
||||||
|
--borders: calc(var(--thumb-border-size) * 2);
|
||||||
|
|
||||||
|
height: calc(var(--thumb-shape-height) + var(--borders));
|
||||||
|
appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: transparent;
|
||||||
|
outline: 1px solid transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
--track-bg: var(--progress-active-bg);
|
||||||
|
--track-border-color: var(--progress-active-border);
|
||||||
|
--thumb--bg: var(--progress-active-fg);
|
||||||
|
--thumb-border-color: var(--progress-active-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline-color: var(--progress-active-fg);
|
||||||
|
--track-border-color: var(--progress-active-fg);
|
||||||
|
--thumb--bg: var(--progress-active-fg);
|
||||||
|
--thumb-border-color: var(--progress-active-fg);
|
||||||
|
|
||||||
|
&::-webkit-slider-runnable-track,
|
||||||
|
&::-ms-fill-lower,
|
||||||
|
&::-ms-fill-upper {
|
||||||
|
background: var(--track-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* webkit */
|
||||||
|
input[type='range']::-webkit-slider-runnable-track {
|
||||||
|
width: 100%;
|
||||||
|
height: var(--progress-height);
|
||||||
|
cursor: pointer;
|
||||||
|
animate: 0.2s;
|
||||||
|
box-shadow: none;
|
||||||
|
background: var(--track-bg);
|
||||||
|
border-radius: var(--track-radius);
|
||||||
|
border: var(--track-border-size) solid var(--track-border-color);
|
||||||
|
}
|
||||||
|
input[type='range']::-webkit-slider-thumb {
|
||||||
|
--offset: calc(var(--track-border-size) * -1);
|
||||||
|
box-shadow: none;
|
||||||
|
border: var(--thumb-border-size) solid var(--thumb-border-color);
|
||||||
|
height: var(--thumb-shape-height);
|
||||||
|
width: var(--thumb-width);
|
||||||
|
border-radius: var(--thumb-radius);
|
||||||
|
background: var(--thumb--bg);
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin-top: var(--offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mozilla */
|
||||||
|
input[type='range']::-moz-range-track {
|
||||||
|
width: 100%;
|
||||||
|
height: var(--progress-height);
|
||||||
|
cursor: pointer;
|
||||||
|
animate: 0.2s;
|
||||||
|
box-shadow: none;
|
||||||
|
background: var(--track-bg);
|
||||||
|
border-radius: var(--track-radius);
|
||||||
|
border: var(--track-border-size) solid var(--track-border-color);
|
||||||
|
}
|
||||||
|
input[type='range']::-moz-range-thumb {
|
||||||
|
box-shadow: none;
|
||||||
|
border: var(--thumb-border-size) solid var(--thumb-border-color);
|
||||||
|
height: var(--thumb-shape-height);
|
||||||
|
width: var(--thumb-width);
|
||||||
|
border-radius: var(--thumb-radius);
|
||||||
|
background: var(--thumb--bg);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* internet explorer */
|
||||||
|
input[type='range']::-ms-track {
|
||||||
|
width: 100%;
|
||||||
|
height: var(--progress-height);
|
||||||
|
cursor: pointer;
|
||||||
|
animate: 0.2s;
|
||||||
|
background: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
input[type='range']::-ms-fill-lower,
|
||||||
|
input[type='range']::-ms-fill-upper {
|
||||||
|
background: var(--track-bg);
|
||||||
|
border: var(--track-border-size) solid var(--track-border-color);
|
||||||
|
border-radius: calc(var(--track-radius) * 2);
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
input[type='range']::-ms-thumb {
|
||||||
|
margin-top: 1px;
|
||||||
|
box-shadow: none;
|
||||||
|
border: var(--thumb-border-size) solid var(--thumb-border-color);
|
||||||
|
height: var(--thumb-shape-height);
|
||||||
|
width: var(--thumb-width);
|
||||||
|
border-radius: var(--thumb-radius);
|
||||||
|
background: var(--thumb--bg);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
+75
-39
@@ -1,10 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { afterNavigate } from '$app/navigation';
|
||||||
import Sidebar from '$src/layout/sidebar.svelte';
|
import Sidebar from '$src/layout/sidebar.svelte';
|
||||||
|
import CloseIcon from '@inqling/svelte-icons/heroicon-24-outline/x-mark.svelte';
|
||||||
import GitHubIcon from '@inqling/svelte-icons/simple-icons/github.svelte';
|
import GitHubIcon from '@inqling/svelte-icons/simple-icons/github.svelte';
|
||||||
import NPMIcon from '@inqling/svelte-icons/simple-icons/npm.svelte';
|
import NPMIcon from '@inqling/svelte-icons/simple-icons/npm.svelte';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
import github from 'svelte-highlight/styles/github';
|
import github from 'svelte-highlight/styles/github';
|
||||||
import { circIn, circOut } from 'svelte/easing';
|
import { circOut, cubicInOut, cubicOut } from 'svelte/easing';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade, scale } from 'svelte/transition';
|
||||||
import '../app.postcss';
|
import '../app.postcss';
|
||||||
|
|
||||||
const page_links = Object.freeze([
|
const page_links = Object.freeze([
|
||||||
@@ -22,6 +25,25 @@
|
|||||||
{ label: 'Type Safety', anchor: 'type_safety' },
|
{ label: 'Type Safety', anchor: 'type_safety' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Components',
|
||||||
|
href: '/components',
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
label: 'AudioPlayer',
|
||||||
|
anchor: 'audioplayer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'AudioProgress',
|
||||||
|
anchor: 'audioprogress',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Examples',
|
||||||
|
href: '/examples',
|
||||||
|
sections: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'API',
|
label: 'API',
|
||||||
href: '/api',
|
href: '/api',
|
||||||
@@ -67,11 +89,6 @@
|
|||||||
{ label: 'seconds_to_timestamp', anchor: 'seconds_to_timestamp' },
|
{ label: 'seconds_to_timestamp', anchor: 'seconds_to_timestamp' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Examples',
|
|
||||||
href: '/examples',
|
|
||||||
sections: [],
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const resource_links = Object.freeze([
|
const resource_links = Object.freeze([
|
||||||
@@ -104,6 +121,38 @@
|
|||||||
|
|
||||||
const open_menu = () => (is_menu_open = true);
|
const open_menu = () => (is_menu_open = true);
|
||||||
const close_menu = () => (is_menu_open = false);
|
const close_menu = () => (is_menu_open = false);
|
||||||
|
const toggle_menu = () => (is_menu_open = !is_menu_open);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {KeyboardEvent} event - The keyboard event object.
|
||||||
|
*/
|
||||||
|
const handle_keydown = (event) => {
|
||||||
|
// on esc close menu
|
||||||
|
if (event.key === 'Escape' || event.key === 'Esc') {
|
||||||
|
close_menu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// on command + / open menu
|
||||||
|
if (event.metaKey && event.key === '/') {
|
||||||
|
toggle_menu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// on command + return open menu
|
||||||
|
if (event.metaKey && event.key === 'Enter') {
|
||||||
|
toggle_menu();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
// close menu on esc
|
||||||
|
window.addEventListener('keydown', handle_keydown);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keydown', handle_keydown);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterNavigate(close_menu);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -119,46 +168,33 @@
|
|||||||
{#if is_menu_open}
|
{#if is_menu_open}
|
||||||
<div
|
<div
|
||||||
in:fade={{
|
in:fade={{
|
||||||
duration: 300,
|
duration: 400,
|
||||||
easing: circOut,
|
easing: cubicOut,
|
||||||
}}
|
}}
|
||||||
out:fade={{
|
out:fade={{
|
||||||
duration: 300,
|
duration: 120,
|
||||||
easing: circIn,
|
easing: cubicInOut,
|
||||||
}}
|
}}
|
||||||
class="fixed inset-0 bg-mono-900/80"
|
class="fixed inset-0 bg-mono-900/80"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="fixed inset-0 flex">
|
{#if is_menu_open}
|
||||||
{#if is_menu_open}
|
<button
|
||||||
|
type="button"
|
||||||
|
on:click={close_menu}
|
||||||
|
class="pointer-events-auto fixed inset-0 flex"
|
||||||
|
>
|
||||||
<div class="relative mr-16 flex w-full max-w-xs flex-1">
|
<div class="relative mr-16 flex w-full max-w-xs flex-1">
|
||||||
<div
|
<div class="absolute left-full top-0 flex w-16 justify-center pt-5">
|
||||||
in:fade
|
<div
|
||||||
out:fade
|
class="pointer-events-auto -m-2.5 origin-center p-2.5"
|
||||||
class="absolute left-full top-0 flex w-16 justify-center pt-5"
|
in:scale={{ delay: 200, easing: circOut, duration: 150 }}
|
||||||
>
|
out:scale={{ easing: cubicInOut, duration: 80 }}
|
||||||
<button
|
|
||||||
on:click={close_menu}
|
|
||||||
type="button"
|
|
||||||
class="pointer-events-auto -m-2.5 p-2.5"
|
|
||||||
>
|
>
|
||||||
<span class="sr-only">Close sidebar</span>
|
<span class="sr-only">Close sidebar</span>
|
||||||
<svg
|
<CloseIcon class="h-6 w-6 text-white" />
|
||||||
class="h-6 w-6 text-white"
|
</div>
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
d="M6 18L18 6M6 6l12 12"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Sidebar
|
<Sidebar
|
||||||
@@ -168,8 +204,8 @@
|
|||||||
podcasts={podcast_links}
|
podcasts={podcast_links}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</button>
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Static sidebar for desktop -->
|
<!-- Static sidebar for desktop -->
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { base } from '$app/paths';
|
import { base } from '$app/paths';
|
||||||
import { PlayerWidget } from '$src/components/example-player';
|
import { PlayerWidget } from '$src/components/player';
|
||||||
import { episodes } from '$src/content/episodes';
|
import { episodes } from '$src/content/episodes';
|
||||||
import { DocsPage } from '$src/layout/page';
|
import { DocsPage } from '$src/layout/page';
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<script>
|
||||||
|
import { episodes } from '$src/content/episodes';
|
||||||
|
import { DocsPage } from '$src/layout/page';
|
||||||
|
import { HighlightSvelte } from 'svelte-highlight';
|
||||||
|
import { PlayerCss, ProgressCss, player_css, progress_css } from './code';
|
||||||
|
|
||||||
|
/** @type { string | undefined} */
|
||||||
|
let audio_src = episodes.knomii.src;
|
||||||
|
audio_src;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DocsPage title="Examples" let:Section>
|
||||||
|
<Section title="AudioPlayer">
|
||||||
|
<p>
|
||||||
|
A component that does not render any UI. Instead, it provides
|
||||||
|
convenient functions, values, and headless components via expoded
|
||||||
|
values
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>This component should help</p>
|
||||||
|
<div class="not-prose py-4">
|
||||||
|
<PlayerCss />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="codeblock not-prose flex flex-col items-stretch gap-2 py-1">
|
||||||
|
<HighlightSvelte code={player_css} />
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section title="AudioProgress">
|
||||||
|
<div class="not-prose py-4">
|
||||||
|
<ProgressCss />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="codeblock not-prose flex flex-col items-stretch gap-2 py-1">
|
||||||
|
<HighlightSvelte code={progress_css} />
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
</DocsPage>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { AudioPlayer } from 'svelte-podcast';
|
||||||
|
|
||||||
|
/** @type { string | undefined} */
|
||||||
|
let src = '/static/example-syntax.mp3';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AudioPlayer
|
||||||
|
src="/static/example-syntax.mp3"
|
||||||
|
metadata={{
|
||||||
|
title: `Supper Club × Rich Harris, Author of Svelte`,
|
||||||
|
artwork: `https://ssl-static.libsyn.com/p/assets/b/3/c/d/b3cdf28da11ad39fe5bbc093207a2619/Syntax_-_499.jpg`,
|
||||||
|
}}
|
||||||
|
let:Player
|
||||||
|
let:action
|
||||||
|
let:attributes
|
||||||
|
>
|
||||||
|
<pre>{JSON.stringify({ attributes }, null, 3)}</pre>
|
||||||
|
</AudioPlayer>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
import { AudioProgress } from 'svelte-podcast/audio';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<AudioProgress step={10} />
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { format_code } from '$src/layout/helper';
|
||||||
|
import { default as player_css_src } from './audio-player.svelte?raw';
|
||||||
|
import { default as progress_css_src } from './audio-progress.svelte?raw';
|
||||||
|
export { default as PlayerCss } from './audio-player.svelte';
|
||||||
|
export { default as ProgressCss } from './audio-progress.svelte';
|
||||||
|
|
||||||
|
export const player_css = format_code(player_css_src);
|
||||||
|
export const progress_css = format_code(progress_css_src);
|
||||||
@@ -1,69 +1,33 @@
|
|||||||
<script>
|
<script>
|
||||||
import PlayerWidget from '$src/components/example-player/player-widget.svelte';
|
import PlayerWidget from '$src/components/player/player-widget.svelte';
|
||||||
import { episodes } from '$src/content/episodes';
|
import { episodes } from '$src/content/episodes';
|
||||||
import { DocsPage } from '$src/layout/page';
|
import { DocsPage } from '$src/layout/page';
|
||||||
import PreviewComponent from '$src/layout/preview-component.svelte';
|
import { HighlightSvelte } from 'svelte-highlight';
|
||||||
|
import { player_css } from './code';
|
||||||
$: player_widget = {
|
|
||||||
current_time: true,
|
|
||||||
playback_rate: true,
|
|
||||||
duration: true,
|
|
||||||
skip_back: 10,
|
|
||||||
skip_forward: 30,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @type { string | undefined} */
|
/** @type { string | undefined} */
|
||||||
let audio_src = episodes.knomii.src;
|
let audio_src = episodes.knomii.src;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DocsPage title="Examples" let:Section>
|
<DocsPage title="Examples" let:Section>
|
||||||
<p class="text-xl font-semibold text-red-500">Work in progress!</p>
|
<Section title="Coming Soon...">
|
||||||
|
<p class="text-xl font-semibold text-red-500">
|
||||||
|
This page is a work in progress.
|
||||||
|
</p>
|
||||||
|
</Section>
|
||||||
<Section title="PlayerWidget">
|
<Section title="PlayerWidget">
|
||||||
<PreviewComponent name="PlayerWidget">
|
<div class="not-prose py-4">
|
||||||
<svelte:fragment slot="options">
|
<PlayerWidget
|
||||||
<div>
|
src={audio_src}
|
||||||
<label for="pw_current_time">current_time</label>
|
skip_back={30}
|
||||||
<input
|
skip_forward={10}
|
||||||
id="pw_current_time"
|
metadata={{}}
|
||||||
type="checkbox"
|
playback_rate_values={[1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4]}
|
||||||
bind:checked={player_widget.current_time}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="pw_playback_rate">playback_rate</label>
|
|
||||||
<input
|
|
||||||
id="pw_playback_rate"
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={player_widget.playback_rate}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="pw_duration">duration</label>
|
|
||||||
<input
|
|
||||||
id="pw_duration"
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={player_widget.duration}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="pw_skip_back">skip_back</label>
|
|
||||||
<input
|
|
||||||
id="pw_skip_back"
|
|
||||||
type="number"
|
|
||||||
bind:value={player_widget.skip_back}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="pw_skip_forward">skip_forward</label>
|
|
||||||
<input
|
|
||||||
id="pw_skip_forward"
|
|
||||||
type="number"
|
|
||||||
bind:value={player_widget.skip_forward}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</svelte:fragment>
|
|
||||||
|
|
||||||
<PlayerWidget src={audio_src} include={player_widget} />
|
<div class="codeblock not-prose flex flex-col items-stretch gap-2 py-1">
|
||||||
</PreviewComponent>
|
<HighlightSvelte code={player_css} />
|
||||||
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
</DocsPage>
|
</DocsPage>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { default as player_css_src } from '$src/components/player/player-widget.svelte?raw';
|
||||||
|
import { format_code } from '$src/layout/helper';
|
||||||
|
|
||||||
|
export const player_css = format_code(player_css_src);
|
||||||
Reference in New Issue
Block a user