srcdev-nuxt-components 4.0.1 → 4.0.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.
@@ -9,6 +9,7 @@ html {
9
9
 
10
10
  font-size: 62.5%;
11
11
  scrollbar-gutter: stable;
12
+ overflow-x: hidden;
12
13
  }
13
14
  body {
14
15
  color: var(--grayscale-text-body);
@@ -18,6 +19,8 @@ body {
18
19
  }
19
20
 
20
21
  body {
22
+ overflow-x: hidden;
23
+
21
24
  &.lock {
22
25
  overflow: hidden;
23
26
  }
@@ -1,44 +1,49 @@
1
1
  <template>
2
- <section class="carousel-basic" :class="[elementClasses]" ref="carouselWrapperRef">
3
-
4
- <div tabindex="0" class="item-container" ref="carouselContainerRef">
5
- <div v-for="(item, index) in carouselDataIds" :key="index" class="item" ref="carouselItems">
6
- <slot :name="item"></slot>
2
+ <section class="carousel-basic" :class="[elementClasses]" ref="carouselWrapperRef" role="region" aria-label="Image carousel">
3
+ <!-- Screen reader announcement for current item -->
4
+ <div aria-live="polite" aria-atomic="true" class="sr-only">Item {{ currentIndex + 1 }} of {{ itemCount }}</div>
5
+
6
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
7
+ <div tabindex="0" class="item-container" :class="{ 'allow-overflow': allowCarouselOverflow }" ref="carouselContainerRef" role="group" aria-label="Carousel items">
8
+ <div v-for="(item, index) in carouselDataIds" :key="index" class="item" ref="carouselItems" :aria-current="currentIndex === index ? 'true' : 'false'">
9
+ <slot :name="item"></slot>
10
+ </div>
7
11
  </div>
8
- </div>
12
+ </LayoutRow>
9
13
 
10
- <div class="timeline-container">
11
- <div v-for="index in itemCount" :key="index" class="timeline-item">
12
- <div class="count">Step {{ Math.floor(index + 1) }}</div>
13
- </div>
14
- </div>
15
-
16
- <div class="controls-container">
17
- <div class="markers-container">
18
- <ul class="markers-list">
19
- <li v-for="index in itemCount" :key="index" class="markers-item">
20
- <button @click.prevent="jumpToFrame(index)" class="btn-marker"
21
- :class="[{ active: currentIndex === index - 1}]"><span class="sr-only">Jump to item{{
22
- Math.floor(index + 1) }}</span></button>
23
- </li>
24
- </ul>
14
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
15
+ <div class="timeline-container">
16
+ <div v-for="index in itemCount" :key="index" class="timeline-item">
17
+ <div class="count">Step {{ index }}</div>
18
+ </div>
25
19
  </div>
26
- <div class="buttons-container">
27
- <button type="submit" @click.prevent="actionPrevious()" class="btn-action">Prev</button>
28
- <button type="submit" @click.prevent="actionNext()" class="btn-action">Next</button>
20
+ </LayoutRow>
21
+
22
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
23
+ <div tabindex="0" class="controls-container" ref="controlsContainerRef">
24
+ <div class="markers-container">
25
+ <ul class="markers-list">
26
+ <li v-for="index in itemCount" :key="index" class="markers-item">
27
+ <button @click.prevent="jumpToFrame(index - 1)" class="btn-marker" :class="[{ active: currentIndex === index - 1 }]" :aria-label="`Jump to item ${Math.floor(index + 1)}`"></button>
28
+ </li>
29
+ </ul>
30
+ </div>
31
+ <div class="buttons-container">
32
+ <button type="button" @click.prevent="actionPrevious()" class="btn-action" aria-label="Go to previous item">Prev</button>
33
+ <button type="button" @click.prevent="actionNext()" class="btn-action" aria-label="Go to next item">Next</button>
34
+ </div>
29
35
  </div>
30
- </div>
36
+ </LayoutRow>
31
37
  </section>
32
38
  </template>
33
39
 
34
40
  <script setup lang="ts">
35
- import type { ICarouselBasic } from "@/types/types.carousel-basic";
36
- import { useEventListener, useResizeObserver, useSwipe } from "@vueuse/core";
41
+ import { useEventListener, useResizeObserver, useSwipe } from '@vueuse/core';
37
42
 
38
43
  const props = defineProps({
39
44
  carouselDataIds: {
40
45
  type: Array as PropType<string[]>,
41
- default: () => []
46
+ default: () => [],
42
47
  },
43
48
  styleClassPassthrough: {
44
49
  type: Array as PropType<string[]>,
@@ -46,8 +51,12 @@ const props = defineProps({
46
51
  },
47
52
  transitionSpeed: {
48
53
  type: Number,
49
- default: 200
50
- }
54
+ default: 200,
55
+ },
56
+ allowCarouselOverflow: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
51
60
  });
52
61
 
53
62
  const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
@@ -55,6 +64,7 @@ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
55
64
  const carouselWrapperRef = ref<HTMLDivElement | null>(null);
56
65
  const carouselContainerRef = ref<HTMLDivElement | null>(null);
57
66
  const carouselItemsRef = useTemplateRef<HTMLDivElement[]>('carouselItems');
67
+ const controlsContainerRef = ref<HTMLDivElement | null>(null);
58
68
  const carouselInitComplete = ref(false);
59
69
 
60
70
  const currentIndex = ref(0);
@@ -63,7 +73,7 @@ const offset = ref(0);
63
73
  const transitionSpeedStr = props.transitionSpeed + 'ms';
64
74
  const itemTransform = computed(() => {
65
75
  return `translateX(calc(${offset.value} * (${itemWidth.value} + var(--_item-gap))))`;
66
- })
76
+ });
67
77
 
68
78
  const itemWidth = ref('0px');
69
79
 
@@ -74,7 +84,7 @@ const actionPrevious = () => {
74
84
 
75
85
  offset.value = Math.min(offset.value + 1);
76
86
  doAction();
77
- }
87
+ };
78
88
 
79
89
  const actionNext = () => {
80
90
  if (offset.value <= -1 * (itemCount.value - 1)) {
@@ -83,19 +93,18 @@ const actionNext = () => {
83
93
 
84
94
  offset.value = Math.min(offset.value - 1);
85
95
  doAction();
86
- }
96
+ };
87
97
 
88
98
  const doAction = () => {
89
99
  currentIndex.value = Math.abs(offset.value);
90
- }
100
+ };
91
101
 
92
102
  const jumpToFrame = (index: number) => {
93
-
94
103
  if (index >= 0 && index < itemCount.value) {
95
104
  offset.value = -index;
96
105
  doAction();
97
106
  }
98
- }
107
+ };
99
108
 
100
109
  const initialSetup = () => {
101
110
  if (carouselItemsRef?.value && carouselItemsRef.value.length > 0 && carouselItemsRef.value[0]) {
@@ -103,33 +112,34 @@ const initialSetup = () => {
103
112
  }
104
113
 
105
114
  carouselInitComplete.value = true;
106
- }
115
+ };
107
116
 
108
- const { direction } = useSwipe(
109
- carouselContainerRef,
110
- {
111
- passive: false,
112
- onSwipeEnd() {
113
- if (direction.value === 'left') {
114
- actionNext();
115
- } else if (direction.value === 'right') {
116
- actionPrevious();
117
- }
118
- },
119
- },
120
- );
121
-
122
- useEventListener(
123
- carouselContainerRef,
124
- 'keydown',
125
- (event: KeyboardEvent) => {
126
- if (event.key === 'ArrowLeft') {
127
- actionPrevious();
128
- } else if (event.key === 'ArrowRight') {
117
+ const { direction } = useSwipe(carouselContainerRef, {
118
+ passive: false,
119
+ onSwipeEnd() {
120
+ if (direction.value === 'left') {
129
121
  actionNext();
122
+ } else if (direction.value === 'right') {
123
+ actionPrevious();
130
124
  }
131
125
  },
132
- );
126
+ });
127
+
128
+ useEventListener(carouselContainerRef, 'keydown', (event: KeyboardEvent) => {
129
+ if (event.key === 'ArrowLeft') {
130
+ actionPrevious();
131
+ } else if (event.key === 'ArrowRight') {
132
+ actionNext();
133
+ }
134
+ });
135
+
136
+ useEventListener(controlsContainerRef, 'keydown', (event: KeyboardEvent) => {
137
+ if (event.key === 'ArrowLeft') {
138
+ actionPrevious();
139
+ } else if (event.key === 'ArrowRight') {
140
+ actionNext();
141
+ }
142
+ });
133
143
 
134
144
  useResizeObserver(carouselWrapperRef, async () => {
135
145
  initialSetup();
@@ -138,11 +148,9 @@ useResizeObserver(carouselWrapperRef, async () => {
138
148
  onMounted(() => {
139
149
  initialSetup();
140
150
  });
141
-
142
151
  </script>
143
152
 
144
153
  <style lang="css">
145
-
146
154
  .carousel-basic {
147
155
  --_item-gap: 10px;
148
156
 
@@ -150,6 +158,18 @@ onMounted(() => {
150
158
  grid-template-columns: 1fr;
151
159
  gap: 10px;
152
160
 
161
+ .sr-only {
162
+ position: absolute;
163
+ width: 1px;
164
+ height: 1px;
165
+ padding: 0;
166
+ margin: -1px;
167
+ overflow: hidden;
168
+ clip: rect(0, 0, 0, 0);
169
+ white-space: nowrap;
170
+ border: 0;
171
+ }
172
+
153
173
  .timeline-container {
154
174
  display: flex;
155
175
  gap: var(--_item-gap);
@@ -184,6 +204,10 @@ onMounted(() => {
184
204
  overflow-x: hidden;
185
205
  position: relative;
186
206
 
207
+ &.allow-overflow {
208
+ overflow-x: initial;
209
+ }
210
+
187
211
  .item {
188
212
  display: flex;
189
213
  flex: 0 0 100%;
@@ -199,7 +223,6 @@ onMounted(() => {
199
223
  justify-content: flex-end;
200
224
 
201
225
  .markers-container {
202
-
203
226
  .markers-list {
204
227
  display: flex;
205
228
  flex-direction: row;
@@ -209,7 +232,6 @@ onMounted(() => {
209
232
  padding: unset;
210
233
 
211
234
  .markers-item {
212
-
213
235
  .btn-marker {
214
236
  border: none;
215
237
  outline: none;
package/nuxt.config.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  export default defineNuxtConfig({
3
3
  devtools: { enabled: true },
4
4
  css: ['modern-normalize', './assets/styles/main.css'],
5
- modules: ['@nuxt/icon', '@nuxt/image', '@nuxt/eslint'],
5
+ modules: ['@nuxt/icon', '@nuxt/image'],
6
6
  app: {
7
7
  head: {
8
8
  htmlAttrs: {
@@ -34,7 +34,4 @@ export default defineNuxtConfig({
34
34
  typescript: {
35
35
  includeWorkspace: true,
36
36
  },
37
- eslint: {
38
- // Add any custom options here
39
- },
40
37
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "4.0.1",
4
+ "version": "4.0.2",
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,12 +27,12 @@
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.5.2",
31
30
  "@nuxt/eslint-config": "1.5.2",
32
31
  "@nuxt/icon": "1.15.0",
33
32
  "@nuxt/image": "1.10.0",
34
33
  "@oddbird/css-anchor-positioning": "0.6.1",
35
34
  "@vueuse/core": "13.5.0",
35
+ "eslint": "9.31.0",
36
36
  "happy-dom": "16.8.1",
37
37
  "nuxt": "3.17.6",
38
38
  "release-it": "18.1.2",