itube-specs 0.0.195

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 (169) hide show
  1. package/README.md +121 -0
  2. package/components/cards/f-video-mini-card.vue +49 -0
  3. package/components/grids/f-grid-categories.vue +20 -0
  4. package/components/grids/f-grid-channels.vue +23 -0
  5. package/components/grids/f-grid-models.vue +25 -0
  6. package/components/grids/f-grid-playlists.vue +21 -0
  7. package/components/grids/f-grid-videos.vue +33 -0
  8. package/components/page-components/f-breadcrumbs.vue +44 -0
  9. package/components/page-components/f-chips-panel.vue +101 -0
  10. package/components/page-components/f-pagination.vue +206 -0
  11. package/components/page-components/f-report.vue +221 -0
  12. package/components/page-components/f-share.vue +96 -0
  13. package/components/page-components/f-sort.vue +57 -0
  14. package/components/page-components/f-videos-title.vue +20 -0
  15. package/components/ui/f-button.vue +50 -0
  16. package/components/ui/f-checkbox.vue +55 -0
  17. package/components/ui/f-chips.vue +116 -0
  18. package/components/ui/f-count.vue +12 -0
  19. package/components/ui/f-country.vue +26 -0
  20. package/components/ui/f-dropdown.vue +122 -0
  21. package/components/ui/f-icon.vue +19 -0
  22. package/components/ui/f-img.vue +46 -0
  23. package/components/ui/f-input.vue +162 -0
  24. package/components/ui/f-label.vue +20 -0
  25. package/components/ui/f-link.vue +33 -0
  26. package/components/ui/f-model-tag.vue +28 -0
  27. package/components/ui/f-notification.vue +77 -0
  28. package/components/ui/f-popup.vue +136 -0
  29. package/components/ui/f-radio.vue +56 -0
  30. package/components/ui/f-select.vue +88 -0
  31. package/components/ui/f-slider.vue +55 -0
  32. package/components/ui/f-snackbar.vue +47 -0
  33. package/components/ui/f-timestamp.vue +51 -0
  34. package/components/ui/f-toggle.vue +29 -0
  35. package/composables/use-antiadblock-domains.ts +20 -0
  36. package/composables/use-auth-popup.ts +25 -0
  37. package/composables/use-convert-query-categories.ts +7 -0
  38. package/composables/use-generate-link.ts +30 -0
  39. package/composables/use-get-pure-route-name.ts +5 -0
  40. package/composables/use-get-videos-filter-request.ts +30 -0
  41. package/composables/use-meta.ts +42 -0
  42. package/composables/use-playlist-edit.ts +36 -0
  43. package/composables/use-report-popup.ts +21 -0
  44. package/composables/use-seo-links.ts +87 -0
  45. package/composables/use-share-popup.ts +23 -0
  46. package/composables/use-snackbar.ts +52 -0
  47. package/composables/use-test-composable.ts +3 -0
  48. package/lib/alphabet-items.ts +2 -0
  49. package/lib/contact-forms-scheme.ts +98 -0
  50. package/lib/contacts/report-issue-items.ts +5 -0
  51. package/lib/contacts/report-malware-items.ts +6 -0
  52. package/lib/contacts/report-reasons-items.ts +12 -0
  53. package/lib/contacts/report-wrong-items.ts +6 -0
  54. package/lib/index.ts +7 -0
  55. package/lib/report-forms-scheme.ts +205 -0
  56. package/nuxt.config.ts +20 -0
  57. package/package.json +53 -0
  58. package/runtime/enums/async-data.ts +48 -0
  59. package/runtime/enums/auth-step.ts +5 -0
  60. package/runtime/enums/contacts-subjects.ts +7 -0
  61. package/runtime/enums/languages.ts +9 -0
  62. package/runtime/enums/niche.ts +6 -0
  63. package/runtime/enums/playlist-step.ts +5 -0
  64. package/runtime/enums/playlist-type.ts +4 -0
  65. package/runtime/enums/report-forms-subjects.ts +7 -0
  66. package/runtime/index.ts +51 -0
  67. package/runtime/utils/cleaners/clean-category-card.ts +9 -0
  68. package/runtime/utils/cleaners/clean-category-info.ts +9 -0
  69. package/runtime/utils/cleaners/clean-channel-card.ts +12 -0
  70. package/runtime/utils/cleaners/clean-channel-info.ts +13 -0
  71. package/runtime/utils/cleaners/clean-model-card.ts +9 -0
  72. package/runtime/utils/cleaners/clean-model-info.ts +11 -0
  73. package/runtime/utils/cleaners/clean-playlist-card.ts +16 -0
  74. package/runtime/utils/cleaners/clean-playlist-data.ts +15 -0
  75. package/runtime/utils/cleaners/clean-playlist-video.ts +12 -0
  76. package/runtime/utils/cleaners/clean-profile-data.ts +11 -0
  77. package/runtime/utils/cleaners/clean-user-playlists-card.ts +11 -0
  78. package/runtime/utils/cleaners/clean-video-card.ts +19 -0
  79. package/runtime/utils/cleaners/clean-video-data.ts +27 -0
  80. package/runtime/utils/compress-image.ts +27 -0
  81. package/runtime/utils/converters/convert-categories-to-chips.ts +13 -0
  82. package/runtime/utils/converters/convert-categories-to-footer.ts +11 -0
  83. package/runtime/utils/converters/convert-date-to-timestamp.ts +37 -0
  84. package/runtime/utils/converters/convert-model-card-to-chips.ts +13 -0
  85. package/runtime/utils/converters/convert-string.ts +56 -0
  86. package/runtime/utils/converters/group-categories-by-first-letter.ts +24 -0
  87. package/runtime/utils/converters/group-objects-by-first-letter.ts +16 -0
  88. package/runtime/utils/format-date.ts +12 -0
  89. package/runtime/utils/format-number.ts +12 -0
  90. package/runtime/utils/format-time-ago.ts +21 -0
  91. package/runtime/utils/get-duration.ts +17 -0
  92. package/runtime/utils/get-month.ts +22 -0
  93. package/runtime/utils/get-multiple-query.ts +26 -0
  94. package/runtime/utils/get-selected-query.ts +6 -0
  95. package/runtime/utils/is-mobile.ts +15 -0
  96. package/runtime/utils/normalize-url.ts +43 -0
  97. package/runtime/utils/on-backdrop-click.ts +5 -0
  98. package/runtime/utils/scroll-lock.ts +28 -0
  99. package/runtime/utils/server/abort-controller.ts +14 -0
  100. package/runtime/utils/server/api-helper.ts +41 -0
  101. package/runtime/utils/server/get-url-with-proxied-params.ts +6 -0
  102. package/runtime/utils/server/parse-api-error.ts +14 -0
  103. package/runtime/utils/server/server-api-helper.ts +28 -0
  104. package/runtime/utils/validate-email.ts +4 -0
  105. package/runtime/utils/validate-password.ts +3 -0
  106. package/runtime/utils/validate-phone.ts +4 -0
  107. package/runtime/utils/validate-username.ts +4 -0
  108. package/runtime/utils/video-data-add-model-icon.ts +20 -0
  109. package/runtime/utils/vtt-helper.ts +86 -0
  110. package/types/authorization-forms.d.ts +16 -0
  111. package/types/breadcrumb-item.d.ts +4 -0
  112. package/types/button-sizes.d.ts +1 -0
  113. package/types/button-themes.d.ts +1 -0
  114. package/types/card-info.d.ts +22 -0
  115. package/types/category-card.d.ts +8 -0
  116. package/types/change-email-form.d.ts +3 -0
  117. package/types/change-password-form.d.ts +4 -0
  118. package/types/channel-card.d.ts +10 -0
  119. package/types/chips-item.d.ts +8 -0
  120. package/types/contacts-form.d.ts +10 -0
  121. package/types/contacts-scheme.d.ts +14 -0
  122. package/types/country.d.ts +5 -0
  123. package/types/css-breakpoints.d.ts +1 -0
  124. package/types/filter-scheme.d.ts +37 -0
  125. package/types/fluid-player.d.ts +226 -0
  126. package/types/gender.d.ts +5 -0
  127. package/types/group-categories.d.ts +15 -0
  128. package/types/index.d.ts +59 -0
  129. package/types/input-types.d.ts +1 -0
  130. package/types/link-item.d.ts +6 -0
  131. package/types/model-card.d.ts +7 -0
  132. package/types/model-filter-payload.d.ts +4 -0
  133. package/types/model-filter.d.ts +15 -0
  134. package/types/model-group.d.ts +5 -0
  135. package/types/model-tag.d.ts +5 -0
  136. package/types/multi-suggest.d.ts +105 -0
  137. package/types/navigation-items.d.ts +10 -0
  138. package/types/paginated-response.d.ts +8 -0
  139. package/types/parameter-model.d.ts +14 -0
  140. package/types/playlist-card.d.ts +16 -0
  141. package/types/playlist-data.d.ts +15 -0
  142. package/types/playlist-info-type.d.ts +28 -0
  143. package/types/playlist-video-form.d.ts +9 -0
  144. package/types/profile-data.d.ts +9 -0
  145. package/types/raw/raw-category-card.d.ts +23 -0
  146. package/types/raw/raw-category-info.d.ts +23 -0
  147. package/types/raw/raw-channel-card.d.ts +29 -0
  148. package/types/raw/raw-channel-info.d.ts +29 -0
  149. package/types/raw/raw-model-card.d.ts +53 -0
  150. package/types/raw/raw-model-info.d.ts +54 -0
  151. package/types/raw/raw-playlist-card.d.ts +27 -0
  152. package/types/raw/raw-playlist-data.d.ts +29 -0
  153. package/types/raw/raw-playlist-user.d.ts +24 -0
  154. package/types/raw/raw-playlist-video.d.ts +18 -0
  155. package/types/raw/raw-profile-data.d.ts +22 -0
  156. package/types/raw/raw-video-card.d.ts +78 -0
  157. package/types/raw/raw-video-data.d.ts +53 -0
  158. package/types/recovery-password-form.d.ts +4 -0
  159. package/types/related-phrases.d.ts +6 -0
  160. package/types/report-form.d.ts +9 -0
  161. package/types/report-scheme.d.ts +21 -0
  162. package/types/request-filters.d.ts +13 -0
  163. package/types/request-pagination.d.ts +5 -0
  164. package/types/search-top-models.d.ts +6 -0
  165. package/types/select-item.d.ts +10 -0
  166. package/types/tab-item.d.ts +6 -0
  167. package/types/thumbs-urls.d.ts +13 -0
  168. package/types/video-card.d.ts +18 -0
  169. package/types/video-data.d.ts +36 -0
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <div
3
+ ref="dropdownRef"
4
+ class="f-dropdown"
5
+ :style="`--max-height: ${getMaxHeight}`"
6
+ :class="[
7
+ {'--top': top},
8
+ {'--right': right},
9
+ {'--center': center},
10
+ {'--open': open},
11
+ {'--separate': separateLastChild},
12
+ ]"
13
+ @mouseleave="mouseHandler(false)"
14
+ @mouseover="mouseHandler(true)"
15
+ >
16
+ <div
17
+ class="f-dropdown__trigger"
18
+ @click="openDropdown"
19
+ >
20
+ <slot name="trigger"></slot>
21
+ </div>
22
+ <transition name="f-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="f-dropdown__menu"
28
+ :class="{'--open': open}"
29
+ @click="close"
30
+ >
31
+ <button
32
+ class="f-dropdown__sheet-close _to-sm"
33
+ type="button"
34
+ @click="close"
35
+ ></button>
36
+ <button
37
+ class="f-dropdown__crest _to-sm"
38
+ type="button"
39
+ @click="close"
40
+ >
41
+ <FIcon name="close" size="16"/>
42
+ </button>
43
+ <slot name="header"></slot>
44
+ <div class="f-dropdown__menu-items" v-if="$slots.items">
45
+ <slot name="items" v-bind="'f-dropdown__item'"></slot>
46
+ </div>
47
+ </dialog>
48
+ </transition>
49
+ </div>
50
+ </template>
51
+
52
+ <script setup lang="ts">
53
+ // На компоненте обязательно вызывать пропсы слота и вешать слот пропс (className) на непосредственных детей
54
+
55
+ import { onClickOutside } from '@vueuse/core';
56
+ import { scrollLock, isMobile } from '../../runtime';
57
+ import type { CssBreakpoints } from '../../types';
58
+
59
+ const dropdownRef = ref()
60
+ const menuRef = ref()
61
+
62
+ const props = withDefaults(defineProps<{
63
+ top?: boolean;
64
+ right?: boolean;
65
+ center?: boolean;
66
+ separateLastChild?: boolean; // deprecated, вешать на нужный child класс модификатор --separate
67
+ maxHeight?: string | number;
68
+ openByClick?: boolean;
69
+ useVIf?: boolean;
70
+ }>(), {
71
+ useVIf: false
72
+ });
73
+
74
+ const open = ref(false)
75
+
76
+ const breakpoints = useAppConfig().cssBreakpoints as Record<CssBreakpoints, number>;
77
+
78
+ function close() {
79
+ open.value = false
80
+
81
+ if (isMobile(breakpoints).value) {
82
+ nextTick(() => {
83
+ menuRef.value?.close?.()
84
+ scrollLock().unlockScroll()
85
+ })
86
+ }
87
+ }
88
+
89
+ function openDropdown() {
90
+ if (props.openByClick) {
91
+ open.value = !open.value
92
+ }
93
+ if (isMobile(breakpoints).value) {
94
+ open.value = !open.value
95
+
96
+ nextTick(() => {
97
+ if (menuRef.value?.showModal) {
98
+ menuRef.value.showModal()
99
+ scrollLock().lockScroll()
100
+ }
101
+ })
102
+ }
103
+ }
104
+
105
+ watch(open, (isOpen) => {
106
+ if (isOpen) {
107
+ onClickOutside(dropdownRef, () => {
108
+ close()
109
+ })
110
+ }
111
+ }, { immediate: true })
112
+
113
+ function mouseHandler(event: boolean) {
114
+ if (!isMobile(breakpoints).value && !props.openByClick) {
115
+ open.value = event
116
+ }
117
+ }
118
+
119
+ const getMaxHeight = computed(() => {
120
+ return props.maxHeight ? `${props.maxHeight}px` : 'none'
121
+ })
122
+ </script>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <Icon
3
+ class="f-icon"
4
+ :name="`${prefix}:${name}`"
5
+ :size="size"
6
+ />
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ withDefaults(defineProps<{
11
+ prefix?: string
12
+ name: string
13
+ size?: string
14
+ }>(), {
15
+ size: '20',
16
+ prefix: 'custom'
17
+ }
18
+ )
19
+ </script>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <NuxtImg
3
+ v-if="!isStaticImg"
4
+ v-bind="{
5
+ ...$attrs,
6
+ fetchpriority: priority ? 'high' : undefined
7
+ }"
8
+ :src="src"
9
+ :width="width"
10
+ :height="height"
11
+ :sizes="sizes"
12
+ :alt="alt"
13
+ :loading="loading"
14
+ :fit="fit"
15
+ />
16
+ <img
17
+ v-else
18
+ v-bind="$attrs"
19
+ :src="src"
20
+ :loading="loading"
21
+ :width="width"
22
+ :height="height"
23
+ :sizes="sizes"
24
+ :alt="alt"
25
+ :fetchpriority="priority ? 'high' : 'auto'"
26
+ >
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ // https://image.nuxt.com/usage/nuxt-img
31
+ const props = withDefaults(defineProps<{
32
+ src: string | Blob,
33
+ width: string | number,
34
+ height: string | number,
35
+ sizes: string,
36
+ alt?: string,
37
+ loading?: 'lazy' | 'eager',
38
+ fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside',
39
+ priority?: boolean,
40
+ }>(), {
41
+ loading: 'lazy',
42
+ fit: 'cover',
43
+ })
44
+
45
+ const isStaticImg = computed(() => String(props.src).startsWith('/img'));
46
+ </script>
@@ -0,0 +1,162 @@
1
+ <template>
2
+ <div
3
+ class="f-input"
4
+ :class="[
5
+ {'f-input--filled': isFilled || isAutoFilled},
6
+ {'f-input--focused': isFocused},
7
+ {'f-input--disabled': disabled},
8
+ {'f-input--error': error},
9
+ {'f-input--textarea': isTextArea},
10
+ {'f-input--icon': isPassword || icon},
11
+ `f-input--${size}`,
12
+ ]"
13
+ >
14
+ <label
15
+ v-if="isTextArea"
16
+ class="f-input__label f-input__label--external"
17
+ :for="name"
18
+ >
19
+ {{ label }}
20
+ </label>
21
+ <div class="f-input__wrapper">
22
+ <textarea
23
+ v-if="isTextArea"
24
+ class="f-input__input"
25
+ rows="3"
26
+ :value="modelValue"
27
+ :name="name"
28
+ :id="name"
29
+ :tabindex="disabled ? '-1' : '0'"
30
+ @input="onInput"
31
+ @focus="onFocus"
32
+ @blur="onBlur"
33
+ spellcheck="false"
34
+ @keyup.enter="(event) => emit('enter', event)"
35
+ v-bind="$attrs"
36
+ ></textarea>
37
+ <input
38
+ v-else
39
+ class="f-input__input"
40
+ :id="name"
41
+ :name="name"
42
+ :type="showText ? 'text' : type"
43
+ :inputmode="inputmode"
44
+ :value="normalizedValue"
45
+ :autocomplete="autocomplete"
46
+ :autofocus="autofocus"
47
+ :tabindex="disabled ? '-1' : '0'"
48
+ autocapitalize="off"
49
+ @input="onInput"
50
+ @focus="onFocus"
51
+ :placeholder="label"
52
+ @blur="onBlur"
53
+ spellcheck="false"
54
+ @keyup.enter="(event) => emit('enter', event)"
55
+ v-bind="$attrs"
56
+ />
57
+ <span
58
+ v-if="!isTextArea && isFilled"
59
+ class="f-input__label">
60
+ {{ label }}
61
+ </span>
62
+ <button
63
+ v-if="isPassword || icon"
64
+ type="button"
65
+ class="f-input__button"
66
+ @click="onButtonInputClick"
67
+ >
68
+ <FIcon
69
+ :name="isPassword ? 'show' : icon || ''"
70
+ class="f-input__button-icon"
71
+ size="24"
72
+ />
73
+ </button>
74
+ </div>
75
+ <!-- <p-->
76
+ <!-- v-if="error"-->
77
+ <!-- class="f-input__error"-->
78
+ <!-- >-->
79
+ <!-- <FIcon-->
80
+ <!-- name="danger"-->
81
+ <!-- size="16"-->
82
+ <!-- />-->
83
+ <!-- {{ error }}-->
84
+ <!-- </p>-->
85
+ </div>
86
+ </template>
87
+
88
+ <script setup lang="ts">
89
+ import type { InputTypes } from '../../types';
90
+
91
+ const props = withDefaults(defineProps<{
92
+ modelValue: string | number | undefined
93
+ type?: InputTypes
94
+ inputmode?: 'text' | 'numeric' | 'email'
95
+ error?: boolean
96
+ success?: string | boolean
97
+ size?: 'm' | 's'
98
+ autofocus?: boolean
99
+ disabled?: boolean
100
+ autocomplete?: string
101
+ name?: string
102
+ label?: string
103
+ icon?: string
104
+ }>(), {
105
+ type: 'text',
106
+ inputmode: 'text',
107
+ size: 'm'
108
+ })
109
+
110
+ const emit = defineEmits<{
111
+ (eventName: 'update:modelValue', value: string): void
112
+ (eventName: 'focus', event: FocusEvent): void
113
+ (eventName: 'blur', event: FocusEvent): void
114
+ (eventName: 'enter', event: KeyboardEvent): void
115
+ (eventName: 'update:error', value: boolean): void
116
+ }>()
117
+
118
+ const showText = ref(false)
119
+
120
+ const isTextArea = computed(() => props.type === 'textarea')
121
+
122
+ const isFilled = computed(() => {
123
+ return props.modelValue && String(props.modelValue).length > 0
124
+ })
125
+
126
+ const isFocused = ref(false)
127
+ const isAutoFilled = ref(false)
128
+ const isPassword = computed(() => props.type === 'password')
129
+
130
+ function onFocus(event: FocusEvent) {
131
+ isFocused.value = true
132
+ isAutoFilled.value = false
133
+ emit('focus', event)
134
+ }
135
+
136
+ function onBlur(event: FocusEvent) {
137
+ isFocused.value = false
138
+ emit('blur', event)
139
+ }
140
+
141
+ function onInput(event: Event) {
142
+ emit('update:modelValue', event.target?.value);
143
+ if (props.error) {
144
+ emit('update:error', false);
145
+ }
146
+ }
147
+
148
+ function onButtonInputClick() {
149
+ if (props.type === 'password') {
150
+ showText.value = !showText.value
151
+ }
152
+ }
153
+
154
+ const isDate = computed(() => props.type === 'date');
155
+
156
+ const normalizedValue = computed(() => {
157
+ if (isDate.value && props.modelValue === '1970-01-01') {
158
+ return ''
159
+ }
160
+ return props.modelValue;
161
+ })
162
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <span
3
+ class="f-label"
4
+ :class="`--${theme}`"
5
+ :data-text="text"
6
+ >
7
+ <slot></slot>
8
+ </span>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ withDefaults(
13
+ defineProps<{
14
+ theme?: 'default' | 'primary' | 'primary-gradient' | 'yellow' | 'green' | 'white' | 'black' | 'backdrop' | 'secondary' | 'success' | 'blur' | 'grey'
15
+ text: string | number
16
+ }>(), {
17
+ theme: 'default'
18
+ }
19
+ )
20
+ </script>
@@ -0,0 +1,33 @@
1
+ <!--Если в кнопке иконка, обязательно ее вставлять не в дефолтный слот-->
2
+ <template>
3
+ <NuxtLink
4
+ class="f-button"
5
+ :class="[
6
+ `--${theme}`,
7
+ `--${size}`,
8
+ {'--wide': wide},
9
+ {'--active': active},
10
+ {'--disabled': disabled},
11
+ ]"
12
+ exact-active-class="--exact-active"
13
+ v-bind="$attrs"
14
+ >
15
+ <slot></slot>
16
+ </NuxtLink>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ withDefaults(
21
+ defineProps<{
22
+ theme?: 'primary' | 'secondary' | 'ghost' | 'bordered' | 'tab',
23
+ size?: 'm' | 's',
24
+ wide?: boolean,
25
+ active?: boolean,
26
+ disabled?: boolean,
27
+ }>(),
28
+ {
29
+ theme: 'primary',
30
+ size: 'm',
31
+ }
32
+ )
33
+ </script>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <NuxtLink
3
+ class="f-model-tag"
4
+ :to="generateLink(`/models/${convertString().toSlug(card.title)}`)"
5
+ >
6
+ <FImg
7
+ class="f-model-tag__img"
8
+ sizes="20px sm:24px"
9
+ :src="card.primaryImageUrl || placeholder"
10
+ width="20"
11
+ height="20"
12
+ :alt="card.title"
13
+ />
14
+ {{ card.title }}
15
+ </NuxtLink>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import type { IModelTag } from '../../types';
20
+ import { convertString } from '../../runtime';
21
+
22
+ defineProps<{
23
+ card: IModelTag
24
+ placeholder: string
25
+ }>()
26
+
27
+ const { generateLink } = useGenerateLink();
28
+ </script>
@@ -0,0 +1,77 @@
1
+ <template>
2
+ <dialog
3
+ ref="notification"
4
+ class="f-notification"
5
+ :class="{'--popup': popup}"
6
+ @click="closeByBackdropClick"
7
+ @cancel="close"
8
+ >
9
+ <div class="f-notification__wrapper">
10
+ <header class="f-notification__header">
11
+ <p
12
+ v-if="$slots.title"
13
+ class="f-notification__title"
14
+ >
15
+ <slot name="title"></slot>
16
+ </p>
17
+ <button
18
+ class="f-notification__close"
19
+ type="button"
20
+ title="close"
21
+ aria-label="close"
22
+ @click="close"
23
+ >
24
+ <FIcon class="f-notification__close-icon" name="close" size="16"/>
25
+ </button>
26
+ </header>
27
+ <div class="f-notification__content">
28
+ <slot></slot>
29
+ </div>
30
+ <div
31
+ v-if="$slots.footer"
32
+ class="f-notification__footer"
33
+ >
34
+ <slot name="footer"></slot>
35
+ </div>
36
+ </div>
37
+ </dialog>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import { onBackdropClick, scrollLock } from '../../runtime';
42
+
43
+ const notification = ref()
44
+
45
+ const emit = defineEmits<{
46
+ (eventName: 'update:modelValue', value: boolean): void
47
+ (eventName: 'close'): void
48
+ }>()
49
+
50
+ const props = defineProps<{
51
+ modelValue: boolean
52
+ popup?: boolean
53
+ }>()
54
+
55
+ onMounted(() => {
56
+ if (props.popup) {
57
+ scrollLock().lockScroll()
58
+ notification.value.showModal()
59
+ } else {
60
+ notification.value.show()
61
+ }
62
+ })
63
+
64
+ onBeforeUnmount(() => {
65
+ scrollLock().unlockScroll()
66
+ })
67
+
68
+ function close() {
69
+ emit('close')
70
+ emit('update:modelValue', false)
71
+ }
72
+
73
+ function closeByBackdropClick(event: Event) {
74
+ const target = event.target as HTMLDialogElement
75
+ onBackdropClick(target, close)
76
+ }
77
+ </script>
@@ -0,0 +1,136 @@
1
+ <template>
2
+ <dialog
3
+ ref="popupRef"
4
+ class="f-popup"
5
+ :class="[
6
+ {'--sheet': sheet},
7
+ {'--transparent-backdrop': transparentBackdrop},
8
+ {'--aside': $slots.aside}
9
+ ]"
10
+ @click="closeByBackdropClick"
11
+ @cancel="close"
12
+ >
13
+ <div class="f-popup__wrapper">
14
+ <div
15
+ v-if="sheet"
16
+ class="f-popup__sheet"
17
+ >
18
+ <button
19
+ class="f-popup__sheet-handler"
20
+ type="button"
21
+ @click="close"
22
+ ></button>
23
+ </div>
24
+
25
+ <aside
26
+ v-if="$slots.aside && !isMobile(breakpoints).value"
27
+ class="f-popup__aside"
28
+ >
29
+ <slot name="aside"></slot>
30
+ </aside>
31
+
32
+ <header
33
+ class="f-popup__header"
34
+ >
35
+ <button
36
+ v-if="back"
37
+ class="f-popup__back"
38
+ type="button"
39
+ @click="$emit('back')"
40
+ >
41
+ <FIcon name="angle-left" size="24" />
42
+ </button>
43
+ <div
44
+ v-if="$slots.title"
45
+ class="f-popup__title"
46
+ >
47
+ <slot name="title"></slot>
48
+ </div>
49
+ <button
50
+ class="f-popup__close"
51
+ type="button"
52
+ @click="close"
53
+ >
54
+ <FIcon name="close" size="24" />
55
+ </button>
56
+ </header>
57
+ <div
58
+ v-if="$slots.fixedContent"
59
+ class="f-popup__subheader"
60
+ >
61
+ <slot name="fixedContent"></slot>
62
+ </div>
63
+ <div
64
+ v-if="$slots.default"
65
+ class="f-popup__content"
66
+ >
67
+ <slot></slot>
68
+ </div>
69
+ <div
70
+ v-if="$slots.footer"
71
+ class="f-popup__footer"
72
+ >
73
+ <slot name="footer"></slot>
74
+ </div>
75
+ </div>
76
+
77
+ <transition mode="out-in">
78
+ <FSnackbar
79
+ v-if="snackbarText && isSnackBarInPopup"
80
+ />
81
+ </transition>
82
+ </dialog>
83
+ </template>
84
+
85
+ <script setup lang="ts">
86
+ import { onBackdropClick, scrollLock, isMobile } from '../../runtime';
87
+ import type { CssBreakpoints } from '../../types';
88
+
89
+ const {resetSnackbar} = useSnackbar();
90
+
91
+ const breakpoints = useAppConfig().cssBreakpoints as Record<CssBreakpoints, number>;
92
+ const popupRef = ref()
93
+ const emit = defineEmits<{
94
+ (eventName: 'update:modelValue', value: boolean): void
95
+ (eventName: 'back'): void
96
+ (eventName: 'close'): void
97
+ }>()
98
+
99
+ const props = defineProps<{
100
+ modelValue: boolean
101
+ back?: boolean
102
+ transparentBackdrop?: boolean
103
+ sheet?: boolean
104
+ title?: string
105
+ notModal?: boolean
106
+ }>()
107
+
108
+ onMounted(() => {
109
+ isSnackBarInPopup.value = true;
110
+ resetSnackbar();
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
+ })
119
+
120
+ onBeforeUnmount(() => {
121
+ isSnackBarInPopup.value = false;
122
+ scrollLock().unlockScroll();
123
+ })
124
+
125
+ function close() {
126
+ emit('close');
127
+ emit('update:modelValue', false);
128
+ }
129
+
130
+ function closeByBackdropClick(event: Event) {
131
+ const target = event.target as HTMLDialogElement;
132
+ onBackdropClick(target, close);
133
+ }
134
+
135
+ const { snackbarText, isSnackBarInPopup } = useSnackbar();
136
+ </script>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <label
3
+ class="f-radio"
4
+ :class="[
5
+ {'f-radio--disabled': disabled},
6
+ {'f-radio--error': error},
7
+ ]"
8
+ >
9
+ <input
10
+ class="f-radio__input _visually-hidden"
11
+ type="radio"
12
+ :name="name"
13
+ :checked="isChecked"
14
+ :value="value"
15
+ @change="onChange"
16
+ v-bind="$attrs"
17
+ >
18
+ <span class="f-radio__check" />
19
+ <span class="f-radio__label">
20
+ <slot>{{ label }}</slot>
21
+ </span>
22
+ <span
23
+ v-if="$slots.description"
24
+ class="f-radio__description"
25
+ >
26
+ <slot name="description"></slot>
27
+ </span>
28
+ </label>
29
+ </template>
30
+
31
+ <script setup lang="ts">
32
+ const properties = defineProps<{
33
+ name?: string
34
+ label?: string
35
+ modelValue: string | number | boolean
36
+ value: string | number | boolean
37
+ disabled?: boolean
38
+ error?: boolean
39
+ }>()
40
+
41
+ const emit = defineEmits<{
42
+ (eventName: 'update:modelValue', value: string | number | boolean): void
43
+ (eventName: 'update:error', value: boolean): void
44
+ }>()
45
+
46
+ function onChange() {
47
+ emit('update:modelValue', properties.value)
48
+ if (properties.error) {
49
+ emit('update:error', false)
50
+ }
51
+ }
52
+
53
+ const isChecked = computed(() => properties.modelValue === properties.value)
54
+ </script>
55
+
56
+