itube-specs 0.0.762 → 0.0.764

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.
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <section class="s-categories-letter">
3
+ <div
4
+ v-for="(items, letter) in categories"
5
+ class="s-categories-letter__block"
6
+ :key="`s-categories-letter-${String(letter)}`"
7
+ >
8
+ <SLetter :text="getLetter(letter)" />
9
+ <SCategoriesList :items="items" />
10
+ </div>
11
+ </section>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import type { ICategoryCard } from '../../types';
16
+
17
+ defineProps<{
18
+ categories: Record<string, Array<ICategoryCard>>
19
+ }>()
20
+
21
+ function getLetter(letter: string) {
22
+ if (letter.toLowerCase() === 'post') {
23
+ return '#'
24
+ }
25
+ return letter
26
+ }
27
+ </script>
28
+
29
+ <style lang="scss">
30
+ .s-categories-letter {
31
+ display: grid;
32
+ row-gap: 48px;
33
+
34
+ @include to-br(sm) {
35
+ max-width: calc(100vw - calc(var(--container-padding-inline) * 2));
36
+ overflow: auto;
37
+ }
38
+ }
39
+
40
+ .s-categories-letter__block {
41
+ display: flex;
42
+ gap: 16px;
43
+ align-items: start;
44
+ content-visibility: auto;
45
+ contain-intrinsic-size: auto 300px;
46
+
47
+ @include to-br(sm) {
48
+ flex-direction: column;
49
+ }
50
+ }
51
+
52
+ .s-categories-letter__block:first-os-type {
53
+ border-top: none;
54
+ padding-top: 0;
55
+ }
56
+ </style>
@@ -0,0 +1,146 @@
1
+ <template>
2
+ <div class="s-categories-list">
3
+ <NuxtLink
4
+ v-for="(category, index) in items"
5
+ class="s-categories-list__link"
6
+ :data-count="category.videosCount"
7
+ :class="{'--top': category.isTop}"
8
+ :key="`category-all-${category.guid}`"
9
+ :to="localePath(`/categories/${slug(category.name)}`)"
10
+ >
11
+ {{ category.title }}
12
+ <img
13
+ v-if="category.icon"
14
+ class="s-categories-list__link-image"
15
+ :src="`/icons/flags/${category.icon}.svg`"
16
+ width="17"
17
+ height="17"
18
+ loading="lazy"
19
+ :alt="category.icon"
20
+ />
21
+ </NuxtLink>
22
+ <NuxtLink
23
+ v-if="allCategories"
24
+ class="s-categories-list__link --all"
25
+ :to="localePath('/categories')"
26
+ >
27
+ {{ t('all_categories') }}
28
+ </NuxtLink>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import type { ICategoryCard } from '../../types';
34
+ import { convertString } from '../../runtime';
35
+
36
+ defineProps<{
37
+ items: Array<ICategoryCard>
38
+ allCategories?: boolean
39
+ }>()
40
+
41
+ function slug(name: string) {
42
+ return convertString().toSlug(name);
43
+ }
44
+
45
+ const localePath = useLocalePath();
46
+ const { t } = useI18n();
47
+ </script>
48
+
49
+ <style lang="scss">
50
+ .s-categories-list {
51
+ overflow: hidden;
52
+ width: 100%;
53
+
54
+ @include to-br(sm) {
55
+ display: flex;
56
+ flex-wrap: wrap;
57
+ column-gap: 8px;
58
+ row-gap: 6px;
59
+ }
60
+ @include from-br(sm) {
61
+ column-count: 3;
62
+ column-gap: 24px;
63
+ }
64
+ @include from-br(md) {
65
+ column-count: 4;
66
+ }
67
+ @include from-br(lg) {
68
+ column-count: 5;
69
+ }
70
+ }
71
+
72
+ .s-categories-list__link {
73
+ @include font-sm;
74
+
75
+ @include hover(color) {
76
+ color: $categories-link-text--hover;
77
+ }
78
+ @include from-br(sm) {
79
+
80
+ display: flex;
81
+ column-gap: 8px;
82
+ align-items: baseline;
83
+ color: $categories-link-text;
84
+ margin-bottom: 6px;
85
+ padding-block: 4px;
86
+ }
87
+ @include to-br(sm) {
88
+ display: flex;
89
+ column-gap: 6px;
90
+ align-items: center;
91
+ padding: 8px 12px;
92
+ background-color: $categories-link-mobile-bg;
93
+ border-radius: $radius-lg;
94
+ color: $categories-link-mobile-text;
95
+ border: 1px solid $categories-link-mobile-border;
96
+ }
97
+ }
98
+
99
+ .s-categories-list__link.--top {
100
+ font-weight: 600;
101
+ color: $categories-link-text-top;
102
+
103
+ @include to-br(sm) {
104
+ background-color: $categories-link-top-bg;
105
+ }
106
+ }
107
+
108
+ .s-categories-list__hot-icon {
109
+ align-self: start;
110
+ flex-shrink: 0;
111
+ }
112
+
113
+ .s-categories-list__link::after {
114
+ @include from-br(sm) {
115
+ @include font-xs;
116
+
117
+ content: attr(data-count);
118
+ color: $categories-link-count;
119
+ flex-shrink: 0;
120
+ }
121
+ }
122
+
123
+ .s-categories-list__link-image {
124
+ width: 17px;
125
+ height: 12px;
126
+ object-fit: cover;
127
+ align-self: start;
128
+ margin-top: 5px;
129
+ flex-shrink: 0;
130
+ }
131
+
132
+ .s-categories-list__link.--all {
133
+ @include font-sm;
134
+
135
+ display: block;
136
+ padding: 8px 16px;
137
+ border-radius: $radius-lg;
138
+ background-color: $categories-link-all-bg;
139
+ color: $categories-link-all-text;
140
+ width: max-content;
141
+
142
+ @include hover(background-color) {
143
+ background-color: $categories-link-all-bg--hover;
144
+ }
145
+ }
146
+ </style>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <SNavigationLinks
3
+ :items="categoriesNavigation"
4
+ theme="secondary"
5
+ />
6
+ <SExpandRow
7
+ class="s-categories-navigation__alphabet"
8
+ :class="{'_from-sm': hideOnMobile}"
9
+ :items="alphabetItems"
10
+ alphabet
11
+ >
12
+ <SChips
13
+ v-for="(item, index) in alphabetItems"
14
+ :item="item"
15
+ :class="{ '--all': item.value === '' }"
16
+ is-link
17
+ alphabet
18
+ :key="`categories-chips-${index}`"
19
+ />
20
+ </SExpandRow>
21
+ </template>
22
+
23
+ <script setup lang="ts">
24
+ import { categoriesNavigation } from '../../lib';
25
+ import { IChipsItem } from '../../types';
26
+
27
+ const props = defineProps<{
28
+ items: IChipsItem[]
29
+ hideOnMobile?: boolean
30
+ }>()
31
+
32
+ const { t } = useI18n();
33
+
34
+ const alphabetItems = computed<IChipsItem[]>(() => [
35
+ {
36
+ title: t('all'),
37
+ value: '',
38
+ prefix: 'categories/all',
39
+ },
40
+ ...(props.items || []),
41
+ ]);
42
+ </script>
43
+
44
+ <style lang="scss">
45
+ .s-categories-navigation__alphabet {
46
+ margin-top: 16px;
47
+ }
48
+ </style>
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <section v-if="items && items.length > 0" class="s-categories-section">
3
+ <SLetter v-if="text" :text="text"/>
4
+ <h2
5
+ class="s-categories-section__title _title"
6
+ v-else-if="title"
7
+ >
8
+ <SIcon
9
+ v-if="icon"
10
+ class="s-categories-section__title-icon"
11
+ :name="icon"
12
+ prefix="categories"
13
+ size="24"
14
+ />
15
+ {{ title }}</h2>
16
+ <SGridCategories
17
+ :categories="items"
18
+ priority
19
+ >
20
+ <!-- <div-->
21
+ <!-- v-if="allLink"-->
22
+ <!-- class="s-categories-section__more"-->
23
+ <!-- >-->
24
+ <!-- <SImg-->
25
+ <!-- alt="category-image"-->
26
+ <!-- class="s-categories-section__more-img"-->
27
+ <!-- sizes="50vw sm:30vw md:250px"-->
28
+ <!-- :src="items[0].thumbUrl || ''"-->
29
+ <!-- width="176"-->
30
+ <!-- height="88"-->
31
+ <!-- />-->
32
+ <!-- <SLink-->
33
+ <!-- :to="allLink"-->
34
+ <!-- class="s-categories-section__more-button"-->
35
+ <!-- theme="primary"-->
36
+ <!-- >{{ t('more') }}</SLink>-->
37
+ <!-- </div>-->
38
+ </SGridCategories>
39
+ </section>
40
+ </template>
41
+
42
+ <script setup lang="ts">
43
+ import type { ICategoryCard } from '../../types';
44
+
45
+ defineProps<{
46
+ items: ICategoryCard[] | null
47
+ icon?: string
48
+ allLink?: string
49
+ text?: string
50
+ title?: string
51
+ }>();
52
+ </script>
53
+
54
+ <style lang="scss">
55
+ .s-categories-section {
56
+ display: grid;
57
+ row-gap: 16px;
58
+ align-items: start;
59
+ align-content: start;
60
+ }
61
+
62
+ .s-categories-section__title {
63
+ display: flex;
64
+ align-items: center;
65
+ column-gap: 8px;
66
+ margin-bottom: 0;
67
+ }
68
+
69
+ .s-categories-section__title-icon {
70
+ color: $categories-section-icon;
71
+ }
72
+
73
+ //.s-categories-section__more {
74
+ // position: relative;
75
+ // display: grid;
76
+ // place-content: center;
77
+ // aspect-ratio: 16/9;
78
+ // overflow: hidden;
79
+ //}
80
+ //
81
+ //.s-categories-section__more::after {
82
+ // position: absolute;
83
+ // inset: 0;
84
+ // content: '';
85
+ // background: linear-gradient(0deg, $bg-fade-90 0%, $bg-fade-90 100%);
86
+ //}
87
+ //
88
+ //.s-categories-section__more-img {
89
+ // position: absolute;
90
+ // inset: 0;
91
+ // border-radius: 8px;
92
+ // width: 100%;
93
+ // height: 100%;
94
+ //}
95
+ //
96
+ //.s-categories-section__more-button {
97
+ // position: relative;
98
+ // z-index: $z-index-plus;
99
+ // text-transform: capitalize;
100
+ // aspect-ratio: 16/9;
101
+ //}
102
+ </style>
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <section class="s-letter-groups">
3
+ <div
4
+ v-for="(groupItems, letter) in grouped"
5
+ class="s-letter-groups__block"
6
+ :key="`s-letter-groups-${String(letter)}`"
7
+ >
8
+ <SLetter :text="String(letter)" />
9
+ <slot :items="groupItems" />
10
+ </div>
11
+ </section>
12
+ </template>
13
+
14
+ <script setup lang="ts" generic="T extends Record<string, any>">
15
+ const props = defineProps<{
16
+ items: T[];
17
+ titleKey?: string;
18
+ }>();
19
+
20
+ const grouped = computed(() => {
21
+ const groups: Record<string, T[]> = {};
22
+ const field = props.titleKey ?? 'title';
23
+ for (const item of props.items) {
24
+ const firstChar = String(item[field] ?? '')[0]?.toUpperCase() ?? '#';
25
+ const key = /[A-Z]/.test(firstChar) ? firstChar : '#';
26
+ if (!groups[key]) groups[key] = [];
27
+ groups[key].push(item);
28
+ }
29
+ return Object.fromEntries(
30
+ Object.entries(groups).sort(([a], [b]) => {
31
+ if (a === '#') return 1;
32
+ if (b === '#') return -1;
33
+ return a.localeCompare(b);
34
+ })
35
+ );
36
+ });
37
+ </script>
38
+
39
+ <style lang="scss">
40
+ .s-letter-groups {
41
+ display: grid;
42
+ row-gap: 20px;
43
+
44
+ @include from-br(sm) {
45
+ row-gap: 48px;
46
+ }
47
+ }
48
+
49
+ .s-letter-groups__block {
50
+ display: grid;
51
+ row-gap: 16px;
52
+ }
53
+ </style>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <h2 class="s-letter">{{ text }}</h2>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ defineProps<{
7
+ text: string
8
+ }>()
9
+ </script>
10
+
11
+ <style lang="scss">
12
+ .s-letter {
13
+ --size: #{$letter-size};
14
+
15
+ @include font-sm;
16
+
17
+ display: grid;
18
+ place-content: center;
19
+ width: var(--size);
20
+ height: var(--size);
21
+ border-radius: $radius-full;
22
+ background-color: $letter-bg;
23
+ text-transform: uppercase;
24
+ color: $letter-text;
25
+ font-feature-settings: 'cv11' on;
26
+ font-weight: 600;
27
+ }
28
+ </style>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <div>
3
+ <h2 class="s-page-videos__title --categories _title">{{ t('main_categories') }}</h2>
4
+
5
+ <SCategoriesLetter
6
+ :categories="categories"
7
+ />
8
+ <SSeoFooterText v-if="footerText" :text="footerText" :links-link="footerLinksLink"/>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import type { ICategoryCard } from '../../types';
14
+
15
+ defineProps<{
16
+ categories: Record<string, Array<ICategoryCard>>
17
+ footerText?: string
18
+ footerLinksLink?: string
19
+ }>();
20
+
21
+ const { t } = useI18n();
22
+ </script>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.762",
4
+ "version": "0.0.764",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {
@@ -10,6 +10,9 @@
10
10
  "eslint fix": "npx eslint . --ext .ts,.vue,.js --fix",
11
11
  "test": "NODE_OPTIONS='--no-warnings' vitest"
12
12
  },
13
+ "engines": {
14
+ "node": ">=22.12.0"
15
+ },
13
16
  "exports": {
14
17
  ".": {
15
18
  "types": "./types/index.d.ts",
@@ -47,7 +50,7 @@
47
50
  "@vue/test-utils": "^2.4.6",
48
51
  "eslint": "^9.37.0",
49
52
  "happy-dom": "^18.0.1",
50
- "nuxt": "3.17.6",
53
+ "nuxt": "^3.21.8",
51
54
  "typescript": "^5.9.3",
52
55
  "vitest": "^3.2.4",
53
56
  "vue": "3.5.17"