mikuru 1.0.32 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +1 -1
- package/components/MikuruVideoPlayer.mikuru +261 -21
- package/package.json +1 -1
- package/types/components/MikuruVideoPlayer.d.ts +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.33 - 2026-05-16
|
|
4
|
+
|
|
5
|
+
- Added `MikuruVideoPlayer` sizing props for width, height, and aspect ratio.
|
|
6
|
+
- Added a `MikuruVideoPlayer` settings menu for quality selection, playback speed, and keyboard skip seconds.
|
|
7
|
+
|
|
3
8
|
## 1.0.32 - 2026-05-16
|
|
4
9
|
|
|
5
10
|
- Added `controls` and `live` props to `MikuruVideoPlayer` and `MikuruAudioPlayer` so callers can choose visible controls and render live-stream UI without seek controls.
|
package/README.md
CHANGED
|
@@ -270,7 +270,7 @@ npm run dev:mikuru-vue-like
|
|
|
270
270
|
|
|
271
271
|
The package also includes original Mikuru components:
|
|
272
272
|
|
|
273
|
-
- `MikuruVideoPlayer.mikuru`: overlay video controls, configurable control visibility, live mode, div-based seeking, volume/mute, playback rate, and fullscreen controls.
|
|
273
|
+
- `MikuruVideoPlayer.mikuru`: overlay video controls, configurable sizing, configurable control visibility, live mode, settings menu, div-based seeking, volume/mute, playback rate, and fullscreen controls.
|
|
274
274
|
- `MikuruAudioPlayer.mikuru`: audio playback with configurable control visibility, live mode, seeking, skip controls, volume, and mute.
|
|
275
275
|
- `MikuruImageViewer.mikuru`: image zoom, pan, rotate, reset, and fullscreen controls.
|
|
276
276
|
- `MikuruModal.mikuru`: accessible modal shell with backdrop, Escape close, slots, and close events.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<section
|
|
3
3
|
class="mikuru-video"
|
|
4
4
|
:class="{ 'is-playing': isPlaying, 'controls-visible': controlsVisible }"
|
|
5
|
+
:style="playerStyle"
|
|
5
6
|
:aria-label="title"
|
|
6
7
|
@mouseenter="showControls"
|
|
7
8
|
@mouseleave="hideControls"
|
|
@@ -9,12 +10,12 @@
|
|
|
9
10
|
@pointerleave="hideControls"
|
|
10
11
|
@focusin="showControls"
|
|
11
12
|
>
|
|
12
|
-
<div class="screen" ref="screenEl">
|
|
13
|
+
<div class="screen" ref="screenEl" :style="screenStyle">
|
|
13
14
|
<video
|
|
14
15
|
ref="mediaEl"
|
|
15
16
|
class="media"
|
|
16
|
-
:src="
|
|
17
|
-
:poster="
|
|
17
|
+
:src="selectedVideoSrc"
|
|
18
|
+
:poster="selectedPoster"
|
|
18
19
|
:preload="preload"
|
|
19
20
|
playsinline
|
|
20
21
|
@loadedmetadata="handleLoadedMetadata"
|
|
@@ -77,7 +78,61 @@
|
|
|
77
78
|
</div>
|
|
78
79
|
|
|
79
80
|
<div class="right-controls">
|
|
80
|
-
<
|
|
81
|
+
<div m-if="showSettingsControl" class="settings" ref="settingsEl" @click="stopEvent">
|
|
82
|
+
<button
|
|
83
|
+
class="icon-button settings-button"
|
|
84
|
+
type="button"
|
|
85
|
+
@click="toggleSettings"
|
|
86
|
+
aria-label="Video settings"
|
|
87
|
+
:aria-expanded="settingsOpen"
|
|
88
|
+
>
|
|
89
|
+
<span class="fa-icon icon-settings" aria-hidden="true"></span>
|
|
90
|
+
</button>
|
|
91
|
+
|
|
92
|
+
<div m-if="settingsOpen" class="settings-menu" role="menu" aria-label="Video settings">
|
|
93
|
+
<div class="settings-group">
|
|
94
|
+
<span class="settings-label">Quality</span>
|
|
95
|
+
<button
|
|
96
|
+
m-for="quality in normalizedQualityOptions"
|
|
97
|
+
:key="quality.id"
|
|
98
|
+
type="button"
|
|
99
|
+
class="settings-option"
|
|
100
|
+
:class="{ active: quality.id === activeQualityId }"
|
|
101
|
+
@click="selectQuality(quality.id)"
|
|
102
|
+
>
|
|
103
|
+
{{ quality.label }}
|
|
104
|
+
</button>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div class="settings-group">
|
|
108
|
+
<span class="settings-label">Speed</span>
|
|
109
|
+
<button
|
|
110
|
+
m-for="rate in rateOptions"
|
|
111
|
+
:key="rate.value"
|
|
112
|
+
type="button"
|
|
113
|
+
class="settings-option"
|
|
114
|
+
:class="{ active: rate.value === playbackRateValue }"
|
|
115
|
+
@click="setPlaybackRate(rate.value)"
|
|
116
|
+
>
|
|
117
|
+
{{ rate.label }}
|
|
118
|
+
</button>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<div class="settings-group">
|
|
122
|
+
<span class="settings-label">Skip</span>
|
|
123
|
+
<button
|
|
124
|
+
m-for="option in skipOptions"
|
|
125
|
+
:key="option.value"
|
|
126
|
+
type="button"
|
|
127
|
+
class="settings-option"
|
|
128
|
+
:class="{ active: option.value === skipSeconds }"
|
|
129
|
+
@click="setSkipSeconds(option.value)"
|
|
130
|
+
>
|
|
131
|
+
{{ option.label }}
|
|
132
|
+
</button>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
81
136
|
<button m-if="showFullscreenControl" class="icon-button fullscreen-button" type="button" @click="toggleFullscreen" aria-label="Fullscreen">
|
|
82
137
|
<span class="fa-icon" :class="fullscreenIconClass" aria-hidden="true"></span>
|
|
83
138
|
</button>
|
|
@@ -97,6 +152,10 @@ const {
|
|
|
97
152
|
title = "Mikuru Video",
|
|
98
153
|
subtitle = "Original player component",
|
|
99
154
|
preload = "metadata",
|
|
155
|
+
width,
|
|
156
|
+
height,
|
|
157
|
+
aspectRatio,
|
|
158
|
+
qualityOptions = [],
|
|
100
159
|
controls,
|
|
101
160
|
live = false
|
|
102
161
|
} = defineProps({
|
|
@@ -105,6 +164,10 @@ const {
|
|
|
105
164
|
title: String,
|
|
106
165
|
subtitle: String,
|
|
107
166
|
preload: String,
|
|
167
|
+
width: String,
|
|
168
|
+
height: String,
|
|
169
|
+
aspectRatio: String,
|
|
170
|
+
qualityOptions: Array,
|
|
108
171
|
controls: Array,
|
|
109
172
|
live: Boolean
|
|
110
173
|
});
|
|
@@ -130,14 +193,46 @@ const muted = ref(false);
|
|
|
130
193
|
const isPlaying = ref(false);
|
|
131
194
|
const isFullscreen = ref(false);
|
|
132
195
|
const isSeeking = ref(false);
|
|
196
|
+
const settingsOpen = ref(false);
|
|
197
|
+
const selectedQualityId = ref("auto");
|
|
198
|
+
const playbackRateValue = ref(1);
|
|
199
|
+
const skipSeconds = ref(5);
|
|
133
200
|
const pointerInside = ref(false);
|
|
134
201
|
const controlsVisible = ref(true);
|
|
135
|
-
const
|
|
136
|
-
const
|
|
202
|
+
const settingsEl = ref(null);
|
|
203
|
+
const allControls = ["play", "seek", "time", "mute", "volume", "settings", "fullscreen"];
|
|
204
|
+
const liveHiddenControls = ["seek", "time"];
|
|
137
205
|
const activeControls = computed(() => {
|
|
138
206
|
const configuredControls = Array.isArray(controls.value) ? controls.value : allControls;
|
|
139
207
|
return new Set(configuredControls);
|
|
140
208
|
});
|
|
209
|
+
const normalizedQualityOptions = computed(() => {
|
|
210
|
+
const source = Array.isArray(qualityOptions.value) ? qualityOptions.value : [];
|
|
211
|
+
const options = source
|
|
212
|
+
.map((option, index) => normalizeQualityOption(option, index))
|
|
213
|
+
.filter(Boolean);
|
|
214
|
+
return options.length > 0
|
|
215
|
+
? options
|
|
216
|
+
: [{ id: "auto", label: "Auto", src: src.value, poster: poster.value }];
|
|
217
|
+
});
|
|
218
|
+
const selectedQuality = computed(() =>
|
|
219
|
+
normalizedQualityOptions.value.find((option) => option.id === selectedQualityId.value) ?? normalizedQualityOptions.value[0]
|
|
220
|
+
);
|
|
221
|
+
const activeQualityId = computed(() => selectedQuality.value?.id);
|
|
222
|
+
const selectedVideoSrc = computed(() => selectedQuality.value?.src || src.value);
|
|
223
|
+
const selectedPoster = computed(() => selectedQuality.value?.poster ?? poster.value);
|
|
224
|
+
const playerStyle = computed(() => {
|
|
225
|
+
const normalizedWidth = normalizeCssSize(width.value);
|
|
226
|
+
return normalizedWidth ? { width: normalizedWidth } : null;
|
|
227
|
+
});
|
|
228
|
+
const screenStyle = computed(() => {
|
|
229
|
+
const normalizedHeight = normalizeCssSize(height.value);
|
|
230
|
+
const normalizedAspectRatio = normalizeAspectRatio(aspectRatio.value);
|
|
231
|
+
return {
|
|
232
|
+
height: normalizedHeight || null,
|
|
233
|
+
aspectRatio: normalizedAspectRatio || null
|
|
234
|
+
};
|
|
235
|
+
});
|
|
141
236
|
const isLive = computed(() => live.value === true);
|
|
142
237
|
const safeDuration = computed(() => duration.value > 0 ? duration.value : 0);
|
|
143
238
|
const seekProgress = computed(() => {
|
|
@@ -151,12 +246,25 @@ const muteLabel = computed(() => muted.value ? "Unmute video" : "Mute video");
|
|
|
151
246
|
const playIconClass = computed(() => isPlaying.value ? "icon-pause" : "icon-play");
|
|
152
247
|
const fullscreenIconClass = computed(() => isFullscreen.value ? "icon-minimize" : "icon-maximize");
|
|
153
248
|
const statusText = computed(() => isLive.value ? "LIVE" : subtitle.value);
|
|
249
|
+
const rateOptions = [
|
|
250
|
+
{ value: 0.75, label: "0.75x" },
|
|
251
|
+
{ value: 1, label: "1x" },
|
|
252
|
+
{ value: 1.25, label: "1.25x" },
|
|
253
|
+
{ value: 1.5, label: "1.5x" },
|
|
254
|
+
{ value: 2, label: "2x" }
|
|
255
|
+
];
|
|
256
|
+
const skipOptions = [
|
|
257
|
+
{ value: 5, label: "5s" },
|
|
258
|
+
{ value: 10, label: "10s" },
|
|
259
|
+
{ value: 15, label: "15s" },
|
|
260
|
+
{ value: 30, label: "30s" }
|
|
261
|
+
];
|
|
154
262
|
const showPlayControl = computed(() => hasControl("play"));
|
|
155
263
|
const showSeekControl = computed(() => hasControl("seek"));
|
|
156
264
|
const showTimeControl = computed(() => hasControl("time"));
|
|
157
265
|
const showMuteControl = computed(() => hasControl("mute"));
|
|
158
266
|
const showVolumeControl = computed(() => hasControl("volume"));
|
|
159
|
-
const
|
|
267
|
+
const showSettingsControl = computed(() => hasControl("settings") || hasControl("rate"));
|
|
160
268
|
const showFullscreenControl = computed(() => hasControl("fullscreen"));
|
|
161
269
|
const showControlShelf = computed(() => (
|
|
162
270
|
showPlayControl.value ||
|
|
@@ -164,19 +272,17 @@ const showControlShelf = computed(() => (
|
|
|
164
272
|
showTimeControl.value ||
|
|
165
273
|
showMuteControl.value ||
|
|
166
274
|
showVolumeControl.value ||
|
|
167
|
-
|
|
275
|
+
showSettingsControl.value ||
|
|
168
276
|
showFullscreenControl.value ||
|
|
169
277
|
isLive.value
|
|
170
278
|
));
|
|
171
|
-
const rates = [1, 1.25, 1.5, 2, 0.75];
|
|
172
|
-
let playbackRate = 1;
|
|
173
|
-
let rateIndex = 0;
|
|
174
279
|
let isDisposed = false;
|
|
175
280
|
let ignoreMediaEventsUntil = 0;
|
|
176
281
|
|
|
177
282
|
onMounted(() => {
|
|
178
283
|
applyAudioSettings();
|
|
179
284
|
document.addEventListener("fullscreenchange", updateFullscreen);
|
|
285
|
+
document.addEventListener("pointerdown", handleDocumentPointerDown);
|
|
180
286
|
});
|
|
181
287
|
|
|
182
288
|
onBeforeUnmount(() => {
|
|
@@ -187,6 +293,7 @@ onBeforeUnmount(() => {
|
|
|
187
293
|
|
|
188
294
|
onUnmounted(() => {
|
|
189
295
|
document.removeEventListener("fullscreenchange", updateFullscreen);
|
|
296
|
+
document.removeEventListener("pointerdown", handleDocumentPointerDown);
|
|
190
297
|
});
|
|
191
298
|
|
|
192
299
|
function getMedia() {
|
|
@@ -202,6 +309,41 @@ function shouldIgnoreMediaEvent() {
|
|
|
202
309
|
return performance.now() < ignoreMediaEventsUntil;
|
|
203
310
|
}
|
|
204
311
|
|
|
312
|
+
function normalizeQualityOption(option, index) {
|
|
313
|
+
if (typeof option === "string") {
|
|
314
|
+
return { id: option || `quality-${index}`, label: option || `Quality ${index + 1}`, src: src.value, poster: poster.value };
|
|
315
|
+
}
|
|
316
|
+
if (!option || typeof option !== "object") {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
const optionSrc = typeof option.src === "string" && option.src ? option.src : src.value;
|
|
320
|
+
const label = typeof option.label === "string" && option.label ? option.label : `Quality ${index + 1}`;
|
|
321
|
+
return {
|
|
322
|
+
id: typeof option.id === "string" || typeof option.id === "number" ? String(option.id) : `${label}-${index}`,
|
|
323
|
+
label,
|
|
324
|
+
src: optionSrc,
|
|
325
|
+
poster: typeof option.poster === "string" ? option.poster : poster.value
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function normalizeCssSize(value) {
|
|
330
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
331
|
+
return value >= 0 ? value + "px" : "";
|
|
332
|
+
}
|
|
333
|
+
if (typeof value !== "string") return "";
|
|
334
|
+
const trimmed = value.trim();
|
|
335
|
+
if (!trimmed) return "";
|
|
336
|
+
return /^\d+(\.\d+)?$/.test(trimmed) ? trimmed + "px" : trimmed;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function normalizeAspectRatio(value) {
|
|
340
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
341
|
+
return value > 0 ? String(value) : "";
|
|
342
|
+
}
|
|
343
|
+
if (typeof value !== "string") return "";
|
|
344
|
+
return value.trim();
|
|
345
|
+
}
|
|
346
|
+
|
|
205
347
|
function hasControl(name) {
|
|
206
348
|
if (isLive.value && liveHiddenControls.includes(name)) return false;
|
|
207
349
|
return activeControls.value.has(name);
|
|
@@ -273,7 +415,7 @@ function applyAudioSettings() {
|
|
|
273
415
|
if (!media) return;
|
|
274
416
|
media.volume = volume.value;
|
|
275
417
|
media.muted = muted.value;
|
|
276
|
-
media.playbackRate =
|
|
418
|
+
media.playbackRate = playbackRateValue.value;
|
|
277
419
|
}
|
|
278
420
|
|
|
279
421
|
function markPlaying(event) {
|
|
@@ -389,7 +531,7 @@ function seekWithKeyboard(event) {
|
|
|
389
531
|
return;
|
|
390
532
|
}
|
|
391
533
|
|
|
392
|
-
const offset = event.key === "ArrowRight" ?
|
|
534
|
+
const offset = event.key === "ArrowRight" ? skipSeconds.value : -skipSeconds.value;
|
|
393
535
|
const nextTime = Math.min(Math.max(currentTime.value + offset, 0), safeDuration.value);
|
|
394
536
|
seekTo(nextTime);
|
|
395
537
|
}
|
|
@@ -421,21 +563,68 @@ function toggleMute(event) {
|
|
|
421
563
|
}, 0);
|
|
422
564
|
}
|
|
423
565
|
|
|
424
|
-
function
|
|
566
|
+
function toggleSettings() {
|
|
425
567
|
if (isDisposed) return;
|
|
426
|
-
|
|
568
|
+
settingsOpen.value = !settingsOpen.value;
|
|
569
|
+
controlsVisible.value = true;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
function selectQuality(id) {
|
|
573
|
+
if (isDisposed) return;
|
|
574
|
+
const media = getMedia();
|
|
575
|
+
const wasPlaying = media ? !media.paused : false;
|
|
576
|
+
const previousTime = media?.currentTime || 0;
|
|
577
|
+
selectedQualityId.value = id;
|
|
578
|
+
settingsOpen.value = false;
|
|
579
|
+
if (!media) return;
|
|
427
580
|
window.setTimeout(() => {
|
|
428
581
|
if (isDisposed) return;
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
582
|
+
const nextMedia = getMedia();
|
|
583
|
+
if (!nextMedia) return;
|
|
584
|
+
if (Number.isFinite(previousTime) && previousTime > 0 && safeDuration.value > 0) {
|
|
585
|
+
nextMedia.currentTime = Math.min(previousTime, safeDuration.value);
|
|
586
|
+
currentTime.value = nextMedia.currentTime;
|
|
434
587
|
}
|
|
435
|
-
|
|
588
|
+
nextMedia.playbackRate = playbackRateValue.value;
|
|
589
|
+
if (wasPlaying) {
|
|
590
|
+
nextMedia.play().catch((error) => {
|
|
591
|
+
if (error?.name !== "AbortError") {
|
|
592
|
+
throw error;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}, 0);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function setPlaybackRate(nextRate) {
|
|
600
|
+
if (isDisposed) return;
|
|
601
|
+
playbackRateValue.value = nextRate;
|
|
602
|
+
settingsOpen.value = false;
|
|
603
|
+
window.setTimeout(() => {
|
|
604
|
+
if (isDisposed) return;
|
|
605
|
+
const media = getMedia();
|
|
606
|
+
if (!media) return;
|
|
607
|
+
media.playbackRate = nextRate;
|
|
436
608
|
}, 0);
|
|
437
609
|
}
|
|
438
610
|
|
|
611
|
+
function setSkipSeconds(nextSeconds) {
|
|
612
|
+
if (isDisposed) return;
|
|
613
|
+
skipSeconds.value = nextSeconds;
|
|
614
|
+
settingsOpen.value = false;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
function handleDocumentPointerDown(event) {
|
|
618
|
+
if (isDisposed || !settingsOpen.value) return;
|
|
619
|
+
const menu = settingsEl.value;
|
|
620
|
+
if (menu?.contains?.(event.target)) return;
|
|
621
|
+
settingsOpen.value = false;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function stopEvent(event) {
|
|
625
|
+
event.stopPropagation();
|
|
626
|
+
}
|
|
627
|
+
|
|
439
628
|
function toggleFullscreen() {
|
|
440
629
|
if (isDisposed) return;
|
|
441
630
|
if (document.fullscreenElement) {
|
|
@@ -696,6 +885,53 @@ function formatTime(seconds) {
|
|
|
696
885
|
font-size: 0.84rem;
|
|
697
886
|
}
|
|
698
887
|
|
|
888
|
+
.settings {
|
|
889
|
+
position: relative;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.settings-menu {
|
|
893
|
+
position: absolute;
|
|
894
|
+
right: 0;
|
|
895
|
+
bottom: calc(100% + 10px);
|
|
896
|
+
z-index: 4;
|
|
897
|
+
display: grid;
|
|
898
|
+
gap: 12px;
|
|
899
|
+
width: min(240px, calc(100vw - 32px));
|
|
900
|
+
padding: 12px;
|
|
901
|
+
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
902
|
+
border-radius: 8px;
|
|
903
|
+
color: #ffffff;
|
|
904
|
+
background: rgba(3, 7, 18, 0.94);
|
|
905
|
+
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.36);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.settings-group {
|
|
909
|
+
display: grid;
|
|
910
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
911
|
+
gap: 6px;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.settings-label {
|
|
915
|
+
grid-column: 1 / -1;
|
|
916
|
+
color: rgba(255, 255, 255, 0.72);
|
|
917
|
+
font-size: 0.78rem;
|
|
918
|
+
font-weight: 700;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
.settings-option {
|
|
922
|
+
min-height: 30px;
|
|
923
|
+
padding: 0 8px;
|
|
924
|
+
border-radius: 6px;
|
|
925
|
+
font-size: 0.8rem;
|
|
926
|
+
white-space: nowrap;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.settings-option.active {
|
|
930
|
+
border-color: #ef4444;
|
|
931
|
+
color: #ffffff;
|
|
932
|
+
background: #ef4444;
|
|
933
|
+
}
|
|
934
|
+
|
|
699
935
|
button {
|
|
700
936
|
min-height: 36px;
|
|
701
937
|
padding: 0 12px;
|
|
@@ -769,6 +1005,10 @@ button:hover {
|
|
|
769
1005
|
mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M80 416L128 416L262.1 535.2C268.5 540.9 276.7 544 285.2 544C304.4 544 320 528.4 320 509.2L320 130.8C320 111.6 304.4 96 285.2 96C276.7 96 268.5 99.1 262.1 104.8L128 224L80 224C53.5 224 32 245.5 32 272L32 368C32 394.5 53.5 416 80 416zM399 239C389.6 248.4 389.6 263.6 399 272.9L446 319.9L399 366.9C389.6 376.3 389.6 391.5 399 400.8C408.4 410.1 423.6 410.2 432.9 400.8L479.9 353.8L526.9 400.8C536.3 410.2 551.5 410.2 560.8 400.8C570.1 391.4 570.2 376.2 560.8 366.9L513.8 319.9L560.8 272.9C570.2 263.5 570.2 248.3 560.8 239C551.4 229.7 536.2 229.6 526.9 239L479.9 286L432.9 239C423.5 229.6 408.3 229.6 399 239z"/></svg>');
|
|
770
1006
|
}
|
|
771
1007
|
|
|
1008
|
+
.icon-settings {
|
|
1009
|
+
mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M259.1 73.5C262.1 59 274.9 48 290 48L350 48C365.1 48 377.9 59 380.9 73.5L389.8 116.8C404.9 122.5 419.2 130 432.5 139.1L474.3 125.1C488.6 120.3 504.4 126.1 512 139.1L542 190.9C549.6 203.9 546.8 220.5 535.5 230.5L502.7 259.8C504 267.7 504.7 275.8 504.7 284C504.7 292.2 504 300.3 502.7 308.2L535.5 337.5C546.8 347.5 549.6 364.1 542 377.1L512 428.9C504.4 441.9 488.6 447.7 474.3 442.9L432.5 428.9C419.2 438 404.9 445.5 389.8 451.2L380.9 494.5C377.9 509 365.1 520 350 520L290 520C274.9 520 262.1 509 259.1 494.5L250.2 451.2C235.1 445.5 220.8 438 207.5 428.9L165.7 442.9C151.4 447.7 135.6 441.9 128 428.9L98 377.1C90.4 364.1 93.2 347.5 104.5 337.5L137.3 308.2C136 300.3 135.3 292.2 135.3 284C135.3 275.8 136 267.7 137.3 259.8L104.5 230.5C93.2 220.5 90.4 203.9 98 190.9L128 139.1C135.6 126.1 151.4 120.3 165.7 125.1L207.5 139.1C220.8 130 235.1 122.5 250.2 116.8L259.1 73.5zM320 356C359.8 356 392 323.8 392 284C392 244.2 359.8 212 320 212C280.2 212 248 244.2 248 284C248 323.8 280.2 356 320 356z"/></svg>');
|
|
1010
|
+
}
|
|
1011
|
+
|
|
772
1012
|
@media (max-width: 620px) {
|
|
773
1013
|
.top-bar {
|
|
774
1014
|
align-items: flex-start;
|
package/package.json
CHANGED
|
@@ -30,14 +30,26 @@ export type MikuruVideoPlayerControl =
|
|
|
30
30
|
| "mute"
|
|
31
31
|
| "volume"
|
|
32
32
|
| "rate"
|
|
33
|
+
| "settings"
|
|
33
34
|
| "fullscreen";
|
|
34
35
|
|
|
36
|
+
export type MikuruVideoPlayerQualityOption = {
|
|
37
|
+
id?: string | number;
|
|
38
|
+
label: string;
|
|
39
|
+
src: string;
|
|
40
|
+
poster?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
35
43
|
export type MikuruVideoPlayerProps = {
|
|
36
44
|
src: string;
|
|
37
45
|
poster?: string;
|
|
38
46
|
title?: string;
|
|
39
47
|
subtitle?: string;
|
|
40
48
|
preload?: string;
|
|
49
|
+
width?: string | number;
|
|
50
|
+
height?: string | number;
|
|
51
|
+
aspectRatio?: string | number;
|
|
52
|
+
qualityOptions?: MikuruVideoPlayerQualityOption[];
|
|
41
53
|
controls?: MikuruVideoPlayerControl[];
|
|
42
54
|
live?: boolean;
|
|
43
55
|
} & MikuruVideoPlayerEvents;
|