@xenterprises/nuxt-x-marketing 1.0.2 → 1.1.0

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 (64) hide show
  1. package/README.md +130 -11
  2. package/app/components/X/Mark/CodeBlock/index.vue +19 -7
  3. package/app/components/X/Mark/Divider/Glow.vue +25 -19
  4. package/app/components/X/Mark/Section/Stitch.vue +45 -31
  5. package/app/composables/{useParallax.ts → useParallax.js} +6 -7
  6. package/app/composables/{useScrollReveal.ts → useScrollReveal.js} +4 -4
  7. package/nuxt.config.ts +1 -11
  8. package/package.json +1 -1
  9. package/.claude/settings.local.json +0 -23
  10. package/.nuxtrc +0 -1
  11. package/.playground/app.config.ts +0 -74
  12. package/.playground/app.vue +0 -269
  13. package/.playground/components/AppFooter.vue +0 -103
  14. package/.playground/components/AppHeader.vue +0 -41
  15. package/.playground/components/CodeExample.vue +0 -70
  16. package/.playground/components/ComponentPlayground.vue +0 -117
  17. package/.playground/components/DocsHeader.vue +0 -19
  18. package/.playground/layouts/default.vue +0 -15
  19. package/.playground/layouts/docs-layout.vue +0 -161
  20. package/.playground/layouts/docs.vue +0 -11
  21. package/.playground/nuxt.config.ts +0 -5
  22. package/.playground/package-lock.json +0 -6
  23. package/.playground/pages/blog/author.vue +0 -145
  24. package/.playground/pages/blog/card.vue +0 -149
  25. package/.playground/pages/blog/cta.vue +0 -131
  26. package/.playground/pages/blog/detail.vue +0 -471
  27. package/.playground/pages/blog/list.vue +0 -261
  28. package/.playground/pages/blog/navigation.vue +0 -228
  29. package/.playground/pages/blog/sidebar.vue +0 -279
  30. package/.playground/pages/config.vue +0 -289
  31. package/.playground/pages/content/comparison.vue +0 -253
  32. package/.playground/pages/content/cta.vue +0 -245
  33. package/.playground/pages/content/features.vue +0 -217
  34. package/.playground/pages/content/newsletter-section.vue +0 -260
  35. package/.playground/pages/content/newsletter.vue +0 -200
  36. package/.playground/pages/content/pricing.vue +0 -335
  37. package/.playground/pages/content/testimonials.vue +0 -188
  38. package/.playground/pages/hero.vue +0 -257
  39. package/.playground/pages/index.vue +0 -381
  40. package/.playground/pages/layout/footer.vue +0 -210
  41. package/.playground/pages/layout/legal-footer.vue +0 -121
  42. package/.playground/pages/layout/navbar.vue +0 -285
  43. package/.playground/pages/layout/section.vue +0 -266
  44. package/.playground/pages/layout/x-legal.vue +0 -199
  45. package/.playground/pages/modals/feature-modal.vue +0 -320
  46. package/.playground/pages/modals/image-lightbox.vue +0 -277
  47. package/.playground/pages/modals/video-modal.vue +0 -222
  48. package/.playground/pages/notifications/announcement-bar.vue +0 -164
  49. package/.playground/pages/notifications/cookie-banner.vue +0 -210
  50. package/.playground/pages/notifications/cookie-toast.vue +0 -143
  51. package/.playground/pages/notifications/gdpr.vue +0 -276
  52. package/.playground/pages/notifications/social-proof-toast.vue +0 -515
  53. package/.playground/pages/ui/badge.vue +0 -161
  54. package/.playground/pages/ui/bg-pattern.vue +0 -177
  55. package/.playground/pages/ui/glass-card.vue +0 -179
  56. package/.playground/pages/ui/glow-divider.vue +0 -179
  57. package/.playground/pages/ui/promo-card.vue +0 -259
  58. package/.playground/pages/ui/section-stitch.vue +0 -411
  59. package/.playground/pages/utilities/back-to-top.vue +0 -153
  60. package/.playground/pages/utilities/popup-chat.vue +0 -224
  61. package/componentList.json +0 -2129
  62. package/screenshots/playground-home.png +0 -0
  63. package/tsconfig.json +0 -3
  64. /package/app/composables/{useXBlog.ts → useXBlog.js} +0 -0
@@ -1,320 +0,0 @@
1
- <template>
2
- <div class="min-h-screen">
3
- <div class="bg-white dark:bg-neutral-900 border-b border-neutral-200 dark:border-neutral-800 px-8 py-6">
4
- <h1 class="text-2xl font-bold text-neutral-900 dark:text-white">Feature Modal</h1>
5
- <p class="mt-2 text-neutral-600 dark:text-neutral-400">Full-screen scrollable modal for detailed feature showcases with Apple-style presentation.</p>
6
- </div>
7
-
8
- <div class="p-8 space-y-12">
9
- <!-- Demo Trigger -->
10
- <section>
11
- <h2 class="text-lg font-semibold mb-4">Feature Showcase Modal</h2>
12
- <p class="text-sm text-neutral-500 mb-4">Opens a full-screen scrollable presentation with hero, content blocks, and CTA.</p>
13
- <XMarkModalFeature
14
- :hero="hero"
15
- :blocks="blocks"
16
- :cta="cta"
17
- :button="{ label: 'Explore Feature', size: 'lg', icon: 'i-lucide-maximize-2' }"
18
- @cta-click="handleCtaClick"
19
- />
20
- </section>
21
-
22
- <!-- Button Object -->
23
- <section>
24
- <h2 class="text-lg font-semibold mb-4">Button Object</h2>
25
- <p class="text-sm text-neutral-500 mb-4">Configure the trigger button with a single object prop.</p>
26
- <div class="flex flex-wrap gap-4">
27
- <XMarkModalFeature
28
- :hero="hero"
29
- :blocks="blocks"
30
- :button="{ label: 'Learn More', color: 'primary' }"
31
- />
32
- <XMarkModalFeature
33
- :hero="hero"
34
- :blocks="blocks"
35
- :button="{ label: 'View Details', color: 'secondary', variant: 'outline' }"
36
- />
37
- <XMarkModalFeature
38
- :hero="hero"
39
- :blocks="blocks"
40
- :button="{ label: 'Explore', color: 'neutral', size: 'lg', icon: 'i-lucide-sparkles' }"
41
- />
42
- </div>
43
- </section>
44
-
45
- <!-- Custom Trigger -->
46
- <section>
47
- <h2 class="text-lg font-semibold mb-4">Custom Trigger (Slot)</h2>
48
- <p class="text-sm text-neutral-500 mb-4">Use the default slot for a completely custom trigger.</p>
49
- <XMarkModalFeature
50
- :hero="hero"
51
- :blocks="blocks"
52
- :cta="cta"
53
- >
54
- <UButton size="xl" label="Advanced Analytics" leading-icon="i-lucide-layers" trailing-icon="i-lucide-arrow-right" />
55
- </XMarkModalFeature>
56
- </section>
57
-
58
- <!-- Block Types -->
59
- <section>
60
- <h2 class="text-lg font-semibold mb-4">Available Block Types</h2>
61
- <div class="grid md:grid-cols-3 gap-6">
62
- <article class="p-6 rounded-lg bg-neutral-100 dark:bg-neutral-800">
63
- <h3 class="font-semibold mb-2">Image Block</h3>
64
- <p class="text-sm text-neutral-600 dark:text-neutral-400">Full-screen image section</p>
65
- <pre class="mt-4 text-xs bg-neutral-200 dark:bg-neutral-700 p-2 rounded overflow-x-auto"><code>{
66
- type: 'image',
67
- image: 'url',
68
- alt: 'description'
69
- }</code></pre>
70
- </article>
71
- <article class="p-6 rounded-lg bg-neutral-100 dark:bg-neutral-800">
72
- <h3 class="font-semibold mb-2">Text Block</h3>
73
- <p class="text-sm text-neutral-600 dark:text-neutral-400">Centered text content</p>
74
- <pre class="mt-4 text-xs bg-neutral-200 dark:bg-neutral-700 p-2 rounded overflow-x-auto"><code>{
75
- type: 'text',
76
- title: 'Heading',
77
- body: 'Content...',
78
- bg: 'bg-white'
79
- }</code></pre>
80
- </article>
81
- <article class="p-6 rounded-lg bg-neutral-100 dark:bg-neutral-800">
82
- <h3 class="font-semibold mb-2">Split Block</h3>
83
- <p class="text-sm text-neutral-600 dark:text-neutral-400">Image + text side by side</p>
84
- <pre class="mt-4 text-xs bg-neutral-200 dark:bg-neutral-700 p-2 rounded overflow-x-auto"><code>{
85
- type: 'split',
86
- title: 'Feature',
87
- body: 'Details...',
88
- image: 'url',
89
- imagePosition: 'left',
90
- features: [...]
91
- }</code></pre>
92
- </article>
93
- </div>
94
- </section>
95
-
96
- <!-- Props -->
97
- <section>
98
- <h2 class="text-lg font-semibold mb-4">Props</h2>
99
- <table class="w-full text-sm">
100
- <thead>
101
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
102
- <th class="text-left py-3 px-4">Prop</th>
103
- <th class="text-left py-3 px-4">Type</th>
104
- <th class="text-left py-3 px-4">Default</th>
105
- <th class="text-left py-3 px-4">Description</th>
106
- </tr>
107
- </thead>
108
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
109
- <tr><td class="py-3 px-4 font-mono text-xs">hero</td><td class="py-3 px-4">Object</td><td class="py-3 px-4">null</td><td class="py-3 px-4">Hero section { image, title, subtitle }</td></tr>
110
- <tr><td class="py-3 px-4 font-mono text-xs">blocks</td><td class="py-3 px-4">Array</td><td class="py-3 px-4">[]</td><td class="py-3 px-4">Array of content blocks</td></tr>
111
- <tr><td class="py-3 px-4 font-mono text-xs">cta</td><td class="py-3 px-4">Object</td><td class="py-3 px-4">null</td><td class="py-3 px-4">CTA section { title, subtitle, button, bg }</td></tr>
112
- <tr><td class="py-3 px-4 font-mono text-xs">button</td><td class="py-3 px-4">Object</td><td class="py-3 px-4">{}</td><td class="py-3 px-4">{ label, color, variant, size, icon }</td></tr>
113
- </tbody>
114
- </table>
115
- </section>
116
-
117
- <!-- Button Object Properties -->
118
- <section>
119
- <h2 class="text-lg font-semibold mb-4">Button Object Properties</h2>
120
- <table class="w-full text-sm">
121
- <thead>
122
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
123
- <th class="text-left py-3 px-4">Property</th>
124
- <th class="text-left py-3 px-4">Type</th>
125
- <th class="text-left py-3 px-4">Default</th>
126
- </tr>
127
- </thead>
128
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
129
- <tr><td class="py-3 px-4 font-mono text-xs">label</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'Learn More'</td></tr>
130
- <tr><td class="py-3 px-4 font-mono text-xs">color</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'primary'</td></tr>
131
- <tr><td class="py-3 px-4 font-mono text-xs">variant</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'solid'</td></tr>
132
- <tr><td class="py-3 px-4 font-mono text-xs">size</td><td class="py-3 px-4">String</td><td class="py-3 px-4">'md'</td></tr>
133
- <tr><td class="py-3 px-4 font-mono text-xs">icon</td><td class="py-3 px-4">String</td><td class="py-3 px-4">''</td></tr>
134
- </tbody>
135
- </table>
136
- </section>
137
-
138
- <!-- Hero Configuration -->
139
- <section>
140
- <h2 class="text-lg font-semibold mb-4">Hero Configuration</h2>
141
- <pre class="bg-neutral-100 dark:bg-neutral-800 p-4 rounded-lg text-sm overflow-x-auto"><code>hero: {
142
- image: 'https://example.com/hero.jpg',
143
- title: 'Feature Name',
144
- subtitle: 'Feature description'
145
- }</code></pre>
146
- </section>
147
-
148
- <!-- Blocks Configuration -->
149
- <section>
150
- <h2 class="text-lg font-semibold mb-4">Blocks Configuration</h2>
151
- <pre class="bg-neutral-100 dark:bg-neutral-800 p-4 rounded-lg text-sm overflow-x-auto"><code>blocks: [
152
- // Full-width image
153
- {
154
- type: 'image',
155
- image: 'https://example.com/showcase.jpg',
156
- alt: 'Feature showcase'
157
- },
158
-
159
- // Centered text section
160
- {
161
- type: 'text',
162
- title: 'Section Title',
163
- body: 'Detailed explanation of the feature...',
164
- bg: 'bg-neutral-50' // Optional background class
165
- },
166
-
167
- // Split layout with image
168
- {
169
- type: 'split',
170
- title: 'Feature Highlight',
171
- body: 'Description of this specific feature...',
172
- image: 'https://example.com/feature.jpg',
173
- imagePosition: 'left', // 'left' or 'right'
174
- features: [ // Optional bullet points
175
- 'Benefit one',
176
- 'Benefit two',
177
- 'Benefit three'
178
- ],
179
- bg: 'bg-white'
180
- }
181
- ]</code></pre>
182
- </section>
183
-
184
- <!-- CTA Configuration -->
185
- <section>
186
- <h2 class="text-lg font-semibold mb-4">CTA Configuration</h2>
187
- <pre class="bg-neutral-100 dark:bg-neutral-800 p-4 rounded-lg text-sm overflow-x-auto"><code>cta: {
188
- title: 'Ready to get started?',
189
- subtitle: 'Join thousands of satisfied customers',
190
- button: { label: 'Start Free Trial', color: 'primary' },
191
- bg: 'bg-neutral-950' // Optional background class
192
- }</code></pre>
193
- </section>
194
-
195
- <!-- Events -->
196
- <section>
197
- <h2 class="text-lg font-semibold mb-4">Events</h2>
198
- <table class="w-full text-sm">
199
- <thead>
200
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
201
- <th class="text-left py-3 px-4">Event</th>
202
- <th class="text-left py-3 px-4">Description</th>
203
- </tr>
204
- </thead>
205
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
206
- <tr><td class="py-3 px-4 font-mono text-xs">@open</td><td class="py-3 px-4">Emitted when modal opens</td></tr>
207
- <tr><td class="py-3 px-4 font-mono text-xs">@close</td><td class="py-3 px-4">Emitted when modal closes</td></tr>
208
- <tr><td class="py-3 px-4 font-mono text-xs">@cta-click</td><td class="py-3 px-4">Emitted when CTA button is clicked</td></tr>
209
- </tbody>
210
- </table>
211
- </section>
212
-
213
- <!-- Code Example -->
214
- <section>
215
- <h2 class="text-lg font-semibold mb-4">Code Example</h2>
216
- <CodeExample title="Feature Modal Usage" :code="codeExample" />
217
- </section>
218
- </div>
219
- </div>
220
- </template>
221
-
222
- <script setup>
223
- const codeExample = `<!-- With button trigger (object) -->
224
- <XMarkModalFeature
225
- :hero="{
226
- image: '/images/hero.jpg',
227
- title: 'Advanced Analytics',
228
- subtitle: 'Gain deep insights into your data'
229
- }"
230
- :blocks="[
231
- { type: 'text', title: 'Overview', body: 'Description...' },
232
- { type: 'image', image: '/showcase.jpg', alt: 'Feature showcase' },
233
- {
234
- type: 'split',
235
- title: 'Key Feature',
236
- body: 'Feature details...',
237
- image: '/feature.jpg',
238
- imagePosition: 'right',
239
- features: ['Benefit 1', 'Benefit 2', 'Benefit 3']
240
- }
241
- ]"
242
- :cta="{
243
- title: 'Ready to start?',
244
- subtitle: 'Free 14-day trial',
245
- button: { label: 'Start Free Trial', color: 'primary' }
246
- }"
247
- :button="{ label: 'Learn More', size: 'lg', icon: 'i-lucide-maximize-2' }"
248
- @cta-click="handleCtaClick"
249
- />
250
-
251
- <!-- Custom trigger (slot) -->
252
- <XMarkModalFeature :hero="hero" :blocks="blocks">
253
- <UButton size="lg" label="Explore Feature" leading-icon="i-lucide-layers" />
254
- </XMarkModalFeature>
255
-
256
- <!-- Minimal (no hero/CTA) -->
257
- <XMarkModalFeature
258
- :blocks="blocks"
259
- :button="{ label: 'View Feature' }"
260
- />`
261
-
262
- const hero = {
263
- image: 'https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1920&h=1080&fit=crop',
264
- title: 'Advanced Analytics',
265
- subtitle: 'Gain deep insights into your data with powerful visualization tools'
266
- }
267
-
268
- const blocks = [
269
- {
270
- type: 'text',
271
- title: 'Understand Your Data Like Never Before',
272
- body: 'Our analytics platform transforms raw data into actionable insights. With real-time dashboards and customizable reports, you can make data-driven decisions faster than ever before.',
273
- bg: 'bg-white dark:bg-neutral-950'
274
- },
275
- {
276
- type: 'image',
277
- image: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=1920&h=1080&fit=crop',
278
- alt: 'Analytics dashboard'
279
- },
280
- {
281
- type: 'split',
282
- title: 'Real-Time Monitoring',
283
- body: 'Track your key metrics as they happen. Our real-time monitoring system ensures you never miss an important trend or anomaly.',
284
- image: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&h=600&fit=crop',
285
- imagePosition: 'right',
286
- features: [
287
- 'Live data streaming',
288
- 'Customizable alerts',
289
- 'Trend detection',
290
- 'Anomaly identification'
291
- ],
292
- bg: 'bg-neutral-50 dark:bg-neutral-900'
293
- },
294
- {
295
- type: 'split',
296
- title: 'Powerful Reporting',
297
- body: 'Generate beautiful, shareable reports with just a few clicks. Export to PDF, Excel, or share via link with your team.',
298
- image: 'https://images.unsplash.com/photo-1551434678-e076c223a692?w=800&h=600&fit=crop',
299
- imagePosition: 'left',
300
- features: [
301
- 'Automated report generation',
302
- 'Custom branding options',
303
- 'Scheduled delivery',
304
- 'Interactive charts'
305
- ],
306
- bg: 'bg-white dark:bg-neutral-950'
307
- }
308
- ]
309
-
310
- const cta = {
311
- title: 'Ready to Transform Your Data?',
312
- subtitle: 'Start your free 14-day trial today. No credit card required.',
313
- button: { label: 'Start Free Trial', color: 'primary' },
314
- bg: 'bg-primary-600'
315
- }
316
-
317
- const handleCtaClick = () => {
318
- console.log('CTA clicked!')
319
- }
320
- </script>
@@ -1,277 +0,0 @@
1
- <template>
2
- <div class="min-h-screen">
3
- <div class="bg-white dark:bg-neutral-900 border-b border-neutral-200 dark:border-neutral-800 px-8 py-6">
4
- <h1 class="text-2xl font-bold text-neutral-900 dark:text-white">Image Lightbox</h1>
5
- <p class="mt-2 text-neutral-600 dark:text-neutral-400">Full-screen image viewer with gallery navigation.</p>
6
- </div>
7
-
8
- <div class="p-8 space-y-12">
9
- <!-- Single Image -->
10
- <section>
11
- <h2 class="text-lg font-semibold mb-4">Single Image</h2>
12
- <p class="text-sm text-neutral-500 mb-4">Click to open lightbox</p>
13
- <button
14
- class="rounded-xl overflow-hidden cursor-zoom-in"
15
- @click="openSingle"
16
- >
17
- <img
18
- :src="singleImage[0].src"
19
- :alt="singleImage[0].alt"
20
- class="w-80 h-60 object-cover hover:opacity-90 transition-opacity"
21
- />
22
- </button>
23
- <XMarkModalImage
24
- v-model="singleOpen"
25
- :images="singleImage"
26
- />
27
- </section>
28
-
29
- <!-- Gallery Grid -->
30
- <section>
31
- <h2 class="text-lg font-semibold mb-4">Gallery with Navigation</h2>
32
- <p class="text-sm text-neutral-500 mb-4">Click any image to open gallery. Use arrows or keyboard to navigate.</p>
33
- <div class="grid grid-cols-4 gap-4">
34
- <button
35
- v-for="(image, index) in galleryImages"
36
- :key="index"
37
- class="rounded-lg overflow-hidden aspect-square cursor-zoom-in"
38
- @click="openGallery(index)"
39
- >
40
- <img
41
- :src="image.src"
42
- :alt="image.alt"
43
- class="w-full h-full object-cover hover:opacity-90 transition-opacity"
44
- />
45
- </button>
46
- </div>
47
- <XMarkModalImage
48
- v-model="galleryOpen"
49
- :images="galleryImages"
50
- :start-index="galleryIndex"
51
- :has-counter="true"
52
- />
53
- </section>
54
-
55
- <!-- With Thumbnails -->
56
- <section>
57
- <h2 class="text-lg font-semibold mb-4">With Thumbnail Navigation</h2>
58
- <div class="grid grid-cols-6 gap-2">
59
- <button
60
- v-for="(image, index) in thumbnailImages"
61
- :key="index"
62
- class="rounded-lg overflow-hidden aspect-square cursor-zoom-in"
63
- @click="openThumbnails(index)"
64
- >
65
- <img
66
- :src="image.src"
67
- :alt="image.alt"
68
- class="w-full h-full object-cover hover:opacity-90 transition-opacity"
69
- />
70
- </button>
71
- </div>
72
- <XMarkModalImage
73
- v-model="thumbnailOpen"
74
- :images="thumbnailImages"
75
- :start-index="thumbnailIndex"
76
- :has-counter="true"
77
- :has-thumbnails="true"
78
- />
79
- </section>
80
-
81
- <!-- With Captions -->
82
- <section>
83
- <h2 class="text-lg font-semibold mb-4">With Captions</h2>
84
- <div class="flex gap-4">
85
- <button
86
- v-for="(image, index) in captionImages"
87
- :key="index"
88
- class="rounded-lg overflow-hidden w-48 h-32 cursor-zoom-in"
89
- @click="openCaptions(index)"
90
- >
91
- <img
92
- :src="image.src"
93
- :alt="image.alt"
94
- class="w-full h-full object-cover hover:opacity-90 transition-opacity"
95
- />
96
- </button>
97
- </div>
98
- <XMarkModalImage
99
- v-model="captionOpen"
100
- :images="captionImages"
101
- :start-index="captionIndex"
102
- />
103
- </section>
104
-
105
- <!-- Props -->
106
- <section>
107
- <h2 class="text-lg font-semibold mb-4">Props</h2>
108
- <div class="overflow-x-auto">
109
- <table class="w-full text-sm">
110
- <thead>
111
- <tr class="border-b border-neutral-200 dark:border-neutral-700">
112
- <th class="text-left py-3 px-4 font-medium">Prop</th>
113
- <th class="text-left py-3 px-4 font-medium">Type</th>
114
- <th class="text-left py-3 px-4 font-medium">Default</th>
115
- <th class="text-left py-3 px-4 font-medium">Description</th>
116
- </tr>
117
- </thead>
118
- <tbody class="divide-y divide-neutral-200 dark:divide-neutral-700">
119
- <tr>
120
- <td class="py-3 px-4 font-mono text-xs">v-model</td>
121
- <td class="py-3 px-4">Boolean</td>
122
- <td class="py-3 px-4">false</td>
123
- <td class="py-3 px-4 text-neutral-600 dark:text-neutral-400">Lightbox visibility state</td>
124
- </tr>
125
- <tr>
126
- <td class="py-3 px-4 font-mono text-xs">images</td>
127
- <td class="py-3 px-4">Array</td>
128
- <td class="py-3 px-4">[]</td>
129
- <td class="py-3 px-4 text-neutral-600 dark:text-neutral-400">Array of { src, alt, caption? }</td>
130
- </tr>
131
- <tr>
132
- <td class="py-3 px-4 font-mono text-xs">startIndex</td>
133
- <td class="py-3 px-4">Number</td>
134
- <td class="py-3 px-4">0</td>
135
- <td class="py-3 px-4 text-neutral-600 dark:text-neutral-400">Starting image index for gallery</td>
136
- </tr>
137
- <tr>
138
- <td class="py-3 px-4 font-mono text-xs">hasCounter</td>
139
- <td class="py-3 px-4">Boolean</td>
140
- <td class="py-3 px-4">true</td>
141
- <td class="py-3 px-4 text-neutral-600 dark:text-neutral-400">Show image counter (1/5)</td>
142
- </tr>
143
- <tr>
144
- <td class="py-3 px-4 font-mono text-xs">hasThumbnails</td>
145
- <td class="py-3 px-4">Boolean</td>
146
- <td class="py-3 px-4">false</td>
147
- <td class="py-3 px-4 text-neutral-600 dark:text-neutral-400">Show thumbnail navigation strip</td>
148
- </tr>
149
- </tbody>
150
- </table>
151
- </div>
152
- </section>
153
-
154
- <!-- Image Object -->
155
- <section>
156
- <h2 class="text-lg font-semibold mb-4">Image Object Structure</h2>
157
- <pre class="bg-neutral-100 dark:bg-neutral-800 p-4 rounded-lg text-sm overflow-x-auto"><code>{
158
- src: 'https://example.com/image.jpg', // Required
159
- alt: 'Image description', // Required
160
- caption: 'Optional caption text' // Optional
161
- }</code></pre>
162
- </section>
163
-
164
- <!-- Keyboard Navigation -->
165
- <section>
166
- <h2 class="text-lg font-semibold mb-4">Keyboard Navigation</h2>
167
- <div class="grid md:grid-cols-3 gap-4">
168
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800 text-center">
169
- <kbd class="px-2 py-1 bg-neutral-200 dark:bg-neutral-700 rounded text-sm">Arrow Left</kbd>
170
- <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400">Previous image</p>
171
- </div>
172
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800 text-center">
173
- <kbd class="px-2 py-1 bg-neutral-200 dark:bg-neutral-700 rounded text-sm">Arrow Right</kbd>
174
- <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400">Next image</p>
175
- </div>
176
- <div class="p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800 text-center">
177
- <kbd class="px-2 py-1 bg-neutral-200 dark:bg-neutral-700 rounded text-sm">Escape</kbd>
178
- <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-400">Close lightbox</p>
179
- </div>
180
- </div>
181
- </section>
182
-
183
- <!-- Code Example -->
184
- <section>
185
- <h2 class="text-lg font-semibold mb-4">Code Example</h2>
186
- <CodeExample title="Image Lightbox Usage" :code="codeExample" />
187
- </section>
188
- </div>
189
- </div>
190
- </template>
191
-
192
- <script setup>
193
- const codeExample = `<!-- Single image -->
194
- <button @click="lightboxOpen = true">
195
- <img :src="images[0].src" :alt="images[0].alt" />
196
- </button>
197
- <XMarkModalImage
198
- v-model="lightboxOpen"
199
- :images="images"
200
- />
201
-
202
- <!-- Gallery with thumbnails -->
203
- <div class="grid grid-cols-4 gap-4">
204
- <button
205
- v-for="(image, index) in images"
206
- :key="index"
207
- @click="openGallery(index)"
208
- >
209
- <img :src="image.src" :alt="image.alt" />
210
- </button>
211
- </div>
212
- <XMarkModalImage
213
- v-model="galleryOpen"
214
- :images="images"
215
- :start-index="startIndex"
216
- :has-counter="true"
217
- :has-thumbnails="true"
218
- />
219
-
220
- <!-- Image data structure -->
221
- const images = [
222
- { src: 'https://...', alt: 'Image 1', caption: 'Optional caption' },
223
- { src: 'https://...', alt: 'Image 2' }
224
- ]`
225
-
226
- const singleOpen = ref(false)
227
- const singleImage = [
228
- { src: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1200&h=800&fit=crop', alt: 'Mountain landscape' }
229
- ]
230
-
231
- const openSingle = () => {
232
- singleOpen.value = true
233
- }
234
-
235
- const galleryOpen = ref(false)
236
- const galleryIndex = ref(0)
237
- const galleryImages = [
238
- { src: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=1200&h=800&fit=crop', alt: 'Nature 1' },
239
- { src: 'https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=1200&h=800&fit=crop', alt: 'Nature 2' },
240
- { src: 'https://images.unsplash.com/photo-1433086966358-54859d0ed716?w=1200&h=800&fit=crop', alt: 'Nature 3' },
241
- { src: 'https://images.unsplash.com/photo-1501854140801-50d01698950b?w=1200&h=800&fit=crop', alt: 'Nature 4' }
242
- ]
243
-
244
- const openGallery = (index) => {
245
- galleryIndex.value = index
246
- galleryOpen.value = true
247
- }
248
-
249
- const thumbnailOpen = ref(false)
250
- const thumbnailIndex = ref(0)
251
- const thumbnailImages = [
252
- { src: 'https://images.unsplash.com/photo-1519681393784-d120267933ba?w=1200&h=800&fit=crop', alt: 'Mountain 1' },
253
- { src: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?w=1200&h=800&fit=crop', alt: 'Mountain 2' },
254
- { src: 'https://images.unsplash.com/photo-1486870591958-9b9d0d1dda99?w=1200&h=800&fit=crop', alt: 'Mountain 3' },
255
- { src: 'https://images.unsplash.com/photo-1454496522488-7a8e488e8606?w=1200&h=800&fit=crop', alt: 'Mountain 4' },
256
- { src: 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=1200&h=800&fit=crop', alt: 'Mountain 5' },
257
- { src: 'https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=1200&h=800&fit=crop', alt: 'Mountain 6' }
258
- ]
259
-
260
- const openThumbnails = (index) => {
261
- thumbnailIndex.value = index
262
- thumbnailOpen.value = true
263
- }
264
-
265
- const captionOpen = ref(false)
266
- const captionIndex = ref(0)
267
- const captionImages = [
268
- { src: 'https://images.unsplash.com/photo-1551524164-687a55dd1126?w=1200&h=800&fit=crop', alt: 'Architecture 1', caption: 'Modern Architecture in Downtown' },
269
- { src: 'https://images.unsplash.com/photo-1487958449943-2429e8be8625?w=1200&h=800&fit=crop', alt: 'Architecture 2', caption: 'Glass and Steel Office Building' },
270
- { src: 'https://images.unsplash.com/photo-1479839672679-a46483c0e7c8?w=1200&h=800&fit=crop', alt: 'Architecture 3', caption: 'Historic Church Exterior' }
271
- ]
272
-
273
- const openCaptions = (index) => {
274
- captionIndex.value = index
275
- captionOpen.value = true
276
- }
277
- </script>