@idealyst/components 1.2.44 → 1.2.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/components",
3
- "version": "1.2.44",
3
+ "version": "1.2.45",
4
4
  "description": "Shared component library for React and React Native",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
6
6
  "readme": "README.md",
@@ -56,7 +56,7 @@
56
56
  "publish:npm": "npm publish"
57
57
  },
58
58
  "peerDependencies": {
59
- "@idealyst/theme": "^1.2.44",
59
+ "@idealyst/theme": "^1.2.45",
60
60
  "@mdi/js": ">=7.0.0",
61
61
  "@mdi/react": ">=1.0.0",
62
62
  "@react-native-vector-icons/common": ">=12.0.0",
@@ -107,7 +107,7 @@
107
107
  },
108
108
  "devDependencies": {
109
109
  "@idealyst/blur": "^1.2.40",
110
- "@idealyst/theme": "^1.2.44",
110
+ "@idealyst/theme": "^1.2.45",
111
111
  "@idealyst/tooling": "^1.2.30",
112
112
  "@mdi/react": "^1.6.1",
113
113
  "@types/react": "^19.1.0",
@@ -34,6 +34,10 @@ export const IconSvg: React.FC<IconSvgProps> = ({
34
34
  // Look up path from registry
35
35
  const path = IconRegistry.get(name);
36
36
 
37
+ // Convert numeric size to pixel string to prevent @mdi/react from
38
+ // treating it as a multiplier of the base 24px size
39
+ const normalizedSize = typeof size === 'number' ? `${size}px` : size;
40
+
37
41
  // Warn in development if icon is not registered
38
42
  if (!path && process.env.NODE_ENV !== 'production') {
39
43
  console.warn(
@@ -51,7 +55,7 @@ export const IconSvg: React.FC<IconSvgProps> = ({
51
55
  style={style}
52
56
  className={className}
53
57
  path={path}
54
- size={size}
58
+ size={normalizedSize}
55
59
  color={color}
56
60
  aria-label={ariaLabel || name}
57
61
  data-testid={testID}
@@ -1,5 +1,6 @@
1
- import { forwardRef } from 'react';
2
- import { View as RNView, ScrollView as RNScrollView, KeyboardAvoidingView, Platform } from 'react-native';
1
+ import { forwardRef, useEffect } from 'react';
2
+ import { View as RNView, ScrollView as RNScrollView, Keyboard, Platform } from 'react-native';
3
+ import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
3
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
5
  import { ScreenProps } from './types';
5
6
  import { screenStyles } from './Screen.styles';
@@ -27,6 +28,40 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
27
28
  }, ref) => {
28
29
  const insets = useSafeAreaInsets();
29
30
 
31
+ // Animated keyboard offset
32
+ const keyboardOffset = useSharedValue(0);
33
+
34
+ // Listen for keyboard events and animate
35
+ useEffect(() => {
36
+ if (!avoidKeyboard) return;
37
+
38
+ const showEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
39
+ const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
40
+
41
+ const showSubscription = Keyboard.addListener(showEvent, (e) => {
42
+ keyboardOffset.value = withTiming(e.endCoordinates.height, {
43
+ duration: Platform.OS === 'ios' ? e.duration : 250,
44
+ easing: Easing.out(Easing.cubic),
45
+ });
46
+ });
47
+
48
+ const hideSubscription = Keyboard.addListener(hideEvent, (e) => {
49
+ keyboardOffset.value = withTiming(0, {
50
+ duration: Platform.OS === 'ios' ? (e.duration ?? 250) : 250,
51
+ easing: Easing.out(Easing.cubic),
52
+ });
53
+ });
54
+
55
+ return () => {
56
+ showSubscription.remove();
57
+ hideSubscription.remove();
58
+ };
59
+ }, [avoidKeyboard]);
60
+
61
+ const animatedKeyboardStyle = useAnimatedStyle(() => ({
62
+ paddingBottom: keyboardOffset.value,
63
+ }));
64
+
30
65
  // Handle 'transparent' background separately since it's not a surface color key
31
66
  // The $surface iterator only expands to actual surface color keys
32
67
  const backgroundVariant = background === 'transparent' ? undefined : background;
@@ -55,13 +90,6 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
55
90
  paddingRight: insets.right,
56
91
  } : undefined;
57
92
 
58
- // Wrapper component for keyboard avoidance
59
- const KeyboardWrapper = avoidKeyboard ? KeyboardAvoidingView : RNView;
60
- const keyboardWrapperProps = avoidKeyboard ? {
61
- behavior: Platform.OS === 'ios' ? 'padding' as const : 'height' as const,
62
- style: { flex: 1 },
63
- } : { style: { flex: 1 } };
64
-
65
93
  if (scrollable) {
66
94
  // Content styles applied via View wrapper for Unistyles reactivity
67
95
  // (contentContainerStyle isn't reactive, only style prop is)
@@ -73,7 +101,7 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
73
101
  } : safeAreaStyle;
74
102
 
75
103
  return (
76
- <KeyboardWrapper {...keyboardWrapperProps}>
104
+ <Animated.View style={[{ flex: 1 }, avoidKeyboard && animatedKeyboardStyle]}>
77
105
  <RNScrollView
78
106
  ref={ref as any}
79
107
  nativeID={id}
@@ -87,16 +115,16 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
87
115
  {children}
88
116
  </RNView>
89
117
  </RNScrollView>
90
- </KeyboardWrapper>
118
+ </Animated.View>
91
119
  );
92
120
  }
93
121
 
94
122
  return (
95
- <KeyboardWrapper {...keyboardWrapperProps}>
123
+ <Animated.View style={[{ flex: 1 }, avoidKeyboard && animatedKeyboardStyle]}>
96
124
  <RNView ref={ref as any} nativeID={id} style={[screenStyle, safeAreaStyle, style]} testID={testID} onLayout={onLayout}>
97
125
  {children}
98
126
  </RNView>
99
- </KeyboardWrapper>
127
+ </Animated.View>
100
128
  );
101
129
  });
102
130