@myelophone/nuxt 0.18.2

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 (259) hide show
  1. package/.devcontainer/Dockerfile +7 -0
  2. package/.devcontainer/devcontainer.json +21 -0
  3. package/.editorconfig +43 -0
  4. package/.github/workflows/package.yml +73 -0
  5. package/.nuxtignore +6 -0
  6. package/.releaserc.js +132 -0
  7. package/.yarn/releases/yarn-4.18.0.cjs +1000 -0
  8. package/.yarnrc.yml +8 -0
  9. package/CHANGELOG.md +141 -0
  10. package/LICENSE +77 -0
  11. package/README.md +3004 -0
  12. package/app/app.vue +455 -0
  13. package/app/assets/css/animation.css +81 -0
  14. package/app/assets/css/backgrounds.css +57 -0
  15. package/app/assets/css/base.css +182 -0
  16. package/app/assets/css/index.css +9 -0
  17. package/app/assets/css/links.css +12 -0
  18. package/app/assets/css/multimedia.css +102 -0
  19. package/app/assets/css/preloader.css +68 -0
  20. package/app/assets/css/print.css +40 -0
  21. package/app/assets/css/tailwind.css +20 -0
  22. package/app/assets/css/theme.css +29 -0
  23. package/app/components/consent/GoogleMap.vue +59 -0
  24. package/app/components/consent/Youtube.vue +27 -0
  25. package/app/components/cookie/Banner.vue +70 -0
  26. package/app/components/cookie/ConsentWrapper.vue +71 -0
  27. package/app/components/cookie/PrivacyPolicy.vue +179 -0
  28. package/app/components/cookie/SettingsModal.vue +387 -0
  29. package/app/components/grid/Col.vue +262 -0
  30. package/app/components/grid/Container.vue +236 -0
  31. package/app/components/grid/Row.vue +248 -0
  32. package/app/components/grid/Stack.vue +233 -0
  33. package/app/components/myelophone/Copyright.vue +5 -0
  34. package/app/components/myelophone/Welcome.vue +107 -0
  35. package/app/components/page/FullscreenPreloader.vue +177 -0
  36. package/app/components/page/Preloader.vue +18 -0
  37. package/app/components/page/ReadyLocalized.vue +19 -0
  38. package/app/components/ready/.gitkeep +0 -0
  39. package/app/components/safe/Email.vue +52 -0
  40. package/app/components/safe/ImgWithLoader.vue +180 -0
  41. package/app/components/safe/NuxtImg.vue +25 -0
  42. package/app/components/safe/NuxtPicture.vue +29 -0
  43. package/app/components/section/.gitkeep +0 -0
  44. package/app/components/seo/BrandInfo.vue +76 -0
  45. package/app/components/seo/ContentNoIndex.vue +35 -0
  46. package/app/components/seo/NoIndex.vue +22 -0
  47. package/app/components/seo/OrgInfo.vue +130 -0
  48. package/app/components/seo/ProfileInfo.vue +137 -0
  49. package/app/components/ui/Accordion.vue +163 -0
  50. package/app/components/ui/Alert.vue +179 -0
  51. package/app/components/ui/Avatar.vue +88 -0
  52. package/app/components/ui/Badge.vue +150 -0
  53. package/app/components/ui/Banner.vue +133 -0
  54. package/app/components/ui/Button.vue +175 -0
  55. package/app/components/ui/Card.vue +66 -0
  56. package/app/components/ui/Checkbox.vue +134 -0
  57. package/app/components/ui/Chip.vue +136 -0
  58. package/app/components/ui/CommandPalette.vue +434 -0
  59. package/app/components/ui/Console.vue +583 -0
  60. package/app/components/ui/CursorCreative.vue +148 -0
  61. package/app/components/ui/FeatureAccordion.vue +165 -0
  62. package/app/components/ui/FileUpload.vue +705 -0
  63. package/app/components/ui/GeoDependent.vue +72 -0
  64. package/app/components/ui/Heading.vue +51 -0
  65. package/app/components/ui/Icon.vue +42 -0
  66. package/app/components/ui/Icon8.vue +39 -0
  67. package/app/components/ui/Input.vue +88 -0
  68. package/app/components/ui/LangLink.vue +34 -0
  69. package/app/components/ui/LangVisible.vue +33 -0
  70. package/app/components/ui/LanguageSelect.vue +202 -0
  71. package/app/components/ui/LightBox.vue +155 -0
  72. package/app/components/ui/LocalTime.vue +170 -0
  73. package/app/components/ui/Modal.vue +161 -0
  74. package/app/components/ui/Popup.vue +200 -0
  75. package/app/components/ui/PostContent.server.vue +23 -0
  76. package/app/components/ui/ProtectedEmail.vue +52 -0
  77. package/app/components/ui/RelativeTime.vue +141 -0
  78. package/app/components/ui/ScheduledContent.vue +150 -0
  79. package/app/components/ui/ScrollToTop.client.vue +48 -0
  80. package/app/components/ui/SegmentedControl.vue +148 -0
  81. package/app/components/ui/SiteSearch.vue +1191 -0
  82. package/app/components/ui/Skeleton.vue +91 -0
  83. package/app/components/ui/SmartContrast.vue +74 -0
  84. package/app/components/ui/SnapContainer.vue +222 -0
  85. package/app/components/ui/SnapSection.vue +294 -0
  86. package/app/components/ui/SonnerStyle.vue +7 -0
  87. package/app/components/ui/SplitSection.vue +99 -0
  88. package/app/components/ui/Steps.vue +858 -0
  89. package/app/components/ui/StickyWrapper.vue +46 -0
  90. package/app/components/ui/Table.vue +251 -0
  91. package/app/components/ui/Tabs.vue +451 -0
  92. package/app/components/ui/TextColumn.vue +36 -0
  93. package/app/components/ui/Textarea.vue +251 -0
  94. package/app/components/ui/Toggler.vue +40 -0
  95. package/app/components/ui/Tooltip.vue +524 -0
  96. package/app/components/ui/TruncateText.vue +105 -0
  97. package/app/components/ui/ViewportSpacer.vue +72 -0
  98. package/app/components/view/AnimatedCounter.vue +121 -0
  99. package/app/components/view/AnnouncementBar.vue +104 -0
  100. package/app/components/view/AvatarGroup.vue +104 -0
  101. package/app/components/view/Breadcrumbs.vue +97 -0
  102. package/app/components/view/ContentWithToc.vue +152 -0
  103. package/app/components/view/Copyright.vue +68 -0
  104. package/app/components/view/CountdownTimer.vue +184 -0
  105. package/app/components/view/CreativeCTA.vue +143 -0
  106. package/app/components/view/CurrencySelect.vue +254 -0
  107. package/app/components/view/FeatureBoxGrid.vue +142 -0
  108. package/app/components/view/HorizontalMenu.vue +97 -0
  109. package/app/components/view/ImageCompare.vue +141 -0
  110. package/app/components/view/ImgSlider.vue +333 -0
  111. package/app/components/view/InfiniteMarquee.vue +147 -0
  112. package/app/components/view/InfoBar.vue +86 -0
  113. package/app/components/view/LogoGrid.vue +106 -0
  114. package/app/components/view/LogoSlider.vue +83 -0
  115. package/app/components/view/NotFound.vue +81 -0
  116. package/app/components/view/PartialBackground.vue +313 -0
  117. package/app/components/view/QuoteBig.vue +111 -0
  118. package/app/components/view/ResponsiveMenu.vue +219 -0
  119. package/app/components/view/ReviewsSlider.vue +230 -0
  120. package/app/components/view/SocialBar.vue +78 -0
  121. package/app/components/view/StickyHeadingContent.vue +158 -0
  122. package/app/components/view/TallyForm.vue +295 -0
  123. package/app/components/view/WarningOutdated.vue +113 -0
  124. package/app/composables/useApi.ts +88 -0
  125. package/app/composables/useAppSeo.ts +78 -0
  126. package/app/composables/useBreadcrumbs.ts +106 -0
  127. package/app/composables/useChangeUrl.ts +73 -0
  128. package/app/composables/useCommand.ts +28 -0
  129. package/app/composables/useCookieControl.ts +111 -0
  130. package/app/composables/useCookieModal.ts +9 -0
  131. package/app/composables/useDevice.ts +109 -0
  132. package/app/composables/useGeoFetch.ts +139 -0
  133. package/app/composables/useLoadScript.ts +36 -0
  134. package/app/composables/useModalState.ts +37 -0
  135. package/app/composables/useMultiLang.ts +278 -0
  136. package/app/composables/useNetwork.ts +49 -0
  137. package/app/composables/useNuxtVersion.ts +5 -0
  138. package/app/composables/usePiniaStore.ts +5 -0
  139. package/app/composables/usePopupControl.ts +57 -0
  140. package/app/composables/useQuery.ts +307 -0
  141. package/app/composables/useReadyPage.ts +182 -0
  142. package/app/composables/useSafeList.ts +90 -0
  143. package/app/composables/useScriptLoader.ts +221 -0
  144. package/app/composables/useSiteSearch.ts +32 -0
  145. package/app/composables/useSnapScroll.ts +24 -0
  146. package/app/composables/useStatic.ts +5 -0
  147. package/app/composables/useStorage.ts +252 -0
  148. package/app/composables/useStoreBroadcast.ts +146 -0
  149. package/app/composables/useThemeSync.ts +81 -0
  150. package/app/constants/layout.ts +109 -0
  151. package/app/constants/predefinedCookieScripts.ts +1222 -0
  152. package/app/constants/ui-events.ts +1 -0
  153. package/app/error.vue +169 -0
  154. package/app/layouts/default-blog.vue +5 -0
  155. package/app/layouts/default.vue +3 -0
  156. package/app/locales/en/commands.json +5 -0
  157. package/app/locales/en/cookies.json +182 -0
  158. package/app/locales/en/error.json +4 -0
  159. package/app/locales/en/interface.json +33 -0
  160. package/app/locales/en/myelophone.json +8 -0
  161. package/app/locales/en/outdated.json +5 -0
  162. package/app/locales/en/times.json +18 -0
  163. package/app/locales/pl/commands.json +5 -0
  164. package/app/locales/pl/cookies.json +182 -0
  165. package/app/locales/pl/error.json +4 -0
  166. package/app/locales/pl/interface.json +33 -0
  167. package/app/locales/pl/myelophone.json +8 -0
  168. package/app/locales/pl/outdated.json +5 -0
  169. package/app/locales/pl/times.json +18 -0
  170. package/app/locales/ru/commands.json +5 -0
  171. package/app/locales/ru/cookies.json +182 -0
  172. package/app/locales/ru/error.json +4 -0
  173. package/app/locales/ru/interface.json +33 -0
  174. package/app/locales/ru/myelophone.json +8 -0
  175. package/app/locales/ru/outdated.json +5 -0
  176. package/app/locales/ru/times.json +18 -0
  177. package/app/middleware/blog-layout.ts +28 -0
  178. package/app/middleware/i18n.global.ts +17 -0
  179. package/app/middleware/not-found-status.ts +11 -0
  180. package/app/modules/default-blog/index.ts +39 -0
  181. package/app/modules/default-blog/posts.ts +80 -0
  182. package/app/modules/default-sitemap/index.ts +116 -0
  183. package/app/modules/default-sitemap/runtime/sitemap.get.ts +42 -0
  184. package/app/modules/fullscreen-preloader/module.ts +43 -0
  185. package/app/modules/htaccess/.htaccess +38 -0
  186. package/app/modules/htaccess/index.ts +23 -0
  187. package/app/modules/i18n-shaker.mjs +221 -0
  188. package/app/modules/multi18n/module.ts +71 -0
  189. package/app/modules/myelophone-config/module.ts +241 -0
  190. package/app/pages/[...all].vue +9 -0
  191. package/app/pages/index.vue +3 -0
  192. package/app/pages/post/[...slug].vue +30 -0
  193. package/app/plugins/bfcache-refresh.client.ts +9 -0
  194. package/app/plugins/canonical.ts +30 -0
  195. package/app/plugins/csp-nonce.server.ts +41 -0
  196. package/app/plugins/multi18n.client.ts +21 -0
  197. package/app/plugins/multi18n.server.ts +15 -0
  198. package/app/plugins/nuxt-version.client.ts +4 -0
  199. package/app/plugins/restore.client.ts +21 -0
  200. package/app/plugins/reveal.ts +89 -0
  201. package/app/plugins/url-helper.client.ts +66 -0
  202. package/app/server/api/exchange-rates.get.ts +216 -0
  203. package/app/server/api/healthz.ts +1 -0
  204. package/app/server/api/logout.post.ts +6 -0
  205. package/app/server/middleware/normalize-url.ts +14 -0
  206. package/app/server/middleware/security-headers.ts +147 -0
  207. package/app/server/middleware/url-helper.ts +43 -0
  208. package/app/server/plugins/clean-html-spaces.ts +15 -0
  209. package/app/server/plugins/clean-styles.ts +94 -0
  210. package/app/server/plugins/compression.ts +122 -0
  211. package/app/server/plugins/css-preload.ts +26 -0
  212. package/app/server/plugins/early-hints.ts +31 -0
  213. package/app/server/plugins/force-noindex.ts +43 -0
  214. package/app/server/plugins/html-one-line.ts +17 -0
  215. package/app/server/plugins/inline-style.ts +7 -0
  216. package/app/server/routes/healthz.get.ts +1 -0
  217. package/app/server/tsconfig.json +3 -0
  218. package/app/stores/cart.ts +945 -0
  219. package/app/stores/commands.ts +43 -0
  220. package/app/stores/device.ts +156 -0
  221. package/app/stores/querySync.ts +5 -0
  222. package/app/stores/settings.ts +145 -0
  223. package/app/stores/user.ts +607 -0
  224. package/app/types/cookie.ts +89 -0
  225. package/app/types/myelophone.d.ts +87 -0
  226. package/app/types/site-search.ts +110 -0
  227. package/app/utils/asyncRefresh.ts +4 -0
  228. package/app/utils/blog.server.ts +142 -0
  229. package/app/utils/jsonLd.ts +56 -0
  230. package/app/utils/myelophoneConfig.ts +4 -0
  231. package/app/utils/sortBy.ts +18 -0
  232. package/app/utils/transliterate.ts +75 -0
  233. package/app/utils/ytVideo.ts +37 -0
  234. package/app/workers/site-search.worker.ts +661 -0
  235. package/biome.json +94 -0
  236. package/commitlint.config.js +3 -0
  237. package/nuxt.config.ts +539 -0
  238. package/package.json +101 -0
  239. package/playground/content/.gitkeep +0 -0
  240. package/playground/locales/.gitkeep +0 -0
  241. package/playground/myelophone.dev.ts +45 -0
  242. package/playground/nuxt.config.ts +105 -0
  243. package/playground/package.json +5 -0
  244. package/playground/pages/.gitkeep +0 -0
  245. package/playground/tsconfig.json +3 -0
  246. package/playwright.config.ts +23 -0
  247. package/public/browsers/chrome.svg +77 -0
  248. package/public/browsers/edge.svg +98 -0
  249. package/public/browsers/firefox.svg +300 -0
  250. package/public/favicon.ico +0 -0
  251. package/public/myelophone_eng.png +0 -0
  252. package/public/myelophone_eng_white.png +0 -0
  253. package/spa-loading-template.html +72 -0
  254. package/tests/home.spec.ts +9 -0
  255. package/tests/utils.ts +23 -0
  256. package/tsconfig.json +16 -0
  257. package/vite/plugins/clean-css.ts +190 -0
  258. package/vite/plugins/postcss-add-viewportunits.ts +33 -0
  259. package/vite/plugins/postcss-viewport-fallback.ts +49 -0
@@ -0,0 +1,182 @@
1
+ @font-face {
2
+ font-family: 'color-emoji';
3
+ src:
4
+ local('Apple Color Emoji'), local('Twemoji Mozilla'),
5
+ local('Segoe UI Emoji'), local('Segoe UI Symbol'),
6
+ local('Noto Color Emoji'), local('EmojiOne Color'),
7
+ local('Android Emoji');
8
+ }
9
+
10
+ body {
11
+ background-color: var(--ui-bg);
12
+ color: var(--ui-text);
13
+ transition:
14
+ background-color 0.3s ease,
15
+ color 0.3s ease;
16
+ min-height: 0.01vw;
17
+ /* biome-ignore lint/suspicious/noDuplicateProperties: trick for old and new browsers */
18
+ min-height: 100dvh;
19
+ text-rendering: optimizelegibility;
20
+ }
21
+
22
+ #__nuxt {
23
+ max-width: 100%;
24
+ }
25
+
26
+ html input,
27
+ html textarea {
28
+ border-color: #e5e7eb;
29
+ }
30
+
31
+ iframe {
32
+ background: var(--ui-bg);
33
+ }
34
+
35
+ .min-h-dvh {
36
+ min-height: 100vh;
37
+ min-height: 100dvh;
38
+ }
39
+
40
+ h2,
41
+ h3,
42
+ h4,
43
+ h5,
44
+ h6 {
45
+ font-weight: 500;
46
+ padding-top: 0.75rem;
47
+ padding-bottom: 0.75rem;
48
+ }
49
+
50
+ h5,
51
+ h6 {
52
+ line-height: 1.4;
53
+ }
54
+
55
+ h1:not([class*='text-']) {
56
+ font-size: 2.4rem;
57
+ }
58
+
59
+ h2:not([class*='text-']) {
60
+ font-size: 2rem;
61
+ }
62
+
63
+ h3:not([class*='text-']) {
64
+ font-size: 1.7rem;
65
+ }
66
+
67
+ h4:not([class*='text-']) {
68
+ font-size: 1.4rem;
69
+ }
70
+
71
+ h5:not([class*='text-']) {
72
+ font-size: 1.2rem;
73
+ }
74
+
75
+ h1 {
76
+ line-height: 1.2;
77
+ font-weight: 600;
78
+ padding-top: 1rem;
79
+ padding-bottom: 1rem;
80
+ }
81
+
82
+ h2 {
83
+ line-height: 1.25;
84
+ }
85
+
86
+ h3 {
87
+ line-height: 1.3;
88
+ }
89
+
90
+ h4 {
91
+ line-height: 1.35;
92
+ }
93
+
94
+ a:not([class*='text-']),
95
+ h6:not([class*='text-']),
96
+ li:not([class*='text-']),
97
+ p:not([class*='text-']),
98
+ span:not([class*='text-']) {
99
+ font-size: 1rem;
100
+ }
101
+
102
+ p a,
103
+ p span,
104
+ a span,
105
+ li a,
106
+ li span,
107
+ span[class^='text-'] {
108
+ font-size: inherit;
109
+ }
110
+
111
+ a,
112
+ li,
113
+ p,
114
+ span {
115
+ line-height: 1.35;
116
+ }
117
+
118
+ button {
119
+ cursor: pointer;
120
+ }
121
+
122
+ @media (max-width: 480px), (max-height: 480px) {
123
+ h1:not([class*='text-']) {
124
+ font-size: 2rem;
125
+ }
126
+ h2:not([class*='text-']) {
127
+ font-size: 1.375rem;
128
+ }
129
+ h3:not([class*='text-']) {
130
+ font-size: 1.275rem;
131
+ }
132
+ h4:not([class*='text-']),
133
+ h5:not([class*='text-']),
134
+ h6:not([class*='text-']) {
135
+ font-size: 1.125rem;
136
+ }
137
+
138
+ h1 {
139
+ padding-top: 0.75rem;
140
+ padding-bottom: 0.75rem;
141
+ }
142
+ h2 {
143
+ padding-top: 0.5rem;
144
+ padding-bottom: 0.5rem;
145
+ }
146
+ h3 {
147
+ padding-top: 0.5rem;
148
+ padding-bottom: 0.5rem;
149
+ }
150
+ h4,
151
+ h5,
152
+ h6 {
153
+ padding-top: 0.5rem;
154
+ padding-bottom: 0.5rem;
155
+ }
156
+ }
157
+
158
+ :focus-visible {
159
+ outline: none;
160
+ }
161
+
162
+ .value {
163
+ font-feature-settings: 'tnum';
164
+ font-variant-numeric: tabular-nums;
165
+ }
166
+
167
+ .app-icon {
168
+ display: inline-block;
169
+ background-color: currentColor;
170
+ flex-shrink: 0;
171
+ vertical-align: middle;
172
+ mask-repeat: no-repeat;
173
+ mask-size: 100% 100%;
174
+ -webkit-mask-repeat: no-repeat;
175
+ -webkit-mask-size: 100% 100%;
176
+ mask-image: var(--icon-url);
177
+ -webkit-mask-image: var(--icon-url);
178
+ }
179
+
180
+ :where(p) .app-icon {
181
+ margin-top: -0.1875rem;
182
+ }
@@ -0,0 +1,9 @@
1
+ @import './tailwind.css';
2
+ @import './base.css';
3
+ @import './theme.css';
4
+ @import './preloader.css';
5
+ @import './multimedia.css';
6
+ @import './backgrounds.css';
7
+ @import './animation.css';
8
+ @import './links.css';
9
+ @import './print.css';
@@ -0,0 +1,12 @@
1
+ a[href^='http']:not(.no-external-icon)::after {
2
+ content: '';
3
+ display: inline-block;
4
+ width: 20px;
5
+ height: 20px;
6
+ vertical-align: middle;
7
+
8
+ background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 8L8 16' stroke='%238A8A8A' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.4 8H16V12.8' stroke='%238A8A8A' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
9
+
10
+ background-repeat: no-repeat;
11
+ background-size: contain;
12
+ }
@@ -0,0 +1,102 @@
1
+ .loadersvg {
2
+ animation: loaderanimation 1s linear infinite;
3
+ will-change: transform;
4
+ }
5
+
6
+ @keyframes loaderanimation {
7
+ to {
8
+ transform: rotate(360deg);
9
+ }
10
+ }
11
+
12
+ .lazy-image-wrapper {
13
+ position: relative;
14
+ display: inline-block;
15
+ width: 100%;
16
+ overflow: hidden;
17
+ }
18
+
19
+ .lazy-image {
20
+ display: block;
21
+ width: 100%;
22
+ height: auto;
23
+ opacity: 0;
24
+ will-change: opacity;
25
+ }
26
+
27
+ .loaderparent {
28
+ width: 100%;
29
+ position: relative;
30
+ display: flex;
31
+ justify-content: center;
32
+ flex-direction: row;
33
+ align-items: center;
34
+ background: rgba(255, 255, 255, 0.05);
35
+ z-index: 2;
36
+ padding-block: 2rem;
37
+ padding-inline: 2rem;
38
+ }
39
+
40
+ .img-fade-in {
41
+ opacity: 0;
42
+ transition: opacity 0.3s ease;
43
+ }
44
+ .img-fade-in.image-visible {
45
+ opacity: 1;
46
+ }
47
+
48
+ .js .ssr-image {
49
+ opacity: 0;
50
+ }
51
+
52
+ .nojs .ssr-image {
53
+ opacity: 1;
54
+ }
55
+
56
+ .video-player {
57
+ position: relative;
58
+ width: 100%;
59
+ aspect-ratio: 16 / 9;
60
+ background-color: #000;
61
+ }
62
+
63
+ .poster-wrapper {
64
+ width: 100%;
65
+ height: 100%;
66
+ background-size: cover;
67
+ background-position: center;
68
+ position: relative;
69
+ cursor: pointer;
70
+ display: flex;
71
+ justify-content: center;
72
+ align-items: center;
73
+ }
74
+
75
+ .play-icon {
76
+ background: rgba(0, 0, 0, 0.6);
77
+ border-radius: 50%;
78
+ padding: 16px;
79
+ transition: opacity 0.3s;
80
+ }
81
+
82
+ .video-wrapper {
83
+ width: 100%;
84
+ height: 100%;
85
+ position: relative;
86
+ }
87
+
88
+ .video {
89
+ width: 100%;
90
+ height: 100%;
91
+ border: none;
92
+ }
93
+
94
+ .loading-overlay {
95
+ position: absolute;
96
+ inset: 0;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ background: rgba(0, 0, 0, 0.4);
101
+ z-index: 2;
102
+ }
@@ -0,0 +1,68 @@
1
+ .preloader {
2
+ position: relative;
3
+ width: 15px;
4
+ height: 15px;
5
+ border: solid 2px transparent;
6
+ border-top-color: #0082e6;
7
+ border-top-color: var(--loader-fill-color);
8
+ border-radius: 10px;
9
+ animation: preloader-spinner 400ms linear infinite;
10
+ pointer-events: none;
11
+ user-select: none;
12
+ margin: 1rem;
13
+ display: flex;
14
+ justify-content: center;
15
+ align-items: center;
16
+ }
17
+
18
+ .preloader.hidden {
19
+ display: none;
20
+ }
21
+
22
+ @keyframes preloader-spinner {
23
+ 0% {
24
+ transform: rotate(0deg);
25
+ }
26
+ 100% {
27
+ transform: rotate(360deg);
28
+ }
29
+ }
30
+
31
+ .lineloader {
32
+ display: block;
33
+ width: 100%;
34
+ height: 2px;
35
+ background-color: transparent;
36
+ position: relative;
37
+ overflow: hidden;
38
+ margin-top: -2px;
39
+ }
40
+
41
+ .lineloader::before {
42
+ content: '';
43
+ position: absolute;
44
+ top: 0;
45
+ left: 0;
46
+ width: 100%;
47
+ height: 100%;
48
+ background-color: #0066cc;
49
+ background-color: var(--loader-fill-color);
50
+ transform: translateX(-100%);
51
+ animation: lineloader-animation 2s linear infinite;
52
+ opacity: 0.5;
53
+ }
54
+
55
+ @keyframes lineloader-animation {
56
+ 0% {
57
+ transform: translateX(-100%);
58
+ }
59
+ 100% {
60
+ transform: translateX(100%);
61
+ }
62
+ }
63
+
64
+ .preloaderBox {
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: center;
68
+ }
@@ -0,0 +1,40 @@
1
+ @media print {
2
+ :root {
3
+ --ui-bg: #f7f7f7;
4
+ --ui-text: #1a1a1b;
5
+ --loader-fill-color: #000;
6
+ --ui-border: #374151;
7
+ }
8
+
9
+ body {
10
+ font-size: 12pt;
11
+ background: none;
12
+ max-width: 210mm;
13
+ margin: auto;
14
+ }
15
+
16
+ nav,
17
+ .sidebar,
18
+ .ads,
19
+ .button {
20
+ display: none;
21
+ }
22
+
23
+ a {
24
+ color: black;
25
+ text-decoration: underline;
26
+ }
27
+
28
+ a::after {
29
+ content: ' (' attr(href) ')';
30
+ font-size: 10pt;
31
+ color: gray;
32
+ }
33
+
34
+ h1,
35
+ h2,
36
+ h3,
37
+ p {
38
+ break-inside: avoid;
39
+ }
40
+ }
@@ -0,0 +1,20 @@
1
+ @import 'tailwindcss';
2
+
3
+ @theme {
4
+ --font-sans:
5
+ -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto,
6
+ Oxygen, Ubuntu, 'Helvetica Neue', Arial, sans-serif, color-emoji;
7
+ --default-font-feature-settings: normal;
8
+ --default-font-variation-settings: normal;
9
+ }
10
+
11
+ html {
12
+ font-family: var(--font-sans) !important;
13
+ font-feature-settings: normal !important;
14
+ font-variation-settings: normal !important;
15
+ }
16
+
17
+ @source "../../../**/*.{vue}";
18
+ @source "../../constants/**/*.ts";
19
+
20
+ @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
@@ -0,0 +1,29 @@
1
+ :root {
2
+ --ui-bg: #f7f7f7;
3
+ --ui-text: #1a1a1b;
4
+ --loader-fill-color: #000;
5
+ --ui-border: #374151;
6
+ }
7
+
8
+ @media (prefers-color-scheme: dark) {
9
+ :root {
10
+ --ui-bg: #121212;
11
+ --ui-text: #e0e0e0;
12
+ --loader-fill-color: #000;
13
+ --ui-border: #d1d5db;
14
+ }
15
+ }
16
+
17
+ [data-theme='light'] {
18
+ --ui-bg: #f7f7f7;
19
+ --ui-text: #1a1a1b;
20
+ --loader-fill-color: #0082e6;
21
+ --ui-border: #374151;
22
+ }
23
+
24
+ [data-theme='dark'] {
25
+ --ui-bg: #121212;
26
+ --ui-text: #e0e0e0;
27
+ --loader-fill-color: #fff;
28
+ --ui-border: #d1d5db;
29
+ }
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ type Props = {
3
+ address?: string;
4
+ placeId?: string;
5
+ language?: string;
6
+ region?: string;
7
+ title?: string;
8
+ };
9
+
10
+ const props = withDefaults(defineProps<Props>(), {
11
+ address: "",
12
+ placeId: "",
13
+ language: "eb",
14
+ region: "pl",
15
+ title: "Google Maps",
16
+ });
17
+
18
+ const mapSrc = computed(() => {
19
+ const query = props.placeId ? `place_id:${props.placeId}` : props.address;
20
+
21
+ if (!query) {
22
+ return "";
23
+ }
24
+
25
+ const params = new URLSearchParams({
26
+ q: query,
27
+ output: "embed",
28
+ hl: props.language,
29
+ gl: props.region,
30
+ });
31
+
32
+ return `https://www.google.com/maps?${params.toString()}`;
33
+ });
34
+
35
+ const { t } = useMultiLang(["interface"]);
36
+ </script>
37
+
38
+ <template>
39
+ <div class="h-100 w-full">
40
+ <CookieConsentWrapper category="functional">
41
+ <iframe
42
+ v-if="mapSrc"
43
+ :src="mapSrc"
44
+ :title="title"
45
+ class="h-full w-full rounded-xl border-0"
46
+ loading="lazy"
47
+ referrerpolicy="no-referrer-when-downgrade"
48
+ allowfullscreen
49
+ />
50
+
51
+ <div
52
+ v-else
53
+ class="flex h-full w-full items-center justify-center rounded-xl bg-gray-100"
54
+ >
55
+ {{ t("interface.noGoogleMapAddress") }}
56
+ </div>
57
+ </CookieConsentWrapper>
58
+ </div>
59
+ </template>
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ videoId: string;
4
+ }>();
5
+ </script>
6
+
7
+ <template>
8
+ <CookieConsentWrapper category="marketing" serviceName="YouTube">
9
+ <div class="aspect-video rounded-xl overflow-hidden shadow-lg">
10
+ <iframe
11
+ width="100%"
12
+ height="100%"
13
+ :src="`https://www.youtube.com/embed/${videoId}`"
14
+ frameborder="0"
15
+ allow="
16
+ accelerometer;
17
+ autoplay;
18
+ clipboard-write;
19
+ encrypted-media;
20
+ gyroscope;
21
+ picture-in-picture;
22
+ "
23
+ allowfullscreen
24
+ ></iframe>
25
+ </div>
26
+ </CookieConsentWrapper>
27
+ </template>
@@ -0,0 +1,70 @@
1
+ <script setup lang="ts">
2
+ const { isBannerVisible, acceptAll } = useCookieControl();
3
+ const emit = defineEmits(["settings"]);
4
+ const { open } = useCookieModal();
5
+
6
+ const handleSettings = () => {
7
+ emit("settings");
8
+ open();
9
+ };
10
+
11
+ const { t } = useMultiLang(["cookies"]);
12
+ </script>
13
+
14
+ <template>
15
+ <Transition
16
+ appear
17
+ enter-active-class="transition duration-500 ease-out delay-300"
18
+ enter-from-class="translate-y-full opacity-0"
19
+ enter-to-class="translate-y-0 opacity-100"
20
+ leave-active-class="transition duration-300 ease-in"
21
+ leave-from-class="translate-y-0 opacity-100"
22
+ leave-to-class="translate-y-full opacity-0"
23
+ >
24
+ <div
25
+ v-if="isBannerVisible"
26
+ class="fixed bottom-4 left-4 right-4 z-60 md:right-auto md:left-6 md:bottom-6 max-w-100 mx-auto md:m-0"
27
+ data-nosnippet
28
+ >
29
+ <div
30
+ class="relative flex flex-col gap-4 p-4 w-full md:w-auto md:max-w-82.5 rounded-xl border border-neutral-200/80 bg-white/90 shadow-xl backdrop-blur-md dark:border-neutral-800/80 dark:bg-neutral-950/90"
31
+ >
32
+ <div class="flex gap-3">
33
+ <span class="text-xl leading-none mt-0.5 select-none"
34
+ >🍪</span
35
+ >
36
+ <p
37
+ class="text-sm font-medium leading-snug text-neutral-600 dark:text-neutral-300"
38
+ >
39
+ {{ t("cookies.weUseCookies") }}
40
+ </p>
41
+ </div>
42
+
43
+ <div class="flex flex-col gap-2">
44
+ <div class="grid grid-cols-2 gap-2">
45
+ <button
46
+ @click="handleSettings"
47
+ class="flex items-center justify-center px-3 py-2 text-xs font-semibold text-neutral-700 bg-neutral-100 rounded-lg transition-colors hover:bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-300 dark:hover:bg-neutral-700"
48
+ >
49
+ {{ t("cookies.decline") }}
50
+ </button>
51
+
52
+ <button
53
+ @click="acceptAll"
54
+ class="flex items-center justify-center px-3 py-2 text-xs font-semibold text-white bg-neutral-900 rounded-lg shadow-sm transition-all hover:bg-neutral-800 hover:shadow dark:bg-white dark:text-neutral-950 dark:hover:bg-neutral-200"
55
+ >
56
+ {{ t("cookies.acceptAll") }}
57
+ </button>
58
+ </div>
59
+
60
+ <button
61
+ @click="handleSettings"
62
+ class="w-full text-center text-xs text-neutral-400 transition-colors hover:text-neutral-900 dark:hover:text-neutral-200"
63
+ >
64
+ {{ t("cookies.changePrefs") }}
65
+ </button>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </Transition>
70
+ </template>
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+ import { toast } from "vue-sonner";
3
+ import type { CookieCategory } from "~/types/cookie";
4
+
5
+ interface Props {
6
+ category: CookieCategory;
7
+ serviceName?: string;
8
+ }
9
+
10
+ const props = defineProps<Props>();
11
+
12
+ const { t } = useMultiLang(["cookies"]);
13
+
14
+ const { checkConsent, isBannerVisible } = useCookieControl();
15
+
16
+ const hasConsent = computed(() => checkConsent(props.category));
17
+
18
+ const categoryNames = computed<Record<CookieCategory, string>>(() => ({
19
+ necessary: t("cookies.necessary"),
20
+ analytics: t("cookies.analytics"),
21
+ marketing: t("cookies.marketing"),
22
+ functional: t("cookies.functional"),
23
+ }));
24
+
25
+ const messageText = computed(() => {
26
+ const catName = categoryNames.value[props.category] || props.category;
27
+ if (props.serviceName) {
28
+ return `${t("cookies.toUse")} ${props.serviceName} ${t("cookies.needToAccept")} ${catName} ${t("cookies.cookies")}.`;
29
+ }
30
+ return `${t("cookies.toSee")} ${catName} ${t("cookies.cookies")}.`;
31
+ });
32
+
33
+ const handleRequestConsent = () => {
34
+ isBannerVisible.value = true;
35
+ toast.message(t("cookies.actionRequired"), {
36
+ description: t("cookies.selectCategories"),
37
+ });
38
+ };
39
+ </script>
40
+
41
+ <template>
42
+ <div class="w-full h-full relative isolate">
43
+ <slot v-if="hasConsent" />
44
+
45
+ <div
46
+ v-else
47
+ class="flex flex-col items-center justify-center w-full h-full min-h-50 p-6 text-center bg-neutral-50 border border-neutral-200 rounded-xl dark:bg-neutral-900 dark:border-neutral-800"
48
+ >
49
+ <div class="text-4xl mb-3 opacity-80 select-none">🍪</div>
50
+
51
+ <h3
52
+ class="text-base font-semibold text-neutral-900 dark:text-neutral-100 mb-2"
53
+ >
54
+ {{ t("cookies.contentHidden") }}
55
+ </h3>
56
+
57
+ <p
58
+ class="text-sm text-neutral-500 dark:text-neutral-400 mb-5 max-w-xs mx-auto leading-relaxed"
59
+ >
60
+ {{ messageText }}
61
+ </p>
62
+
63
+ <button
64
+ @click="handleRequestConsent"
65
+ class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-neutral-900 rounded-lg shadow-sm hover:bg-neutral-800 transition-all dark:bg-white dark:text-neutral-950 dark:hover:bg-neutral-200"
66
+ >
67
+ {{ t("cookies.setPrefs") }}
68
+ </button>
69
+ </div>
70
+ </div>
71
+ </template>