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.
@@ -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('timeline_markers') },
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
- <UiPopup
7
- v-if="open && request"
8
- v-model="open"
9
- sheet
10
- :back="!!drill"
11
- class="player-menu"
12
- @back="drill = null"
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
- <li
24
- v-for="option in drill.options"
25
- :key="option.value"
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
- <button
28
- :class="{ '--active': option.active }"
29
- class="player-menu__option"
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
- {{ option.label }}
34
- </button>
35
- </li>
36
- </ul>
37
-
38
- <!-- Шестерёнка: тоглы + строки-дриллы -->
39
- <ul
40
- v-else-if="request.kind === 'settings'"
41
- class="player-menu__rows"
42
- >
43
- <li
44
- v-for="entry in request.entries"
45
- :key="entry.key"
46
- class="player-menu__row"
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
- <div
49
- v-if="entry.toggle"
50
- class="player-menu__toggle-row"
44
+ <li
45
+ v-for="entry in request.entries"
46
+ :key="entry.key"
47
+ class="player-menu__row"
51
48
  >
52
- <span class="player-menu__label">{{ entry.label }}</span>
53
- <UiToggle
54
- :model-value="entry.toggle.value"
55
- @update:model-value="entry.toggle.set(!!$event)"
56
- />
57
- </div>
58
- <button
59
- v-else-if="entry.options && entry.select"
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
- </span>
72
- </button>
73
- <div
74
- v-else
75
- class="player-menu__toggle-row"
76
- >
77
- <span class="player-menu__label">{{ entry.label }}</span>
78
- <span class="player-menu__value">{{ entry.value }}</span>
79
- </div>
80
- </li>
81
- </ul>
82
-
83
- <!-- Тайм-коды: аккордеон типов сцен -->
84
- <ul
85
- v-else-if="request.kind === 'sceneTypes'"
86
- class="player-menu__groups"
87
- >
88
- <li
89
- v-for="group in request.groups"
90
- :key="group.id"
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
- <details
93
- :open="group.active"
94
- class="player-menu__group"
95
- @toggle="onGroupToggle($event, group)"
89
+ <li
90
+ v-for="group in request.groups"
91
+ :key="group.id"
96
92
  >
97
- <summary class="player-menu__summary">
98
- <span
99
- v-if="iconSvg(group.icon)"
100
- class="player-menu__summary-icon"
101
- v-html="iconSvg(group.icon)"
102
- />
103
- <span class="player-menu__summary-title">{{ group.title }}</span>
104
- <UiIcon
105
- name="angle-right"
106
- size="16"
107
- class="player-menu__summary-arrow"
108
- />
109
- </summary>
110
- <ul class="player-menu__scenes">
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="scene in group.scenes"
113
- :key="scene.start"
146
+ v-for="item in section.items"
147
+ :key="item.value"
114
148
  >
115
149
  <button
116
- :class="{ '--current': scene.current }"
117
- class="player-menu__scene"
150
+ :class="{ '--active': item.active }"
151
+ class="player-menu__option"
118
152
  type="button"
119
- @click="selectScene(group.id, scene.start)"
153
+ @click="pick(section.select, item.value)"
120
154
  >
121
- <span class="player-menu__scene-label">{{ scene.label }}</span>
122
- <span class="player-menu__scene-time">{{ scene.time }}</span>
155
+ {{ item.label }}
123
156
  </button>
124
157
  </li>
125
158
  </ul>
126
- </details>
127
- </li>
128
- </ul>
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
- // Фон шторки под нативную (bg-zinc-900); шапка/бордеры ui-popup уже совпадают (#0d0d0d, zinc-800).
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-sm;
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-sm;
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-sm;
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: 13px 20px;
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
- color: $player-menu-icon;
347
+ flex-shrink: 0;
324
348
 
325
349
  svg {
326
- width: 20px;
327
- height: 20px;
350
+ width: 16px;
351
+ height: 16px;
328
352
  }
329
353
  }
330
354
 
331
355
  .player-menu__summary-title {
332
- @include font-sm;
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
- transform: rotate(90deg);
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-sm;
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: 16px;
387
+ gap: 12px;
358
388
  width: 100%;
359
- min-height: 44px;
360
- padding: 10px 20px 10px 48px;
389
+ min-height: 48px;
390
+ padding: 6px 20px 6px 56px;
361
391
  color: $player-menu-scene-text;
362
392
 
363
- @include hover(background-color, 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
- color: $player-menu-scene-text--current;
372
- font-weight: 500;
373
- box-shadow: inset 3px 0 $player-menu-scene-bar--current;
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
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.826",
4
+ "version": "0.0.828",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {