@idealyst/theme 1.2.79 → 1.2.81
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/package.json +2 -2
- package/src/animation/index.ts +13 -0
- package/src/animation/springApproximation.ts +315 -0
- package/src/animation/transitions.ts +91 -2
- package/src/colorScheme.ts +1 -1
- package/src/index.ts +3 -0
- package/src/styleBuilder.ts +1 -0
- package/src/useTheme.ts +46 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/theme",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.81",
|
|
4
4
|
"description": "Theming system for Idealyst Framework",
|
|
5
5
|
"readme": "README.md",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"publish:npm": "npm publish"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@idealyst/tooling": "^1.2.
|
|
66
|
+
"@idealyst/tooling": "^1.2.81"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"react-native-unistyles": ">=3.0.0"
|
package/src/animation/index.ts
CHANGED
|
@@ -44,6 +44,8 @@ export type {
|
|
|
44
44
|
export {
|
|
45
45
|
resolveDuration,
|
|
46
46
|
resolveEasing,
|
|
47
|
+
resolveEasingWithDuration,
|
|
48
|
+
getSpringInfo,
|
|
47
49
|
cssTransition,
|
|
48
50
|
cssPreset,
|
|
49
51
|
cssKeyframes,
|
|
@@ -54,6 +56,17 @@ export {
|
|
|
54
56
|
pulseGradientStyle,
|
|
55
57
|
} from './transitions';
|
|
56
58
|
|
|
59
|
+
// Export spring approximation utilities
|
|
60
|
+
export {
|
|
61
|
+
approximateSpring,
|
|
62
|
+
getSpringApproximation,
|
|
63
|
+
springApproximations,
|
|
64
|
+
isLinearEasingSupported,
|
|
65
|
+
getLinearFallback,
|
|
66
|
+
usesLinearEasing,
|
|
67
|
+
type SpringApproximation,
|
|
68
|
+
} from './springApproximation';
|
|
69
|
+
|
|
57
70
|
// Export native utilities (these are also exported from index.native.ts)
|
|
58
71
|
// Including here allows type-checking in monorepo without platform resolution
|
|
59
72
|
export {
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spring-to-CSS Approximation Utilities
|
|
3
|
+
*
|
|
4
|
+
* These utilities convert spring physics parameters to CSS-compatible
|
|
5
|
+
* bezier curves and durations, enabling performant CSS-only animations
|
|
6
|
+
* on web that approximate native spring behavior.
|
|
7
|
+
*
|
|
8
|
+
* CSS cannot truly replicate spring physics (damping, stiffness, mass, velocity),
|
|
9
|
+
* but we can create close approximations using cubic-bezier curves and the
|
|
10
|
+
* CSS linear() function for more accurate representations.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { SpringConfig, BezierEasing } from './types';
|
|
14
|
+
import { easings } from './tokens';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Result of converting a spring config to CSS-compatible values
|
|
18
|
+
*/
|
|
19
|
+
export interface SpringApproximation {
|
|
20
|
+
/** CSS easing string (cubic-bezier or linear()) */
|
|
21
|
+
css: string;
|
|
22
|
+
/** Bezier curve values (for fallback or simpler scenarios) */
|
|
23
|
+
bezier: BezierEasing;
|
|
24
|
+
/** Calculated duration in milliseconds */
|
|
25
|
+
duration: number;
|
|
26
|
+
/** Whether this spring has significant overshoot */
|
|
27
|
+
hasOvershoot: boolean;
|
|
28
|
+
/** Description of the approximation quality */
|
|
29
|
+
quality: 'good' | 'approximate' | 'limited';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Pre-computed approximations for built-in spring types
|
|
34
|
+
*
|
|
35
|
+
* These are hand-tuned to feel as close as possible to the
|
|
36
|
+
* native spring implementations.
|
|
37
|
+
*/
|
|
38
|
+
export const springApproximations: Record<string, SpringApproximation> = {
|
|
39
|
+
/**
|
|
40
|
+
* spring: { damping: 15, stiffness: 200, mass: 1 }
|
|
41
|
+
* Medium bounce, good for toggles and state changes
|
|
42
|
+
* Has noticeable overshoot (~10-15%)
|
|
43
|
+
*/
|
|
44
|
+
spring: {
|
|
45
|
+
css: 'cubic-bezier(0.34, 1.4, 0.64, 1)',
|
|
46
|
+
bezier: [0.34, 1.4, 0.64, 1] as BezierEasing,
|
|
47
|
+
duration: 350,
|
|
48
|
+
hasOvershoot: true,
|
|
49
|
+
quality: 'approximate',
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* springStiff: { damping: 40, stiffness: 200, mass: 1 }
|
|
54
|
+
* Snappy with minimal overshoot, good for switches
|
|
55
|
+
* Very little bounce, CSS can approximate well
|
|
56
|
+
*/
|
|
57
|
+
springStiff: {
|
|
58
|
+
css: 'cubic-bezier(0.22, 0.68, 0, 1)',
|
|
59
|
+
bezier: [0.22, 0.68, 0, 1] as BezierEasing,
|
|
60
|
+
duration: 200,
|
|
61
|
+
hasOvershoot: false,
|
|
62
|
+
quality: 'good',
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* springBouncy: { damping: 10, stiffness: 180, mass: 1 }
|
|
67
|
+
* Very bouncy, playful feel
|
|
68
|
+
* Significant overshoot that CSS bezier can't fully replicate
|
|
69
|
+
*/
|
|
70
|
+
springBouncy: {
|
|
71
|
+
// Using linear() for better overshoot representation
|
|
72
|
+
// This samples the spring curve at key points
|
|
73
|
+
css: `linear(
|
|
74
|
+
0, 0.178 9.09%, 0.638 18.18%, 0.935 27.27%,
|
|
75
|
+
1.105 36.36%, 1.13 40.91%, 1.114 45.45%,
|
|
76
|
+
1.059 54.55%, 1.012 63.64%, 0.992 72.73%,
|
|
77
|
+
0.997 81.82%, 1.001 90.91%, 1
|
|
78
|
+
)`,
|
|
79
|
+
bezier: [0.34, 1.56, 0.64, 1] as BezierEasing,
|
|
80
|
+
duration: 500,
|
|
81
|
+
hasOvershoot: true,
|
|
82
|
+
quality: 'approximate',
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Approximate damping ratio from spring config
|
|
88
|
+
*
|
|
89
|
+
* ζ = damping / (2 * sqrt(stiffness * mass))
|
|
90
|
+
* - ζ < 1: Underdamped (oscillates/overshoots)
|
|
91
|
+
* - ζ = 1: Critically damped (fastest without overshoot)
|
|
92
|
+
* - ζ > 1: Overdamped (slow, no overshoot)
|
|
93
|
+
*/
|
|
94
|
+
function calculateDampingRatio(config: SpringConfig): number {
|
|
95
|
+
const { damping, stiffness, mass } = config;
|
|
96
|
+
return damping / (2 * Math.sqrt(stiffness * mass));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Calculate approximate duration for spring to settle
|
|
101
|
+
*
|
|
102
|
+
* Uses the formula: duration ≈ (4 * mass) / damping
|
|
103
|
+
* With adjustments for stiffness and a minimum floor
|
|
104
|
+
*/
|
|
105
|
+
function calculateSpringDuration(config: SpringConfig): number {
|
|
106
|
+
const { damping, stiffness, mass } = config;
|
|
107
|
+
|
|
108
|
+
// Natural frequency
|
|
109
|
+
const omega0 = Math.sqrt(stiffness / mass);
|
|
110
|
+
|
|
111
|
+
// Settling time approximation (to 2% of final value)
|
|
112
|
+
// For underdamped: t ≈ 4 / (damping_ratio * omega0)
|
|
113
|
+
// For overdamped: longer settling time
|
|
114
|
+
const dampingRatio = calculateDampingRatio(config);
|
|
115
|
+
|
|
116
|
+
let duration: number;
|
|
117
|
+
if (dampingRatio < 1) {
|
|
118
|
+
// Underdamped - oscillates before settling
|
|
119
|
+
duration = (4 / (dampingRatio * omega0)) * 1000;
|
|
120
|
+
} else {
|
|
121
|
+
// Critically damped or overdamped
|
|
122
|
+
duration = ((4 * mass) / damping) * 1000;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Clamp to reasonable range
|
|
126
|
+
return Math.max(150, Math.min(800, Math.round(duration)));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Generate bezier approximation for a spring config
|
|
131
|
+
*
|
|
132
|
+
* This creates a cubic-bezier that approximates the spring's
|
|
133
|
+
* velocity profile. For underdamped springs, we simulate
|
|
134
|
+
* overshoot by pushing control points beyond [0,1].
|
|
135
|
+
*/
|
|
136
|
+
function generateBezierApproximation(config: SpringConfig): BezierEasing {
|
|
137
|
+
const dampingRatio = calculateDampingRatio(config);
|
|
138
|
+
|
|
139
|
+
if (dampingRatio >= 1) {
|
|
140
|
+
// Critically damped or overdamped - no overshoot
|
|
141
|
+
// Use a deceleration curve
|
|
142
|
+
const decelFactor = Math.min(1, dampingRatio - 0.5);
|
|
143
|
+
return [0.22, 0.68 * decelFactor, 0, 1] as BezierEasing;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Underdamped - has overshoot
|
|
147
|
+
// Calculate overshoot amount (0-1 scale, where 0.3 = 30% overshoot)
|
|
148
|
+
const overshoot = Math.exp((-dampingRatio * Math.PI) / Math.sqrt(1 - dampingRatio * dampingRatio));
|
|
149
|
+
|
|
150
|
+
// Map overshoot to bezier control point
|
|
151
|
+
// Y2 > 1 creates overshoot effect
|
|
152
|
+
const y2 = 1 + Math.min(0.6, overshoot * 0.8);
|
|
153
|
+
|
|
154
|
+
return [0.34, y2, 0.64, 1] as BezierEasing;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Generate CSS linear() easing for springs with significant bounce
|
|
159
|
+
*
|
|
160
|
+
* linear() allows us to define arbitrary easing curves by sampling
|
|
161
|
+
* points along the spring's motion. This gives better accuracy for
|
|
162
|
+
* bouncy springs than cubic-bezier.
|
|
163
|
+
*
|
|
164
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#linear_easing_function
|
|
165
|
+
*/
|
|
166
|
+
function generateLinearEasing(config: SpringConfig, samples: number = 12): string {
|
|
167
|
+
const { damping, stiffness, mass } = config;
|
|
168
|
+
const omega0 = Math.sqrt(stiffness / mass);
|
|
169
|
+
const dampingRatio = calculateDampingRatio(config);
|
|
170
|
+
const duration = calculateSpringDuration(config);
|
|
171
|
+
|
|
172
|
+
// Sample the spring curve
|
|
173
|
+
const points: string[] = [];
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i <= samples; i++) {
|
|
176
|
+
const t = i / samples;
|
|
177
|
+
const time = (t * duration) / 1000; // Convert to seconds
|
|
178
|
+
|
|
179
|
+
let value: number;
|
|
180
|
+
if (dampingRatio < 1) {
|
|
181
|
+
// Underdamped spring equation
|
|
182
|
+
const dampedFreq = omega0 * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
183
|
+
const envelope = Math.exp(-dampingRatio * omega0 * time);
|
|
184
|
+
value = 1 - envelope * Math.cos(dampedFreq * time);
|
|
185
|
+
} else {
|
|
186
|
+
// Critically damped or overdamped
|
|
187
|
+
value = 1 - Math.exp(-omega0 * time) * (1 + omega0 * time);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Format point (value with optional percentage)
|
|
191
|
+
const percent = Math.round(t * 10000) / 100;
|
|
192
|
+
if (i === 0) {
|
|
193
|
+
points.push('0');
|
|
194
|
+
} else if (i === samples) {
|
|
195
|
+
points.push('1');
|
|
196
|
+
} else {
|
|
197
|
+
points.push(`${value.toFixed(3)} ${percent}%`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return `linear(${points.join(', ')})`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Convert a spring configuration to CSS-compatible values
|
|
206
|
+
*
|
|
207
|
+
* Analyzes the spring parameters and generates the best possible
|
|
208
|
+
* CSS approximation, choosing between cubic-bezier and linear()
|
|
209
|
+
* based on the spring's characteristics.
|
|
210
|
+
*
|
|
211
|
+
* @param config - Spring configuration (damping, stiffness, mass)
|
|
212
|
+
* @returns CSS easing string, bezier fallback, and calculated duration
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* import { approximateSpring } from '@idealyst/theme/animation';
|
|
216
|
+
*
|
|
217
|
+
* const result = approximateSpring({ damping: 15, stiffness: 200, mass: 1 });
|
|
218
|
+
* // => {
|
|
219
|
+
* // css: 'cubic-bezier(0.34, 1.4, 0.64, 1)',
|
|
220
|
+
* // bezier: [0.34, 1.4, 0.64, 1],
|
|
221
|
+
* // duration: 350,
|
|
222
|
+
* // hasOvershoot: true,
|
|
223
|
+
* // quality: 'approximate'
|
|
224
|
+
* // }
|
|
225
|
+
*/
|
|
226
|
+
export function approximateSpring(config: SpringConfig): SpringApproximation {
|
|
227
|
+
const dampingRatio = calculateDampingRatio(config);
|
|
228
|
+
const duration = calculateSpringDuration(config);
|
|
229
|
+
const bezier = generateBezierApproximation(config);
|
|
230
|
+
const hasOvershoot = dampingRatio < 1;
|
|
231
|
+
|
|
232
|
+
// Determine quality and best CSS representation
|
|
233
|
+
let css: string;
|
|
234
|
+
let quality: SpringApproximation['quality'];
|
|
235
|
+
|
|
236
|
+
if (dampingRatio >= 0.9) {
|
|
237
|
+
// Nearly critically damped - bezier is accurate
|
|
238
|
+
css = `cubic-bezier(${bezier.join(', ')})`;
|
|
239
|
+
quality = 'good';
|
|
240
|
+
} else if (dampingRatio >= 0.5) {
|
|
241
|
+
// Moderately underdamped - bezier approximates well
|
|
242
|
+
css = `cubic-bezier(${bezier.join(', ')})`;
|
|
243
|
+
quality = 'approximate';
|
|
244
|
+
} else {
|
|
245
|
+
// Heavily underdamped (very bouncy) - use linear() for accuracy
|
|
246
|
+
css = generateLinearEasing(config);
|
|
247
|
+
quality = 'limited';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
css,
|
|
252
|
+
bezier,
|
|
253
|
+
duration,
|
|
254
|
+
hasOvershoot,
|
|
255
|
+
quality,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Get spring approximation by name or config
|
|
261
|
+
*
|
|
262
|
+
* For named springs (spring, springStiff, springBouncy), returns
|
|
263
|
+
* pre-computed approximations. For custom configs, calculates
|
|
264
|
+
* the approximation on demand.
|
|
265
|
+
*
|
|
266
|
+
* @param spring - Spring name or configuration object
|
|
267
|
+
* @returns CSS-compatible spring approximation
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* // Named spring
|
|
271
|
+
* const stiff = getSpringApproximation('springStiff');
|
|
272
|
+
*
|
|
273
|
+
* // Custom config
|
|
274
|
+
* const custom = getSpringApproximation({ damping: 20, stiffness: 300, mass: 1 });
|
|
275
|
+
*/
|
|
276
|
+
export function getSpringApproximation(
|
|
277
|
+
spring: keyof typeof springApproximations | SpringConfig
|
|
278
|
+
): SpringApproximation {
|
|
279
|
+
if (typeof spring === 'string') {
|
|
280
|
+
return springApproximations[spring] ?? springApproximations.spring;
|
|
281
|
+
}
|
|
282
|
+
return approximateSpring(spring);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Check if a CSS easing uses the linear() function
|
|
287
|
+
*
|
|
288
|
+
* Useful for feature detection since linear() has limited browser support.
|
|
289
|
+
* Falls back to bezier approximation if needed.
|
|
290
|
+
*/
|
|
291
|
+
export function usesLinearEasing(css: string): boolean {
|
|
292
|
+
return css.startsWith('linear(');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Get fallback CSS for browsers without linear() support
|
|
297
|
+
*
|
|
298
|
+
* @param approximation - Spring approximation result
|
|
299
|
+
* @returns CSS cubic-bezier string
|
|
300
|
+
*/
|
|
301
|
+
export function getLinearFallback(approximation: SpringApproximation): string {
|
|
302
|
+
return `cubic-bezier(${approximation.bezier.join(', ')})`;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Check if linear() easing is supported in the current environment
|
|
307
|
+
*
|
|
308
|
+
* linear() was added in Chrome 113, Firefox 112, Safari 17.2
|
|
309
|
+
*/
|
|
310
|
+
export function isLinearEasingSupported(): boolean {
|
|
311
|
+
if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
return CSS.supports('animation-timing-function', 'linear(0, 1)');
|
|
315
|
+
}
|
|
@@ -15,6 +15,13 @@ import type {
|
|
|
15
15
|
AnimationDirection,
|
|
16
16
|
AnimationFillMode,
|
|
17
17
|
} from './types';
|
|
18
|
+
import {
|
|
19
|
+
springApproximations,
|
|
20
|
+
getSpringApproximation,
|
|
21
|
+
isLinearEasingSupported,
|
|
22
|
+
getLinearFallback,
|
|
23
|
+
type SpringApproximation,
|
|
24
|
+
} from './springApproximation';
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
27
|
* Resolve a duration value to milliseconds
|
|
@@ -28,16 +35,98 @@ export function resolveDuration(duration: Duration): number {
|
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
37
|
* Resolve an easing key to CSS string
|
|
38
|
+
*
|
|
39
|
+
* For spring easings, returns an approximated CSS easing that
|
|
40
|
+
* tries to match the spring's feel as closely as possible.
|
|
31
41
|
*/
|
|
32
42
|
export function resolveEasing(easing: EasingKey): string {
|
|
33
43
|
const easingConfig = easings[easing];
|
|
34
|
-
|
|
44
|
+
|
|
45
|
+
// Handle spring configs with smart approximation
|
|
35
46
|
if ('damping' in easingConfig) {
|
|
36
|
-
|
|
47
|
+
const approx = getSpringApproximation(easing as keyof typeof springApproximations);
|
|
48
|
+
|
|
49
|
+
// Check if linear() is supported for bouncy springs
|
|
50
|
+
if (approx.css.startsWith('linear(') && !isLinearEasingSupported()) {
|
|
51
|
+
return getLinearFallback(approx);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return approx.css;
|
|
37
55
|
}
|
|
56
|
+
|
|
38
57
|
return easingConfig.css;
|
|
39
58
|
}
|
|
40
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Resolve an easing key to both CSS string and duration
|
|
62
|
+
*
|
|
63
|
+
* For spring easings, this returns the approximated CSS easing
|
|
64
|
+
* along with a calculated duration that matches the spring's
|
|
65
|
+
* settling time. This provides better spring approximation than
|
|
66
|
+
* using resolveEasing alone.
|
|
67
|
+
*
|
|
68
|
+
* @param easing - Easing token key
|
|
69
|
+
* @param baseDuration - Base duration (used for non-spring easings)
|
|
70
|
+
* @returns Object with CSS easing and recommended duration
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Non-spring easing - uses provided duration
|
|
74
|
+
* resolveEasingWithDuration('easeOut', 200)
|
|
75
|
+
* // => { css: 'ease-out', duration: 200 }
|
|
76
|
+
*
|
|
77
|
+
* // Spring easing - calculates optimal duration
|
|
78
|
+
* resolveEasingWithDuration('spring', 200)
|
|
79
|
+
* // => { css: 'cubic-bezier(0.34, 1.4, 0.64, 1)', duration: 350 }
|
|
80
|
+
*/
|
|
81
|
+
export function resolveEasingWithDuration(
|
|
82
|
+
easing: EasingKey,
|
|
83
|
+
baseDuration: number
|
|
84
|
+
): { css: string; duration: number } {
|
|
85
|
+
const easingConfig = easings[easing];
|
|
86
|
+
|
|
87
|
+
// Handle spring configs with smart approximation
|
|
88
|
+
if ('damping' in easingConfig) {
|
|
89
|
+
const approx = getSpringApproximation(easing as keyof typeof springApproximations);
|
|
90
|
+
|
|
91
|
+
let css = approx.css;
|
|
92
|
+
if (approx.css.startsWith('linear(') && !isLinearEasingSupported()) {
|
|
93
|
+
css = getLinearFallback(approx);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
css,
|
|
98
|
+
duration: approx.duration,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
css: easingConfig.css,
|
|
104
|
+
duration: baseDuration,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Check if an easing is a spring type
|
|
110
|
+
*/
|
|
111
|
+
export function isSpringEasing(easing: EasingKey): boolean {
|
|
112
|
+
const easingConfig = easings[easing];
|
|
113
|
+
return 'damping' in easingConfig;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get detailed spring approximation info for an easing
|
|
118
|
+
*
|
|
119
|
+
* Returns null for non-spring easings. For springs, returns
|
|
120
|
+
* the full approximation data including quality assessment.
|
|
121
|
+
*/
|
|
122
|
+
export function getSpringInfo(easing: EasingKey): SpringApproximation | null {
|
|
123
|
+
const easingConfig = easings[easing];
|
|
124
|
+
if (!('damping' in easingConfig)) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return getSpringApproximation(easing as keyof typeof springApproximations);
|
|
128
|
+
}
|
|
129
|
+
|
|
41
130
|
/**
|
|
42
131
|
* Generate a CSS transition string from tokens
|
|
43
132
|
*
|
package/src/colorScheme.ts
CHANGED
|
@@ -48,6 +48,6 @@ export const ThemeSettings = {
|
|
|
48
48
|
UnistylesRuntime.setRootViewBackgroundColor(
|
|
49
49
|
contentColor === 'dark' ? '#000000' : '#ffffff'
|
|
50
50
|
);
|
|
51
|
-
UnistylesRuntime.statusBar.setStyle(contentColor === 'dark' ? 'light' : 'dark', animated);
|
|
51
|
+
UnistylesRuntime.statusBar.setStyle((contentColor === 'dark' ? 'light' : 'dark') as any, animated);
|
|
52
52
|
},
|
|
53
53
|
};
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,9 @@ export * from './useResponsiveStyle';
|
|
|
28
28
|
// Color scheme utilities
|
|
29
29
|
export * from './colorScheme';
|
|
30
30
|
|
|
31
|
+
// Theme hook
|
|
32
|
+
export { useTheme } from './useTheme';
|
|
33
|
+
|
|
31
34
|
// Style props hook (platform-specific via .native.ts)
|
|
32
35
|
export { useStyleProps, type StyleProps } from './useStyleProps';
|
|
33
36
|
|
package/src/styleBuilder.ts
CHANGED
package/src/useTheme.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useUnistyles } from 'react-native-unistyles';
|
|
2
|
+
import type { Theme } from './theme';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook to access the current theme.
|
|
6
|
+
*
|
|
7
|
+
* Returns the current theme object with full TypeScript inference
|
|
8
|
+
* based on your registered theme type.
|
|
9
|
+
*
|
|
10
|
+
* @returns The current theme object
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { useTheme } from '@idealyst/theme';
|
|
15
|
+
*
|
|
16
|
+
* function MyComponent() {
|
|
17
|
+
* const theme = useTheme();
|
|
18
|
+
*
|
|
19
|
+
* return (
|
|
20
|
+
* <View style={{ backgroundColor: theme.colors.surface.primary }}>
|
|
21
|
+
* <Text style={{ color: theme.colors.text.primary }}>
|
|
22
|
+
* Hello
|
|
23
|
+
* </Text>
|
|
24
|
+
* </View>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Access intent colors
|
|
32
|
+
* const theme = useTheme();
|
|
33
|
+
* const primaryColor = theme.intents.primary.primary;
|
|
34
|
+
* const successLight = theme.intents.success.light;
|
|
35
|
+
*
|
|
36
|
+
* // Access sizes
|
|
37
|
+
* const buttonPadding = theme.sizes.button.md.paddingHorizontal;
|
|
38
|
+
*
|
|
39
|
+
* // Access radii
|
|
40
|
+
* const borderRadius = theme.radii.md;
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function useTheme(): Theme {
|
|
44
|
+
const { theme } = useUnistyles();
|
|
45
|
+
return theme as Theme;
|
|
46
|
+
}
|