@mrmeg/expo-ui 0.6.0 → 0.7.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.
Files changed (54) hide show
  1. package/LLM_USAGE.md +4 -5
  2. package/README.md +6 -6
  3. package/dist/components/Accordion.js +21 -16
  4. package/dist/components/AnimatedView.d.ts +1 -1
  5. package/dist/components/AnimatedView.js +2 -2
  6. package/dist/components/Badge.d.ts +3 -2
  7. package/dist/components/Badge.js +4 -3
  8. package/dist/components/BottomSheet.js +31 -29
  9. package/dist/components/BottomSheetKeyboard.d.ts +7 -0
  10. package/dist/components/BottomSheetKeyboard.js +35 -0
  11. package/dist/components/Button.d.ts +55 -13
  12. package/dist/components/Button.js +72 -28
  13. package/dist/components/Card.js +8 -10
  14. package/dist/components/Checkbox.js +22 -25
  15. package/dist/components/Collapsible.js +3 -7
  16. package/dist/components/Dialog.js +1 -1
  17. package/dist/components/DismissKeyboard.js +3 -3
  18. package/dist/components/Drawer.js +21 -10
  19. package/dist/components/DropdownMenu.d.ts +16 -12
  20. package/dist/components/DropdownMenu.js +32 -30
  21. package/dist/components/EmptyState.js +1 -1
  22. package/dist/components/InputOTP.js +16 -40
  23. package/dist/components/Notification.js +50 -25
  24. package/dist/components/Popover.js +1 -1
  25. package/dist/components/Progress.d.ts +2 -2
  26. package/dist/components/Progress.js +36 -34
  27. package/dist/components/RadioGroup.js +22 -20
  28. package/dist/components/Select.js +30 -20
  29. package/dist/components/Skeleton.js +6 -6
  30. package/dist/components/Slider.js +90 -97
  31. package/dist/components/StyledText.context.d.ts +6 -0
  32. package/dist/components/StyledText.context.js +5 -0
  33. package/dist/components/StyledText.d.ts +7 -58
  34. package/dist/components/StyledText.js +8 -28
  35. package/dist/components/Switch.js +30 -26
  36. package/dist/components/Tabs.d.ts +23 -3
  37. package/dist/components/Tabs.js +39 -17
  38. package/dist/components/TextInput.d.ts +6 -2
  39. package/dist/components/TextInput.js +6 -7
  40. package/dist/components/Toggle.js +12 -7
  41. package/dist/components/ToggleGroup.js +17 -11
  42. package/dist/components/Tooltip.js +1 -1
  43. package/dist/hooks/useDimensions.js +25 -26
  44. package/dist/hooks/useReduceMotion.d.ts +5 -1
  45. package/dist/hooks/useReduceMotion.js +46 -41
  46. package/dist/hooks/useResources.js +6 -1
  47. package/dist/hooks/useScalePress.d.ts +6 -5
  48. package/dist/hooks/useScalePress.js +25 -21
  49. package/dist/hooks/useStaggeredEntrance.d.ts +9 -8
  50. package/dist/hooks/useStaggeredEntrance.js +48 -21
  51. package/dist/state/themeColorScope.js +3 -3
  52. package/llms-full.md +4 -5
  53. package/llms.txt +2 -2
  54. package/package.json +1 -4
@@ -1,7 +1,8 @@
1
- import { useEffect } from "react";
2
- import { useSharedValue, useAnimatedStyle, withTiming, withSpring, withDelay, useReducedMotion, Easing, } from "react-native-reanimated";
1
+ import { useEffect, useMemo, useRef } from "react";
2
+ import { Animated, Easing } from "react-native";
3
+ import { useReducedMotion } from "./useReduceMotion.js";
3
4
  /**
4
- * Hook for entrance animations with stagger support using Reanimated.
5
+ * Hook for entrance animations with stagger support using React Native Animated.
5
6
  *
6
7
  * Returns an animated style to apply to an Animated.View.
7
8
  * Respects reduced motion preferences.
@@ -22,50 +23,76 @@ import { useSharedValue, useAnimatedStyle, withTiming, withSpring, withDelay, us
22
23
  export function useStaggeredEntrance(options = {}) {
23
24
  const { type = "fadeSlideUp", delay = 0, duration = 200, slideDistance = 8, initialScale = 0.95, } = options;
24
25
  const reduceMotion = useReducedMotion();
25
- const opacity = useSharedValue(reduceMotion ? 1 : 0);
26
- const translateY = useSharedValue(reduceMotion
26
+ const opacity = useRef(new Animated.Value(reduceMotion ? 1 : 0)).current;
27
+ const translateY = useRef(new Animated.Value(reduceMotion
27
28
  ? 0
28
29
  : type === "fadeSlideUp"
29
30
  ? slideDistance
30
31
  : type === "fadeSlideDown"
31
32
  ? -slideDistance
32
- : 0);
33
- const scale = useSharedValue(reduceMotion ? 1 : type === "scale" ? initialScale : 1);
33
+ : 0)).current;
34
+ const scale = useRef(new Animated.Value(reduceMotion ? 1 : type === "scale" ? initialScale : 1)).current;
34
35
  useEffect(() => {
35
36
  if (reduceMotion) {
36
- opacity.value = 1;
37
- translateY.value = 0;
38
- scale.value = 1;
37
+ opacity.setValue(1);
38
+ translateY.setValue(0);
39
+ scale.setValue(1);
39
40
  return;
40
41
  }
42
+ opacity.setValue(0);
43
+ translateY.setValue(type === "fadeSlideUp"
44
+ ? slideDistance
45
+ : type === "fadeSlideDown"
46
+ ? -slideDistance
47
+ : 0);
48
+ scale.setValue(type === "scale" ? initialScale : 1);
41
49
  const timingConfig = {
42
50
  duration,
43
51
  easing: Easing.out(Easing.cubic),
52
+ useNativeDriver: true,
44
53
  };
45
- opacity.value = withDelay(delay, withTiming(1, timingConfig));
54
+ const animations = [
55
+ Animated.timing(opacity, {
56
+ toValue: 1,
57
+ ...timingConfig,
58
+ }),
59
+ ];
46
60
  if (type === "fadeSlideUp" || type === "fadeSlideDown") {
47
- translateY.value = withDelay(delay, withTiming(0, timingConfig));
61
+ animations.push(Animated.timing(translateY, {
62
+ toValue: 0,
63
+ ...timingConfig,
64
+ }));
48
65
  }
49
66
  if (type === "scale") {
50
- scale.value = withDelay(delay, withSpring(1, { damping: 14, stiffness: 250 }));
67
+ animations.push(Animated.spring(scale, {
68
+ toValue: 1,
69
+ damping: 14,
70
+ stiffness: 250,
71
+ useNativeDriver: true,
72
+ }));
51
73
  }
52
- }, [reduceMotion]);
53
- const animatedStyle = useAnimatedStyle(() => {
74
+ const animation = delay > 0
75
+ ? Animated.sequence([Animated.delay(delay), Animated.parallel(animations)])
76
+ : Animated.parallel(animations);
77
+ animation.start();
78
+ return () => animation.stop();
79
+ }, [delay, duration, initialScale, opacity, reduceMotion, scale, slideDistance, translateY, type]);
80
+ const animatedStyle = useMemo(() => {
54
81
  if (type === "fade") {
55
- return { opacity: opacity.value };
82
+ return { opacity };
56
83
  }
57
84
  if (type === "fadeSlideUp" || type === "fadeSlideDown") {
58
85
  return {
59
- opacity: opacity.value,
60
- transform: [{ translateY: translateY.value }],
86
+ opacity,
87
+ transform: [{ translateY }],
61
88
  };
62
89
  }
63
90
  // scale
64
91
  return {
65
- opacity: opacity.value,
66
- transform: [{ scale: scale.value }],
92
+ opacity,
93
+ transform: [{ scale }],
67
94
  };
68
- });
95
+ }, [opacity, scale, translateY, type]);
69
96
  return animatedStyle;
70
97
  }
71
98
  /**
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useMemo } from "react";
2
+ import { createContext, use, useMemo } from "react";
3
3
  /**
4
4
  * Per-subtree color overrides, layered on top of the global theme by `useTheme`.
5
5
  *
@@ -13,7 +13,7 @@ import { createContext, useContext, useMemo } from "react";
13
13
  const ThemeColorScopeContext = createContext(null);
14
14
  /** Read the active scoped override (null when not inside a scope). */
15
15
  export function useThemeColorScope() {
16
- return useContext(ThemeColorScopeContext);
16
+ return use(ThemeColorScopeContext);
17
17
  }
18
18
  // Nested scopes layer: the inner scope's keys win, the outer scope's fill in.
19
19
  function mergeScopes(parent, next) {
@@ -25,7 +25,7 @@ function mergeScopes(parent, next) {
25
25
  };
26
26
  }
27
27
  export function ThemeColorScope({ colors, children, }) {
28
- const parent = useContext(ThemeColorScopeContext);
28
+ const parent = use(ThemeColorScopeContext);
29
29
  const value = useMemo(() => mergeScopes(parent, colors), [parent, colors]);
30
30
  return (_jsx(ThemeColorScopeContext.Provider, { value: value, children: children }));
31
31
  }
package/llms-full.md CHANGED
@@ -36,10 +36,9 @@ the root when the app uses package feedback or overlay components.
36
36
  `BottomSheet`, `Drawer`, `DropdownMenu`, `Popover`, `SelectContent`,
37
37
  `Tooltip`, or `globalUIStore` notifications.
38
38
 
39
- On native, `BottomSheet.Content` composes its sheet transform with
40
- `react-native-keyboard-controller` keyboard animation values. Mount that
41
- library's `KeyboardProvider` near the app root before using bottom sheets with
42
- text inputs, or pass `avoidKeyboard={false}` for sheets that should not move.
39
+ On native, `BottomSheet.Content` composes its sheet transform with React Native
40
+ keyboard event values. Pass `avoidKeyboard={false}` for sheets that should not
41
+ move.
43
42
 
44
43
  i18n is optional. Plain children and `text` props work without `i18next` or
45
44
  `react-i18next`. Use `configureExpoUiI18n()` only when a consuming app wants
@@ -87,7 +86,7 @@ Use this catalog before creating a new app-local primitive.
87
86
  | `Alert` | `@mrmeg/expo-ui/components` | Cross-platform imperative alerts | Avoid direct `window.alert` and duplicated native/web branching. |
88
87
  | `AnimatedView` | `@mrmeg/expo-ui/components` | Entrance and visibility animation | Keep simple reveal effects in the package wrapper. |
89
88
  | `Badge` | `@mrmeg/expo-ui/components` | Short status labels | Prefer over custom pill views. |
90
- | `BottomSheet` | `@mrmeg/expo-ui/components` | Mobile-first modal sheets | Requires root `UIProvider`; native text-input sheets also require `KeyboardProvider`. |
89
+ | `BottomSheet` | `@mrmeg/expo-ui/components` | Mobile-first modal sheets | Requires root `UIProvider`; text-input sheets can disable `avoidKeyboard`. |
91
90
  | `Button` | `@mrmeg/expo-ui/components` | Commands and CTAs | Use `preset`, not `variant`; visible heights are compact. |
92
91
  | `Card` | `@mrmeg/expo-ui/components` | Individual framed content groups | Do not wrap whole page sections in cards. |
93
92
  | `Checkbox` | `@mrmeg/expo-ui/components` | Boolean selection in forms or lists | Prefer over custom checkmark controls. |
package/llms.txt CHANGED
@@ -25,8 +25,8 @@ Call useResources() once near the Expo app root. Mount UIProvider once near the
25
25
  root before using package notifications or overlay primitives: Dialog,
26
26
  AlertDialog, BottomSheet, Drawer, DropdownMenu, Popover, SelectContent, or
27
27
  Tooltip.
28
- On native, mount react-native-keyboard-controller's KeyboardProvider before
29
- using BottomSheet.Content with text inputs; avoidKeyboard defaults to true.
28
+ BottomSheet.Content uses React Native keyboard events for text inputs;
29
+ avoidKeyboard defaults to true.
30
30
 
31
31
  Use useTheme(), useStyles(), semantic tokens, StyledText, and package controls.
32
32
  Do not add app-local Appearance or matchMedia listeners for package theme sync.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrmeg/expo-ui",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "private": false,
5
5
  "description": "Reusable Expo and React Native UI primitives for MrMeg projects.",
6
6
  "keywords": [
@@ -109,12 +109,9 @@
109
109
  "react": ">=19.2.0 <20.0.0",
110
110
  "react-native": ">=0.83.0 <0.86.0",
111
111
  "react-native-gesture-handler": ">=2.30.0 <2.32.0",
112
- "react-native-keyboard-controller": ">=1.20.0 <2.0.0",
113
- "react-native-reanimated": ">=4.2.0 <5.0.0",
114
112
  "react-native-safe-area-context": ">=5.6.0 <6.0.0",
115
113
  "react-native-screens": ">=4.23.0 <5.0.0",
116
114
  "react-native-web": ">=0.21.0 <0.22.0",
117
- "react-native-worklets": ">=0.7.0 <0.9.0",
118
115
  "zustand": ">=5.0.0 <6.0.0"
119
116
  },
120
117
  "devDependencies": {