itube-specs 0.0.826 → 0.0.828
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/components/player/core.vue +1 -1
- package/components/player/menu.vue +200 -159
- package/package.json +1 -1
|
@@ -250,7 +250,7 @@ const options = computed<Omit<PlayerOptions, 'source'>>(() => ({
|
|
|
250
250
|
},
|
|
251
251
|
icons: PLAYER_ICONS,
|
|
252
252
|
// Заголовок дропдауна выбора типа сцен (дефолт «Scene type»).
|
|
253
|
-
labels: { sceneTypes: t('
|
|
253
|
+
labels: { sceneTypes: t('jump_to') },
|
|
254
254
|
// Запоминаем громкость/mute в localStorage.
|
|
255
255
|
persist: { key: PLAYER_PERSIST_KEY },
|
|
256
256
|
}));
|
|
@@ -3,161 +3,163 @@
|
|
|
3
3
|
колбэками, которые сами применяют выбор. Рендерим её в нашем ui-popup (--sheet).
|
|
4
4
|
Дрилл «Настройки → Скорость/Качество» — через стек drill с кнопкой «назад». -->
|
|
5
5
|
<template>
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<template #title>
|
|
15
|
-
{{ drill?.label ?? request.title }}
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<!-- Дрилл: опции одной настройки (скорость / качество / субтитры) -->
|
|
19
|
-
<ul
|
|
20
|
-
v-if="drill"
|
|
21
|
-
class="player-menu__options"
|
|
6
|
+
<transition mode="out-in">
|
|
7
|
+
<UiPopup
|
|
8
|
+
v-if="open && request"
|
|
9
|
+
v-model="open"
|
|
10
|
+
sheet
|
|
11
|
+
:back="!!drill"
|
|
12
|
+
class="player-menu"
|
|
13
|
+
@back="drill = null"
|
|
22
14
|
>
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
<template #title>
|
|
16
|
+
{{ drill?.label ?? request.title }}
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<!-- Дрилл: опции одной настройки (скорость / качество / субтитры) -->
|
|
20
|
+
<ul
|
|
21
|
+
v-if="drill"
|
|
22
|
+
class="player-menu__options"
|
|
26
23
|
>
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
type="button"
|
|
31
|
-
@click="pick(drill.select, option.value)"
|
|
24
|
+
<li
|
|
25
|
+
v-for="option in drill.options"
|
|
26
|
+
:key="option.value"
|
|
32
27
|
>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
28
|
+
<button
|
|
29
|
+
:class="{ '--active': option.active }"
|
|
30
|
+
class="player-menu__option"
|
|
31
|
+
type="button"
|
|
32
|
+
@click="pick(drill.select, option.value)"
|
|
33
|
+
>
|
|
34
|
+
{{ option.label }}
|
|
35
|
+
</button>
|
|
36
|
+
</li>
|
|
37
|
+
</ul>
|
|
38
|
+
|
|
39
|
+
<!-- Шестерёнка: тоглы + строки-дриллы -->
|
|
40
|
+
<ul
|
|
41
|
+
v-else-if="request.kind === 'settings'"
|
|
42
|
+
class="player-menu__rows"
|
|
47
43
|
>
|
|
48
|
-
<
|
|
49
|
-
v-
|
|
50
|
-
|
|
44
|
+
<li
|
|
45
|
+
v-for="entry in request.entries"
|
|
46
|
+
:key="entry.key"
|
|
47
|
+
class="player-menu__row"
|
|
51
48
|
>
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class="player-menu__row-btn"
|
|
61
|
-
type="button"
|
|
62
|
-
@click="drill = { label: entry.label, options: entry.options, select: entry.select }"
|
|
63
|
-
>
|
|
64
|
-
<span class="player-menu__label">{{ entry.label }}</span>
|
|
65
|
-
<span class="player-menu__value">
|
|
66
|
-
{{ entry.value }}
|
|
67
|
-
<UiIcon
|
|
68
|
-
name="angle-right"
|
|
69
|
-
size="16"
|
|
49
|
+
<div
|
|
50
|
+
v-if="entry.toggle"
|
|
51
|
+
class="player-menu__toggle-row"
|
|
52
|
+
>
|
|
53
|
+
<span class="player-menu__label">{{ entry.label }}</span>
|
|
54
|
+
<UiToggle
|
|
55
|
+
:model-value="entry.toggle.value"
|
|
56
|
+
@update:model-value="entry.toggle.set(!!$event)"
|
|
70
57
|
/>
|
|
71
|
-
</
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
58
|
+
</div>
|
|
59
|
+
<button
|
|
60
|
+
v-else-if="entry.options && entry.select"
|
|
61
|
+
class="player-menu__row-btn"
|
|
62
|
+
type="button"
|
|
63
|
+
@click="drill = { label: entry.label, options: entry.options, select: entry.select }"
|
|
64
|
+
>
|
|
65
|
+
<span class="player-menu__label">{{ entry.label }}</span>
|
|
66
|
+
<span class="player-menu__value">
|
|
67
|
+
{{ entry.value }}
|
|
68
|
+
<UiIcon
|
|
69
|
+
name="chevron-right"
|
|
70
|
+
size="16"
|
|
71
|
+
/>
|
|
72
|
+
</span>
|
|
73
|
+
</button>
|
|
74
|
+
<div
|
|
75
|
+
v-else
|
|
76
|
+
class="player-menu__toggle-row"
|
|
77
|
+
>
|
|
78
|
+
<span class="player-menu__label">{{ entry.label }}</span>
|
|
79
|
+
<span class="player-menu__value">{{ entry.value }}</span>
|
|
80
|
+
</div>
|
|
81
|
+
</li>
|
|
82
|
+
</ul>
|
|
83
|
+
|
|
84
|
+
<!-- Тайм-коды: аккордеон типов сцен -->
|
|
85
|
+
<ul
|
|
86
|
+
v-else-if="request.kind === 'sceneTypes'"
|
|
87
|
+
class="player-menu__groups"
|
|
91
88
|
>
|
|
92
|
-
<
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@toggle="onGroupToggle($event, group)"
|
|
89
|
+
<li
|
|
90
|
+
v-for="group in request.groups"
|
|
91
|
+
:key="group.id"
|
|
96
92
|
>
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
93
|
+
<details
|
|
94
|
+
:open="group.active"
|
|
95
|
+
class="player-menu__group"
|
|
96
|
+
@toggle="onGroupToggle($event, group)"
|
|
97
|
+
>
|
|
98
|
+
<summary class="player-menu__summary">
|
|
99
|
+
<span
|
|
100
|
+
v-if="iconSvg(group.icon)"
|
|
101
|
+
class="player-menu__summary-icon"
|
|
102
|
+
v-html="iconSvg(group.icon)"
|
|
103
|
+
/>
|
|
104
|
+
<span class="player-menu__summary-title">{{ group.title }}</span>
|
|
105
|
+
<UiIcon
|
|
106
|
+
name="chevron-down"
|
|
107
|
+
size="16"
|
|
108
|
+
class="player-menu__summary-arrow"
|
|
109
|
+
/>
|
|
110
|
+
</summary>
|
|
111
|
+
<ul class="player-menu__scenes">
|
|
112
|
+
<li
|
|
113
|
+
v-for="scene in group.scenes"
|
|
114
|
+
:key="scene.start"
|
|
115
|
+
>
|
|
116
|
+
<button
|
|
117
|
+
:class="{ '--current': scene.current }"
|
|
118
|
+
class="player-menu__scene"
|
|
119
|
+
type="button"
|
|
120
|
+
@click="selectScene(group.id, scene.start)"
|
|
121
|
+
>
|
|
122
|
+
<span class="player-menu__scene-label">{{ scene.label }}</span>
|
|
123
|
+
<span class="player-menu__scene-time">{{ scene.time }}</span>
|
|
124
|
+
</button>
|
|
125
|
+
</li>
|
|
126
|
+
</ul>
|
|
127
|
+
</details>
|
|
128
|
+
</li>
|
|
129
|
+
</ul>
|
|
130
|
+
|
|
131
|
+
<!-- ⋯ и одиночные меню (скорость/качество/субтитры, если вынесены кнопками) -->
|
|
132
|
+
<template v-else-if="request.kind === 'menu'">
|
|
133
|
+
<section
|
|
134
|
+
v-for="(section, index) in request.sections"
|
|
135
|
+
:key="index"
|
|
136
|
+
class="player-menu__section"
|
|
137
|
+
>
|
|
138
|
+
<h3
|
|
139
|
+
v-if="section.title"
|
|
140
|
+
class="player-menu__section-title"
|
|
141
|
+
>
|
|
142
|
+
{{ section.title }}
|
|
143
|
+
</h3>
|
|
144
|
+
<ul class="player-menu__options">
|
|
111
145
|
<li
|
|
112
|
-
v-for="
|
|
113
|
-
:key="
|
|
146
|
+
v-for="item in section.items"
|
|
147
|
+
:key="item.value"
|
|
114
148
|
>
|
|
115
149
|
<button
|
|
116
|
-
:class="{ '--
|
|
117
|
-
class="player-
|
|
150
|
+
:class="{ '--active': item.active }"
|
|
151
|
+
class="player-menu__option"
|
|
118
152
|
type="button"
|
|
119
|
-
@click="
|
|
153
|
+
@click="pick(section.select, item.value)"
|
|
120
154
|
>
|
|
121
|
-
|
|
122
|
-
<span class="player-menu__scene-time">{{ scene.time }}</span>
|
|
155
|
+
{{ item.label }}
|
|
123
156
|
</button>
|
|
124
157
|
</li>
|
|
125
158
|
</ul>
|
|
126
|
-
</
|
|
127
|
-
</
|
|
128
|
-
</
|
|
129
|
-
|
|
130
|
-
<!-- ⋯ и одиночные меню (скорость/качество/субтитры, если вынесены кнопками) -->
|
|
131
|
-
<template v-else-if="request.kind === 'menu'">
|
|
132
|
-
<section
|
|
133
|
-
v-for="(section, index) in request.sections"
|
|
134
|
-
:key="index"
|
|
135
|
-
class="player-menu__section"
|
|
136
|
-
>
|
|
137
|
-
<h3
|
|
138
|
-
v-if="section.title"
|
|
139
|
-
class="player-menu__section-title"
|
|
140
|
-
>
|
|
141
|
-
{{ section.title }}
|
|
142
|
-
</h3>
|
|
143
|
-
<ul class="player-menu__options">
|
|
144
|
-
<li
|
|
145
|
-
v-for="item in section.items"
|
|
146
|
-
:key="item.value"
|
|
147
|
-
>
|
|
148
|
-
<button
|
|
149
|
-
:class="{ '--active': item.active }"
|
|
150
|
-
class="player-menu__option"
|
|
151
|
-
type="button"
|
|
152
|
-
@click="pick(section.select, item.value)"
|
|
153
|
-
>
|
|
154
|
-
{{ item.label }}
|
|
155
|
-
</button>
|
|
156
|
-
</li>
|
|
157
|
-
</ul>
|
|
158
|
-
</section>
|
|
159
|
-
</template>
|
|
160
|
-
</UiPopup>
|
|
159
|
+
</section>
|
|
160
|
+
</template>
|
|
161
|
+
</UiPopup>
|
|
162
|
+
</transition>
|
|
161
163
|
</template>
|
|
162
164
|
|
|
163
165
|
<script setup lang="ts">
|
|
@@ -213,12 +215,18 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
213
215
|
</script>
|
|
214
216
|
|
|
215
217
|
<style lang="scss">
|
|
216
|
-
// Фон шторки
|
|
218
|
+
// Фон шторки (bg-zinc-900); шапка/бордеры ui-popup уже совпадают с v0 (#0d0d0d, zinc-800).
|
|
217
219
|
.player-menu .ui-popup__wrapper,
|
|
218
220
|
.player-menu .ui-popup__content {
|
|
219
221
|
background-color: $player-menu-bg;
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
// Вертикальный воздух списка + safe-area снизу (py-2 pb-[env(safe-area-inset-bottom)] в v0).
|
|
225
|
+
// Сильный селектор — перебиваем padding:0 у .ui-popup--sheet на мобиле.
|
|
226
|
+
.player-menu.ui-popup[open].--sheet .ui-popup__content {
|
|
227
|
+
padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
|
|
228
|
+
}
|
|
229
|
+
|
|
222
230
|
.player-menu__rows,
|
|
223
231
|
.player-menu__groups,
|
|
224
232
|
.player-menu__options {
|
|
@@ -247,14 +255,26 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
247
255
|
}
|
|
248
256
|
}
|
|
249
257
|
|
|
258
|
+
// Без слота лейбл ui-toggle нулевой ширины → абсолютный трек уезжает за padding шторки.
|
|
259
|
+
// Резервируем ширину контрола и перекрашиваем вкл-состояние в indigo (в v0 bg-indigo-500).
|
|
260
|
+
.player-menu .ui-toggle {
|
|
261
|
+
flex-shrink: 0;
|
|
262
|
+
width: 36px;
|
|
263
|
+
height: 20px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.player-menu .ui-toggle.ui-toggle--checked::before {
|
|
267
|
+
background: $player-menu-toggle-bg--active;
|
|
268
|
+
}
|
|
269
|
+
|
|
250
270
|
.player-menu__label {
|
|
251
|
-
@include font-
|
|
271
|
+
@include font-md;
|
|
252
272
|
|
|
253
273
|
color: $player-menu-row-text;
|
|
254
274
|
}
|
|
255
275
|
|
|
256
276
|
.player-menu__value {
|
|
257
|
-
@include font-
|
|
277
|
+
@include font-md;
|
|
258
278
|
|
|
259
279
|
display: inline-flex;
|
|
260
280
|
align-items: center;
|
|
@@ -263,7 +283,7 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
263
283
|
}
|
|
264
284
|
|
|
265
285
|
.player-menu__option {
|
|
266
|
-
@include font-
|
|
286
|
+
@include font-md;
|
|
267
287
|
|
|
268
288
|
position: relative;
|
|
269
289
|
display: flex;
|
|
@@ -302,7 +322,7 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
302
322
|
align-items: center;
|
|
303
323
|
gap: 10px;
|
|
304
324
|
min-height: 52px;
|
|
305
|
-
padding:
|
|
325
|
+
padding: 8px 20px;
|
|
306
326
|
color: $player-menu-acc-head-text;
|
|
307
327
|
cursor: pointer;
|
|
308
328
|
list-style: none;
|
|
@@ -311,6 +331,10 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
311
331
|
&::-webkit-details-marker {
|
|
312
332
|
display: none;
|
|
313
333
|
}
|
|
334
|
+
|
|
335
|
+
@include hover(background-color) {
|
|
336
|
+
background-color: $player-menu-acc-head-bg--hover;
|
|
337
|
+
}
|
|
314
338
|
}
|
|
315
339
|
|
|
316
340
|
.player-menu__group[open] .player-menu__summary {
|
|
@@ -320,18 +344,19 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
320
344
|
.player-menu__summary-icon {
|
|
321
345
|
display: grid;
|
|
322
346
|
place-content: center;
|
|
323
|
-
|
|
347
|
+
flex-shrink: 0;
|
|
324
348
|
|
|
325
349
|
svg {
|
|
326
|
-
width:
|
|
327
|
-
height:
|
|
350
|
+
width: 16px;
|
|
351
|
+
height: 16px;
|
|
328
352
|
}
|
|
329
353
|
}
|
|
330
354
|
|
|
331
355
|
.player-menu__summary-title {
|
|
332
|
-
@include font-
|
|
356
|
+
@include font-md;
|
|
333
357
|
|
|
334
358
|
flex: 1;
|
|
359
|
+
font-weight: 500;
|
|
335
360
|
overflow: hidden;
|
|
336
361
|
text-overflow: ellipsis;
|
|
337
362
|
white-space: nowrap;
|
|
@@ -340,45 +365,61 @@ function onGroupToggle(event: Event, group: SceneGroup): void {
|
|
|
340
365
|
.player-menu__summary-arrow {
|
|
341
366
|
flex-shrink: 0;
|
|
342
367
|
color: $player-menu-icon;
|
|
343
|
-
transition: transform var(--transition);
|
|
368
|
+
transition: transform var(--transition), color var(--transition);
|
|
344
369
|
}
|
|
345
370
|
|
|
346
371
|
.player-menu__group[open] .player-menu__summary-arrow {
|
|
347
|
-
|
|
372
|
+
color: $player-menu-icon--open;
|
|
373
|
+
transform: rotate(180deg);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.player-menu__scenes {
|
|
377
|
+
padding-bottom: 4px;
|
|
348
378
|
}
|
|
349
379
|
|
|
350
380
|
.player-menu__scene {
|
|
351
|
-
@include font-
|
|
381
|
+
@include font-md;
|
|
352
382
|
|
|
353
383
|
position: relative;
|
|
354
384
|
display: flex;
|
|
355
385
|
align-items: center;
|
|
356
386
|
justify-content: space-between;
|
|
357
|
-
gap:
|
|
387
|
+
gap: 12px;
|
|
358
388
|
width: 100%;
|
|
359
|
-
min-height:
|
|
360
|
-
padding:
|
|
389
|
+
min-height: 48px;
|
|
390
|
+
padding: 6px 20px 6px 56px;
|
|
361
391
|
color: $player-menu-scene-text;
|
|
362
392
|
|
|
363
|
-
@include hover(background-color
|
|
393
|
+
@include hover(background-color) {
|
|
364
394
|
background-color: $player-menu-scene-bg--hover;
|
|
365
|
-
color: $player-menu-scene-text--current;
|
|
366
395
|
}
|
|
367
396
|
}
|
|
368
397
|
|
|
369
398
|
.player-menu__scene.--current {
|
|
370
399
|
background-color: $player-menu-scene-bg--current;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.player-menu__scene.--current::before {
|
|
403
|
+
content: '';
|
|
404
|
+
position: absolute;
|
|
405
|
+
inset-block: 0;
|
|
406
|
+
left: 0;
|
|
407
|
+
width: 2px;
|
|
408
|
+
background-color: $player-menu-scene-bar--current;
|
|
374
409
|
}
|
|
375
410
|
|
|
376
411
|
.player-menu__scene-label {
|
|
412
|
+
flex: 1;
|
|
377
413
|
overflow: hidden;
|
|
378
414
|
text-overflow: ellipsis;
|
|
379
415
|
white-space: nowrap;
|
|
380
416
|
}
|
|
381
417
|
|
|
418
|
+
.player-menu__scene.--current .player-menu__scene-label {
|
|
419
|
+
font-weight: 500;
|
|
420
|
+
color: $player-menu-scene-text--current;
|
|
421
|
+
}
|
|
422
|
+
|
|
382
423
|
.player-menu__scene-time {
|
|
383
424
|
@include font-xs;
|
|
384
425
|
|