@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,135 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types';
3
+
4
+ interface Props extends HTMLAttributes<'div'> {
5
+ /** Label shown in tooltip on hover */
6
+ label?: string;
7
+ /** Whether this item is currently active/running */
8
+ active?: boolean;
9
+ /** Custom class names */
10
+ class?: string;
11
+ }
12
+
13
+ const { label, active = false, class: className = "", ...rest } = Astro.props;
14
+ ---
15
+
16
+ <div class:list={["dock-item", { "is-active": active }, className]} {...rest}>
17
+ {label && <span class="dock-label">{label}</span>}
18
+ <slot />
19
+ </div>
20
+
21
+ <style>
22
+ .dock-item {
23
+ position: relative;
24
+ width: var(--item-size, 3.2rem);
25
+ height: var(--item-size, 3.2rem);
26
+ border-radius: 0.75rem;
27
+ background: transparent;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ cursor: pointer;
32
+ transform: scale(var(--dock-item-scale, 1))
33
+ translateY(var(--dock-item-y, 0px));
34
+ margin: 0 var(--dock-item-margin, 4px);
35
+ transition:
36
+ transform 0.2s ease-out,
37
+ margin 0.2s ease-out;
38
+ transform-origin: var(--dock-origin, bottom center);
39
+ will-change: transform, margin;
40
+ flex-shrink: 0;
41
+ overflow: visible;
42
+ transform-style: preserve-3d;
43
+ }
44
+
45
+ .dock-item :global(img) {
46
+ width: 100%;
47
+ height: 100%;
48
+ object-fit: contain;
49
+ filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
50
+ transition: filter 0.2s ease;
51
+ image-rendering: -webkit-optimize-contrast;
52
+ backface-visibility: hidden;
53
+ transform: translateZ(0);
54
+ }
55
+
56
+ .dock-item:hover :global(img),
57
+ .dock-item.is-active :global(img) {
58
+ filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.4));
59
+ }
60
+
61
+ /* Running indicator dot */
62
+ .dock-item.is-active::after {
63
+ content: "";
64
+ position: absolute;
65
+ bottom: -8px;
66
+ width: 4px;
67
+ height: 4px;
68
+ border-radius: 50%;
69
+ background: rgba(255, 255, 255, 0.6);
70
+ }
71
+
72
+ .dock-label {
73
+ position: absolute;
74
+ bottom: var(--tooltip-bottom, calc(100% + 0.75rem));
75
+ top: var(--tooltip-top, auto);
76
+ left: var(--tooltip-left, 50%);
77
+ right: var(--tooltip-right, auto);
78
+ transform: var(--tooltip-transform, translateX(-50%) translateY(4px))
79
+ scale(var(--dock-label-scale, 1));
80
+ transform-origin: inherit;
81
+ background: rgba(0, 0, 0, 0.85);
82
+ color: white;
83
+ padding: 0.4rem 0.9rem;
84
+ border-radius: 0.4rem;
85
+ font-size: 0.8rem;
86
+ font-weight: 500;
87
+ font-family:
88
+ system-ui,
89
+ -apple-system,
90
+ sans-serif;
91
+ border: 1px solid rgba(255, 255, 255, 0.15);
92
+ opacity: 0;
93
+ pointer-events: none;
94
+ transition: opacity 0.15s ease;
95
+ white-space: nowrap;
96
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
97
+ z-index: 100;
98
+ -webkit-font-smoothing: antialiased;
99
+ text-rendering: geometricPrecision;
100
+ backface-visibility: hidden;
101
+ -webkit-backface-visibility: hidden;
102
+ will-change: opacity, transform;
103
+ }
104
+
105
+ .dock-label::after {
106
+ content: "";
107
+ position: absolute;
108
+ top: var(--tooltip-arrow-top, 100%);
109
+ bottom: var(--tooltip-arrow-bottom, auto);
110
+ left: var(--tooltip-arrow-left, 50%);
111
+ right: var(--tooltip-arrow-right, auto);
112
+ transform: var(--tooltip-arrow-transform, translateX(-50%));
113
+ border: 5px solid transparent;
114
+ border-color: var(--tooltip-arrow-border-color, rgba(0, 0, 0, 0.85) transparent transparent transparent);
115
+ }
116
+
117
+ .dock-item:hover .dock-label {
118
+ opacity: 1;
119
+ transform: var(--tooltip-transform-hover, translateX(-50%) translateY(0)) scale(var(--dock-label-scale, 1));
120
+ }
121
+
122
+ @media (prefers-reduced-motion: reduce) {
123
+ .dock-item {
124
+ transition: none !important;
125
+ transform: none !important;
126
+ }
127
+ .dock-item :global(img) {
128
+ transition: none !important;
129
+ }
130
+ .dock-label {
131
+ transition: none !important;
132
+ transform: translateX(-50%) translateY(0) !important;
133
+ }
134
+ }
135
+ </style>
@@ -0,0 +1,264 @@
1
+ ---
2
+ export type DropdownItem = {
3
+ label: string;
4
+ icon?: string;
5
+ href?: string;
6
+ onClick?: string;
7
+ };
8
+
9
+ interface Props {
10
+ /** Button text label */
11
+ label: string;
12
+ /** Menu items array */
13
+ items: (string | DropdownItem)[];
14
+ /** Enable animations */
15
+ enhance?: boolean;
16
+ /** Open trigger type */
17
+ trigger?: 'click' | 'hover';
18
+ /** Hover close delay in ms */
19
+ hoverDelay?: number;
20
+ /** Callback when item selected - pass index */
21
+ onSelect?: (index: number) => void;
22
+ }
23
+
24
+ const {
25
+ label,
26
+ items = [],
27
+ enhance = false,
28
+ trigger = 'click',
29
+ hoverDelay = 120
30
+ } = Astro.props;
31
+ ---
32
+
33
+ <style>
34
+ /* ✅ CRITERION 1: Zero-JS baseline — content is present in HTML, trigger does nothing without JS */
35
+ .dropdown-root {
36
+ position: relative;
37
+ display: inline-block;
38
+ }
39
+
40
+ /* Trigger button reset */
41
+ .dropdown-trigger-wrap {
42
+ display: inline-block;
43
+ cursor: pointer;
44
+ }
45
+
46
+ /* ✅ CRITERION 1: Menu hidden by default (CSS-only fallback = menu not shown without JS) */
47
+ .menu-content {
48
+ display: none;
49
+ position: absolute;
50
+ z-index: 50;
51
+ min-width: 200px;
52
+ top: calc(100% + 6px);
53
+ left: 0;
54
+ background: #1a1a1a;
55
+ border: 1px solid #333;
56
+ border-radius: 10px;
57
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
58
+ overflow: hidden;
59
+ }
60
+
61
+ /* ✅ CRITERION 7: JS only toggles data-state — all animation is pure CSS */
62
+ [data-ready="true"] .menu-content {
63
+ display: block;
64
+ opacity: 0;
65
+ pointer-events: none;
66
+ transform: translateY(-6px) scale(0.97);
67
+ transform-origin: top left;
68
+ transition:
69
+ opacity 0.18s ease,
70
+ transform 0.18s ease;
71
+ }
72
+
73
+ [data-ready="true"][data-state="open"] .menu-content {
74
+ opacity: 1;
75
+ pointer-events: auto;
76
+ transform: translateY(0) scale(1);
77
+ }
78
+
79
+ /* ─── Hover mode: CSS-only zero-JS baseline ──────────────────────────────
80
+ When trigger=hover and no JS, show menu on native :hover so the
81
+ component still functions (no JS needed for the baseline experience). */
82
+ [data-trigger="hover"] .menu-content {
83
+ display: block;
84
+ opacity: 0;
85
+ pointer-events: none;
86
+ }
87
+
88
+ /* Bridge the gap to prevent hover loss when moving cursor to menu */
89
+ [data-trigger="hover"]::after {
90
+ content: '';
91
+ position: absolute;
92
+ top: 100%;
93
+ left: 0;
94
+ width: 100%;
95
+ height: 10px;
96
+ background: transparent;
97
+ }
98
+
99
+ /* CSS-only hover show (no JS) */
100
+ [data-trigger="hover"]:hover .menu-content {
101
+ opacity: 1;
102
+ pointer-events: auto;
103
+ }
104
+
105
+ /* When JS is ready, hand full control to data-state (override :hover) */
106
+ [data-trigger="hover"][data-ready="true"] .menu-content {
107
+ opacity: 0;
108
+ pointer-events: none;
109
+ transform: translateY(-6px) scale(0.97);
110
+ transform-origin: top left;
111
+ transition:
112
+ opacity 0.18s ease,
113
+ transform 0.18s ease;
114
+ }
115
+
116
+ [data-trigger="hover"][data-ready="true"][data-state="open"] .menu-content {
117
+ opacity: 1;
118
+ pointer-events: auto;
119
+ transform: translateY(0) scale(1);
120
+ }
121
+
122
+ /* Default trigger button styles */
123
+ .dropdown-trigger {
124
+ display: inline-block;
125
+ padding: 0.8rem 1rem;
126
+ background: #333;
127
+ color: white;
128
+ border: none;
129
+ border-radius: 0.5rem;
130
+ cursor: pointer;
131
+ font-family: system-ui, -apple-system, sans-serif;
132
+ font-size: 0.9rem;
133
+ transition: background 0.15s ease;
134
+ }
135
+
136
+ .dropdown-trigger:hover {
137
+ background: #444;
138
+ }
139
+
140
+ .dropdown-trigger-content {
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: space-between;
144
+ gap: 0.5rem;
145
+ }
146
+
147
+ .dropdown-chevron {
148
+ width: 1rem;
149
+ height: 1rem;
150
+ flex-shrink: 0;
151
+ transition: transform 0.2s ease;
152
+ }
153
+
154
+ [data-state="open"] .dropdown-chevron {
155
+ transform: rotate(180deg);
156
+ }
157
+
158
+ /* Menu item styles */
159
+ .menu-item {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 0.75rem;
163
+ padding: 0.5rem 1rem;
164
+ color: white;
165
+ text-decoration: none;
166
+ cursor: pointer;
167
+ border-radius: 0.25rem;
168
+ font-family: system-ui, -apple-system, sans-serif;
169
+ font-size: 0.9rem;
170
+ transition: background 0.15s ease;
171
+ }
172
+
173
+ .menu-item-icon {
174
+ display: flex;
175
+ align-items: center;
176
+ justify-content: center;
177
+ width: 1.15rem;
178
+ height: 1.15rem;
179
+ flex-shrink: 0;
180
+ }
181
+
182
+ .menu-item-icon :global(svg) {
183
+ width: 100%;
184
+ height: 100%;
185
+ }
186
+
187
+ .menu-item:hover {
188
+ background: #333;
189
+ }
190
+
191
+ .menu-item:first-child {
192
+ margin-top: 0.5rem;
193
+ }
194
+
195
+ .menu-item:last-child {
196
+ margin-bottom: 0.5rem;
197
+ }
198
+
199
+ /* ✅ CRITERION 6: Reduced motion — kill all transitions */
200
+ @media (prefers-reduced-motion: reduce) {
201
+ [data-ready="true"] .menu-content {
202
+ transition: none !important;
203
+ transform: none !important;
204
+ }
205
+ }
206
+ </style>
207
+
208
+ <div
209
+ class="dropdown-root"
210
+ data-dropdown
211
+ data-enhance={enhance ? "true" : "false"}
212
+ data-trigger={trigger}
213
+ data-hover-delay={hoverDelay}
214
+ >
215
+ <button
216
+ class="dropdown-trigger"
217
+ data-dropdown-trigger
218
+ type="button"
219
+ aria-haspopup="true"
220
+ aria-expanded="false"
221
+ >
222
+ <span class="dropdown-trigger-content">
223
+ {label}
224
+ <svg class="dropdown-chevron" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 9-7 7-7-7"/></svg>
225
+ </span>
226
+ </button>
227
+
228
+ <div
229
+ class="menu-content"
230
+ data-dropdown-content
231
+ role="menu"
232
+ aria-hidden="true"
233
+ >
234
+ {items.map((item, index) => {
235
+ const isObject = typeof item === 'object';
236
+ const itemLabel = isObject ? item.label : item;
237
+ const itemIcon = isObject ? item.icon : undefined;
238
+ const itemHref = isObject ? item.href : undefined;
239
+ const itemOnClick = isObject ? item.onClick : undefined;
240
+
241
+ const Tag = itemHref ? 'a' : 'div';
242
+
243
+ return (
244
+ <Tag class="menu-item" data-index={index} role="menuitem" href={itemHref} onclick={itemOnClick}>
245
+ {itemIcon && <span class="menu-item-icon" set:html={itemIcon} />}
246
+ <span>{itemLabel}</span>
247
+ </Tag>
248
+ );
249
+ })}
250
+ </div>
251
+ </div>
252
+
253
+ {enhance && (
254
+ <script>
255
+ import { enhanceDropdown } from "../../internal/dropdown";
256
+
257
+ // ✅ CRITERION 6: PRIMARY reduced motion guard lives here in .astro script block
258
+ if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
259
+ document.querySelectorAll<HTMLElement>('[data-dropdown][data-enhance="true"]').forEach((el) => {
260
+ enhanceDropdown(el);
261
+ });
262
+ }
263
+ </script>
264
+ )}