@aspect-ops/exon-ui 0.2.2 → 0.3.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 (35) hide show
  1. package/dist/components/CTASection/CTASection.svelte +298 -0
  2. package/dist/components/CTASection/CTASection.svelte.d.ts +15 -0
  3. package/dist/components/CTASection/index.d.ts +2 -0
  4. package/dist/components/CTASection/index.js +1 -0
  5. package/dist/components/GlobalHeader/GlobalHeader.svelte +692 -0
  6. package/dist/components/GlobalHeader/GlobalHeader.svelte.d.ts +3 -0
  7. package/dist/components/GlobalHeader/index.d.ts +2 -0
  8. package/dist/components/GlobalHeader/index.js +1 -0
  9. package/dist/components/Hero/Hero.svelte +306 -0
  10. package/dist/components/Hero/Hero.svelte.d.ts +18 -0
  11. package/dist/components/Hero/index.d.ts +2 -0
  12. package/dist/components/Hero/index.js +1 -0
  13. package/dist/components/LogoCloud/LogoCloud.svelte +333 -0
  14. package/dist/components/LogoCloud/LogoCloud.svelte.d.ts +20 -0
  15. package/dist/components/LogoCloud/index.d.ts +2 -0
  16. package/dist/components/LogoCloud/index.js +1 -0
  17. package/dist/components/ServiceCard/ServiceCard.svelte +359 -0
  18. package/dist/components/ServiceCard/ServiceCard.svelte.d.ts +16 -0
  19. package/dist/components/ServiceCard/index.d.ts +1 -0
  20. package/dist/components/ServiceCard/index.js +1 -0
  21. package/dist/components/SplitSection/SplitSection.svelte +194 -0
  22. package/dist/components/SplitSection/SplitSection.svelte.d.ts +15 -0
  23. package/dist/components/SplitSection/index.d.ts +1 -0
  24. package/dist/components/SplitSection/index.js +1 -0
  25. package/dist/components/TestimonialCard/TestimonialCard.svelte +290 -0
  26. package/dist/components/TestimonialCard/TestimonialCard.svelte.d.ts +14 -0
  27. package/dist/components/TestimonialCard/index.d.ts +1 -0
  28. package/dist/components/TestimonialCard/index.js +1 -0
  29. package/dist/components/Timeline/Timeline.svelte +444 -0
  30. package/dist/components/Timeline/Timeline.svelte.d.ts +19 -0
  31. package/dist/components/Timeline/index.d.ts +2 -0
  32. package/dist/components/Timeline/index.js +1 -0
  33. package/dist/index.d.ts +16 -0
  34. package/dist/index.js +9 -0
  35. package/package.json +1 -1
@@ -0,0 +1,306 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ export interface HeroProps {
5
+ variant?: 'default' | 'centered' | 'split' | 'video';
6
+ backgroundImage?: string;
7
+ backgroundVideo?: string;
8
+ overlay?: boolean | string;
9
+ overlayOpacity?: number;
10
+ height?: 'auto' | 'screen' | 'half' | string;
11
+ align?: 'left' | 'center' | 'right';
12
+ class?: string;
13
+ children: Snippet;
14
+ actions?: Snippet;
15
+ badge?: Snippet;
16
+ media?: Snippet;
17
+ }
18
+
19
+ let {
20
+ variant = 'default',
21
+ backgroundImage,
22
+ backgroundVideo,
23
+ overlay = false,
24
+ overlayOpacity = 0.6,
25
+ height = 'screen',
26
+ align = 'left',
27
+ class: className = '',
28
+ children,
29
+ actions,
30
+ badge,
31
+ media
32
+ }: HeroProps = $props();
33
+
34
+ const heightValue = $derived(() => {
35
+ switch (height) {
36
+ case 'screen':
37
+ return '100vh';
38
+ case 'half':
39
+ return '50vh';
40
+ case 'auto':
41
+ return 'auto';
42
+ default:
43
+ return height;
44
+ }
45
+ });
46
+
47
+ const overlayColor = $derived(() => {
48
+ if (overlay === true)
49
+ return 'rgba(0, 0, 0, var(--hero-overlay-opacity, ' + overlayOpacity + '))';
50
+ if (typeof overlay === 'string') return overlay;
51
+ return 'transparent';
52
+ });
53
+ </script>
54
+
55
+ <section
56
+ class="hero hero--{variant} hero--align-{align} {className}"
57
+ role="banner"
58
+ style:--hero-height={heightValue()}
59
+ style:--hero-overlay-color={overlayColor()}
60
+ style:--hero-overlay-opacity={overlayOpacity}
61
+ >
62
+ {#if backgroundImage && variant !== 'video'}
63
+ <div class="hero__background" aria-hidden="true">
64
+ <img src={backgroundImage} alt="" loading="lazy" />
65
+ </div>
66
+ {/if}
67
+
68
+ {#if variant === 'video' && backgroundVideo}
69
+ <div class="hero__background hero__background--video" aria-hidden="true">
70
+ <video autoplay muted loop playsinline poster={backgroundImage}>
71
+ <source src={backgroundVideo} type="video/mp4" />
72
+ </video>
73
+ </div>
74
+ {/if}
75
+
76
+ {#if overlay}
77
+ <div class="hero__overlay" aria-hidden="true"></div>
78
+ {/if}
79
+
80
+ <div class="hero__content">
81
+ {#if badge}
82
+ <div class="hero__badge">
83
+ {@render badge()}
84
+ </div>
85
+ {/if}
86
+
87
+ <div class="hero__main">
88
+ {@render children()}
89
+ </div>
90
+
91
+ {#if actions}
92
+ <div class="hero__actions">
93
+ {@render actions()}
94
+ </div>
95
+ {/if}
96
+ </div>
97
+
98
+ {#if variant === 'split' && media}
99
+ <div class="hero__media">
100
+ {@render media()}
101
+ </div>
102
+ {/if}
103
+ </section>
104
+
105
+ <style>
106
+ .hero {
107
+ position: relative;
108
+ display: flex;
109
+ min-height: var(--hero-min-height, var(--hero-height, 100vh));
110
+ padding: var(
111
+ --hero-padding,
112
+ max(env(safe-area-inset-top), 3rem) max(env(safe-area-inset-right), 1.5rem)
113
+ max(env(safe-area-inset-bottom), 3rem) max(env(safe-area-inset-left), 1.5rem)
114
+ );
115
+ overflow: hidden;
116
+ animation: hero-fade-in 0.6s ease-out;
117
+ }
118
+
119
+ @media (prefers-reduced-motion: reduce) {
120
+ .hero {
121
+ animation: none;
122
+ }
123
+ }
124
+
125
+ @keyframes hero-fade-in {
126
+ from {
127
+ opacity: 0;
128
+ transform: translateY(1rem);
129
+ }
130
+ to {
131
+ opacity: 1;
132
+ transform: translateY(0);
133
+ }
134
+ }
135
+
136
+ /* Background */
137
+ .hero__background {
138
+ position: absolute;
139
+ top: 0;
140
+ left: 0;
141
+ width: 100%;
142
+ height: 100%;
143
+ z-index: 0;
144
+ }
145
+
146
+ .hero__background img,
147
+ .hero__background video {
148
+ width: 100%;
149
+ height: 100%;
150
+ object-fit: cover;
151
+ }
152
+
153
+ .hero__background--video video {
154
+ pointer-events: none;
155
+ }
156
+
157
+ /* Overlay */
158
+ .hero__overlay {
159
+ position: absolute;
160
+ top: 0;
161
+ left: 0;
162
+ width: 100%;
163
+ height: 100%;
164
+ background: var(--hero-overlay-color);
165
+ z-index: 1;
166
+ }
167
+
168
+ /* Content */
169
+ .hero__content {
170
+ position: relative;
171
+ z-index: 2;
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 1.5rem;
175
+ width: 100%;
176
+ max-width: var(--hero-content-max-width, 75rem);
177
+ margin: 0 auto;
178
+ color: var(--hero-text-color, inherit);
179
+ }
180
+
181
+ .hero__badge {
182
+ display: inline-flex;
183
+ }
184
+
185
+ .hero__main {
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 1rem;
189
+ }
190
+
191
+ .hero__actions {
192
+ display: flex;
193
+ flex-wrap: wrap;
194
+ gap: 1rem;
195
+ margin-top: 0.5rem;
196
+ }
197
+
198
+ /* Variants */
199
+ .hero--default {
200
+ align-items: center;
201
+ }
202
+
203
+ .hero--centered {
204
+ align-items: center;
205
+ text-align: center;
206
+ }
207
+
208
+ .hero--centered .hero__content {
209
+ align-items: center;
210
+ }
211
+
212
+ .hero--centered .hero__badge {
213
+ align-self: center;
214
+ }
215
+
216
+ .hero--centered .hero__actions {
217
+ justify-content: center;
218
+ }
219
+
220
+ .hero--split {
221
+ display: grid;
222
+ grid-template-columns: 1fr;
223
+ gap: 2rem;
224
+ align-items: center;
225
+ }
226
+
227
+ .hero--split .hero__content {
228
+ max-width: none;
229
+ }
230
+
231
+ .hero__media {
232
+ position: relative;
233
+ z-index: 2;
234
+ width: 100%;
235
+ }
236
+
237
+ .hero__media :global(img),
238
+ .hero__media :global(video) {
239
+ width: 100%;
240
+ height: auto;
241
+ border-radius: 0.5rem;
242
+ }
243
+
244
+ .hero--video {
245
+ align-items: center;
246
+ }
247
+
248
+ /* Alignment */
249
+ .hero--align-left .hero__content {
250
+ align-items: flex-start;
251
+ text-align: left;
252
+ }
253
+
254
+ .hero--align-center .hero__content {
255
+ align-items: center;
256
+ text-align: center;
257
+ }
258
+
259
+ .hero--align-right .hero__content {
260
+ align-items: flex-end;
261
+ text-align: right;
262
+ }
263
+
264
+ /* Responsive */
265
+ @media (min-width: 48rem) {
266
+ .hero {
267
+ padding: var(
268
+ --hero-padding,
269
+ max(env(safe-area-inset-top), 4rem) max(env(safe-area-inset-right), 2rem)
270
+ max(env(safe-area-inset-bottom), 4rem) max(env(safe-area-inset-left), 2rem)
271
+ );
272
+ }
273
+
274
+ .hero--split {
275
+ grid-template-columns: 1fr 1fr;
276
+ gap: 3rem;
277
+ }
278
+
279
+ .hero__content {
280
+ gap: 2rem;
281
+ }
282
+
283
+ .hero__main {
284
+ gap: 1.5rem;
285
+ }
286
+
287
+ .hero__actions {
288
+ gap: 1.5rem;
289
+ margin-top: 1rem;
290
+ }
291
+ }
292
+
293
+ @media (min-width: 64rem) {
294
+ .hero {
295
+ padding: var(
296
+ --hero-padding,
297
+ max(env(safe-area-inset-top), 5rem) max(env(safe-area-inset-right), 3rem)
298
+ max(env(safe-area-inset-bottom), 5rem) max(env(safe-area-inset-left), 3rem)
299
+ );
300
+ }
301
+
302
+ .hero--split {
303
+ gap: 4rem;
304
+ }
305
+ }
306
+ </style>
@@ -0,0 +1,18 @@
1
+ import type { Snippet } from 'svelte';
2
+ export interface HeroProps {
3
+ variant?: 'default' | 'centered' | 'split' | 'video';
4
+ backgroundImage?: string;
5
+ backgroundVideo?: string;
6
+ overlay?: boolean | string;
7
+ overlayOpacity?: number;
8
+ height?: 'auto' | 'screen' | 'half' | string;
9
+ align?: 'left' | 'center' | 'right';
10
+ class?: string;
11
+ children: Snippet;
12
+ actions?: Snippet;
13
+ badge?: Snippet;
14
+ media?: Snippet;
15
+ }
16
+ declare const Hero: import("svelte").Component<HeroProps, {}, "">;
17
+ type Hero = ReturnType<typeof Hero>;
18
+ export default Hero;
@@ -0,0 +1,2 @@
1
+ export { default as Hero } from './Hero.svelte';
2
+ export type { HeroProps } from './Hero.svelte';
@@ -0,0 +1 @@
1
+ export { default as Hero } from './Hero.svelte';
@@ -0,0 +1,333 @@
1
+ <script lang="ts">
2
+ export interface LogoItem {
3
+ src: string;
4
+ alt: string;
5
+ href?: string;
6
+ }
7
+
8
+ export interface LogoCloudProps {
9
+ logos: LogoItem[];
10
+ columns?: 2 | 3 | 4 | 5 | 6;
11
+ size?: 'sm' | 'md' | 'lg';
12
+ variant?: 'grid' | 'scroll' | 'marquee';
13
+ grayscale?: boolean;
14
+ hoverEffect?: 'scale' | 'lift' | 'glow' | 'color' | 'none';
15
+ gap?: 'sm' | 'md' | 'lg' | 'xl';
16
+ title?: string;
17
+ subtitle?: string;
18
+ class?: string;
19
+ }
20
+
21
+ let {
22
+ logos,
23
+ columns = 4,
24
+ size = 'md',
25
+ variant = 'grid',
26
+ grayscale = false,
27
+ hoverEffect = 'scale',
28
+ gap = 'md',
29
+ title,
30
+ subtitle,
31
+ class: className = ''
32
+ }: LogoCloudProps = $props();
33
+
34
+ const sizeMap = {
35
+ sm: '2rem',
36
+ md: '3rem',
37
+ lg: '4rem'
38
+ };
39
+
40
+ const gapMap = {
41
+ sm: '1rem',
42
+ md: '2rem',
43
+ lg: '3rem',
44
+ xl: '4rem'
45
+ };
46
+
47
+ // For marquee variant, duplicate logos for seamless infinite scroll
48
+ const displayLogos = $derived(variant === 'marquee' ? [...logos, ...logos] : logos);
49
+ </script>
50
+
51
+ <div class="logo-cloud-wrapper {className}">
52
+ {#if title || subtitle}
53
+ <div class="logo-cloud-header">
54
+ {#if title}
55
+ <h2 class="logo-cloud-title">{title}</h2>
56
+ {/if}
57
+ {#if subtitle}
58
+ <p class="logo-cloud-subtitle">{subtitle}</p>
59
+ {/if}
60
+ </div>
61
+ {/if}
62
+
63
+ <div
64
+ class="logo-cloud logo-cloud--{variant} logo-cloud--{size} logo-cloud--gap-{gap} logo-cloud--hover-{hoverEffect}"
65
+ class:logo-cloud--grayscale={grayscale}
66
+ style="--logo-cloud-height: {sizeMap[size]}; --logo-cloud-gap: {gapMap[
67
+ gap
68
+ ]}; --logo-cloud-columns: {columns};"
69
+ aria-label={title || 'Partner logos'}
70
+ role="region"
71
+ >
72
+ <div class="logo-cloud-container">
73
+ {#each displayLogos as logo, index}
74
+ <div class="logo-cloud-item" aria-hidden={variant === 'marquee' && index >= logos.length}>
75
+ {#if logo.href}
76
+ <a href={logo.href} class="logo-cloud-link" target="_blank" rel="noopener noreferrer">
77
+ <img
78
+ src={logo.src}
79
+ alt={logo.alt}
80
+ class="logo-cloud-image"
81
+ loading="lazy"
82
+ decoding="async"
83
+ />
84
+ </a>
85
+ {:else}
86
+ <img
87
+ src={logo.src}
88
+ alt={logo.alt}
89
+ class="logo-cloud-image"
90
+ loading="lazy"
91
+ decoding="async"
92
+ />
93
+ {/if}
94
+ </div>
95
+ {/each}
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <style>
101
+ .logo-cloud-wrapper {
102
+ width: 100%;
103
+ }
104
+
105
+ .logo-cloud-header {
106
+ text-align: center;
107
+ margin-bottom: 3rem;
108
+ }
109
+
110
+ .logo-cloud-title {
111
+ font-size: 2rem;
112
+ font-weight: 700;
113
+ margin: 0 0 0.5rem 0;
114
+ color: var(--logo-cloud-title-color, var(--text-primary, #1a1a1a));
115
+ }
116
+
117
+ .logo-cloud-subtitle {
118
+ font-size: 1rem;
119
+ margin: 0;
120
+ color: var(--logo-cloud-subtitle-color, var(--text-secondary, #666));
121
+ }
122
+
123
+ .logo-cloud {
124
+ width: 100%;
125
+ --logo-cloud-gap: 2rem;
126
+ --logo-cloud-height: 3rem;
127
+ --logo-cloud-columns: 4;
128
+ --logo-cloud-grayscale-opacity: 0.6;
129
+ --logo-cloud-transition: all 0.3s ease;
130
+ }
131
+
132
+ /* Grid variant */
133
+ .logo-cloud--grid .logo-cloud-container {
134
+ display: grid;
135
+ grid-template-columns: repeat(2, 1fr);
136
+ gap: var(--logo-cloud-gap);
137
+ align-items: center;
138
+ justify-items: center;
139
+ }
140
+
141
+ @media (min-width: 768px) {
142
+ .logo-cloud--grid .logo-cloud-container {
143
+ grid-template-columns: repeat(var(--logo-cloud-columns), 1fr);
144
+ }
145
+ }
146
+
147
+ /* Scroll variant */
148
+ .logo-cloud--scroll {
149
+ overflow-x: auto;
150
+ -webkit-overflow-scrolling: touch;
151
+ scrollbar-width: thin;
152
+ scrollbar-color: var(--scrollbar-thumb, #ccc) var(--scrollbar-track, #f0f0f0);
153
+ }
154
+
155
+ .logo-cloud--scroll .logo-cloud-container {
156
+ display: flex;
157
+ gap: var(--logo-cloud-gap);
158
+ padding-bottom: 1rem;
159
+ min-width: min-content;
160
+ }
161
+
162
+ .logo-cloud--scroll::-webkit-scrollbar {
163
+ height: 0.5rem;
164
+ }
165
+
166
+ .logo-cloud--scroll::-webkit-scrollbar-track {
167
+ background: var(--scrollbar-track, #f0f0f0);
168
+ border-radius: 0.25rem;
169
+ }
170
+
171
+ .logo-cloud--scroll::-webkit-scrollbar-thumb {
172
+ background: var(--scrollbar-thumb, #ccc);
173
+ border-radius: 0.25rem;
174
+ }
175
+
176
+ .logo-cloud--scroll::-webkit-scrollbar-thumb:hover {
177
+ background: var(--scrollbar-thumb-hover, #999);
178
+ }
179
+
180
+ /* Marquee variant */
181
+ .logo-cloud--marquee {
182
+ overflow: hidden;
183
+ position: relative;
184
+ }
185
+
186
+ .logo-cloud--marquee .logo-cloud-container {
187
+ display: flex;
188
+ gap: var(--logo-cloud-gap);
189
+ animation: marquee 30s linear infinite;
190
+ width: fit-content;
191
+ }
192
+
193
+ @keyframes marquee {
194
+ 0% {
195
+ transform: translateX(0);
196
+ }
197
+ 100% {
198
+ transform: translateX(-50%);
199
+ }
200
+ }
201
+
202
+ .logo-cloud--marquee:hover .logo-cloud-container,
203
+ .logo-cloud--marquee:focus-within .logo-cloud-container {
204
+ animation-play-state: paused;
205
+ }
206
+
207
+ @media (prefers-reduced-motion: reduce) {
208
+ .logo-cloud--marquee .logo-cloud-container {
209
+ animation: none;
210
+ }
211
+ }
212
+
213
+ /* Logo items */
214
+ .logo-cloud-item {
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ transition: var(--logo-cloud-transition);
219
+ flex-shrink: 0;
220
+ }
221
+
222
+ .logo-cloud--scroll .logo-cloud-item,
223
+ .logo-cloud--marquee .logo-cloud-item {
224
+ min-width: calc(var(--logo-cloud-height) * 2);
225
+ }
226
+
227
+ .logo-cloud-link {
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ text-decoration: none;
232
+ width: 100%;
233
+ height: 100%;
234
+ transition: var(--logo-cloud-transition);
235
+ }
236
+
237
+ .logo-cloud-link:focus {
238
+ outline: 2px solid var(--focus-ring-color, #0066ff);
239
+ outline-offset: 0.25rem;
240
+ border-radius: 0.25rem;
241
+ }
242
+
243
+ .logo-cloud-image {
244
+ height: var(--logo-cloud-height);
245
+ width: auto;
246
+ max-width: 100%;
247
+ object-fit: contain;
248
+ transition: var(--logo-cloud-transition);
249
+ }
250
+
251
+ /* Grayscale mode */
252
+ .logo-cloud--grayscale .logo-cloud-image {
253
+ filter: grayscale(100%);
254
+ opacity: var(--logo-cloud-grayscale-opacity);
255
+ }
256
+
257
+ .logo-cloud--grayscale .logo-cloud-item:hover .logo-cloud-image,
258
+ .logo-cloud--grayscale .logo-cloud-link:hover .logo-cloud-image,
259
+ .logo-cloud--grayscale .logo-cloud-link:focus .logo-cloud-image {
260
+ filter: grayscale(0%);
261
+ opacity: 1;
262
+ }
263
+
264
+ /* Hover effects */
265
+ /* Scale effect */
266
+ .logo-cloud--hover-scale .logo-cloud-item:hover .logo-cloud-image,
267
+ .logo-cloud--hover-scale .logo-cloud-link:hover .logo-cloud-image,
268
+ .logo-cloud--hover-scale .logo-cloud-link:focus .logo-cloud-image {
269
+ transform: scale(1.1);
270
+ }
271
+
272
+ /* Lift effect */
273
+ .logo-cloud--hover-lift .logo-cloud-item:hover,
274
+ .logo-cloud--hover-lift .logo-cloud-link:hover,
275
+ .logo-cloud--hover-lift .logo-cloud-link:focus {
276
+ transform: translateY(-0.5rem);
277
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
278
+ }
279
+
280
+ /* Glow effect */
281
+ .logo-cloud--hover-glow .logo-cloud-item:hover .logo-cloud-image,
282
+ .logo-cloud--hover-glow .logo-cloud-link:hover .logo-cloud-image,
283
+ .logo-cloud--hover-glow .logo-cloud-link:focus .logo-cloud-image {
284
+ filter: drop-shadow(0 0 1rem rgba(0, 102, 255, 0.3));
285
+ }
286
+
287
+ /* Color effect (similar to grayscale but forces it) */
288
+ .logo-cloud--hover-color .logo-cloud-image {
289
+ filter: grayscale(100%);
290
+ opacity: var(--logo-cloud-grayscale-opacity);
291
+ }
292
+
293
+ .logo-cloud--hover-color .logo-cloud-item:hover .logo-cloud-image,
294
+ .logo-cloud--hover-color .logo-cloud-link:hover .logo-cloud-image,
295
+ .logo-cloud--hover-color .logo-cloud-link:focus .logo-cloud-image {
296
+ filter: grayscale(0%);
297
+ opacity: 1;
298
+ }
299
+
300
+ /* None effect - no additional styles needed */
301
+ .logo-cloud--hover-none .logo-cloud-item:hover,
302
+ .logo-cloud--hover-none .logo-cloud-link:hover {
303
+ transform: none;
304
+ box-shadow: none;
305
+ }
306
+
307
+ /* Dark mode support */
308
+ @media (prefers-color-scheme: dark) {
309
+ .logo-cloud-title {
310
+ color: var(--logo-cloud-title-color, var(--text-primary, #ffffff));
311
+ }
312
+
313
+ .logo-cloud-subtitle {
314
+ color: var(--logo-cloud-subtitle-color, var(--text-secondary, #a0a0a0));
315
+ }
316
+
317
+ .logo-cloud--scroll {
318
+ scrollbar-color: var(--scrollbar-thumb, #555) var(--scrollbar-track, #2a2a2a);
319
+ }
320
+
321
+ .logo-cloud--scroll::-webkit-scrollbar-track {
322
+ background: var(--scrollbar-track, #2a2a2a);
323
+ }
324
+
325
+ .logo-cloud--scroll::-webkit-scrollbar-thumb {
326
+ background: var(--scrollbar-thumb, #555);
327
+ }
328
+
329
+ .logo-cloud--scroll::-webkit-scrollbar-thumb:hover {
330
+ background: var(--scrollbar-thumb-hover, #777);
331
+ }
332
+ }
333
+ </style>
@@ -0,0 +1,20 @@
1
+ export interface LogoItem {
2
+ src: string;
3
+ alt: string;
4
+ href?: string;
5
+ }
6
+ export interface LogoCloudProps {
7
+ logos: LogoItem[];
8
+ columns?: 2 | 3 | 4 | 5 | 6;
9
+ size?: 'sm' | 'md' | 'lg';
10
+ variant?: 'grid' | 'scroll' | 'marquee';
11
+ grayscale?: boolean;
12
+ hoverEffect?: 'scale' | 'lift' | 'glow' | 'color' | 'none';
13
+ gap?: 'sm' | 'md' | 'lg' | 'xl';
14
+ title?: string;
15
+ subtitle?: string;
16
+ class?: string;
17
+ }
18
+ declare const LogoCloud: import("svelte").Component<LogoCloudProps, {}, "">;
19
+ type LogoCloud = ReturnType<typeof LogoCloud>;
20
+ export default LogoCloud;
@@ -0,0 +1,2 @@
1
+ export { default as LogoCloud } from './LogoCloud.svelte';
2
+ export type { LogoItem, LogoCloudProps } from './LogoCloud.svelte';
@@ -0,0 +1 @@
1
+ export { default as LogoCloud } from './LogoCloud.svelte';