srcdev-nuxt-components 0.0.27 → 0.0.28

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,19 +1,33 @@
1
1
  <template>
2
- <ul role="tablist" aria-labelledby="channel-name" ref="navContainerRef" @mouseleave="resetHoverToActivePosition()" class="tabs-list" :class="[elementClasses]">
3
- <li v-for="(item, index) in navItems" class="masonry-grid-ordered-item" ref="gridItemsRefs">
4
- <button @click.prevent="navItemClicked($event)" @mouseover="navItemHovered($event)" :data-tab-index="index" data-nav-item role="tab" aria-selected="false" class="tabs-list-item">
5
- {{ item.name }}
6
- </button>
7
- </li>
8
- </ul>
2
+ <div class="tabs">
3
+ <ul role="tablist" aria-labelledby="channel-name" ref="tabsNavRef" @mouseleave="resetHoverToActivePosition()" class="tabs-list" :class="[elementClasses]">
4
+ <li v-for="(index, key) in navItems" :key="key">
5
+ <button
6
+ @click.prevent="navItemClicked($event)"
7
+ @mouseover="navItemHovered($event)"
8
+ :id="`tab-${key}-trigger`"
9
+ :data-tab-index="index"
10
+ data-nav-item
11
+ role="tab"
12
+ aria-selected="false"
13
+ class="tabs-list-item"
14
+ >
15
+ <slot :name="`tab-${key}-trigger`"></slot>
16
+ </button>
17
+ </li>
18
+ </ul>
19
+ <div class="tab-content-wrapper">
20
+ <div v-for="(item, key) in navItems" :key="key" class="tab-content" :aria-labelledby="`tab-${key}-trigger`" :id="`tab-${key}-content`" role="region" aria-hidden="true" ref="tabsContentRefs">
21
+ <div>
22
+ <slot :name="`tab-${key}-content`"></slot>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
9
27
  </template>
10
28
 
11
29
  <script setup lang="ts">
12
- interface INavLink {
13
- action?: string;
14
- name: string;
15
- path?: string;
16
- }
30
+ import type { ITabNav } from '@/types/types.tabs';
17
31
 
18
32
  const props = defineProps({
19
33
  tag: {
@@ -21,7 +35,7 @@ const props = defineProps({
21
35
  default: 'button',
22
36
  },
23
37
  navItems: {
24
- type: Array as PropType<INavLink[]>,
38
+ type: Array as PropType<ITabNav[]>,
25
39
  required: true,
26
40
  },
27
41
  trackHover: {
@@ -44,9 +58,10 @@ const props = defineProps({
44
58
 
45
59
  const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
46
60
 
47
- const navContainerRef = ref<HTMLElement | null>(null);
61
+ const tabsNavRef = ref<HTMLElement | null>(null);
62
+ const tabsContentRefs = ref<HTMLElement[] | null>(null);
48
63
 
49
- const { initNavDecorators, navItemClicked, navItemHovered, resetHoverToActivePosition } = useNavDecoration(navContainerRef);
64
+ const { initNavDecorators, navItemClicked, navItemHovered, resetHoverToActivePosition } = useTabs(tabsNavRef, tabsContentRefs);
50
65
 
51
66
  onMounted(() => {
52
67
  initNavDecorators();
@@ -168,4 +183,14 @@ onMounted(() => {
168
183
  }
169
184
  }
170
185
  }
186
+
187
+ .tab-content-wrapper {
188
+ display: grid;
189
+ grid-template-areas: 'element-stack';
190
+
191
+ .tab-content {
192
+ grid-area: element-stack;
193
+ display: none;
194
+ }
195
+ }
171
196
  </style>
@@ -1,6 +1,6 @@
1
1
  import { useResizeObserver } from '@vueuse/core';
2
2
 
3
- const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: number = 200) => {
3
+ const useTabs = (tabsNavRef: Ref<HTMLElement | null>, tabsContentRefs: Ref<HTMLElement[] | null>, duration: number = 200) => {
4
4
  const navItems = ref<HTMLElement[] | null>(null);
5
5
  const previousActiveTab = useState<HTMLElement | null>('previousActiveTab', () => null);
6
6
  const currentActiveTab = ref<HTMLElement>();
@@ -10,7 +10,7 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
10
10
  const tagName = ref<string>();
11
11
 
12
12
  const initNavDecorators = () => {
13
- navItems.value = navContainerRef.value ? (Array.from(navContainerRef.value.querySelectorAll('[data-nav-item')) as HTMLElement[]) : [];
13
+ navItems.value = tabsNavRef.value ? (Array.from(tabsNavRef.value.querySelectorAll('[data-nav-item')) as HTMLElement[]) : [];
14
14
  tagName.value = navItems.value[0].tagName.toLowerCase();
15
15
 
16
16
  const activeIndex = ref(0);
@@ -34,15 +34,16 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
34
34
  previousHoveredTab.value = navItems.value[activeIndex.value];
35
35
 
36
36
  addNavDecorators();
37
+ setActiveTabContent();
37
38
  };
38
39
 
39
40
  const addNavDecorators = () => {
40
41
  const elementClasses = ['nav__active-indicator', 'nav__active', 'nav__hovered'];
41
- if (navContainerRef.value) {
42
+ if (tabsNavRef.value) {
42
43
  for (let i = 0; i < 3; i++) {
43
44
  const div = document.createElement('div');
44
45
  div.classList.add(elementClasses[i]);
45
- navContainerRef.value.appendChild(div);
46
+ tabsNavRef.value.appendChild(div);
46
47
  }
47
48
  }
48
49
  };
@@ -75,26 +76,27 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
75
76
  });
76
77
 
77
78
  moveActiveIndicator();
79
+ setActiveTabContent();
78
80
  };
79
81
 
80
82
  const setFinalHoveredPositions = (resized: boolean = false) => {
81
83
  const setDuration = resized ? 0 : duration;
82
- const newTabWidth = currentHoveredTab.value && navContainerRef.value ? currentHoveredTab.value.offsetWidth / navContainerRef.value.offsetWidth : 0;
83
- navContainerRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
84
- navContainerRef.value?.style.setProperty('--_left-hovered', currentHoveredTab.value?.offsetLeft + 'px');
85
- navContainerRef.value?.style.setProperty('--_width-hovered', newTabWidth?.toString());
84
+ const newTabWidth = currentHoveredTab.value && tabsNavRef.value ? currentHoveredTab.value.offsetWidth / tabsNavRef.value.offsetWidth : 0;
85
+ tabsNavRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
86
+ tabsNavRef.value?.style.setProperty('--_left-hovered', currentHoveredTab.value?.offsetLeft + 'px');
87
+ tabsNavRef.value?.style.setProperty('--_width-hovered', newTabWidth?.toString());
86
88
  };
87
89
 
88
90
  const setFinalActivePositions = (resized: boolean = false) => {
89
91
  const setDuration = resized ? 0 : duration;
90
- const newTabWidth = currentActiveTab.value && navContainerRef.value ? currentActiveTab.value.offsetWidth / navContainerRef.value.offsetWidth : 0;
91
- navContainerRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
92
- navContainerRef.value?.style.setProperty('--_left-active', currentActiveTab.value?.offsetLeft + 'px');
93
- navContainerRef.value?.style.setProperty('--_width-active', newTabWidth?.toString());
92
+ const newTabWidth = currentActiveTab.value && tabsNavRef.value ? currentActiveTab.value.offsetWidth / tabsNavRef.value.offsetWidth : 0;
93
+ tabsNavRef.value?.style.setProperty('--_transition-duration', setDuration + 'ms');
94
+ tabsNavRef.value?.style.setProperty('--_left-active', currentActiveTab.value?.offsetLeft + 'px');
95
+ tabsNavRef.value?.style.setProperty('--_width-active', newTabWidth?.toString());
94
96
  };
95
97
 
96
98
  const moveActiveIndicator = () => {
97
- navContainerRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
99
+ tabsNavRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
98
100
 
99
101
  const newTabPosition = previousActiveTab.value && currentActiveTab.value ? previousActiveTab.value.compareDocumentPosition(currentActiveTab.value) : 0;
100
102
  let transitionWidth;
@@ -103,10 +105,10 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
103
105
  transitionWidth = currentActiveTab.value && previousActiveTab.value ? currentActiveTab.value.offsetLeft + currentActiveTab.value.offsetWidth - previousActiveTab.value.offsetLeft : 0;
104
106
  } else {
105
107
  transitionWidth = previousActiveTab.value && currentActiveTab.value ? previousActiveTab.value.offsetLeft + previousActiveTab.value.offsetWidth - currentActiveTab.value.offsetLeft : 0;
106
- navContainerRef.value?.style.setProperty('--_left-active', currentActiveTab.value ? currentActiveTab.value.offsetLeft + 'px' : '0');
108
+ tabsNavRef.value?.style.setProperty('--_left-active', currentActiveTab.value ? currentActiveTab.value.offsetLeft + 'px' : '0');
107
109
  }
108
110
 
109
- navContainerRef.value?.style.setProperty('--_width-active', String(transitionWidth / navContainerRef.value.offsetWidth));
111
+ tabsNavRef.value?.style.setProperty('--_width-active', String(transitionWidth / tabsNavRef.value.offsetWidth));
110
112
 
111
113
  setTimeout(() => {
112
114
  setFinalActivePositions();
@@ -114,7 +116,7 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
114
116
  };
115
117
 
116
118
  const moveHoveredIndicator = () => {
117
- navContainerRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
119
+ tabsNavRef.value?.style.setProperty('--_transition-duration', duration + 'ms');
118
120
 
119
121
  const newTabPosition = previousHoveredTab.value && currentHoveredTab.value ? previousHoveredTab.value.compareDocumentPosition(currentHoveredTab.value) : 0;
120
122
  let transitionWidth;
@@ -123,28 +125,38 @@ const useNavDecoration = (navContainerRef: Ref<HTMLElement | null>, duration: nu
123
125
  transitionWidth = currentHoveredTab.value && previousHoveredTab.value ? currentHoveredTab.value.offsetLeft + currentHoveredTab.value.offsetWidth - previousHoveredTab.value.offsetLeft : 0;
124
126
  } else {
125
127
  transitionWidth = previousHoveredTab.value && currentHoveredTab.value ? previousHoveredTab.value.offsetLeft + previousHoveredTab.value.offsetWidth - currentHoveredTab.value.offsetLeft : 0;
126
- navContainerRef.value?.style.setProperty('--_left-hovered', currentHoveredTab.value ? currentHoveredTab.value.offsetLeft + 'px' : '0');
128
+ tabsNavRef.value?.style.setProperty('--_left-hovered', currentHoveredTab.value ? currentHoveredTab.value.offsetLeft + 'px' : '0');
127
129
  }
128
130
 
129
- navContainerRef.value?.style.setProperty('--_width-hovered', String(transitionWidth / navContainerRef.value.offsetWidth));
131
+ tabsNavRef.value?.style.setProperty('--_width-hovered', String(transitionWidth / tabsNavRef.value.offsetWidth));
130
132
 
131
133
  setTimeout(() => {
132
134
  setFinalHoveredPositions();
133
135
  }, Math.floor(duration + 20));
134
136
  };
135
137
 
136
- useResizeObserver(navContainerRef, () => {
138
+ const setActiveTabContent = () => {
139
+ const activeIndex = navItems.value?.findIndex((el) => el === currentActiveTab.value);
140
+ tabsContentRefs.value?.forEach((tabContent: HTMLElement, index: number) => {
141
+ tabContent.style.display = activeIndex === index ? 'block' : 'none';
142
+ });
143
+ };
144
+
145
+ const animationRunning = (running: boolean) => {
146
+ console.log('animationRunning', running);
147
+ };
148
+
149
+ useResizeObserver(tabsNavRef, () => {
137
150
  setFinalActivePositions(true);
138
151
  setFinalHoveredPositions(true);
139
152
  });
140
153
 
141
154
  return {
142
155
  initNavDecorators,
143
- navContainerRef,
144
156
  navItemClicked,
145
157
  navItemHovered,
146
158
  resetHoverToActivePosition,
147
159
  };
148
160
  };
149
161
 
150
- export default useNavDecoration;
162
+ export default useTabs;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "0.0.27",
4
+ "version": "0.0.28",
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",