@anubis609/astroanimate-core 0.1.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.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +212 -0
  3. package/dist/components/AnimatedBorderButton/AnimatedBorderButton.astro +129 -0
  4. package/dist/components/AnimatedBorderButton/index.js +3 -0
  5. package/dist/components/AnimatedBorderButton/index.js.map +1 -0
  6. package/dist/components/AnimatedButton/AnimatedButton.astro +299 -0
  7. package/dist/components/AnimatedButton/index.js +3 -0
  8. package/dist/components/AnimatedButton/index.js.map +1 -0
  9. package/dist/components/AnimatedCard/AnimatedCard.astro +832 -0
  10. package/dist/components/AnimatedCard/index.js +3 -0
  11. package/dist/components/AnimatedCard/index.js.map +1 -0
  12. package/dist/components/AnimatedTabs/AnimatedTabs.astro +348 -0
  13. package/dist/components/AnimatedTabs/index.js +3 -0
  14. package/dist/components/AnimatedTabs/index.js.map +1 -0
  15. package/dist/components/ArrowCTAButton/ArrowCTAButton.astro +159 -0
  16. package/dist/components/ArticleCard/ArticleCard.astro +208 -0
  17. package/dist/components/CardStack/CardStack.astro +444 -0
  18. package/dist/components/CardStack/index.js +3 -0
  19. package/dist/components/CardStack/index.js.map +1 -0
  20. package/dist/components/CountUp/CountUp.astro +89 -0
  21. package/dist/components/CountUp/index.js +3 -0
  22. package/dist/components/CountUp/index.js.map +1 -0
  23. package/dist/components/Dock/Dock.astro +567 -0
  24. package/dist/components/Dock/DockItem.astro +135 -0
  25. package/dist/components/Dropdown/Dropdown.astro +264 -0
  26. package/dist/components/ExpandableCard/ExpandableCard.astro +402 -0
  27. package/dist/components/ExpandableCard/index.js +3 -0
  28. package/dist/components/ExpandableCard/index.js.map +1 -0
  29. package/dist/components/FadeInText/FadeInText.astro +314 -0
  30. package/dist/components/FadeInText/index.js +3 -0
  31. package/dist/components/FadeInText/index.js.map +1 -0
  32. package/dist/components/FillHoverButton/FillHoverButton.astro +125 -0
  33. package/dist/components/GitHubShineButton/GitHubShineButton.astro +208 -0
  34. package/dist/components/GlassCard/GlassCard.astro +245 -0
  35. package/dist/components/GlassCard/index.js +3 -0
  36. package/dist/components/GlassCard/index.js.map +1 -0
  37. package/dist/components/GridDotsBackground/GridDotsBackground.astro +144 -0
  38. package/dist/components/HighlightText/HighlightText.astro +106 -0
  39. package/dist/components/InfiniteMarquee/InfiniteMarquee.astro +339 -0
  40. package/dist/components/JobCard/JobCard.astro +230 -0
  41. package/dist/components/LiquidGlassCard/LiquidGlassCard.astro +569 -0
  42. package/dist/components/Loader/Loader.astro +156 -0
  43. package/dist/components/Loader/index.js +3 -0
  44. package/dist/components/Loader/index.js.map +1 -0
  45. package/dist/components/NewsletterPopupCard/NewsletterPopupCard.astro +331 -0
  46. package/dist/components/ProductReviewCard/ProductReviewCard.astro +188 -0
  47. package/dist/components/ProgressBar/ProgressBar.astro +137 -0
  48. package/dist/components/ProgressBar/index.js +3 -0
  49. package/dist/components/ProgressBar/index.js.map +1 -0
  50. package/dist/components/RevealImage/RevealImage.astro +160 -0
  51. package/dist/components/RevealImage/index.js +3 -0
  52. package/dist/components/RevealImage/index.js.map +1 -0
  53. package/dist/components/ScaleIn/ScaleIn.astro +231 -0
  54. package/dist/components/ScaleIn/index.js +3 -0
  55. package/dist/components/ScaleIn/index.js.map +1 -0
  56. package/dist/components/SlidingOverlayButton/SlidingOverlayButton.astro +126 -0
  57. package/dist/components/StaggerTextButton/StaggerTextButton.astro +132 -0
  58. package/dist/components/Tooltip/Tooltip.astro +255 -0
  59. package/dist/components/Tooltip/index.js +3 -0
  60. package/dist/components/Tooltip/index.js.map +1 -0
  61. package/dist/components/TypewriterText/TypewriterText.astro +380 -0
  62. package/dist/components/TypewriterText/index.js +3 -0
  63. package/dist/components/TypewriterText/index.js.map +1 -0
  64. package/dist/components/index.js +33 -0
  65. package/dist/components/index.js.map +1 -0
  66. package/dist/index.js +31 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/internal/countup.js +90 -0
  69. package/dist/internal/countup.js.map +1 -0
  70. package/dist/internal/dropdown.js +166 -0
  71. package/dist/internal/dropdown.js.map +1 -0
  72. package/dist/internal/fadein.js +116 -0
  73. package/dist/internal/fadein.js.map +1 -0
  74. package/dist/internal/guards.js +12 -0
  75. package/dist/internal/guards.js.map +1 -0
  76. package/dist/internal/tabs.js +140 -0
  77. package/dist/internal/tabs.js.map +1 -0
  78. package/package.json +229 -0
@@ -0,0 +1,339 @@
1
+ ---
2
+ /**
3
+ * InfiniteScroll - A premium continuous scrolling component.
4
+ * Supports horizontal and vertical directions with glassmorphism and smooth motion.
5
+ */
6
+ interface Testimonial {
7
+ name: string;
8
+ handle: string;
9
+ img?: string;
10
+ quote: string;
11
+ }
12
+
13
+ interface Props {
14
+ direction?: "left" | "right" | "up" | "down";
15
+ speed?: string;
16
+ pauseOnHover?: boolean;
17
+ gap?: string;
18
+ fade?: boolean;
19
+ mainClassName?: string;
20
+ cardMode?: boolean;
21
+ cardWidth?: string;
22
+ testimonials?: Testimonial[];
23
+ cardBg?: string;
24
+ cardBorderColor?: string;
25
+ cardRadius?: string;
26
+ cardPadding?: string;
27
+ textColor?: string;
28
+ nameColor?: string;
29
+ handleColor?: string;
30
+ }
31
+
32
+ const {
33
+ direction = "left",
34
+ speed = "30s",
35
+ pauseOnHover = true,
36
+ gap = "2rem",
37
+ fade = true,
38
+ mainClassName = "",
39
+ cardMode = false,
40
+ cardWidth = "320px",
41
+ testimonials = [],
42
+ cardBg = "white",
43
+ cardBorderColor = "#e5e5e5",
44
+ cardRadius = "16px",
45
+ cardPadding = "1.5rem",
46
+ textColor = "#333",
47
+ nameColor = "#111",
48
+ handleColor = "#666",
49
+ } = Astro.props;
50
+
51
+ // Render the slot content once so we can duplicate it multiple times
52
+ let slotContent = '';
53
+ if (!cardMode && Astro.slots.has('default')) {
54
+ slotContent = await Astro.slots.render('default');
55
+ }
56
+
57
+ // Generate 6 copies to ensure it always fills the screen, even if the content is short
58
+ const parts = Array.from({ length: 6 });
59
+ ---
60
+
61
+ <div
62
+ class:list={[
63
+ "marquee-container",
64
+ `marquee-${direction}`,
65
+ { "pause-hover": pauseOnHover },
66
+ { "fade-mask": fade },
67
+ mainClassName,
68
+ ]}
69
+ style={`
70
+ --speed: ${speed};
71
+ --gap: ${gap};
72
+ --card-width: ${cardWidth};
73
+ --card-bg: ${cardBg};
74
+ --card-border-color: ${cardBorderColor};
75
+ --card-radius: ${cardRadius};
76
+ --card-padding: ${cardPadding};
77
+ --text-color: ${textColor};
78
+ --name-color: ${nameColor};
79
+ --handle-color: ${handleColor};
80
+ `}
81
+ >
82
+ <div class="marquee-track">
83
+ {
84
+ parts.map((_, i) => (
85
+ <div class="marquee-content" data-marquee-part={i + 1} aria-hidden={i > 0 ? "true" : undefined}>
86
+ {
87
+ cardMode && testimonials.length > 0 ? (
88
+ testimonials.map((t) => (
89
+ <div class="marquee-card">
90
+ <div class="marquee-card-header">
91
+ <div class="marquee-card-avatar">
92
+ {t.img ? (
93
+ <img src={t.img} alt={t.name} />
94
+ ) : null}
95
+ </div>
96
+ <div class="marquee-card-info">
97
+ <p class="marquee-card-name">{t.name}</p>
98
+ <p class="marquee-card-handle">
99
+ {t.handle.startsWith("@")
100
+ ? t.handle
101
+ : "@" + t.handle}
102
+ </p>
103
+ </div>
104
+ </div>
105
+ <p class="marquee-card-content">{t.quote}</p>
106
+ </div>
107
+ ))
108
+ ) : (
109
+ <Fragment set:html={slotContent} />
110
+ )
111
+ }
112
+ </div>
113
+ ))
114
+ }
115
+ </div>
116
+ </div>
117
+
118
+ <style>
119
+ .marquee-container {
120
+ position: relative;
121
+ display: flex;
122
+ overflow: hidden;
123
+ user-select: none;
124
+ width: 100%;
125
+ background: transparent;
126
+ }
127
+
128
+ /* Horizontal layouts */
129
+ .marquee-left,
130
+ .marquee-right {
131
+ flex-direction: row;
132
+ }
133
+
134
+ /* Vertical layouts */
135
+ .marquee-up,
136
+ .marquee-down {
137
+ flex-direction: column;
138
+ height: 400px; /* Constrain height so it clips properly and doesn't reveal empty space */
139
+ max-height: 100vh;
140
+ width: fit-content;
141
+ }
142
+
143
+ .marquee-track {
144
+ display: flex;
145
+ flex-shrink: 0;
146
+ gap: var(--gap);
147
+ width: max-content;
148
+ }
149
+
150
+ .marquee-up .marquee-track,
151
+ .marquee-down .marquee-track {
152
+ flex-direction: column;
153
+ width: max-content; /* Changed from 100% so track only spans the width of the cards */
154
+ height: max-content;
155
+ }
156
+
157
+ .marquee-content {
158
+ flex-shrink: 0;
159
+ display: flex;
160
+ gap: var(--gap);
161
+ padding: 10px 0; /* Only top/bottom padding to not affect horizontal scroll width */
162
+ }
163
+
164
+ .marquee-up .marquee-content,
165
+ .marquee-down .marquee-content {
166
+ flex-direction: column;
167
+ min-width: auto;
168
+ padding: 0 10px; /* Only left/right padding to not affect vertical scroll height */
169
+ }
170
+
171
+ /* Horizontal Animations applied to individual content blocks */
172
+ .marquee-left .marquee-content {
173
+ animation: scroll-left var(--speed) linear infinite;
174
+ }
175
+
176
+ .marquee-right .marquee-content {
177
+ animation: scroll-right var(--speed) linear infinite;
178
+ }
179
+
180
+ /* Vertical Animations applied to individual content blocks */
181
+ .marquee-up .marquee-content {
182
+ animation: scroll-up var(--speed) linear infinite;
183
+ }
184
+
185
+ .marquee-down .marquee-content {
186
+ animation: scroll-down var(--speed) linear infinite;
187
+ }
188
+
189
+ /* Only pause when hovering the actual track (items), not the empty space in the container */
190
+ .pause-hover .marquee-track:hover .marquee-content {
191
+ animation-play-state: paused;
192
+ }
193
+
194
+ @keyframes scroll-left {
195
+ to {
196
+ transform: translateX(calc(-100% - var(--gap)));
197
+ }
198
+ }
199
+
200
+ @keyframes scroll-right {
201
+ from {
202
+ transform: translateX(calc(-100% - var(--gap)));
203
+ }
204
+ to {
205
+ transform: translateX(0);
206
+ }
207
+ }
208
+
209
+ @keyframes scroll-up {
210
+ to {
211
+ transform: translateY(calc(-100% - var(--gap)));
212
+ }
213
+ }
214
+
215
+ @keyframes scroll-down {
216
+ from {
217
+ transform: translateY(calc(-100% - var(--gap)));
218
+ }
219
+ to {
220
+ transform: translateY(0);
221
+ }
222
+ }
223
+
224
+ /* Edge Fading */
225
+ .fade-mask.marquee-left,
226
+ .fade-mask.marquee-right {
227
+ mask-image: linear-gradient(
228
+ to right,
229
+ transparent,
230
+ black 10%,
231
+ black 90%,
232
+ transparent
233
+ );
234
+ }
235
+
236
+ .fade-mask.marquee-up,
237
+ .fade-mask.marquee-down {
238
+ mask-image: linear-gradient(
239
+ to bottom,
240
+ transparent,
241
+ black 10%,
242
+ black 90%,
243
+ transparent
244
+ );
245
+ }
246
+
247
+ /* Premium item styles (can be overridden by slots) */
248
+ :global(.marquee-item) {
249
+ background: rgba(255, 255, 255, 0.03);
250
+ border: 1px solid rgba(255, 255, 255, 0.08);
251
+ border-radius: 12px;
252
+ padding: 1rem 2rem;
253
+ backdrop-filter: blur(10px);
254
+ transition: all 0.3s ease;
255
+ display: flex;
256
+ align-items: center;
257
+ justify-content: center;
258
+ white-space: nowrap;
259
+ color: rgba(255, 255, 255, 0.8);
260
+ }
261
+
262
+ :global(.marquee-item:hover) {
263
+ background: rgba(255, 255, 255, 0.1);
264
+ border-color: rgba(255, 255, 255, 0.2);
265
+ color: #fff;
266
+ transform: translateY(-2px);
267
+ box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.5);
268
+ }
269
+
270
+ /* Card Styles */
271
+ .marquee-card {
272
+ flex-shrink: 0;
273
+ width: var(--card-width);
274
+ background: var(--card-bg);
275
+ border: 1px solid var(--card-border-color);
276
+ border-radius: var(--card-radius);
277
+ padding: var(--card-padding);
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: 0.75rem;
281
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
282
+ }
283
+
284
+ .marquee-card-header {
285
+ display: flex;
286
+ align-items: center;
287
+ gap: 0.75rem;
288
+ }
289
+
290
+ .marquee-card-avatar {
291
+ width: 40px;
292
+ height: 40px;
293
+ border-radius: 50%;
294
+ background: #e5e5e5;
295
+ display: flex;
296
+ align-items: center;
297
+ justify-content: center;
298
+ flex-shrink: 0;
299
+ overflow: hidden;
300
+ }
301
+
302
+ .marquee-card-avatar img {
303
+ width: 100%;
304
+ height: 100%;
305
+ object-fit: cover;
306
+ }
307
+
308
+ .marquee-card-info {
309
+ display: flex;
310
+ flex-direction: column;
311
+ }
312
+
313
+ .marquee-card-name {
314
+ font-weight: 600;
315
+ font-size: 0.95rem;
316
+ color: var(--name-color);
317
+ margin: 0;
318
+ }
319
+
320
+ .marquee-card-handle {
321
+ font-size: 0.85rem;
322
+ color: var(--handle-color);
323
+ margin: 0;
324
+ }
325
+
326
+ .marquee-card-content {
327
+ font-size: 0.9rem;
328
+ line-height: 1.5;
329
+ color: var(--text-color);
330
+ margin: 0;
331
+ }
332
+
333
+ @media (prefers-reduced-motion: reduce) {
334
+ .marquee-track, .marquee-content {
335
+ animation: none !important;
336
+ transform: none !important;
337
+ }
338
+ }
339
+ </style>
@@ -0,0 +1,230 @@
1
+ ---
2
+ interface Props {
3
+ title: string;
4
+ rate: string;
5
+
6
+ company?: string;
7
+ buttonLabel?: string;
8
+
9
+ /* NEW */
10
+ companyLogo?: string;
11
+
12
+ as?: "button" | "a";
13
+ href?: string;
14
+
15
+ class?: string;
16
+ }
17
+
18
+ const {
19
+ title,
20
+ rate,
21
+
22
+ company = "Company",
23
+ buttonLabel = "View",
24
+
25
+ /* NEW */
26
+ companyLogo,
27
+
28
+ as = "button",
29
+ href,
30
+ class: className = "",
31
+ } = Astro.props;
32
+ ---
33
+
34
+ <style>
35
+ /* ✅ CRITERION 7: CSS-FIRST */
36
+
37
+ [data-job-card] {
38
+ width: min(320px, 100%);
39
+ padding: 0.5rem;
40
+
41
+ border: 1px solid #e5e5e5;
42
+ border-radius: 1rem;
43
+
44
+ background: #fefefe;
45
+ color: #141417;
46
+
47
+ font-family:
48
+ Inter,
49
+ ui-sans-serif,
50
+ system-ui,
51
+ -apple-system,
52
+ BlinkMacSystemFont,
53
+ "Segoe UI",
54
+ sans-serif;
55
+
56
+ -webkit-font-smoothing: antialiased;
57
+ -moz-osx-font-smoothing: grayscale;
58
+ }
59
+
60
+ .hero {
61
+ padding: 1.5rem;
62
+ border-radius: 0.75rem 0.75rem 0 0;
63
+
64
+ background: #fef4e2;
65
+ font-size: 0.875rem;
66
+ }
67
+
68
+ .hero-header {
69
+ display: flex;
70
+ justify-content: space-between;
71
+ align-items: center;
72
+ gap: 1rem;
73
+
74
+ font-weight: 700;
75
+ }
76
+
77
+ .title {
78
+ margin: 2rem 0;
79
+ padding-right: 2rem;
80
+
81
+ font-size: 2rem;
82
+ font-weight: 600;
83
+ line-height: 1.1;
84
+ letter-spacing: -0.04em;
85
+ }
86
+
87
+ .footer {
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: 1rem;
91
+
92
+ padding: 0.75rem;
93
+
94
+ font-size: 0.875rem;
95
+ font-weight: 700;
96
+ }
97
+
98
+ @media (min-width: 340px) {
99
+ .footer {
100
+ flex-direction: row;
101
+ align-items: center;
102
+ justify-content: space-between;
103
+ }
104
+ }
105
+
106
+ .summary {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 0.75rem;
110
+ }
111
+
112
+ .company {
113
+ line-height: 1.2;
114
+ }
115
+
116
+ .btn {
117
+ width: 100%;
118
+ padding: 0.75rem 1.35rem;
119
+
120
+ border: none;
121
+ border-radius: 999px;
122
+
123
+ background: #141417;
124
+ color: white;
125
+
126
+ font-size: 1rem;
127
+ font-weight: 500;
128
+
129
+ cursor: pointer;
130
+ text-align: center;
131
+ text-decoration: none;
132
+ text-transform: lowercase;
133
+
134
+ transition:
135
+ opacity 200ms ease,
136
+ transform 200ms ease;
137
+ }
138
+
139
+ .btn:hover {
140
+ opacity: 0.92;
141
+ }
142
+
143
+ .btn:active {
144
+ transform: scale(0.98);
145
+ }
146
+
147
+ @media (min-width: 340px) {
148
+ .btn {
149
+ width: max-content;
150
+ }
151
+ }
152
+
153
+ .icon {
154
+ flex-shrink: 0;
155
+ display: inline-flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ }
159
+
160
+ /* Accessibility */
161
+ .btn:focus-visible {
162
+ outline: 2px solid black;
163
+ outline-offset: 4px;
164
+ }
165
+
166
+ @media (prefers-reduced-motion: reduce) {
167
+ .btn {
168
+ transition: none !important;
169
+ }
170
+ .btn:active {
171
+ transform: none !important;
172
+ }
173
+ }
174
+ </style>
175
+
176
+ <article
177
+ data-job-card
178
+ class={className}
179
+ >
180
+ <section class="hero">
181
+ <header class="hero-header">
182
+ <span>{rate}</span>
183
+ </header>
184
+
185
+ <p class="title">{title}</p>
186
+ </section>
187
+
188
+ <footer class="footer">
189
+ <div class="summary">
190
+ <div
191
+ class="icon"
192
+ aria-hidden="true"
193
+ >
194
+ {companyLogo && (
195
+ companyLogo.trim().startsWith('<svg') ? (
196
+ <Fragment set:html={companyLogo} />
197
+ ) : (
198
+ <img
199
+ src={companyLogo}
200
+ alt={`${company} logo`}
201
+ width="32"
202
+ height="32"
203
+ style="object-fit: contain; border-radius: 4px;"
204
+ />
205
+ )
206
+ )}
207
+ </div>
208
+
209
+ <div class="company">
210
+ <p>{company}</p>
211
+ </div>
212
+ </div>
213
+
214
+ {as === "a" ? (
215
+ <a
216
+ href={href}
217
+ class="btn"
218
+ >
219
+ {buttonLabel}
220
+ </a>
221
+ ) : (
222
+ <button
223
+ type="button"
224
+ class="btn"
225
+ >
226
+ {buttonLabel}
227
+ </button>
228
+ )}
229
+ </footer>
230
+ </article>