srcdev-nuxt-components 3.0.0 → 4.0.1

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 (90) hide show
  1. package/assets/styles/a11y/_utils.css +20 -0
  2. package/assets/styles/a11y/_variables.css +8 -0
  3. package/assets/styles/a11y/index.css +2 -0
  4. package/assets/styles/forms/index.css +2 -0
  5. package/assets/styles/forms/themes/_error.css +77 -0
  6. package/assets/styles/forms/themes/_ghost.css +77 -0
  7. package/assets/styles/forms/themes/_input-action.css +20 -0
  8. package/assets/styles/forms/themes/_primary.css +82 -0
  9. package/assets/styles/forms/themes/_secondary.css +77 -0
  10. package/assets/styles/forms/themes/_success.css +77 -0
  11. package/assets/styles/forms/themes/_tertiary.css +77 -0
  12. package/assets/styles/forms/themes/_warning.css +77 -0
  13. package/assets/styles/forms/themes/index.css +8 -0
  14. package/assets/styles/forms/variables/_sizes.css +82 -0
  15. package/assets/styles/forms/variables/_theme.css +11 -0
  16. package/assets/styles/forms/variables/index.css +2 -0
  17. package/assets/styles/main.css +5 -0
  18. package/assets/styles/typography/index.css +2 -0
  19. package/assets/styles/typography/utils/_font-classes.css +160 -0
  20. package/assets/styles/typography/utils/_weights.css +69 -0
  21. package/assets/styles/typography/utils/index.css +2 -0
  22. package/assets/styles/typography/variables/_colors.css +14 -0
  23. package/assets/styles/typography/variables/_reponsive-font-size.css +10 -0
  24. package/assets/styles/typography/variables/index.css +2 -0
  25. package/assets/styles/utils/_animations.css +42 -0
  26. package/assets/styles/utils/_canvasWidths.css +18 -0
  27. package/assets/styles/utils/_display.css +7 -0
  28. package/assets/styles/utils/_margin-helpers.css +334 -0
  29. package/assets/styles/utils/_padding-helpers.css +308 -0
  30. package/assets/styles/utils/_page.css +24 -0
  31. package/assets/styles/utils/_placement.css +73 -0
  32. package/assets/styles/utils/index.css +7 -0
  33. package/assets/styles/variables/colors/_blue.css +15 -0
  34. package/assets/styles/variables/colors/_gray.css +16 -0
  35. package/assets/styles/variables/colors/_green.css +15 -0
  36. package/assets/styles/variables/colors/_orange.css +15 -0
  37. package/assets/styles/variables/colors/_red.css +15 -0
  38. package/assets/styles/variables/colors/_yellow.css +15 -0
  39. package/assets/styles/variables/colors/colors.css +6 -0
  40. package/assets/styles/variables/components/_accordian.css +7 -0
  41. package/assets/styles/variables/components/_container-glow-core.css +16 -0
  42. package/assets/styles/variables/components/_display-dialog-core.css +35 -0
  43. package/assets/styles/variables/components/_tabs.css +18 -0
  44. package/assets/styles/variables/components/display-prompt-core/_scaffolding.css +57 -0
  45. package/assets/styles/variables/components/display-prompt-core/index.css +2 -0
  46. package/assets/styles/variables/components/display-prompt-core/themes/_error.css +39 -0
  47. package/assets/styles/variables/components/display-prompt-core/themes/_info.css +39 -0
  48. package/assets/styles/variables/components/display-prompt-core/themes/_success.css +39 -0
  49. package/assets/styles/variables/components/display-prompt-core/themes/_warning.css +39 -0
  50. package/assets/styles/variables/components/display-prompt-core/themes/index.css +4 -0
  51. package/assets/styles/variables/components/index.css +5 -0
  52. package/assets/styles/variables/index.css +2 -0
  53. package/components/animated-svg-text/AnimatedSvgText.vue +87 -0
  54. package/components/canvas-switcher/CanvasSwitcher.vue +77 -0
  55. package/components/carousel-basic/CarouselBasic.vue +241 -0
  56. package/components/carousel-basic/CarouselFlip.vue +378 -0
  57. package/components/clip-element/ClipElement.vue +73 -0
  58. package/components/clipped-panels/ClippedPanel.vue +73 -0
  59. package/components/deep-expanding-menu/DeepExpandingMenu.vue +214 -0
  60. package/components/deep-expanding-menu/DeepExpandingMenuOld.vue +218 -0
  61. package/components/display-banner/DisplayBanner.vue +63 -0
  62. package/components/display-details/DisplayDetailsCore.vue +312 -0
  63. package/components/functional/accordian/AccordianCore.vue +138 -0
  64. package/components/functional/display-dialog/DisplayDialogCore.vue +244 -0
  65. package/components/functional/display-dialog/variants/DisplayDialogConfirm.vue +45 -0
  66. package/components/functional/display-dialog/variants/DisplayDialogScrollableContent.vue +49 -0
  67. package/components/functional/pop-over/PopOver.vue +88 -0
  68. package/components/image-galleries/SliderGallery.vue +784 -0
  69. package/components/masonry-grid-ordered/MasonryGridOrdered.vue +158 -0
  70. package/components/presentation/container-glow/ContainerGlowCore.vue +211 -0
  71. package/components/presentation/display-grid/DisplayGridCore.vue +22 -0
  72. package/components/presentation/display-prompt/DisplayPromptCore.vue +150 -0
  73. package/components/presentation/display-prompt/variants/DisplayPromptError.vue +53 -0
  74. package/components/presentation/layout-grids/LayoutGridA.vue +103 -0
  75. package/components/presentation/layout-grids/LayoutGridB.vue +132 -0
  76. package/components/presentation/layout-row/LayoutRow.vue +157 -0
  77. package/components/presentation/masonry-grid/MasonryGrid.vue +62 -0
  78. package/components/presentation/masonry-grid-sorted/MasonryGridSorted.vue +115 -0
  79. package/components/presentation/tabs/TabsCore.vue +308 -0
  80. package/components/responsive-header/NavigationItems.vue +164 -0
  81. package/components/responsive-header/ResponsiveHeader.vue +586 -0
  82. package/components/rotating-carousel/RotatingCarouselImage.vue +200 -0
  83. package/composables/useDialogControls.ts +23 -0
  84. package/composables/useStyleClassPassthrough.ts +35 -0
  85. package/composables/useTabs.ts +201 -0
  86. package/nuxt.config.ts +0 -3
  87. package/package.json +7 -7
  88. package/types/gallery-data.ts +13 -0
  89. package/types/responsiveHeader.ts +38 -0
  90. package/types/types.carousel-basic.ts +19 -0
@@ -0,0 +1,200 @@
1
+ <template>
2
+ <component
3
+ :is="tag"
4
+ class="rotating-carousel"
5
+ :class="[elementClasses]"
6
+ :style="`--_rotate-x: ${rotateXProp}deg; --_perspective: ${perspectiveProp}; --_translateZ: ${translateZProp}; --_animation-play-state: ${pauseOnHover ? 'paused' : 'running'}`"
7
+ ref="carouselRef"
8
+ >
9
+ <div class="slider" :style="`--quantity: ${Object.keys(data).length}`">
10
+ <div v-for="(item, key) in data" :key="key" class="item" :style="`--_position: ${key}`"><NuxtImg :src="item.src" :alt="item.alt" /></div>
11
+ </div>
12
+ </component>
13
+ </template>
14
+
15
+ <script lang="ts">
16
+ const TAGS_ALLOWED = <string[]>['div', 'p', 'span', 'section', 'article', 'aside', 'header', 'footer', 'main', 'nav', 'ul', 'ol'];
17
+ interface IAccordianData {
18
+ src: string;
19
+ alt: string;
20
+ }
21
+ </script>
22
+
23
+ <script setup lang="ts">
24
+ const props = defineProps({
25
+ data: {
26
+ type: Array as PropType<IAccordianData[]>,
27
+ default: () => [],
28
+ },
29
+ tag: {
30
+ type: String,
31
+ default: 'div',
32
+ validator(value: string) {
33
+ return TAGS_ALLOWED.includes(value);
34
+ },
35
+ },
36
+ rotateX: {
37
+ type: Number,
38
+ default: 0,
39
+ },
40
+ perspective: {
41
+ type: Number,
42
+ default: 1000,
43
+ },
44
+ translateZ: {
45
+ type: Number,
46
+ default: 1000,
47
+ },
48
+ pauseOnHover: {
49
+ type: Boolean,
50
+ default: false,
51
+ },
52
+ useParallaxEffect: {
53
+ type: Boolean,
54
+ default: true,
55
+ },
56
+ styleClassPassthrough: {
57
+ type: Array as PropType<string[]>,
58
+ default: () => [],
59
+ },
60
+ });
61
+
62
+ const perspectiveProp = computed(() => `${props.perspective.toString()}px`);
63
+ const translateZProp = computed(() => `${props.translateZ.toString()}px`);
64
+
65
+ const carouselRef = ref<HTMLElement | null>(null);
66
+ const rotateXProp = ref(props.rotateX);
67
+ const minRotateX = -32;
68
+ const maxRotateX = 32;
69
+
70
+ const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
71
+
72
+ watch(
73
+ () => props.styleClassPassthrough,
74
+ () => {
75
+ resetElementClasses(props.styleClassPassthrough);
76
+ }
77
+ );
78
+
79
+ watch(
80
+ () => props.rotateX,
81
+ () => {
82
+ if (!props.useParallaxEffect) {
83
+ console.log('rotateXProp changed: ', rotateXProp.value);
84
+
85
+ rotateXProp.value = props.rotateX;
86
+ }
87
+ }
88
+ );
89
+
90
+ watch(
91
+ () => props.useParallaxEffect,
92
+ (currentValue) => {
93
+ if (currentValue) {
94
+ handleScroll();
95
+ window.addEventListener('scroll', handleScroll);
96
+ } else {
97
+ window.removeEventListener('scroll', handleScroll);
98
+ }
99
+ }
100
+ );
101
+
102
+ const handleScroll = () => {
103
+ if (!carouselRef.value) return;
104
+ if ('IntersectionObserver' in window) {
105
+ const rect = carouselRef.value.getBoundingClientRect();
106
+ const viewportHeight = window.innerHeight;
107
+
108
+ const elementCenter = rect.top + rect.height / 2;
109
+ const viewportCenter = viewportHeight / 2;
110
+ const distanceFromCenter = viewportCenter - elementCenter;
111
+ const maxDistance = viewportHeight / 2 + rect.height / 2;
112
+
113
+ const progress = (distanceFromCenter + maxDistance) / (maxDistance * 2);
114
+ const clampedProgress = Math.max(0, Math.min(1, progress));
115
+
116
+ rotateXProp.value = minRotateX + (maxRotateX - minRotateX) * clampedProgress;
117
+ }
118
+ };
119
+
120
+ onMounted(async () => {
121
+ if (props.useParallaxEffect) {
122
+ handleScroll();
123
+ await nextTick();
124
+ window.addEventListener('scroll', handleScroll);
125
+ }
126
+ });
127
+
128
+ onUnmounted(() => {
129
+ window.removeEventListener('scroll', handleScroll);
130
+ });
131
+ </script>
132
+
133
+ <style lang="css">
134
+ /* @property --_rotate-x {
135
+ syntax: '<angle>';
136
+ inherits: false;
137
+ initial-value: 0deg;
138
+ }
139
+
140
+ @keyframes autoRotateAnimation {
141
+ from {
142
+ --_rotate-x: -16deg;
143
+ }
144
+ to {
145
+ --_rotate-x: 16deg;
146
+ }
147
+ } */
148
+
149
+ @keyframes autoRun {
150
+ from {
151
+ transform: perspective(var(--_perspective)) rotateX(var(--_rotate-x)) rotateY(0deg);
152
+ }
153
+ to {
154
+ transform: perspective(var(--_perspective)) rotateX(var(--_rotate-x)) rotateY(360deg);
155
+ }
156
+ }
157
+
158
+ .rotating-carousel {
159
+ width: 100%;
160
+ height: 70svh;
161
+ text-align: center;
162
+ overflow: hidden;
163
+ position: relative;
164
+
165
+ /* padding-block: 800px; */
166
+
167
+ /* &.scroll-effect {
168
+ animation: autoRotateAnimation;
169
+ animation-timeline: view();
170
+ } */
171
+
172
+ .slider {
173
+ position: absolute;
174
+ width: 200px;
175
+ height: 250px;
176
+ bottom: 35%;
177
+ left: calc(50% - 100px);
178
+ transform-style: preserve-3d;
179
+ transform: perspective(var(--_perspective));
180
+ animation: autoRun 30s linear infinite;
181
+ z-index: 2;
182
+
183
+ &:has(.item img:hover) {
184
+ animation-play-state: var(--_animation-play-state);
185
+ }
186
+
187
+ .item {
188
+ position: absolute;
189
+ inset: 0 0 0 0;
190
+ transform: rotateY(calc((var(--_position) - 1) * (360 / var(--quantity)) * 1deg)) translateZ(var(--_translateZ));
191
+
192
+ img {
193
+ width: 100%;
194
+ height: 100%;
195
+ object-fit: cover;
196
+ }
197
+ }
198
+ }
199
+ }
200
+ </style>
@@ -0,0 +1,23 @@
1
+ export const useDialogControls = () => {
2
+ interface DialogConfig {
3
+ [key: string]: boolean;
4
+ }
5
+
6
+ const dialogsConfig = reactive<DialogConfig>({});
7
+
8
+ function initialiseDialogs(dialogIds: string[]) {
9
+ dialogIds.forEach((id) => {
10
+ dialogsConfig[id] = false;
11
+ });
12
+ }
13
+
14
+ const controlDialogs = (name: string, state: boolean) => {
15
+ dialogsConfig[name] = state;
16
+ };
17
+
18
+ return {
19
+ dialogsConfig,
20
+ controlDialogs,
21
+ initialiseDialogs,
22
+ };
23
+ };
@@ -0,0 +1,35 @@
1
+ export const useStyleClassPassthrough = (styleClassPassthrough: string[]) => {
2
+ const styleClassPassthroughRef = ref(styleClassPassthrough);
3
+
4
+ const elementClasses = computed(() => {
5
+ return styleClassPassthroughRef.value.join(' ');
6
+ });
7
+
8
+ const updateElementClasses = (cssClass: string | string[]) => {
9
+ let cssClasses = [] as string[];
10
+ if (typeof cssClass === 'string') {
11
+ cssClasses = [cssClass];
12
+ } else if (Array.isArray(cssClass)) {
13
+ cssClasses = cssClass;
14
+ }
15
+
16
+ cssClasses.forEach((cssClass) => {
17
+ if (styleClassPassthroughRef.value.includes(cssClass)) {
18
+ styleClassPassthroughRef.value = styleClassPassthroughRef.value.filter((className) => className !== cssClass);
19
+ } else {
20
+ styleClassPassthroughRef.value.push(cssClass);
21
+ }
22
+ });
23
+ };
24
+
25
+ const resetElementClasses = (propsClasses: string[]) => {
26
+ styleClassPassthroughRef.value = propsClasses;
27
+ };
28
+
29
+ return {
30
+ elementClasses,
31
+ updateElementClasses,
32
+ resetElementClasses,
33
+ styleClassPassthroughRef,
34
+ };
35
+ };
@@ -0,0 +1,201 @@
1
+ import { useResizeObserver } from '@vueuse/core';
2
+
3
+ const useTabs = (axis: string, tabsNavRef: Ref<HTMLElement | null>, tabsContentRefs: Ref<HTMLElement[] | null>, duration: number) => {
4
+ const navItems = ref<HTMLElement[] | null>(null);
5
+ const previousActiveTab = useState<HTMLElement | null>('previousActiveTab', () => null);
6
+ const currentActiveTab = ref<HTMLElement>();
7
+
8
+ const previousHoveredTab = ref<HTMLElement>();
9
+ const currentHoveredTab = ref<HTMLElement>();
10
+ const tagName = ref<string>();
11
+
12
+ const initNavDecorators = () => {
13
+ navItems.value = tabsNavRef.value ? (Array.from(tabsNavRef.value.querySelectorAll('[data-nav-item')) as HTMLElement[]) : [];
14
+ tagName.value = navItems.value[0].tagName.toLowerCase();
15
+
16
+ const activeIndex = ref(0);
17
+
18
+ // Temporarily set the first nav item as active
19
+ navItems.value[0].setAttribute('aria-selected', 'true');
20
+
21
+ // Test if navItems are hyperlinks
22
+ if (navItems.value[0].tagName.toLowerCase() === 'a') {
23
+ // Find index of element with class "router-link-active"
24
+ activeIndex.value = navItems.value.findIndex((el) => el.classList.contains('router-link-active'));
25
+ }
26
+ // else {
27
+ // Set actve tab
28
+ // }
29
+
30
+ currentActiveTab.value = navItems.value[activeIndex.value];
31
+ currentHoveredTab.value = navItems.value[activeIndex.value];
32
+
33
+ previousActiveTab.value = navItems.value[activeIndex.value];
34
+ previousHoveredTab.value = navItems.value[activeIndex.value];
35
+
36
+ addNavDecorators();
37
+ setActiveTabContent();
38
+ };
39
+
40
+ const addNavDecorators = () => {
41
+ const elementClasses = ['nav__active-indicator', 'nav__active', 'nav__hovered'];
42
+ if (tabsNavRef.value) {
43
+ for (let i = 0; i < 3; i++) {
44
+ const div = document.createElement('div');
45
+ div.classList.add(elementClasses[i]);
46
+ tabsNavRef.value.appendChild(div);
47
+ }
48
+ }
49
+ };
50
+
51
+ const navItemHovered = (event: Event) => {
52
+ const target = event.target as HTMLElement;
53
+ const newTabPosition = currentHoveredTab.value ? currentHoveredTab.value.compareDocumentPosition(target) : 0;
54
+
55
+ if (newTabPosition !== 0) {
56
+ previousHoveredTab.value = currentHoveredTab.value;
57
+ currentHoveredTab.value = target;
58
+ moveHoveredIndicator();
59
+ }
60
+ };
61
+
62
+ const resetHoverToActivePosition = () => {
63
+ previousHoveredTab.value = currentHoveredTab.value;
64
+ currentHoveredTab.value = currentActiveTab.value;
65
+ moveHoveredIndicator();
66
+ };
67
+
68
+ const navItemClicked = (event: Event) => {
69
+ const target = event.target as HTMLElement;
70
+
71
+ previousActiveTab.value = currentActiveTab.value || null;
72
+ currentActiveTab.value = target;
73
+
74
+ navItems.value?.forEach((tab) => {
75
+ tab.setAttribute('aria-selected', currentActiveTab.value === tab ? 'true' : 'false');
76
+ });
77
+
78
+ moveActiveIndicator();
79
+ setActiveTabContent();
80
+ };
81
+
82
+ const handleTransitioningClass = (transitionDuration: number = 200) => {
83
+ if (previousHoveredTab.value && currentHoveredTab.value) {
84
+ const newTabPosition = previousHoveredTab.value.compareDocumentPosition(currentHoveredTab.value);
85
+ const navItemsArray = navItems.value || [];
86
+
87
+ const timeout = Math.floor(transitionDuration / Math.abs(navItemsArray.indexOf(currentHoveredTab.value) - navItemsArray.indexOf(previousHoveredTab.value)));
88
+
89
+ if (newTabPosition === 4) {
90
+ for (let i = navItemsArray.indexOf(previousHoveredTab.value); i < navItemsArray.indexOf(currentHoveredTab.value); i++) {
91
+ navItemsArray[i].classList.add('transitioning');
92
+ if (i >= navItemsArray.indexOf(previousHoveredTab.value) && i < navItemsArray.indexOf(currentHoveredTab.value)) {
93
+ setTimeout(() => {
94
+ navItemsArray[i].classList.remove('transitioning');
95
+ // }, timeout * (i - navItemsArray.indexOf(previousHoveredTab.value) - 1));
96
+ }, duration * 1.5);
97
+ }
98
+ }
99
+ } else {
100
+ for (let i = navItemsArray.indexOf(previousHoveredTab.value); i > navItemsArray.indexOf(currentHoveredTab.value); i--) {
101
+ navItemsArray[i].classList.add('transitioning');
102
+ if (i <= navItemsArray.indexOf(previousHoveredTab.value) && i > navItemsArray.indexOf(currentHoveredTab.value)) {
103
+ setTimeout(() => {
104
+ navItemsArray[i].classList.remove('transitioning');
105
+ // }, timeout * (i - navItemsArray.indexOf(previousHoveredTab.value) - 1));
106
+ }, duration * 1.5);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ };
112
+
113
+ const setFinalHoveredPositions = (resized: boolean = false) => {
114
+ const setDuration = resized ? 0 : duration;
115
+ // const tabsNavRefYPosition = tabsNavRef.value?.getBoundingClientRect().top || 0;
116
+ const newTabWidth = currentHoveredTab.value && tabsNavRef.value ? currentHoveredTab.value.offsetWidth / tabsNavRef.value.offsetWidth : 0;
117
+ tabsNavRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
118
+ tabsNavRef.value?.style.setProperty('--_x-hovered', currentHoveredTab.value?.offsetLeft + 'px');
119
+
120
+ tabsNavRef.value?.style.setProperty('--_width-hovered', newTabWidth?.toString());
121
+ tabsNavRef.value?.style.setProperty('--_y-hovered', currentHoveredTab.value?.offsetTop + 'px');
122
+ tabsNavRef.value?.style.setProperty('--_y-height', currentHoveredTab.value?.offsetHeight + 'px');
123
+ tabsNavRef.value?.style.setProperty('--_y-width', currentHoveredTab.value?.offsetWidth + 'px');
124
+ };
125
+
126
+ const setFinalActivePositions = (resized: boolean = false) => {
127
+ const setDuration = resized ? 0 : duration;
128
+ const newTabWidth = currentActiveTab.value && tabsNavRef.value ? currentActiveTab.value.offsetWidth / tabsNavRef.value.offsetWidth : 0;
129
+ tabsNavRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
130
+ tabsNavRef.value?.style.setProperty('--_x-active', currentActiveTab.value?.offsetLeft + 'px');
131
+ tabsNavRef.value?.style.setProperty('--_width-active', newTabWidth?.toString());
132
+ tabsNavRef.value?.style.setProperty('--_y-active', currentActiveTab.value?.offsetTop + 'px');
133
+ tabsNavRef.value?.style.setProperty('--_y-height', currentActiveTab.value?.offsetHeight + 'px');
134
+ tabsNavRef.value?.style.setProperty('--_y-width', currentActiveTab.value?.offsetWidth + 'px');
135
+ };
136
+
137
+ const moveActiveIndicator = () => {
138
+ tabsNavRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
139
+
140
+ const newTabPosition = previousActiveTab.value && currentActiveTab.value ? previousActiveTab.value.compareDocumentPosition(currentActiveTab.value) : 0;
141
+ let transitionWidth;
142
+
143
+ if (newTabPosition === 4) {
144
+ transitionWidth = currentActiveTab.value && previousActiveTab.value ? currentActiveTab.value.offsetLeft + currentActiveTab.value.offsetWidth - previousActiveTab.value.offsetLeft : 0;
145
+ } else {
146
+ transitionWidth = previousActiveTab.value && currentActiveTab.value ? previousActiveTab.value.offsetLeft + previousActiveTab.value.offsetWidth - currentActiveTab.value.offsetLeft : 0;
147
+ tabsNavRef.value?.style.setProperty('--_x-active', currentActiveTab.value ? currentActiveTab.value.offsetLeft + 'px' : '0');
148
+ }
149
+
150
+ tabsNavRef.value?.style.setProperty('--_width-active', String(transitionWidth / tabsNavRef.value.offsetWidth));
151
+
152
+ handleTransitioningClass(duration);
153
+
154
+ setTimeout(() => {
155
+ setFinalActivePositions();
156
+ }, Math.floor(duration + 20));
157
+ };
158
+
159
+ const moveHoveredIndicator = () => {
160
+ tabsNavRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
161
+
162
+ const newTabPosition = previousHoveredTab.value && currentHoveredTab.value ? previousHoveredTab.value.compareDocumentPosition(currentHoveredTab.value) : 0;
163
+ let transitionWidth;
164
+
165
+ if (newTabPosition === 4) {
166
+ transitionWidth = currentHoveredTab.value && previousHoveredTab.value ? currentHoveredTab.value.offsetLeft + currentHoveredTab.value.offsetWidth - previousHoveredTab.value.offsetLeft : 0;
167
+ } else {
168
+ transitionWidth = previousHoveredTab.value && currentHoveredTab.value ? previousHoveredTab.value.offsetLeft + previousHoveredTab.value.offsetWidth - currentHoveredTab.value.offsetLeft : 0;
169
+ tabsNavRef.value?.style.setProperty('--_x-hovered', currentHoveredTab.value ? currentHoveredTab.value.offsetLeft + 'px' : '0');
170
+ }
171
+
172
+ tabsNavRef.value?.style.setProperty('--_width-hovered', String(transitionWidth / tabsNavRef.value.offsetWidth));
173
+
174
+ handleTransitioningClass(duration);
175
+
176
+ setTimeout(() => {
177
+ setFinalHoveredPositions();
178
+ }, Math.floor(duration + 20));
179
+ };
180
+
181
+ const setActiveTabContent = () => {
182
+ const activeIndex = navItems.value?.findIndex((el) => el === currentActiveTab.value);
183
+ tabsContentRefs.value?.forEach((tabContent: HTMLElement, index: number) => {
184
+ tabContent.style.display = activeIndex === index ? 'block' : 'none';
185
+ });
186
+ };
187
+
188
+ useResizeObserver(tabsNavRef, () => {
189
+ setFinalActivePositions(true);
190
+ setFinalHoveredPositions(true);
191
+ });
192
+
193
+ return {
194
+ initNavDecorators,
195
+ navItemClicked,
196
+ navItemHovered,
197
+ resetHoverToActivePosition,
198
+ };
199
+ };
200
+
201
+ export default useTabs;
package/nuxt.config.ts CHANGED
@@ -1,8 +1,5 @@
1
1
  // https://nuxt.com/docs/api/configuration/nuxt-config
2
2
  export default defineNuxtConfig({
3
- future: {
4
- compatibilityVersion: 4,
5
- },
6
3
  devtools: { enabled: true },
7
4
  css: ['modern-normalize', './assets/styles/main.css'],
8
5
  modules: ['@nuxt/icon', '@nuxt/image', '@nuxt/eslint'],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "3.0.0",
4
+ "version": "4.0.1",
5
5
  "main": "nuxt.config.ts",
6
6
  "scripts": {
7
7
  "clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",
@@ -27,18 +27,18 @@
27
27
  "devDependencies": {
28
28
  "@iconify-json/akar-icons": "1.2.2",
29
29
  "@iconify-json/bitcoin-icons": "1.2.2",
30
- "@nuxt/eslint": "1.3.0",
31
- "@nuxt/eslint-config": "1.3.0",
32
- "@nuxt/icon": "1.12.0",
30
+ "@nuxt/eslint": "1.5.2",
31
+ "@nuxt/eslint-config": "1.5.2",
32
+ "@nuxt/icon": "1.15.0",
33
33
  "@nuxt/image": "1.10.0",
34
+ "@oddbird/css-anchor-positioning": "0.6.1",
35
+ "@vueuse/core": "13.5.0",
34
36
  "happy-dom": "16.8.1",
35
- "nuxt": "3.17.2",
37
+ "nuxt": "3.17.6",
36
38
  "release-it": "18.1.2",
37
39
  "typescript": "5.8.3"
38
40
  },
39
41
  "dependencies": {
40
- "@oddbird/css-anchor-positioning": "0.6.0",
41
- "@vueuse/core": "13.1.0",
42
42
  "focus-trap-vue": "4.0.3",
43
43
  "modern-normalize": "3.0.1"
44
44
  },
@@ -0,0 +1,13 @@
1
+ export interface IGalleryData {
2
+ src: string;
3
+ alt: string;
4
+ stylist?: string;
5
+ title?: string;
6
+ category?: string;
7
+ description?: string;
8
+ thumbnail?: {
9
+ title: string;
10
+ description: string;
11
+ };
12
+ textBrightness: 'light' | 'dark';
13
+ }
@@ -0,0 +1,38 @@
1
+ export interface ResponsiveHeaderNavItem {
2
+ name: string;
3
+ path?: string;
4
+ iconName?: string;
5
+ imageSrc?: string;
6
+ imageAlt?: string;
7
+ description?: string;
8
+ isActive?: boolean;
9
+ isExternal?: boolean;
10
+ childLinksTitle?: string;
11
+ childLinks?: ResponsiveHeaderNavItem[];
12
+ config?: ResponsiveHeaderItemRects;
13
+ }
14
+
15
+ export interface ResponsiveHeaderProp {
16
+ [key: string]: ResponsiveHeaderNavItem[];
17
+ }
18
+
19
+ export interface IFlooredRect {
20
+ left: number;
21
+ right: number;
22
+ top: number;
23
+ bottom: number;
24
+ width: number;
25
+ height: number;
26
+ }
27
+
28
+ export interface ResponsiveHeaderItemRects {
29
+ left: number;
30
+ right: number;
31
+ width?: number;
32
+ visible: boolean;
33
+ }
34
+
35
+ export interface ResponsiveHeaderState {
36
+ navListVisibility: Record<string, boolean>;
37
+ clonedNavLinks?: ResponsiveHeaderProp;
38
+ }
@@ -0,0 +1,19 @@
1
+ export interface CarouselBasicItem {
2
+ id: number | string;
3
+ url: string;
4
+ alt: string;
5
+ }
6
+
7
+ export interface CarouselModifiedItem {
8
+ id: number | string;
9
+ url: string;
10
+ alt: string;
11
+ order: number;
12
+ }
13
+
14
+ export interface ICarouselBasic {
15
+ items: CarouselBasicItem[] | CarouselModifiedItem[];
16
+ total: number;
17
+ skip: number;
18
+ limit: number;
19
+ }