@idealyst/theme 1.2.29 → 1.2.30
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 +7 -1
- package/src/animation/index.native.ts +62 -0
- package/src/animation/index.ts +68 -0
- package/src/animation/tokens.ts +145 -0
- package/src/animation/transitions.native.ts +219 -0
- package/src/animation/transitions.ts +293 -0
- package/src/animation/types.ts +80 -0
- package/src/builder.ts +3 -0
- package/src/components/CLAUDE.md +1 -1
- package/src/config/generator.ts +2 -2
- package/src/darkTheme.ts +1 -1
- package/src/index.ts +5 -1
- package/src/lightTheme.ts +8 -1
- package/src/styleBuilder.ts +1 -0
- package/src/theme/extensions.ts +2 -1
- package/src/theme/structures.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/theme",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.30",
|
|
4
4
|
"description": "Theming system for Idealyst Framework",
|
|
5
5
|
"readme": "README.md",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -50,6 +50,12 @@
|
|
|
50
50
|
"import": "./src/darkTheme.ts",
|
|
51
51
|
"require": "./src/darkTheme.ts",
|
|
52
52
|
"types": "./src/darkTheme.ts"
|
|
53
|
+
},
|
|
54
|
+
"./animation": {
|
|
55
|
+
"native": "./src/animation/index.native.ts",
|
|
56
|
+
"import": "./src/animation/index.ts",
|
|
57
|
+
"require": "./src/animation/index.ts",
|
|
58
|
+
"types": "./src/animation/index.ts"
|
|
53
59
|
}
|
|
54
60
|
},
|
|
55
61
|
"scripts": {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation module for @idealyst/theme (Native)
|
|
3
|
+
*
|
|
4
|
+
* This module provides animation tokens and utilities for creating
|
|
5
|
+
* consistent animations across web and native platforms.
|
|
6
|
+
*
|
|
7
|
+
* Native-specific exports include Reanimated-compatible utilities.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Import tokens
|
|
11
|
+
* import { durations, easings, presets } from '@idealyst/theme/animation';
|
|
12
|
+
*
|
|
13
|
+
* // Import native utilities
|
|
14
|
+
* import { timingConfig, springConfig, animationConfig } from '@idealyst/theme/animation';
|
|
15
|
+
*
|
|
16
|
+
* // Use with Reanimated
|
|
17
|
+
* import { withTiming, withSpring, Easing } from 'react-native-reanimated';
|
|
18
|
+
*
|
|
19
|
+
* const config = timingConfig('normal', 'easeOut');
|
|
20
|
+
* value.value = withTiming(target, {
|
|
21
|
+
* duration: config.duration,
|
|
22
|
+
* easing: Easing.bezier(...config.easing),
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// Export tokens
|
|
27
|
+
export { durations, easings, presets } from './tokens';
|
|
28
|
+
export type { DurationKey, EasingKey, PresetKey } from './tokens';
|
|
29
|
+
|
|
30
|
+
// Export types
|
|
31
|
+
export type {
|
|
32
|
+
Duration,
|
|
33
|
+
Easing,
|
|
34
|
+
BezierEasing,
|
|
35
|
+
SpringConfig,
|
|
36
|
+
CSSEasing,
|
|
37
|
+
AnimationConfig,
|
|
38
|
+
TransitionConfig,
|
|
39
|
+
Keyframes,
|
|
40
|
+
KeyframeAnimationConfig,
|
|
41
|
+
AnimationIterations,
|
|
42
|
+
AnimationDirection,
|
|
43
|
+
AnimationFillMode,
|
|
44
|
+
SpringType,
|
|
45
|
+
TimingAnimationConfig,
|
|
46
|
+
PlatformAnimationOptions,
|
|
47
|
+
GradientAnimation,
|
|
48
|
+
GradientBorderConfig,
|
|
49
|
+
} from './types';
|
|
50
|
+
|
|
51
|
+
// Export native utilities
|
|
52
|
+
export {
|
|
53
|
+
resolveDuration,
|
|
54
|
+
resolveEasingBezier,
|
|
55
|
+
isSpringEasing,
|
|
56
|
+
timingConfig,
|
|
57
|
+
springConfig,
|
|
58
|
+
animationConfig,
|
|
59
|
+
presetConfig,
|
|
60
|
+
delayMs,
|
|
61
|
+
sequenceSteps,
|
|
62
|
+
} from './transitions.native';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation module for @idealyst/theme
|
|
3
|
+
*
|
|
4
|
+
* This module provides animation tokens and utilities for creating
|
|
5
|
+
* consistent animations across web and native platforms.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Import tokens
|
|
9
|
+
* import { durations, easings, presets } from '@idealyst/theme/animation';
|
|
10
|
+
*
|
|
11
|
+
* // Import web utilities
|
|
12
|
+
* import { cssTransition, cssPreset, cssKeyframes } from '@idealyst/theme/animation';
|
|
13
|
+
*
|
|
14
|
+
* // Import native utilities (in .native.ts files)
|
|
15
|
+
* import { timingConfig, springConfig } from '@idealyst/theme/animation';
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Export tokens
|
|
19
|
+
export { durations, easings, presets } from './tokens';
|
|
20
|
+
export type { DurationKey, EasingKey, PresetKey } from './tokens';
|
|
21
|
+
|
|
22
|
+
// Export types
|
|
23
|
+
export type {
|
|
24
|
+
Duration,
|
|
25
|
+
Easing,
|
|
26
|
+
BezierEasing,
|
|
27
|
+
SpringConfig,
|
|
28
|
+
CSSEasing,
|
|
29
|
+
AnimationConfig,
|
|
30
|
+
TransitionConfig,
|
|
31
|
+
Keyframes,
|
|
32
|
+
KeyframeAnimationConfig,
|
|
33
|
+
AnimationIterations,
|
|
34
|
+
AnimationDirection,
|
|
35
|
+
AnimationFillMode,
|
|
36
|
+
SpringType,
|
|
37
|
+
TimingAnimationConfig,
|
|
38
|
+
PlatformAnimationOptions,
|
|
39
|
+
GradientAnimation,
|
|
40
|
+
GradientBorderConfig,
|
|
41
|
+
} from './types';
|
|
42
|
+
|
|
43
|
+
// Export web utilities
|
|
44
|
+
export {
|
|
45
|
+
resolveDuration,
|
|
46
|
+
resolveEasing,
|
|
47
|
+
cssTransition,
|
|
48
|
+
cssPreset,
|
|
49
|
+
cssKeyframes,
|
|
50
|
+
cssAnimation,
|
|
51
|
+
gradientPropertyCSS,
|
|
52
|
+
injectGradientCSS,
|
|
53
|
+
conicSpinnerStyle,
|
|
54
|
+
pulseGradientStyle,
|
|
55
|
+
} from './transitions';
|
|
56
|
+
|
|
57
|
+
// Export native utilities (these are also exported from index.native.ts)
|
|
58
|
+
// Including here allows type-checking in monorepo without platform resolution
|
|
59
|
+
export {
|
|
60
|
+
resolveEasingBezier,
|
|
61
|
+
isSpringEasing,
|
|
62
|
+
timingConfig,
|
|
63
|
+
springConfig,
|
|
64
|
+
animationConfig,
|
|
65
|
+
presetConfig,
|
|
66
|
+
delayMs,
|
|
67
|
+
sequenceSteps,
|
|
68
|
+
} from './transitions.native';
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation tokens for @idealyst/theme
|
|
3
|
+
*
|
|
4
|
+
* These tokens provide consistent animation timing across the framework.
|
|
5
|
+
* Use these instead of hardcoded values for consistency and maintainability.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Duration tokens in milliseconds
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { durations } from '@idealyst/theme/animation';
|
|
13
|
+
*
|
|
14
|
+
* // Use in CSS transition
|
|
15
|
+
* transition: `opacity ${durations.normal}ms ease`
|
|
16
|
+
*
|
|
17
|
+
* // Use with Reanimated
|
|
18
|
+
* withTiming(value, { duration: durations.fast })
|
|
19
|
+
*/
|
|
20
|
+
export const durations = {
|
|
21
|
+
/** 0ms - No animation, instant change */
|
|
22
|
+
instant: 0,
|
|
23
|
+
/** 100ms - Micro-interactions: hover, focus, press feedback */
|
|
24
|
+
fast: 100,
|
|
25
|
+
/** 200ms - Standard state transitions: toggle, selection changes */
|
|
26
|
+
normal: 200,
|
|
27
|
+
/** 300ms - Complex transitions: expand/collapse, progress bars */
|
|
28
|
+
slow: 300,
|
|
29
|
+
/** 500ms - Entrance animations: modals, toasts appearing */
|
|
30
|
+
slower: 500,
|
|
31
|
+
/** 750ms - Extended animations: skeleton pulse, loading states */
|
|
32
|
+
slowest: 750,
|
|
33
|
+
/** 1000ms - Loop animations: spinners, continuous indicators */
|
|
34
|
+
loop: 1000,
|
|
35
|
+
} as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Easing tokens with both CSS string and bezier values
|
|
39
|
+
*
|
|
40
|
+
* CSS easings include both a CSS string for web transitions
|
|
41
|
+
* and bezier curve values for Reanimated's Easing.bezier()
|
|
42
|
+
*
|
|
43
|
+
* Spring easings are native-only and include damping/stiffness/mass
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* import { easings } from '@idealyst/theme/animation';
|
|
47
|
+
*
|
|
48
|
+
* // Web: use CSS string
|
|
49
|
+
* transition: `opacity 200ms ${easings.easeOut.css}`
|
|
50
|
+
*
|
|
51
|
+
* // Native: use bezier values
|
|
52
|
+
* Easing.bezier(...easings.easeOut.bezier)
|
|
53
|
+
*
|
|
54
|
+
* // Native spring
|
|
55
|
+
* withSpring(value, easings.spring)
|
|
56
|
+
*/
|
|
57
|
+
export const easings = {
|
|
58
|
+
// Standard CSS easings
|
|
59
|
+
/** Linear - constant speed, no acceleration */
|
|
60
|
+
linear: { css: 'linear', bezier: [0, 0, 1, 1] as const },
|
|
61
|
+
/** Ease - slight acceleration at start, deceleration at end */
|
|
62
|
+
ease: { css: 'ease', bezier: [0.25, 0.1, 0.25, 1] as const },
|
|
63
|
+
/** Ease-in - starts slow, accelerates */
|
|
64
|
+
easeIn: { css: 'ease-in', bezier: [0.42, 0, 1, 1] as const },
|
|
65
|
+
/** Ease-out - starts fast, decelerates (most common for UI) */
|
|
66
|
+
easeOut: { css: 'ease-out', bezier: [0, 0, 0.58, 1] as const },
|
|
67
|
+
/** Ease-in-out - symmetric acceleration and deceleration */
|
|
68
|
+
easeInOut: { css: 'ease-in-out', bezier: [0.42, 0, 0.58, 1] as const },
|
|
69
|
+
|
|
70
|
+
// Material Design easings
|
|
71
|
+
/** Standard - Material Design standard easing, balanced feel */
|
|
72
|
+
standard: { css: 'cubic-bezier(0.4, 0, 0.2, 1)', bezier: [0.4, 0, 0.2, 1] as const },
|
|
73
|
+
/** Decelerate - Material Design deceleration, for entering elements */
|
|
74
|
+
decelerate: { css: 'cubic-bezier(0, 0, 0.2, 1)', bezier: [0, 0, 0.2, 1] as const },
|
|
75
|
+
/** Accelerate - Material Design acceleration, for exiting elements */
|
|
76
|
+
accelerate: { css: 'cubic-bezier(0.4, 0, 1, 1)', bezier: [0.4, 0, 1, 1] as const },
|
|
77
|
+
|
|
78
|
+
// Spring configurations (native only - used with withSpring)
|
|
79
|
+
/** Spring - balanced spring, good for toggles and state changes */
|
|
80
|
+
spring: { damping: 15, stiffness: 200, mass: 1 } as const,
|
|
81
|
+
/** Spring stiff - less bounce, snappier feel, good for switches */
|
|
82
|
+
springStiff: { damping: 40, stiffness: 200, mass: 1 } as const,
|
|
83
|
+
/** Spring bouncy - more bounce, playful feel, good for buttons */
|
|
84
|
+
springBouncy: { damping: 10, stiffness: 180, mass: 1 } as const,
|
|
85
|
+
} as const;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Animation presets for common use cases
|
|
89
|
+
*
|
|
90
|
+
* These combine duration and easing for specific interaction patterns.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* import { presets } from '@idealyst/theme/animation';
|
|
94
|
+
*
|
|
95
|
+
* // Use for hover effects
|
|
96
|
+
* _web: { transition: cssPreset(presets.hover) }
|
|
97
|
+
*/
|
|
98
|
+
export const presets = {
|
|
99
|
+
// Micro-interactions
|
|
100
|
+
/** Hover effect - fast, subtle */
|
|
101
|
+
hover: { duration: 'fast' as const, easing: 'ease' as const },
|
|
102
|
+
/** Press/active feedback - fast, ease-out */
|
|
103
|
+
press: { duration: 'fast' as const, easing: 'easeOut' as const },
|
|
104
|
+
/** Focus ring - normal speed */
|
|
105
|
+
focus: { duration: 'normal' as const, easing: 'ease' as const },
|
|
106
|
+
|
|
107
|
+
// State changes
|
|
108
|
+
/** Toggle/switch - normal with spring on native */
|
|
109
|
+
toggle: { duration: 'normal' as const, easing: 'spring' as const },
|
|
110
|
+
/** Selection change - normal, standard easing */
|
|
111
|
+
select: { duration: 'normal' as const, easing: 'standard' as const },
|
|
112
|
+
|
|
113
|
+
// Expand/collapse
|
|
114
|
+
/** Expand content - slow, standard easing */
|
|
115
|
+
expand: { duration: 'slow' as const, easing: 'standard' as const },
|
|
116
|
+
/** Collapse content - slightly faster than expand */
|
|
117
|
+
collapse: { duration: 'normal' as const, easing: 'accelerate' as const },
|
|
118
|
+
|
|
119
|
+
// Entrance/exit
|
|
120
|
+
/** Fade in - normal, decelerate */
|
|
121
|
+
fadeIn: { duration: 'normal' as const, easing: 'decelerate' as const },
|
|
122
|
+
/** Fade out - fast, accelerate */
|
|
123
|
+
fadeOut: { duration: 'fast' as const, easing: 'accelerate' as const },
|
|
124
|
+
/** Scale in (modal, dialog) - slower, decelerate */
|
|
125
|
+
scaleIn: { duration: 'slower' as const, easing: 'decelerate' as const },
|
|
126
|
+
/** Scale out - normal, accelerate */
|
|
127
|
+
scaleOut: { duration: 'normal' as const, easing: 'accelerate' as const },
|
|
128
|
+
/** Slide in - slow, standard */
|
|
129
|
+
slideIn: { duration: 'slow' as const, easing: 'standard' as const },
|
|
130
|
+
/** Slide out - normal, accelerate */
|
|
131
|
+
slideOut: { duration: 'normal' as const, easing: 'accelerate' as const },
|
|
132
|
+
|
|
133
|
+
// Loading/continuous
|
|
134
|
+
/** Spinner rotation - 1s linear loop */
|
|
135
|
+
spin: { duration: 'loop' as const, easing: 'linear' as const, iterations: 'infinite' as const },
|
|
136
|
+
/** Pulse effect - slowest, ease-in-out loop */
|
|
137
|
+
pulse: { duration: 'slowest' as const, easing: 'easeInOut' as const, iterations: 'infinite' as const },
|
|
138
|
+
/** Skeleton wave - slower than pulse */
|
|
139
|
+
wave: { duration: 1500 as const, easing: 'easeInOut' as const, iterations: 'infinite' as const },
|
|
140
|
+
} as const;
|
|
141
|
+
|
|
142
|
+
// Type exports for convenience
|
|
143
|
+
export type DurationKey = keyof typeof durations;
|
|
144
|
+
export type EasingKey = keyof typeof easings;
|
|
145
|
+
export type PresetKey = keyof typeof presets;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native-specific animation utilities
|
|
3
|
+
*
|
|
4
|
+
* These utilities generate Reanimated-compatible configurations
|
|
5
|
+
* from animation tokens for use in React Native animations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { durations, easings } from './tokens';
|
|
9
|
+
import type { DurationKey, EasingKey, PresetKey } from './tokens';
|
|
10
|
+
import type { Duration, SpringType, BezierEasing } from './types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a duration value to milliseconds
|
|
14
|
+
*/
|
|
15
|
+
export function resolveDuration(duration: Duration): number {
|
|
16
|
+
if (typeof duration === 'number') {
|
|
17
|
+
return duration;
|
|
18
|
+
}
|
|
19
|
+
return durations[duration];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolve an easing key to bezier curve values
|
|
24
|
+
* Returns bezier array for use with Easing.bezier()
|
|
25
|
+
*
|
|
26
|
+
* Note: Spring easings return a fallback bezier curve.
|
|
27
|
+
* For actual spring behavior, use springConfig() instead.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveEasingBezier(easing: EasingKey): BezierEasing {
|
|
30
|
+
const easingConfig = easings[easing];
|
|
31
|
+
// Spring configs don't have bezier equivalent, fall back to ease-out
|
|
32
|
+
if ('damping' in easingConfig) {
|
|
33
|
+
return easings.easeOut.bezier;
|
|
34
|
+
}
|
|
35
|
+
return easingConfig.bezier;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Check if an easing is a spring configuration
|
|
40
|
+
*/
|
|
41
|
+
export function isSpringEasing(easing: EasingKey): easing is SpringType {
|
|
42
|
+
return easing === 'spring' || easing === 'springStiff' || easing === 'springBouncy';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get Reanimated withTiming configuration from tokens
|
|
47
|
+
*
|
|
48
|
+
* Use with Reanimated's withTiming() function.
|
|
49
|
+
* The returned config includes duration and a bezier easing function creator.
|
|
50
|
+
*
|
|
51
|
+
* @param duration - Duration token key or milliseconds
|
|
52
|
+
* @param easing - Easing token key (spring easings fall back to easeOut)
|
|
53
|
+
* @returns Configuration object with duration and easing bezier values
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* import { timingConfig } from '@idealyst/theme/animation';
|
|
57
|
+
* import { withTiming, Easing } from 'react-native-reanimated';
|
|
58
|
+
*
|
|
59
|
+
* const config = timingConfig('normal', 'easeOut');
|
|
60
|
+
* // => { duration: 200, easing: [0, 0, 0.58, 1] }
|
|
61
|
+
*
|
|
62
|
+
* // Use with Reanimated
|
|
63
|
+
* animatedValue.value = withTiming(targetValue, {
|
|
64
|
+
* duration: config.duration,
|
|
65
|
+
* easing: Easing.bezier(...config.easing),
|
|
66
|
+
* });
|
|
67
|
+
*/
|
|
68
|
+
export function timingConfig(
|
|
69
|
+
duration: Duration = 'normal',
|
|
70
|
+
easing: EasingKey = 'easeOut'
|
|
71
|
+
): { duration: number; easing: BezierEasing } {
|
|
72
|
+
return {
|
|
73
|
+
duration: resolveDuration(duration),
|
|
74
|
+
easing: resolveEasingBezier(easing),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get Reanimated withSpring configuration from tokens
|
|
80
|
+
*
|
|
81
|
+
* Use with Reanimated's withSpring() function.
|
|
82
|
+
*
|
|
83
|
+
* @param type - Spring type: 'spring', 'springStiff', or 'springBouncy'
|
|
84
|
+
* @returns Spring configuration object
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* import { springConfig } from '@idealyst/theme/animation';
|
|
88
|
+
* import { withSpring } from 'react-native-reanimated';
|
|
89
|
+
*
|
|
90
|
+
* const config = springConfig('springStiff');
|
|
91
|
+
* // => { damping: 40, stiffness: 200, mass: 1 }
|
|
92
|
+
*
|
|
93
|
+
* // Use with Reanimated
|
|
94
|
+
* animatedValue.value = withSpring(targetValue, config);
|
|
95
|
+
*/
|
|
96
|
+
export function springConfig(
|
|
97
|
+
type: SpringType = 'spring'
|
|
98
|
+
): { damping: number; stiffness: number; mass: number } {
|
|
99
|
+
const config = easings[type];
|
|
100
|
+
return {
|
|
101
|
+
damping: config.damping,
|
|
102
|
+
stiffness: config.stiffness,
|
|
103
|
+
mass: config.mass,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get animation configuration based on easing type
|
|
109
|
+
*
|
|
110
|
+
* Automatically returns spring config for spring easings,
|
|
111
|
+
* or timing config for bezier easings.
|
|
112
|
+
*
|
|
113
|
+
* @param duration - Duration token key or milliseconds
|
|
114
|
+
* @param easing - Easing token key
|
|
115
|
+
* @returns Either spring config or timing config
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* import { animationConfig } from '@idealyst/theme/animation';
|
|
119
|
+
*
|
|
120
|
+
* // Returns spring config
|
|
121
|
+
* animationConfig('normal', 'spring')
|
|
122
|
+
* // => { type: 'spring', config: { damping: 15, stiffness: 200, mass: 1 } }
|
|
123
|
+
*
|
|
124
|
+
* // Returns timing config
|
|
125
|
+
* animationConfig('normal', 'easeOut')
|
|
126
|
+
* // => { type: 'timing', config: { duration: 200, easing: [0, 0, 0.58, 1] } }
|
|
127
|
+
*/
|
|
128
|
+
export function animationConfig(
|
|
129
|
+
duration: Duration = 'normal',
|
|
130
|
+
easing: EasingKey = 'easeOut'
|
|
131
|
+
):
|
|
132
|
+
| { type: 'spring'; config: ReturnType<typeof springConfig> }
|
|
133
|
+
| { type: 'timing'; config: ReturnType<typeof timingConfig> } {
|
|
134
|
+
if (isSpringEasing(easing)) {
|
|
135
|
+
return {
|
|
136
|
+
type: 'spring',
|
|
137
|
+
config: springConfig(easing),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
type: 'timing',
|
|
142
|
+
config: timingConfig(duration, easing),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get preset animation configuration for native
|
|
148
|
+
*
|
|
149
|
+
* @param presetName - Preset key
|
|
150
|
+
* @returns Animation configuration for the preset
|
|
151
|
+
*/
|
|
152
|
+
export function presetConfig(presetName: keyof typeof import('./tokens').presets) {
|
|
153
|
+
const { presets } = require('./tokens');
|
|
154
|
+
const preset = presets[presetName];
|
|
155
|
+
return animationConfig(preset.duration, preset.easing);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Helper to create a delay configuration
|
|
160
|
+
*
|
|
161
|
+
* Use with Reanimated's withDelay() function.
|
|
162
|
+
*
|
|
163
|
+
* @param delay - Delay in milliseconds or duration token
|
|
164
|
+
* @returns Delay in milliseconds
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* import { delayMs } from '@idealyst/theme/animation';
|
|
168
|
+
* import { withDelay, withTiming } from 'react-native-reanimated';
|
|
169
|
+
*
|
|
170
|
+
* // Using duration token
|
|
171
|
+
* animatedValue.value = withDelay(
|
|
172
|
+
* delayMs('normal'),
|
|
173
|
+
* withTiming(targetValue, timingConfig('fast', 'easeOut'))
|
|
174
|
+
* );
|
|
175
|
+
*/
|
|
176
|
+
export function delayMs(delay: Duration): number {
|
|
177
|
+
return resolveDuration(delay);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create a sequence of timing animations
|
|
182
|
+
*
|
|
183
|
+
* Helper for creating withSequence() compatible values.
|
|
184
|
+
*
|
|
185
|
+
* @param steps - Array of { value, duration?, easing? } objects
|
|
186
|
+
* @returns Array of animation configurations
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* import { sequenceSteps } from '@idealyst/theme/animation';
|
|
190
|
+
*
|
|
191
|
+
* const steps = sequenceSteps([
|
|
192
|
+
* { value: 0 },
|
|
193
|
+
* { value: 1, duration: 'normal', easing: 'easeOut' },
|
|
194
|
+
* { value: 0.5, duration: 'fast' },
|
|
195
|
+
* ]);
|
|
196
|
+
*
|
|
197
|
+
* // Use with Reanimated
|
|
198
|
+
* animatedValue.value = withSequence(
|
|
199
|
+
* ...steps.map(s => withTiming(s.value, {
|
|
200
|
+
* duration: s.config.duration,
|
|
201
|
+
* easing: Easing.bezier(...s.config.easing)
|
|
202
|
+
* }))
|
|
203
|
+
* );
|
|
204
|
+
*/
|
|
205
|
+
export function sequenceSteps(
|
|
206
|
+
steps: Array<{
|
|
207
|
+
value: number;
|
|
208
|
+
duration?: Duration;
|
|
209
|
+
easing?: EasingKey;
|
|
210
|
+
}>
|
|
211
|
+
): Array<{
|
|
212
|
+
value: number;
|
|
213
|
+
config: ReturnType<typeof timingConfig>;
|
|
214
|
+
}> {
|
|
215
|
+
return steps.map((step) => ({
|
|
216
|
+
value: step.value,
|
|
217
|
+
config: timingConfig(step.duration ?? 'normal', step.easing ?? 'easeOut'),
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web-specific animation utilities
|
|
3
|
+
*
|
|
4
|
+
* These utilities generate CSS transition and animation strings
|
|
5
|
+
* from animation tokens for use in web stylesheets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { durations, easings, presets } from './tokens';
|
|
9
|
+
import type { DurationKey, EasingKey, PresetKey } from './tokens';
|
|
10
|
+
import type {
|
|
11
|
+
Duration,
|
|
12
|
+
Keyframes,
|
|
13
|
+
KeyframeAnimationConfig,
|
|
14
|
+
AnimationIterations,
|
|
15
|
+
AnimationDirection,
|
|
16
|
+
AnimationFillMode,
|
|
17
|
+
} from './types';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a duration value to milliseconds
|
|
21
|
+
*/
|
|
22
|
+
export function resolveDuration(duration: Duration): number {
|
|
23
|
+
if (typeof duration === 'number') {
|
|
24
|
+
return duration;
|
|
25
|
+
}
|
|
26
|
+
return durations[duration];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolve an easing key to CSS string
|
|
31
|
+
*/
|
|
32
|
+
export function resolveEasing(easing: EasingKey): string {
|
|
33
|
+
const easingConfig = easings[easing];
|
|
34
|
+
// Spring configs don't have CSS equivalent, fall back to ease-out
|
|
35
|
+
if ('damping' in easingConfig) {
|
|
36
|
+
return 'ease-out';
|
|
37
|
+
}
|
|
38
|
+
return easingConfig.css;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate a CSS transition string from tokens
|
|
43
|
+
*
|
|
44
|
+
* @param properties - CSS property or array of properties to transition
|
|
45
|
+
* @param duration - Duration token key or milliseconds
|
|
46
|
+
* @param easing - Easing token key
|
|
47
|
+
* @returns CSS transition string
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* import { cssTransition } from '@idealyst/theme/animation';
|
|
51
|
+
*
|
|
52
|
+
* // Single property
|
|
53
|
+
* cssTransition('opacity', 'normal', 'easeOut')
|
|
54
|
+
* // => "opacity 200ms ease-out"
|
|
55
|
+
*
|
|
56
|
+
* // Multiple properties
|
|
57
|
+
* cssTransition(['opacity', 'transform'], 'fast', 'standard')
|
|
58
|
+
* // => "opacity 100ms cubic-bezier(0.4, 0, 0.2, 1), transform 100ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
59
|
+
*
|
|
60
|
+
* // With numeric duration
|
|
61
|
+
* cssTransition('background-color', 150, 'ease')
|
|
62
|
+
* // => "background-color 150ms ease"
|
|
63
|
+
*/
|
|
64
|
+
export function cssTransition(
|
|
65
|
+
properties: string | string[],
|
|
66
|
+
duration: Duration = 'normal',
|
|
67
|
+
easing: EasingKey = 'ease'
|
|
68
|
+
): string {
|
|
69
|
+
const props = Array.isArray(properties) ? properties : [properties];
|
|
70
|
+
const durationMs = resolveDuration(duration);
|
|
71
|
+
const easingValue = resolveEasing(easing);
|
|
72
|
+
|
|
73
|
+
return props.map((prop) => `${prop} ${durationMs}ms ${easingValue}`).join(', ');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Generate a CSS transition string from a preset
|
|
78
|
+
*
|
|
79
|
+
* @param presetName - Preset key from presets
|
|
80
|
+
* @param properties - Optional CSS properties (defaults to 'all')
|
|
81
|
+
* @returns CSS transition string
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* import { cssPreset } from '@idealyst/theme/animation';
|
|
85
|
+
*
|
|
86
|
+
* cssPreset('hover')
|
|
87
|
+
* // => "all 100ms ease"
|
|
88
|
+
*
|
|
89
|
+
* cssPreset('fadeIn', 'opacity')
|
|
90
|
+
* // => "opacity 200ms cubic-bezier(0, 0, 0.2, 1)"
|
|
91
|
+
*/
|
|
92
|
+
export function cssPreset(presetName: PresetKey, properties: string | string[] = 'all'): string {
|
|
93
|
+
const preset = presets[presetName];
|
|
94
|
+
return cssTransition(properties, preset.duration, preset.easing);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Generate CSS @keyframes string
|
|
99
|
+
*
|
|
100
|
+
* @param name - Unique name for the keyframes
|
|
101
|
+
* @param frames - Keyframe definitions
|
|
102
|
+
* @returns CSS @keyframes string
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* import { cssKeyframes } from '@idealyst/theme/animation';
|
|
106
|
+
*
|
|
107
|
+
* const fadeIn = cssKeyframes('fadeIn', {
|
|
108
|
+
* '0%': { opacity: 0 },
|
|
109
|
+
* '100%': { opacity: 1 },
|
|
110
|
+
* });
|
|
111
|
+
* // => "@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }"
|
|
112
|
+
*/
|
|
113
|
+
export function cssKeyframes(name: string, frames: Keyframes): string {
|
|
114
|
+
const frameStrings = Object.entries(frames)
|
|
115
|
+
.map(([key, styles]) => {
|
|
116
|
+
const styleString = Object.entries(styles || {})
|
|
117
|
+
.map(([prop, value]) => {
|
|
118
|
+
// Convert camelCase to kebab-case
|
|
119
|
+
const kebabProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
120
|
+
return `${kebabProp}: ${value}`;
|
|
121
|
+
})
|
|
122
|
+
.join('; ');
|
|
123
|
+
return `${key} { ${styleString}; }`;
|
|
124
|
+
})
|
|
125
|
+
.join(' ');
|
|
126
|
+
|
|
127
|
+
return `@keyframes ${name} { ${frameStrings} }`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Generate CSS animation shorthand string
|
|
132
|
+
*
|
|
133
|
+
* @param name - Animation name (must match @keyframes name)
|
|
134
|
+
* @param config - Animation configuration
|
|
135
|
+
* @returns CSS animation shorthand string
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* import { cssAnimation } from '@idealyst/theme/animation';
|
|
139
|
+
*
|
|
140
|
+
* cssAnimation('fadeIn', { duration: 'normal', easing: 'easeOut' })
|
|
141
|
+
* // => "fadeIn 200ms ease-out"
|
|
142
|
+
*
|
|
143
|
+
* cssAnimation('spin', { duration: 'loop', easing: 'linear', iterations: 'infinite' })
|
|
144
|
+
* // => "spin 1000ms linear infinite"
|
|
145
|
+
*/
|
|
146
|
+
export function cssAnimation(name: string, config: KeyframeAnimationConfig = {}): string {
|
|
147
|
+
const {
|
|
148
|
+
duration = 'normal',
|
|
149
|
+
easing = 'ease',
|
|
150
|
+
delay = 0,
|
|
151
|
+
iterations = 1,
|
|
152
|
+
direction = 'normal',
|
|
153
|
+
fillMode = 'none',
|
|
154
|
+
} = config;
|
|
155
|
+
|
|
156
|
+
const durationMs = resolveDuration(duration);
|
|
157
|
+
const easingValue = resolveEasing(easing);
|
|
158
|
+
|
|
159
|
+
const parts = [
|
|
160
|
+
name,
|
|
161
|
+
`${durationMs}ms`,
|
|
162
|
+
easingValue,
|
|
163
|
+
delay > 0 ? `${delay}ms` : null,
|
|
164
|
+
iterations !== 1 ? iterations : null,
|
|
165
|
+
direction !== 'normal' ? direction : null,
|
|
166
|
+
fillMode !== 'none' ? fillMode : null,
|
|
167
|
+
].filter(Boolean);
|
|
168
|
+
|
|
169
|
+
return parts.join(' ');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* CSS @property registration for animatable custom properties
|
|
174
|
+
*
|
|
175
|
+
* This CSS should be injected once into the document head to enable
|
|
176
|
+
* smooth gradient animations using CSS custom properties.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* // Inject in your app's entry point
|
|
180
|
+
* import { gradientPropertyCSS, injectGradientCSS } from '@idealyst/theme/animation';
|
|
181
|
+
*
|
|
182
|
+
* // Option 1: Manual injection
|
|
183
|
+
* const style = document.createElement('style');
|
|
184
|
+
* style.textContent = gradientPropertyCSS;
|
|
185
|
+
* document.head.appendChild(style);
|
|
186
|
+
*
|
|
187
|
+
* // Option 2: Use helper
|
|
188
|
+
* injectGradientCSS();
|
|
189
|
+
*/
|
|
190
|
+
export const gradientPropertyCSS = `
|
|
191
|
+
@property --gradient-angle {
|
|
192
|
+
syntax: '<angle>';
|
|
193
|
+
initial-value: 0deg;
|
|
194
|
+
inherits: false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@property --gradient-position {
|
|
198
|
+
syntax: '<percentage>';
|
|
199
|
+
initial-value: 0%;
|
|
200
|
+
inherits: false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@keyframes spin-gradient {
|
|
204
|
+
from { --gradient-angle: 0deg; }
|
|
205
|
+
to { --gradient-angle: 360deg; }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@keyframes pulse-gradient {
|
|
209
|
+
0%, 100% { opacity: 1; }
|
|
210
|
+
50% { opacity: 0.5; }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@keyframes wave-gradient {
|
|
214
|
+
from { --gradient-position: -100%; }
|
|
215
|
+
to { --gradient-position: 200%; }
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
let gradientCSSInjected = false;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Inject gradient CSS into document head (idempotent)
|
|
223
|
+
*
|
|
224
|
+
* Call this once in your app to enable gradient border animations.
|
|
225
|
+
* Safe to call multiple times - will only inject once.
|
|
226
|
+
*/
|
|
227
|
+
export function injectGradientCSS(): void {
|
|
228
|
+
if (typeof document === 'undefined' || gradientCSSInjected) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const style = document.createElement('style');
|
|
233
|
+
style.id = 'idealyst-gradient-animations';
|
|
234
|
+
style.textContent = gradientPropertyCSS;
|
|
235
|
+
document.head.appendChild(style);
|
|
236
|
+
gradientCSSInjected = true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Generate conic gradient border spinner styles
|
|
241
|
+
*
|
|
242
|
+
* @param colors - Array of gradient colors
|
|
243
|
+
* @param borderWidth - Border thickness in pixels
|
|
244
|
+
* @param duration - Animation duration
|
|
245
|
+
* @returns Style object for animated gradient border
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* import { conicSpinnerStyle } from '@idealyst/theme/animation';
|
|
249
|
+
*
|
|
250
|
+
* const spinnerStyle = conicSpinnerStyle(
|
|
251
|
+
* ['#3b82f6', '#8b5cf6', '#ec4899'],
|
|
252
|
+
* 2,
|
|
253
|
+
* 2000
|
|
254
|
+
* );
|
|
255
|
+
*/
|
|
256
|
+
export function conicSpinnerStyle(
|
|
257
|
+
colors: string[],
|
|
258
|
+
borderWidth: number = 2,
|
|
259
|
+
duration: Duration = 2000
|
|
260
|
+
): Record<string, string | number> {
|
|
261
|
+
const durationMs = resolveDuration(duration);
|
|
262
|
+
const colorString = colors.join(', ');
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
background: `conic-gradient(from var(--gradient-angle), ${colorString})`,
|
|
266
|
+
animation: `spin-gradient ${durationMs}ms linear infinite`,
|
|
267
|
+
// Mask technique for border-only effect
|
|
268
|
+
WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
|
|
269
|
+
WebkitMaskComposite: 'xor',
|
|
270
|
+
maskComposite: 'exclude',
|
|
271
|
+
padding: borderWidth,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Generate pulse gradient styles
|
|
277
|
+
*
|
|
278
|
+
* @param colors - Array of gradient colors
|
|
279
|
+
* @param duration - Animation duration
|
|
280
|
+
* @returns Style object for pulsing gradient
|
|
281
|
+
*/
|
|
282
|
+
export function pulseGradientStyle(
|
|
283
|
+
colors: string[],
|
|
284
|
+
duration: Duration = 'slowest'
|
|
285
|
+
): Record<string, string | number> {
|
|
286
|
+
const durationMs = resolveDuration(duration);
|
|
287
|
+
const colorString = colors.join(', ');
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
background: `linear-gradient(135deg, ${colorString})`,
|
|
291
|
+
animation: `pulse-gradient ${durationMs}ms ease-in-out infinite`,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation type definitions for @idealyst/theme
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { durations, easings } from './tokens';
|
|
6
|
+
|
|
7
|
+
// Duration types
|
|
8
|
+
export type DurationKey = keyof typeof durations;
|
|
9
|
+
export type Duration = DurationKey | number;
|
|
10
|
+
|
|
11
|
+
// Easing types
|
|
12
|
+
export type EasingKey = keyof typeof easings;
|
|
13
|
+
export type BezierEasing = readonly [number, number, number, number];
|
|
14
|
+
export type SpringConfig = {
|
|
15
|
+
readonly damping: number;
|
|
16
|
+
readonly stiffness: number;
|
|
17
|
+
readonly mass: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type CSSEasing = {
|
|
21
|
+
readonly css: string;
|
|
22
|
+
readonly bezier: BezierEasing;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type Easing = CSSEasing | SpringConfig;
|
|
26
|
+
|
|
27
|
+
// Animation configuration
|
|
28
|
+
export interface AnimationConfig {
|
|
29
|
+
duration?: Duration;
|
|
30
|
+
easing?: EasingKey;
|
|
31
|
+
delay?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Transition configuration for CSS
|
|
35
|
+
export interface TransitionConfig extends AnimationConfig {
|
|
36
|
+
properties?: string | string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Keyframe types
|
|
40
|
+
export type KeyframeStyles = Record<string, React.CSSProperties>;
|
|
41
|
+
export type KeyframePercentage = `${number}%` | 'from' | 'to';
|
|
42
|
+
export type Keyframes = Partial<Record<KeyframePercentage, React.CSSProperties>>;
|
|
43
|
+
|
|
44
|
+
// Animation iteration
|
|
45
|
+
export type AnimationIterations = number | 'infinite';
|
|
46
|
+
export type AnimationDirection = 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
|
|
47
|
+
export type AnimationFillMode = 'none' | 'forwards' | 'backwards' | 'both';
|
|
48
|
+
|
|
49
|
+
// Full animation configuration
|
|
50
|
+
export interface KeyframeAnimationConfig extends AnimationConfig {
|
|
51
|
+
iterations?: AnimationIterations;
|
|
52
|
+
direction?: AnimationDirection;
|
|
53
|
+
fillMode?: AnimationFillMode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Spring types for native
|
|
57
|
+
export type SpringType = 'spring' | 'springStiff' | 'springBouncy';
|
|
58
|
+
|
|
59
|
+
// Timing config for Reanimated
|
|
60
|
+
export interface TimingAnimationConfig {
|
|
61
|
+
duration: number;
|
|
62
|
+
easing: BezierEasing;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Platform-specific options
|
|
66
|
+
export interface PlatformAnimationOptions {
|
|
67
|
+
web?: Partial<TransitionConfig> & { transition?: string };
|
|
68
|
+
native?: Partial<AnimationConfig> & Partial<SpringConfig>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Gradient animation types
|
|
72
|
+
export type GradientAnimation = 'spin' | 'pulse' | 'wave';
|
|
73
|
+
|
|
74
|
+
export interface GradientBorderConfig {
|
|
75
|
+
colors: string[];
|
|
76
|
+
borderWidth?: number;
|
|
77
|
+
borderRadius?: number;
|
|
78
|
+
duration?: Duration;
|
|
79
|
+
animation?: GradientAnimation;
|
|
80
|
+
}
|
package/src/builder.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
ProgressSizeValue,
|
|
21
21
|
AccordionSizeValue,
|
|
22
22
|
ActivityIndicatorSizeValue,
|
|
23
|
+
AlertSizeValue,
|
|
23
24
|
BreadcrumbSizeValue,
|
|
24
25
|
ListSizeValue,
|
|
25
26
|
MenuSizeValue,
|
|
@@ -68,6 +69,7 @@ export type BuiltTheme<
|
|
|
68
69
|
progress: Record<TSize, ProgressSizeValue>;
|
|
69
70
|
accordion: Record<TSize, AccordionSizeValue>;
|
|
70
71
|
activityIndicator: Record<TSize, ActivityIndicatorSizeValue>;
|
|
72
|
+
alert: Record<TSize, AlertSizeValue>;
|
|
71
73
|
breadcrumb: Record<TSize, BreadcrumbSizeValue>;
|
|
72
74
|
list: Record<TSize, ListSizeValue>;
|
|
73
75
|
menu: Record<TSize, MenuSizeValue>;
|
|
@@ -259,6 +261,7 @@ export class ThemeBuilder<
|
|
|
259
261
|
progress: Record<S, ProgressSizeValue>;
|
|
260
262
|
accordion: Record<S, AccordionSizeValue>;
|
|
261
263
|
activityIndicator: Record<S, ActivityIndicatorSizeValue>;
|
|
264
|
+
alert: Record<S, AlertSizeValue>;
|
|
262
265
|
breadcrumb: Record<S, BreadcrumbSizeValue>;
|
|
263
266
|
list: Record<S, ListSizeValue>;
|
|
264
267
|
menu: Record<S, MenuSizeValue>;
|
package/src/components/CLAUDE.md
CHANGED
|
@@ -141,7 +141,7 @@ function createSizeVariants(theme: Theme) {
|
|
|
141
141
|
|
|
142
142
|
#### Colors
|
|
143
143
|
- **Intents**: `theme.intents[intent].primary`, `.contrast`, `.light`, `.dark`
|
|
144
|
-
- Available intents: `primary`, `success`, `
|
|
144
|
+
- Available intents: `primary`, `success`, `danger`, `warning`, `neutral`, `info`
|
|
145
145
|
- **Surface**: `theme.colors.surface.primary`, `.secondary`, `.tertiary`, `.inverse`, etc.
|
|
146
146
|
- **Text**: `theme.colors.text.primary`, `.secondary`, `.tertiary`, `.inverse`, etc.
|
|
147
147
|
- **Border**: `theme.colors.border.primary`, `.secondary`, `.tertiary`, `.disabled`
|
package/src/config/generator.ts
CHANGED
|
@@ -636,7 +636,7 @@ function generateInputStyles(theme: Theme, extensions?: ComponentExtensions): Re
|
|
|
636
636
|
},
|
|
637
637
|
error: {
|
|
638
638
|
true: {
|
|
639
|
-
borderColor: themeRef('intents.
|
|
639
|
+
borderColor: themeRef('intents.danger.primary'),
|
|
640
640
|
},
|
|
641
641
|
false: {},
|
|
642
642
|
},
|
|
@@ -666,7 +666,7 @@ function generateInputStyles(theme: Theme, extensions?: ComponentExtensions): Re
|
|
|
666
666
|
fontSize: 12,
|
|
667
667
|
variants: {
|
|
668
668
|
error: {
|
|
669
|
-
true: { color: themeRef('intents.
|
|
669
|
+
true: { color: themeRef('intents.danger.primary') },
|
|
670
670
|
false: {},
|
|
671
671
|
},
|
|
672
672
|
},
|
package/src/darkTheme.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -23,4 +23,8 @@ export * from './componentStyles';
|
|
|
23
23
|
// Responsive utilities
|
|
24
24
|
export * from './responsive';
|
|
25
25
|
export * from './breakpoints';
|
|
26
|
-
export * from './useResponsiveStyle';
|
|
26
|
+
export * from './useResponsiveStyle';
|
|
27
|
+
|
|
28
|
+
// Animation tokens and utilities
|
|
29
|
+
// Note: Use '@idealyst/theme/animation' for full animation API
|
|
30
|
+
export { durations, easings, presets } from './animation/tokens';
|
package/src/lightTheme.ts
CHANGED
|
@@ -19,7 +19,7 @@ export const lightTheme = createTheme()
|
|
|
19
19
|
light: '#a7f3d0',
|
|
20
20
|
dark: '#165e29',
|
|
21
21
|
})
|
|
22
|
-
.addIntent('
|
|
22
|
+
.addIntent('danger', {
|
|
23
23
|
primary: '#ef4444',
|
|
24
24
|
contrast: '#ffffff',
|
|
25
25
|
light: '#fca5a1',
|
|
@@ -211,6 +211,13 @@ export const lightTheme = createTheme()
|
|
|
211
211
|
lg: { size: 48, borderWidth: 4 },
|
|
212
212
|
xl: { size: 64, borderWidth: 5 },
|
|
213
213
|
},
|
|
214
|
+
alert: {
|
|
215
|
+
xs: { padding: 8, gap: 6, borderRadius: 4, titleFontSize: 12, titleLineHeight: 16, messageFontSize: 11, messageLineHeight: 14, iconSize: 16, closeIconSize: 12 },
|
|
216
|
+
sm: { padding: 12, gap: 8, borderRadius: 6, titleFontSize: 14, titleLineHeight: 20, messageFontSize: 12, messageLineHeight: 16, iconSize: 20, closeIconSize: 14 },
|
|
217
|
+
md: { padding: 16, gap: 10, borderRadius: 8, titleFontSize: 16, titleLineHeight: 24, messageFontSize: 14, messageLineHeight: 20, iconSize: 24, closeIconSize: 16 },
|
|
218
|
+
lg: { padding: 20, gap: 12, borderRadius: 10, titleFontSize: 18, titleLineHeight: 28, messageFontSize: 16, messageLineHeight: 24, iconSize: 28, closeIconSize: 18 },
|
|
219
|
+
xl: { padding: 24, gap: 14, borderRadius: 12, titleFontSize: 20, titleLineHeight: 32, messageFontSize: 18, messageLineHeight: 28, iconSize: 32, closeIconSize: 20 },
|
|
220
|
+
},
|
|
214
221
|
breadcrumb: {
|
|
215
222
|
xs: { fontSize: 10, lineHeight: 14, iconSize: 12 },
|
|
216
223
|
sm: { fontSize: 12, lineHeight: 16, iconSize: 14 },
|
package/src/styleBuilder.ts
CHANGED
package/src/theme/extensions.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
|
2
2
|
|
|
3
|
-
import type { IntentValue, ShadowValue, Shade, ColorValue, InteractionConfig, ButtonSizeValue, ChipSizeValue, BadgeSizeValue, IconSizeValue, InputSizeValue, RadioButtonSizeValue, SelectSizeValue, SliderSizeValue, SwitchSizeValue, TextAreaSizeValue, AvatarSizeValue, ProgressSizeValue, AccordionSizeValue, ActivityIndicatorSizeValue, BreadcrumbSizeValue, ListSizeValue, MenuSizeValue, TextSizeValue, TabBarSizeValue, TableSizeValue, TooltipSizeValue, ViewSizeValue, Typography, TypographyValue } from './structures';
|
|
3
|
+
import type { IntentValue, ShadowValue, Shade, ColorValue, InteractionConfig, ButtonSizeValue, ChipSizeValue, BadgeSizeValue, IconSizeValue, InputSizeValue, RadioButtonSizeValue, SelectSizeValue, SliderSizeValue, SwitchSizeValue, TextAreaSizeValue, AvatarSizeValue, ProgressSizeValue, AccordionSizeValue, ActivityIndicatorSizeValue, AlertSizeValue, BreadcrumbSizeValue, ListSizeValue, MenuSizeValue, TextSizeValue, TabBarSizeValue, TableSizeValue, TooltipSizeValue, ViewSizeValue, Typography, TypographyValue } from './structures';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Default fallback theme structure.
|
|
@@ -32,6 +32,7 @@ export interface DefaultTheme {
|
|
|
32
32
|
progress: Record<string, ProgressSizeValue>;
|
|
33
33
|
accordion: Record<string, AccordionSizeValue>;
|
|
34
34
|
activityIndicator: Record<string, ActivityIndicatorSizeValue>;
|
|
35
|
+
alert: Record<string, AlertSizeValue>;
|
|
35
36
|
breadcrumb: Record<string, BreadcrumbSizeValue>;
|
|
36
37
|
list: Record<string, ListSizeValue>;
|
|
37
38
|
menu: Record<string, MenuSizeValue>;
|
package/src/theme/structures.ts
CHANGED
|
@@ -194,6 +194,18 @@ export type ActivityIndicatorSizeValue = {
|
|
|
194
194
|
borderWidth: SizeValue;
|
|
195
195
|
};
|
|
196
196
|
|
|
197
|
+
export type AlertSizeValue = {
|
|
198
|
+
padding: SizeValue;
|
|
199
|
+
gap: SizeValue;
|
|
200
|
+
borderRadius: SizeValue;
|
|
201
|
+
titleFontSize: SizeValue;
|
|
202
|
+
titleLineHeight: SizeValue;
|
|
203
|
+
messageFontSize: SizeValue;
|
|
204
|
+
messageLineHeight: SizeValue;
|
|
205
|
+
iconSize: SizeValue;
|
|
206
|
+
closeIconSize: SizeValue;
|
|
207
|
+
};
|
|
208
|
+
|
|
197
209
|
export type BreadcrumbSizeValue = {
|
|
198
210
|
fontSize: SizeValue;
|
|
199
211
|
lineHeight: SizeValue;
|