mulmocast-viewer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  **MulmoCast Viewer** is a Vue 3 component library for playing and displaying bundles (JSON and media files) generated by mulmocast-cli in a browser.
4
4
 
5
+ > **Note**: For application-specific features (ListView, Digest mode, mobile optimization, etc.), see [APP_FEATURES.md](./APP_FEATURES.md).
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
@@ -137,9 +139,169 @@ const basePath = 'https://example.com/bundle_demo'
137
139
 
138
140
  MulmoViewer references media files (images, audio, video) relative to this `basePath`.
139
141
 
142
+ ## Additional Components
143
+
144
+ ### BeatGridView & BeatListView
145
+
146
+ Display a list of beats in grid or list format. These components are perfect for creating a beat catalog or overview page.
147
+
148
+ #### Simplest Usage
149
+
150
+ ```vue
151
+ <template>
152
+ <div>
153
+ <BeatGridView
154
+ :beats="beatsWithIndex"
155
+ base-path="/my-content"
156
+ text-lang="en"
157
+ />
158
+ </div>
159
+ </template>
160
+
161
+ <script setup lang="ts">
162
+ import { computed } from 'vue'
163
+ import { BeatGridView } from 'mulmocast-viewer'
164
+ import 'mulmocast-viewer/style.css'
165
+
166
+ import data from './path/to/mulmo_view.json'
167
+
168
+ // Transform beats array to include original indices
169
+ const beatsWithIndex = computed(() =>
170
+ data.beats.map((beat, index) => ({ beat, originalIndex: index }))
171
+ )
172
+ </script>
173
+ ```
174
+
175
+ #### With Router Integration
176
+
177
+ For Vue Router applications, pass a link builder function and RouterLink component:
178
+
179
+ ```vue
180
+ <template>
181
+ <div>
182
+ <BeatGridView
183
+ :beats="beatsWithIndex"
184
+ base-path="/my-content"
185
+ text-lang="en"
186
+ :link-url-builder="buildBeatUrl"
187
+ :link-component="RouterLink"
188
+ />
189
+ </div>
190
+ </template>
191
+
192
+ <script setup lang="ts">
193
+ import { computed } from 'vue'
194
+ import { RouterLink } from 'vue-router'
195
+ import { BeatGridView } from 'mulmocast-viewer'
196
+ import 'mulmocast-viewer/style.css'
197
+
198
+ import data from './path/to/mulmo_view.json'
199
+
200
+ const beatsWithIndex = computed(() =>
201
+ data.beats.map((beat, index) => ({ beat, originalIndex: index }))
202
+ )
203
+
204
+ // Simple function to build URLs - no HTML needed!
205
+ const buildBeatUrl = (index: number) => {
206
+ return `/viewer/${index}`
207
+ }
208
+ </script>
209
+ ```
210
+
211
+ **Key Points:**
212
+ - `beats`: Array of `{ beat: BundleItem, originalIndex: number }` - preserves original indices for linking
213
+ - `basePath`: Base path for images (e.g., `/my-content` → images at `/my-content/1.jpg`, `/my-content/2.jpg`, etc.)
214
+ - `textLang`: Language for text display
215
+ - `linkUrlBuilder`: Optional function `(index: number) => string` - returns URL for each beat
216
+ - `linkComponent`: Optional component for links - use `RouterLink` for Vue Router, or `'a'` (default) for regular links
217
+
218
+ **BeatListView** has the same API but displays beats in a newspaper-style layout with text wrapping around images.
219
+
220
+ ### MulmoViewerHeader
221
+
222
+ A shared header component with language/speed controls and mobile settings modal.
223
+
224
+ #### Simplest Usage
225
+
226
+ ```vue
227
+ <template>
228
+ <MulmoViewerHeader
229
+ v-model:audio-lang="audioLang"
230
+ v-model:text-lang="textLang"
231
+ v-model:playback-speed="playbackSpeed"
232
+ v-model:show-mobile-settings="showSettings"
233
+ >
234
+ <template #left>
235
+ <h1>My Viewer</h1>
236
+ </template>
237
+ </MulmoViewerHeader>
238
+ </template>
239
+
240
+ <script setup lang="ts">
241
+ import { ref } from 'vue'
242
+ import { MulmoViewerHeader } from 'mulmocast-viewer'
243
+ import 'mulmocast-viewer/style.css'
244
+
245
+ const audioLang = ref('en')
246
+ const textLang = ref('en')
247
+ const playbackSpeed = ref(1)
248
+ const showSettings = ref(false)
249
+ </script>
250
+ ```
251
+
252
+ #### With Custom Actions
253
+
254
+ ```vue
255
+ <template>
256
+ <MulmoViewerHeader
257
+ v-model:audio-lang="audioLang"
258
+ v-model:text-lang="textLang"
259
+ v-model:playback-speed="playbackSpeed"
260
+ v-model:show-mobile-settings="showSettings"
261
+ :sticky="true"
262
+ >
263
+ <template #left>
264
+ <h1>Beat Viewer</h1>
265
+ </template>
266
+
267
+ <template #actions>
268
+ <button @click="handlePlay">Play All</button>
269
+ <button @click="toggleDigest">Digest</button>
270
+ </template>
271
+
272
+ <template #mobile-actions>
273
+ <button @click="showSettings = true">⚙️</button>
274
+ </template>
275
+ </MulmoViewerHeader>
276
+ </template>
277
+
278
+ <script setup lang="ts">
279
+ import { ref } from 'vue'
280
+ import { MulmoViewerHeader } from 'mulmocast-viewer'
281
+ import 'mulmocast-viewer/style.css'
282
+
283
+ const audioLang = ref('en')
284
+ const textLang = ref('en')
285
+ const playbackSpeed = ref(1)
286
+ const showSettings = ref(false)
287
+
288
+ const handlePlay = () => { /* ... */ }
289
+ const toggleDigest = () => { /* ... */ }
290
+ </script>
291
+ ```
292
+
293
+ **Key Points:**
294
+ - All language/speed controls are built-in with v-model bindings
295
+ - `#left` slot: For title or custom content on the left
296
+ - `#actions` slot: For custom buttons/controls (desktop)
297
+ - `#mobile-actions` slot: For mobile-only buttons
298
+ - `sticky`: Makes header sticky at top
299
+ - `showSpeedControl`, `showAudioLang`, `hideDesktopControls`: Control visibility of built-in controls
300
+ - Mobile settings modal is automatically included and managed via `v-model:show-mobile-settings`
301
+
140
302
  ## API Reference
141
303
 
142
- ### Props
304
+ ### MulmoViewer Props
143
305
 
144
306
  | Prop | Type | Required | Default | Description |
145
307
  |------|------|----------|---------|-------------|
@@ -148,14 +310,15 @@ MulmoViewer references media files (images, audio, video) relative to this `base
148
310
  | `initPage` | `number` | No | `0` | Initial page to display |
149
311
  | `audioLang` | `string` | No | `'en'` | Audio language |
150
312
  | `textLang` | `string` | No | `'en'` | Text language |
313
+ | `playbackSpeed` | `number` | No | `1` | Playback speed (1, 1.25, 1.5, 1.75, 2) |
151
314
 
152
- ### Events
315
+ ### MulmoViewer Events
153
316
 
154
317
  | Event | Parameters | Description |
155
318
  |-------|------------|-------------|
156
319
  | `updatedPage` | `nextPage: number` | Emitted when the page is changed |
157
320
 
158
- ### Slot Props (for Custom UI)
321
+ ### MulmoViewer Slot Props (for Custom UI)
159
322
 
160
323
  The default slot exposes the following properties and components:
161
324
 
@@ -171,6 +334,43 @@ The default slot exposes the following properties and components:
171
334
  | `textLang` | `Ref<string>` | Text language (mutable) |
172
335
  | `SelectLanguage` | `Component` | Language selection component |
173
336
 
337
+ ### BeatGridView / BeatListView Props
338
+
339
+ | Prop | Type | Required | Default | Description |
340
+ |------|------|----------|---------|-------------|
341
+ | `beats` | `Array<{ beat: BundleItem, originalIndex: number }>` | Yes | - | Array of beats with original indices |
342
+ | `basePath` | `string` | No | `''` | Base path for images |
343
+ | `textLang` | `string` | No | `'en'` | Text language |
344
+ | `linkUrlBuilder` | `(index: number) => string` | No | - | Function to generate link URLs |
345
+ | `linkComponent` | `string \| Component` | No | `'a'` | Link component (e.g., RouterLink or 'a') |
346
+
347
+ ### BeatGridView / BeatListView Events
348
+
349
+ | Event | Parameters | Description |
350
+ |-------|------------|-------------|
351
+ | `beat-click` | `index: number` | Emitted when a beat is clicked |
352
+
353
+ ### MulmoViewerHeader Props
354
+
355
+ | Prop | Type | Required | Default | Description |
356
+ |------|------|----------|---------|-------------|
357
+ | `audioLang` | `string` | Yes | - | Audio language (v-model) |
358
+ | `textLang` | `string` | Yes | - | Text language (v-model) |
359
+ | `playbackSpeed` | `number` | No | `1` | Playback speed (v-model) |
360
+ | `showMobileSettings` | `boolean` | No | `false` | Mobile settings modal visibility (v-model) |
361
+ | `showSpeedControl` | `boolean` | No | `true` | Show speed control |
362
+ | `showAudioLang` | `boolean` | No | `true` | Show audio language control |
363
+ | `hideDesktopControls` | `boolean` | No | `false` | Hide desktop controls |
364
+ | `sticky` | `boolean` | No | `false` | Make header sticky |
365
+
366
+ ### MulmoViewerHeader Slots
367
+
368
+ | Slot | Description |
369
+ |------|-------------|
370
+ | `left` | Content for left side (title, logo, etc.) |
371
+ | `actions` | Custom action buttons (desktop) |
372
+ | `mobile-actions` | Custom action buttons (mobile only) |
373
+
174
374
  ## For Developers
175
375
 
176
376
  This repository provides a development environment for the viewer component.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  import { default as MulmoViewer } from './components/mulmo_viewer.vue';
2
2
  import { default as SelectLanguage } from './components/select_language.vue';
3
- export { MulmoViewer, SelectLanguage };
3
+ import { default as MulmoViewerHeader } from './components/mulmo_viewer_header.vue';
4
+ import { default as BeatGridView } from './components/beat_grid_view.vue';
5
+ import { default as BeatListView } from './components/beat_list_view.vue';
6
+ export { MulmoViewer, SelectLanguage, MulmoViewerHeader, BeatGridView, BeatListView };
@@ -1 +1 @@
1
- /*! tailwindcss v4.1.15 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-xl:80rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--font-weight-medium:500;--font-weight-bold:700;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.right-8{right:calc(var(--spacing)*8)}.bottom-2{bottom:calc(var(--spacing)*2)}.bottom-8{bottom:calc(var(--spacing)*8)}.left-1\/2{left:50%}.z-50{z-index:50}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.h-4{height:calc(var(--spacing)*4)}.h-6\!{height:calc(var(--spacing)*6)!important}.h-auto{height:auto}.h-full{height:100%}.max-h-\[80vh\]{max-height:80vh}.max-h-full{max-height:100%}.w-4{width:calc(var(--spacing)*4)}.w-30{width:calc(var(--spacing)*30)}.w-auto{width:auto}.w-full{width:100%}.max-w-7xl{max-width:var(--container-7xl)}.max-w-full{max-width:100%}.max-w-screen-xl{max-width:var(--breakpoint-xl)}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.gap-8{gap:calc(var(--spacing)*8)}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.bg-black{background-color:var(--color-black)}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black)60%,transparent)}}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-500{background-color:var(--color-gray-500)}.bg-gray-600{background-color:var(--color-gray-600)}.bg-indigo-600{background-color:var(--color-indigo-600)}.object-contain{object-fit:contain}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.p-10{padding:calc(var(--spacing)*10)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.text-center{text-align:center}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.text-gray-800{color:var(--color-gray-800)}.text-white{color:var(--color-white)}.opacity-0\!{opacity:0!important}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:bg-black\/80:hover{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/80:hover{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}.hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}}.mulmocast-video::-webkit-media-controls-enclosure{background-color:#00000080!important;border-radius:0!important}.mulmocast-video::-webkit-media-controls-current-time-display{-webkit-text-fill-color:#fff!important}.mulmocast-video::-webkit-media-controls-time-remaining-display{-webkit-text-fill-color:#fff!important}.mulmocast-video::-webkit-media-controls-play-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-mute-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-overlay-play-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-fullscreen-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls{opacity:0;transition:opacity .3s}.mulmocast-video:hover::-webkit-media-controls{opacity:1}.mulmocast-audio::-webkit-media-controls-enclosure{background-color:#00000080!important;border-radius:0!important}.mulmocast-audio::-webkit-media-controls-current-time-display{-webkit-text-fill-color:#fff!important}.mulmocast-audio::-webkit-media-controls-time-remaining-display{-webkit-text-fill-color:#fff!important}.mulmocast-audio::-webkit-media-controls-play-button{filter:brightness(1.1)}.mulmocast-audio::-webkit-media-controls-mute-button{filter:brightness(1.1)}.mulmocast-audio::-webkit-media-controls{opacity:0;transition:opacity .3s}.mulmocast-audio:hover::-webkit-media-controls{opacity:1}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-2xl:1rem;--aspect-video:16/9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.top-2{top:calc(var(--spacing)*2)}.right-0{right:calc(var(--spacing)*0)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-2{bottom:calc(var(--spacing)*2)}.left-0{left:calc(var(--spacing)*0)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.z-50{z-index:50}.float-left{float:left}.clear-both{clear:both}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-4{margin-right:calc(var(--spacing)*4)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.table{display:table}.aspect-video{aspect-ratio:var(--aspect-video)}.h-4{height:calc(var(--spacing)*4)}.h-6\!{height:calc(var(--spacing)*6)!important}.h-auto{height:auto}.h-full{height:100%}.max-h-\[80vh\]{max-height:80vh}.max-h-full{max-height:100%}.w-4{width:calc(var(--spacing)*4)}.w-30{width:calc(var(--spacing)*30)}.w-64{width:calc(var(--spacing)*64)}.w-auto{width:auto}.w-full{width:100%}.max-w-7xl{max-width:var(--container-7xl)}.max-w-full{max-width:100%}.flex-shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-t-2xl{border-top-left-radius:var(--radius-2xl);border-top-right-radius:var(--radius-2xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.bg-amber-600{background-color:var(--color-amber-600)}.bg-black{background-color:var(--color-black)}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black)60%,transparent)}}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-500{background-color:var(--color-gray-500)}.bg-gray-600{background-color:var(--color-gray-600)}.bg-green-600{background-color:var(--color-green-600)}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-red-600{background-color:var(--color-red-600)}.bg-white{background-color:var(--color-white)}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-10{padding:calc(var(--spacing)*10)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-8{padding-block:calc(var(--spacing)*8)}.py-12{padding-block:calc(var(--spacing)*12)}.text-center{text-align:center}.text-left{text-align:left}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-red-600{color:var(--color-red-600)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.opacity-0\!{opacity:0!important}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}@media(hover:hover){.group-hover\:text-indigo-600:is(:where(.group):hover *){color:var(--color-indigo-600)}.hover\:border-gray-400:hover{border-color:var(--color-gray-400)}.hover\:border-indigo-400:hover{border-color:var(--color-indigo-400)}.hover\:bg-amber-700:hover{background-color:var(--color-amber-700)}.hover\:bg-black\/80:hover{background-color:#000c}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/80:hover{background-color:color-mix(in oklab,var(--color-black)80%,transparent)}}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:opacity-80:hover{opacity:.8}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\:shadow-xl:hover{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:border-indigo-500:focus{border-color:var(--color-indigo-500)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-indigo-200:focus{--tw-ring-color:var(--color-indigo-200)}.focus\:ring-indigo-500:focus{--tw-ring-color:var(--color-indigo-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:40rem){.sm\:block{display:block}.sm\:flex{display:flex}.sm\:hidden{display:none}.sm\:inline-block{display:inline-block}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:gap-4{gap:calc(var(--spacing)*4)}.sm\:py-4{padding-block:calc(var(--spacing)*4)}.sm\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}}@media(min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:80rem){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}}.mulmocast-video::-webkit-media-controls-enclosure{background-color:#00000080!important;border-radius:0!important}.mulmocast-video::-webkit-media-controls-current-time-display{-webkit-text-fill-color:#fff!important}.mulmocast-video::-webkit-media-controls-time-remaining-display{-webkit-text-fill-color:#fff!important}.mulmocast-video::-webkit-media-controls-play-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-mute-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-overlay-play-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls-fullscreen-button{filter:brightness(1.1)}.mulmocast-video::-webkit-media-controls{opacity:0;transition:opacity .3s}.mulmocast-video:hover::-webkit-media-controls{opacity:1}.mulmocast-audio::-webkit-media-controls-enclosure{background-color:#00000080!important;border-radius:0!important}.mulmocast-audio::-webkit-media-controls-current-time-display{-webkit-text-fill-color:#fff!important}.mulmocast-audio::-webkit-media-controls-time-remaining-display{-webkit-text-fill-color:#fff!important}.mulmocast-audio::-webkit-media-controls-play-button{filter:brightness(1.1)}.mulmocast-audio::-webkit-media-controls-mute-button{filter:brightness(1.1)}.mulmocast-audio::-webkit-media-controls{opacity:0;transition:opacity .3s}.mulmocast-audio:hover::-webkit-media-controls{opacity:1}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}
@@ -1,14 +1,20 @@
1
- import { defineComponent as $, ref as m, createElementBlock as i, openBlock as u, createTextVNode as H, createElementVNode as d, createCommentVNode as R, toDisplayString as C, Fragment as N, renderList as I, computed as x, renderSlot as O, withDirectives as q, normalizeProps as W, guardReactiveProps as G, createVNode as J, mergeProps as j, unref as K, createBlock as Q, vShow as U } from "vue";
2
- const B = async (t) => await new Promise((S) => setTimeout(S, t)), X = { class: "items-center justify-center w-full" }, Y = { key: 0 }, Z = ["src"], ee = {
1
+ import { defineComponent as M, ref as w, watch as T, onMounted as q, onUnmounted as Z, createElementBlock as d, openBlock as u, createCommentVNode as b, createElementVNode as a, toDisplayString as $, Fragment as V, renderList as G, computed as B, renderSlot as W, withDirectives as I, normalizeProps as J, guardReactiveProps as ee, createVNode as D, mergeProps as K, unref as te, createBlock as O, vShow as ae, normalizeClass as oe, withModifiers as le, resolveDynamicComponent as Q, withCtx as X } from "vue";
2
+ const F = async (e) => await new Promise((v) => setTimeout(v, e)), ne = { class: "items-center justify-center w-full" }, se = { key: 0 }, ie = ["src"], ue = {
3
3
  key: 1,
4
4
  class: "relative inline-block"
5
- }, ae = ["src"], te = ["src"], oe = {
5
+ }, de = ["src"], re = ["src"], ce = {
6
6
  key: 2,
7
7
  class: "relative inline-block"
8
- }, ue = ["src"], ne = ["src"], ie = {
8
+ }, ve = ["src"], ge = ["src"], me = {
9
9
  key: 3,
10
10
  class: "relative inline-block"
11
- }, le = ["src"], se = { key: 4 }, ce = "https://github.com/receptron/mulmocast-cli/blob/main/assets/images/mulmocast_credit.png?raw=true", L = /* @__PURE__ */ $({
11
+ }, fe = ["src"], pe = { key: 4 }, ye = {
12
+ key: 5,
13
+ class: "mt-4 px-6 py-4 text-left"
14
+ }, he = { class: "text-lg leading-relaxed font-sans text-gray-800" }, be = {
15
+ key: 0,
16
+ class: "text-base leading-relaxed font-sans text-gray-400 mt-3 italic"
17
+ }, xe = "https://github.com/receptron/mulmocast-cli/blob/main/assets/images/mulmocast_credit.png?raw=true", H = /* @__PURE__ */ M({
12
18
  __name: "mulmo_player",
13
19
  props: {
14
20
  index: {},
@@ -18,234 +24,532 @@ const B = async (t) => await new Promise((S) => setTimeout(S, t)), X = { class:
18
24
  imageSource: {},
19
25
  audioSource: {},
20
26
  text: {},
21
- duration: {}
27
+ originalText: {},
28
+ duration: {},
29
+ defaultLang: {},
30
+ currentLang: {},
31
+ playbackSpeed: { default: 1 }
22
32
  },
23
33
  emits: ["play", "pause", "ended"],
24
- setup(t, { expose: S, emit: _ }) {
25
- const n = t, c = _, l = m(), a = m(), o = m(), g = m(), f = m(), p = () => {
26
- o.value && a.value && (o.value.currentTime = a.value.currentTime, o.value.currentTime === a.value.currentTime && o.value.play()), c("play");
27
- }, k = (v) => {
28
- !a.value?.ended && o?.value && o.value?.pause(), console.log(v), b(v);
29
- }, w = () => {
30
- !o.value?.paused && !o.value?.ended && (o.value?.currentTime ?? 0) > 0 || P();
31
- }, r = () => {
32
- !a.value?.paused && !a.value?.ended && (a.value?.currentTime ?? 0) > 0 || P();
33
- }, h = () => {
34
- c("play");
35
- }, b = (v) => {
36
- const y = v.target;
37
- y.duration !== y.currentTime && c("pause");
38
- }, P = () => {
39
- c("ended");
34
+ setup(e, { expose: v, emit: t }) {
35
+ const o = e, f = t, m = w(), s = w(), r = w(), l = w(), g = w(), c = () => {
36
+ s.value && o.videoSource && (o.audioSource && o.currentLang && o.defaultLang && o.currentLang !== o.defaultLang ? s.value.volume = 0.2 : s.value.volume = 0);
37
+ }, i = () => {
38
+ const p = o.playbackSpeed ?? 1;
39
+ m.value && (m.value.playbackRate = p), s.value && (s.value.playbackRate = p), r.value && (r.value.playbackRate = p), l.value && (l.value.playbackRate = p);
40
40
  };
41
- return S({
42
- play: async () => {
43
- l.value && l.value.play(), a.value && a.value.play(), g.value && g.value.play(), !l.value && !a.value && !g.value && (await B((n.duration ?? 0) * 1e3), c("ended"));
41
+ T([() => o.currentLang, () => o.defaultLang, () => o.videoSource, () => o.audioSource], () => {
42
+ c();
43
+ }), T(
44
+ () => o.playbackSpeed,
45
+ () => {
46
+ i();
44
47
  }
45
- }), (v, y) => (u(), i("div", X, [
46
- t.videoWithAudioSource ? (u(), i("div", Y, [
47
- d("video", {
48
+ ), T(s, (p) => {
49
+ p && (c(), i());
50
+ }), T([m, r, l], () => {
51
+ i();
52
+ }), q(() => {
53
+ c(), i();
54
+ });
55
+ const P = () => {
56
+ h.value = !0, r.value && s.value && (r.value.currentTime = s.value.currentTime, r.value.currentTime === s.value.currentTime && r.value.play()), f("play");
57
+ }, L = (p) => {
58
+ document.hidden || (h.value = !1), !s.value?.ended && r?.value && r.value?.pause(), console.log(p), E(p);
59
+ }, x = () => {
60
+ !r.value?.paused && !r.value?.ended && (r.value?.currentTime ?? 0) > 0 || C();
61
+ }, _ = () => {
62
+ !s.value?.paused && !s.value?.ended && (s.value?.currentTime ?? 0) > 0 || C();
63
+ }, U = () => {
64
+ h.value = !0, f("play");
65
+ }, E = (p) => {
66
+ document.hidden || (h.value = !1);
67
+ const n = p.target;
68
+ n.duration !== n.currentTime && f("pause");
69
+ }, C = () => {
70
+ h.value = !1, f("ended");
71
+ }, h = w(!1);
72
+ let k = null;
73
+ const z = async () => {
74
+ h.value = !0, m.value && (i(), m.value.play()), s.value && (c(), i(), s.value.play(), r.value && (r.value.currentTime = s.value.currentTime, r.value.play())), l.value && (i(), l.value.play()), !m.value && !s.value && !l.value && (await F((o.duration ?? 0) * 1e3), h.value = !1, f("ended"));
75
+ }, R = () => {
76
+ h.value && (m.value?.paused && m.value.play().catch(() => {
77
+ }), s.value?.paused && s.value.play().catch(() => {
78
+ }), l.value?.paused && l.value.play().catch(() => {
79
+ }), r.value?.paused && r.value.play().catch(() => {
80
+ }));
81
+ }, N = () => {
82
+ document.hidden && h.value ? k || (k = setInterval(R, 500)) : document.hidden || k && (clearInterval(k), k = null);
83
+ }, S = () => {
84
+ document.hidden && h.value && setTimeout(R, 50);
85
+ };
86
+ return q(() => {
87
+ document.addEventListener("visibilitychange", N), m.value?.addEventListener("pause", S), s.value?.addEventListener("pause", S), l.value?.addEventListener("pause", S), r.value?.addEventListener("pause", S);
88
+ }), Z(() => {
89
+ document.removeEventListener("visibilitychange", N), m.value?.removeEventListener("pause", S), s.value?.removeEventListener("pause", S), l.value?.removeEventListener("pause", S), r.value?.removeEventListener("pause", S), k && (clearInterval(k), k = null);
90
+ }), v({
91
+ play: z
92
+ }), (p, n) => (u(), d("div", ne, [
93
+ e.videoWithAudioSource ? (u(), d("div", se, [
94
+ a("video", {
48
95
  ref_key: "videoWithAudioRef",
49
- ref: l,
50
- src: t.videoWithAudioSource,
96
+ ref: m,
97
+ src: e.videoWithAudioSource,
51
98
  class: "mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",
52
99
  controls: !0,
53
100
  playsinline: "true",
54
- onPlay: h,
55
- onPause: b,
56
- onEnded: P
57
- }, null, 40, Z)
58
- ])) : t.soundEffectSource || t.videoSource ? (u(), i("div", ee, [
59
- d("video", {
101
+ onPlay: U,
102
+ onPause: E,
103
+ onEnded: C
104
+ }, null, 40, ie)
105
+ ])) : e.soundEffectSource || e.videoSource ? (u(), d("div", ue, [
106
+ a("video", {
60
107
  ref_key: "videoRef",
61
- ref: a,
108
+ ref: s,
62
109
  class: "mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",
63
- src: t.soundEffectSource || t.videoSource,
110
+ src: e.soundEffectSource || e.videoSource,
64
111
  controls: !0,
65
112
  playsinline: "true",
66
- onPlay: p,
67
- onPause: k,
68
- onEnded: w
69
- }, null, 40, ae),
70
- t.audioSource ? (u(), i("audio", {
113
+ onPlay: P,
114
+ onPause: L,
115
+ onEnded: x
116
+ }, null, 40, de),
117
+ e.audioSource ? (u(), d("audio", {
71
118
  key: 0,
72
119
  ref_key: "audioSyncRef",
73
- ref: o,
74
- src: t.audioSource,
120
+ ref: r,
121
+ src: e.audioSource,
75
122
  controls: !0,
76
123
  class: "hidden",
77
- onEnded: r
78
- }, null, 40, te)) : R("", !0)
79
- ])) : t.audioSource ? (u(), i("div", oe, [
80
- t.imageSource ? (u(), i("img", {
124
+ onEnded: _
125
+ }, null, 40, re)) : b("", !0)
126
+ ])) : e.audioSource ? (u(), d("div", ce, [
127
+ e.imageSource ? (u(), d("img", {
81
128
  key: 0,
82
- src: t.imageSource,
129
+ src: e.imageSource,
83
130
  class: "mx-auto h-auto max-h-[80vh] w-auto object-contain",
84
131
  alt: "Background"
85
- }, null, 8, ue)) : (u(), i("img", {
132
+ }, null, 8, ve)) : (u(), d("img", {
86
133
  key: 1,
87
- src: ce,
134
+ src: xe,
88
135
  class: "mx-auto h-auto max-h-[80vh] w-auto object-contain",
89
136
  alt: "Background"
90
137
  })),
91
- d("audio", {
138
+ a("audio", {
92
139
  ref_key: "audioRef",
93
- ref: g,
140
+ ref: l,
94
141
  class: "mulmocast-audio absolute inset-0 w-full h-full",
95
- src: t.audioSource,
142
+ src: e.audioSource,
96
143
  controls: !0,
97
- onPlay: h,
98
- onPause: b,
99
- onEnded: P
100
- }, null, 40, ne)
101
- ])) : t.imageSource ? (u(), i("div", ie, [
102
- d("img", {
144
+ onPlay: U,
145
+ onPause: E,
146
+ onEnded: C
147
+ }, null, 40, ge)
148
+ ])) : e.imageSource ? (u(), d("div", me, [
149
+ a("img", {
103
150
  ref_key: "imageRef",
104
- ref: f,
105
- src: t.imageSource,
151
+ ref: g,
152
+ src: e.imageSource,
106
153
  class: "max-w-full max-h-full object-contain"
107
- }, null, 8, le)
108
- ])) : (u(), i("div", se, "No media available")),
109
- H(" " + C(t.text), 1)
154
+ }, null, 8, fe)
155
+ ])) : (u(), d("div", pe, "No media available")),
156
+ e.text ? (u(), d("div", ye, [
157
+ a("p", he, $(e.text), 1),
158
+ e.originalText && e.originalText !== e.text ? (u(), d("p", be, $(e.originalText), 1)) : b("", !0)
159
+ ])) : b("", !0)
110
160
  ]));
111
161
  }
112
- }), de = ["value"], re = ["value"], ve = /* @__PURE__ */ $({
162
+ }), ke = ["value"], Se = ["value"], j = /* @__PURE__ */ M({
113
163
  __name: "select_language",
114
164
  props: {
115
165
  modelValue: {}
116
166
  },
117
167
  emits: ["update:modelValue"],
118
- setup(t, { emit: S }) {
119
- const _ = ["en", "ja"], n = S, c = (l) => {
120
- const a = l.target;
121
- n("update:modelValue", a.value);
168
+ setup(e, { emit: v }) {
169
+ const t = ["en", "ja"], o = {
170
+ en: "English",
171
+ ja: "日本語"
172
+ }, f = v, m = (s) => {
173
+ const r = s.target;
174
+ f("update:modelValue", r.value);
122
175
  };
123
- return (l, a) => (u(), i("select", {
124
- value: t.modelValue,
125
- onChange: c
176
+ return (s, r) => (u(), d("select", {
177
+ value: e.modelValue,
178
+ class: "px-4 py-2 bg-white border-2 border-gray-300 rounded-lg shadow-sm hover:border-indigo-400 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 focus:outline-none transition-colors cursor-pointer text-base font-medium text-gray-700",
179
+ onChange: m
126
180
  }, [
127
- (u(), i(N, null, I(_, (o) => d("option", {
128
- key: o,
129
- value: o
130
- }, C(o), 9, re)), 64))
131
- ], 40, de));
181
+ (u(), d(V, null, G(t, (l) => a("option", {
182
+ key: l,
183
+ value: l
184
+ }, $(o[l] || l), 9, Se)), 64))
185
+ ], 40, ke));
132
186
  }
133
- }), me = { class: "w-full overflow-hidden" }, ge = { class: "max-w-7xl mx-auto px-4" }, fe = { class: "flex items-center justify-between" }, he = ["disabled"], ye = { class: "px-4" }, Se = ["disabled"], Pe = ["src"], pe = /* @__PURE__ */ $({
187
+ }), we = { class: "w-full overflow-hidden" }, $e = { class: "max-w-7xl mx-auto px-4" }, Le = { class: "flex items-center justify-between" }, Pe = ["disabled"], Ce = { class: "px-4" }, Be = ["disabled"], Ee = ["src"], it = /* @__PURE__ */ M({
134
188
  __name: "mulmo_viewer",
135
189
  props: {
136
190
  dataSet: {},
137
191
  basePath: {},
138
192
  initPage: {},
139
193
  audioLang: { default: "en" },
140
- textLang: { default: "en" }
194
+ textLang: { default: "en" },
195
+ playbackSpeed: { default: 1 }
141
196
  },
142
197
  emits: ["updatedPage", "update:audioLang", "update:textLang"],
143
- setup(t, { expose: S, emit: _ }) {
144
- const n = t, c = _, l = n.dataSet?.beats?.length ?? 0, a = m(n.initPage ?? 0), o = m(!0), g = m(), f = m(), p = x({
145
- get: () => n.audioLang,
146
- set: (e) => c("update:audioLang", e || "en")
147
- }), k = x({
148
- get: () => n.textLang,
149
- set: (e) => c("update:textLang", e || "en")
150
- }), w = x(() => n.dataSet?.beats[a.value]), r = (e) => e ? n.basePath + "/" + e : "", h = m(!1), b = () => {
151
- h.value = !0, f.value && f.value.play();
152
- }, P = () => {
153
- console.log("pause"), h.value = !1, f.value && f.value.pause();
198
+ setup(e, { expose: v, emit: t }) {
199
+ const o = e, f = t, m = o.dataSet?.beats?.length ?? 0, s = w(o.initPage ?? 0), r = w(!0), l = w(), g = w(), c = B({
200
+ get: () => o.audioLang,
201
+ set: (n) => f("update:audioLang", n || "en")
202
+ }), i = B({
203
+ get: () => o.textLang,
204
+ set: (n) => f("update:textLang", n || "en")
205
+ });
206
+ T(
207
+ () => o.audioLang,
208
+ async (n, y) => {
209
+ if (n !== y && x.value) {
210
+ const A = x.value;
211
+ x.value = !1, await F(500), A && l.value && (x.value = !0, await l.value.play());
212
+ }
213
+ }
214
+ ), T(
215
+ () => o.textLang,
216
+ async (n, y) => {
217
+ n !== y && x.value && (await F(100), l.value && await l.value.play());
218
+ }
219
+ );
220
+ const P = B(() => o.dataSet?.beats[s.value]), L = (n) => n ? o.basePath + "/" + n : "", x = w(!1), _ = () => {
221
+ x.value = !0, g.value && g.value.play();
222
+ }, U = () => {
223
+ console.log("pause"), x.value = !1, g.value && g.value.pause();
154
224
  }, E = async () => {
155
- await B(500), g.value && g.value.play();
156
- }, v = (e) => {
157
- a.value !== e && (a.value = e, h.value && o.value && E());
158
- }, y = (e) => {
159
- const s = a.value + e;
160
- return s > -1 && s < l ? (v(s), c("updatedPage", s), !0) : !1;
161
- }, V = () => {
162
- console.log("end"), o.value && y(1) ? E() : (h.value = !1, f.value && f.value.pause());
163
- }, D = {
164
- onPlay: b,
165
- onPause: P,
166
- onEnded: V
167
- }, A = x(() => {
168
- const e = w.value, s = e?.audioSources?.[p.value];
225
+ await F(500), l.value && l.value.play();
226
+ }, C = (n) => {
227
+ s.value !== n && (s.value = n, x.value && r.value && E());
228
+ }, h = (n) => {
229
+ const y = s.value + n;
230
+ return y > -1 && y < m ? (C(y), f("updatedPage", y), !0) : !1;
231
+ }, k = () => {
232
+ console.log("end"), r.value && h(1) ? E() : (x.value = !1, g.value && g.value.pause());
233
+ }, z = {
234
+ onPlay: _,
235
+ onPause: U,
236
+ onEnded: k
237
+ }, R = B(() => {
238
+ const n = P.value, y = n?.audioSources?.[c.value], A = n?.multiLinguals?.[i.value] ?? n?.text ?? "", Y = o.dataSet?.lang ? n?.multiLinguals?.[o.dataSet.lang] ?? n?.text ?? "" : "";
169
239
  return {
170
- videoWithAudioSource: r(e?.videoWithAudioSource),
171
- videoSource: r(e?.videoSource),
172
- soundEffectSource: r(e?.soundEffectSource),
173
- audioSource: s ? n.basePath + "/" + s : "",
174
- imageSource: r(e?.imageSource),
175
- index: a.value,
176
- text: e?.multiLinguals?.[k.value] ?? e?.text ?? "",
177
- duration: e?.duration,
178
- ...D
240
+ videoWithAudioSource: L(n?.videoWithAudioSource),
241
+ videoSource: L(n?.videoSource),
242
+ soundEffectSource: L(n?.soundEffectSource),
243
+ audioSource: y ? o.basePath + "/" + y : "",
244
+ imageSource: L(n?.imageSource),
245
+ index: s.value,
246
+ text: A,
247
+ originalText: Y,
248
+ duration: n?.duration,
249
+ defaultLang: o.dataSet?.lang,
250
+ currentLang: c.value,
251
+ playbackSpeed: o.playbackSpeed,
252
+ ...z
179
253
  };
180
- }), F = x(() => n.dataSet?.beats[a.value + 1]), T = x(() => {
181
- if (a.value + 1 >= l) return null;
182
- const e = F.value;
254
+ }), N = B(() => o.dataSet?.beats[s.value + 1]), S = B(() => {
255
+ if (s.value + 1 >= m) return null;
256
+ const n = N.value;
183
257
  return {
184
- videoWithAudioSource: r(e?.videoWithAudioSource),
185
- videoSource: r(e?.videoSource),
186
- soundEffectSource: r(e?.soundEffectSource),
187
- audioSource: e?.audioSources?.[p.value] ? n.basePath + "/" + e.audioSources[p.value] : "",
188
- imageSource: r(e?.imageSource),
189
- index: a.value + 1,
190
- text: e?.multiLinguals?.[k.value] ?? e?.text ?? "",
191
- duration: e?.duration
258
+ videoWithAudioSource: L(n?.videoWithAudioSource),
259
+ videoSource: L(n?.videoSource),
260
+ soundEffectSource: L(n?.soundEffectSource),
261
+ audioSource: n?.audioSources?.[c.value] ? o.basePath + "/" + n.audioSources[c.value] : "",
262
+ imageSource: L(n?.imageSource),
263
+ index: s.value + 1,
264
+ text: n?.multiLinguals?.[i.value] ?? n?.text ?? "",
265
+ duration: n?.duration
192
266
  };
193
- }), M = x(() => ({
194
- MulmoPlayer: L,
195
- pageProps: A.value,
196
- currentPage: a.value,
197
- pageCount: l,
198
- pageMove: y,
199
- isPlaying: h.value,
200
- audioLang: p,
201
- textLang: k,
202
- SelectLanguage: ve,
203
- mediaPlayerRef: g,
267
+ }), p = B(() => ({
268
+ MulmoPlayer: H,
269
+ pageProps: R.value,
270
+ currentPage: s.value,
271
+ pageCount: m,
272
+ pageMove: h,
273
+ isPlaying: x.value,
274
+ audioLang: c,
275
+ textLang: i,
276
+ SelectLanguage: j,
277
+ mediaPlayerRef: l,
204
278
  // Event handlers for direct access
205
- handlePlay: b,
206
- handlePause: P,
207
- handleEnded: V
279
+ handlePlay: _,
280
+ handlePause: U,
281
+ handleEnded: k
208
282
  }));
209
- return S({
210
- updatePage: v
211
- }), (e, s) => (u(), i(N, null, [
212
- O(e.$slots, "default", W(G(M.value)), () => [
213
- d("div", me, [
214
- d("div", ge, [
215
- d("div", fe, [
216
- d("button", {
283
+ return v({
284
+ updatePage: C
285
+ }), (n, y) => (u(), d(V, null, [
286
+ W(n.$slots, "default", J(ee(p.value)), () => [
287
+ a("div", we, [
288
+ a("div", $e, [
289
+ a("div", Le, [
290
+ a("button", {
217
291
  class: "px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",
218
- disabled: a.value === 0,
219
- onClick: s[0] || (s[0] = (z) => y(-1))
220
- }, " Prev ", 8, he),
221
- d("div", ye, [
222
- J(L, j({
292
+ disabled: s.value === 0,
293
+ onClick: y[0] || (y[0] = (A) => h(-1))
294
+ }, " Prev ", 8, Pe),
295
+ a("div", Ce, [
296
+ D(H, K({
223
297
  ref_key: "mediaPlayer",
224
- ref: g
225
- }, A.value), null, 16)
298
+ ref: l
299
+ }, R.value), null, 16)
226
300
  ]),
227
- d("button", {
301
+ a("button", {
228
302
  class: "px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",
229
- disabled: a.value >= K(l) - 1,
230
- onClick: s[1] || (s[1] = (z) => y(1))
231
- }, " Next ", 8, Se)
303
+ disabled: s.value >= te(m) - 1,
304
+ onClick: y[1] || (y[1] = (A) => h(1))
305
+ }, " Next ", 8, Be)
232
306
  ])
233
307
  ])
234
308
  ])
235
309
  ]),
236
- T.value ? q((u(), Q(L, W(j({ key: 0 }, T.value)), null, 16)), [
237
- [U, !1]
238
- ]) : R("", !0),
239
- t.dataSet?.bgmFile ? (u(), i("audio", {
310
+ S.value ? I((u(), O(H, J(K({ key: 0 }, S.value)), null, 16)), [
311
+ [ae, !1]
312
+ ]) : b("", !0),
313
+ e.dataSet?.bgmFile ? (u(), d("audio", {
240
314
  key: 1,
241
315
  ref_key: "bgmRef",
242
- ref: f,
243
- src: t.dataSet?.bgmFile
244
- }, null, 8, Pe)) : R("", !0)
316
+ ref: g,
317
+ src: e.dataSet?.bgmFile
318
+ }, null, 8, Ee)) : b("", !0)
319
+ ], 64));
320
+ }
321
+ }), Te = { class: "container mx-auto px-4 py-2 sm:py-4" }, Ve = { class: "flex flex-col sm:flex-row justify-between items-start sm:items-center gap-2 sm:gap-4" }, Me = { class: "flex items-center gap-4 flex-wrap" }, Ue = { class: "flex items-center gap-2 sm:gap-4 flex-wrap w-full sm:w-auto" }, Re = {
322
+ key: 0,
323
+ class: "hidden sm:flex items-center gap-3"
324
+ }, Ae = ["value"], De = {
325
+ key: 1,
326
+ class: "hidden sm:flex items-center gap-3"
327
+ }, je = { class: "hidden sm:flex items-center gap-3" }, _e = { class: "flex items-center justify-between mb-4" }, Ne = {
328
+ key: 0,
329
+ class: "space-y-2"
330
+ }, We = ["value"], Fe = {
331
+ key: 1,
332
+ class: "space-y-2"
333
+ }, ze = { class: "space-y-2" }, ut = /* @__PURE__ */ M({
334
+ __name: "mulmo_viewer_header",
335
+ props: {
336
+ audioLang: {},
337
+ textLang: {},
338
+ playbackSpeed: { default: 1 },
339
+ showSpeedControl: { type: Boolean, default: !0 },
340
+ showAudioLang: { type: Boolean, default: !0 },
341
+ hideDesktopControls: { type: Boolean, default: !1 },
342
+ showMobileSettings: { type: Boolean, default: !1 },
343
+ sticky: { type: Boolean, default: !1 }
344
+ },
345
+ emits: ["update:audioLang", "update:textLang", "update:playbackSpeed", "update:showMobileSettings"],
346
+ setup(e) {
347
+ return (v, t) => (u(), d(V, null, [
348
+ a("div", {
349
+ class: oe(["bg-white shadow-md border-b border-gray-200", { "sticky top-0 z-50": e.sticky }])
350
+ }, [
351
+ a("div", Te, [
352
+ a("div", Ve, [
353
+ a("div", Me, [
354
+ W(v.$slots, "left")
355
+ ]),
356
+ a("div", Ue, [
357
+ W(v.$slots, "actions"),
358
+ e.hideDesktopControls ? b("", !0) : (u(), d(V, { key: 0 }, [
359
+ e.showSpeedControl ? (u(), d("div", Re, [
360
+ t[11] || (t[11] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide" }, "Speed:", -1)),
361
+ a("select", {
362
+ value: e.playbackSpeed,
363
+ class: "px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 font-medium shadow-sm hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors",
364
+ onChange: t[0] || (t[0] = (o) => v.$emit("update:playbackSpeed", Number(o.target.value)))
365
+ }, [...t[10] || (t[10] = [
366
+ a("option", { value: 1 }, "1x", -1),
367
+ a("option", { value: 1.25 }, "1.25x", -1),
368
+ a("option", { value: 1.5 }, "1.5x", -1),
369
+ a("option", { value: 1.75 }, "1.75x", -1),
370
+ a("option", { value: 2 }, "2x", -1)
371
+ ])], 40, Ae)
372
+ ])) : b("", !0),
373
+ e.showAudioLang ? (u(), d("div", De, [
374
+ t[12] || (t[12] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide" }, "Audio:", -1)),
375
+ D(j, {
376
+ "model-value": e.audioLang,
377
+ "onUpdate:modelValue": t[1] || (t[1] = (o) => v.$emit("update:audioLang", o))
378
+ }, null, 8, ["model-value"])
379
+ ])) : b("", !0),
380
+ a("div", je, [
381
+ t[13] || (t[13] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide" }, "Text:", -1)),
382
+ D(j, {
383
+ "model-value": e.textLang,
384
+ "onUpdate:modelValue": t[2] || (t[2] = (o) => v.$emit("update:textLang", o))
385
+ }, null, 8, ["model-value"])
386
+ ])
387
+ ], 64)),
388
+ W(v.$slots, "mobile-actions")
389
+ ])
390
+ ])
391
+ ])
392
+ ], 2),
393
+ e.showMobileSettings ? (u(), d("div", {
394
+ key: 0,
395
+ class: "fixed inset-0 bg-black bg-opacity-50 z-50 sm:hidden",
396
+ onClick: t[9] || (t[9] = (o) => v.$emit("update:showMobileSettings", !1))
397
+ }, [
398
+ a("div", {
399
+ class: "absolute bottom-0 left-0 right-0 bg-white rounded-t-2xl shadow-xl p-6 space-y-4",
400
+ onClick: t[8] || (t[8] = le(() => {
401
+ }, ["stop"]))
402
+ }, [
403
+ a("div", _e, [
404
+ t[14] || (t[14] = a("h2", { class: "text-xl font-bold text-gray-800" }, "Settings", -1)),
405
+ a("button", {
406
+ class: "text-gray-500 hover:text-gray-700 text-2xl",
407
+ onClick: t[3] || (t[3] = (o) => v.$emit("update:showMobileSettings", !1))
408
+ }, " × ")
409
+ ]),
410
+ e.showSpeedControl ? (u(), d("div", Ne, [
411
+ t[16] || (t[16] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide block" }, "Playback Speed", -1)),
412
+ a("select", {
413
+ value: e.playbackSpeed,
414
+ class: "w-full px-4 py-3 border border-gray-300 rounded-lg bg-white text-gray-700 font-medium shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500",
415
+ onChange: t[4] || (t[4] = (o) => v.$emit("update:playbackSpeed", Number(o.target.value)))
416
+ }, [...t[15] || (t[15] = [
417
+ a("option", { value: 1 }, "1x (Normal)", -1),
418
+ a("option", { value: 1.25 }, "1.25x", -1),
419
+ a("option", { value: 1.5 }, "1.5x", -1),
420
+ a("option", { value: 1.75 }, "1.75x", -1),
421
+ a("option", { value: 2 }, "2x (Double)", -1)
422
+ ])], 40, We)
423
+ ])) : b("", !0),
424
+ e.showAudioLang ? (u(), d("div", Fe, [
425
+ t[17] || (t[17] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide block" }, "Audio Language", -1)),
426
+ D(j, {
427
+ "model-value": e.audioLang,
428
+ class: "w-full",
429
+ "onUpdate:modelValue": t[5] || (t[5] = (o) => v.$emit("update:audioLang", o))
430
+ }, null, 8, ["model-value"])
431
+ ])) : b("", !0),
432
+ a("div", ze, [
433
+ t[18] || (t[18] = a("label", { class: "text-sm font-semibold text-gray-700 uppercase tracking-wide block" }, "Text Language", -1)),
434
+ D(j, {
435
+ "model-value": e.textLang,
436
+ class: "w-full",
437
+ "onUpdate:modelValue": t[6] || (t[6] = (o) => v.$emit("update:textLang", o))
438
+ }, null, 8, ["model-value"])
439
+ ]),
440
+ a("button", {
441
+ class: "w-full px-4 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 font-medium shadow-sm transition-colors mt-4",
442
+ onClick: t[7] || (t[7] = (o) => v.$emit("update:showMobileSettings", !1))
443
+ }, " Done ")
444
+ ])
445
+ ])) : b("", !0)
245
446
  ], 64));
246
447
  }
448
+ }), He = { class: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6" }, Ge = { class: "relative aspect-video bg-gray-200" }, Oe = ["src", "alt"], qe = { class: "absolute top-2 left-2 bg-black bg-opacity-70 text-white px-3 py-1 rounded-full text-sm font-semibold" }, Je = { class: "p-4" }, Ke = { class: "text-gray-700 text-sm line-clamp-3 group-hover:text-indigo-600 transition-colors" }, Qe = { class: "text-gray-500 text-xs mt-2 space-y-1" }, Xe = { key: 0 }, Ye = { key: 1 }, dt = /* @__PURE__ */ M({
449
+ __name: "beat_grid_view",
450
+ props: {
451
+ beats: {},
452
+ basePath: { default: "" },
453
+ textLang: { default: "en" },
454
+ linkUrlBuilder: {},
455
+ linkComponent: { default: "a" }
456
+ },
457
+ emits: ["beat-click"],
458
+ setup(e, { emit: v }) {
459
+ const t = e, o = v, f = (l) => {
460
+ const g = Math.floor(l / 3600), c = Math.floor(l % 3600 / 60), i = Math.floor(l % 60);
461
+ return g > 0 ? `${g}:${c.toString().padStart(2, "0")}:${i.toString().padStart(2, "0")}` : `${c}:${i.toString().padStart(2, "0")}`;
462
+ }, m = (l) => l.multiLinguals?.[t.textLang] || l.text || "No text available", s = (l) => `${t.basePath}/${l + 1}.jpg`, r = (l, g) => {
463
+ t.linkComponent === "a" && t.linkUrlBuilder && g.preventDefault(), o("beat-click", l);
464
+ };
465
+ return (l, g) => (u(), d("div", He, [
466
+ (u(!0), d(V, null, G(e.beats, ({ beat: c, originalIndex: i }) => (u(), O(Q(e.linkComponent), {
467
+ key: i,
468
+ to: e.linkUrlBuilder ? e.linkUrlBuilder(i) : void 0,
469
+ href: e.linkUrlBuilder ? e.linkUrlBuilder(i) : void 0,
470
+ class: "group block bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300 overflow-hidden",
471
+ onClick: (P) => r(i, P)
472
+ }, {
473
+ default: X(() => [
474
+ a("div", Ge, [
475
+ a("img", {
476
+ src: s(i),
477
+ alt: `Beat ${i + 1}`,
478
+ class: "w-full h-full object-cover"
479
+ }, null, 8, Oe),
480
+ a("div", qe, $(i + 1), 1)
481
+ ]),
482
+ a("div", Je, [
483
+ a("p", Ke, $(m(c)), 1),
484
+ a("div", Qe, [
485
+ c.startTime !== void 0 ? (u(), d("p", Xe, "Start: " + $(f(c.startTime)), 1)) : b("", !0),
486
+ c.duration ? (u(), d("p", Ye, "Duration: " + $(f(c.duration)), 1)) : b("", !0)
487
+ ])
488
+ ])
489
+ ]),
490
+ _: 2
491
+ }, 1032, ["to", "href", "onClick"]))), 128))
492
+ ]));
493
+ }
494
+ }), Ze = { class: "space-y-6" }, Ie = ["id"], et = { class: "flex items-center gap-3 mb-2 flex-wrap" }, tt = { class: "bg-indigo-600 text-white px-4 py-1 rounded-full text-sm font-semibold" }, at = {
495
+ key: 0,
496
+ class: "text-gray-500 text-sm"
497
+ }, ot = {
498
+ key: 1,
499
+ class: "text-gray-500 text-sm"
500
+ }, lt = ["src", "alt"], nt = { class: "text-gray-800 text-base leading-relaxed font-sans" }, rt = /* @__PURE__ */ M({
501
+ __name: "beat_list_view",
502
+ props: {
503
+ beats: {},
504
+ basePath: { default: "" },
505
+ textLang: { default: "en" },
506
+ linkUrlBuilder: {},
507
+ linkComponent: { default: "a" }
508
+ },
509
+ emits: ["beat-click"],
510
+ setup(e, { emit: v }) {
511
+ const t = e, o = v, f = (l) => {
512
+ const g = Math.floor(l / 3600), c = Math.floor(l % 3600 / 60), i = Math.floor(l % 60);
513
+ return g > 0 ? `${g}:${c.toString().padStart(2, "0")}:${i.toString().padStart(2, "0")}` : `${c}:${i.toString().padStart(2, "0")}`;
514
+ }, m = (l) => l.multiLinguals?.[t.textLang] || l.text || "No text available", s = (l) => `${t.basePath}/${l + 1}.jpg`, r = (l, g) => {
515
+ t.linkComponent === "a" && t.linkUrlBuilder && g.preventDefault(), o("beat-click", l);
516
+ };
517
+ return (l, g) => (u(), d("div", Ze, [
518
+ (u(!0), d(V, null, G(e.beats, ({ beat: c, originalIndex: i }) => (u(), d("div", {
519
+ id: `beat-${i}`,
520
+ key: i,
521
+ class: "bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"
522
+ }, [
523
+ (u(), O(Q(e.linkComponent), {
524
+ to: e.linkUrlBuilder ? e.linkUrlBuilder(i) : void 0,
525
+ href: e.linkUrlBuilder ? e.linkUrlBuilder(i) : void 0,
526
+ class: "float-left mr-4 mb-2 w-64 flex-shrink-0",
527
+ onClick: (P) => r(i, P)
528
+ }, {
529
+ default: X(() => [
530
+ a("div", et, [
531
+ a("span", tt, " #" + $(i + 1), 1),
532
+ c.startTime !== void 0 ? (u(), d("span", at, " Start: " + $(f(c.startTime)), 1)) : b("", !0),
533
+ c.duration ? (u(), d("span", ot, " Duration: " + $(f(c.duration)), 1)) : b("", !0)
534
+ ]),
535
+ a("img", {
536
+ src: s(i),
537
+ alt: `Beat ${i + 1}`,
538
+ class: "w-full h-auto object-cover rounded-lg hover:opacity-80 transition-opacity shadow-sm"
539
+ }, null, 8, lt)
540
+ ]),
541
+ _: 2
542
+ }, 1032, ["to", "href", "onClick"])),
543
+ a("p", nt, $(m(c)), 1),
544
+ g[0] || (g[0] = a("div", { class: "clear-both" }, null, -1))
545
+ ], 8, Ie))), 128))
546
+ ]));
547
+ }
247
548
  });
248
549
  export {
249
- pe as MulmoViewer,
250
- ve as SelectLanguage
550
+ dt as BeatGridView,
551
+ rt as BeatListView,
552
+ it as MulmoViewer,
553
+ ut as MulmoViewerHeader,
554
+ j as SelectLanguage
251
555
  };
@@ -1 +1 @@
1
- (function(f,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(f=typeof globalThis<"u"?globalThis:f||self,e(f.MulmoCastViewer={},f.Vue))})(this,(function(f,e){"use strict";const _=async a=>await new Promise(y=>setTimeout(y,a)),L={class:"items-center justify-center w-full"},R={key:0},$=["src"],C={key:1,class:"relative inline-block"},T=["src"],A=["src"],j={key:2,class:"relative inline-block"},W=["src"],D=["src"],M={key:3,class:"relative inline-block"},F=["src"],z={key:4},O="https://github.com/receptron/mulmocast-cli/blob/main/assets/images/mulmocast_credit.png?raw=true",x=e.defineComponent({__name:"mulmo_player",props:{index:{},videoWithAudioSource:{},soundEffectSource:{},videoSource:{},imageSource:{},audioSource:{},text:{},duration:{}},emits:["play","pause","ended"],setup(a,{expose:y,emit:k}){const l=a,d=k,c=e.ref(),o=e.ref(),n=e.ref(),r=e.ref(),m=e.ref(),S=()=>{n.value&&o.value&&(n.value.currentTime=o.value.currentTime,n.value.currentTime===o.value.currentTime&&n.value.play()),d("play")},v=u=>{!o.value?.ended&&n?.value&&n.value?.pause(),console.log(u),P(u)},E=()=>{!n.value?.paused&&!n.value?.ended&&(n.value?.currentTime??0)>0||p()},s=()=>{!o.value?.paused&&!o.value?.ended&&(o.value?.currentTime??0)>0||p()},g=()=>{d("play")},P=u=>{const h=u.target;h.duration!==h.currentTime&&d("pause")},p=()=>{d("ended")};return y({play:async()=>{c.value&&c.value.play(),o.value&&o.value.play(),r.value&&r.value.play(),!c.value&&!o.value&&!r.value&&(await _((l.duration??0)*1e3),d("ended"))}}),(u,h)=>(e.openBlock(),e.createElementBlock("div",L,[a.videoWithAudioSource?(e.openBlock(),e.createElementBlock("div",R,[e.createElementVNode("video",{ref_key:"videoWithAudioRef",ref:c,src:a.videoWithAudioSource,class:"mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",controls:!0,playsinline:"true",onPlay:g,onPause:P,onEnded:p},null,40,$)])):a.soundEffectSource||a.videoSource?(e.openBlock(),e.createElementBlock("div",C,[e.createElementVNode("video",{ref_key:"videoRef",ref:o,class:"mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",src:a.soundEffectSource||a.videoSource,controls:!0,playsinline:"true",onPlay:S,onPause:v,onEnded:E},null,40,T),a.audioSource?(e.openBlock(),e.createElementBlock("audio",{key:0,ref_key:"audioSyncRef",ref:n,src:a.audioSource,controls:!0,class:"hidden",onEnded:s},null,40,A)):e.createCommentVNode("",!0)])):a.audioSource?(e.openBlock(),e.createElementBlock("div",j,[a.imageSource?(e.openBlock(),e.createElementBlock("img",{key:0,src:a.imageSource,class:"mx-auto h-auto max-h-[80vh] w-auto object-contain",alt:"Background"},null,8,W)):(e.openBlock(),e.createElementBlock("img",{key:1,src:O,class:"mx-auto h-auto max-h-[80vh] w-auto object-contain",alt:"Background"})),e.createElementVNode("audio",{ref_key:"audioRef",ref:r,class:"mulmocast-audio absolute inset-0 w-full h-full",src:a.audioSource,controls:!0,onPlay:g,onPause:P,onEnded:p},null,40,D)])):a.imageSource?(e.openBlock(),e.createElementBlock("div",M,[e.createElementVNode("img",{ref_key:"imageRef",ref:m,src:a.imageSource,class:"max-w-full max-h-full object-contain"},null,8,F)])):(e.openBlock(),e.createElementBlock("div",z,"No media available")),e.createTextVNode(" "+e.toDisplayString(a.text),1)]))}}),q=["value"],H=["value"],B=e.defineComponent({__name:"select_language",props:{modelValue:{}},emits:["update:modelValue"],setup(a,{emit:y}){const k=["en","ja"],l=y,d=c=>{const o=c.target;l("update:modelValue",o.value)};return(c,o)=>(e.openBlock(),e.createElementBlock("select",{value:a.modelValue,onChange:d},[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(k,n=>e.createElementVNode("option",{key:n,value:n},e.toDisplayString(n),9,H)),64))],40,q))}}),I={class:"w-full overflow-hidden"},G={class:"max-w-7xl mx-auto px-4"},J={class:"flex items-center justify-between"},K=["disabled"],Q={class:"px-4"},U=["disabled"],X=["src"],Y=e.defineComponent({__name:"mulmo_viewer",props:{dataSet:{},basePath:{},initPage:{},audioLang:{default:"en"},textLang:{default:"en"}},emits:["updatedPage","update:audioLang","update:textLang"],setup(a,{expose:y,emit:k}){const l=a,d=k,c=l.dataSet?.beats?.length??0,o=e.ref(l.initPage??0),n=e.ref(!0),r=e.ref(),m=e.ref(),S=e.computed({get:()=>l.audioLang,set:t=>d("update:audioLang",t||"en")}),v=e.computed({get:()=>l.textLang,set:t=>d("update:textLang",t||"en")}),E=e.computed(()=>l.dataSet?.beats[o.value]),s=t=>t?l.basePath+"/"+t:"",g=e.ref(!1),P=()=>{g.value=!0,m.value&&m.value.play()},p=()=>{console.log("pause"),g.value=!1,m.value&&m.value.pause()},b=async()=>{await _(500),r.value&&r.value.play()},u=t=>{o.value!==t&&(o.value=t,g.value&&n.value&&b())},h=t=>{const i=o.value+t;return i>-1&&i<c?(u(i),d("updatedPage",i),!0):!1},V=()=>{console.log("end"),n.value&&h(1)?b():(g.value=!1,m.value&&m.value.pause())},Z={onPlay:P,onPause:p,onEnded:V},w=e.computed(()=>{const t=E.value,i=t?.audioSources?.[S.value];return{videoWithAudioSource:s(t?.videoWithAudioSource),videoSource:s(t?.videoSource),soundEffectSource:s(t?.soundEffectSource),audioSource:i?l.basePath+"/"+i:"",imageSource:s(t?.imageSource),index:o.value,text:t?.multiLinguals?.[v.value]??t?.text??"",duration:t?.duration,...Z}}),ee=e.computed(()=>l.dataSet?.beats[o.value+1]),N=e.computed(()=>{if(o.value+1>=c)return null;const t=ee.value;return{videoWithAudioSource:s(t?.videoWithAudioSource),videoSource:s(t?.videoSource),soundEffectSource:s(t?.soundEffectSource),audioSource:t?.audioSources?.[S.value]?l.basePath+"/"+t.audioSources[S.value]:"",imageSource:s(t?.imageSource),index:o.value+1,text:t?.multiLinguals?.[v.value]??t?.text??"",duration:t?.duration}}),te=e.computed(()=>({MulmoPlayer:x,pageProps:w.value,currentPage:o.value,pageCount:c,pageMove:h,isPlaying:g.value,audioLang:S,textLang:v,SelectLanguage:B,mediaPlayerRef:r,handlePlay:P,handlePause:p,handleEnded:V}));return y({updatePage:u}),(t,i)=>(e.openBlock(),e.createElementBlock(e.Fragment,null,[e.renderSlot(t.$slots,"default",e.normalizeProps(e.guardReactiveProps(te.value)),()=>[e.createElementVNode("div",I,[e.createElementVNode("div",G,[e.createElementVNode("div",J,[e.createElementVNode("button",{class:"px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",disabled:o.value===0,onClick:i[0]||(i[0]=oe=>h(-1))}," Prev ",8,K),e.createElementVNode("div",Q,[e.createVNode(x,e.mergeProps({ref_key:"mediaPlayer",ref:r},w.value),null,16)]),e.createElementVNode("button",{class:"px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",disabled:o.value>=e.unref(c)-1,onClick:i[1]||(i[1]=oe=>h(1))}," Next ",8,U)])])])]),N.value?e.withDirectives((e.openBlock(),e.createBlock(x,e.normalizeProps(e.mergeProps({key:0},N.value)),null,16)),[[e.vShow,!1]]):e.createCommentVNode("",!0),a.dataSet?.bgmFile?(e.openBlock(),e.createElementBlock("audio",{key:1,ref_key:"bgmRef",ref:m,src:a.dataSet?.bgmFile},null,8,X)):e.createCommentVNode("",!0)],64))}});f.MulmoViewer=Y,f.SelectLanguage=B,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(h,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(h=typeof globalThis<"u"?globalThis:h||self,e(h.MulmoCastViewer={},h.Vue))})(this,(function(h,e){"use strict";const L=async t=>await new Promise(c=>setTimeout(c,t)),M={class:"items-center justify-center w-full"},U={key:0},R=["src"],j={key:1,class:"relative inline-block"},A=["src"],_=["src"],F={key:2,class:"relative inline-block"},W=["src"],z=["src"],H={key:3,class:"relative inline-block"},O=["src"],q={key:4},G={key:5,class:"mt-4 px-6 py-4 text-left"},J={class:"text-lg leading-relaxed font-sans text-gray-800"},K={key:0,class:"text-base leading-relaxed font-sans text-gray-400 mt-3 italic"},Q="https://github.com/receptron/mulmocast-cli/blob/main/assets/images/mulmocast_credit.png?raw=true",T=e.defineComponent({__name:"mulmo_player",props:{index:{},videoWithAudioSource:{},soundEffectSource:{},videoSource:{},imageSource:{},audioSource:{},text:{},originalText:{},duration:{},defaultLang:{},currentLang:{},playbackSpeed:{default:1}},emits:["play","pause","ended"],setup(t,{expose:c,emit:a}){const o=t,g=a,m=e.ref(),i=e.ref(),d=e.ref(),l=e.ref(),u=e.ref(),r=()=>{i.value&&o.videoSource&&(o.audioSource&&o.currentLang&&o.defaultLang&&o.currentLang!==o.defaultLang?i.value.volume=.2:i.value.volume=0)},s=()=>{const f=o.playbackSpeed??1;m.value&&(m.value.playbackRate=f),i.value&&(i.value.playbackRate=f),d.value&&(d.value.playbackRate=f),l.value&&(l.value.playbackRate=f)};e.watch([()=>o.currentLang,()=>o.defaultLang,()=>o.videoSource,()=>o.audioSource],()=>{r()}),e.watch(()=>o.playbackSpeed,()=>{s()}),e.watch(i,f=>{f&&(r(),s())}),e.watch([m,d,l],()=>{s()}),e.onMounted(()=>{r(),s()});const E=()=>{y.value=!0,d.value&&i.value&&(d.value.currentTime=i.value.currentTime,d.value.currentTime===i.value.currentTime&&d.value.play()),g("play")},S=f=>{document.hidden||(y.value=!1),!i.value?.ended&&d?.value&&d.value?.pause(),console.log(f),V(f)},k=()=>{!d.value?.paused&&!d.value?.ended&&(d.value?.currentTime??0)>0||w()},P=()=>{!i.value?.paused&&!i.value?.ended&&(i.value?.currentTime??0)>0||w()},N=()=>{y.value=!0,g("play")},V=f=>{document.hidden||(y.value=!1);const n=f.target;n.duration!==n.currentTime&&g("pause")},w=()=>{y.value=!1,g("ended")},y=e.ref(!1);let b=null;const D=async()=>{y.value=!0,m.value&&(s(),m.value.play()),i.value&&(r(),s(),i.value.play(),d.value&&(d.value.currentTime=i.value.currentTime,d.value.play())),l.value&&(s(),l.value.play()),!m.value&&!i.value&&!l.value&&(await L((o.duration??0)*1e3),y.value=!1,g("ended"))},$=()=>{y.value&&(m.value?.paused&&m.value.play().catch(()=>{}),i.value?.paused&&i.value.play().catch(()=>{}),l.value?.paused&&l.value.play().catch(()=>{}),d.value?.paused&&d.value.play().catch(()=>{}))},C=()=>{document.hidden&&y.value?b||(b=setInterval($,500)):document.hidden||b&&(clearInterval(b),b=null)},x=()=>{document.hidden&&y.value&&setTimeout($,50)};return e.onMounted(()=>{document.addEventListener("visibilitychange",C),m.value?.addEventListener("pause",x),i.value?.addEventListener("pause",x),l.value?.addEventListener("pause",x),d.value?.addEventListener("pause",x)}),e.onUnmounted(()=>{document.removeEventListener("visibilitychange",C),m.value?.removeEventListener("pause",x),i.value?.removeEventListener("pause",x),l.value?.removeEventListener("pause",x),d.value?.removeEventListener("pause",x),b&&(clearInterval(b),b=null)}),c({play:D}),(f,n)=>(e.openBlock(),e.createElementBlock("div",M,[t.videoWithAudioSource?(e.openBlock(),e.createElementBlock("div",U,[e.createElementVNode("video",{ref_key:"videoWithAudioRef",ref:m,src:t.videoWithAudioSource,class:"mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",controls:!0,playsinline:"true",onPlay:N,onPause:V,onEnded:w},null,40,R)])):t.soundEffectSource||t.videoSource?(e.openBlock(),e.createElementBlock("div",j,[e.createElementVNode("video",{ref_key:"videoRef",ref:i,class:"mulmocast-video mx-auto h-auto max-h-[80vh] w-auto object-contain",src:t.soundEffectSource||t.videoSource,controls:!0,playsinline:"true",onPlay:E,onPause:S,onEnded:k},null,40,A),t.audioSource?(e.openBlock(),e.createElementBlock("audio",{key:0,ref_key:"audioSyncRef",ref:d,src:t.audioSource,controls:!0,class:"hidden",onEnded:P},null,40,_)):e.createCommentVNode("",!0)])):t.audioSource?(e.openBlock(),e.createElementBlock("div",F,[t.imageSource?(e.openBlock(),e.createElementBlock("img",{key:0,src:t.imageSource,class:"mx-auto h-auto max-h-[80vh] w-auto object-contain",alt:"Background"},null,8,W)):(e.openBlock(),e.createElementBlock("img",{key:1,src:Q,class:"mx-auto h-auto max-h-[80vh] w-auto object-contain",alt:"Background"})),e.createElementVNode("audio",{ref_key:"audioRef",ref:l,class:"mulmocast-audio absolute inset-0 w-full h-full",src:t.audioSource,controls:!0,onPlay:N,onPause:V,onEnded:w},null,40,z)])):t.imageSource?(e.openBlock(),e.createElementBlock("div",H,[e.createElementVNode("img",{ref_key:"imageRef",ref:u,src:t.imageSource,class:"max-w-full max-h-full object-contain"},null,8,O)])):(e.openBlock(),e.createElementBlock("div",q,"No media available")),t.text?(e.openBlock(),e.createElementBlock("div",G,[e.createElementVNode("p",J,e.toDisplayString(t.text),1),t.originalText&&t.originalText!==t.text?(e.openBlock(),e.createElementBlock("p",K,e.toDisplayString(t.originalText),1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0)]))}}),X=["value"],Y=["value"],B=e.defineComponent({__name:"select_language",props:{modelValue:{}},emits:["update:modelValue"],setup(t,{emit:c}){const a=["en","ja"],o={en:"English",ja:"日本語"},g=c,m=i=>{const d=i.target;g("update:modelValue",d.value)};return(i,d)=>(e.openBlock(),e.createElementBlock("select",{value:t.modelValue,class:"px-4 py-2 bg-white border-2 border-gray-300 rounded-lg shadow-sm hover:border-indigo-400 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 focus:outline-none transition-colors cursor-pointer text-base font-medium text-gray-700",onChange:m},[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(a,l=>e.createElementVNode("option",{key:l,value:l},e.toDisplayString(o[l]||l),9,Y)),64))],40,X))}}),Z={class:"w-full overflow-hidden"},I={class:"max-w-7xl mx-auto px-4"},ee={class:"flex items-center justify-between"},te=["disabled"],ae={class:"px-4"},oe=["disabled"],le=["src"],ne=e.defineComponent({__name:"mulmo_viewer",props:{dataSet:{},basePath:{},initPage:{},audioLang:{default:"en"},textLang:{default:"en"},playbackSpeed:{default:1}},emits:["updatedPage","update:audioLang","update:textLang"],setup(t,{expose:c,emit:a}){const o=t,g=a,m=o.dataSet?.beats?.length??0,i=e.ref(o.initPage??0),d=e.ref(!0),l=e.ref(),u=e.ref(),r=e.computed({get:()=>o.audioLang,set:n=>g("update:audioLang",n||"en")}),s=e.computed({get:()=>o.textLang,set:n=>g("update:textLang",n||"en")});e.watch(()=>o.audioLang,async(n,p)=>{if(n!==p&&k.value){const v=k.value;k.value=!1,await L(500),v&&l.value&&(k.value=!0,await l.value.play())}}),e.watch(()=>o.textLang,async(n,p)=>{n!==p&&k.value&&(await L(100),l.value&&await l.value.play())});const E=e.computed(()=>o.dataSet?.beats[i.value]),S=n=>n?o.basePath+"/"+n:"",k=e.ref(!1),P=()=>{k.value=!0,u.value&&u.value.play()},N=()=>{console.log("pause"),k.value=!1,u.value&&u.value.pause()},V=async()=>{await L(500),l.value&&l.value.play()},w=n=>{i.value!==n&&(i.value=n,k.value&&d.value&&V())},y=n=>{const p=i.value+n;return p>-1&&p<m?(w(p),g("updatedPage",p),!0):!1},b=()=>{console.log("end"),d.value&&y(1)?V():(k.value=!1,u.value&&u.value.pause())},D={onPlay:P,onPause:N,onEnded:b},$=e.computed(()=>{const n=E.value,p=n?.audioSources?.[r.value],v=n?.multiLinguals?.[s.value]??n?.text??"",_e=o.dataSet?.lang?n?.multiLinguals?.[o.dataSet.lang]??n?.text??"":"";return{videoWithAudioSource:S(n?.videoWithAudioSource),videoSource:S(n?.videoSource),soundEffectSource:S(n?.soundEffectSource),audioSource:p?o.basePath+"/"+p:"",imageSource:S(n?.imageSource),index:i.value,text:v,originalText:_e,duration:n?.duration,defaultLang:o.dataSet?.lang,currentLang:r.value,playbackSpeed:o.playbackSpeed,...D}}),C=e.computed(()=>o.dataSet?.beats[i.value+1]),x=e.computed(()=>{if(i.value+1>=m)return null;const n=C.value;return{videoWithAudioSource:S(n?.videoWithAudioSource),videoSource:S(n?.videoSource),soundEffectSource:S(n?.soundEffectSource),audioSource:n?.audioSources?.[r.value]?o.basePath+"/"+n.audioSources[r.value]:"",imageSource:S(n?.imageSource),index:i.value+1,text:n?.multiLinguals?.[s.value]??n?.text??"",duration:n?.duration}}),f=e.computed(()=>({MulmoPlayer:T,pageProps:$.value,currentPage:i.value,pageCount:m,pageMove:y,isPlaying:k.value,audioLang:r,textLang:s,SelectLanguage:B,mediaPlayerRef:l,handlePlay:P,handlePause:N,handleEnded:b}));return c({updatePage:w}),(n,p)=>(e.openBlock(),e.createElementBlock(e.Fragment,null,[e.renderSlot(n.$slots,"default",e.normalizeProps(e.guardReactiveProps(f.value)),()=>[e.createElementVNode("div",Z,[e.createElementVNode("div",I,[e.createElementVNode("div",ee,[e.createElementVNode("button",{class:"px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",disabled:i.value===0,onClick:p[0]||(p[0]=v=>y(-1))}," Prev ",8,te),e.createElementVNode("div",ae,[e.createVNode(T,e.mergeProps({ref_key:"mediaPlayer",ref:l},$.value),null,16)]),e.createElementVNode("button",{class:"px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 disabled:opacity-50",disabled:i.value>=e.unref(m)-1,onClick:p[1]||(p[1]=v=>y(1))}," Next ",8,oe)])])])]),x.value?e.withDirectives((e.openBlock(),e.createBlock(T,e.normalizeProps(e.mergeProps({key:0},x.value)),null,16)),[[e.vShow,!1]]):e.createCommentVNode("",!0),t.dataSet?.bgmFile?(e.openBlock(),e.createElementBlock("audio",{key:1,ref_key:"bgmRef",ref:u,src:t.dataSet?.bgmFile},null,8,le)):e.createCommentVNode("",!0)],64))}}),ie={class:"container mx-auto px-4 py-2 sm:py-4"},se={class:"flex flex-col sm:flex-row justify-between items-start sm:items-center gap-2 sm:gap-4"},de={class:"flex items-center gap-4 flex-wrap"},re={class:"flex items-center gap-2 sm:gap-4 flex-wrap w-full sm:w-auto"},ce={key:0,class:"hidden sm:flex items-center gap-3"},ue=["value"],me={key:1,class:"hidden sm:flex items-center gap-3"},ge={class:"hidden sm:flex items-center gap-3"},fe={class:"flex items-center justify-between mb-4"},pe={key:0,class:"space-y-2"},ye=["value"],ke={key:1,class:"space-y-2"},he={class:"space-y-2"},be=e.defineComponent({__name:"mulmo_viewer_header",props:{audioLang:{},textLang:{},playbackSpeed:{default:1},showSpeedControl:{type:Boolean,default:!0},showAudioLang:{type:Boolean,default:!0},hideDesktopControls:{type:Boolean,default:!1},showMobileSettings:{type:Boolean,default:!1},sticky:{type:Boolean,default:!1}},emits:["update:audioLang","update:textLang","update:playbackSpeed","update:showMobileSettings"],setup(t){return(c,a)=>(e.openBlock(),e.createElementBlock(e.Fragment,null,[e.createElementVNode("div",{class:e.normalizeClass(["bg-white shadow-md border-b border-gray-200",{"sticky top-0 z-50":t.sticky}])},[e.createElementVNode("div",ie,[e.createElementVNode("div",se,[e.createElementVNode("div",de,[e.renderSlot(c.$slots,"left")]),e.createElementVNode("div",re,[e.renderSlot(c.$slots,"actions"),t.hideDesktopControls?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[t.showSpeedControl?(e.openBlock(),e.createElementBlock("div",ce,[a[11]||(a[11]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide"},"Speed:",-1)),e.createElementVNode("select",{value:t.playbackSpeed,class:"px-3 py-2 border border-gray-300 rounded-lg bg-white text-gray-700 font-medium shadow-sm hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors",onChange:a[0]||(a[0]=o=>c.$emit("update:playbackSpeed",Number(o.target.value)))},[...a[10]||(a[10]=[e.createElementVNode("option",{value:1},"1x",-1),e.createElementVNode("option",{value:1.25},"1.25x",-1),e.createElementVNode("option",{value:1.5},"1.5x",-1),e.createElementVNode("option",{value:1.75},"1.75x",-1),e.createElementVNode("option",{value:2},"2x",-1)])],40,ue)])):e.createCommentVNode("",!0),t.showAudioLang?(e.openBlock(),e.createElementBlock("div",me,[a[12]||(a[12]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide"},"Audio:",-1)),e.createVNode(B,{"model-value":t.audioLang,"onUpdate:modelValue":a[1]||(a[1]=o=>c.$emit("update:audioLang",o))},null,8,["model-value"])])):e.createCommentVNode("",!0),e.createElementVNode("div",ge,[a[13]||(a[13]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide"},"Text:",-1)),e.createVNode(B,{"model-value":t.textLang,"onUpdate:modelValue":a[2]||(a[2]=o=>c.$emit("update:textLang",o))},null,8,["model-value"])])],64)),e.renderSlot(c.$slots,"mobile-actions")])])])],2),t.showMobileSettings?(e.openBlock(),e.createElementBlock("div",{key:0,class:"fixed inset-0 bg-black bg-opacity-50 z-50 sm:hidden",onClick:a[9]||(a[9]=o=>c.$emit("update:showMobileSettings",!1))},[e.createElementVNode("div",{class:"absolute bottom-0 left-0 right-0 bg-white rounded-t-2xl shadow-xl p-6 space-y-4",onClick:a[8]||(a[8]=e.withModifiers(()=>{},["stop"]))},[e.createElementVNode("div",fe,[a[14]||(a[14]=e.createElementVNode("h2",{class:"text-xl font-bold text-gray-800"},"Settings",-1)),e.createElementVNode("button",{class:"text-gray-500 hover:text-gray-700 text-2xl",onClick:a[3]||(a[3]=o=>c.$emit("update:showMobileSettings",!1))}," × ")]),t.showSpeedControl?(e.openBlock(),e.createElementBlock("div",pe,[a[16]||(a[16]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide block"},"Playback Speed",-1)),e.createElementVNode("select",{value:t.playbackSpeed,class:"w-full px-4 py-3 border border-gray-300 rounded-lg bg-white text-gray-700 font-medium shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500",onChange:a[4]||(a[4]=o=>c.$emit("update:playbackSpeed",Number(o.target.value)))},[...a[15]||(a[15]=[e.createElementVNode("option",{value:1},"1x (Normal)",-1),e.createElementVNode("option",{value:1.25},"1.25x",-1),e.createElementVNode("option",{value:1.5},"1.5x",-1),e.createElementVNode("option",{value:1.75},"1.75x",-1),e.createElementVNode("option",{value:2},"2x (Double)",-1)])],40,ye)])):e.createCommentVNode("",!0),t.showAudioLang?(e.openBlock(),e.createElementBlock("div",ke,[a[17]||(a[17]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide block"},"Audio Language",-1)),e.createVNode(B,{"model-value":t.audioLang,class:"w-full","onUpdate:modelValue":a[5]||(a[5]=o=>c.$emit("update:audioLang",o))},null,8,["model-value"])])):e.createCommentVNode("",!0),e.createElementVNode("div",he,[a[18]||(a[18]=e.createElementVNode("label",{class:"text-sm font-semibold text-gray-700 uppercase tracking-wide block"},"Text Language",-1)),e.createVNode(B,{"model-value":t.textLang,class:"w-full","onUpdate:modelValue":a[6]||(a[6]=o=>c.$emit("update:textLang",o))},null,8,["model-value"])]),e.createElementVNode("button",{class:"w-full px-4 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 font-medium shadow-sm transition-colors mt-4",onClick:a[7]||(a[7]=o=>c.$emit("update:showMobileSettings",!1))}," Done ")])])):e.createCommentVNode("",!0)],64))}}),xe={class:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"},Se={class:"relative aspect-video bg-gray-200"},Ee=["src","alt"],we={class:"absolute top-2 left-2 bg-black bg-opacity-70 text-white px-3 py-1 rounded-full text-sm font-semibold"},Be={class:"p-4"},Ve={class:"text-gray-700 text-sm line-clamp-3 group-hover:text-indigo-600 transition-colors"},Ne={class:"text-gray-500 text-xs mt-2 space-y-1"},$e={key:0},ve={key:1},Le=e.defineComponent({__name:"beat_grid_view",props:{beats:{},basePath:{default:""},textLang:{default:"en"},linkUrlBuilder:{},linkComponent:{default:"a"}},emits:["beat-click"],setup(t,{emit:c}){const a=t,o=c,g=l=>{const u=Math.floor(l/3600),r=Math.floor(l%3600/60),s=Math.floor(l%60);return u>0?`${u}:${r.toString().padStart(2,"0")}:${s.toString().padStart(2,"0")}`:`${r}:${s.toString().padStart(2,"0")}`},m=l=>l.multiLinguals?.[a.textLang]||l.text||"No text available",i=l=>`${a.basePath}/${l+1}.jpg`,d=(l,u)=>{a.linkComponent==="a"&&a.linkUrlBuilder&&u.preventDefault(),o("beat-click",l)};return(l,u)=>(e.openBlock(),e.createElementBlock("div",xe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.beats,({beat:r,originalIndex:s})=>(e.openBlock(),e.createBlock(e.resolveDynamicComponent(t.linkComponent),{key:s,to:t.linkUrlBuilder?t.linkUrlBuilder(s):void 0,href:t.linkUrlBuilder?t.linkUrlBuilder(s):void 0,class:"group block bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300 overflow-hidden",onClick:E=>d(s,E)},{default:e.withCtx(()=>[e.createElementVNode("div",Se,[e.createElementVNode("img",{src:i(s),alt:`Beat ${s+1}`,class:"w-full h-full object-cover"},null,8,Ee),e.createElementVNode("div",we,e.toDisplayString(s+1),1)]),e.createElementVNode("div",Be,[e.createElementVNode("p",Ve,e.toDisplayString(m(r)),1),e.createElementVNode("div",Ne,[r.startTime!==void 0?(e.openBlock(),e.createElementBlock("p",$e,"Start: "+e.toDisplayString(g(r.startTime)),1)):e.createCommentVNode("",!0),r.duration?(e.openBlock(),e.createElementBlock("p",ve,"Duration: "+e.toDisplayString(g(r.duration)),1)):e.createCommentVNode("",!0)])])]),_:2},1032,["to","href","onClick"]))),128))]))}}),Pe={class:"space-y-6"},Ce=["id"],Te={class:"flex items-center gap-3 mb-2 flex-wrap"},De={class:"bg-indigo-600 text-white px-4 py-1 rounded-full text-sm font-semibold"},Me={key:0,class:"text-gray-500 text-sm"},Ue={key:1,class:"text-gray-500 text-sm"},Re=["src","alt"],je={class:"text-gray-800 text-base leading-relaxed font-sans"},Ae=e.defineComponent({__name:"beat_list_view",props:{beats:{},basePath:{default:""},textLang:{default:"en"},linkUrlBuilder:{},linkComponent:{default:"a"}},emits:["beat-click"],setup(t,{emit:c}){const a=t,o=c,g=l=>{const u=Math.floor(l/3600),r=Math.floor(l%3600/60),s=Math.floor(l%60);return u>0?`${u}:${r.toString().padStart(2,"0")}:${s.toString().padStart(2,"0")}`:`${r}:${s.toString().padStart(2,"0")}`},m=l=>l.multiLinguals?.[a.textLang]||l.text||"No text available",i=l=>`${a.basePath}/${l+1}.jpg`,d=(l,u)=>{a.linkComponent==="a"&&a.linkUrlBuilder&&u.preventDefault(),o("beat-click",l)};return(l,u)=>(e.openBlock(),e.createElementBlock("div",Pe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.beats,({beat:r,originalIndex:s})=>(e.openBlock(),e.createElementBlock("div",{id:`beat-${s}`,key:s,class:"bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"},[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(t.linkComponent),{to:t.linkUrlBuilder?t.linkUrlBuilder(s):void 0,href:t.linkUrlBuilder?t.linkUrlBuilder(s):void 0,class:"float-left mr-4 mb-2 w-64 flex-shrink-0",onClick:E=>d(s,E)},{default:e.withCtx(()=>[e.createElementVNode("div",Te,[e.createElementVNode("span",De," #"+e.toDisplayString(s+1),1),r.startTime!==void 0?(e.openBlock(),e.createElementBlock("span",Me," Start: "+e.toDisplayString(g(r.startTime)),1)):e.createCommentVNode("",!0),r.duration?(e.openBlock(),e.createElementBlock("span",Ue," Duration: "+e.toDisplayString(g(r.duration)),1)):e.createCommentVNode("",!0)]),e.createElementVNode("img",{src:i(s),alt:`Beat ${s+1}`,class:"w-full h-auto object-cover rounded-lg hover:opacity-80 transition-opacity shadow-sm"},null,8,Re)]),_:2},1032,["to","href","onClick"])),e.createElementVNode("p",je,e.toDisplayString(m(r)),1),u[0]||(u[0]=e.createElementVNode("div",{class:"clear-both"},null,-1))],8,Ce))),128))]))}});h.BeatGridView=Le,h.BeatListView=Ae,h.MulmoViewer=ne,h.MulmoViewerHeader=be,h.SelectLanguage=B,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast-viewer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "dist/mulmocast-viewer.umd.js",
@@ -33,29 +33,27 @@
33
33
  },
34
34
  "repository": "git+ssh://git@github.com/receptron/mulmocast-viewer.git",
35
35
  "author": "receptron",
36
- "dependencies": {
37
- "vue": "^3.5.22",
38
- "vue-i18n": "^11.1.12",
39
- "vue-router": "^4.6.3"
40
- },
41
36
  "devDependencies": {
42
- "@eslint/js": "^9.38.0",
43
- "@tailwindcss/vite": "^4.1.15",
44
- "@types/node": "^24.9.1",
37
+ "@eslint/js": "^9.39.1",
38
+ "@tailwindcss/vite": "^4.1.17",
39
+ "@types/node": "^24.10.1",
45
40
  "@vitejs/plugin-vue": "^6.0.1",
46
41
  "@vue/tsconfig": "^0.8.1",
47
- "eslint": "^9.38.0",
42
+ "eslint": "^9.39.1",
48
43
  "eslint-config-prettier": "^10.1.8",
49
44
  "eslint-plugin-sonarjs": "^3.0.5",
50
45
  "eslint-plugin-vue": "^10.5.1",
51
- "globals": "^16.4.0",
46
+ "globals": "^16.5.0",
52
47
  "prettier": "^3.6.2",
53
- "tailwindcss": "^4.1.15",
48
+ "tailwindcss": "^4.1.17",
54
49
  "typescript": "~5.9.3",
55
- "typescript-eslint": "^8.46.2",
56
- "vite": "^7.1.11",
50
+ "typescript-eslint": "^8.47.0",
51
+ "vite": "^7.2.2",
57
52
  "vite-plugin-dts": "^4.5.4",
58
53
  "vue-eslint-parser": "^10.2.0",
59
- "vue-tsc": "^3.1.0"
54
+ "vue": "^3.5.24",
55
+ "vue-i18n": "^11.1.12",
56
+ "vue-router": "^4.6.3",
57
+ "vue-tsc": "^3.1.4"
60
58
  }
61
59
  }