itube-specs 0.0.366 → 0.0.368

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.
@@ -1,70 +1,69 @@
1
1
  <template>
2
- <ClientOnly>
3
- <div
4
- ref="dropdownRef"
5
- class="s-dropdown"
6
- :style="`--max-height: ${getMaxHeight}`"
7
- :class="[
2
+ <div
3
+ ref="dropdownRef"
4
+ class="s-dropdown"
5
+ :style="`--max-height: ${getMaxHeight}`"
6
+ :class="[
8
7
  {'--top': top},
9
8
  {'--right': right},
10
9
  {'--center': center},
11
10
  {'--open': open},
12
11
  {'--separate': separateLastChild},
13
12
  ]"
14
- @mouseleave="mouseHandler(false)"
15
- @mouseover="mouseHandler(true)"
13
+ @mouseleave="mouseHandler(false)"
14
+ @mouseover="mouseHandler(true)"
15
+ >
16
+ <div
17
+ class="s-dropdown__trigger"
18
+ @click="openDropdown"
16
19
  >
17
- <div
18
- class="s-dropdown__trigger"
19
- @click="openDropdown"
20
+ <slot name="trigger"></slot>
21
+ </div>
22
+ <transition name="s-dropdown" mode="out-in">
23
+ <dialog
24
+ v-if="useVIf ? open && $slots.items : true"
25
+ :style="!useVIf ? { display: (open && $slots.items) ? '' : 'none' } : {}"
26
+ ref="menuRef"
27
+ class="s-dropdown__menu"
28
+ :class="{'--open': open}"
29
+ @click="close"
20
30
  >
21
- <slot name="trigger"></slot>
22
- </div>
23
- <transition name="s-dropdown" mode="out-in">
24
- <dialog
25
- v-if="useVIf ? open && $slots.items : true"
26
- :style="!useVIf ? { display: (open && $slots.items) ? '' : 'none' } : {}"
27
- ref="menuRef"
28
- class="s-dropdown__menu"
29
- :class="{'--open': open}"
31
+ <button
32
+ class="s-dropdown__sheet-close _to-sm"
33
+ type="button"
34
+ @click="close"
35
+ ></button>
36
+ <button
37
+ class="s-dropdown__crest _to-sm"
38
+ type="button"
30
39
  @click="close"
31
40
  >
32
- <button
33
- class="s-dropdown__sheet-close _to-sm"
34
- type="button"
35
- @click="close"
36
- ></button>
37
- <button
38
- class="s-dropdown__crest _to-sm"
39
- type="button"
40
- @click="close"
41
- >
42
- <SIcon name="close" size="16"/>
43
- </button>
44
- <slot name="header"></slot>
45
- <div class="s-dropdown__menu-items" v-if="$slots.items">
46
- <slot name="items" v-bind="'s-dropdown__item'"></slot>
47
- </div>
48
- </dialog>
49
- </transition>
50
- </div>
51
- </ClientOnly>
41
+ <SIcon name="close" size="16"/>
42
+ </button>
43
+ <slot name="header"></slot>
44
+ <div class="s-dropdown__menu-items" v-if="$slots.items">
45
+ <slot name="items" v-bind="'s-dropdown__item'"></slot>
46
+ </div>
47
+ </dialog>
48
+ </transition>
49
+ </div>
52
50
  </template>
53
51
 
54
52
  <script setup lang="ts">
55
53
  // На компоненте обязательно вызывать пропсы слота и вешать слот пропс (className) на непосредственных детей
56
- import { onClickOutside, useScrollLock } from '@vueuse/core';
57
- import { isMobile } from '../../runtime';
54
+
55
+ import { onClickOutside } from '@vueuse/core';
56
+ import { scrollLock, isMobile } from '../../runtime';
58
57
  import type { CssBreakpoints } from '../../types';
59
58
 
60
- const dropdownRef = ref<HTMLDialogElement | null>(null);
61
- const menuRef = ref<HTMLDialogElement | null>(null);
59
+ const dropdownRef = ref()
60
+ const menuRef = ref()
62
61
 
63
62
  const props = withDefaults(defineProps<{
64
63
  top?: boolean;
65
64
  right?: boolean;
66
65
  center?: boolean;
67
- separateLastChild?: boolean;
66
+ separateLastChild?: boolean; // deprecated, вешать на нужный child класс модификатор --separate
68
67
  maxHeight?: string | number;
69
68
  openByClick?: boolean;
70
69
  useVIf?: boolean;
@@ -72,56 +71,52 @@ const props = withDefaults(defineProps<{
72
71
  useVIf: false
73
72
  });
74
73
 
75
- const open = ref(false);
74
+ const open = ref(false)
76
75
 
77
76
  const breakpoints = useAppConfig().cssBreakpoints as Record<CssBreakpoints, number>;
78
77
 
79
- // Блокируем скролл body при открытии на мобильных
80
- const bodyScrollLocked = useScrollLock(document.body);
81
-
82
78
  function close() {
83
- open.value = false;
79
+ open.value = false
84
80
 
85
81
  if (isMobile(breakpoints).value) {
86
82
  nextTick(() => {
87
- menuRef.value?.close?.();
88
- bodyScrollLocked.value = false; // разблокируем
89
- });
83
+ menuRef.value?.close?.()
84
+ scrollLock().unlockScroll()
85
+ })
90
86
  }
91
87
  }
92
88
 
93
89
  function openDropdown() {
94
90
  if (props.openByClick) {
95
- open.value = !open.value;
91
+ open.value = !open.value
96
92
  }
97
-
98
93
  if (isMobile(breakpoints).value) {
99
- open.value = true;
94
+ open.value = !open.value
100
95
 
101
96
  nextTick(() => {
102
97
  if (menuRef.value?.showModal) {
103
- menuRef.value.showModal();
104
- bodyScrollLocked.value = true; // блокируем
98
+ menuRef.value.showModal()
99
+ scrollLock().lockScroll()
105
100
  }
106
- });
101
+ })
107
102
  }
108
103
  }
109
104
 
110
105
  watch(open, (isOpen) => {
111
106
  if (isOpen) {
112
107
  onClickOutside(dropdownRef, () => {
113
- close();
114
- });
108
+ close()
109
+ })
115
110
  }
116
- }, { immediate: true });
111
+ }, { immediate: true })
117
112
 
118
113
  function mouseHandler(event: boolean) {
119
114
  if (!isMobile(breakpoints).value && !props.openByClick) {
120
- open.value = event;
115
+ open.value = event
121
116
  }
122
117
  }
123
118
 
124
119
  const getMaxHeight = computed(() => {
125
- return props.maxHeight ? `${props.maxHeight}px` : 'none';
126
- });
120
+ return props.maxHeight ? `${props.maxHeight}px` : 'none'
121
+ })
127
122
  </script>
@@ -1,97 +1,77 @@
1
1
  <template>
2
- <ClientOnly>
3
- <dialog
4
- ref="notification"
5
- class="s-notification"
6
- :class="{'--popup': popup}"
7
- @click="closeByBackdropClick"
8
- @cancel="close"
9
- >
10
- <div class="s-notification__wrapper">
11
- <header class="s-notification__header">
12
- <p
13
- v-if="$slots.title"
14
- class="s-notification__title"
15
- >
16
- <slot name="title"></slot>
17
- </p>
18
- <button
19
- class="s-notification__close"
20
- type="button"
21
- title="close"
22
- aria-label="close"
23
- @click="close"
24
- >
25
- <SIcon class="s-notification__close-icon" name="close" size="16"/>
26
- </button>
27
- </header>
28
- <div class="s-notification__content">
29
- <slot></slot>
30
- </div>
31
- <div
32
- v-if="$slots.footer"
33
- class="s-notification__footer"
2
+ <dialog
3
+ ref="notification"
4
+ class="s-notification"
5
+ :class="{'--popup': popup}"
6
+ @click="closeByBackdropClick"
7
+ @cancel="close"
8
+ >
9
+ <div class="s-notification__wrapper">
10
+ <header class="s-notification__header">
11
+ <p
12
+ v-if="$slots.title"
13
+ class="s-notification__title"
34
14
  >
35
- <slot name="footer"></slot>
36
- </div>
15
+ <slot name="title"></slot>
16
+ </p>
17
+ <button
18
+ class="s-notification__close"
19
+ type="button"
20
+ title="close"
21
+ aria-label="close"
22
+ @click="close"
23
+ >
24
+ <SIcon class="s-notification__close-icon" name="close" size="16"/>
25
+ </button>
26
+ </header>
27
+ <div class="s-notification__content">
28
+ <slot></slot>
29
+ </div>
30
+ <div
31
+ v-if="$slots.footer"
32
+ class="s-notification__footer"
33
+ >
34
+ <slot name="footer"></slot>
37
35
  </div>
38
- </dialog>
39
- </ClientOnly>
36
+ </div>
37
+ </dialog>
40
38
  </template>
41
39
 
42
40
  <script setup lang="ts">
43
- import { ref, watch, onBeforeUnmount } from 'vue';
44
- import { useScrollLock } from '@vueuse/core';
45
- import { onBackdropClick } from '../../runtime'; // оставляем, если используется где-то ещё
41
+ import { onBackdropClick, scrollLock } from '../../runtime';
46
42
 
47
- const notification = ref<HTMLDialogElement | null>(null);
43
+ const notification = ref()
48
44
 
49
45
  const emit = defineEmits<{
50
46
  (eventName: 'update:modelValue', value: boolean): void
51
47
  (eventName: 'close'): void
52
- }>();
48
+ }>()
53
49
 
54
50
  const props = defineProps<{
55
51
  modelValue: boolean
56
52
  popup?: boolean
57
- }>();
58
-
59
- // Блокировка скролла тела страницы (body) при открытом модальном окне
60
- const bodyElement = ref(document.body);
61
- const isBodyScrollLocked = useScrollLock(bodyElement);
53
+ }>()
62
54
 
63
- watch(
64
- () => props.modelValue,
65
- (newVal) => {
66
- if (newVal && props.popup) {
67
- // Открываем dialog и блокируем скролл
68
- notification.value?.showModal();
69
- isBodyScrollLocked.value = true;
70
- } else if (!newVal && props.popup) {
71
- // Закрываем и разблокируем
72
- notification.value?.close();
73
- isBodyScrollLocked.value = false;
74
- } else if (newVal && !props.popup) {
75
- notification.value?.show();
76
- } else if (!newVal && !props.popup) {
77
- notification.value?.close();
78
- }
79
- },
80
- { immediate: true }
81
- );
55
+ onMounted(() => {
56
+ if (props.popup) {
57
+ scrollLock().lockScroll()
58
+ notification.value.showModal()
59
+ } else {
60
+ notification.value.show()
61
+ }
62
+ })
82
63
 
83
- // Дополнительная очистка при размонтировании (на всякий случай)
84
64
  onBeforeUnmount(() => {
85
- isBodyScrollLocked.value = false;
86
- });
65
+ scrollLock().unlockScroll()
66
+ })
87
67
 
88
68
  function close() {
89
- emit('close');
90
- emit('update:modelValue', false);
69
+ emit('close')
70
+ emit('update:modelValue', false)
91
71
  }
92
72
 
93
73
  function closeByBackdropClick(event: Event) {
94
- const target = event.target as HTMLDialogElement;
95
- onBackdropClick(target, close);
74
+ const target = event.target as HTMLDialogElement
75
+ onBackdropClick(target, close)
96
76
  }
97
77
  </script>
@@ -1,95 +1,92 @@
1
1
  <template>
2
- <ClientOnly>
3
- <dialog
4
- ref="popupRef"
5
- class="s-popup"
6
- :class="[
2
+ <dialog
3
+ ref="popupRef"
4
+ class="s-popup"
5
+ :class="[
7
6
  {'--sheet': sheet},
8
7
  {'--transparent-backdrop': transparentBackdrop},
9
8
  {'--aside': $slots.aside}
10
9
  ]"
11
- @click="closeByBackdropClick"
12
- @cancel="close"
10
+ @click="closeByBackdropClick"
11
+ @cancel="close"
12
+ >
13
+ <div class="s-popup__wrapper">
14
+ <div
15
+ v-if="sheet"
16
+ class="s-popup__sheet"
13
17
  >
14
- <div class="s-popup__wrapper">
15
- <div
16
- v-if="sheet"
17
- class="s-popup__sheet"
18
- >
19
- <button
20
- class="s-popup__sheet-handler"
21
- type="button"
22
- @click="close"
23
- ></button>
24
- </div>
18
+ <button
19
+ class="s-popup__sheet-handler"
20
+ type="button"
21
+ @click="close"
22
+ ></button>
23
+ </div>
25
24
 
26
- <aside
27
- v-if="$slots.aside && !isMobile(breakpoints).value"
28
- class="s-popup__aside"
29
- >
30
- <slot name="aside"></slot>
31
- </aside>
25
+ <aside
26
+ v-if="$slots.aside && !isMobile(breakpoints).value"
27
+ class="s-popup__aside"
28
+ >
29
+ <slot name="aside"></slot>
30
+ </aside>
32
31
 
33
- <header
34
- class="s-popup__header"
35
- >
36
- <button
37
- v-if="back"
38
- class="s-popup__back"
39
- type="button"
40
- @click="$emit('back')"
41
- >
42
- <SIcon name="angle-left" size="24"/>
43
- </button>
44
- <div
45
- v-if="$slots.title"
46
- class="s-popup__title"
47
- >
48
- <slot name="title"></slot>
49
- </div>
50
- <button
51
- class="s-popup__close"
52
- type="button"
53
- @click="close"
54
- >
55
- <SIcon name="close" size="24"/>
56
- </button>
57
- </header>
58
- <div
59
- v-if="$slots.fixedContent"
60
- class="s-popup__subheader"
61
- >
62
- <slot name="fixedContent"></slot>
63
- </div>
64
- <div
65
- v-if="$slots.default"
66
- class="s-popup__content"
67
- >
68
- <slot></slot>
69
- </div>
70
- <div
71
- v-if="$slots.footer"
72
- class="s-popup__footer"
73
- >
74
- <slot name="footer"></slot>
75
- </div>
32
+ <header
33
+ class="s-popup__header"
34
+ >
35
+ <button
36
+ v-if="back"
37
+ class="s-popup__back"
38
+ type="button"
39
+ @click="$emit('back')"
40
+ >
41
+ <SIcon name="angle-left" size="24" />
42
+ </button>
43
+ <div
44
+ v-if="$slots.title"
45
+ class="s-popup__title"
46
+ >
47
+ <slot name="title"></slot>
76
48
  </div>
49
+ <button
50
+ class="s-popup__close"
51
+ type="button"
52
+ @click="close"
53
+ >
54
+ <SIcon name="close" size="24" />
55
+ </button>
56
+ </header>
57
+ <div
58
+ v-if="$slots.fixedContent"
59
+ class="s-popup__subheader"
60
+ >
61
+ <slot name="fixedContent"></slot>
62
+ </div>
63
+ <div
64
+ v-if="$slots.default"
65
+ class="s-popup__content"
66
+ >
67
+ <slot></slot>
68
+ </div>
69
+ <div
70
+ v-if="$slots.footer"
71
+ class="s-popup__footer"
72
+ >
73
+ <slot name="footer"></slot>
74
+ </div>
75
+ </div>
77
76
 
78
- <transition mode="out-in">
79
- <SSnackbar
80
- v-if="snackbarText && isSnackBarInPopup"
81
- />
82
- </transition>
83
- </dialog>
84
- </ClientOnly>
77
+ <transition mode="out-in">
78
+ <SSnackbar
79
+ v-if="snackbarText && isSnackBarInPopup"
80
+ />
81
+ </transition>
82
+ </dialog>
85
83
  </template>
86
84
 
87
85
  <script setup lang="ts">
88
- import { onBackdropClick, isMobile } from '../../runtime';
86
+ import { onBackdropClick, scrollLock, isMobile } from '../../runtime';
89
87
  import type { CssBreakpoints } from '../../types';
90
- import { useScrollLock } from '@vueuse/core';
91
88
 
92
- const { resetSnackbar } = useSnackbar();
89
+ const {resetSnackbar} = useSnackbar();
93
90
 
94
91
  const breakpoints = useAppConfig().cssBreakpoints as Record<CssBreakpoints, number>;
95
92
  const popupRef = ref()
@@ -108,40 +105,22 @@ const props = defineProps<{
108
105
  notModal?: boolean
109
106
  }>()
110
107
 
111
- const isLocked = useScrollLock(
112
- typeof document !== 'undefined' ? document.body : null
113
- );
114
-
115
- watch(
116
- () => props.modelValue,
117
- (newVal) => {
118
- if (newVal) {
119
- nextTick(() => {
120
- isLocked.value = true;
121
-
122
- if (props.notModal) {
123
- popupRef.value?.show();
124
- } else {
125
- popupRef.value?.showModal();
126
- }
127
- popupRef.value?.focus({ preventScroll: true });
128
- });
129
- } else {
130
- isLocked.value = false;
131
- }
132
- },
133
- { immediate: true }
134
- );
135
-
136
108
  onMounted(() => {
137
109
  isSnackBarInPopup.value = true;
138
110
  resetSnackbar();
139
- });
111
+ setTimeout(() => scrollLock().lockScroll(), 100);
112
+ if (props.notModal) {
113
+ popupRef.value.show();
114
+ } else {
115
+ popupRef.value.showModal();
116
+ }
117
+ popupRef.value.focus({ preventScroll: true })
118
+ })
140
119
 
141
120
  onBeforeUnmount(() => {
142
121
  isSnackBarInPopup.value = false;
143
- isLocked.value = false;
144
- });
122
+ scrollLock().unlockScroll();
123
+ })
145
124
 
146
125
  function close() {
147
126
  emit('close');
@@ -1,11 +1,17 @@
1
1
  import { computed, unref } from 'vue';
2
2
  import type { Ref } from 'vue';
3
3
  import { useRoute } from 'vue-router';
4
+ import type { IChipsItem } from '../types';
4
5
 
5
- export function useMeta(t, page: string, brandName: string, hasSort?: boolean, text?: Ref<string>, secondText?: Ref<string>) {
6
+ export function useMeta(t, page: string, brandName: string, sortOptions?: IChipsItem[], text?: Ref<string>, secondText?: Ref<string>) {
6
7
  const route = useRoute();
7
8
 
8
- const sortType = computed(() => route?.query?.['sort'] || 'trending');
9
+ const sortType = computed(() => {
10
+ const values = sortOptions?.map(item => item.value);
11
+ const queryValue = String(route?.query?.['sort']);
12
+ const DEFAULT_VALUE = 'trending';
13
+ return queryValue && values?.includes(queryValue) ? queryValue : DEFAULT_VALUE;
14
+ });
9
15
 
10
16
  function getPath(key: string) {
11
17
  const plainSlug = unref(text);
@@ -14,7 +20,7 @@ export function useMeta(t, page: string, brandName: string, hasSort?: boolean, t
14
20
  const pageText = unref(pageNumber) === 1 ? null : ` #${unref(pageNumber)}`;
15
21
 
16
22
  return t(
17
- `meta.${page}.${hasSort ? `${sortType.value}.` : ''}${key}`,
23
+ `meta.${page}.${sortOptions && sortOptions.length > 0 ? `${sortType.value}.` : ''}${key}`,
18
24
  {
19
25
  text: plainSlug,
20
26
  secondText: secondTextValue,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "itube-specs",
3
3
  "type": "module",
4
- "version": "0.0.366",
4
+ "version": "0.0.368",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./types/index.d.ts",
7
7
  "scripts": {