@metacells/mcellui-core 0.1.2 → 0.2.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/dist/index-DtYPPizh.d.ts +682 -0
- package/dist/index.d.ts +3851 -0
- package/dist/index.js +7191 -0
- package/dist/index.js.map +1 -0
- package/dist/shadows-CwlbfJco.d.ts +194 -0
- package/dist/tokens/index.d.ts +17 -0
- package/dist/tokens/index.js +176 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +4150 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +18 -11
- package/src/components/ErrorBoundary.tsx +0 -188
- package/src/components/index.ts +0 -6
- package/src/config/ConfigProvider.tsx +0 -145
- package/src/config/defineConfig.ts +0 -75
- package/src/config/index.ts +0 -42
- package/src/config/types.ts +0 -185
- package/src/constants.ts +0 -203
- package/src/index.ts +0 -144
- package/src/primitives/Portal.tsx +0 -185
- package/src/primitives/Pressable.tsx +0 -114
- package/src/primitives/Slot.tsx +0 -177
- package/src/primitives/index.ts +0 -19
- package/src/theme/ThemeProvider.tsx +0 -506
- package/src/theme/animations.ts +0 -381
- package/src/theme/colors.ts +0 -266
- package/src/theme/components.ts +0 -267
- package/src/theme/index.ts +0 -130
- package/src/theme/presets.ts +0 -341
- package/src/theme/radius.ts +0 -175
- package/src/theme/shadows.ts +0 -166
- package/src/theme/spacing.ts +0 -41
- package/src/theme/typography.ts +0 -389
- package/src/tokens/colors.ts +0 -67
- package/src/tokens/index.ts +0 -29
- package/src/tokens/radius.ts +0 -18
- package/src/tokens/shadows.ts +0 -38
- package/src/tokens/spacing.ts +0 -45
- package/src/tokens/typography.ts +0 -70
- package/src/utils/accessibility.ts +0 -112
- package/src/utils/cn.ts +0 -58
- package/src/utils/expoGo.ts +0 -72
- package/src/utils/haptics.ts +0 -125
- package/src/utils/index.ts +0 -33
- package/src/utils/platform.ts +0 -66
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Accessibility Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helpers for building accessible components
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { AccessibilityRole, AccessibilityState } from 'react-native';
|
|
8
|
-
|
|
9
|
-
export interface A11yProps {
|
|
10
|
-
accessible?: boolean;
|
|
11
|
-
accessibilityLabel?: string;
|
|
12
|
-
accessibilityHint?: string;
|
|
13
|
-
accessibilityRole?: AccessibilityRole;
|
|
14
|
-
accessibilityState?: AccessibilityState;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates accessibility props for a button
|
|
19
|
-
*/
|
|
20
|
-
export function buttonA11y(
|
|
21
|
-
label: string,
|
|
22
|
-
options?: {
|
|
23
|
-
hint?: string;
|
|
24
|
-
disabled?: boolean;
|
|
25
|
-
selected?: boolean;
|
|
26
|
-
}
|
|
27
|
-
): A11yProps {
|
|
28
|
-
return {
|
|
29
|
-
accessible: true,
|
|
30
|
-
accessibilityRole: 'button',
|
|
31
|
-
accessibilityLabel: label,
|
|
32
|
-
accessibilityHint: options?.hint,
|
|
33
|
-
accessibilityState: {
|
|
34
|
-
disabled: options?.disabled,
|
|
35
|
-
selected: options?.selected,
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Creates accessibility props for a checkbox/switch
|
|
42
|
-
*/
|
|
43
|
-
export function toggleA11y(
|
|
44
|
-
label: string,
|
|
45
|
-
checked: boolean,
|
|
46
|
-
options?: {
|
|
47
|
-
hint?: string;
|
|
48
|
-
disabled?: boolean;
|
|
49
|
-
}
|
|
50
|
-
): A11yProps {
|
|
51
|
-
return {
|
|
52
|
-
accessible: true,
|
|
53
|
-
accessibilityRole: 'switch',
|
|
54
|
-
accessibilityLabel: label,
|
|
55
|
-
accessibilityHint: options?.hint,
|
|
56
|
-
accessibilityState: {
|
|
57
|
-
checked,
|
|
58
|
-
disabled: options?.disabled,
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Creates accessibility props for a link
|
|
65
|
-
*/
|
|
66
|
-
export function linkA11y(
|
|
67
|
-
label: string,
|
|
68
|
-
options?: {
|
|
69
|
-
hint?: string;
|
|
70
|
-
}
|
|
71
|
-
): A11yProps {
|
|
72
|
-
return {
|
|
73
|
-
accessible: true,
|
|
74
|
-
accessibilityRole: 'link',
|
|
75
|
-
accessibilityLabel: label,
|
|
76
|
-
accessibilityHint: options?.hint ?? 'Double tap to open',
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Creates accessibility props for an image
|
|
82
|
-
*/
|
|
83
|
-
export function imageA11y(
|
|
84
|
-
label: string,
|
|
85
|
-
options?: {
|
|
86
|
-
decorative?: boolean;
|
|
87
|
-
}
|
|
88
|
-
): A11yProps {
|
|
89
|
-
if (options?.decorative) {
|
|
90
|
-
return {
|
|
91
|
-
accessible: false,
|
|
92
|
-
accessibilityLabel: undefined,
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
accessible: true,
|
|
98
|
-
accessibilityRole: 'image',
|
|
99
|
-
accessibilityLabel: label,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Creates accessibility props for a heading
|
|
105
|
-
*/
|
|
106
|
-
export function headingA11y(label: string): A11yProps {
|
|
107
|
-
return {
|
|
108
|
-
accessible: true,
|
|
109
|
-
accessibilityRole: 'header',
|
|
110
|
-
accessibilityLabel: label,
|
|
111
|
-
};
|
|
112
|
-
}
|
package/src/utils/cn.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cn() - Class Name / Style Merger
|
|
3
|
-
*
|
|
4
|
-
* The core utility for merging styles in mcellui.
|
|
5
|
-
* Inspired by shadcn/ui's cn() but adapted for React Native StyleSheet.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
|
|
9
|
-
|
|
10
|
-
type Style = ViewStyle | TextStyle | ImageStyle;
|
|
11
|
-
type StyleInput = Style | Style[] | null | undefined | false;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Merges multiple style objects into a single flattened style.
|
|
15
|
-
* Handles undefined, null, false, and nested arrays.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```tsx
|
|
19
|
-
* const styles = cn(
|
|
20
|
-
* baseStyles.container,
|
|
21
|
-
* isActive && activeStyles,
|
|
22
|
-
* { padding: 16 }
|
|
23
|
-
* );
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export function cn(...inputs: StyleInput[]): Style {
|
|
27
|
-
const styles: Style[] = [];
|
|
28
|
-
|
|
29
|
-
for (const input of inputs) {
|
|
30
|
-
if (!input) continue;
|
|
31
|
-
|
|
32
|
-
if (Array.isArray(input)) {
|
|
33
|
-
const flattened = StyleSheet.flatten(input);
|
|
34
|
-
if (flattened) styles.push(flattened);
|
|
35
|
-
} else {
|
|
36
|
-
styles.push(input);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return StyleSheet.flatten(styles);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Creates a style object from conditional styles.
|
|
45
|
-
* More explicit alternative to cn() for complex conditions.
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```tsx
|
|
49
|
-
* const styles = mergeStyles({
|
|
50
|
-
* base: baseStyle,
|
|
51
|
-
* active: isActive && activeStyle,
|
|
52
|
-
* disabled: isDisabled && disabledStyle,
|
|
53
|
-
* });
|
|
54
|
-
* ```
|
|
55
|
-
*/
|
|
56
|
-
export function mergeStyles(styles: Record<string, StyleInput>): Style {
|
|
57
|
-
return cn(...Object.values(styles));
|
|
58
|
-
}
|
package/src/utils/expoGo.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Expo Go Detection Utility
|
|
3
|
-
*
|
|
4
|
-
* Provides detection for Expo Go environment to gracefully disable
|
|
5
|
-
* Reanimated animations when running in Expo Go client.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```tsx
|
|
9
|
-
* import { isExpoGo, areAnimationsDisabled } from '@metacells/mcellui-core';
|
|
10
|
-
*
|
|
11
|
-
* // Check environment
|
|
12
|
-
* if (isExpoGo()) {
|
|
13
|
-
* console.log('Running in Expo Go');
|
|
14
|
-
* }
|
|
15
|
-
*
|
|
16
|
-
* // Check if animations should be disabled
|
|
17
|
-
* if (areAnimationsDisabled()) {
|
|
18
|
-
* // Skip animation, use static styles
|
|
19
|
-
* }
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
let executionEnvironment: string | undefined;
|
|
24
|
-
|
|
25
|
-
// Try to load expo-constants at module load time
|
|
26
|
-
try {
|
|
27
|
-
// Dynamic require to avoid bundler issues when expo-constants is not available
|
|
28
|
-
const Constants = require('expo-constants').default;
|
|
29
|
-
executionEnvironment = Constants?.executionEnvironment;
|
|
30
|
-
} catch {
|
|
31
|
-
// expo-constants not available - not in Expo environment
|
|
32
|
-
executionEnvironment = undefined;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Check if the app is running in Expo Go client.
|
|
37
|
-
* Returns false in development builds, production builds, or non-Expo environments.
|
|
38
|
-
*/
|
|
39
|
-
export function isExpoGo(): boolean {
|
|
40
|
-
return executionEnvironment === 'storeClient';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Internal state for animation override
|
|
44
|
-
let animationsDisabledOverride: boolean | null = null;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Manually override the animation disabled state.
|
|
48
|
-
* Set to `true` to force disable animations, `false` to force enable,
|
|
49
|
-
* or `null` to use automatic detection (Expo Go = disabled).
|
|
50
|
-
*
|
|
51
|
-
* @param disabled - Override value or null for automatic
|
|
52
|
-
*/
|
|
53
|
-
export function setAnimationsDisabled(disabled: boolean | null): void {
|
|
54
|
-
animationsDisabledOverride = disabled;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Check if animations should be disabled.
|
|
59
|
-
* Returns true if:
|
|
60
|
-
* - Manually overridden to true via setAnimationsDisabled(true)
|
|
61
|
-
* - Running in Expo Go (automatic detection)
|
|
62
|
-
*
|
|
63
|
-
* Returns false if:
|
|
64
|
-
* - Manually overridden to false via setAnimationsDisabled(false)
|
|
65
|
-
* - Running in development/production build
|
|
66
|
-
*/
|
|
67
|
-
export function areAnimationsDisabled(): boolean {
|
|
68
|
-
if (animationsDisabledOverride !== null) {
|
|
69
|
-
return animationsDisabledOverride;
|
|
70
|
-
}
|
|
71
|
-
return isExpoGo();
|
|
72
|
-
}
|
package/src/utils/haptics.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Haptics Utilities
|
|
3
|
-
*
|
|
4
|
-
* Unified haptic feedback interface.
|
|
5
|
-
* Falls back gracefully when expo-haptics is not available.
|
|
6
|
-
*
|
|
7
|
-
* Design Philosophy:
|
|
8
|
-
* - Every interactive element should provide tactile feedback
|
|
9
|
-
* - Haptics should be subtle and purposeful
|
|
10
|
-
* - Respect user's haptic preferences
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
export type HapticStyle = 'light' | 'medium' | 'heavy' | 'success' | 'warning' | 'error' | 'selection';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Haptic presets for common interactions
|
|
17
|
-
*/
|
|
18
|
-
export const hapticPresets = {
|
|
19
|
-
/** For button presses, checkbox toggles */
|
|
20
|
-
buttonPress: 'light' as HapticStyle,
|
|
21
|
-
/** For switch toggles */
|
|
22
|
-
toggle: 'medium' as HapticStyle,
|
|
23
|
-
/** For successful actions */
|
|
24
|
-
success: 'success' as HapticStyle,
|
|
25
|
-
/** For errors */
|
|
26
|
-
error: 'error' as HapticStyle,
|
|
27
|
-
/** For selection changes (radio, picker) */
|
|
28
|
-
selection: 'selection' as HapticStyle,
|
|
29
|
-
/** For destructive actions */
|
|
30
|
-
destructive: 'warning' as HapticStyle,
|
|
31
|
-
} as const;
|
|
32
|
-
|
|
33
|
-
let Haptics: typeof import('expo-haptics') | null = null;
|
|
34
|
-
|
|
35
|
-
// Try to load expo-haptics (optional dependency)
|
|
36
|
-
try {
|
|
37
|
-
Haptics = require('expo-haptics');
|
|
38
|
-
} catch {
|
|
39
|
-
// expo-haptics not available, haptics will be no-ops
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
-
// Global Haptics State
|
|
44
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
45
|
-
|
|
46
|
-
let hapticsEnabled = true;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Enable or disable haptic feedback globally.
|
|
50
|
-
* Use this to respect user preferences or accessibility settings.
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* ```tsx
|
|
54
|
-
* // In ThemeProvider or app setup
|
|
55
|
-
* setHapticsEnabled(false);
|
|
56
|
-
*
|
|
57
|
-
* // Or via config
|
|
58
|
-
* <ThemeProvider haptics={false}>
|
|
59
|
-
* ```
|
|
60
|
-
*/
|
|
61
|
-
export function setHapticsEnabled(enabled: boolean): void {
|
|
62
|
-
hapticsEnabled = enabled;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Check if haptics are currently enabled
|
|
67
|
-
*/
|
|
68
|
-
export function isHapticsEnabled(): boolean {
|
|
69
|
-
return hapticsEnabled && Haptics !== null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Trigger haptic feedback
|
|
74
|
-
*
|
|
75
|
-
* Respects the global haptics enabled state. Disabled via:
|
|
76
|
-
* - `setHapticsEnabled(false)`
|
|
77
|
-
* - `<ThemeProvider haptics={false}>`
|
|
78
|
-
* - `mcellui.config.ts` with `haptics: false`
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```tsx
|
|
82
|
-
* onPress={() => {
|
|
83
|
-
* haptic('light');
|
|
84
|
-
* // ... rest of handler
|
|
85
|
-
* }}
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
export async function haptic(style: HapticStyle = 'light'): Promise<void> {
|
|
89
|
-
if (!hapticsEnabled || !Haptics) return;
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
switch (style) {
|
|
93
|
-
case 'light':
|
|
94
|
-
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
|
95
|
-
break;
|
|
96
|
-
case 'medium':
|
|
97
|
-
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
|
|
98
|
-
break;
|
|
99
|
-
case 'heavy':
|
|
100
|
-
await Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy);
|
|
101
|
-
break;
|
|
102
|
-
case 'success':
|
|
103
|
-
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
|
104
|
-
break;
|
|
105
|
-
case 'warning':
|
|
106
|
-
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Warning);
|
|
107
|
-
break;
|
|
108
|
-
case 'error':
|
|
109
|
-
await Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
|
|
110
|
-
break;
|
|
111
|
-
case 'selection':
|
|
112
|
-
await Haptics.selectionAsync();
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
} catch {
|
|
116
|
-
// Silently fail if haptics not supported
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Check if haptics are available
|
|
122
|
-
*/
|
|
123
|
-
export function hapticsAvailable(): boolean {
|
|
124
|
-
return Haptics !== null;
|
|
125
|
-
}
|
package/src/utils/index.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export { cn, mergeStyles } from './cn';
|
|
2
|
-
export {
|
|
3
|
-
isIOS,
|
|
4
|
-
isAndroid,
|
|
5
|
-
isWeb,
|
|
6
|
-
iosVersion,
|
|
7
|
-
androidApiLevel,
|
|
8
|
-
isTablet,
|
|
9
|
-
pixelRatio,
|
|
10
|
-
roundToNearestPixel,
|
|
11
|
-
getFontScale,
|
|
12
|
-
} from './platform';
|
|
13
|
-
export {
|
|
14
|
-
buttonA11y,
|
|
15
|
-
toggleA11y,
|
|
16
|
-
linkA11y,
|
|
17
|
-
imageA11y,
|
|
18
|
-
headingA11y,
|
|
19
|
-
type A11yProps,
|
|
20
|
-
} from './accessibility';
|
|
21
|
-
export {
|
|
22
|
-
haptic,
|
|
23
|
-
hapticsAvailable,
|
|
24
|
-
setHapticsEnabled,
|
|
25
|
-
isHapticsEnabled,
|
|
26
|
-
hapticPresets,
|
|
27
|
-
type HapticStyle,
|
|
28
|
-
} from './haptics';
|
|
29
|
-
export {
|
|
30
|
-
isExpoGo,
|
|
31
|
-
setAnimationsDisabled,
|
|
32
|
-
areAnimationsDisabled,
|
|
33
|
-
} from './expoGo';
|
package/src/utils/platform.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helpers for platform-specific behavior
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { Platform, Dimensions, PixelRatio } from 'react-native';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Check if running on iOS
|
|
11
|
-
*/
|
|
12
|
-
export const isIOS = Platform.OS === 'ios';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Check if running on Android
|
|
16
|
-
*/
|
|
17
|
-
export const isAndroid = Platform.OS === 'android';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Check if running on web
|
|
21
|
-
*/
|
|
22
|
-
export const isWeb = Platform.OS === 'web';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Get iOS version (returns 0 on non-iOS)
|
|
26
|
-
*/
|
|
27
|
-
export const iosVersion = isIOS
|
|
28
|
-
? parseInt(String(Platform.Version), 10)
|
|
29
|
-
: 0;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Get Android API level (returns 0 on non-Android)
|
|
33
|
-
*/
|
|
34
|
-
export const androidApiLevel = isAndroid
|
|
35
|
-
? (Platform.Version as number)
|
|
36
|
-
: 0;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Check if device is a tablet (rough heuristic)
|
|
40
|
-
*/
|
|
41
|
-
export function isTablet(): boolean {
|
|
42
|
-
const { width, height } = Dimensions.get('window');
|
|
43
|
-
const aspectRatio = Math.max(width, height) / Math.min(width, height);
|
|
44
|
-
const isLargeScreen = Math.min(width, height) >= 600;
|
|
45
|
-
|
|
46
|
-
return isLargeScreen && aspectRatio < 1.6;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Get pixel ratio for crisp rendering
|
|
51
|
-
*/
|
|
52
|
-
export const pixelRatio = PixelRatio.get();
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Round to nearest pixel for crisp lines
|
|
56
|
-
*/
|
|
57
|
-
export function roundToNearestPixel(value: number): number {
|
|
58
|
-
return PixelRatio.roundToNearestPixel(value);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Get safe font scale (clamped for accessibility)
|
|
63
|
-
*/
|
|
64
|
-
export function getFontScale(maxScale = 1.3): number {
|
|
65
|
-
return Math.min(PixelRatio.getFontScale(), maxScale);
|
|
66
|
-
}
|