mikuru 1.0.26 → 1.0.28

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 (57) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +36 -4
  3. package/components/MikuruAudioPlayer.mikuru +263 -0
  4. package/components/MikuruCarousel.mikuru +280 -0
  5. package/components/MikuruCodeBlock.mikuru +96 -0
  6. package/components/MikuruDropdown.mikuru +153 -0
  7. package/components/MikuruImageViewer.mikuru +269 -0
  8. package/components/MikuruModal.mikuru +159 -0
  9. package/components/MikuruProgress.mikuru +85 -0
  10. package/components/MikuruToast.mikuru +128 -0
  11. package/components/MikuruToolTip.mikuru +95 -0
  12. package/components/MikuruVideoPlayer.mikuru +635 -0
  13. package/dist/compiler/compile.js +9 -2
  14. package/dist/compiler/compile.js.map +1 -1
  15. package/dist/compiler/compileHydration.js +9 -2
  16. package/dist/compiler/compileHydration.js.map +1 -1
  17. package/dist/compiler/compileSsr.js +4 -1
  18. package/dist/compiler/compileSsr.js.map +1 -1
  19. package/dist/compiler/generate.d.ts +1 -0
  20. package/dist/compiler/generate.js +17 -2
  21. package/dist/compiler/generate.js.map +1 -1
  22. package/dist/compiler/generateHydration.js +1 -1
  23. package/dist/compiler/generateHydration.js.map +1 -1
  24. package/dist/compiler/index.d.ts +2 -0
  25. package/dist/compiler/index.js +1 -0
  26. package/dist/compiler/index.js.map +1 -1
  27. package/dist/compiler/parseSfc.js +20 -2
  28. package/dist/compiler/parseSfc.js.map +1 -1
  29. package/dist/compiler/sourceMap.js +72 -16
  30. package/dist/compiler/sourceMap.js.map +1 -1
  31. package/dist/compiler/templateTypeCheck.d.ts +19 -0
  32. package/dist/compiler/templateTypeCheck.js +270 -0
  33. package/dist/compiler/templateTypeCheck.js.map +1 -0
  34. package/dist/compiler/types.d.ts +7 -0
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/runtime/devtools.d.ts +19 -5
  39. package/dist/runtime/devtools.js +26 -3
  40. package/dist/runtime/devtools.js.map +1 -1
  41. package/dist/runtime/index.d.ts +2 -2
  42. package/dist/runtime/index.js +1 -1
  43. package/dist/runtime/index.js.map +1 -1
  44. package/dist/vite.d.ts +1 -0
  45. package/dist/vite.js +65 -3
  46. package/dist/vite.js.map +1 -1
  47. package/package.json +84 -2
  48. package/types/components/MikuruAudioPlayer.d.ts +12 -0
  49. package/types/components/MikuruCarousel.d.ts +21 -0
  50. package/types/components/MikuruCodeBlock.d.ts +11 -0
  51. package/types/components/MikuruDropdown.d.ts +17 -0
  52. package/types/components/MikuruImageViewer.d.ts +14 -0
  53. package/types/components/MikuruModal.d.ts +14 -0
  54. package/types/components/MikuruProgress.d.ts +12 -0
  55. package/types/components/MikuruToast.d.ts +17 -0
  56. package/types/components/MikuruToolTip.d.ts +11 -0
  57. package/types/components/MikuruVideoPlayer.d.ts +13 -0
@@ -0,0 +1,635 @@
1
+ <template>
2
+ <section
3
+ class="mikuru-video"
4
+ :class="{ 'is-playing': isPlaying, 'controls-visible': controlsVisible }"
5
+ :aria-label="title"
6
+ @mouseenter="showControls"
7
+ @mouseleave="hideControls"
8
+ @pointerenter="showControls"
9
+ @pointerleave="hideControls"
10
+ @focusin="showControls"
11
+ >
12
+ <div class="screen" ref="screenEl">
13
+ <video
14
+ ref="mediaEl"
15
+ class="media"
16
+ :src="src"
17
+ :poster="poster"
18
+ :preload="preload"
19
+ playsinline
20
+ @loadedmetadata="syncMedia"
21
+ @timeupdate="syncMedia"
22
+ @durationchange="syncMedia"
23
+ @play="markPlaying"
24
+ @pause="markPaused"
25
+ @ended="markPaused"
26
+ @click="togglePlayback"
27
+ ></video>
28
+
29
+ <div class="top-bar">
30
+ <strong>{{ title }}</strong>
31
+ <span>{{ subtitle }}</span>
32
+ </div>
33
+
34
+ <button class="center-toggle" type="button" @click="togglePlayback" :aria-label="playLabel">
35
+ <span m-if="isPlaying" class="fa-icon icon-pause large" aria-hidden="true"></span>
36
+ <span m-else class="fa-icon icon-play large" aria-hidden="true"></span>
37
+ </button>
38
+
39
+ <div class="control-shelf">
40
+ <div
41
+ class="seek"
42
+ role="slider"
43
+ tabindex="0"
44
+ aria-label="Seek"
45
+ aria-valuemin="0"
46
+ :aria-valuemax="safeDuration"
47
+ :aria-valuenow="currentTime"
48
+ :aria-valuetext="formatTime(currentTime) + ' of ' + formatTime(duration)"
49
+ :style="seekStyle"
50
+ @click="seekFromPointer"
51
+ @keydown="seekWithKeyboard"
52
+ @pointerdown="startSeek"
53
+ @pointermove="dragSeek"
54
+ @pointerup="endSeek"
55
+ @pointercancel="endSeek"
56
+ >
57
+ <span class="seek-fill"></span>
58
+ <span class="seek-thumb"></span>
59
+ </div>
60
+
61
+ <div class="control-row">
62
+ <div class="left-controls">
63
+ <button class="icon-button" type="button" @click="togglePlayback" :aria-label="playLabel">
64
+ <span m-if="isPlaying" class="fa-icon icon-pause" aria-hidden="true"></span>
65
+ <span m-else class="fa-icon icon-play" aria-hidden="true"></span>
66
+ </button>
67
+ <button class="icon-button" type="button" @click="stopPlayback" aria-label="Stop video">
68
+ <span class="fa-icon icon-stop" aria-hidden="true"></span>
69
+ </button>
70
+ <button class="icon-button" type="button" @click="toggleMute" :aria-label="muteLabel">
71
+ <span m-if="muted" class="fa-icon icon-mute" aria-hidden="true"></span>
72
+ <span m-else class="fa-icon icon-volume" aria-hidden="true"></span>
73
+ </button>
74
+ <label class="volume">
75
+ <span>Volume</span>
76
+ <input type="range" min="0" max="1" step="0.01" :value="volume" @input="setVolume" />
77
+ </label>
78
+ <span class="clock">{{ formatTime(currentTime) }} / {{ formatTime(duration) }}</span>
79
+ </div>
80
+
81
+ <div class="right-controls">
82
+ <button class="pill-button" type="button" @click="cycleRate">{{ playbackRate }}x</button>
83
+ <button class="icon-button fullscreen-button" type="button" @click="toggleFullscreen" aria-label="Fullscreen">
84
+ <span m-if="isFullscreen" class="fa-icon icon-minimize" aria-hidden="true"></span>
85
+ <span m-else class="fa-icon icon-maximize" aria-hidden="true"></span>
86
+ </button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </section>
92
+ </template>
93
+
94
+ <script>
95
+ import { computed, onMounted, onUnmounted, ref } from "mikuru";
96
+
97
+ const {
98
+ src,
99
+ poster = "",
100
+ title = "Mikuru Video",
101
+ subtitle = "Original player component",
102
+ preload = "metadata"
103
+ } = defineProps({
104
+ src: String,
105
+ poster: String,
106
+ title: String,
107
+ subtitle: String,
108
+ preload: String
109
+ });
110
+
111
+ const mediaEl = ref(null);
112
+ const screenEl = ref(null);
113
+ const currentTime = ref(0);
114
+ const duration = ref(0);
115
+ const volume = ref(0.8);
116
+ const muted = ref(false);
117
+ const isPlaying = ref(false);
118
+ const isFullscreen = ref(false);
119
+ const isSeeking = ref(false);
120
+ const pointerInside = ref(false);
121
+ const controlsVisible = ref(true);
122
+ const playbackRate = ref(1);
123
+ const safeDuration = computed(() => duration.value > 0 ? duration.value : 0);
124
+ const seekProgress = computed(() => {
125
+ if (safeDuration.value <= 0) return 0;
126
+ if (safeDuration.value - currentTime.value <= 0.15) return 100;
127
+ return Math.min((currentTime.value / safeDuration.value) * 100, 100);
128
+ });
129
+ const seekStyle = computed(() => "--progress: " + seekProgress.value + "%");
130
+ const playLabel = computed(() => isPlaying.value ? "Pause video" : "Play video");
131
+ const muteLabel = computed(() => muted.value ? "Unmute video" : "Mute video");
132
+ const rates = [1, 1.25, 1.5, 2, 0.75];
133
+
134
+ onMounted(() => {
135
+ applyAudioSettings();
136
+ document.addEventListener("fullscreenchange", updateFullscreen);
137
+ });
138
+
139
+ onUnmounted(() => {
140
+ document.removeEventListener("fullscreenchange", updateFullscreen);
141
+ });
142
+
143
+ function getMedia() {
144
+ return mediaEl.value;
145
+ }
146
+
147
+ function syncMedia() {
148
+ const media = getMedia();
149
+ if (!media) return;
150
+ currentTime.value = media.currentTime || 0;
151
+ duration.value = Number.isFinite(media.duration) ? media.duration : 0;
152
+ volume.value = media.volume;
153
+ muted.value = media.muted;
154
+ playbackRate.value = media.playbackRate;
155
+ }
156
+
157
+ function applyAudioSettings() {
158
+ const media = getMedia();
159
+ if (!media) return;
160
+ media.volume = volume.value;
161
+ media.muted = muted.value;
162
+ media.playbackRate = playbackRate.value;
163
+ }
164
+
165
+ function markPlaying() {
166
+ isPlaying.value = true;
167
+ controlsVisible.value = pointerInside.value;
168
+ }
169
+
170
+ function markPaused() {
171
+ isPlaying.value = false;
172
+ controlsVisible.value = true;
173
+ }
174
+
175
+ function updateFullscreen() {
176
+ isFullscreen.value = document.fullscreenElement === screenEl.value || document.fullscreenElement === mediaEl.value;
177
+ }
178
+
179
+ async function togglePlayback() {
180
+ const media = getMedia();
181
+ if (!media) return;
182
+ if (media.paused) {
183
+ await media.play();
184
+ return;
185
+ }
186
+ media.pause();
187
+ }
188
+
189
+ function getPointerTime(event) {
190
+ const rect = event.currentTarget.getBoundingClientRect();
191
+ const ratio = rect.width > 0 ? Math.min(Math.max((event.clientX - rect.left) / rect.width, 0), 1) : 0;
192
+ const rawTime = ratio * safeDuration.value;
193
+ return safeDuration.value - rawTime <= 0.15 ? safeDuration.value : rawTime;
194
+ }
195
+
196
+ function seekTo(nextTime) {
197
+ const media = getMedia();
198
+ currentTime.value = nextTime;
199
+ if (media) {
200
+ media.currentTime = nextTime;
201
+ }
202
+ }
203
+
204
+ function seekFromPointer(event) {
205
+ seekTo(getPointerTime(event));
206
+ }
207
+
208
+ function startSeek(event) {
209
+ isSeeking.value = true;
210
+ controlsVisible.value = true;
211
+ event.currentTarget.setPointerCapture?.(event.pointerId);
212
+ seekFromPointer(event);
213
+ }
214
+
215
+ function dragSeek(event) {
216
+ if (!isSeeking.value) return;
217
+ seekFromPointer(event);
218
+ }
219
+
220
+ function endSeek(event) {
221
+ if (!isSeeking.value) return;
222
+ isSeeking.value = false;
223
+ event.currentTarget.releasePointerCapture?.(event.pointerId);
224
+ seekFromPointer(event);
225
+ }
226
+
227
+ function showControls() {
228
+ pointerInside.value = true;
229
+ controlsVisible.value = true;
230
+ }
231
+
232
+ function hideControls() {
233
+ pointerInside.value = false;
234
+ if (!isPlaying.value || isSeeking.value) return;
235
+ controlsVisible.value = false;
236
+ }
237
+
238
+ function seekWithKeyboard(event) {
239
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight" && event.key !== "Home" && event.key !== "End") {
240
+ return;
241
+ }
242
+
243
+ event.preventDefault();
244
+ if (event.key === "Home") {
245
+ seekTo(0);
246
+ return;
247
+ }
248
+ if (event.key === "End") {
249
+ seekTo(safeDuration.value);
250
+ return;
251
+ }
252
+
253
+ const offset = event.key === "ArrowRight" ? 5 : -5;
254
+ const nextTime = Math.min(Math.max(currentTime.value + offset, 0), safeDuration.value);
255
+ seekTo(nextTime);
256
+ }
257
+
258
+ function stopPlayback() {
259
+ const media = getMedia();
260
+ if (!media) return;
261
+ media.pause();
262
+ media.currentTime = 0;
263
+ currentTime.value = 0;
264
+ isPlaying.value = false;
265
+ }
266
+
267
+ function setVolume(event) {
268
+ const nextVolume = Number(event.target.value);
269
+ volume.value = nextVolume;
270
+ muted.value = nextVolume === 0;
271
+ applyAudioSettings();
272
+ }
273
+
274
+ function toggleMute() {
275
+ muted.value = !muted.value;
276
+ applyAudioSettings();
277
+ }
278
+
279
+ function cycleRate() {
280
+ const currentIndex = rates.indexOf(playbackRate.value);
281
+ playbackRate.value = rates[(currentIndex + 1) % rates.length];
282
+ applyAudioSettings();
283
+ }
284
+
285
+ function toggleFullscreen() {
286
+ if (document.fullscreenElement) {
287
+ document.exitFullscreen?.();
288
+ return;
289
+ }
290
+ const target = screenEl.value ?? getMedia();
291
+ if (!target || typeof target.requestFullscreen !== "function") return;
292
+ target.requestFullscreen();
293
+ }
294
+
295
+ function formatTime(seconds) {
296
+ const safeSeconds = Number.isFinite(seconds) ? Math.floor(seconds) : 0;
297
+ const minutes = Math.floor(safeSeconds / 60);
298
+ const remainder = String(safeSeconds % 60).padStart(2, "0");
299
+ return minutes + ":" + remainder;
300
+ }
301
+ </script>
302
+
303
+ <style scoped>
304
+ .mikuru-video {
305
+ overflow: hidden;
306
+ border: 1px solid #18181b;
307
+ border-radius: 8px;
308
+ color: #ffffff;
309
+ background: #050505;
310
+ box-shadow: 0 20px 48px rgba(0, 0, 0, 0.28);
311
+ }
312
+
313
+ .screen {
314
+ position: relative;
315
+ display: grid;
316
+ aspect-ratio: 16 / 9;
317
+ background: #111827;
318
+ }
319
+
320
+ .screen::before,
321
+ .screen::after {
322
+ position: absolute;
323
+ right: 0;
324
+ left: 0;
325
+ z-index: 1;
326
+ height: 34%;
327
+ pointer-events: none;
328
+ content: "";
329
+ }
330
+
331
+ .screen::before {
332
+ top: 0;
333
+ background: linear-gradient(180deg, rgba(0, 0, 0, 0.68), rgba(0, 0, 0, 0));
334
+ }
335
+
336
+ .screen::after {
337
+ bottom: 0;
338
+ background: linear-gradient(0deg, rgba(0, 0, 0, 0.82), rgba(0, 0, 0, 0));
339
+ }
340
+
341
+ .media {
342
+ width: 100%;
343
+ height: 100%;
344
+ object-fit: cover;
345
+ cursor: pointer;
346
+ }
347
+
348
+ .top-bar {
349
+ position: absolute;
350
+ top: 0;
351
+ right: 0;
352
+ left: 0;
353
+ z-index: 2;
354
+ display: flex;
355
+ align-items: center;
356
+ justify-content: space-between;
357
+ gap: 16px;
358
+ min-height: 58px;
359
+ padding: 12px 16px;
360
+ color: #ffffff;
361
+ opacity: 0;
362
+ transition: opacity 0.16s ease;
363
+ }
364
+
365
+ .top-bar strong,
366
+ .top-bar span,
367
+ .clock {
368
+ overflow: hidden;
369
+ text-overflow: ellipsis;
370
+ white-space: nowrap;
371
+ }
372
+
373
+ .top-bar span,
374
+ .clock,
375
+ .seek span,
376
+ .volume span {
377
+ color: rgba(255, 255, 255, 0.82);
378
+ font-size: 0.88rem;
379
+ }
380
+
381
+ .center-toggle {
382
+ position: absolute;
383
+ top: 50%;
384
+ left: 50%;
385
+ z-index: 2;
386
+ display: grid;
387
+ place-items: center;
388
+ width: 88px;
389
+ height: 64px;
390
+ min-width: 88px;
391
+ min-height: 64px;
392
+ padding: 0;
393
+ border: 0;
394
+ border-radius: 999px;
395
+ color: #ffffff;
396
+ background: rgba(0, 0, 0, 0.68);
397
+ box-shadow: 0 10px 34px rgba(0, 0, 0, 0.36);
398
+ transform: translate(-50%, -50%);
399
+ opacity: 0;
400
+ pointer-events: none;
401
+ transition: opacity 0.16s ease;
402
+ }
403
+
404
+ .controls-visible .center-toggle,
405
+ .center-toggle:focus-visible {
406
+ opacity: 0.95;
407
+ pointer-events: auto;
408
+ }
409
+
410
+ .control-shelf {
411
+ position: absolute;
412
+ right: 0;
413
+ bottom: 0;
414
+ left: 0;
415
+ z-index: 2;
416
+ display: grid;
417
+ gap: 8px;
418
+ padding: 0 14px 12px;
419
+ background: rgba(0, 0, 0, 0.58);
420
+ backdrop-filter: blur(8px);
421
+ opacity: 0;
422
+ pointer-events: none;
423
+ transform: translateY(8px);
424
+ transition: opacity 0.16s ease, transform 0.16s ease;
425
+ }
426
+
427
+ .controls-visible .top-bar,
428
+ .controls-visible .control-shelf {
429
+ opacity: 1;
430
+ }
431
+
432
+ .controls-visible .control-shelf {
433
+ pointer-events: auto;
434
+ transform: translateY(0);
435
+ }
436
+
437
+ .seek {
438
+ position: relative;
439
+ display: block;
440
+ height: 18px;
441
+ cursor: pointer;
442
+ touch-action: none;
443
+ }
444
+
445
+ .volume span {
446
+ position: absolute;
447
+ width: 1px;
448
+ height: 1px;
449
+ overflow: hidden;
450
+ clip: rect(0 0 0 0);
451
+ }
452
+
453
+ .control-row,
454
+ .left-controls,
455
+ .right-controls,
456
+ .volume {
457
+ display: flex;
458
+ align-items: center;
459
+ gap: 8px;
460
+ }
461
+
462
+ .control-row {
463
+ justify-content: space-between;
464
+ min-height: 38px;
465
+ }
466
+
467
+ .left-controls,
468
+ .right-controls {
469
+ min-width: 0;
470
+ }
471
+
472
+ .clock {
473
+ min-width: 92px;
474
+ font-variant-numeric: tabular-nums;
475
+ }
476
+
477
+ .volume input {
478
+ width: 100%;
479
+ accent-color: #ef4444;
480
+ }
481
+
482
+ .seek::before,
483
+ .seek-fill {
484
+ position: absolute;
485
+ top: 50%;
486
+ left: 0;
487
+ height: 6px;
488
+ border-radius: 999px;
489
+ transform: translateY(-50%);
490
+ content: "";
491
+ }
492
+
493
+ .seek::before {
494
+ right: 0;
495
+ background: rgba(255, 255, 255, 0.9);
496
+ }
497
+
498
+ .seek-fill {
499
+ width: var(--progress);
500
+ background: #ef4444;
501
+ }
502
+
503
+ .seek-thumb {
504
+ position: absolute;
505
+ top: 50%;
506
+ left: var(--progress);
507
+ width: 16px;
508
+ height: 16px;
509
+ border-radius: 999px;
510
+ background: #ef4444;
511
+ box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.18);
512
+ transform: translate(-50%, -50%);
513
+ }
514
+
515
+ .seek:focus-visible {
516
+ outline: 2px solid rgba(255, 255, 255, 0.95);
517
+ outline-offset: 3px;
518
+ }
519
+
520
+ .volume input {
521
+ width: 86px;
522
+ }
523
+
524
+ .pill-button {
525
+ min-width: 48px;
526
+ border-radius: 999px;
527
+ font-size: 0.84rem;
528
+ }
529
+
530
+ button {
531
+ min-height: 36px;
532
+ padding: 0 12px;
533
+ border: 1px solid rgba(255, 255, 255, 0.14);
534
+ border-radius: 8px;
535
+ color: #ffffff;
536
+ background: rgba(17, 24, 39, 0.42);
537
+ font: inherit;
538
+ cursor: pointer;
539
+ }
540
+
541
+ button:hover {
542
+ border-color: rgba(255, 255, 255, 0.38);
543
+ background: rgba(17, 24, 39, 0.88);
544
+ }
545
+
546
+ .icon-button {
547
+ display: inline-grid;
548
+ place-items: center;
549
+ width: 38px;
550
+ padding: 0;
551
+ border-color: transparent;
552
+ background: transparent;
553
+ }
554
+
555
+ .fa-icon {
556
+ display: block;
557
+ width: 18px;
558
+ height: 18px;
559
+ background: currentColor;
560
+ filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.28));
561
+ mask-position: center;
562
+ mask-repeat: no-repeat;
563
+ mask-size: contain;
564
+ }
565
+
566
+ .fa-icon.large {
567
+ width: 42px;
568
+ height: 42px;
569
+ }
570
+
571
+ .center-toggle .icon-play {
572
+ transform: translateX(3px);
573
+ }
574
+
575
+ .center-toggle .icon-pause,
576
+ .center-toggle .icon-stop {
577
+ transform: translateX(0);
578
+ }
579
+
580
+ .icon-play {
581
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M187.2 100.9C174.8 94.1 159.8 94.4 147.6 101.6C135.4 108.8 128 121.9 128 136L128 504C128 518.1 135.5 531.2 147.6 538.4C159.7 545.6 174.8 545.9 187.2 539.1L523.2 355.1C536 348.1 544 334.6 544 320C544 305.4 536 291.9 523.2 284.9L187.2 100.9z"/></svg>');
582
+ }
583
+
584
+ .icon-pause {
585
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M176 96C149.5 96 128 117.5 128 144L128 496C128 522.5 149.5 544 176 544L240 544C266.5 544 288 522.5 288 496L288 144C288 117.5 266.5 96 240 96L176 96zM400 96C373.5 96 352 117.5 352 144L352 496C352 522.5 373.5 544 400 544L464 544C490.5 544 512 522.5 512 496L512 144C512 117.5 490.5 96 464 96L400 96z"/></svg>');
586
+ }
587
+
588
+ .icon-stop {
589
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M160 96L480 96C515.3 96 544 124.7 544 160L544 480C544 515.3 515.3 544 480 544L160 544C124.7 544 96 515.3 96 480L96 160C96 124.7 124.7 96 160 96z"/></svg>');
590
+ }
591
+
592
+ .icon-maximize {
593
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M264 96L120 96C106.7 96 96 106.7 96 120L96 264C96 273.7 101.8 282.5 110.8 286.2C119.8 289.9 130.1 287.8 137 281L177 241L256 320L177 399L137 359C130.1 352.1 119.8 350.1 110.8 353.8C101.8 357.5 96 366.3 96 376L96 520C96 533.3 106.7 544 120 544L264 544C273.7 544 282.5 538.2 286.2 529.2C289.9 520.2 287.9 509.9 281 503L241 463L320 384L399 463L359 503C352.1 509.9 350.1 520.2 353.8 529.2C357.5 538.2 366.3 544 376 544L520 544C533.3 544 544 533.3 544 520L544 376C544 366.3 538.2 357.5 529.2 353.8C520.2 350.1 509.9 352.1 503 359L463 399L384 320L463 241L503 281C509.9 287.9 520.2 289.9 529.2 286.2C538.2 282.5 544 273.7 544 264L544 120C544 106.7 533.3 96 520 96L376 96C366.3 96 357.5 101.8 353.8 110.8C350.1 119.8 352.2 130.1 359 137L399 177L320 256L241 177L281 137C287.9 130.1 289.9 119.8 286.2 110.8C282.5 101.8 273.7 96 264 96z"/></svg>');
594
+ }
595
+
596
+ .icon-minimize {
597
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M520 288L376 288C362.7 288 352 277.3 352 264L352 120C352 110.3 357.8 101.5 366.8 97.8C375.8 94.1 386.1 96.2 393 103L433 143L506.4 69.6C510 66 514.9 64 520 64C525.1 64 530 66 533.7 69.7L570.4 106.4C574 110 576 114.9 576 120C576 125.1 574 130 570.3 133.7L497 207L537 247C543.9 253.9 545.9 264.2 542.2 273.2C538.5 282.2 529.7 288 520 288zM520 352C529.7 352 538.5 357.8 542.2 366.8C545.9 375.8 543.9 386.1 537 393L497 433L570.4 506.4C574 510 576.1 514.9 576.1 520.1C576.1 525.3 574.1 530.1 570.4 533.8L533.7 570.5C530 574 525.1 576 520 576C514.9 576 510 574 506.3 570.3L433 497L393 537C386.1 543.9 375.8 545.9 366.8 542.2C357.8 538.5 352 529.7 352 520L352 376C352 362.7 362.7 352 376 352L520 352zM264 352C277.3 352 288 362.7 288 376L288 520C288 529.7 282.2 538.5 273.2 542.2C264.2 545.9 253.9 543.9 247 537L207 497L133.6 570.4C130 574 125.1 576 120 576C114.9 576 110 574 106.3 570.3L69.7 533.7C66 530 64 525.1 64 520C64 514.9 66 510 69.7 506.3L143 433L103 393C96.1 386.1 94.1 375.8 97.8 366.8C101.5 357.8 110.3 352 120 352L264 352zM120 288C110.3 288 101.5 282.2 97.8 273.2C94.1 264.2 96.2 253.9 103 247L143 207L69.7 133.7C66 130 64 125.1 64 120C64 114.9 66 110 69.7 106.3L106.3 69.7C110 66 114.9 64 120 64C125.1 64 130 66 133.7 69.7L207 143L247 103C253.9 96.1 264.2 94.1 273.2 97.8C282.2 101.5 288 110.3 288 120L288 264C288 277.3 277.3 288 264 288L120 288z"/></svg>');
598
+ }
599
+
600
+ .icon-volume {
601
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M112 416L160 416L294.1 535.2C300.5 540.9 308.7 544 317.2 544C336.4 544 352 528.4 352 509.2L352 130.8C352 111.6 336.4 96 317.2 96C308.7 96 300.5 99.1 294.1 104.8L160 224L112 224C85.5 224 64 245.5 64 272L64 368C64 394.5 85.5 416 112 416zM505.1 171C494.8 162.6 479.7 164.2 471.3 174.5C462.9 184.8 464.5 199.9 474.8 208.3C507.3 234.7 528 274.9 528 320C528 365.1 507.3 405.3 474.8 431.8C464.5 440.2 463 455.3 471.3 465.6C479.6 475.9 494.8 477.4 505.1 469.1C548.3 433.9 576 380.2 576 320.1C576 260 548.3 206.3 505.1 171.1zM444.6 245.5C434.3 237.1 419.2 238.7 410.8 249C402.4 259.3 404 274.4 414.3 282.8C425.1 291.6 432 305 432 320C432 335 425.1 348.4 414.3 357.3C404 365.7 402.5 380.8 410.8 391.1C419.1 401.4 434.3 402.9 444.6 394.6C466.1 376.9 480 350.1 480 320C480 289.9 466.1 263.1 444.5 245.5z"/></svg>');
602
+ }
603
+
604
+ .icon-mute {
605
+ 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>');
606
+ }
607
+
608
+ @media (max-width: 620px) {
609
+ .top-bar {
610
+ align-items: flex-start;
611
+ flex-direction: column;
612
+ gap: 2px;
613
+ min-height: 70px;
614
+ }
615
+
616
+ .control-row {
617
+ align-items: stretch;
618
+ flex-direction: column;
619
+ }
620
+
621
+ .left-controls,
622
+ .right-controls {
623
+ flex-wrap: wrap;
624
+ }
625
+
626
+ .volume {
627
+ flex: 1;
628
+ }
629
+
630
+ .volume input {
631
+ width: 100%;
632
+ min-width: 88px;
633
+ }
634
+ }
635
+ </style>
@@ -5,6 +5,7 @@ import { generate } from "./generate.js";
5
5
  import { parseSfc } from "./parseSfc.js";
6
6
  import { parseTemplate } from "./parseTemplate.js";
7
7
  import { createSourceMap } from "./sourceMap.js";
8
+ import { assertTemplateTypeCheck } from "./templateTypeCheck.js";
8
9
  import { emitDebugDiagnostic } from "../runtime/devtools.js";
9
10
  export function compile(source, options = {}) {
10
11
  try {
@@ -15,6 +16,7 @@ export function compile(source, options = {}) {
15
16
  offset: descriptor.templateOffset
16
17
  });
17
18
  emitCompatDirectiveDiagnostics(ast, { debug: options.debug === true, filename: options.filename, phase: "compile" });
19
+ const templateTypeCheck = options.templateTypeCheck === true ? assertTemplateTypeCheck(descriptor, ast) : undefined;
18
20
  if (options.debug === true && descriptor.style?.trim()) {
19
21
  const styleResult = compileDescriptorStyle(descriptor, descriptor.styleScoped ? `data-mikuru-scope-preview` : undefined);
20
22
  for (const diagnostic of styleResult.diagnostics) {
@@ -29,14 +31,19 @@ export function compile(source, options = {}) {
29
31
  }
30
32
  }
31
33
  const bindings = analyzeTemplate(ast, { source, filename: options.filename });
32
- const code = generate(descriptor, ast, { debug: options.debug === true, batchedUpdates: options.batchedUpdates === true });
34
+ const code = generate(descriptor, ast, {
35
+ debug: options.debug === true,
36
+ batchedUpdates: options.batchedUpdates === true,
37
+ externalStyles: options.externalStyles === true
38
+ });
33
39
  const map = createSourceMap(code, descriptor, ast);
34
40
  return {
35
41
  code,
36
42
  map,
37
43
  descriptor,
38
44
  ast,
39
- bindings
45
+ bindings,
46
+ templateTypeCheck
40
47
  };
41
48
  }
42
49
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,UAAU,OAAO,CAAC,MAAc,EAAE,UAA0B,EAAE;IAClE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,aAAa,CAAC,UAAU,CAAC,QAAQ,EAAE;YAC7C,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM;YACN,MAAM,EAAE,UAAU,CAAC,cAAc;SAClC,CAAC,CAAC;QACH,8BAA8B,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACrH,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;YACvD,MAAM,WAAW,GAAG,sBAAsB,CAAC,UAAU,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACzH,KAAK,MAAM,UAAU,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;gBACjD,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE;oBACpE,KAAK,EAAE,OAAO;oBACd,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,KAAK,EAAE,UAAU,CAAC,KAAK;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC,CAAC;QAC3H,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;QAEnD,OAAO;YACL,IAAI;YACJ,GAAG;YACH,UAAU;YACV,GAAG;YACH,QAAQ;SACT,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAC/F,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK;SACN,CAAC,CAAC;QACH,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/compiler/compile.ts"],"names":[],"mappings":"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"}