@cdx-ui/components 0.0.1-beta.79 → 0.0.1-beta.80
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/lib/commonjs/animation/hooks/index.js +17 -0
- package/lib/commonjs/animation/hooks/index.js.map +1 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js +50 -0
- package/lib/commonjs/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/commonjs/animation/index.js +39 -0
- package/lib/commonjs/animation/index.js.map +1 -0
- package/lib/commonjs/animation/types.js +6 -0
- package/lib/commonjs/animation/types.js.map +1 -0
- package/lib/commonjs/animation/utils.js +223 -0
- package/lib/commonjs/animation/utils.js.map +1 -0
- package/lib/commonjs/components/CLAUDE.md +1 -1
- package/lib/commonjs/components/Card/index.js +45 -17
- package/lib/commonjs/components/Card/index.js.map +1 -1
- package/lib/commonjs/components/Toast/animation.js +329 -0
- package/lib/commonjs/components/Toast/animation.js.map +1 -0
- package/lib/commonjs/components/Toast/hooks.js +66 -0
- package/lib/commonjs/components/Toast/hooks.js.map +1 -0
- package/lib/commonjs/components/Toast/index.js +493 -0
- package/lib/commonjs/components/Toast/index.js.map +1 -0
- package/lib/commonjs/components/Toast/styles.js +141 -0
- package/lib/commonjs/components/Toast/styles.js.map +1 -0
- package/lib/commonjs/components/Toast/types.js +6 -0
- package/lib/commonjs/components/Toast/types.js.map +1 -0
- package/lib/commonjs/components/index.js +12 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/index.js +15 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/providers/animation-settings/index.js +31 -0
- package/lib/commonjs/providers/animation-settings/index.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/provider.js +59 -0
- package/lib/commonjs/providers/animation-settings/provider.js.map +1 -0
- package/lib/commonjs/providers/animation-settings/types.js +6 -0
- package/lib/commonjs/providers/animation-settings/types.js.map +1 -0
- package/lib/commonjs/providers/forge-design/index.js +29 -0
- package/lib/commonjs/providers/forge-design/index.js.map +1 -0
- package/lib/commonjs/providers/forge-design/provider.js +71 -0
- package/lib/commonjs/providers/forge-design/provider.js.map +1 -0
- package/lib/commonjs/providers/forge-design/types.js +6 -0
- package/lib/commonjs/providers/forge-design/types.js.map +1 -0
- package/lib/commonjs/providers/text-component/index.js +28 -0
- package/lib/commonjs/providers/text-component/index.js.map +1 -0
- package/lib/commonjs/providers/text-component/provider.js +11 -0
- package/lib/commonjs/providers/text-component/provider.js.map +1 -0
- package/lib/commonjs/providers/text-component/types.js +6 -0
- package/lib/commonjs/providers/text-component/types.js.map +1 -0
- package/lib/commonjs/providers/toast/index.js +33 -0
- package/lib/commonjs/providers/toast/index.js.map +1 -0
- package/lib/commonjs/providers/toast/insets-container.js +160 -0
- package/lib/commonjs/providers/toast/insets-container.js.map +1 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js +36 -0
- package/lib/commonjs/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/commonjs/providers/toast/provider.js +508 -0
- package/lib/commonjs/providers/toast/provider.js.map +1 -0
- package/lib/commonjs/providers/toast/reducer.js +46 -0
- package/lib/commonjs/providers/toast/reducer.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-config.context.js +29 -0
- package/lib/commonjs/providers/toast/toast-config.context.js.map +1 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js +43 -0
- package/lib/commonjs/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/commonjs/providers/toast/types.js +6 -0
- package/lib/commonjs/providers/toast/types.js.map +1 -0
- package/lib/module/animation/hooks/index.js +4 -0
- package/lib/module/animation/hooks/index.js.map +1 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js +47 -0
- package/lib/module/animation/hooks/useCombinedAnimationDisabledState.js.map +1 -0
- package/lib/module/animation/index.js +6 -0
- package/lib/module/animation/index.js.map +1 -0
- package/lib/module/animation/types.js +4 -0
- package/lib/module/animation/types.js.map +1 -0
- package/lib/module/animation/utils.js +212 -0
- package/lib/module/animation/utils.js.map +1 -0
- package/lib/module/components/CLAUDE.md +1 -1
- package/lib/module/components/Card/index.js +47 -19
- package/lib/module/components/Card/index.js.map +1 -1
- package/lib/module/components/Toast/animation.js +324 -0
- package/lib/module/components/Toast/animation.js.map +1 -0
- package/lib/module/components/Toast/hooks.js +61 -0
- package/lib/module/components/Toast/hooks.js.map +1 -0
- package/lib/module/components/Toast/index.js +487 -0
- package/lib/module/components/Toast/index.js.map +1 -0
- package/lib/module/components/Toast/styles.js +138 -0
- package/lib/module/components/Toast/styles.js.map +1 -0
- package/lib/module/components/Toast/types.js +4 -0
- package/lib/module/components/Toast/types.js.map +1 -0
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/providers/animation-settings/index.js +4 -0
- package/lib/module/providers/animation-settings/index.js.map +1 -0
- package/lib/module/providers/animation-settings/provider.js +52 -0
- package/lib/module/providers/animation-settings/provider.js.map +1 -0
- package/lib/module/providers/animation-settings/types.js +4 -0
- package/lib/module/providers/animation-settings/types.js.map +1 -0
- package/lib/module/providers/forge-design/index.js +5 -0
- package/lib/module/providers/forge-design/index.js.map +1 -0
- package/lib/module/providers/forge-design/provider.js +66 -0
- package/lib/module/providers/forge-design/provider.js.map +1 -0
- package/lib/module/providers/forge-design/types.js +4 -0
- package/lib/module/providers/forge-design/types.js.map +1 -0
- package/lib/module/providers/text-component/index.js +5 -0
- package/lib/module/providers/text-component/index.js.map +1 -0
- package/lib/module/providers/text-component/provider.js +6 -0
- package/lib/module/providers/text-component/provider.js.map +1 -0
- package/lib/module/providers/text-component/types.js +4 -0
- package/lib/module/providers/text-component/types.js.map +1 -0
- package/lib/module/providers/toast/index.js +6 -0
- package/lib/module/providers/toast/index.js.map +1 -0
- package/lib/module/providers/toast/insets-container.js +156 -0
- package/lib/module/providers/toast/insets-container.js.map +1 -0
- package/lib/module/providers/toast/lifecycle.context.js +32 -0
- package/lib/module/providers/toast/lifecycle.context.js.map +1 -0
- package/lib/module/providers/toast/provider.js +503 -0
- package/lib/module/providers/toast/provider.js.map +1 -0
- package/lib/module/providers/toast/reducer.js +42 -0
- package/lib/module/providers/toast/reducer.js.map +1 -0
- package/lib/module/providers/toast/toast-config.context.js +25 -0
- package/lib/module/providers/toast/toast-config.context.js.map +1 -0
- package/lib/module/providers/toast/toast-item-renderer.js +39 -0
- package/lib/module/providers/toast/toast-item-renderer.js.map +1 -0
- package/lib/module/providers/toast/types.js +4 -0
- package/lib/module/providers/toast/types.js.map +1 -0
- package/lib/typescript/animation/hooks/index.d.ts +2 -0
- package/lib/typescript/animation/hooks/index.d.ts.map +1 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts +22 -0
- package/lib/typescript/animation/hooks/useCombinedAnimationDisabledState.d.ts.map +1 -0
- package/lib/typescript/animation/index.d.ts +4 -0
- package/lib/typescript/animation/index.d.ts.map +1 -0
- package/lib/typescript/animation/types.d.ts +105 -0
- package/lib/typescript/animation/types.d.ts.map +1 -0
- package/lib/typescript/animation/utils.d.ts +120 -0
- package/lib/typescript/animation/utils.d.ts.map +1 -0
- package/lib/typescript/components/Card/index.d.ts +4 -0
- package/lib/typescript/components/Card/index.d.ts.map +1 -1
- package/lib/typescript/components/Toast/animation.d.ts +21 -0
- package/lib/typescript/components/Toast/animation.d.ts.map +1 -0
- package/lib/typescript/components/Toast/hooks.d.ts +17 -0
- package/lib/typescript/components/Toast/hooks.d.ts.map +1 -0
- package/lib/typescript/components/Toast/index.d.ts +28 -0
- package/lib/typescript/components/Toast/index.d.ts.map +1 -0
- package/lib/typescript/components/Toast/styles.d.ts +73 -0
- package/lib/typescript/components/Toast/styles.d.ts.map +1 -0
- package/lib/typescript/components/Toast/types.d.ts +303 -0
- package/lib/typescript/components/Toast/types.d.ts.map +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/providers/animation-settings/index.d.ts +3 -0
- package/lib/typescript/providers/animation-settings/index.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts +28 -0
- package/lib/typescript/providers/animation-settings/provider.d.ts.map +1 -0
- package/lib/typescript/providers/animation-settings/types.d.ts +35 -0
- package/lib/typescript/providers/animation-settings/types.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/index.d.ts +3 -0
- package/lib/typescript/providers/forge-design/index.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/provider.d.ts +24 -0
- package/lib/typescript/providers/forge-design/provider.d.ts.map +1 -0
- package/lib/typescript/providers/forge-design/types.d.ts +82 -0
- package/lib/typescript/providers/forge-design/types.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/index.d.ts +3 -0
- package/lib/typescript/providers/text-component/index.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/provider.d.ts +7 -0
- package/lib/typescript/providers/text-component/provider.d.ts.map +1 -0
- package/lib/typescript/providers/text-component/types.d.ts +51 -0
- package/lib/typescript/providers/text-component/types.d.ts.map +1 -0
- package/lib/typescript/providers/toast/index.d.ts +5 -0
- package/lib/typescript/providers/toast/index.d.ts.map +1 -0
- package/lib/typescript/providers/toast/insets-container.d.ts +72 -0
- package/lib/typescript/providers/toast/insets-container.d.ts.map +1 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts +32 -0
- package/lib/typescript/providers/toast/lifecycle.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/provider.d.ts +32 -0
- package/lib/typescript/providers/toast/provider.d.ts.map +1 -0
- package/lib/typescript/providers/toast/reducer.d.ts +14 -0
- package/lib/typescript/providers/toast/reducer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts +20 -0
- package/lib/typescript/providers/toast/toast-config.context.d.ts.map +1 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts +7 -0
- package/lib/typescript/providers/toast/toast-item-renderer.d.ts.map +1 -0
- package/lib/typescript/providers/toast/types.d.ts +422 -0
- package/lib/typescript/providers/toast/types.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/animation/hooks/index.ts +1 -0
- package/src/animation/hooks/useCombinedAnimationDisabledState.ts +46 -0
- package/src/animation/index.ts +3 -0
- package/src/animation/types.ts +128 -0
- package/src/animation/utils.ts +249 -0
- package/src/components/CLAUDE.md +1 -1
- package/src/components/Card/index.tsx +58 -28
- package/src/components/Toast/animation.ts +387 -0
- package/src/components/Toast/hooks.ts +92 -0
- package/src/components/Toast/index.tsx +520 -0
- package/src/components/Toast/styles.ts +186 -0
- package/src/components/Toast/types.ts +332 -0
- package/src/components/index.ts +1 -0
- package/src/index.ts +2 -0
- package/src/providers/animation-settings/index.ts +11 -0
- package/src/providers/animation-settings/provider.tsx +54 -0
- package/src/providers/animation-settings/types.ts +37 -0
- package/src/providers/forge-design/index.ts +2 -0
- package/src/providers/forge-design/provider.tsx +61 -0
- package/src/providers/forge-design/types.ts +84 -0
- package/src/providers/text-component/index.ts +2 -0
- package/src/providers/text-component/provider.tsx +7 -0
- package/src/providers/text-component/types.ts +52 -0
- package/src/providers/toast/index.ts +4 -0
- package/src/providers/toast/insets-container.tsx +230 -0
- package/src/providers/toast/lifecycle.context.tsx +37 -0
- package/src/providers/toast/provider.tsx +567 -0
- package/src/providers/toast/reducer.ts +40 -0
- package/src/providers/toast/toast-config.context.ts +25 -0
- package/src/providers/toast/toast-item-renderer.tsx +40 -0
- package/src/providers/toast/types.ts +431 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useGlobalAnimationSettings,
|
|
3
|
+
useAnimationSettings,
|
|
4
|
+
} from '../../providers/animation-settings';
|
|
5
|
+
import type { AnimationRoot } from '../types';
|
|
6
|
+
import { getCombinedAnimationDisabledState, getRootAnimationState } from '../utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Hook to combine global, parent, and own animation disabled states
|
|
10
|
+
*
|
|
11
|
+
* @description
|
|
12
|
+
* This hook combines three sources of animation disabled state:
|
|
13
|
+
* 1. Global state from GlobalAnimationSettingsProvider
|
|
14
|
+
* 2. Parent state from AnimationSettingsContext (component tree cascading)
|
|
15
|
+
* 3. Own state from the component's animation prop
|
|
16
|
+
*
|
|
17
|
+
* Priority: Global > Parent > Own (global wins if enabled)
|
|
18
|
+
*
|
|
19
|
+
* @param animation - Root animation configuration for the component
|
|
20
|
+
* @returns Combined isAllAnimationsDisabled value
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const isAllAnimationsDisabled = useCombinedAnimationDisabledState(animation);
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useCombinedAnimationDisabledState<TConfig extends Record<string, any>>(
|
|
28
|
+
animation: AnimationRoot<TConfig> | undefined,
|
|
29
|
+
): boolean {
|
|
30
|
+
// Get global animation disabled state
|
|
31
|
+
const { globalIsAllAnimationsDisabled } = useGlobalAnimationSettings();
|
|
32
|
+
|
|
33
|
+
// Read parent animation disabled state from global context
|
|
34
|
+
const parentAnimationSettingsContext = useAnimationSettings();
|
|
35
|
+
const parentIsAllAnimationsDisabled = parentAnimationSettingsContext?.isAllAnimationsDisabled;
|
|
36
|
+
|
|
37
|
+
// Get own animation disabled state
|
|
38
|
+
const { isAllAnimationsDisabled: ownIsAllAnimationsDisabled } = getRootAnimationState(animation);
|
|
39
|
+
|
|
40
|
+
// Combine global, parent, and own disable-all states (global > parent > own)
|
|
41
|
+
return getCombinedAnimationDisabledState({
|
|
42
|
+
globalIsAllAnimationsDisabled,
|
|
43
|
+
parentIsAllAnimationsDisabled,
|
|
44
|
+
ownIsAllAnimationsDisabled,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseAnimationBuilder,
|
|
3
|
+
EntryOrExitLayoutType,
|
|
4
|
+
LayoutAnimationFunction,
|
|
5
|
+
WithSpringConfig,
|
|
6
|
+
WithTimingConfig,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Universal animation prop type
|
|
11
|
+
* - `true` or `undefined`: Use default animations
|
|
12
|
+
* - `false` or `"disabled"`: Disable all animations
|
|
13
|
+
* - `object`: Custom animation configuration
|
|
14
|
+
* - Can include `state?: 'disabled' | boolean | undefined` to disable animations while customizing properties
|
|
15
|
+
*/
|
|
16
|
+
export type Animation<TConfig extends Record<string, any> = Record<string, any>> =
|
|
17
|
+
| boolean
|
|
18
|
+
| 'disabled'
|
|
19
|
+
| (TConfig & { state?: 'disabled' | boolean });
|
|
20
|
+
|
|
21
|
+
export type AnimationDisabled = 'disabled' | false;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Root-level animation prop type with cascading control
|
|
25
|
+
* - `true` or `undefined`: Use default animations
|
|
26
|
+
* - `false` or `"disabled"`: Disable only root animations (children can still animate)
|
|
27
|
+
* - `"disable-all"`: Disable all animations including children (cascades down)
|
|
28
|
+
* - `object`: Custom animation configuration
|
|
29
|
+
* - Can include `state?: 'disabled' | 'disable-all' | boolean` to disable animations while customizing properties
|
|
30
|
+
*/
|
|
31
|
+
export type AnimationRoot<TConfig extends Record<string, any> = Record<string, any>> =
|
|
32
|
+
| boolean
|
|
33
|
+
| 'disabled'
|
|
34
|
+
| 'disable-all'
|
|
35
|
+
| (TConfig & { state?: 'disabled' | 'disable-all' | boolean });
|
|
36
|
+
|
|
37
|
+
export type AnimationRootDisableAll = Extract<AnimationRoot, 'disable-all'>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Animation value that can be a custom config
|
|
41
|
+
* Used for granular animation control within a component
|
|
42
|
+
*/
|
|
43
|
+
export type AnimationValue<TConfig extends Record<string, any> = Record<string, any>> = TConfig;
|
|
44
|
+
|
|
45
|
+
export type LayoutTransition =
|
|
46
|
+
| BaseAnimationBuilder
|
|
47
|
+
| LayoutAnimationFunction
|
|
48
|
+
| typeof BaseAnimationBuilder
|
|
49
|
+
| undefined;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Spring animation configuration
|
|
53
|
+
*/
|
|
54
|
+
export interface SpringAnimationConfig {
|
|
55
|
+
type: 'spring';
|
|
56
|
+
config?: WithSpringConfig;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Timing animation configuration
|
|
61
|
+
*/
|
|
62
|
+
export interface TimingAnimationConfig {
|
|
63
|
+
type: 'timing';
|
|
64
|
+
config?: WithTimingConfig;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Animation configuration for popup overlay components (Dialog, Select, BottomSheet, Popover, etc.)
|
|
69
|
+
* Supports both progress-based opacity animation and entering/exiting animations
|
|
70
|
+
*/
|
|
71
|
+
export type PopupOverlayAnimation = Animation<{
|
|
72
|
+
/**
|
|
73
|
+
* Opacity animation configuration (progress-based)
|
|
74
|
+
* Takes effect for bottom-sheet/dialog presentation
|
|
75
|
+
* @default [0, 1, 0] - opacity values for [idle, open, close] states
|
|
76
|
+
*/
|
|
77
|
+
opacity?: AnimationValue<{
|
|
78
|
+
/**
|
|
79
|
+
* Opacity values [idle, open, close]
|
|
80
|
+
* @default [0, 1, 0]
|
|
81
|
+
*/
|
|
82
|
+
value?: [number, number, number];
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Takes effect for popover presentation
|
|
86
|
+
* @default FadeIn with duration 200ms
|
|
87
|
+
*/
|
|
88
|
+
entering?: EntryOrExitLayoutType;
|
|
89
|
+
/**
|
|
90
|
+
* Takes effect for popover presentation
|
|
91
|
+
* @default FadeOut with duration 150ms
|
|
92
|
+
*/
|
|
93
|
+
exiting?: EntryOrExitLayoutType;
|
|
94
|
+
}>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Animation configuration for popup dialog content components (Dialog, Select dialog presentation)
|
|
98
|
+
* Supports opacity and scale animations
|
|
99
|
+
*/
|
|
100
|
+
export type PopupDialogContentAnimation = Animation<{
|
|
101
|
+
/**
|
|
102
|
+
* Custom Keyframe animation for entering transition
|
|
103
|
+
* @default Keyframe with scale, and opacity (200ms)
|
|
104
|
+
*/
|
|
105
|
+
entering?: EntryOrExitLayoutType;
|
|
106
|
+
/**
|
|
107
|
+
* Custom Keyframe animation for exiting transition
|
|
108
|
+
* @default Keyframe mirroring entering animation (150ms)
|
|
109
|
+
*/
|
|
110
|
+
exiting?: EntryOrExitLayoutType;
|
|
111
|
+
}>;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Animation configuration for popup popover content components (Popover, Select popover presentation)
|
|
115
|
+
* Supports custom Keyframe animations for entering and exiting transitions
|
|
116
|
+
*/
|
|
117
|
+
export type PopupPopoverContentAnimation = Animation<{
|
|
118
|
+
/**
|
|
119
|
+
* Custom Keyframe animation for entering transition
|
|
120
|
+
* @default Keyframe with translateY/translateX, scale, and opacity (200ms)
|
|
121
|
+
*/
|
|
122
|
+
entering?: EntryOrExitLayoutType;
|
|
123
|
+
/**
|
|
124
|
+
* Custom Keyframe animation for exiting transition
|
|
125
|
+
* @default Keyframe mirroring entering animation (150ms)
|
|
126
|
+
*/
|
|
127
|
+
exiting?: EntryOrExitLayoutType;
|
|
128
|
+
}>;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import type { Animation, AnimationRoot, AnimationValue } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if the entire animation is disabled
|
|
5
|
+
* @param animation - Animation configuration
|
|
6
|
+
* @returns true if animation is disabled
|
|
7
|
+
*/
|
|
8
|
+
export function isAnimationDisabled<TConfig extends Record<string, any>>(
|
|
9
|
+
animation: Animation<TConfig> | AnimationRoot<TConfig> | undefined,
|
|
10
|
+
): boolean {
|
|
11
|
+
// Check top-level disabled values
|
|
12
|
+
if (animation === false || animation === 'disabled') {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Check state property in config objects
|
|
17
|
+
if (typeof animation === 'object' && animation !== null && 'state' in animation) {
|
|
18
|
+
const state = animation.state;
|
|
19
|
+
return state === false || state === 'disabled';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if root animation should cascade disable to all children
|
|
27
|
+
* @param animation - Root animation configuration
|
|
28
|
+
* @returns true if all animations should be disabled (including children)
|
|
29
|
+
*/
|
|
30
|
+
export function shouldDisableAll<TConfig extends Record<string, any>>(
|
|
31
|
+
animation: AnimationRoot<TConfig> | undefined,
|
|
32
|
+
): boolean {
|
|
33
|
+
// Check top-level disable-all value
|
|
34
|
+
if (animation === 'disable-all') {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check state property in config objects
|
|
39
|
+
if (typeof animation === 'object' && animation !== null && 'state' in animation) {
|
|
40
|
+
const state = animation.state;
|
|
41
|
+
return state === 'disable-all';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get animation state including config and disabled status
|
|
49
|
+
* @param animation - Animation configuration
|
|
50
|
+
* @returns Object with animationConfig and isAnimationDisabled
|
|
51
|
+
*/
|
|
52
|
+
export function getAnimationState<TConfig extends Record<string, any>>(
|
|
53
|
+
animation: Animation<TConfig> | undefined,
|
|
54
|
+
): {
|
|
55
|
+
animationConfig: TConfig | undefined;
|
|
56
|
+
isAnimationDisabled: boolean;
|
|
57
|
+
} {
|
|
58
|
+
const isDisabled = isAnimationDisabled(animation);
|
|
59
|
+
// Always extract config when it's an object, regardless of disabled state
|
|
60
|
+
// This allows users to customize colors/properties even when animations are disabled
|
|
61
|
+
const config =
|
|
62
|
+
typeof animation === 'object' && animation !== null ? (animation as TConfig) : undefined;
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
animationConfig: config,
|
|
66
|
+
isAnimationDisabled: isDisabled,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get root animation state including config, disabled status, and cascade flag
|
|
72
|
+
* @param animation - Root animation configuration
|
|
73
|
+
* @returns Object with animationConfig, isAnimationDisabled, and isAllAnimationsDisabled
|
|
74
|
+
*/
|
|
75
|
+
export function getRootAnimationState<TConfig extends Record<string, any>>(
|
|
76
|
+
animation: AnimationRoot<TConfig> | undefined,
|
|
77
|
+
): {
|
|
78
|
+
animationConfig: TConfig | undefined;
|
|
79
|
+
isAnimationDisabled: boolean;
|
|
80
|
+
isAllAnimationsDisabled: boolean;
|
|
81
|
+
} {
|
|
82
|
+
const shouldCascade = shouldDisableAll(animation);
|
|
83
|
+
const isDisabled = isAnimationDisabled(animation) || shouldCascade;
|
|
84
|
+
// Always extract config when it's an object, regardless of disabled state
|
|
85
|
+
// This allows users to customize colors/properties even when animations are disabled
|
|
86
|
+
const config =
|
|
87
|
+
typeof animation === 'object' && animation !== null ? (animation as TConfig) : undefined;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
animationConfig: config,
|
|
91
|
+
isAnimationDisabled: isDisabled,
|
|
92
|
+
isAllAnimationsDisabled: shouldCascade,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get animation value property or return default
|
|
98
|
+
* Extracts a property from the animation value config object
|
|
99
|
+
*
|
|
100
|
+
* @param options - Object containing animationValue, property, and defaultValue
|
|
101
|
+
* @param options.animationValue - The animation value configuration
|
|
102
|
+
* @param options.property - Property name to extract
|
|
103
|
+
* @param options.defaultValue - Default value if property is not found
|
|
104
|
+
* @returns The property value or default (never undefined)
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const scaleValue = getAnimationValueProperty({
|
|
108
|
+
* animationValue: animation?.scale,
|
|
109
|
+
* property: 'value',
|
|
110
|
+
* defaultValue: 0.95
|
|
111
|
+
* });
|
|
112
|
+
*/
|
|
113
|
+
export function getAnimationValueProperty<
|
|
114
|
+
TConfig extends Record<string, any>,
|
|
115
|
+
K extends keyof TConfig,
|
|
116
|
+
D extends NonNullable<TConfig[K]>,
|
|
117
|
+
>(options: {
|
|
118
|
+
animationValue: AnimationValue<TConfig> | undefined;
|
|
119
|
+
property: K;
|
|
120
|
+
defaultValue: D;
|
|
121
|
+
}): D {
|
|
122
|
+
// If animation value is undefined, return default
|
|
123
|
+
if (options.animationValue === undefined) {
|
|
124
|
+
return options.defaultValue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Return the property value if it exists, otherwise return default
|
|
128
|
+
return options.animationValue[options.property] ?? options.defaultValue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get animation value merged config or return default
|
|
133
|
+
* Merges the animation value config with defaults, useful when you need multiple properties
|
|
134
|
+
*
|
|
135
|
+
* @param options - Object containing animationValue, property, and defaultValue
|
|
136
|
+
* @param options.animationValue - The animation value configuration
|
|
137
|
+
* @param options.property - Property name to extract from the config
|
|
138
|
+
* @param options.defaultValue - Default configuration object
|
|
139
|
+
* @returns The merged config object or default
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* const scaleConfig = getAnimationValueMergedConfig({
|
|
143
|
+
* animationValue: animation?.scale,
|
|
144
|
+
* property: 'timingConfig',
|
|
145
|
+
* defaultValue: { duration: 150 }
|
|
146
|
+
* });
|
|
147
|
+
*/
|
|
148
|
+
export function getAnimationValueMergedConfig<
|
|
149
|
+
TConfig extends Record<string, any>,
|
|
150
|
+
K extends keyof TConfig,
|
|
151
|
+
>(options: {
|
|
152
|
+
animationValue: AnimationValue<TConfig> | undefined;
|
|
153
|
+
property: K;
|
|
154
|
+
defaultValue: TConfig[K];
|
|
155
|
+
}): TConfig[K] {
|
|
156
|
+
// If animation value is undefined, return default
|
|
157
|
+
if (options.animationValue === undefined) {
|
|
158
|
+
return options.defaultValue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const value = options.animationValue[options.property];
|
|
162
|
+
|
|
163
|
+
// If the specific property value is undefined or not an object, return default
|
|
164
|
+
if (value === undefined || typeof value !== 'object') {
|
|
165
|
+
return options.defaultValue;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Merge with defaults to ensure all properties exist
|
|
169
|
+
return { ...options.defaultValue, ...value };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Determine if animations should be disabled based on disabled flags
|
|
174
|
+
* Priority: isAllAnimationsDisabled > isAnimationDisabled
|
|
175
|
+
*
|
|
176
|
+
* @param options - Object containing isAnimationDisabled and isAllAnimationsDisabled
|
|
177
|
+
* @param options.isAnimationDisabled - Whether animation is explicitly disabled
|
|
178
|
+
* @param options.isAllAnimationsDisabled - Whether all animations should be disabled (cascading from root/global)
|
|
179
|
+
* @returns true if animations should be disabled, false otherwise
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* const isDisabled = getIsAnimationDisabledValue({
|
|
183
|
+
* isAnimationDisabled: false,
|
|
184
|
+
* isAllAnimationsDisabled: true
|
|
185
|
+
* });
|
|
186
|
+
* // Returns: true (all animations disabled takes priority)
|
|
187
|
+
*/
|
|
188
|
+
export function getIsAnimationDisabledValue(options: {
|
|
189
|
+
isAnimationDisabled: boolean;
|
|
190
|
+
isAllAnimationsDisabled: boolean | undefined;
|
|
191
|
+
}): boolean {
|
|
192
|
+
const { isAnimationDisabled: isDisabled, isAllAnimationsDisabled } = options;
|
|
193
|
+
|
|
194
|
+
// First priority: if all animations are disabled, return true
|
|
195
|
+
if (isAllAnimationsDisabled === true) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Second priority: if this animation is disabled, return true
|
|
200
|
+
if (isDisabled) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Default: animations are enabled
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Combine global, parent, and own animation disabled states
|
|
210
|
+
* Priority: Global > Parent > Own (global wins if enabled)
|
|
211
|
+
*
|
|
212
|
+
* @param options - Object containing globalIsAllAnimationsDisabled, parentIsAllAnimationsDisabled, and ownIsAllAnimationsDisabled
|
|
213
|
+
* @param options.globalIsAllAnimationsDisabled - Whether global provider has disable-all (from GlobalAnimationSettingsProvider)
|
|
214
|
+
* @param options.parentIsAllAnimationsDisabled - Whether parent context has disable-all (from AnimationSettingsContext)
|
|
215
|
+
* @param options.ownIsAllAnimationsDisabled - Whether own animation prop has disable-all
|
|
216
|
+
* @returns Combined isAllAnimationsDisabled value (global || parent || own)
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* const combined = getCombinedAnimationDisabledState({
|
|
220
|
+
* globalIsAllAnimationsDisabled: true,
|
|
221
|
+
* parentIsAllAnimationsDisabled: false,
|
|
222
|
+
* ownIsAllAnimationsDisabled: false
|
|
223
|
+
* });
|
|
224
|
+
* // Returns: true (global wins)
|
|
225
|
+
*/
|
|
226
|
+
export function getCombinedAnimationDisabledState(options: {
|
|
227
|
+
globalIsAllAnimationsDisabled?: boolean;
|
|
228
|
+
parentIsAllAnimationsDisabled: boolean | undefined;
|
|
229
|
+
ownIsAllAnimationsDisabled: boolean;
|
|
230
|
+
}): boolean {
|
|
231
|
+
const {
|
|
232
|
+
globalIsAllAnimationsDisabled,
|
|
233
|
+
parentIsAllAnimationsDisabled,
|
|
234
|
+
ownIsAllAnimationsDisabled,
|
|
235
|
+
} = options;
|
|
236
|
+
|
|
237
|
+
// Global always wins if it has disable-all
|
|
238
|
+
if (globalIsAllAnimationsDisabled === true) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Parent wins if it has disable-all
|
|
243
|
+
if (parentIsAllAnimationsDisabled === true) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Otherwise use own value
|
|
248
|
+
return ownIsAllAnimationsDisabled;
|
|
249
|
+
}
|
package/src/components/CLAUDE.md
CHANGED
|
@@ -120,7 +120,7 @@ Where: **styled layer.** Pure styling hint with no behavior or a11y semantics
|
|
|
120
120
|
Each component follows this structure (see `Button/index.tsx`):
|
|
121
121
|
|
|
122
122
|
1. **Imports** — RN base components, primitive `Root` and `Slot` from `@cdx-ui/primitives`, `cn` + style context from `@cdx-ui/utils`, variant functions from `./styles`
|
|
123
|
-
2. **Scope constant** — `const SCOPE = 'COMPONENT_NAME'` for `
|
|
123
|
+
2. **Scope constant** — `const SCOPE = 'COMPONENT_NAME'` for `useStyleContext` with a `ParentContext.Provider` wrapper for static variant context
|
|
124
124
|
3. **Root component** — renders the primitive Root (or a host element directly when no primitive exists), spreads `dataAttributes({ slot: '<component>' })`
|
|
125
125
|
4. **Sub-slots** — each accepts `asChild`, renders a host element via `const Comp = asChild ? Slot : DefaultElement`, spreads `dataAttributes({ slot: '<component>-<slot>' })`. Sub-slots **do not** call `useButtonContext()` (or its equivalent) unless their own styling reacts to interaction state.
|
|
126
126
|
5. **Position-aware sub-slots** — icon/spinner-style slots accept `position?: 'leading' | 'trailing'` and emit `data-icon` via `dataAttributes({ icon: '...' })`.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { forwardRef, type ReactNode } from 'react';
|
|
1
|
+
import { forwardRef, useMemo, type ReactNode } from 'react';
|
|
2
2
|
import { View, type ViewProps } from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import { Slot, dataAttributes, mergeDataAttributes } from '@cdx-ui/primitives';
|
|
4
|
+
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
4
5
|
import {
|
|
5
6
|
cardContentVariants,
|
|
6
7
|
cardFooterVariants,
|
|
@@ -17,29 +18,34 @@ import {
|
|
|
17
18
|
|
|
18
19
|
const SCOPE = 'CARD';
|
|
19
20
|
|
|
20
|
-
const Root = withStyleContext(View, SCOPE);
|
|
21
|
-
|
|
22
21
|
const useCardStyleContext = () => useStyleContext(SCOPE) as CardVariantProps;
|
|
23
22
|
|
|
24
23
|
export interface CardProps extends ViewProps, CardVariantProps {
|
|
24
|
+
asChild?: boolean;
|
|
25
25
|
className?: string;
|
|
26
26
|
children?: ReactNode;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const CardRoot = forwardRef<View, CardProps>(
|
|
30
|
-
({ className, children, style, fullBleed, ...props }, ref) => {
|
|
30
|
+
({ asChild, className, children, style, fullBleed, ...props }, ref) => {
|
|
31
|
+
const parent = useParentContext();
|
|
32
|
+
const ctx = useMemo(() => ({ ...parent, [SCOPE]: { fullBleed } }), [parent, fullBleed]);
|
|
33
|
+
|
|
31
34
|
const computedClassName = cn(cardRootVariants(), className);
|
|
35
|
+
const Comp = asChild ? Slot : View;
|
|
32
36
|
|
|
33
37
|
return (
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
<ParentContext.Provider value={ctx}>
|
|
39
|
+
<Comp
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={computedClassName}
|
|
42
|
+
style={style}
|
|
43
|
+
{...props}
|
|
44
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'card' }))}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</Comp>
|
|
48
|
+
</ParentContext.Provider>
|
|
43
49
|
);
|
|
44
50
|
},
|
|
45
51
|
);
|
|
@@ -51,18 +57,26 @@ CardRoot.displayName = 'Card';
|
|
|
51
57
|
// =============================================================================
|
|
52
58
|
|
|
53
59
|
export interface CardHeaderProps extends ViewProps {
|
|
60
|
+
asChild?: boolean;
|
|
54
61
|
className?: string;
|
|
55
62
|
children?: ReactNode;
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
const CardHeader = forwardRef<View, CardHeaderProps>(
|
|
59
|
-
({ className, children, style, ...props }, ref) => {
|
|
66
|
+
({ asChild, className, children, style, ...props }, ref) => {
|
|
60
67
|
const computedClassName = cn(cardHeaderVariants(), className);
|
|
68
|
+
const Comp = asChild ? Slot : View;
|
|
61
69
|
|
|
62
70
|
return (
|
|
63
|
-
<
|
|
71
|
+
<Comp
|
|
72
|
+
ref={ref}
|
|
73
|
+
className={computedClassName}
|
|
74
|
+
style={style}
|
|
75
|
+
{...props}
|
|
76
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'card-header' }))}
|
|
77
|
+
>
|
|
64
78
|
{children}
|
|
65
|
-
</
|
|
79
|
+
</Comp>
|
|
66
80
|
);
|
|
67
81
|
},
|
|
68
82
|
);
|
|
@@ -74,22 +88,30 @@ CardHeader.displayName = 'Card.Header';
|
|
|
74
88
|
// =============================================================================
|
|
75
89
|
|
|
76
90
|
export interface CardContentProps extends ViewProps, CardContentVariantProps {
|
|
91
|
+
asChild?: boolean;
|
|
77
92
|
className?: string;
|
|
78
93
|
children?: ReactNode;
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
const CardContent = forwardRef<View, CardContentProps>(
|
|
82
|
-
({ className, children, style, fullBleed, ...props }, ref) => {
|
|
97
|
+
({ asChild, className, children, style, fullBleed, ...props }, ref) => {
|
|
83
98
|
const { fullBleed: fullBleedFromContext } = useCardStyleContext();
|
|
84
99
|
const computedClassName = cn(
|
|
85
100
|
cardContentVariants({ fullBleed: fullBleed ?? fullBleedFromContext }),
|
|
86
101
|
className,
|
|
87
102
|
);
|
|
103
|
+
const Comp = asChild ? Slot : View;
|
|
88
104
|
|
|
89
105
|
return (
|
|
90
|
-
<
|
|
106
|
+
<Comp
|
|
107
|
+
ref={ref}
|
|
108
|
+
className={computedClassName}
|
|
109
|
+
style={style}
|
|
110
|
+
{...props}
|
|
111
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'card-content' }))}
|
|
112
|
+
>
|
|
91
113
|
{children}
|
|
92
|
-
</
|
|
114
|
+
</Comp>
|
|
93
115
|
);
|
|
94
116
|
},
|
|
95
117
|
);
|
|
@@ -101,22 +123,30 @@ CardContent.displayName = 'Card.Content';
|
|
|
101
123
|
// =============================================================================
|
|
102
124
|
|
|
103
125
|
export interface CardFooterProps extends ViewProps, CardFooterVariantProps {
|
|
126
|
+
asChild?: boolean;
|
|
104
127
|
className?: string;
|
|
105
128
|
children?: ReactNode;
|
|
106
129
|
}
|
|
107
130
|
|
|
108
131
|
const CardFooter = forwardRef<View, CardFooterProps>(
|
|
109
|
-
({ className, children, style, fullBleed, ...props }, ref) => {
|
|
132
|
+
({ asChild, className, children, style, fullBleed, ...props }, ref) => {
|
|
110
133
|
const { fullBleed: fullBleedFromContext } = useCardStyleContext();
|
|
111
134
|
const computedClassName = cn(
|
|
112
135
|
cardFooterVariants({ fullBleed: fullBleed ?? fullBleedFromContext }),
|
|
113
136
|
className,
|
|
114
137
|
);
|
|
138
|
+
const Comp = asChild ? Slot : View;
|
|
115
139
|
|
|
116
140
|
return (
|
|
117
|
-
<
|
|
141
|
+
<Comp
|
|
142
|
+
ref={ref}
|
|
143
|
+
className={computedClassName}
|
|
144
|
+
style={style}
|
|
145
|
+
{...props}
|
|
146
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'card-footer' }))}
|
|
147
|
+
>
|
|
118
148
|
{children}
|
|
119
|
-
</
|
|
149
|
+
</Comp>
|
|
120
150
|
);
|
|
121
151
|
},
|
|
122
152
|
);
|
|
@@ -133,8 +163,8 @@ type CardCompoundComponent = typeof CardRoot & {
|
|
|
133
163
|
Footer: typeof CardFooter;
|
|
134
164
|
};
|
|
135
165
|
|
|
136
|
-
export const Card = CardRoot
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
166
|
+
export const Card = Object.assign(CardRoot, {
|
|
167
|
+
Header: CardHeader,
|
|
168
|
+
Content: CardContent,
|
|
169
|
+
Footer: CardFooter,
|
|
170
|
+
}) as CardCompoundComponent;
|