@sc4rfurryx/proteusjs 1.1.0 → 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.
- package/README.md +684 -899
- package/dist/.tsbuildinfo +1 -1
- package/dist/modules/a11y-audit.d.ts +2 -10
- package/dist/modules/a11y-audit.esm.js +31 -476
- package/dist/modules/a11y-audit.esm.js.map +1 -1
- package/dist/modules/a11y-primitives.d.ts +9 -42
- package/dist/modules/a11y-primitives.esm.js +70 -401
- package/dist/modules/a11y-primitives.esm.js.map +1 -1
- package/dist/modules/anchor.d.ts +2 -1
- package/dist/modules/anchor.esm.js +3 -2
- package/dist/modules/anchor.esm.js.map +1 -1
- package/dist/modules/container.d.ts +1 -1
- package/dist/modules/container.esm.js +34 -34
- package/dist/modules/container.esm.js.map +1 -1
- package/dist/modules/perf.d.ts +1 -1
- package/dist/modules/perf.esm.js +2 -2
- package/dist/modules/popover.d.ts +1 -1
- package/dist/modules/popover.esm.js +2 -2
- package/dist/modules/scroll.d.ts +1 -1
- package/dist/modules/scroll.esm.js +14 -14
- package/dist/modules/scroll.esm.js.map +1 -1
- package/dist/modules/transitions.d.ts +1 -1
- package/dist/modules/transitions.esm.js +12 -12
- package/dist/modules/transitions.esm.js.map +1 -1
- package/dist/modules/typography.d.ts +1 -1
- package/dist/modules/typography.esm.js +2 -2
- package/dist/proteus.cjs.js +163 -941
- package/dist/proteus.cjs.js.map +1 -1
- package/dist/proteus.d.ts +23 -68
- package/dist/proteus.esm.js +163 -941
- package/dist/proteus.esm.js.map +1 -1
- package/dist/proteus.esm.min.js +2 -2
- package/dist/proteus.esm.min.js.map +1 -1
- package/dist/proteus.js +163 -941
- package/dist/proteus.js.map +1 -1
- package/dist/proteus.min.js +2 -2
- package/dist/proteus.min.js.map +1 -1
- package/package.json +44 -7
- package/src/adapters/react.ts +607 -264
- package/src/adapters/svelte.ts +321 -321
- package/src/adapters/vue.ts +268 -268
- package/src/core/ProteusJS.ts +6 -6
- package/src/index.ts +3 -3
- package/src/modules/a11y-audit/index.ts +84 -608
- package/src/modules/a11y-primitives/index.ts +152 -554
- package/src/modules/anchor/index.ts +259 -257
- package/src/modules/container/index.ts +230 -230
- package/src/modules/perf/index.ts +291 -291
- package/src/modules/popover/index.ts +238 -238
- package/src/modules/scroll/index.ts +251 -251
- package/src/modules/transitions/index.ts +145 -145
- package/src/modules/typography/index.ts +239 -239
- package/src/utils/version.ts +1 -1
- package/dist/adapters/react.d.ts +0 -139
- package/dist/adapters/react.esm.js +0 -848
- package/dist/adapters/react.esm.js.map +0 -1
- package/dist/adapters/svelte.d.ts +0 -181
- package/dist/adapters/svelte.esm.js +0 -908
- package/dist/adapters/svelte.esm.js.map +0 -1
- package/dist/adapters/vue.d.ts +0 -205
- package/dist/adapters/vue.esm.js +0 -872
- package/dist/adapters/vue.esm.js.map +0 -1
|
@@ -1,239 +1,239 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @sc4rfurryx/proteusjs/typography
|
|
3
|
-
* Fluid typography with CSS-first approach
|
|
4
|
-
*
|
|
5
|
-
* @version
|
|
6
|
-
* @author sc4rfurry
|
|
7
|
-
* @license MIT
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export interface FluidTypeOptions {
|
|
11
|
-
minViewportPx?: number;
|
|
12
|
-
maxViewportPx?: number;
|
|
13
|
-
lineHeight?: number;
|
|
14
|
-
containerUnits?: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface FluidTypeResult {
|
|
18
|
-
css: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate pure-CSS clamp() rules for fluid typography
|
|
23
|
-
*/
|
|
24
|
-
export function fluidType(
|
|
25
|
-
minRem: number,
|
|
26
|
-
maxRem: number,
|
|
27
|
-
options: FluidTypeOptions = {}
|
|
28
|
-
): FluidTypeResult {
|
|
29
|
-
const {
|
|
30
|
-
minViewportPx = 320,
|
|
31
|
-
maxViewportPx = 1200,
|
|
32
|
-
lineHeight,
|
|
33
|
-
containerUnits = false
|
|
34
|
-
} = options;
|
|
35
|
-
|
|
36
|
-
// Convert rem to px for calculations (assuming 16px base)
|
|
37
|
-
const minPx = minRem * 16;
|
|
38
|
-
const maxPx = maxRem * 16;
|
|
39
|
-
|
|
40
|
-
// Calculate slope and y-intercept for linear interpolation
|
|
41
|
-
const slope = (maxPx - minPx) / (maxViewportPx - minViewportPx);
|
|
42
|
-
const yIntercept = minPx - slope * minViewportPx;
|
|
43
|
-
|
|
44
|
-
// Generate clamp() function
|
|
45
|
-
const viewportUnit = containerUnits ? 'cqw' : 'vw';
|
|
46
|
-
const clampValue = `clamp(${minRem}rem, ${yIntercept / 16}rem + ${slope * 100}${viewportUnit}, ${maxRem}rem)`;
|
|
47
|
-
|
|
48
|
-
let css = `font-size: ${clampValue};`;
|
|
49
|
-
|
|
50
|
-
// Add line-height if specified
|
|
51
|
-
if (lineHeight) {
|
|
52
|
-
css += `\nline-height: ${lineHeight};`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return { css };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Apply fluid typography to elements
|
|
60
|
-
*/
|
|
61
|
-
export function applyFluidType(
|
|
62
|
-
selector: string,
|
|
63
|
-
minRem: number,
|
|
64
|
-
maxRem: number,
|
|
65
|
-
options: FluidTypeOptions = {}
|
|
66
|
-
): void {
|
|
67
|
-
const { css } = fluidType(minRem, maxRem, options);
|
|
68
|
-
|
|
69
|
-
const styleElement = document.createElement('style');
|
|
70
|
-
styleElement.textContent = `${selector} {\n ${css.replace(/\n/g, '\n ')}\n}`;
|
|
71
|
-
styleElement.setAttribute('data-proteus-typography', selector);
|
|
72
|
-
document.head.appendChild(styleElement);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Create a complete typographic scale
|
|
77
|
-
*/
|
|
78
|
-
export function createTypographicScale(
|
|
79
|
-
baseSize: number = 1,
|
|
80
|
-
ratio: number = 1.25,
|
|
81
|
-
steps: number = 6,
|
|
82
|
-
options: FluidTypeOptions = {}
|
|
83
|
-
): Record<string, FluidTypeResult> {
|
|
84
|
-
const scale: Record<string, FluidTypeResult> = {};
|
|
85
|
-
|
|
86
|
-
for (let i = -2; i <= steps - 3; i++) {
|
|
87
|
-
const size = baseSize * Math.pow(ratio, i);
|
|
88
|
-
const minSize = size * 0.8; // 20% smaller at min viewport
|
|
89
|
-
const maxSize = size * 1.2; // 20% larger at max viewport
|
|
90
|
-
|
|
91
|
-
const stepName = i <= 0 ? `small${Math.abs(i)}` : `large${i}`;
|
|
92
|
-
scale[stepName] = fluidType(minSize, maxSize, options);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return scale;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Generate CSS custom properties for a typographic scale
|
|
100
|
-
*/
|
|
101
|
-
export function generateScaleCSS(
|
|
102
|
-
scale: Record<string, FluidTypeResult>,
|
|
103
|
-
prefix: string = '--font-size'
|
|
104
|
-
): string {
|
|
105
|
-
const cssVars = Object.entries(scale)
|
|
106
|
-
.map(([name, result]) => ` ${prefix}-${name}: ${result.css.replace('font-size: ', '').replace(';', '')};`)
|
|
107
|
-
.join('\n');
|
|
108
|
-
|
|
109
|
-
return `:root {\n${cssVars}\n}`;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Optimize line height for readability
|
|
114
|
-
*/
|
|
115
|
-
export function optimizeLineHeight(fontSize: number, measure: number = 65): number {
|
|
116
|
-
// Optimal line height based on font size and measure (characters per line)
|
|
117
|
-
// Smaller fonts need more line height, larger fonts need less
|
|
118
|
-
const baseLineHeight = 1.4;
|
|
119
|
-
const sizeAdjustment = Math.max(0.1, Math.min(0.3, (1 - fontSize) * 0.5));
|
|
120
|
-
const measureAdjustment = Math.max(-0.1, Math.min(0.1, (65 - measure) * 0.002));
|
|
121
|
-
|
|
122
|
-
return baseLineHeight + sizeAdjustment + measureAdjustment;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Calculate optimal font size for container width
|
|
127
|
-
*/
|
|
128
|
-
export function calculateOptimalSize(
|
|
129
|
-
containerWidth: number,
|
|
130
|
-
targetCharacters: number = 65,
|
|
131
|
-
baseCharWidth: number = 0.5
|
|
132
|
-
): number {
|
|
133
|
-
// Calculate font size to achieve target characters per line
|
|
134
|
-
const optimalFontSize = containerWidth / (targetCharacters * baseCharWidth);
|
|
135
|
-
|
|
136
|
-
// Clamp to reasonable bounds (12px to 24px)
|
|
137
|
-
return Math.max(0.75, Math.min(1.5, optimalFontSize));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Apply responsive typography to an element
|
|
142
|
-
*/
|
|
143
|
-
export function makeResponsive(
|
|
144
|
-
target: Element | string,
|
|
145
|
-
options: {
|
|
146
|
-
minSize?: number;
|
|
147
|
-
maxSize?: number;
|
|
148
|
-
targetCharacters?: number;
|
|
149
|
-
autoLineHeight?: boolean;
|
|
150
|
-
} = {}
|
|
151
|
-
): void {
|
|
152
|
-
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
|
153
|
-
if (!targetEl) {
|
|
154
|
-
throw new Error('Target element not found');
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const {
|
|
158
|
-
minSize = 0.875,
|
|
159
|
-
maxSize = 1.25,
|
|
160
|
-
targetCharacters = 65,
|
|
161
|
-
autoLineHeight = true
|
|
162
|
-
} = options;
|
|
163
|
-
|
|
164
|
-
// Apply fluid typography
|
|
165
|
-
const { css } = fluidType(minSize, maxSize);
|
|
166
|
-
const element = targetEl as HTMLElement;
|
|
167
|
-
|
|
168
|
-
// Parse and apply CSS
|
|
169
|
-
const styles = css.split(';').filter(Boolean);
|
|
170
|
-
styles.forEach(style => {
|
|
171
|
-
const [property, value] = style.split(':').map(s => s.trim());
|
|
172
|
-
if (property && value) {
|
|
173
|
-
element.style.setProperty(property, value);
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// Auto line height if enabled
|
|
178
|
-
if (autoLineHeight) {
|
|
179
|
-
const updateLineHeight = () => {
|
|
180
|
-
const computedStyle = getComputedStyle(element);
|
|
181
|
-
const fontSize = parseFloat(computedStyle.fontSize);
|
|
182
|
-
const containerWidth = element.getBoundingClientRect().width;
|
|
183
|
-
const charactersPerLine = containerWidth / (fontSize * 0.5);
|
|
184
|
-
|
|
185
|
-
const optimalLineHeight = optimizeLineHeight(fontSize / 16, charactersPerLine);
|
|
186
|
-
element.style.lineHeight = optimalLineHeight.toString();
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
updateLineHeight();
|
|
190
|
-
|
|
191
|
-
// Update on resize
|
|
192
|
-
if ('ResizeObserver' in window) {
|
|
193
|
-
const resizeObserver = new ResizeObserver(updateLineHeight);
|
|
194
|
-
resizeObserver.observe(element);
|
|
195
|
-
|
|
196
|
-
// Store cleanup function
|
|
197
|
-
(element as any)._proteusTypographyCleanup = () => {
|
|
198
|
-
resizeObserver.disconnect();
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Remove applied typography styles
|
|
206
|
-
*/
|
|
207
|
-
export function cleanup(target?: Element | string): void {
|
|
208
|
-
if (target) {
|
|
209
|
-
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
|
210
|
-
if (targetEl && (targetEl as any)._proteusTypographyCleanup) {
|
|
211
|
-
(targetEl as any)._proteusTypographyCleanup();
|
|
212
|
-
delete (targetEl as any)._proteusTypographyCleanup;
|
|
213
|
-
}
|
|
214
|
-
} else {
|
|
215
|
-
// Remove all typography style elements
|
|
216
|
-
const styleElements = document.querySelectorAll('style[data-proteus-typography]');
|
|
217
|
-
styleElements.forEach(element => element.remove());
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Check if container query units are supported
|
|
223
|
-
*/
|
|
224
|
-
export function supportsContainerUnits(): boolean {
|
|
225
|
-
return CSS.supports('width', '1cqw');
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Export default object for convenience
|
|
229
|
-
export default {
|
|
230
|
-
fluidType,
|
|
231
|
-
applyFluidType,
|
|
232
|
-
createTypographicScale,
|
|
233
|
-
generateScaleCSS,
|
|
234
|
-
optimizeLineHeight,
|
|
235
|
-
calculateOptimalSize,
|
|
236
|
-
makeResponsive,
|
|
237
|
-
cleanup,
|
|
238
|
-
supportsContainerUnits
|
|
239
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* @sc4rfurryx/proteusjs/typography
|
|
3
|
+
* Fluid typography with CSS-first approach
|
|
4
|
+
*
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
* @author sc4rfurry
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface FluidTypeOptions {
|
|
11
|
+
minViewportPx?: number;
|
|
12
|
+
maxViewportPx?: number;
|
|
13
|
+
lineHeight?: number;
|
|
14
|
+
containerUnits?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface FluidTypeResult {
|
|
18
|
+
css: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate pure-CSS clamp() rules for fluid typography
|
|
23
|
+
*/
|
|
24
|
+
export function fluidType(
|
|
25
|
+
minRem: number,
|
|
26
|
+
maxRem: number,
|
|
27
|
+
options: FluidTypeOptions = {}
|
|
28
|
+
): FluidTypeResult {
|
|
29
|
+
const {
|
|
30
|
+
minViewportPx = 320,
|
|
31
|
+
maxViewportPx = 1200,
|
|
32
|
+
lineHeight,
|
|
33
|
+
containerUnits = false
|
|
34
|
+
} = options;
|
|
35
|
+
|
|
36
|
+
// Convert rem to px for calculations (assuming 16px base)
|
|
37
|
+
const minPx = minRem * 16;
|
|
38
|
+
const maxPx = maxRem * 16;
|
|
39
|
+
|
|
40
|
+
// Calculate slope and y-intercept for linear interpolation
|
|
41
|
+
const slope = (maxPx - minPx) / (maxViewportPx - minViewportPx);
|
|
42
|
+
const yIntercept = minPx - slope * minViewportPx;
|
|
43
|
+
|
|
44
|
+
// Generate clamp() function
|
|
45
|
+
const viewportUnit = containerUnits ? 'cqw' : 'vw';
|
|
46
|
+
const clampValue = `clamp(${minRem}rem, ${yIntercept / 16}rem + ${slope * 100}${viewportUnit}, ${maxRem}rem)`;
|
|
47
|
+
|
|
48
|
+
let css = `font-size: ${clampValue};`;
|
|
49
|
+
|
|
50
|
+
// Add line-height if specified
|
|
51
|
+
if (lineHeight) {
|
|
52
|
+
css += `\nline-height: ${lineHeight};`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { css };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Apply fluid typography to elements
|
|
60
|
+
*/
|
|
61
|
+
export function applyFluidType(
|
|
62
|
+
selector: string,
|
|
63
|
+
minRem: number,
|
|
64
|
+
maxRem: number,
|
|
65
|
+
options: FluidTypeOptions = {}
|
|
66
|
+
): void {
|
|
67
|
+
const { css } = fluidType(minRem, maxRem, options);
|
|
68
|
+
|
|
69
|
+
const styleElement = document.createElement('style');
|
|
70
|
+
styleElement.textContent = `${selector} {\n ${css.replace(/\n/g, '\n ')}\n}`;
|
|
71
|
+
styleElement.setAttribute('data-proteus-typography', selector);
|
|
72
|
+
document.head.appendChild(styleElement);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Create a complete typographic scale
|
|
77
|
+
*/
|
|
78
|
+
export function createTypographicScale(
|
|
79
|
+
baseSize: number = 1,
|
|
80
|
+
ratio: number = 1.25,
|
|
81
|
+
steps: number = 6,
|
|
82
|
+
options: FluidTypeOptions = {}
|
|
83
|
+
): Record<string, FluidTypeResult> {
|
|
84
|
+
const scale: Record<string, FluidTypeResult> = {};
|
|
85
|
+
|
|
86
|
+
for (let i = -2; i <= steps - 3; i++) {
|
|
87
|
+
const size = baseSize * Math.pow(ratio, i);
|
|
88
|
+
const minSize = size * 0.8; // 20% smaller at min viewport
|
|
89
|
+
const maxSize = size * 1.2; // 20% larger at max viewport
|
|
90
|
+
|
|
91
|
+
const stepName = i <= 0 ? `small${Math.abs(i)}` : `large${i}`;
|
|
92
|
+
scale[stepName] = fluidType(minSize, maxSize, options);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return scale;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Generate CSS custom properties for a typographic scale
|
|
100
|
+
*/
|
|
101
|
+
export function generateScaleCSS(
|
|
102
|
+
scale: Record<string, FluidTypeResult>,
|
|
103
|
+
prefix: string = '--font-size'
|
|
104
|
+
): string {
|
|
105
|
+
const cssVars = Object.entries(scale)
|
|
106
|
+
.map(([name, result]) => ` ${prefix}-${name}: ${result.css.replace('font-size: ', '').replace(';', '')};`)
|
|
107
|
+
.join('\n');
|
|
108
|
+
|
|
109
|
+
return `:root {\n${cssVars}\n}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Optimize line height for readability
|
|
114
|
+
*/
|
|
115
|
+
export function optimizeLineHeight(fontSize: number, measure: number = 65): number {
|
|
116
|
+
// Optimal line height based on font size and measure (characters per line)
|
|
117
|
+
// Smaller fonts need more line height, larger fonts need less
|
|
118
|
+
const baseLineHeight = 1.4;
|
|
119
|
+
const sizeAdjustment = Math.max(0.1, Math.min(0.3, (1 - fontSize) * 0.5));
|
|
120
|
+
const measureAdjustment = Math.max(-0.1, Math.min(0.1, (65 - measure) * 0.002));
|
|
121
|
+
|
|
122
|
+
return baseLineHeight + sizeAdjustment + measureAdjustment;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Calculate optimal font size for container width
|
|
127
|
+
*/
|
|
128
|
+
export function calculateOptimalSize(
|
|
129
|
+
containerWidth: number,
|
|
130
|
+
targetCharacters: number = 65,
|
|
131
|
+
baseCharWidth: number = 0.5
|
|
132
|
+
): number {
|
|
133
|
+
// Calculate font size to achieve target characters per line
|
|
134
|
+
const optimalFontSize = containerWidth / (targetCharacters * baseCharWidth);
|
|
135
|
+
|
|
136
|
+
// Clamp to reasonable bounds (12px to 24px)
|
|
137
|
+
return Math.max(0.75, Math.min(1.5, optimalFontSize));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Apply responsive typography to an element
|
|
142
|
+
*/
|
|
143
|
+
export function makeResponsive(
|
|
144
|
+
target: Element | string,
|
|
145
|
+
options: {
|
|
146
|
+
minSize?: number;
|
|
147
|
+
maxSize?: number;
|
|
148
|
+
targetCharacters?: number;
|
|
149
|
+
autoLineHeight?: boolean;
|
|
150
|
+
} = {}
|
|
151
|
+
): void {
|
|
152
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
|
153
|
+
if (!targetEl) {
|
|
154
|
+
throw new Error('Target element not found');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const {
|
|
158
|
+
minSize = 0.875,
|
|
159
|
+
maxSize = 1.25,
|
|
160
|
+
targetCharacters = 65,
|
|
161
|
+
autoLineHeight = true
|
|
162
|
+
} = options;
|
|
163
|
+
|
|
164
|
+
// Apply fluid typography
|
|
165
|
+
const { css } = fluidType(minSize, maxSize);
|
|
166
|
+
const element = targetEl as HTMLElement;
|
|
167
|
+
|
|
168
|
+
// Parse and apply CSS
|
|
169
|
+
const styles = css.split(';').filter(Boolean);
|
|
170
|
+
styles.forEach(style => {
|
|
171
|
+
const [property, value] = style.split(':').map(s => s.trim());
|
|
172
|
+
if (property && value) {
|
|
173
|
+
element.style.setProperty(property, value);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Auto line height if enabled
|
|
178
|
+
if (autoLineHeight) {
|
|
179
|
+
const updateLineHeight = () => {
|
|
180
|
+
const computedStyle = getComputedStyle(element);
|
|
181
|
+
const fontSize = parseFloat(computedStyle.fontSize);
|
|
182
|
+
const containerWidth = element.getBoundingClientRect().width;
|
|
183
|
+
const charactersPerLine = containerWidth / (fontSize * 0.5);
|
|
184
|
+
|
|
185
|
+
const optimalLineHeight = optimizeLineHeight(fontSize / 16, charactersPerLine);
|
|
186
|
+
element.style.lineHeight = optimalLineHeight.toString();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
updateLineHeight();
|
|
190
|
+
|
|
191
|
+
// Update on resize
|
|
192
|
+
if ('ResizeObserver' in window) {
|
|
193
|
+
const resizeObserver = new ResizeObserver(updateLineHeight);
|
|
194
|
+
resizeObserver.observe(element);
|
|
195
|
+
|
|
196
|
+
// Store cleanup function
|
|
197
|
+
(element as any)._proteusTypographyCleanup = () => {
|
|
198
|
+
resizeObserver.disconnect();
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Remove applied typography styles
|
|
206
|
+
*/
|
|
207
|
+
export function cleanup(target?: Element | string): void {
|
|
208
|
+
if (target) {
|
|
209
|
+
const targetEl = typeof target === 'string' ? document.querySelector(target) : target;
|
|
210
|
+
if (targetEl && (targetEl as any)._proteusTypographyCleanup) {
|
|
211
|
+
(targetEl as any)._proteusTypographyCleanup();
|
|
212
|
+
delete (targetEl as any)._proteusTypographyCleanup;
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
// Remove all typography style elements
|
|
216
|
+
const styleElements = document.querySelectorAll('style[data-proteus-typography]');
|
|
217
|
+
styleElements.forEach(element => element.remove());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Check if container query units are supported
|
|
223
|
+
*/
|
|
224
|
+
export function supportsContainerUnits(): boolean {
|
|
225
|
+
return CSS.supports('width', '1cqw');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Export default object for convenience
|
|
229
|
+
export default {
|
|
230
|
+
fluidType,
|
|
231
|
+
applyFluidType,
|
|
232
|
+
createTypographicScale,
|
|
233
|
+
generateScaleCSS,
|
|
234
|
+
optimizeLineHeight,
|
|
235
|
+
calculateOptimalSize,
|
|
236
|
+
makeResponsive,
|
|
237
|
+
cleanup,
|
|
238
|
+
supportsContainerUnits
|
|
239
|
+
};
|
package/src/utils/version.ts
CHANGED
package/dist/adapters/react.d.ts
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import React, { RefObject } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @sc4rfurryx/proteusjs/scroll
|
|
5
|
-
* Scroll-driven animations with CSS Scroll-Linked Animations
|
|
6
|
-
*
|
|
7
|
-
* @version 1.1.0
|
|
8
|
-
* @author sc4rfurry
|
|
9
|
-
* @license MIT
|
|
10
|
-
*/
|
|
11
|
-
interface ScrollAnimateOptions {
|
|
12
|
-
keyframes: Keyframe[];
|
|
13
|
-
range?: [string, string];
|
|
14
|
-
timeline?: {
|
|
15
|
-
axis?: 'block' | 'inline';
|
|
16
|
-
start?: string;
|
|
17
|
-
end?: string;
|
|
18
|
-
};
|
|
19
|
-
fallback?: 'io' | false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @sc4rfurryx/proteusjs/popover
|
|
24
|
-
* HTML Popover API wrapper with robust focus/inert handling
|
|
25
|
-
*
|
|
26
|
-
* @version 1.1.0
|
|
27
|
-
* @author sc4rfurry
|
|
28
|
-
* @license MIT
|
|
29
|
-
*/
|
|
30
|
-
interface PopoverOptions {
|
|
31
|
-
type?: 'menu' | 'dialog' | 'tooltip';
|
|
32
|
-
trapFocus?: boolean;
|
|
33
|
-
restoreFocus?: boolean;
|
|
34
|
-
closeOnEscape?: boolean;
|
|
35
|
-
onOpen?: () => void;
|
|
36
|
-
onClose?: () => void;
|
|
37
|
-
}
|
|
38
|
-
interface PopoverController {
|
|
39
|
-
open(): void;
|
|
40
|
-
close(): void;
|
|
41
|
-
toggle(): void;
|
|
42
|
-
destroy(): void;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @sc4rfurryx/proteusjs/anchor
|
|
47
|
-
* CSS Anchor Positioning utilities with robust JS fallback
|
|
48
|
-
*
|
|
49
|
-
* @version 1.1.0
|
|
50
|
-
* @author sc4rfurry
|
|
51
|
-
* @license MIT
|
|
52
|
-
*/
|
|
53
|
-
interface TetherOptions {
|
|
54
|
-
anchor: Element | string;
|
|
55
|
-
placement?: 'top' | 'bottom' | 'left' | 'right' | 'auto';
|
|
56
|
-
align?: 'start' | 'center' | 'end';
|
|
57
|
-
offset?: number;
|
|
58
|
-
strategy?: 'absolute' | 'fixed';
|
|
59
|
-
}
|
|
60
|
-
interface TetherController {
|
|
61
|
-
destroy(): void;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @sc4rfurryx/proteusjs/container
|
|
66
|
-
* Container/Style Query helpers with visualization devtools
|
|
67
|
-
*
|
|
68
|
-
* @version 1.1.0
|
|
69
|
-
* @author sc4rfurry
|
|
70
|
-
* @license MIT
|
|
71
|
-
*/
|
|
72
|
-
interface ContainerOptions {
|
|
73
|
-
type?: 'size' | 'style';
|
|
74
|
-
inlineSize?: boolean;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* @sc4rfurryx/proteusjs/adapters/react
|
|
79
|
-
* React hooks and components for ProteusJS
|
|
80
|
-
*
|
|
81
|
-
* @version 1.1.0
|
|
82
|
-
* @author sc4rfurry
|
|
83
|
-
* @license MIT
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Hook for view transitions
|
|
88
|
-
*/
|
|
89
|
-
declare function useTransition(): any;
|
|
90
|
-
/**
|
|
91
|
-
* Hook for scroll-driven animations
|
|
92
|
-
*/
|
|
93
|
-
declare function useScrollAnimate(ref: RefObject<HTMLElement>, opts: ScrollAnimateOptions): void;
|
|
94
|
-
/**
|
|
95
|
-
* Hook for popover functionality
|
|
96
|
-
*/
|
|
97
|
-
declare function usePopover(triggerRef: RefObject<HTMLElement>, panelRef: RefObject<HTMLElement>, opts?: PopoverOptions): PopoverController | null;
|
|
98
|
-
/**
|
|
99
|
-
* Hook for anchor positioning
|
|
100
|
-
*/
|
|
101
|
-
declare function useAnchor(floatingRef: RefObject<HTMLElement>, anchorRef: RefObject<HTMLElement>, opts?: Omit<TetherOptions, 'anchor'>): TetherController | null;
|
|
102
|
-
/**
|
|
103
|
-
* Hook for container queries
|
|
104
|
-
*/
|
|
105
|
-
declare function useContainer(ref: RefObject<HTMLElement>, name?: string, opts?: ContainerOptions): void;
|
|
106
|
-
/**
|
|
107
|
-
* Hook for performance optimizations
|
|
108
|
-
*/
|
|
109
|
-
declare function usePerformance(ref: RefObject<HTMLElement>): void;
|
|
110
|
-
/**
|
|
111
|
-
* Hook for accessibility features
|
|
112
|
-
*/
|
|
113
|
-
declare function useA11y(ref: RefObject<HTMLElement>, options?: {
|
|
114
|
-
announceChanges?: boolean;
|
|
115
|
-
focusManagement?: boolean;
|
|
116
|
-
}): void;
|
|
117
|
-
/**
|
|
118
|
-
* Higher-order component for adding ProteusJS features
|
|
119
|
-
*/
|
|
120
|
-
declare function withProteus<P extends object>(Component: React.ComponentType<P>, features?: {
|
|
121
|
-
container?: {
|
|
122
|
-
name?: string;
|
|
123
|
-
options?: ContainerOptions;
|
|
124
|
-
};
|
|
125
|
-
performance?: boolean;
|
|
126
|
-
accessibility?: boolean;
|
|
127
|
-
}): (props: P) => any;
|
|
128
|
-
declare const _default: {
|
|
129
|
-
useTransition: typeof useTransition;
|
|
130
|
-
useScrollAnimate: typeof useScrollAnimate;
|
|
131
|
-
usePopover: typeof usePopover;
|
|
132
|
-
useAnchor: typeof useAnchor;
|
|
133
|
-
useContainer: typeof useContainer;
|
|
134
|
-
usePerformance: typeof usePerformance;
|
|
135
|
-
useA11y: typeof useA11y;
|
|
136
|
-
withProteus: typeof withProteus;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export { _default as default, useA11y, useAnchor, useContainer, usePerformance, usePopover, useScrollAnimate, useTransition, withProteus };
|