@castui/cast-ui 4.9.0 → 4.10.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 +23 -1
- package/dist/components/Accordion/Accordion.js +4 -3
- package/dist/components/Backdrop/Backdrop.js +7 -8
- package/dist/components/BottomSheet/BottomSheet.js +12 -14
- package/dist/components/Drawer/Drawer.js +12 -14
- package/dist/components/Progress/Progress.js +5 -4
- package/dist/components/Skeleton/Skeleton.js +11 -13
- package/dist/components/SpeedDial/SpeedDial.js +3 -5
- package/dist/components/Spinner/Spinner.js +6 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -3
- package/dist/theme/ThemeContext.d.ts +12 -1
- package/dist/theme/ThemeContext.js +5 -2
- package/dist/theme/applyCastTheme.d.ts +32 -2
- package/dist/theme/applyCastTheme.js +72 -0
- package/dist/theme/index.d.ts +1 -0
- package/dist/theme/index.js +3 -1
- package/dist/theme/useMotion.d.ts +32 -0
- package/dist/theme/useMotion.js +55 -0
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.js +12 -1
- package/dist/tokens/motion.d.ts +196 -0
- package/dist/tokens/motion.js +175 -0
- package/package.json +2 -1
- package/skills/cast-ui-component/SKILL.md +834 -0
- package/skills/cast-ui-docs-site/SKILL.md +114 -0
- package/skills/cast-ui-usage/SKILL.md +587 -0
package/dist/theme/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ThemeProvider, useTheme, type ThemeProviderProps, type Theme } from './ThemeContext';
|
|
2
2
|
export { themes } from './themes';
|
|
3
|
+
export { useMotion, type Motion } from './useMotion';
|
|
3
4
|
export { applyCastTheme, type CastThemeFile, type CastThemeProps, } from './applyCastTheme';
|
|
4
5
|
export type { DensityTheme, ComponentTokens, AccordionSizeTokens, AccordionThemeTokens, ButtonSizeTokens, ButtonThemeTokens, DialogSizeTokens, DialogThemeTokens, InputSizeTokens, InputThemeTokens, SelectContentTokens, SelectOptionTokens, SelectGroupTokens, SelectSeparatorTokens, SelectThemeTokens, ListItemTokens, ListSubheaderTokens, ListThemeTokens, CheckboxSizeTokens, CheckboxThemeTokens, AlertSizeTokens, AlertThemeTokens, ToggleSizeTokens, ToggleThemeTokens, CardSizeTokens, CardThemeTokens, BadgeSizeTokens, BadgeThemeTokens, RadioSizeTokens, RadioThemeTokens, ToastSizeTokens, ToastThemeTokens, ChipSizeTokens, ChipThemeTokens, AvatarSizeTokens, AvatarThemeTokens, PopoverSizeTokens, PopoverThemeTokens, TooltipSizeTokens, TooltipThemeTokens, ProgressSizeTokens, ProgressThemeTokens, TabsSizeTokens, TabsThemeTokens, SpinnerSizeTokens, SpinnerThemeTokens, BottomSheetThemeTokens, LinkSizeTokens, LinkThemeTokens, BreadcrumbsSizeTokens, BreadcrumbsThemeTokens, CodeBlockSizeTokens, CodeBlockThemeTokens, DrawerThemeTokens, MenuItemTokens, MenuGroupTokens, MenuThemeTokens, ToggleButtonGroupSizeTokens, ToggleButtonGroupThemeTokens, AppBarSizeTokens, AppBarThemeTokens, SliderSizeTokens, SliderThemeTokens, SpeedDialSizeTokens, SpeedDialThemeTokens, TableSizeTokens, TableThemeTokens, DeepPartial, } from './types';
|
package/dist/theme/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.applyCastTheme = exports.themes = exports.useTheme = exports.ThemeProvider = void 0;
|
|
3
|
+
exports.applyCastTheme = exports.useMotion = exports.themes = exports.useTheme = exports.ThemeProvider = void 0;
|
|
4
4
|
var ThemeContext_1 = require("./ThemeContext");
|
|
5
5
|
Object.defineProperty(exports, "ThemeProvider", { enumerable: true, get: function () { return ThemeContext_1.ThemeProvider; } });
|
|
6
6
|
Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return ThemeContext_1.useTheme; } });
|
|
7
7
|
var themes_1 = require("./themes");
|
|
8
8
|
Object.defineProperty(exports, "themes", { enumerable: true, get: function () { return themes_1.themes; } });
|
|
9
|
+
var useMotion_1 = require("./useMotion");
|
|
10
|
+
Object.defineProperty(exports, "useMotion", { enumerable: true, get: function () { return useMotion_1.useMotion; } });
|
|
9
11
|
var applyCastTheme_1 = require("./applyCastTheme");
|
|
10
12
|
Object.defineProperty(exports, "applyCastTheme", { enumerable: true, get: function () { return applyCastTheme_1.applyCastTheme; } });
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useMotion — the single access point for animation in Cast UI.
|
|
3
|
+
*
|
|
4
|
+
* Returns the theme's motion tokens plus three runtime helpers:
|
|
5
|
+
* reduceMotion true when the OS "reduce motion" setting is on.
|
|
6
|
+
* useNativeDriver the Animated.timing native-driver flag (false on web).
|
|
7
|
+
* scale(ms) a duration in ms, collapsed to 0 when reduceMotion is on.
|
|
8
|
+
*
|
|
9
|
+
* Components read a semantic role for the value and wrap durations in scale(),
|
|
10
|
+
* so the whole library honours reduce-motion from one place:
|
|
11
|
+
*
|
|
12
|
+
* const motion = useMotion();
|
|
13
|
+
* Animated.timing(v, {
|
|
14
|
+
* toValue: 1,
|
|
15
|
+
* duration: motion.scale(motion.transition.standard.duration),
|
|
16
|
+
* easing: motion.transition.standard.easing,
|
|
17
|
+
* useNativeDriver: motion.useNativeDriver,
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* For continuous loops (spinner, skeleton, progress), check reduceMotion and
|
|
21
|
+
* skip starting the loop.
|
|
22
|
+
*/
|
|
23
|
+
import type { MotionTokens } from '../tokens/motion';
|
|
24
|
+
export type Motion = MotionTokens & {
|
|
25
|
+
/** True when the OS "reduce motion" accessibility setting is enabled. */
|
|
26
|
+
reduceMotion: boolean;
|
|
27
|
+
/** Animated useNativeDriver value. False on web (the web driver can't animate layout). */
|
|
28
|
+
useNativeDriver: boolean;
|
|
29
|
+
/** Returns the given duration, or 0 when reduce-motion is on. */
|
|
30
|
+
scale: (ms: number) => number;
|
|
31
|
+
};
|
|
32
|
+
export declare function useMotion(): Motion;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* useMotion — the single access point for animation in Cast UI.
|
|
4
|
+
*
|
|
5
|
+
* Returns the theme's motion tokens plus three runtime helpers:
|
|
6
|
+
* reduceMotion true when the OS "reduce motion" setting is on.
|
|
7
|
+
* useNativeDriver the Animated.timing native-driver flag (false on web).
|
|
8
|
+
* scale(ms) a duration in ms, collapsed to 0 when reduceMotion is on.
|
|
9
|
+
*
|
|
10
|
+
* Components read a semantic role for the value and wrap durations in scale(),
|
|
11
|
+
* so the whole library honours reduce-motion from one place:
|
|
12
|
+
*
|
|
13
|
+
* const motion = useMotion();
|
|
14
|
+
* Animated.timing(v, {
|
|
15
|
+
* toValue: 1,
|
|
16
|
+
* duration: motion.scale(motion.transition.standard.duration),
|
|
17
|
+
* easing: motion.transition.standard.easing,
|
|
18
|
+
* useNativeDriver: motion.useNativeDriver,
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* For continuous loops (spinner, skeleton, progress), check reduceMotion and
|
|
22
|
+
* skip starting the loop.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.useMotion = useMotion;
|
|
26
|
+
const react_1 = require("react");
|
|
27
|
+
const react_native_1 = require("react-native");
|
|
28
|
+
const ThemeContext_1 = require("./ThemeContext");
|
|
29
|
+
function useMotion() {
|
|
30
|
+
const { motion } = (0, ThemeContext_1.useTheme)();
|
|
31
|
+
const [reduceMotion, setReduceMotion] = (0, react_1.useState)(false);
|
|
32
|
+
(0, react_1.useEffect)(() => {
|
|
33
|
+
let active = true;
|
|
34
|
+
const read = react_native_1.AccessibilityInfo.isReduceMotionEnabled;
|
|
35
|
+
if (typeof read === 'function') {
|
|
36
|
+
read()
|
|
37
|
+
.then((value) => {
|
|
38
|
+
if (active)
|
|
39
|
+
setReduceMotion(!!value);
|
|
40
|
+
})
|
|
41
|
+
.catch(() => { });
|
|
42
|
+
}
|
|
43
|
+
const sub = react_native_1.AccessibilityInfo.addEventListener?.('reduceMotionChanged', (value) => setReduceMotion(!!value));
|
|
44
|
+
return () => {
|
|
45
|
+
active = false;
|
|
46
|
+
sub?.remove?.();
|
|
47
|
+
};
|
|
48
|
+
}, []);
|
|
49
|
+
return {
|
|
50
|
+
...motion,
|
|
51
|
+
reduceMotion,
|
|
52
|
+
useNativeDriver: react_native_1.Platform.OS !== 'web',
|
|
53
|
+
scale: (ms) => (reduceMotion ? 0 : ms),
|
|
54
|
+
};
|
|
55
|
+
}
|
package/dist/tokens/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { lightColors, darkColors, colorSchemes, intentColors, disabledColors, co
|
|
|
2
2
|
export { fontFamily, fontWeight, label, title, body, heading, display, caption, type LabelSize, } from './typography';
|
|
3
3
|
export { iconSize, type IconSize } from './icon';
|
|
4
4
|
export { breakpoints, breakpointOrder, resolveBreakpoint, resolveResponsiveValue, type Breakpoint, type BreakpointKey, } from './breakpoints';
|
|
5
|
+
export { duration, cycle, easing, easingBezier, spring, transition, feedback, loop, motionTokens, resolveMotion, type MotionTokens, type MotionTransition, type MotionOverrides, type MotionDurations, type MotionCycles, type EasingName, type EasingBezierPoints, type SpringConfig, } from './motion';
|
package/dist/tokens/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveResponsiveValue = exports.resolveBreakpoint = exports.breakpointOrder = exports.breakpoints = exports.iconSize = exports.caption = exports.display = exports.heading = exports.body = exports.title = exports.label = exports.fontWeight = exports.fontFamily = exports.tableColors = exports.sliderColors = exports.skeletonColors = exports.avatarColors = exports.radioColors = exports.tabsColors = exports.progressColors = exports.toggleColors = exports.checkboxColors = exports.listColors = exports.errorTokens = exports.tagTokens = exports.menuColors = exports.selectColors = exports.overlayTokens = exports.textTokens = exports.surfaceTokens = exports.controlTokens = exports.disabledColors = exports.intentColors = exports.colorSchemes = exports.darkColors = exports.lightColors = void 0;
|
|
3
|
+
exports.resolveMotion = exports.motionTokens = exports.loop = exports.feedback = exports.transition = exports.spring = exports.easingBezier = exports.easing = exports.cycle = exports.duration = exports.resolveResponsiveValue = exports.resolveBreakpoint = exports.breakpointOrder = exports.breakpoints = exports.iconSize = exports.caption = exports.display = exports.heading = exports.body = exports.title = exports.label = exports.fontWeight = exports.fontFamily = exports.tableColors = exports.sliderColors = exports.skeletonColors = exports.avatarColors = exports.radioColors = exports.tabsColors = exports.progressColors = exports.toggleColors = exports.checkboxColors = exports.listColors = exports.errorTokens = exports.tagTokens = exports.menuColors = exports.selectColors = exports.overlayTokens = exports.textTokens = exports.surfaceTokens = exports.controlTokens = exports.disabledColors = exports.intentColors = exports.colorSchemes = exports.darkColors = exports.lightColors = void 0;
|
|
4
4
|
var colors_1 = require("./colors");
|
|
5
5
|
Object.defineProperty(exports, "lightColors", { enumerable: true, get: function () { return colors_1.lightColors; } });
|
|
6
6
|
Object.defineProperty(exports, "darkColors", { enumerable: true, get: function () { return colors_1.darkColors; } });
|
|
@@ -41,3 +41,14 @@ Object.defineProperty(exports, "breakpoints", { enumerable: true, get: function
|
|
|
41
41
|
Object.defineProperty(exports, "breakpointOrder", { enumerable: true, get: function () { return breakpoints_1.breakpointOrder; } });
|
|
42
42
|
Object.defineProperty(exports, "resolveBreakpoint", { enumerable: true, get: function () { return breakpoints_1.resolveBreakpoint; } });
|
|
43
43
|
Object.defineProperty(exports, "resolveResponsiveValue", { enumerable: true, get: function () { return breakpoints_1.resolveResponsiveValue; } });
|
|
44
|
+
var motion_1 = require("./motion");
|
|
45
|
+
Object.defineProperty(exports, "duration", { enumerable: true, get: function () { return motion_1.duration; } });
|
|
46
|
+
Object.defineProperty(exports, "cycle", { enumerable: true, get: function () { return motion_1.cycle; } });
|
|
47
|
+
Object.defineProperty(exports, "easing", { enumerable: true, get: function () { return motion_1.easing; } });
|
|
48
|
+
Object.defineProperty(exports, "easingBezier", { enumerable: true, get: function () { return motion_1.easingBezier; } });
|
|
49
|
+
Object.defineProperty(exports, "spring", { enumerable: true, get: function () { return motion_1.spring; } });
|
|
50
|
+
Object.defineProperty(exports, "transition", { enumerable: true, get: function () { return motion_1.transition; } });
|
|
51
|
+
Object.defineProperty(exports, "feedback", { enumerable: true, get: function () { return motion_1.feedback; } });
|
|
52
|
+
Object.defineProperty(exports, "loop", { enumerable: true, get: function () { return motion_1.loop; } });
|
|
53
|
+
Object.defineProperty(exports, "motionTokens", { enumerable: true, get: function () { return motion_1.motionTokens; } });
|
|
54
|
+
Object.defineProperty(exports, "resolveMotion", { enumerable: true, get: function () { return motion_1.resolveMotion; } });
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Motion tokens — the single source for animation timing across Cast UI.
|
|
3
|
+
*
|
|
4
|
+
* Two layers, mirroring the colour and spacing token system:
|
|
5
|
+
* Primitive raw durations, cubic-bezier easings, spring configs.
|
|
6
|
+
* Semantic named roles (transition / feedback / loop) that components read.
|
|
7
|
+
*
|
|
8
|
+
* Motion is constant across density and colour mode. Density changes spacing
|
|
9
|
+
* only. Easings are real cubic-beziers, so the same numbers map 1:1 to the
|
|
10
|
+
* `motion` variable collection in the Figma kit and to CSS.
|
|
11
|
+
*
|
|
12
|
+
* Components never read a raw number. They read a semantic role through
|
|
13
|
+
* useMotion(), for example motion.transition.standard or motion.loop.spin.
|
|
14
|
+
*
|
|
15
|
+
* Theming: a cast-theme.json can carry a `motion` block (exported by the
|
|
16
|
+
* cast-sync plugin from the kit's `motion` variable collection). ThemeProvider
|
|
17
|
+
* accepts those primitive-level overrides via its `motion` prop and
|
|
18
|
+
* `resolveMotion` rebuilds every semantic role from them, so a brand can
|
|
19
|
+
* re-tune timing with no code changes.
|
|
20
|
+
*/
|
|
21
|
+
type EasingFn = (value: number) => number;
|
|
22
|
+
export type EasingName = 'standard' | 'entrance' | 'exit' | 'emphasized' | 'linear';
|
|
23
|
+
/** Cubic-bezier control points as [x1, y1, x2, y2]. */
|
|
24
|
+
export type EasingBezierPoints = readonly [number, number, number, number];
|
|
25
|
+
export type MotionDurations = {
|
|
26
|
+
/** Micro feedback, e.g. a press. */
|
|
27
|
+
instant: number;
|
|
28
|
+
/** Small enters/exits and expands. */
|
|
29
|
+
fast: number;
|
|
30
|
+
/** The general state-to-state duration. */
|
|
31
|
+
base: number;
|
|
32
|
+
/** Large surfaces or long distances. */
|
|
33
|
+
slow: number;
|
|
34
|
+
};
|
|
35
|
+
export type MotionCycles = {
|
|
36
|
+
/** Skeleton fade half-cycle. */
|
|
37
|
+
pulse: number;
|
|
38
|
+
/** Spinner full rotation. */
|
|
39
|
+
spin: number;
|
|
40
|
+
/** Progress indeterminate sweep. */
|
|
41
|
+
sweep: number;
|
|
42
|
+
};
|
|
43
|
+
export type SpringConfig = {
|
|
44
|
+
damping: number;
|
|
45
|
+
stiffness: number;
|
|
46
|
+
mass: number;
|
|
47
|
+
};
|
|
48
|
+
export type MotionTransition = {
|
|
49
|
+
duration: number;
|
|
50
|
+
easing: EasingFn;
|
|
51
|
+
};
|
|
52
|
+
export type MotionTokens = {
|
|
53
|
+
duration: MotionDurations;
|
|
54
|
+
cycle: MotionCycles;
|
|
55
|
+
easing: Record<EasingName, EasingFn>;
|
|
56
|
+
easingBezier: Record<EasingName, EasingBezierPoints>;
|
|
57
|
+
spring: {
|
|
58
|
+
overlay: SpringConfig;
|
|
59
|
+
};
|
|
60
|
+
transition: {
|
|
61
|
+
standard: MotionTransition;
|
|
62
|
+
enter: MotionTransition;
|
|
63
|
+
exit: MotionTransition;
|
|
64
|
+
expand: MotionTransition;
|
|
65
|
+
};
|
|
66
|
+
feedback: {
|
|
67
|
+
press: MotionTransition & {
|
|
68
|
+
scale: number;
|
|
69
|
+
};
|
|
70
|
+
shake: MotionTransition & {
|
|
71
|
+
amplitude: number;
|
|
72
|
+
};
|
|
73
|
+
pop: MotionTransition;
|
|
74
|
+
};
|
|
75
|
+
loop: {
|
|
76
|
+
spin: MotionTransition;
|
|
77
|
+
pulse: MotionTransition & {
|
|
78
|
+
from: number;
|
|
79
|
+
to: number;
|
|
80
|
+
};
|
|
81
|
+
indeterminate: MotionTransition;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Primitive-level motion overrides, the shape a cast-theme.json `motion`
|
|
86
|
+
* block maps onto. Only numbers and beziers — semantic roles are rebuilt
|
|
87
|
+
* from these by `resolveMotion`, never overridden directly.
|
|
88
|
+
*/
|
|
89
|
+
export type MotionOverrides = {
|
|
90
|
+
duration?: Partial<MotionDurations>;
|
|
91
|
+
cycle?: Partial<MotionCycles>;
|
|
92
|
+
easingBezier?: Partial<Record<EasingName, EasingBezierPoints>>;
|
|
93
|
+
spring?: {
|
|
94
|
+
overlay?: Partial<SpringConfig>;
|
|
95
|
+
};
|
|
96
|
+
feedback?: {
|
|
97
|
+
press?: {
|
|
98
|
+
scale?: number;
|
|
99
|
+
};
|
|
100
|
+
shake?: {
|
|
101
|
+
amplitude?: number;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
loop?: {
|
|
105
|
+
pulse?: {
|
|
106
|
+
from?: number;
|
|
107
|
+
to?: number;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
/** Primitive: transition durations in ms (state to state). */
|
|
112
|
+
export declare const duration: MotionDurations;
|
|
113
|
+
/** Primitive: loop cycle lengths in ms (continuous, not state to state). */
|
|
114
|
+
export declare const cycle: MotionCycles;
|
|
115
|
+
/**
|
|
116
|
+
* Primitive: easing control points as cubic-bezier [x1, y1, x2, y2].
|
|
117
|
+
* This is the design-side value. The `motion` collection in the Figma kit
|
|
118
|
+
* carries these exact numbers (easing/{name}/{x1,y1,x2,y2}).
|
|
119
|
+
*/
|
|
120
|
+
export declare const easingBezier: Record<EasingName, EasingBezierPoints>;
|
|
121
|
+
/** Primitive: easing as runtime functions (the code-side value). */
|
|
122
|
+
export declare const easing: Record<EasingName, EasingFn>;
|
|
123
|
+
/** Primitive: spring configs for Animated.spring. */
|
|
124
|
+
export declare const spring: {
|
|
125
|
+
overlay: SpringConfig;
|
|
126
|
+
};
|
|
127
|
+
export declare const transition: {
|
|
128
|
+
/** General state-to-state fade or slide. Backdrops, overlay fades. */
|
|
129
|
+
standard: {
|
|
130
|
+
duration: number;
|
|
131
|
+
easing: EasingFn;
|
|
132
|
+
};
|
|
133
|
+
/** Something appearing. Decelerates as it lands. */
|
|
134
|
+
enter: {
|
|
135
|
+
duration: number;
|
|
136
|
+
easing: EasingFn;
|
|
137
|
+
};
|
|
138
|
+
/** Something leaving. Accelerates as it goes. */
|
|
139
|
+
exit: {
|
|
140
|
+
duration: number;
|
|
141
|
+
easing: EasingFn;
|
|
142
|
+
};
|
|
143
|
+
/** Expand or collapse. Accordion chevron, height reveals. */
|
|
144
|
+
expand: {
|
|
145
|
+
duration: number;
|
|
146
|
+
easing: EasingFn;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
export declare const feedback: {
|
|
150
|
+
/** Press-down scale on a pressable (reserved for future use). */
|
|
151
|
+
press: {
|
|
152
|
+
duration: number;
|
|
153
|
+
easing: EasingFn;
|
|
154
|
+
scale: number;
|
|
155
|
+
};
|
|
156
|
+
/** Error shake, e.g. input rejection. amplitude in px (future use). */
|
|
157
|
+
shake: {
|
|
158
|
+
duration: number;
|
|
159
|
+
easing: EasingFn;
|
|
160
|
+
amplitude: number;
|
|
161
|
+
};
|
|
162
|
+
/** Pop-in for a check, badge, or toast (future use). */
|
|
163
|
+
pop: {
|
|
164
|
+
duration: number;
|
|
165
|
+
easing: EasingFn;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
export declare const loop: {
|
|
169
|
+
/** Spinner rotation. */
|
|
170
|
+
spin: {
|
|
171
|
+
duration: number;
|
|
172
|
+
easing: EasingFn;
|
|
173
|
+
};
|
|
174
|
+
/** Skeleton pulse. Fades opacity between from and to. */
|
|
175
|
+
pulse: {
|
|
176
|
+
duration: number;
|
|
177
|
+
easing: EasingFn;
|
|
178
|
+
from: number;
|
|
179
|
+
to: number;
|
|
180
|
+
};
|
|
181
|
+
/** Progress indeterminate sweep. */
|
|
182
|
+
indeterminate: {
|
|
183
|
+
duration: number;
|
|
184
|
+
easing: EasingFn;
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
/** The full default motion token set, exposed on the theme as `theme.motion`. */
|
|
188
|
+
export declare const motionTokens: MotionTokens;
|
|
189
|
+
/**
|
|
190
|
+
* Resolve a full motion token set from primitive-level overrides.
|
|
191
|
+
* With no overrides this returns the shared default set (no allocation).
|
|
192
|
+
* Semantic roles are always rebuilt from the merged primitives, so a
|
|
193
|
+
* duration override flows into every role that uses it.
|
|
194
|
+
*/
|
|
195
|
+
export declare function resolveMotion(overrides?: MotionOverrides): MotionTokens;
|
|
196
|
+
export {};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Motion tokens — the single source for animation timing across Cast UI.
|
|
4
|
+
*
|
|
5
|
+
* Two layers, mirroring the colour and spacing token system:
|
|
6
|
+
* Primitive raw durations, cubic-bezier easings, spring configs.
|
|
7
|
+
* Semantic named roles (transition / feedback / loop) that components read.
|
|
8
|
+
*
|
|
9
|
+
* Motion is constant across density and colour mode. Density changes spacing
|
|
10
|
+
* only. Easings are real cubic-beziers, so the same numbers map 1:1 to the
|
|
11
|
+
* `motion` variable collection in the Figma kit and to CSS.
|
|
12
|
+
*
|
|
13
|
+
* Components never read a raw number. They read a semantic role through
|
|
14
|
+
* useMotion(), for example motion.transition.standard or motion.loop.spin.
|
|
15
|
+
*
|
|
16
|
+
* Theming: a cast-theme.json can carry a `motion` block (exported by the
|
|
17
|
+
* cast-sync plugin from the kit's `motion` variable collection). ThemeProvider
|
|
18
|
+
* accepts those primitive-level overrides via its `motion` prop and
|
|
19
|
+
* `resolveMotion` rebuilds every semantic role from them, so a brand can
|
|
20
|
+
* re-tune timing with no code changes.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.motionTokens = exports.loop = exports.feedback = exports.transition = exports.spring = exports.easing = exports.easingBezier = exports.cycle = exports.duration = void 0;
|
|
24
|
+
exports.resolveMotion = resolveMotion;
|
|
25
|
+
const react_native_1 = require("react-native");
|
|
26
|
+
/** Primitive: transition durations in ms (state to state). */
|
|
27
|
+
exports.duration = {
|
|
28
|
+
instant: 100,
|
|
29
|
+
fast: 150,
|
|
30
|
+
base: 220,
|
|
31
|
+
slow: 320,
|
|
32
|
+
};
|
|
33
|
+
/** Primitive: loop cycle lengths in ms (continuous, not state to state). */
|
|
34
|
+
exports.cycle = {
|
|
35
|
+
pulse: 700,
|
|
36
|
+
spin: 800,
|
|
37
|
+
sweep: 1200,
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Primitive: easing control points as cubic-bezier [x1, y1, x2, y2].
|
|
41
|
+
* This is the design-side value. The `motion` collection in the Figma kit
|
|
42
|
+
* carries these exact numbers (easing/{name}/{x1,y1,x2,y2}).
|
|
43
|
+
*/
|
|
44
|
+
exports.easingBezier = {
|
|
45
|
+
standard: [0.4, 0, 0.2, 1],
|
|
46
|
+
entrance: [0, 0, 0.2, 1],
|
|
47
|
+
exit: [0.4, 0, 1, 1],
|
|
48
|
+
emphasized: [0.7, -0.4, 0.4, 1.4],
|
|
49
|
+
linear: [0, 0, 1, 1],
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Build a lazy easing function from bezier points. The Easing function is
|
|
53
|
+
* only created when an animation actually runs, so importing the tokens
|
|
54
|
+
* never touches the native Easing API. That keeps the library safe to
|
|
55
|
+
* import in any environment.
|
|
56
|
+
*/
|
|
57
|
+
function lazyEasing(points, linear) {
|
|
58
|
+
let fn = null;
|
|
59
|
+
return (value) => {
|
|
60
|
+
if (!fn) {
|
|
61
|
+
fn = linear ? react_native_1.Easing.linear : react_native_1.Easing.bezier(points[0], points[1], points[2], points[3]);
|
|
62
|
+
}
|
|
63
|
+
return fn(value);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function isLinear(points) {
|
|
67
|
+
return points[0] === 0 && points[1] === 0 && points[2] === 1 && points[3] === 1;
|
|
68
|
+
}
|
|
69
|
+
function buildEasings(beziers) {
|
|
70
|
+
return {
|
|
71
|
+
standard: lazyEasing(beziers.standard, isLinear(beziers.standard)),
|
|
72
|
+
entrance: lazyEasing(beziers.entrance, isLinear(beziers.entrance)),
|
|
73
|
+
exit: lazyEasing(beziers.exit, isLinear(beziers.exit)),
|
|
74
|
+
emphasized: lazyEasing(beziers.emphasized, isLinear(beziers.emphasized)),
|
|
75
|
+
linear: lazyEasing(beziers.linear, isLinear(beziers.linear)),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Primitive: easing as runtime functions (the code-side value). */
|
|
79
|
+
exports.easing = buildEasings(exports.easingBezier);
|
|
80
|
+
/** Primitive: spring configs for Animated.spring. */
|
|
81
|
+
exports.spring = {
|
|
82
|
+
/** Overlay surfaces sliding in (drawer, bottom sheet). */
|
|
83
|
+
overlay: { damping: 22, stiffness: 220, mass: 0.9 },
|
|
84
|
+
};
|
|
85
|
+
function buildRoles(p) {
|
|
86
|
+
return {
|
|
87
|
+
transition: {
|
|
88
|
+
/** General state-to-state fade or slide. Backdrops, overlay fades. */
|
|
89
|
+
standard: { duration: p.duration.base, easing: p.easing.standard },
|
|
90
|
+
/** Something appearing. Decelerates as it lands. */
|
|
91
|
+
enter: { duration: p.duration.fast, easing: p.easing.entrance },
|
|
92
|
+
/** Something leaving. Accelerates as it goes. */
|
|
93
|
+
exit: { duration: p.duration.fast, easing: p.easing.exit },
|
|
94
|
+
/** Expand or collapse. Accordion chevron, height reveals. */
|
|
95
|
+
expand: { duration: p.duration.fast, easing: p.easing.standard },
|
|
96
|
+
},
|
|
97
|
+
feedback: {
|
|
98
|
+
/** Press-down scale on a pressable (reserved for future use). */
|
|
99
|
+
press: { duration: p.duration.instant, easing: p.easing.standard, scale: p.press.scale },
|
|
100
|
+
/** Error shake, e.g. input rejection. amplitude in px (future use). */
|
|
101
|
+
shake: { duration: p.duration.base, easing: p.easing.standard, amplitude: p.shake.amplitude },
|
|
102
|
+
/** Pop-in for a check, badge, or toast (future use). */
|
|
103
|
+
pop: { duration: p.duration.fast, easing: p.easing.emphasized },
|
|
104
|
+
},
|
|
105
|
+
loop: {
|
|
106
|
+
/** Spinner rotation. */
|
|
107
|
+
spin: { duration: p.cycle.spin, easing: p.easing.linear },
|
|
108
|
+
/** Skeleton pulse. Fades opacity between from and to. */
|
|
109
|
+
pulse: { duration: p.cycle.pulse, easing: p.easing.standard, from: p.pulse.from, to: p.pulse.to },
|
|
110
|
+
/** Progress indeterminate sweep. */
|
|
111
|
+
indeterminate: { duration: p.cycle.sweep, easing: p.easing.standard },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const defaultRoles = buildRoles({
|
|
116
|
+
duration: exports.duration,
|
|
117
|
+
cycle: exports.cycle,
|
|
118
|
+
easing: exports.easing,
|
|
119
|
+
press: { scale: 0.97 },
|
|
120
|
+
shake: { amplitude: 4 },
|
|
121
|
+
pulse: { from: 1, to: 0.5 },
|
|
122
|
+
});
|
|
123
|
+
exports.transition = defaultRoles.transition;
|
|
124
|
+
exports.feedback = defaultRoles.feedback;
|
|
125
|
+
exports.loop = defaultRoles.loop;
|
|
126
|
+
/** The full default motion token set, exposed on the theme as `theme.motion`. */
|
|
127
|
+
exports.motionTokens = {
|
|
128
|
+
duration: exports.duration,
|
|
129
|
+
cycle: exports.cycle,
|
|
130
|
+
easing: exports.easing,
|
|
131
|
+
easingBezier: exports.easingBezier,
|
|
132
|
+
spring: exports.spring,
|
|
133
|
+
transition: exports.transition,
|
|
134
|
+
feedback: exports.feedback,
|
|
135
|
+
loop: exports.loop,
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a full motion token set from primitive-level overrides.
|
|
139
|
+
* With no overrides this returns the shared default set (no allocation).
|
|
140
|
+
* Semantic roles are always rebuilt from the merged primitives, so a
|
|
141
|
+
* duration override flows into every role that uses it.
|
|
142
|
+
*/
|
|
143
|
+
function resolveMotion(overrides) {
|
|
144
|
+
if (!overrides)
|
|
145
|
+
return exports.motionTokens;
|
|
146
|
+
const mergedDuration = { ...exports.duration, ...(overrides.duration ?? {}) };
|
|
147
|
+
const mergedCycle = { ...exports.cycle, ...(overrides.cycle ?? {}) };
|
|
148
|
+
const mergedBezier = {
|
|
149
|
+
...exports.easingBezier,
|
|
150
|
+
...(overrides.easingBezier ?? {}),
|
|
151
|
+
};
|
|
152
|
+
const mergedEasing = overrides.easingBezier ? buildEasings(mergedBezier) : exports.easing;
|
|
153
|
+
const mergedSpring = {
|
|
154
|
+
overlay: { ...exports.spring.overlay, ...(overrides.spring?.overlay ?? {}) },
|
|
155
|
+
};
|
|
156
|
+
const roles = buildRoles({
|
|
157
|
+
duration: mergedDuration,
|
|
158
|
+
cycle: mergedCycle,
|
|
159
|
+
easing: mergedEasing,
|
|
160
|
+
press: { scale: overrides.feedback?.press?.scale ?? 0.97 },
|
|
161
|
+
shake: { amplitude: overrides.feedback?.shake?.amplitude ?? 4 },
|
|
162
|
+
pulse: {
|
|
163
|
+
from: overrides.loop?.pulse?.from ?? 1,
|
|
164
|
+
to: overrides.loop?.pulse?.to ?? 0.5,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
duration: mergedDuration,
|
|
169
|
+
cycle: mergedCycle,
|
|
170
|
+
easing: mergedEasing,
|
|
171
|
+
easingBezier: mergedBezier,
|
|
172
|
+
spring: mergedSpring,
|
|
173
|
+
...roles,
|
|
174
|
+
};
|
|
175
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@castui/cast-ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0",
|
|
4
4
|
"description": "A cross-platform design system for React Native (iOS, Android, Web) with multi-theme support.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"react-dom": "^19.2.4",
|
|
66
66
|
"react-native": "^0.84.0",
|
|
67
67
|
"react-native-web": "^0.21.2",
|
|
68
|
+
"remark-gfm": "^4.0.0",
|
|
68
69
|
"storybook": "^10.2.8",
|
|
69
70
|
"typescript": "^5.9.3"
|
|
70
71
|
},
|