@sc4rfurryx/proteusjs 1.0.0 → 1.1.1
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.
- package/LICENSE +1 -1
- package/README.md +331 -77
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/react.d.ts +140 -0
- package/dist/adapters/react.esm.js +849 -0
- package/dist/adapters/react.esm.js.map +1 -0
- package/dist/adapters/svelte.d.ts +181 -0
- package/dist/adapters/svelte.esm.js +909 -0
- package/dist/adapters/svelte.esm.js.map +1 -0
- package/dist/adapters/vue.d.ts +205 -0
- package/dist/adapters/vue.esm.js +873 -0
- package/dist/adapters/vue.esm.js.map +1 -0
- package/dist/modules/a11y-audit.d.ts +31 -0
- package/dist/modules/a11y-audit.esm.js +64 -0
- package/dist/modules/a11y-audit.esm.js.map +1 -0
- package/dist/modules/a11y-primitives.d.ts +36 -0
- package/dist/modules/a11y-primitives.esm.js +114 -0
- package/dist/modules/a11y-primitives.esm.js.map +1 -0
- package/dist/modules/anchor.d.ts +30 -0
- package/dist/modules/anchor.esm.js +219 -0
- package/dist/modules/anchor.esm.js.map +1 -0
- package/dist/modules/container.d.ts +60 -0
- package/dist/modules/container.esm.js +194 -0
- package/dist/modules/container.esm.js.map +1 -0
- package/dist/modules/perf.d.ts +82 -0
- package/dist/modules/perf.esm.js +257 -0
- package/dist/modules/perf.esm.js.map +1 -0
- package/dist/modules/popover.d.ts +33 -0
- package/dist/modules/popover.esm.js +191 -0
- package/dist/modules/popover.esm.js.map +1 -0
- package/dist/modules/scroll.d.ts +43 -0
- package/dist/modules/scroll.esm.js +195 -0
- package/dist/modules/scroll.esm.js.map +1 -0
- package/dist/modules/transitions.d.ts +35 -0
- package/dist/modules/transitions.esm.js +120 -0
- package/dist/modules/transitions.esm.js.map +1 -0
- package/dist/modules/typography.d.ts +72 -0
- package/dist/modules/typography.esm.js +168 -0
- package/dist/modules/typography.esm.js.map +1 -0
- package/dist/proteus.cjs.js +1554 -12
- package/dist/proteus.cjs.js.map +1 -1
- package/dist/proteus.d.ts +516 -12
- package/dist/proteus.esm.js +1545 -12
- package/dist/proteus.esm.js.map +1 -1
- package/dist/proteus.esm.min.js +3 -3
- package/dist/proteus.esm.min.js.map +1 -1
- package/dist/proteus.js +1554 -12
- package/dist/proteus.js.map +1 -1
- package/dist/proteus.min.js +3 -3
- package/dist/proteus.min.js.map +1 -1
- package/package.json +69 -7
- package/src/adapters/react.ts +264 -0
- package/src/adapters/svelte.ts +321 -0
- package/src/adapters/vue.ts +268 -0
- package/src/index.ts +33 -6
- package/src/modules/a11y-audit/index.ts +84 -0
- package/src/modules/a11y-primitives/index.ts +152 -0
- package/src/modules/anchor/index.ts +259 -0
- package/src/modules/container/index.ts +230 -0
- package/src/modules/perf/index.ts +291 -0
- package/src/modules/popover/index.ts +238 -0
- package/src/modules/scroll/index.ts +251 -0
- package/src/modules/transitions/index.ts +145 -0
- package/src/modules/typography/index.ts +239 -0
- package/src/utils/version.ts +1 -1
@@ -0,0 +1,191 @@
|
|
1
|
+
/*!
|
2
|
+
* ProteusJS v1.1.1
|
3
|
+
* Shape-shifting responsive design that adapts like the sea god himself
|
4
|
+
* (c) 2025 sc4rfurry
|
5
|
+
* Released under the MIT License
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* @sc4rfurryx/proteusjs/popover
|
9
|
+
* HTML Popover API wrapper with robust focus/inert handling
|
10
|
+
*
|
11
|
+
* @version 1.1.0
|
12
|
+
* @author sc4rfurry
|
13
|
+
* @license MIT
|
14
|
+
*/
|
15
|
+
/**
|
16
|
+
* Unified API for menus, tooltips, and dialogs using the native Popover API
|
17
|
+
* with robust focus/inert handling
|
18
|
+
*/
|
19
|
+
function attach(trigger, panel, opts = {}) {
|
20
|
+
const triggerEl = typeof trigger === 'string' ? document.querySelector(trigger) : trigger;
|
21
|
+
const panelEl = typeof panel === 'string' ? document.querySelector(panel) : panel;
|
22
|
+
if (!triggerEl || !panelEl) {
|
23
|
+
throw new Error('Both trigger and panel elements must exist');
|
24
|
+
}
|
25
|
+
const { type = 'menu', trapFocus = type === 'dialog', restoreFocus = true, closeOnEscape = true, onOpen, onClose } = opts;
|
26
|
+
let isOpen = false;
|
27
|
+
let previousFocus = null;
|
28
|
+
let focusTrap = null;
|
29
|
+
// Check for native Popover API support
|
30
|
+
const hasPopoverAPI = 'popover' in HTMLElement.prototype;
|
31
|
+
// Set up ARIA attributes
|
32
|
+
const setupAria = () => {
|
33
|
+
const panelId = panelEl.id || `popover-${Math.random().toString(36).substr(2, 9)}`;
|
34
|
+
panelEl.id = panelId;
|
35
|
+
triggerEl.setAttribute('aria-expanded', 'false');
|
36
|
+
triggerEl.setAttribute('aria-controls', panelId);
|
37
|
+
if (type === 'menu') {
|
38
|
+
triggerEl.setAttribute('aria-haspopup', 'menu');
|
39
|
+
panelEl.setAttribute('role', 'menu');
|
40
|
+
}
|
41
|
+
else if (type === 'dialog') {
|
42
|
+
triggerEl.setAttribute('aria-haspopup', 'dialog');
|
43
|
+
panelEl.setAttribute('role', 'dialog');
|
44
|
+
panelEl.setAttribute('aria-modal', 'true');
|
45
|
+
}
|
46
|
+
else if (type === 'tooltip') {
|
47
|
+
triggerEl.setAttribute('aria-describedby', panelId);
|
48
|
+
panelEl.setAttribute('role', 'tooltip');
|
49
|
+
}
|
50
|
+
};
|
51
|
+
// Set up native popover if supported
|
52
|
+
const setupNativePopover = () => {
|
53
|
+
if (hasPopoverAPI) {
|
54
|
+
panelEl.popover = type === 'dialog' ? 'manual' : 'auto';
|
55
|
+
triggerEl.setAttribute('popovertarget', panelEl.id);
|
56
|
+
}
|
57
|
+
};
|
58
|
+
// Focus trap implementation
|
59
|
+
class FocusTrap {
|
60
|
+
constructor(container) {
|
61
|
+
this.container = container;
|
62
|
+
this.focusableElements = [];
|
63
|
+
this.handleKeyDown = (e) => {
|
64
|
+
if (e.key !== 'Tab')
|
65
|
+
return;
|
66
|
+
const firstElement = this.focusableElements[0];
|
67
|
+
const lastElement = this.focusableElements[this.focusableElements.length - 1];
|
68
|
+
if (e.shiftKey) {
|
69
|
+
if (document.activeElement === firstElement) {
|
70
|
+
e.preventDefault();
|
71
|
+
lastElement.focus();
|
72
|
+
}
|
73
|
+
}
|
74
|
+
else {
|
75
|
+
if (document.activeElement === lastElement) {
|
76
|
+
e.preventDefault();
|
77
|
+
firstElement.focus();
|
78
|
+
}
|
79
|
+
}
|
80
|
+
};
|
81
|
+
this.updateFocusableElements();
|
82
|
+
}
|
83
|
+
updateFocusableElements() {
|
84
|
+
const selector = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
85
|
+
this.focusableElements = Array.from(this.container.querySelectorAll(selector));
|
86
|
+
}
|
87
|
+
activate() {
|
88
|
+
this.updateFocusableElements();
|
89
|
+
if (this.focusableElements.length > 0) {
|
90
|
+
this.focusableElements[0].focus();
|
91
|
+
}
|
92
|
+
document.addEventListener('keydown', this.handleKeyDown);
|
93
|
+
}
|
94
|
+
deactivate() {
|
95
|
+
document.removeEventListener('keydown', this.handleKeyDown);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
const open = () => {
|
99
|
+
if (isOpen)
|
100
|
+
return;
|
101
|
+
if (restoreFocus) {
|
102
|
+
previousFocus = document.activeElement;
|
103
|
+
}
|
104
|
+
if (hasPopoverAPI) {
|
105
|
+
panelEl.showPopover();
|
106
|
+
}
|
107
|
+
else {
|
108
|
+
panelEl.style.display = 'block';
|
109
|
+
panelEl.setAttribute('data-popover-open', 'true');
|
110
|
+
}
|
111
|
+
triggerEl.setAttribute('aria-expanded', 'true');
|
112
|
+
isOpen = true;
|
113
|
+
if (trapFocus) {
|
114
|
+
focusTrap = new FocusTrap(panelEl);
|
115
|
+
focusTrap.activate();
|
116
|
+
}
|
117
|
+
if (onOpen) {
|
118
|
+
onOpen();
|
119
|
+
}
|
120
|
+
};
|
121
|
+
const close = () => {
|
122
|
+
if (!isOpen)
|
123
|
+
return;
|
124
|
+
if (hasPopoverAPI) {
|
125
|
+
panelEl.hidePopover();
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
panelEl.style.display = 'none';
|
129
|
+
panelEl.removeAttribute('data-popover-open');
|
130
|
+
}
|
131
|
+
triggerEl.setAttribute('aria-expanded', 'false');
|
132
|
+
isOpen = false;
|
133
|
+
if (focusTrap) {
|
134
|
+
focusTrap.deactivate();
|
135
|
+
focusTrap = null;
|
136
|
+
}
|
137
|
+
if (restoreFocus && previousFocus) {
|
138
|
+
previousFocus.focus();
|
139
|
+
previousFocus = null;
|
140
|
+
}
|
141
|
+
if (onClose) {
|
142
|
+
onClose();
|
143
|
+
}
|
144
|
+
};
|
145
|
+
const toggle = () => {
|
146
|
+
if (isOpen) {
|
147
|
+
close();
|
148
|
+
}
|
149
|
+
else {
|
150
|
+
open();
|
151
|
+
}
|
152
|
+
};
|
153
|
+
const handleKeyDown = (e) => {
|
154
|
+
if (closeOnEscape && e.key === 'Escape' && isOpen) {
|
155
|
+
e.preventDefault();
|
156
|
+
close();
|
157
|
+
}
|
158
|
+
};
|
159
|
+
const handleClick = (e) => {
|
160
|
+
e.preventDefault();
|
161
|
+
toggle();
|
162
|
+
};
|
163
|
+
const destroy = () => {
|
164
|
+
triggerEl.removeEventListener('click', handleClick);
|
165
|
+
document.removeEventListener('keydown', handleKeyDown);
|
166
|
+
if (focusTrap) {
|
167
|
+
focusTrap.deactivate();
|
168
|
+
}
|
169
|
+
if (isOpen) {
|
170
|
+
close();
|
171
|
+
}
|
172
|
+
};
|
173
|
+
// Initialize
|
174
|
+
setupAria();
|
175
|
+
setupNativePopover();
|
176
|
+
triggerEl.addEventListener('click', handleClick);
|
177
|
+
document.addEventListener('keydown', handleKeyDown);
|
178
|
+
return {
|
179
|
+
open,
|
180
|
+
close,
|
181
|
+
toggle,
|
182
|
+
destroy
|
183
|
+
};
|
184
|
+
}
|
185
|
+
// Export default object for convenience
|
186
|
+
var index = {
|
187
|
+
attach
|
188
|
+
};
|
189
|
+
|
190
|
+
export { attach, index as default };
|
191
|
+
//# sourceMappingURL=popover.esm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"popover.esm.js","sources":["../../src/modules/popover/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
@@ -0,0 +1,43 @@
|
|
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
|
+
interface ScrollAnimateOptions {
|
10
|
+
keyframes: Keyframe[];
|
11
|
+
range?: [string, string];
|
12
|
+
timeline?: {
|
13
|
+
axis?: 'block' | 'inline';
|
14
|
+
start?: string;
|
15
|
+
end?: string;
|
16
|
+
};
|
17
|
+
fallback?: 'io' | false;
|
18
|
+
}
|
19
|
+
/**
|
20
|
+
* Zero-boilerplate setup for CSS Scroll-Linked Animations with fallbacks
|
21
|
+
*/
|
22
|
+
declare function scrollAnimate(target: Element | string, opts: ScrollAnimateOptions): void;
|
23
|
+
/**
|
24
|
+
* Create a scroll-triggered animation that plays once when element enters viewport
|
25
|
+
*/
|
26
|
+
declare function scrollTrigger(target: Element | string, keyframes: Keyframe[], options?: KeyframeAnimationOptions): void;
|
27
|
+
/**
|
28
|
+
* Parallax effect using scroll-driven animations
|
29
|
+
*/
|
30
|
+
declare function parallax(target: Element | string, speed?: number): void;
|
31
|
+
/**
|
32
|
+
* Cleanup function to remove scroll animations
|
33
|
+
*/
|
34
|
+
declare function cleanup(target: Element | string): void;
|
35
|
+
declare const _default: {
|
36
|
+
scrollAnimate: typeof scrollAnimate;
|
37
|
+
scrollTrigger: typeof scrollTrigger;
|
38
|
+
parallax: typeof parallax;
|
39
|
+
cleanup: typeof cleanup;
|
40
|
+
};
|
41
|
+
|
42
|
+
export { cleanup, _default as default, parallax, scrollAnimate, scrollTrigger };
|
43
|
+
export type { ScrollAnimateOptions };
|
@@ -0,0 +1,195 @@
|
|
1
|
+
/*!
|
2
|
+
* ProteusJS v1.1.1
|
3
|
+
* Shape-shifting responsive design that adapts like the sea god himself
|
4
|
+
* (c) 2025 sc4rfurry
|
5
|
+
* Released under the MIT License
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* @sc4rfurryx/proteusjs/scroll
|
9
|
+
* Scroll-driven animations with CSS Scroll-Linked Animations
|
10
|
+
*
|
11
|
+
* @version 1.1.0
|
12
|
+
* @author sc4rfurry
|
13
|
+
* @license MIT
|
14
|
+
*/
|
15
|
+
/**
|
16
|
+
* Zero-boilerplate setup for CSS Scroll-Linked Animations with fallbacks
|
17
|
+
*/
|
18
|
+
function scrollAnimate(target, opts) {
|
19
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
20
|
+
if (!targetEl) {
|
21
|
+
throw new Error('Target element not found');
|
22
|
+
}
|
23
|
+
const { keyframes, range = ['0%', '100%'], timeline = {}, fallback = 'io' } = opts;
|
24
|
+
const { axis = 'block', start = '0%', end = '100%' } = timeline;
|
25
|
+
// Check for CSS Scroll-Linked Animations support
|
26
|
+
const hasScrollTimeline = 'CSS' in window && CSS.supports('animation-timeline', 'scroll()');
|
27
|
+
// Check for reduced motion preference
|
28
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
29
|
+
if (prefersReducedMotion) {
|
30
|
+
// Respect user preference - either disable or reduce animation
|
31
|
+
if (fallback === false)
|
32
|
+
return;
|
33
|
+
// Apply only the end state for reduced motion
|
34
|
+
const endKeyframe = keyframes[keyframes.length - 1];
|
35
|
+
Object.assign(targetEl.style, endKeyframe);
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
if (hasScrollTimeline) {
|
39
|
+
// Use native CSS Scroll-Linked Animations
|
40
|
+
const timelineName = `scroll-timeline-${Math.random().toString(36).substr(2, 9)}`;
|
41
|
+
// Create scroll timeline
|
42
|
+
const style = document.createElement('style');
|
43
|
+
style.textContent = `
|
44
|
+
@scroll-timeline ${timelineName} {
|
45
|
+
source: nearest;
|
46
|
+
orientation: ${axis};
|
47
|
+
scroll-offsets: ${start}, ${end};
|
48
|
+
}
|
49
|
+
|
50
|
+
.scroll-animate-${timelineName} {
|
51
|
+
animation-timeline: ${timelineName};
|
52
|
+
animation-duration: 1ms; /* Required but ignored */
|
53
|
+
animation-fill-mode: both;
|
54
|
+
}
|
55
|
+
`;
|
56
|
+
document.head.appendChild(style);
|
57
|
+
// Apply animation class
|
58
|
+
targetEl.classList.add(`scroll-animate-${timelineName}`);
|
59
|
+
// Create Web Animations API animation
|
60
|
+
const animation = targetEl.animate(keyframes, {
|
61
|
+
duration: 1, // Required but ignored with scroll timeline
|
62
|
+
fill: 'both'
|
63
|
+
});
|
64
|
+
// Set scroll timeline (when supported)
|
65
|
+
if ('timeline' in animation) {
|
66
|
+
animation.timeline = new window.ScrollTimeline({
|
67
|
+
source: document.scrollingElement,
|
68
|
+
orientation: axis,
|
69
|
+
scrollOffsets: [
|
70
|
+
{ target: targetEl, edge: 'start', threshold: parseFloat(start) / 100 },
|
71
|
+
{ target: targetEl, edge: 'end', threshold: parseFloat(end) / 100 }
|
72
|
+
]
|
73
|
+
});
|
74
|
+
}
|
75
|
+
}
|
76
|
+
else if (fallback === 'io') {
|
77
|
+
// Fallback using Intersection Observer
|
78
|
+
let animation = null;
|
79
|
+
const observer = new IntersectionObserver((entries) => {
|
80
|
+
entries.forEach(entry => {
|
81
|
+
const progress = Math.max(0, Math.min(1, entry.intersectionRatio));
|
82
|
+
if (!animation) {
|
83
|
+
animation = targetEl.animate(keyframes, {
|
84
|
+
duration: 1000,
|
85
|
+
fill: 'both'
|
86
|
+
});
|
87
|
+
animation.pause();
|
88
|
+
}
|
89
|
+
// Update animation progress based on intersection
|
90
|
+
animation.currentTime = progress * 1000;
|
91
|
+
});
|
92
|
+
}, {
|
93
|
+
threshold: Array.from({ length: 101 }, (_, i) => i / 100) // 0 to 1 in 0.01 steps
|
94
|
+
});
|
95
|
+
observer.observe(targetEl);
|
96
|
+
// Store cleanup function
|
97
|
+
targetEl._scrollAnimateCleanup = () => {
|
98
|
+
observer.disconnect();
|
99
|
+
if (animation) {
|
100
|
+
animation.cancel();
|
101
|
+
}
|
102
|
+
};
|
103
|
+
}
|
104
|
+
}
|
105
|
+
/**
|
106
|
+
* Create a scroll-triggered animation that plays once when element enters viewport
|
107
|
+
*/
|
108
|
+
function scrollTrigger(target, keyframes, options = {}) {
|
109
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
110
|
+
if (!targetEl) {
|
111
|
+
throw new Error('Target element not found');
|
112
|
+
}
|
113
|
+
// Check for reduced motion preference
|
114
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
115
|
+
if (prefersReducedMotion) {
|
116
|
+
// Apply end state immediately
|
117
|
+
const endKeyframe = keyframes[keyframes.length - 1];
|
118
|
+
Object.assign(targetEl.style, endKeyframe);
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
const observer = new IntersectionObserver((entries) => {
|
122
|
+
entries.forEach(entry => {
|
123
|
+
if (entry.isIntersecting) {
|
124
|
+
// Play animation
|
125
|
+
targetEl.animate(keyframes, {
|
126
|
+
duration: 600,
|
127
|
+
easing: 'ease-out',
|
128
|
+
fill: 'forwards',
|
129
|
+
...options
|
130
|
+
});
|
131
|
+
// Disconnect observer after first trigger
|
132
|
+
observer.disconnect();
|
133
|
+
}
|
134
|
+
});
|
135
|
+
}, {
|
136
|
+
threshold: 0.1,
|
137
|
+
rootMargin: '0px 0px -10% 0px'
|
138
|
+
});
|
139
|
+
observer.observe(targetEl);
|
140
|
+
}
|
141
|
+
/**
|
142
|
+
* Parallax effect using scroll-driven animations
|
143
|
+
*/
|
144
|
+
function parallax(target, speed = 0.5) {
|
145
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
146
|
+
if (!targetEl) {
|
147
|
+
throw new Error('Target element not found');
|
148
|
+
}
|
149
|
+
// Check for reduced motion preference
|
150
|
+
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
151
|
+
if (prefersReducedMotion)
|
152
|
+
return;
|
153
|
+
const keyframes = [
|
154
|
+
{ transform: `translateY(${ -100 * speed}px)` },
|
155
|
+
{ transform: `translateY(${100 * speed}px)` }
|
156
|
+
];
|
157
|
+
scrollAnimate(targetEl, {
|
158
|
+
keyframes,
|
159
|
+
range: ['0%', '100%'],
|
160
|
+
timeline: { axis: 'block' },
|
161
|
+
fallback: 'io'
|
162
|
+
});
|
163
|
+
}
|
164
|
+
/**
|
165
|
+
* Cleanup function to remove scroll animations
|
166
|
+
*/
|
167
|
+
function cleanup(target) {
|
168
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
169
|
+
if (!targetEl)
|
170
|
+
return;
|
171
|
+
// Call stored cleanup function if it exists
|
172
|
+
if (targetEl._scrollAnimateCleanup) {
|
173
|
+
targetEl._scrollAnimateCleanup();
|
174
|
+
delete targetEl._scrollAnimateCleanup;
|
175
|
+
}
|
176
|
+
// Remove animation classes
|
177
|
+
targetEl.classList.forEach(className => {
|
178
|
+
if (className.startsWith('scroll-animate-')) {
|
179
|
+
targetEl.classList.remove(className);
|
180
|
+
}
|
181
|
+
});
|
182
|
+
// Cancel any running animations
|
183
|
+
const animations = targetEl.getAnimations();
|
184
|
+
animations.forEach(animation => animation.cancel());
|
185
|
+
}
|
186
|
+
// Export default object for convenience
|
187
|
+
var index = {
|
188
|
+
scrollAnimate,
|
189
|
+
scrollTrigger,
|
190
|
+
parallax,
|
191
|
+
cleanup
|
192
|
+
};
|
193
|
+
|
194
|
+
export { cleanup, index as default, parallax, scrollAnimate, scrollTrigger };
|
195
|
+
//# sourceMappingURL=scroll.esm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"scroll.esm.js","sources":["../../src/modules/scroll/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
/**
|
2
|
+
* @sc4rfurryx/proteusjs/transitions
|
3
|
+
* View Transitions API wrapper with safe fallbacks
|
4
|
+
*
|
5
|
+
* @version 1.1.0
|
6
|
+
* @author sc4rfurry
|
7
|
+
* @license MIT
|
8
|
+
*/
|
9
|
+
interface TransitionOptions {
|
10
|
+
name?: string;
|
11
|
+
duration?: number;
|
12
|
+
onBefore?: () => void;
|
13
|
+
onAfter?: () => void;
|
14
|
+
allowInterrupt?: boolean;
|
15
|
+
}
|
16
|
+
interface NavigateOptions {
|
17
|
+
name?: string;
|
18
|
+
prerender?: boolean;
|
19
|
+
}
|
20
|
+
/**
|
21
|
+
* One API for animating DOM state changes and cross-document navigations
|
22
|
+
* using the View Transitions API with safe fallbacks.
|
23
|
+
*/
|
24
|
+
declare function transition(run: () => Promise<any> | any, opts?: TransitionOptions): Promise<void>;
|
25
|
+
/**
|
26
|
+
* MPA-friendly navigation with view transitions when supported
|
27
|
+
*/
|
28
|
+
declare function navigate(url: string, opts?: NavigateOptions): Promise<void>;
|
29
|
+
declare const _default: {
|
30
|
+
transition: typeof transition;
|
31
|
+
navigate: typeof navigate;
|
32
|
+
};
|
33
|
+
|
34
|
+
export { _default as default, navigate, transition };
|
35
|
+
export type { NavigateOptions, TransitionOptions };
|
@@ -0,0 +1,120 @@
|
|
1
|
+
/*!
|
2
|
+
* ProteusJS v1.1.1
|
3
|
+
* Shape-shifting responsive design that adapts like the sea god himself
|
4
|
+
* (c) 2025 sc4rfurry
|
5
|
+
* Released under the MIT License
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* @sc4rfurryx/proteusjs/transitions
|
9
|
+
* View Transitions API wrapper with safe fallbacks
|
10
|
+
*
|
11
|
+
* @version 1.1.0
|
12
|
+
* @author sc4rfurry
|
13
|
+
* @license MIT
|
14
|
+
*/
|
15
|
+
/**
|
16
|
+
* One API for animating DOM state changes and cross-document navigations
|
17
|
+
* using the View Transitions API with safe fallbacks.
|
18
|
+
*/
|
19
|
+
async function transition(run, opts = {}) {
|
20
|
+
const { name, duration = 300, onBefore, onAfter, allowInterrupt = true } = opts;
|
21
|
+
// Check for View Transitions API support
|
22
|
+
const hasViewTransitions = 'startViewTransition' in document;
|
23
|
+
if (onBefore) {
|
24
|
+
onBefore();
|
25
|
+
}
|
26
|
+
if (!hasViewTransitions) {
|
27
|
+
// Fallback: run immediately without transitions
|
28
|
+
try {
|
29
|
+
await run();
|
30
|
+
}
|
31
|
+
finally {
|
32
|
+
if (onAfter) {
|
33
|
+
onAfter();
|
34
|
+
}
|
35
|
+
}
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
// Use native View Transitions API
|
39
|
+
try {
|
40
|
+
const viewTransition = document.startViewTransition(async () => {
|
41
|
+
await run();
|
42
|
+
});
|
43
|
+
// Add CSS view-transition-name if name provided
|
44
|
+
if (name) {
|
45
|
+
const style = document.createElement('style');
|
46
|
+
style.textContent = `
|
47
|
+
::view-transition-old(${name}),
|
48
|
+
::view-transition-new(${name}) {
|
49
|
+
animation-duration: ${duration}ms;
|
50
|
+
}
|
51
|
+
`;
|
52
|
+
document.head.appendChild(style);
|
53
|
+
// Clean up style after transition
|
54
|
+
viewTransition.finished.finally(() => {
|
55
|
+
style.remove();
|
56
|
+
});
|
57
|
+
}
|
58
|
+
await viewTransition.finished;
|
59
|
+
}
|
60
|
+
catch (error) {
|
61
|
+
console.warn('View transition failed, falling back to immediate execution:', error);
|
62
|
+
await run();
|
63
|
+
}
|
64
|
+
finally {
|
65
|
+
if (onAfter) {
|
66
|
+
onAfter();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
/**
|
71
|
+
* MPA-friendly navigation with view transitions when supported
|
72
|
+
*/
|
73
|
+
async function navigate(url, opts = {}) {
|
74
|
+
const { name, prerender = false } = opts;
|
75
|
+
// Optional prerender hint (basic implementation)
|
76
|
+
if (prerender && 'speculation' in HTMLScriptElement.prototype) {
|
77
|
+
const script = document.createElement('script');
|
78
|
+
script.type = 'speculationrules';
|
79
|
+
script.textContent = JSON.stringify({
|
80
|
+
prerender: [{ where: { href_matches: url } }]
|
81
|
+
});
|
82
|
+
document.head.appendChild(script);
|
83
|
+
}
|
84
|
+
// Check for View Transitions API support
|
85
|
+
const hasViewTransitions = 'startViewTransition' in document;
|
86
|
+
if (!hasViewTransitions) {
|
87
|
+
// Fallback: normal navigation
|
88
|
+
window.location.href = url;
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
try {
|
92
|
+
// Use view transitions for navigation
|
93
|
+
const viewTransition = document.startViewTransition(() => {
|
94
|
+
window.location.href = url;
|
95
|
+
});
|
96
|
+
if (name) {
|
97
|
+
const style = document.createElement('style');
|
98
|
+
style.textContent = `
|
99
|
+
::view-transition-old(${name}),
|
100
|
+
::view-transition-new(${name}) {
|
101
|
+
animation-duration: 300ms;
|
102
|
+
}
|
103
|
+
`;
|
104
|
+
document.head.appendChild(style);
|
105
|
+
}
|
106
|
+
await viewTransition.finished;
|
107
|
+
}
|
108
|
+
catch (error) {
|
109
|
+
console.warn('View transition navigation failed, falling back to normal navigation:', error);
|
110
|
+
window.location.href = url;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
// Export default object for convenience
|
114
|
+
var index = {
|
115
|
+
transition,
|
116
|
+
navigate
|
117
|
+
};
|
118
|
+
|
119
|
+
export { index as default, navigate, transition };
|
120
|
+
//# sourceMappingURL=transitions.esm.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"transitions.esm.js","sources":["../../src/modules/transitions/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
/**
|
2
|
+
* @sc4rfurryx/proteusjs/typography
|
3
|
+
* Fluid typography with CSS-first approach
|
4
|
+
*
|
5
|
+
* @version 1.1.0
|
6
|
+
* @author sc4rfurry
|
7
|
+
* @license MIT
|
8
|
+
*/
|
9
|
+
interface FluidTypeOptions {
|
10
|
+
minViewportPx?: number;
|
11
|
+
maxViewportPx?: number;
|
12
|
+
lineHeight?: number;
|
13
|
+
containerUnits?: boolean;
|
14
|
+
}
|
15
|
+
interface FluidTypeResult {
|
16
|
+
css: string;
|
17
|
+
}
|
18
|
+
/**
|
19
|
+
* Generate pure-CSS clamp() rules for fluid typography
|
20
|
+
*/
|
21
|
+
declare function fluidType(minRem: number, maxRem: number, options?: FluidTypeOptions): FluidTypeResult;
|
22
|
+
/**
|
23
|
+
* Apply fluid typography to elements
|
24
|
+
*/
|
25
|
+
declare function applyFluidType(selector: string, minRem: number, maxRem: number, options?: FluidTypeOptions): void;
|
26
|
+
/**
|
27
|
+
* Create a complete typographic scale
|
28
|
+
*/
|
29
|
+
declare function createTypographicScale(baseSize?: number, ratio?: number, steps?: number, options?: FluidTypeOptions): Record<string, FluidTypeResult>;
|
30
|
+
/**
|
31
|
+
* Generate CSS custom properties for a typographic scale
|
32
|
+
*/
|
33
|
+
declare function generateScaleCSS(scale: Record<string, FluidTypeResult>, prefix?: string): string;
|
34
|
+
/**
|
35
|
+
* Optimize line height for readability
|
36
|
+
*/
|
37
|
+
declare function optimizeLineHeight(fontSize: number, measure?: number): number;
|
38
|
+
/**
|
39
|
+
* Calculate optimal font size for container width
|
40
|
+
*/
|
41
|
+
declare function calculateOptimalSize(containerWidth: number, targetCharacters?: number, baseCharWidth?: number): number;
|
42
|
+
/**
|
43
|
+
* Apply responsive typography to an element
|
44
|
+
*/
|
45
|
+
declare function makeResponsive(target: Element | string, options?: {
|
46
|
+
minSize?: number;
|
47
|
+
maxSize?: number;
|
48
|
+
targetCharacters?: number;
|
49
|
+
autoLineHeight?: boolean;
|
50
|
+
}): void;
|
51
|
+
/**
|
52
|
+
* Remove applied typography styles
|
53
|
+
*/
|
54
|
+
declare function cleanup(target?: Element | string): void;
|
55
|
+
/**
|
56
|
+
* Check if container query units are supported
|
57
|
+
*/
|
58
|
+
declare function supportsContainerUnits(): boolean;
|
59
|
+
declare const _default: {
|
60
|
+
fluidType: typeof fluidType;
|
61
|
+
applyFluidType: typeof applyFluidType;
|
62
|
+
createTypographicScale: typeof createTypographicScale;
|
63
|
+
generateScaleCSS: typeof generateScaleCSS;
|
64
|
+
optimizeLineHeight: typeof optimizeLineHeight;
|
65
|
+
calculateOptimalSize: typeof calculateOptimalSize;
|
66
|
+
makeResponsive: typeof makeResponsive;
|
67
|
+
cleanup: typeof cleanup;
|
68
|
+
supportsContainerUnits: typeof supportsContainerUnits;
|
69
|
+
};
|
70
|
+
|
71
|
+
export { applyFluidType, calculateOptimalSize, cleanup, createTypographicScale, _default as default, fluidType, generateScaleCSS, makeResponsive, optimizeLineHeight, supportsContainerUnits };
|
72
|
+
export type { FluidTypeOptions, FluidTypeResult };
|