@idealyst/components 1.2.121 → 1.2.123

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.121",
3
+ "version": "1.2.123",
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,12 +56,13 @@
56
56
  "publish:npm": "npm publish"
57
57
  },
58
58
  "peerDependencies": {
59
- "@idealyst/theme": "^1.2.121",
59
+ "@idealyst/theme": "^1.2.123",
60
60
  "@mdi/js": ">=7.0.0",
61
61
  "@mdi/react": ">=1.0.0",
62
62
  "@react-native-vector-icons/common": ">=12.0.0",
63
63
  "@react-native-vector-icons/material-design-icons": ">=12.0.0",
64
64
  "@react-native/normalize-colors": "*",
65
+ "@react-navigation/bottom-tabs": ">=7.0.0",
65
66
  "react": ">=16.8.0",
66
67
  "react-native": ">=0.60.0",
67
68
  "react-native-edge-to-edge": "*",
@@ -80,6 +81,9 @@
80
81
  "@mdi/react": {
81
82
  "optional": true
82
83
  },
84
+ "@react-navigation/bottom-tabs": {
85
+ "optional": true
86
+ },
83
87
  "@react-native/normalize-colors": {
84
88
  "optional": true
85
89
  },
@@ -107,8 +111,8 @@
107
111
  },
108
112
  "devDependencies": {
109
113
  "@idealyst/blur": "^1.2.40",
110
- "@idealyst/theme": "^1.2.121",
111
- "@idealyst/tooling": "^1.2.121",
114
+ "@idealyst/theme": "^1.2.123",
115
+ "@idealyst/tooling": "^1.2.123",
112
116
  "@mdi/react": "^1.6.1",
113
117
  "@types/react": "^19.1.0",
114
118
  "react": "^19.1.0",
@@ -155,6 +155,14 @@ export const menuStyles = defineStyle('Menu', (theme: Theme) => ({
155
155
  height: theme.sizes.$menu.iconSize,
156
156
  fontSize: theme.sizes.$menu.iconSize,
157
157
  },
158
+ intent: {
159
+ neutral: {},
160
+ primary: { color: theme.intents.primary.primary },
161
+ success: { color: theme.intents.success.primary },
162
+ danger: { color: theme.intents.danger.primary },
163
+ warning: { color: theme.intents.warning.primary },
164
+ info: { color: theme.intents.info.primary },
165
+ },
158
166
  },
159
167
  }),
160
168
 
@@ -165,6 +173,14 @@ export const menuStyles = defineStyle('Menu', (theme: Theme) => ({
165
173
  size: {
166
174
  fontSize: theme.sizes.$menu.labelFontSize,
167
175
  },
176
+ intent: {
177
+ neutral: {},
178
+ primary: { color: theme.intents.primary.primary },
179
+ success: { color: theme.intents.success.primary },
180
+ danger: { color: theme.intents.danger.primary },
181
+ warning: { color: theme.intents.warning.primary },
182
+ info: { color: theme.intents.info.primary },
183
+ },
168
184
  },
169
185
  }),
170
186
  }));
@@ -20,9 +20,10 @@ const MenuItem = forwardRef<IdealystElement, MenuItemProps>(({ item, onPress, si
20
20
  });
21
21
 
22
22
  // Call styles as functions to get theme-reactive styles
23
- const itemStyle = (menuItemStyles.item as any)({ intent: item.intent || 'neutral' });
24
- const iconStyle = (menuItemStyles.icon as any)({});
25
- const labelStyle = (menuItemStyles.label as any)({});
23
+ const intent = item.intent || 'neutral';
24
+ const itemStyle = (menuItemStyles.item as any)({ intent });
25
+ const iconStyle = (menuItemStyles.icon as any)({ intent });
26
+ const labelStyle = (menuItemStyles.label as any)({ intent });
26
27
 
27
28
  // Extract icon size from theme variant (fontSize is set by $menu.iconSize)
28
29
  const iconSize = iconStyle.fontSize || iconStyle.width || 20;
@@ -118,6 +118,14 @@ export const menuItemStyles = defineStyle('MenuItem', (theme: Theme) => ({
118
118
  height: theme.sizes.$menu.iconSize,
119
119
  fontSize: theme.sizes.$menu.iconSize,
120
120
  },
121
+ intent: {
122
+ neutral: {},
123
+ primary: { color: theme.intents.primary.primary },
124
+ success: { color: theme.intents.success.primary },
125
+ danger: { color: theme.intents.danger.primary },
126
+ warning: { color: theme.intents.warning.primary },
127
+ info: { color: theme.intents.info.primary },
128
+ },
121
129
  },
122
130
  _web: {
123
131
  display: 'flex',
@@ -131,6 +139,14 @@ export const menuItemStyles = defineStyle('MenuItem', (theme: Theme) => ({
131
139
  size: {
132
140
  fontSize: theme.sizes.$menu.labelFontSize,
133
141
  },
142
+ intent: {
143
+ neutral: {},
144
+ primary: { color: theme.intents.primary.primary },
145
+ success: { color: theme.intents.success.primary },
146
+ danger: { color: theme.intents.danger.primary },
147
+ warning: { color: theme.intents.warning.primary },
148
+ info: { color: theme.intents.info.primary },
149
+ },
134
150
  },
135
151
  }),
136
152
  }));
@@ -22,9 +22,10 @@ const MenuItem = forwardRef<IdealystElement, MenuItemProps>(({ item, onPress, si
22
22
  });
23
23
 
24
24
  // Compute dynamic styles - call as functions for theme reactivity
25
- const itemStyle = (menuItemStyles.item as any)({ intent: item.intent || 'neutral' });
26
- const iconStyle = (menuItemStyles.icon as any)({});
27
- const labelStyle = (menuItemStyles.label as any)({});
25
+ const intent = item.intent || 'neutral';
26
+ const itemStyle = (menuItemStyles.item as any)({ intent });
27
+ const iconStyle = (menuItemStyles.icon as any)({ intent });
28
+ const labelStyle = (menuItemStyles.label as any)({ intent });
28
29
 
29
30
  const itemProps = getWebProps([itemStyle]);
30
31
  const iconProps = getWebProps([iconStyle]);
@@ -1,7 +1,8 @@
1
- import { forwardRef, useEffect } from 'react';
1
+ import { forwardRef, useContext, useEffect } from 'react';
2
2
  import { View as RNView, ScrollView as RNScrollView, Keyboard, Platform } from 'react-native';
3
3
  import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
4
4
  import { useSafeAreaInsets } from '@idealyst/theme';
5
+ import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';
5
6
  import { ScreenProps } from './types';
6
7
  import { screenStyles } from './Screen.styles';
7
8
  import type { IdealystElement } from '../utils/refTypes';
@@ -16,6 +17,7 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
16
17
  safeAreaRight,
17
18
  scrollable = true,
18
19
  avoidKeyboard = true,
20
+ keyboardAvoidingOffset = 0,
19
21
  contentInset,
20
22
  onLayout,
21
23
  // Spacing variants from ContainerStyleProps
@@ -38,6 +40,9 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
38
40
  const applySafeAreaLeft = safeAreaLeft ?? safeArea;
39
41
  const applySafeAreaRight = safeAreaRight ?? safeArea;
40
42
 
43
+ // Detect tab bar height when inside a bottom tab navigator
44
+ const tabBarHeight = useContext(BottomTabBarHeightContext) ?? 0;
45
+
41
46
  // Animated keyboard offset
42
47
  const keyboardOffset = useSharedValue(0);
43
48
 
@@ -49,7 +54,10 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
49
54
  const hideEvent = Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
50
55
 
51
56
  const showSubscription = Keyboard.addListener(showEvent, (e) => {
52
- keyboardOffset.value = withTiming(e.endCoordinates.height, {
57
+ // Subtract the tab bar height and any manual offset since those areas
58
+ // are already occupied and don't need additional padding
59
+ const adjustedHeight = Math.max(0, e.endCoordinates.height - tabBarHeight - keyboardAvoidingOffset);
60
+ keyboardOffset.value = withTiming(adjustedHeight, {
53
61
  duration: Platform.OS === 'ios' ? e.duration : 250,
54
62
  easing: Easing.out(Easing.cubic),
55
63
  });
@@ -66,7 +74,7 @@ const Screen = forwardRef<IdealystElement, ScreenProps>(({
66
74
  showSubscription.remove();
67
75
  hideSubscription.remove();
68
76
  };
69
- }, [avoidKeyboard]);
77
+ }, [avoidKeyboard, tabBarHeight, keyboardAvoidingOffset]);
70
78
 
71
79
  const animatedKeyboardStyle = useAnimatedStyle(() => ({
72
80
  paddingBottom: keyboardOffset.value,
@@ -84,6 +84,15 @@ export interface ScreenProps extends ContainerStyleProps {
84
84
  */
85
85
  avoidKeyboard?: boolean;
86
86
 
87
+ /**
88
+ * Additional offset to subtract from the keyboard height when avoiding the keyboard.
89
+ * The Screen automatically accounts for the tab bar height when inside a tab navigator,
90
+ * but this prop can be used for other fixed UI elements that occupy space at the bottom.
91
+ * @default 0
92
+ * @platform native
93
+ */
94
+ keyboardAvoidingOffset?: number;
95
+
87
96
  /**
88
97
  * Called when the layout of the screen changes.
89
98
  * Provides the new width, height, x, and y coordinates.
@@ -127,7 +127,9 @@ export const tabBarStyles = defineStyle('TabBar', (theme: Theme) => ({
127
127
  variants: {
128
128
  size: {
129
129
  fontSize: theme.sizes.$tabBar.fontSize,
130
- padding: theme.sizes.$tabBar.padding,
130
+ paddingHorizontal: theme.sizes.$tabBar.padding,
131
+ paddingTop: theme.sizes.$tabBar.padding,
132
+ paddingBottom: theme.sizes.$tabBar.paddingBottom,
131
133
  lineHeight: theme.sizes.$tabBar.lineHeight,
132
134
  },
133
135
  },