itube-specs 0.0.878 → 0.0.884

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/assets/icons/common/trash-bin.svg +1 -1
  2. package/assets/scss/mixins/_button.scss +0 -4
  3. package/assets/scss/mixins/_surface.scss +2 -2
  4. package/assets/scss/themes/dark/_theme.scss +51 -3
  5. package/assets/scss/themes/light/_theme.scss +51 -3
  6. package/assets/scss/vars/_palette.scss +5 -0
  7. package/components/card/history.vue +371 -0
  8. package/components/card/playlist.vue +5 -12
  9. package/components/card/{video/preview.vue → preview.vue} +9 -9
  10. package/components/card/video/index.vue +1 -1
  11. package/components/filter/selects.vue +0 -6
  12. package/components/grid/playlists.vue +28 -1
  13. package/components/library/item.vue +152 -0
  14. package/components/profile/delete.vue +9 -41
  15. package/components/section/nav-links.vue +10 -6
  16. package/components/section/toolbar.vue +2 -2
  17. package/components/ui/btn.vue +0 -4
  18. package/components/ui/confirm.vue +61 -0
  19. package/components/ui/toggle.vue +7 -1
  20. package/composables/__tests__/use-format-time-ago.test.ts +19 -0
  21. package/composables/use-format-time-ago.ts +15 -3
  22. package/composables/use-meta.ts +2 -2
  23. package/lib/index.ts +1 -0
  24. package/lib/scheme/categories-navigation.ts +2 -2
  25. package/lib/scheme/history-periods.ts +31 -0
  26. package/lib/scheme/sort-channels.ts +2 -2
  27. package/lib/scheme/sort-items-default.ts +2 -2
  28. package/lib/scheme/sort-models.ts +2 -2
  29. package/lib/scheme/sort-playlists.ts +2 -2
  30. package/package.json +2 -1
  31. package/pages/history.vue +307 -1
  32. package/pages/library.vue +361 -1
  33. package/runtime/utils/get-multiple-query.ts +2 -2
  34. package/runtime/utils/get-selected-query.ts +2 -2
  35. package/stubs/history.ts +65 -0
  36. package/stubs/library.ts +16 -0
  37. package/types/index.d.ts +1 -0
  38. package/types/nav-link-item.d.ts +18 -0
  39. package/utils/history/__tests__/group-by-watched-day.test.ts +66 -0
  40. package/utils/history/group-by-watched-day.ts +53 -0
@@ -1 +1 @@
1
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
1
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 11v6"/><path d="M14 11v6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
@@ -13,7 +13,6 @@ $button-variants: (
13
13
  'border': $button-primary-border,
14
14
  'border--hover': $button-primary-border,
15
15
  'border--active': $button-primary-border,
16
- 'icon': $button-primary-text,
17
16
  ),
18
17
  secondary: (
19
18
  'bg': $button-secondary-bg,
@@ -24,7 +23,6 @@ $button-variants: (
24
23
  'border': $button-secondary-border,
25
24
  'border--hover': $button-secondary-border,
26
25
  'border--active': $button-secondary-border--active,
27
- 'icon': $button-secondary-icon,
28
26
  ),
29
27
  muted: (
30
28
  'bg': $button-muted-bg,
@@ -35,7 +33,6 @@ $button-variants: (
35
33
  'border': $button-muted-border,
36
34
  'border--hover': $button-muted-border--hover,
37
35
  'border--active': $button-muted-border,
38
- 'icon': $button-muted-text,
39
36
  ),
40
37
  warning: (
41
38
  'bg': $button-warning-bg,
@@ -46,7 +43,6 @@ $button-variants: (
46
43
  'border': $button-warning-border,
47
44
  'border--hover': $button-warning-border,
48
45
  'border--active': $button-warning-border,
49
- 'icon': $button-warning-text,
50
46
  ),
51
47
  );
52
48
 
@@ -32,8 +32,8 @@
32
32
  // А вот опечатка в @include surface(...) иначе прошла бы молча, отсюда список.
33
33
  $surface-names: (overlay,);
34
34
  $surface-roles: (
35
- text: (--video-mini-card-title, --radio-text, --checkbox-text),
36
- text-muted: (--video-mini-card-channel, --video-mini-card-duration),
35
+ text: (--video-mini-card-title, --radio-text, --checkbox-text, --page-history-confirm-text),
36
+ text-muted: (--video-mini-card-channel, --video-mini-card-duration, --page-history-confirm-muted),
37
37
  control-bg: (--input-bg, --select-bg),
38
38
  control-compact-bg: (--input-s-bg,),
39
39
  control-bg--disabled: (--input-bg--disabled,),
@@ -204,7 +204,24 @@ $video-card-mini-title: $color-zinc-300;
204
204
  $video-card-mini-weight: 400;
205
205
  $video-card-user-text: $color-zinc-400;
206
206
  $video-card-user-bg: $color-zinc-700;
207
- $video-card-preview-loader-bg: linear-gradient(to right, $color-indigo-muted, $color-indigo-deep);
207
+ $card-preview-loader-bg: linear-gradient(to right, $color-indigo-muted, $color-indigo-deep);
208
+
209
+ // ─── History card ───
210
+ $history-card-bg: $color-zinc-900-40;
211
+ $history-card-wrapper-bg: $color-zinc-900-60;
212
+ $history-card-border: $color-zinc-800;
213
+ $history-card-border--hover: $color-zinc-700;
214
+ $history-card-poster-border: $color-zinc-700-50;
215
+ $history-card-title: $color-white;
216
+ $history-card-title--hover: $color-indigo-400;
217
+ $history-card-secondary: $color-zinc-500;
218
+ $history-card-user-text: $color-zinc-400;
219
+ $history-card-user-bg: $color-zinc-700;
220
+ $history-card-dropdown-icon: $color-zinc-500;
221
+ $history-card-dropdown-icon--hover: $color-white;
222
+ $history-card-progress-bg: $mono-white-50;
223
+ $history-card-progress-fill: $color-indigo-500;
224
+ $history-card-remaining: $color-indigo-400;
208
225
 
209
226
  // ─── Video card dropdown ───
210
227
  $video-card-dropdown-border: $color-zinc-800;
@@ -453,7 +470,6 @@ $button-secondary-text: $color-zinc-400;
453
470
  $button-secondary-text--active: $color-white;
454
471
  $button-secondary-border: $color-zinc-700-50;
455
472
  $button-secondary-border--active: $color-indigo-500;
456
- $button-secondary-icon: $color-indigo-600;
457
473
  $button-muted-bg: $color-zinc-800;
458
474
  $button-muted-text: $color-zinc-300;
459
475
  $button-muted-bg--hover: $color-zinc-700;
@@ -707,7 +723,6 @@ $filters-main-slider-border: $color-zinc-800;
707
723
  $filters-main-select-border--active: $color-indigo-500-50;
708
724
  $filters-main-select-bg--active: $color-indigo-600-20;
709
725
  $filters-main-select-text--active: $color-indigo-300;
710
- $filters-main-select-icon: $color-zinc-400;
711
726
  $filters-main-slider-content-bg: $color-zinc-900;
712
727
  $filters-main-bg--hover: $color-zinc-700-70;
713
728
 
@@ -932,6 +947,39 @@ $page-channels-border: $color-zinc-800;
932
947
  // ─── Page: channel ───
933
948
  $page-channel-border: $color-zinc-800;
934
949
 
950
+ // ─── Library item (карточка-ссылка) ───
951
+ $library-item-bg: $color-zinc-900-40;
952
+ $library-item-bg--hover: $color-zinc-900;
953
+ $library-item-border: $color-zinc-800;
954
+ $library-item-border--hover: $color-indigo-500-50;
955
+ $library-item-icon: $color-indigo-400;
956
+ $library-item-icon-bg: $color-indigo-500-10;
957
+ $library-item-icon-bg--hover: $color-indigo-500-20;
958
+ $library-item-icon-border: $color-indigo-500-20;
959
+ $library-item-icon-border--hover: $color-indigo-500-40;
960
+ $library-item-title: $color-white;
961
+ $library-item-title--hover: $color-indigo-400;
962
+ $library-item-subtitle: $color-zinc-500;
963
+ $library-item-badge-bg: $color-indigo-600-90;
964
+ $library-item-badge-text: $color-white;
965
+ $library-item-badge-bordered-border: $color-zinc-600;
966
+ $library-item-badge-bordered-text: $color-zinc-400;
967
+
968
+ // ─── Page: library ───
969
+ $page-library-heading: $color-white;
970
+ $page-library-heading-icon: $color-white;
971
+ $page-library-heading-icon-bg: $mono-white-10;
972
+ $page-library-toggle-text: $color-zinc-300;
973
+
974
+ // ─── Page: history ───
975
+ $page-history-group-title: $color-zinc-300;
976
+ $page-history-group-icon: $color-zinc-500;
977
+ $page-history-group-count: $color-zinc-500;
978
+ $page-history-confirm-text: $color-zinc-300;
979
+ $page-history-confirm-muted: $color-zinc-500;
980
+ $page-history-confirm-link: $color-indigo-400;
981
+ $page-history-confirm-link--hover: $color-indigo-300;
982
+
935
983
  // ─── Document ───
936
984
  $document-header-border: $color-zinc-700;
937
985
  $document-section-bg: $color-night;
@@ -261,9 +261,26 @@ $video-card-mini-title: $color-gray-900;
261
261
  $video-card-mini-weight: 500;
262
262
  $video-card-user-text: $color-gray-700;
263
263
  $video-card-user-bg: $color-gray-300;
264
- $video-card-preview-loader-bg: linear-gradient(to right, $color-indigo-muted, $color-indigo-deep);
264
+ $card-preview-loader-bg: linear-gradient(to right, $color-indigo-muted, $color-indigo-deep);
265
265
  $video-card-dropdown-size--hover: 1.25;
266
266
 
267
+ // ─── History card ───
268
+ $history-card-bg: $color-gray-100;
269
+ $history-card-wrapper-bg: $color-gray-100;
270
+ $history-card-border: transparent;
271
+ $history-card-border--hover: transparent;
272
+ $history-card-poster-border: transparent;
273
+ $history-card-title: $color-gray-900;
274
+ $history-card-title--hover: $color-gray-900;
275
+ $history-card-secondary: $color-gray-600;
276
+ $history-card-user-text: $color-gray-700;
277
+ $history-card-user-bg: $color-gray-300;
278
+ $history-card-dropdown-icon: $color-gray-600;
279
+ $history-card-dropdown-icon--hover: $color-gray-900;
280
+ $history-card-progress-bg: $color-gray-300;
281
+ $history-card-progress-fill: $color-indigo-500;
282
+ $history-card-remaining: $color-indigo-600;
283
+
267
284
  // ─── Video card dropdown ───
268
285
  $video-card-dropdown-border: transparent;
269
286
 
@@ -510,7 +527,6 @@ $button-secondary-text: $color-gray-700;
510
527
  $button-secondary-text--active: $color-white;
511
528
  $button-secondary-border: transparent;
512
529
  $button-secondary-border--active: $color-indigo-soft;
513
- $button-secondary-icon: $color-gray-700;
514
530
  $button-muted-bg: transparent;
515
531
  $button-muted-text: $color-gray-300;
516
532
  $button-muted-bg--hover: $color-slate-750;
@@ -737,7 +753,6 @@ $filters-main-slider-border: transparent;
737
753
  $filters-main-select-border--active: $color-indigo-500-50;
738
754
  $filters-main-select-bg--active: $color-gray-300;
739
755
  $filters-main-select-text--active: $color-gray-700;
740
- $filters-main-select-icon: $color-gray-700;
741
756
  $filters-main-slider-content-bg: $color-slate-800;
742
757
  $filters-main-bg--hover: $button-secondary-bg--hover;
743
758
 
@@ -962,6 +977,39 @@ $page-channels-border: transparent;
962
977
  // ─── Page: channel ───
963
978
  $page-channel-border: transparent;
964
979
 
980
+ // ─── Library item (карточка-ссылка) ───
981
+ $library-item-bg: $color-gray-100;
982
+ $library-item-bg--hover: $color-gray-200;
983
+ $library-item-border: transparent;
984
+ $library-item-border--hover: $color-indigo-500-50;
985
+ $library-item-icon: $color-indigo-600;
986
+ $library-item-icon-bg: $color-indigo-500-10;
987
+ $library-item-icon-bg--hover: $color-indigo-500-20;
988
+ $library-item-icon-border: transparent;
989
+ $library-item-icon-border--hover: transparent;
990
+ $library-item-title: $color-gray-900;
991
+ $library-item-title--hover: $color-indigo-600;
992
+ $library-item-subtitle: $color-gray-500;
993
+ $library-item-badge-bg: $color-indigo-600;
994
+ $library-item-badge-text: $color-white;
995
+ $library-item-badge-bordered-border: $color-gray-300;
996
+ $library-item-badge-bordered-text: $color-gray-600;
997
+
998
+ // ─── Page: library ───
999
+ $page-library-heading: $color-gray-900;
1000
+ $page-library-heading-icon: $color-gray-900;
1001
+ $page-library-heading-icon-bg: $color-gray-200;
1002
+ $page-library-toggle-text: $color-gray-700;
1003
+
1004
+ // ─── Page: history ───
1005
+ $page-history-group-title: $color-gray-900;
1006
+ $page-history-group-icon: $color-gray-500;
1007
+ $page-history-group-count: $color-gray-500;
1008
+ $page-history-confirm-text: $color-gray-900;
1009
+ $page-history-confirm-muted: $color-gray-500;
1010
+ $page-history-confirm-link: $color-indigo-400;
1011
+ $page-history-confirm-link--hover: $color-indigo-300;
1012
+
965
1013
  // ─── Document ───
966
1014
  $document-header-border: $color-gray-300;
967
1015
  $document-section-bg: $color-gray-200;
@@ -5,7 +5,9 @@ $color-zinc-950-0: lab(2.51107% .242703 -.886115 / 0%); // zinc-950 / 0%
5
5
  $color-zinc-950-75: lab(2.51107% .242703 -.886115 / 75%); // zinc-950 / 75%
6
6
  $color-zinc-950-90: lab(2.51107% .242703 -.886115 / 90%); // zinc-950 / 90%
7
7
  $color-zinc-900: lab(8.30603% .618205 -2.16572); // #18181b
8
+ $color-zinc-900-60: lab(8.30603% .618205 -2.16572 / 60%); // zinc-900 / 60%
8
9
  $color-zinc-900-50: lab(8.30603% .618205 -2.16572 / 50%); // #18181b
10
+ $color-zinc-900-40: lab(8.30603% .618205 -2.16572 / 40%); // zinc-900 / 40%
9
11
  $color-zinc-900-95: lab(8.30603% .618205 -2.16572 / 95%); // #18181b
10
12
  $color-zinc-900-98: lab(8.30603% .618205 -2.16572 / 98%); // #18181b
11
13
  $color-zinc-850: lab(11.9084% 1.043 -2.7081); // #1f1f23
@@ -50,9 +52,12 @@ $color-indigo-300: lab(74.0235% 8.54138 -41.6075); // #a4b3ff
50
52
  $color-indigo-400: lab(59.866% 22.4834 -64.4485); // #7d87ff
51
53
  $color-indigo-500: lab(48.295% 38.3129 -81.9673); // #625fff
52
54
  $color-indigo-500-10: lab(48.295% 38.3129 -81.9673 / 10%);
55
+ $color-indigo-500-20: lab(48.295% 38.3129 -81.9673 / 20%);
56
+ $color-indigo-500-40: lab(48.295% 38.3129 -81.9673 / 40%);
53
57
  $color-indigo-500-50: lab(48.295% 38.3129 -81.9673 / 50%);
54
58
  $color-indigo-600: lab(38.4009% 52.6132 -92.3857); // #4f39f6
55
59
  $color-indigo-600-20: lab(38.4009% 52.6132 -92.3857 / 20%);
60
+ $color-indigo-600-90: lab(38.4009% 52.6132 -92.3857 / 90%);
56
61
  $color-indigo-700: lab(32.4486% 49.2217 -84.6695); // #432dd7
57
62
  $color-indigo-800: lab(26.6645% 37.9804 -68.6402); // #372aac
58
63
  $color-indigo-900: lab(23.3911% 24.6978 -50.4718); // #312c85
@@ -0,0 +1,371 @@
1
+ <!-- Карточка истории просмотров: постер с полосой прогресса, канал и время последнего просмотра -->
2
+ <template>
3
+ <div class="card-history">
4
+ <NuxtLink
5
+ :to="link"
6
+ class="card-history__poster-wrapper"
7
+ @mouseenter.passive="startPreviewByHover(previewId)"
8
+ @mouseleave.passive="stopPreviewByHover(previewId)"
9
+ @touchstart.passive="startPreviewByTouch(previewId)"
10
+ >
11
+ <UiImg
12
+ :src="currentPoster"
13
+ :urls="card.thumbUrls"
14
+ :loading="loading"
15
+ :priority="priority"
16
+ :sizes="`(max-width: ${CSS_BREAKPOINTS.lg}px) 180px, 480px`"
17
+ :alt="card.title"
18
+ class="card-history__poster"
19
+ width="480"
20
+ height="270"
21
+ @error="posterError = true"
22
+ />
23
+ <CardPreview
24
+ v-if="isPreviewShow && card.previewUrl"
25
+ :url="card.previewUrl"
26
+ />
27
+ <UiLabel
28
+ v-if="card.quality"
29
+ :text="`${card.quality}p`"
30
+ class="card-history__resolution"
31
+ theme="yellow"
32
+ />
33
+ <UiLabel
34
+ v-if="card.duration"
35
+ :text="duration"
36
+ class="card-history__duration"
37
+ theme="black"
38
+ />
39
+ <span
40
+ :style="{ '--card-history-progress': `${progress}%` }"
41
+ :aria-label="t('watched_percent', { percent: progress })"
42
+ :aria-valuenow="progress"
43
+ class="card-history__progress"
44
+ role="progressbar"
45
+ aria-valuemin="0"
46
+ aria-valuemax="100"
47
+ />
48
+ </NuxtLink>
49
+
50
+ <div class="card-history__wrapper">
51
+ <component
52
+ :is="channelComponent"
53
+ :to="channelLink"
54
+ class="card-history__logo-wrapper"
55
+ >
56
+ <UiImg
57
+ v-if="card.channelAvatar"
58
+ :src="card.channelAvatar"
59
+ :alt="card.channelName"
60
+ :loading="loading"
61
+ class="card-history__channel-logo"
62
+ width="32"
63
+ height="32"
64
+ sizes="32px"
65
+ />
66
+ <span
67
+ v-else
68
+ class="card-history__user"
69
+ >U</span>
70
+ </component>
71
+
72
+ <NuxtLink
73
+ :to="link"
74
+ :title="card.title"
75
+ class="card-history__title _truncate"
76
+ >{{ card.title }}
77
+ </NuxtLink>
78
+
79
+ <p class="card-history__meta">
80
+ <NuxtLink
81
+ v-if="card.channelName"
82
+ :to="channelLink"
83
+ class="card-history__channel _truncate"
84
+ >{{ card.channelName }}</NuxtLink>
85
+ <span
86
+ :class="{'--remaining': remaining}"
87
+ class="card-history__watched"
88
+ >
89
+ <UiIcon
90
+ name="clock"
91
+ size="12"
92
+ />
93
+ {{ remaining ? remainingText : watchedAgo }}
94
+ </span>
95
+ </p>
96
+
97
+ <LazyCardVideoDropdown
98
+ v-if="dropdownMounted"
99
+ :card="videoCard"
100
+ class="card-history__dropdown"
101
+ show-remove
102
+ show-share
103
+ auto-open
104
+ @share="emit('share', videoCard)"
105
+ @remove="emit('remove', card)"
106
+ />
107
+ <button
108
+ v-else
109
+ :aria-label="t('open_menu')"
110
+ class="card-history__dropdown card-video-dropdown__trigger"
111
+ type="button"
112
+ @click="dropdownMounted = true"
113
+ >
114
+ <UiIcon
115
+ name="dots-vertical"
116
+ size="18"
117
+ />
118
+ </button>
119
+ </div>
120
+ </div>
121
+ </template>
122
+
123
+ <script setup lang="ts">
124
+ import type { HistoryStubCard } from '../../stubs/history';
125
+ import type { IVideoCard } from '../../types';
126
+ import { convertString, getDuration } from '../../runtime';
127
+ import { CSS_BREAKPOINTS } from '../../config/css-breakpoints';
128
+
129
+ const props = defineProps<{
130
+ card: HistoryStubCard
131
+ loading?: 'eager' | 'lazy'
132
+ priority?: boolean
133
+ /** Развилка мета-строки: вместо «когда смотрели» — сколько осталось до конца («Продолжить просмотр») */
134
+ remaining?: boolean
135
+ }>();
136
+
137
+ const emit = defineEmits<{
138
+ (e: 'remove', card: HistoryStubCard): void
139
+ (e: 'share', card: IVideoCard): void
140
+ }>();
141
+
142
+ const { t, locale } = useI18n();
143
+
144
+ const { generateLink } = useGenerateLink();
145
+
146
+ const NuxtLinkComponent = resolveComponent('NuxtLink');
147
+
148
+ const channelComponent = computed(() => props.card.channelName ? NuxtLinkComponent : 'span');
149
+
150
+ const posterError = ref(false);
151
+
152
+ const currentPoster = computed(() => {
153
+ if (posterError.value || !props.card.thumbUrls) return '/img/placeholder.webp';
154
+ return undefined;
155
+ });
156
+
157
+ const previewId = useId();
158
+ const { activePreviewId, startPreviewByHover, stopPreviewByHover, startPreviewByTouch } = useVideoPreview();
159
+
160
+ const isPreviewShow = computed(() => activePreviewId.value === previewId);
161
+
162
+ const duration = computed(() => getDuration(props.card.duration));
163
+
164
+ const progress = computed(() => Math.min(100, Math.max(0, Math.round(props.card.progress))));
165
+
166
+ const watchedAgo = computed(() => useFormatTimeAgo(props.card.watchedAt, locale.value, true));
167
+
168
+ const remainingText = computed(() => {
169
+ const left = Math.ceil((props.card.duration * (100 - progress.value)) / 100 / 60);
170
+ return t('minutes_left', { count: Math.max(left, 1) });
171
+ });
172
+
173
+ const link = computed(() => generateLink(`/videos/${props.card.id}`));
174
+
175
+ const channelLink = computed(() => props.card.channelName
176
+ ? generateLink(`/channels/${convertString().toSlug(props.card.channelName)}`)
177
+ : undefined);
178
+
179
+ /** Дропдаун и репорт работают с обычной карточкой видео — переиспользуем её контракт. */
180
+ const videoCard = computed<IVideoCard>(() => ({
181
+ guid: props.card.guid,
182
+ id: props.card.id,
183
+ title: props.card.title,
184
+ duration: props.card.duration,
185
+ quality: props.card.quality,
186
+ channelName: props.card.channelName,
187
+ channelAvatar: props.card.channelAvatar,
188
+ thumbUrls: props.card.thumbUrls,
189
+ }));
190
+
191
+ const dropdownMounted = ref(false);
192
+ </script>
193
+
194
+ <style lang="scss">
195
+ $inset-label: 8px;
196
+ $progress-height: 4px;
197
+
198
+ .card-history {
199
+ @include video-card;
200
+
201
+ row-gap: 0;
202
+ background-color: $history-card-bg;
203
+ border: 1px solid $history-card-border;
204
+ border-radius: $radius-xl;
205
+
206
+ @include to-br(xs) {
207
+ touch-action: manipulation;
208
+ }
209
+
210
+ @include hover(border-color, box-shadow) {
211
+ border-color: $history-card-border--hover;
212
+ box-shadow: $card-ring-shadow--hover;
213
+ }
214
+ }
215
+
216
+ .card-history__poster-wrapper {
217
+ @include video-card-poster;
218
+
219
+ border-radius: calc($radius-xl - 1px) calc($radius-xl - 1px) 0 0;
220
+ border-bottom: 1px solid $history-card-poster-border;
221
+ }
222
+
223
+ .card-history__poster {
224
+ width: 100%;
225
+ height: auto;
226
+ object-fit: cover;
227
+ aspect-ratio: 16/9;
228
+ }
229
+
230
+ .card-history__duration,
231
+ .card-history__resolution {
232
+ position: absolute;
233
+ }
234
+
235
+ .card-history__resolution {
236
+ top: $inset-label;
237
+ right: $inset-label;
238
+ }
239
+
240
+ .card-history__duration {
241
+ bottom: $inset-label + $progress-height;
242
+ left: $inset-label;
243
+ }
244
+
245
+ .card-history__progress {
246
+ position: absolute;
247
+ right: 0;
248
+ bottom: 0;
249
+ left: 0;
250
+ height: $progress-height;
251
+ background-color: $history-card-progress-bg;
252
+
253
+ &::after {
254
+ content: '';
255
+ display: block;
256
+ width: var(--card-history-progress, 0%);
257
+ height: 100%;
258
+ background-color: $history-card-progress-fill;
259
+ }
260
+ }
261
+
262
+ .card-history__wrapper {
263
+ display: grid;
264
+ column-gap: 8px;
265
+ grid-template-columns: 32px 1fr auto;
266
+ align-items: start;
267
+ padding: 12px;
268
+ color: $history-card-secondary;
269
+ background-color: $history-card-wrapper-bg;
270
+ border-radius: 0 0 calc($radius-xl - 1px) calc($radius-xl - 1px);
271
+ }
272
+
273
+ .card-history__logo-wrapper {
274
+ grid-row: 1/3;
275
+ grid-column: 1;
276
+ }
277
+
278
+ .card-history__channel-logo {
279
+ border-radius: $radius-full;
280
+ }
281
+
282
+ .card-history__user {
283
+ @include font-xs;
284
+
285
+ width: 32px;
286
+ height: 32px;
287
+ display: grid;
288
+ place-content: center;
289
+ font-weight: 700;
290
+ text-transform: uppercase;
291
+ color: $history-card-user-text;
292
+ background-color: $history-card-user-bg;
293
+ border-radius: $radius-full;
294
+ }
295
+
296
+ .card-history__title {
297
+ @include font-sm;
298
+
299
+ --line-clamp: 2;
300
+
301
+ grid-row: 1;
302
+ grid-column: 2;
303
+ color: $history-card-title;
304
+
305
+ @include hover(color) {
306
+ color: $history-card-title--hover;
307
+ }
308
+ }
309
+
310
+ .card-history__meta {
311
+ @include font-xs;
312
+
313
+ display: flex;
314
+ align-items: center;
315
+ grid-row: 2;
316
+ grid-column: 2;
317
+ margin-top: 6px;
318
+ font-weight: 400;
319
+ color: $history-card-secondary;
320
+ }
321
+
322
+ .card-history__channel {
323
+ color: $history-card-secondary;
324
+ }
325
+
326
+ .card-history__channel + .card-history__watched::before {
327
+ content: '·';
328
+ margin-inline: 6px;
329
+ }
330
+
331
+ .card-history__watched {
332
+ display: flex;
333
+ align-items: center;
334
+ column-gap: 4px;
335
+ flex-shrink: 0;
336
+ }
337
+
338
+ .card-history__watched.--remaining {
339
+ color: $history-card-remaining;
340
+ }
341
+
342
+ .card-history__dropdown {
343
+ grid-row: 1/3;
344
+ grid-column: 3;
345
+ align-self: start;
346
+ color: $history-card-dropdown-icon;
347
+
348
+ @include hover(color) {
349
+ color: $history-card-dropdown-icon--hover;
350
+ }
351
+ }
352
+
353
+ @include to-br(xs) {
354
+ .card-history__logo-wrapper {
355
+ display: none;
356
+ }
357
+
358
+ .card-history__wrapper {
359
+ grid-template-columns: 1fr auto;
360
+ }
361
+
362
+ .card-history__title,
363
+ .card-history__meta {
364
+ grid-column: 1;
365
+ }
366
+
367
+ .card-history__dropdown {
368
+ grid-column: 2;
369
+ }
370
+ }
371
+ </style>
@@ -141,7 +141,7 @@
141
141
  <button
142
142
  :class="className"
143
143
  type="button"
144
- @click="isShareOpen = true"
144
+ @click="emit('share', card)"
145
145
  >
146
146
  <UiIcon
147
147
  name="share"
@@ -160,15 +160,6 @@
160
160
  {{ card.searchTags.join(' · ')}}
161
161
  </p>
162
162
  </div>
163
-
164
- <ShareMain
165
- v-model="isShareOpen"
166
- :url="link"
167
- >
168
- <template #card>
169
- <CardPlaylistMini :card="card" />
170
- </template>
171
- </ShareMain>
172
163
  </div>
173
164
  </template>
174
165
 
@@ -184,12 +175,14 @@ const props = defineProps<{
184
175
  priority?: boolean
185
176
  }>();
186
177
 
178
+ const emit = defineEmits<{
179
+ (e: 'share', card: IPlaylistCard): void
180
+ }>();
181
+
187
182
  const { t } = useI18n();
188
183
 
189
184
  const { generateLink } = useGenerateLink();
190
185
 
191
- const isShareOpen = ref(false);
192
-
193
186
  const userProfileData = computed(() => useState<IProfileData>('profileData').value);
194
187
 
195
188
  const { isAuthorized } = useUser(AuthorizationApiService);