srcdev-nuxt-components 4.0.1 → 4.0.3

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,53 @@
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">
33
+ <Icon name="ic:outline-keyboard-arrow-left" class="arrows-icon" />
34
+ </button>
35
+ <button type="button" @click.prevent="actionNext()" class="btn-action" aria-label="Go to next item">
36
+ <Icon name="ic:outline-keyboard-arrow-right" class="arrows-icon" />
37
+ </button>
38
+ </div>
29
39
  </div>
30
- </div>
40
+ </LayoutRow>
31
41
  </section>
32
42
  </template>
33
43
 
34
44
  <script setup lang="ts">
35
- import type { ICarouselBasic } from "@/types/types.carousel-basic";
36
- import { useEventListener, useResizeObserver, useSwipe } from "@vueuse/core";
45
+ import { useEventListener, useResizeObserver, useSwipe } from '@vueuse/core';
37
46
 
38
47
  const props = defineProps({
39
48
  carouselDataIds: {
40
49
  type: Array as PropType<string[]>,
41
- default: () => []
50
+ default: () => [],
42
51
  },
43
52
  styleClassPassthrough: {
44
53
  type: Array as PropType<string[]>,
@@ -46,8 +55,12 @@ const props = defineProps({
46
55
  },
47
56
  transitionSpeed: {
48
57
  type: Number,
49
- default: 200
50
- }
58
+ default: 200,
59
+ },
60
+ allowCarouselOverflow: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
51
64
  });
52
65
 
53
66
  const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
@@ -55,6 +68,7 @@ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
55
68
  const carouselWrapperRef = ref<HTMLDivElement | null>(null);
56
69
  const carouselContainerRef = ref<HTMLDivElement | null>(null);
57
70
  const carouselItemsRef = useTemplateRef<HTMLDivElement[]>('carouselItems');
71
+ const controlsContainerRef = ref<HTMLDivElement | null>(null);
58
72
  const carouselInitComplete = ref(false);
59
73
 
60
74
  const currentIndex = ref(0);
@@ -63,7 +77,7 @@ const offset = ref(0);
63
77
  const transitionSpeedStr = props.transitionSpeed + 'ms';
64
78
  const itemTransform = computed(() => {
65
79
  return `translateX(calc(${offset.value} * (${itemWidth.value} + var(--_item-gap))))`;
66
- })
80
+ });
67
81
 
68
82
  const itemWidth = ref('0px');
69
83
 
@@ -74,7 +88,7 @@ const actionPrevious = () => {
74
88
 
75
89
  offset.value = Math.min(offset.value + 1);
76
90
  doAction();
77
- }
91
+ };
78
92
 
79
93
  const actionNext = () => {
80
94
  if (offset.value <= -1 * (itemCount.value - 1)) {
@@ -83,19 +97,18 @@ const actionNext = () => {
83
97
 
84
98
  offset.value = Math.min(offset.value - 1);
85
99
  doAction();
86
- }
100
+ };
87
101
 
88
102
  const doAction = () => {
89
103
  currentIndex.value = Math.abs(offset.value);
90
- }
104
+ };
91
105
 
92
106
  const jumpToFrame = (index: number) => {
93
-
94
107
  if (index >= 0 && index < itemCount.value) {
95
108
  offset.value = -index;
96
109
  doAction();
97
110
  }
98
- }
111
+ };
99
112
 
100
113
  const initialSetup = () => {
101
114
  if (carouselItemsRef?.value && carouselItemsRef.value.length > 0 && carouselItemsRef.value[0]) {
@@ -103,33 +116,34 @@ const initialSetup = () => {
103
116
  }
104
117
 
105
118
  carouselInitComplete.value = true;
106
- }
119
+ };
107
120
 
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') {
121
+ const { direction } = useSwipe(carouselContainerRef, {
122
+ passive: false,
123
+ onSwipeEnd() {
124
+ if (direction.value === 'left') {
129
125
  actionNext();
126
+ } else if (direction.value === 'right') {
127
+ actionPrevious();
130
128
  }
131
129
  },
132
- );
130
+ });
131
+
132
+ useEventListener(carouselContainerRef, 'keydown', (event: KeyboardEvent) => {
133
+ if (event.key === 'ArrowLeft') {
134
+ actionPrevious();
135
+ } else if (event.key === 'ArrowRight') {
136
+ actionNext();
137
+ }
138
+ });
139
+
140
+ useEventListener(controlsContainerRef, 'keydown', (event: KeyboardEvent) => {
141
+ if (event.key === 'ArrowLeft') {
142
+ actionPrevious();
143
+ } else if (event.key === 'ArrowRight') {
144
+ actionNext();
145
+ }
146
+ });
133
147
 
134
148
  useResizeObserver(carouselWrapperRef, async () => {
135
149
  initialSetup();
@@ -138,11 +152,9 @@ useResizeObserver(carouselWrapperRef, async () => {
138
152
  onMounted(() => {
139
153
  initialSetup();
140
154
  });
141
-
142
155
  </script>
143
156
 
144
157
  <style lang="css">
145
-
146
158
  .carousel-basic {
147
159
  --_item-gap: 10px;
148
160
 
@@ -150,6 +162,18 @@ onMounted(() => {
150
162
  grid-template-columns: 1fr;
151
163
  gap: 10px;
152
164
 
165
+ .sr-only {
166
+ position: absolute;
167
+ width: 1px;
168
+ height: 1px;
169
+ padding: 0;
170
+ margin: -1px;
171
+ overflow: hidden;
172
+ clip: rect(0, 0, 0, 0);
173
+ white-space: nowrap;
174
+ border: 0;
175
+ }
176
+
153
177
  .timeline-container {
154
178
  display: flex;
155
179
  gap: var(--_item-gap);
@@ -184,6 +208,10 @@ onMounted(() => {
184
208
  overflow-x: hidden;
185
209
  position: relative;
186
210
 
211
+ &.allow-overflow {
212
+ overflow-x: initial;
213
+ }
214
+
187
215
  .item {
188
216
  display: flex;
189
217
  flex: 0 0 100%;
@@ -199,7 +227,6 @@ onMounted(() => {
199
227
  justify-content: flex-end;
200
228
 
201
229
  .markers-container {
202
-
203
230
  .markers-list {
204
231
  display: flex;
205
232
  flex-direction: row;
@@ -209,7 +236,6 @@ onMounted(() => {
209
236
  padding: unset;
210
237
 
211
238
  .markers-item {
212
-
213
239
  .btn-marker {
214
240
  border: none;
215
241
  outline: none;
@@ -232,8 +258,17 @@ onMounted(() => {
232
258
  gap: 20px;
233
259
 
234
260
  .btn-action {
261
+ display: flex;
262
+ align-items: center;
263
+ justify-content: center;
264
+
235
265
  cursor: pointer;
236
266
  height: fit-content;
267
+
268
+ .arrows-icon {
269
+ width: 24px;
270
+ height: 24px;
271
+ }
237
272
  }
238
273
  }
239
274
  }
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.3",
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",