@sc4rfurryx/proteusjs 1.1.1 → 2.0.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 (60) hide show
  1. package/README.md +684 -899
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/modules/a11y-audit.d.ts +1 -1
  4. package/dist/modules/a11y-audit.esm.js +3 -3
  5. package/dist/modules/a11y-primitives.d.ts +2 -2
  6. package/dist/modules/a11y-primitives.esm.js +2 -2
  7. package/dist/modules/a11y-primitives.esm.js.map +1 -1
  8. package/dist/modules/anchor.d.ts +1 -1
  9. package/dist/modules/anchor.esm.js +2 -2
  10. package/dist/modules/container.d.ts +1 -1
  11. package/dist/modules/container.esm.js +34 -34
  12. package/dist/modules/container.esm.js.map +1 -1
  13. package/dist/modules/perf.d.ts +1 -1
  14. package/dist/modules/perf.esm.js +2 -2
  15. package/dist/modules/popover.d.ts +1 -1
  16. package/dist/modules/popover.esm.js +2 -2
  17. package/dist/modules/scroll.d.ts +1 -1
  18. package/dist/modules/scroll.esm.js +14 -14
  19. package/dist/modules/scroll.esm.js.map +1 -1
  20. package/dist/modules/transitions.d.ts +1 -1
  21. package/dist/modules/transitions.esm.js +12 -12
  22. package/dist/modules/transitions.esm.js.map +1 -1
  23. package/dist/modules/typography.d.ts +1 -1
  24. package/dist/modules/typography.esm.js +2 -2
  25. package/dist/proteus.cjs.js +68 -68
  26. package/dist/proteus.cjs.js.map +1 -1
  27. package/dist/proteus.d.ts +13 -13
  28. package/dist/proteus.esm.js +68 -68
  29. package/dist/proteus.esm.js.map +1 -1
  30. package/dist/proteus.esm.min.js +2 -2
  31. package/dist/proteus.esm.min.js.map +1 -1
  32. package/dist/proteus.js +68 -68
  33. package/dist/proteus.js.map +1 -1
  34. package/dist/proteus.min.js +2 -2
  35. package/dist/proteus.min.js.map +1 -1
  36. package/package.json +40 -8
  37. package/src/adapters/react.ts +607 -264
  38. package/src/adapters/svelte.ts +321 -321
  39. package/src/adapters/vue.ts +268 -268
  40. package/src/core/ProteusJS.ts +6 -6
  41. package/src/index.ts +2 -2
  42. package/src/modules/a11y-audit/index.ts +84 -84
  43. package/src/modules/a11y-primitives/index.ts +151 -151
  44. package/src/modules/anchor/index.ts +259 -259
  45. package/src/modules/container/index.ts +230 -230
  46. package/src/modules/perf/index.ts +291 -291
  47. package/src/modules/popover/index.ts +238 -238
  48. package/src/modules/scroll/index.ts +251 -251
  49. package/src/modules/transitions/index.ts +145 -145
  50. package/src/modules/typography/index.ts +239 -239
  51. package/src/utils/version.ts +1 -1
  52. package/dist/adapters/react.d.ts +0 -140
  53. package/dist/adapters/react.esm.js +0 -849
  54. package/dist/adapters/react.esm.js.map +0 -1
  55. package/dist/adapters/svelte.d.ts +0 -181
  56. package/dist/adapters/svelte.esm.js +0 -909
  57. package/dist/adapters/svelte.esm.js.map +0 -1
  58. package/dist/adapters/vue.d.ts +0 -205
  59. package/dist/adapters/vue.esm.js +0 -873
  60. package/dist/adapters/vue.esm.js.map +0 -1
@@ -1,251 +1,251 @@
1
- /**
2
- * @sc4rfurryx/proteusjs/scroll
3
- * Scroll-driven animations with CSS Scroll-Linked Animations
4
- *
5
- * @version 1.1.0
6
- * @author sc4rfurry
7
- * @license MIT
8
- */
9
-
10
- export interface ScrollAnimateOptions {
11
- keyframes: Keyframe[];
12
- range?: [string, string];
13
- timeline?: {
14
- axis?: 'block' | 'inline';
15
- start?: string;
16
- end?: string;
17
- };
18
- fallback?: 'io' | false;
19
- }
20
-
21
- /**
22
- * Zero-boilerplate setup for CSS Scroll-Linked Animations with fallbacks
23
- */
24
- export function scrollAnimate(
25
- target: Element | string,
26
- opts: ScrollAnimateOptions
27
- ): void {
28
- const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
29
- if (!targetEl) {
30
- throw new Error('Target element not found');
31
- }
32
-
33
- const {
34
- keyframes,
35
- range = ['0%', '100%'],
36
- timeline = {},
37
- fallback = 'io'
38
- } = opts;
39
-
40
- const {
41
- axis = 'block',
42
- start = '0%',
43
- end = '100%'
44
- } = timeline;
45
-
46
- // Check for CSS Scroll-Linked Animations support
47
- const hasScrollTimeline = 'CSS' in window && CSS.supports('animation-timeline', 'scroll()');
48
-
49
- // Check for reduced motion preference
50
- const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
51
-
52
- if (prefersReducedMotion) {
53
- // Respect user preference - either disable or reduce animation
54
- if (fallback === false) return;
55
-
56
- // Apply only the end state for reduced motion
57
- const endKeyframe = keyframes[keyframes.length - 1];
58
- Object.assign((targetEl as HTMLElement).style, endKeyframe);
59
- return;
60
- }
61
-
62
- if (hasScrollTimeline) {
63
- // Use native CSS Scroll-Linked Animations
64
- const timelineName = `scroll-timeline-${Math.random().toString(36).substr(2, 9)}`;
65
-
66
- // Create scroll timeline
67
- const style = document.createElement('style');
68
- style.textContent = `
69
- @scroll-timeline ${timelineName} {
70
- source: nearest;
71
- orientation: ${axis};
72
- scroll-offsets: ${start}, ${end};
73
- }
74
-
75
- .scroll-animate-${timelineName} {
76
- animation-timeline: ${timelineName};
77
- animation-duration: 1ms; /* Required but ignored */
78
- animation-fill-mode: both;
79
- }
80
- `;
81
- document.head.appendChild(style);
82
-
83
- // Apply animation class
84
- targetEl.classList.add(`scroll-animate-${timelineName}`);
85
-
86
- // Create Web Animations API animation
87
- const animation = targetEl.animate(keyframes, {
88
- duration: 1, // Required but ignored with scroll timeline
89
- fill: 'both'
90
- });
91
-
92
- // Set scroll timeline (when supported)
93
- if ('timeline' in animation) {
94
- (animation as any).timeline = new (window as any).ScrollTimeline({
95
- source: document.scrollingElement,
96
- orientation: axis,
97
- scrollOffsets: [
98
- { target: targetEl, edge: 'start', threshold: parseFloat(start) / 100 },
99
- { target: targetEl, edge: 'end', threshold: parseFloat(end) / 100 }
100
- ]
101
- });
102
- }
103
-
104
- } else if (fallback === 'io') {
105
- // Fallback using Intersection Observer
106
- let animation: Animation | null = null;
107
-
108
- const observer = new IntersectionObserver(
109
- (entries) => {
110
- entries.forEach(entry => {
111
- const progress = Math.max(0, Math.min(1, entry.intersectionRatio));
112
-
113
- if (!animation) {
114
- animation = targetEl.animate(keyframes, {
115
- duration: 1000,
116
- fill: 'both'
117
- });
118
- animation.pause();
119
- }
120
-
121
- // Update animation progress based on intersection
122
- animation.currentTime = progress * 1000;
123
- });
124
- },
125
- {
126
- threshold: Array.from({ length: 101 }, (_, i) => i / 100) // 0 to 1 in 0.01 steps
127
- }
128
- );
129
-
130
- observer.observe(targetEl);
131
-
132
- // Store cleanup function
133
- (targetEl as any)._scrollAnimateCleanup = () => {
134
- observer.disconnect();
135
- if (animation) {
136
- animation.cancel();
137
- }
138
- };
139
- }
140
- }
141
-
142
- /**
143
- * Create a scroll-triggered animation that plays once when element enters viewport
144
- */
145
- export function scrollTrigger(
146
- target: Element | string,
147
- keyframes: Keyframe[],
148
- options: KeyframeAnimationOptions = {}
149
- ): void {
150
- const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
151
- if (!targetEl) {
152
- throw new Error('Target element not found');
153
- }
154
-
155
- // Check for reduced motion preference
156
- const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
157
-
158
- if (prefersReducedMotion) {
159
- // Apply end state immediately
160
- const endKeyframe = keyframes[keyframes.length - 1];
161
- Object.assign((targetEl as HTMLElement).style, endKeyframe);
162
- return;
163
- }
164
-
165
- const observer = new IntersectionObserver(
166
- (entries) => {
167
- entries.forEach(entry => {
168
- if (entry.isIntersecting) {
169
- // Play animation
170
- targetEl.animate(keyframes, {
171
- duration: 600,
172
- easing: 'ease-out',
173
- fill: 'forwards',
174
- ...options
175
- });
176
-
177
- // Disconnect observer after first trigger
178
- observer.disconnect();
179
- }
180
- });
181
- },
182
- {
183
- threshold: 0.1,
184
- rootMargin: '0px 0px -10% 0px'
185
- }
186
- );
187
-
188
- observer.observe(targetEl);
189
- }
190
-
191
- /**
192
- * Parallax effect using scroll-driven animations
193
- */
194
- export function parallax(
195
- target: Element | string,
196
- speed: number = 0.5
197
- ): void {
198
- const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
199
- if (!targetEl) {
200
- throw new Error('Target element not found');
201
- }
202
-
203
- // Check for reduced motion preference
204
- const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
205
- if (prefersReducedMotion) return;
206
-
207
- const keyframes = [
208
- { transform: `translateY(${-100 * speed}px)` },
209
- { transform: `translateY(${100 * speed}px)` }
210
- ];
211
-
212
- scrollAnimate(targetEl, {
213
- keyframes,
214
- range: ['0%', '100%'],
215
- timeline: { axis: 'block' },
216
- fallback: 'io'
217
- });
218
- }
219
-
220
- /**
221
- * Cleanup function to remove scroll animations
222
- */
223
- export function cleanup(target: Element | string): void {
224
- const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
225
- if (!targetEl) return;
226
-
227
- // Call stored cleanup function if it exists
228
- if ((targetEl as any)._scrollAnimateCleanup) {
229
- (targetEl as any)._scrollAnimateCleanup();
230
- delete (targetEl as any)._scrollAnimateCleanup;
231
- }
232
-
233
- // Remove animation classes
234
- targetEl.classList.forEach(className => {
235
- if (className.startsWith('scroll-animate-')) {
236
- targetEl.classList.remove(className);
237
- }
238
- });
239
-
240
- // Cancel any running animations
241
- const animations = targetEl.getAnimations();
242
- animations.forEach(animation => animation.cancel());
243
- }
244
-
245
- // Export default object for convenience
246
- export default {
247
- scrollAnimate,
248
- scrollTrigger,
249
- parallax,
250
- cleanup
251
- };
1
+ /**
2
+ * @sc4rfurryx/proteusjs/scroll
3
+ * Scroll-driven animations with CSS Scroll-Linked Animations
4
+ *
5
+ * @version 2.0.0
6
+ * @author sc4rfurry
7
+ * @license MIT
8
+ */
9
+
10
+ export interface ScrollAnimateOptions {
11
+ keyframes: Keyframe[];
12
+ range?: [string, string];
13
+ timeline?: {
14
+ axis?: 'block' | 'inline';
15
+ start?: string;
16
+ end?: string;
17
+ };
18
+ fallback?: 'io' | false;
19
+ }
20
+
21
+ /**
22
+ * Zero-boilerplate setup for CSS Scroll-Linked Animations with fallbacks
23
+ */
24
+ export function scrollAnimate(
25
+ target: Element | string,
26
+ opts: ScrollAnimateOptions
27
+ ): void {
28
+ const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
29
+ if (!targetEl) {
30
+ throw new Error('Target element not found');
31
+ }
32
+
33
+ const {
34
+ keyframes,
35
+ range = ['0%', '100%'],
36
+ timeline = {},
37
+ fallback = 'io'
38
+ } = opts;
39
+
40
+ const {
41
+ axis = 'block',
42
+ start = '0%',
43
+ end = '100%'
44
+ } = timeline;
45
+
46
+ // Check for CSS Scroll-Linked Animations support
47
+ const hasScrollTimeline = 'CSS' in window && CSS.supports('animation-timeline', 'scroll()');
48
+
49
+ // Check for reduced motion preference
50
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
51
+
52
+ if (prefersReducedMotion) {
53
+ // Respect user preference - either disable or reduce animation
54
+ if (fallback === false) return;
55
+
56
+ // Apply only the end state for reduced motion
57
+ const endKeyframe = keyframes[keyframes.length - 1];
58
+ Object.assign((targetEl as HTMLElement).style, endKeyframe);
59
+ return;
60
+ }
61
+
62
+ if (hasScrollTimeline) {
63
+ // Use native CSS Scroll-Linked Animations
64
+ const timelineName = `scroll-timeline-${Math.random().toString(36).substr(2, 9)}`;
65
+
66
+ // Create scroll timeline
67
+ const style = document.createElement('style');
68
+ style.textContent = `
69
+ @scroll-timeline ${timelineName} {
70
+ source: nearest;
71
+ orientation: ${axis};
72
+ scroll-offsets: ${start}, ${end};
73
+ }
74
+
75
+ .scroll-animate-${timelineName} {
76
+ animation-timeline: ${timelineName};
77
+ animation-duration: 1ms; /* Required but ignored */
78
+ animation-fill-mode: both;
79
+ }
80
+ `;
81
+ document.head.appendChild(style);
82
+
83
+ // Apply animation class
84
+ targetEl.classList.add(`scroll-animate-${timelineName}`);
85
+
86
+ // Create Web Animations API animation
87
+ const animation = targetEl.animate(keyframes, {
88
+ duration: 1, // Required but ignored with scroll timeline
89
+ fill: 'both'
90
+ });
91
+
92
+ // Set scroll timeline (when supported)
93
+ if ('timeline' in animation) {
94
+ (animation as any).timeline = new (window as any).ScrollTimeline({
95
+ source: document.scrollingElement,
96
+ orientation: axis,
97
+ scrollOffsets: [
98
+ { target: targetEl, edge: 'start', threshold: parseFloat(start) / 100 },
99
+ { target: targetEl, edge: 'end', threshold: parseFloat(end) / 100 }
100
+ ]
101
+ });
102
+ }
103
+
104
+ } else if (fallback === 'io') {
105
+ // Fallback using Intersection Observer
106
+ let animation: Animation | null = null;
107
+
108
+ const observer = new IntersectionObserver(
109
+ (entries) => {
110
+ entries.forEach(entry => {
111
+ const progress = Math.max(0, Math.min(1, entry.intersectionRatio));
112
+
113
+ if (!animation) {
114
+ animation = targetEl.animate(keyframes, {
115
+ duration: 1000,
116
+ fill: 'both'
117
+ });
118
+ animation.pause();
119
+ }
120
+
121
+ // Update animation progress based on intersection
122
+ animation.currentTime = progress * 1000;
123
+ });
124
+ },
125
+ {
126
+ threshold: Array.from({ length: 101 }, (_, i) => i / 100) // 0 to 1 in 0.01 steps
127
+ }
128
+ );
129
+
130
+ observer.observe(targetEl);
131
+
132
+ // Store cleanup function
133
+ (targetEl as any)._scrollAnimateCleanup = () => {
134
+ observer.disconnect();
135
+ if (animation) {
136
+ animation.cancel();
137
+ }
138
+ };
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Create a scroll-triggered animation that plays once when element enters viewport
144
+ */
145
+ export function scrollTrigger(
146
+ target: Element | string,
147
+ keyframes: Keyframe[],
148
+ options: KeyframeAnimationOptions = {}
149
+ ): void {
150
+ const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
151
+ if (!targetEl) {
152
+ throw new Error('Target element not found');
153
+ }
154
+
155
+ // Check for reduced motion preference
156
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
157
+
158
+ if (prefersReducedMotion) {
159
+ // Apply end state immediately
160
+ const endKeyframe = keyframes[keyframes.length - 1];
161
+ Object.assign((targetEl as HTMLElement).style, endKeyframe);
162
+ return;
163
+ }
164
+
165
+ const observer = new IntersectionObserver(
166
+ (entries) => {
167
+ entries.forEach(entry => {
168
+ if (entry.isIntersecting) {
169
+ // Play animation
170
+ targetEl.animate(keyframes, {
171
+ duration: 600,
172
+ easing: 'ease-out',
173
+ fill: 'forwards',
174
+ ...options
175
+ });
176
+
177
+ // Disconnect observer after first trigger
178
+ observer.disconnect();
179
+ }
180
+ });
181
+ },
182
+ {
183
+ threshold: 0.1,
184
+ rootMargin: '0px 0px -10% 0px'
185
+ }
186
+ );
187
+
188
+ observer.observe(targetEl);
189
+ }
190
+
191
+ /**
192
+ * Parallax effect using scroll-driven animations
193
+ */
194
+ export function parallax(
195
+ target: Element | string,
196
+ speed: number = 0.5
197
+ ): void {
198
+ const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
199
+ if (!targetEl) {
200
+ throw new Error('Target element not found');
201
+ }
202
+
203
+ // Check for reduced motion preference
204
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
205
+ if (prefersReducedMotion) return;
206
+
207
+ const keyframes = [
208
+ { transform: `translateY(${-100 * speed}px)` },
209
+ { transform: `translateY(${100 * speed}px)` }
210
+ ];
211
+
212
+ scrollAnimate(targetEl, {
213
+ keyframes,
214
+ range: ['0%', '100%'],
215
+ timeline: { axis: 'block' },
216
+ fallback: 'io'
217
+ });
218
+ }
219
+
220
+ /**
221
+ * Cleanup function to remove scroll animations
222
+ */
223
+ export function cleanup(target: Element | string): void {
224
+ const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
225
+ if (!targetEl) return;
226
+
227
+ // Call stored cleanup function if it exists
228
+ if ((targetEl as any)._scrollAnimateCleanup) {
229
+ (targetEl as any)._scrollAnimateCleanup();
230
+ delete (targetEl as any)._scrollAnimateCleanup;
231
+ }
232
+
233
+ // Remove animation classes
234
+ targetEl.classList.forEach(className => {
235
+ if (className.startsWith('scroll-animate-')) {
236
+ targetEl.classList.remove(className);
237
+ }
238
+ });
239
+
240
+ // Cancel any running animations
241
+ const animations = targetEl.getAnimations();
242
+ animations.forEach(animation => animation.cancel());
243
+ }
244
+
245
+ // Export default object for convenience
246
+ export default {
247
+ scrollAnimate,
248
+ scrollTrigger,
249
+ parallax,
250
+ cleanup
251
+ };