@comergehq/studio 0.1.8 → 0.1.9

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": "@comergehq/studio",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Comerge studio",
5
5
  "main": "src/index.ts",
6
6
  "module": "dist/index.mjs",
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { View, type NativeScrollEvent, type NativeSyntheticEvent, type ViewStyle } from 'react-native';
2
+ import { Platform, View, type NativeScrollEvent, type NativeSyntheticEvent, type ViewStyle } from 'react-native';
3
3
  import { BottomSheetFlatList } from '@gorhom/bottom-sheet';
4
4
 
5
5
  import type { ChatMessage } from '../models/types';
@@ -119,6 +119,8 @@ export const ChatMessageList = React.forwardRef<ChatMessageListRef, ChatMessageL
119
119
  ref={listRef}
120
120
  data={messages}
121
121
  keyExtractor={(m: ChatMessage) => m.id}
122
+ keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}
123
+ keyboardShouldPersistTaps="handled"
122
124
  onScroll={handleScroll}
123
125
  scrollEventThrottle={16}
124
126
  showsVerticalScrollIndicator={false}
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Keyboard, Platform, View, type ViewStyle } from 'react-native';
3
3
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
- import Animated, { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated';
5
4
 
6
5
  import type { ChatMessage } from '../models/types';
7
6
  import { useTheme } from '../../theme';
@@ -42,11 +41,9 @@ export function ChatPage({
42
41
  const insets = useSafeAreaInsets();
43
42
  const [composerHeight, setComposerHeight] = React.useState(0);
44
43
  const [keyboardVisible, setKeyboardVisible] = React.useState(false);
45
- const animatedKeyboard = useAnimatedKeyboard();
46
44
 
47
45
  React.useEffect(() => {
48
46
  if (Platform.OS !== 'ios') return;
49
-
50
47
  const show = Keyboard.addListener('keyboardWillShow', () => setKeyboardVisible(true));
51
48
  const hide = Keyboard.addListener('keyboardWillHide', () => setKeyboardVisible(false));
52
49
  return () => {
@@ -56,10 +53,6 @@ export function ChatPage({
56
53
  }, []);
57
54
 
58
55
  const footerBottomPadding = Platform.OS === 'ios' ? (keyboardVisible ? 0 : insets.bottom) : insets.bottom + 10;
59
- const footerAnimatedStyle = useAnimatedStyle(() => {
60
- if (Platform.OS !== 'ios') return { paddingBottom: insets.bottom + 10 };
61
- return { paddingBottom: animatedKeyboard.height.value > 0 ? 0 : insets.bottom };
62
- });
63
56
  const overlayBottom = composerHeight + footerBottomPadding + theme.spacing.lg;
64
57
  const bottomInset = composerHeight + footerBottomPadding + theme.spacing.xl;
65
58
 
@@ -80,35 +73,36 @@ export function ChatPage({
80
73
  </View>
81
74
  ) : null}
82
75
  <View style={{ flex: 1 }}>
83
- <ChatMessageList
84
- ref={listRef}
85
- messages={messages}
86
- showTypingIndicator={showTypingIndicator}
87
- renderMessageContent={renderMessageContent}
88
- onNearBottomChange={onNearBottomChange}
89
- bottomInset={bottomInset}
90
- />
91
- {resolvedOverlay}
92
-
93
- <Animated.View
94
- style={[
95
- {
96
- position: 'absolute',
97
- left: 0,
98
- right: 0,
99
- bottom: 0,
100
- paddingHorizontal: theme.spacing.lg,
101
- paddingTop: theme.spacing.sm,
102
- },
103
- footerAnimatedStyle,
104
- ]}
76
+ <View
77
+ style={{ flex: 1 }}
78
+ >
79
+ <ChatMessageList
80
+ ref={listRef}
81
+ messages={messages}
82
+ showTypingIndicator={showTypingIndicator}
83
+ renderMessageContent={renderMessageContent}
84
+ onNearBottomChange={onNearBottomChange}
85
+ bottomInset={bottomInset}
86
+ />
87
+ {resolvedOverlay}
88
+ </View>
89
+ <View
90
+ style={{
91
+ position: 'absolute',
92
+ left: 0,
93
+ right: 0,
94
+ bottom: 0,
95
+ paddingHorizontal: theme.spacing.lg,
96
+ paddingTop: theme.spacing.sm,
97
+ paddingBottom: footerBottomPadding,
98
+ }}
105
99
  >
106
100
  <ChatComposer
107
101
  {...composer}
108
102
  attachments={composer.attachments ?? []}
109
103
  onLayout={({ height }) => setComposerHeight(height)}
110
104
  />
111
- </Animated.View>
105
+ </View>
112
106
  </View>
113
107
  </View>
114
108
  );
@@ -35,8 +35,7 @@ export type StudioBottomSheetProps = {
35
35
  children: React.ReactNode;
36
36
 
37
37
  /**
38
- * Additional BottomSheet props, for advanced tuning.
39
- * We intentionally do not expose everything as first-class props to keep SRP.
38
+ * Additional BottomSheet props
40
39
  */
41
40
  bottomSheetProps?: Omit<
42
41
  BottomSheetProps,
@@ -93,20 +92,6 @@ export function StudioBottomSheet({
93
92
  return () => sub.remove();
94
93
  }, [open, resolvedSheetRef]);
95
94
 
96
- React.useEffect(() => {
97
- if (Platform.OS !== 'ios') return;
98
- const sub = Keyboard.addListener('keyboardDidHide', () => {
99
- const sheet = resolvedSheetRef.current;
100
- if (!sheet || !open) return;
101
- const targetIndex = snapPoints.length - 1;
102
- // Only "re-snap" if we're already at the highest snap point.
103
- if (currentIndexRef.current === targetIndex) {
104
- setTimeout(() => sheet.snapToIndex(targetIndex), 10);
105
- }
106
- });
107
- return () => sub.remove();
108
- }, [open, resolvedSheetRef, snapPoints.length]);
109
-
110
95
  React.useEffect(() => {
111
96
  const sheet = resolvedSheetRef.current;
112
97
  if (!sheet) return;
@@ -104,11 +104,15 @@ export function StudioOverlay({
104
104
  [confirmMrId, incomingMergeRequests]
105
105
  );
106
106
 
107
- const closeSheet = React.useCallback(() => {
108
- setSheetOpen(false);
109
- Keyboard.dismiss();
107
+ const handleSheetOpenChange = React.useCallback((open: boolean) => {
108
+ setSheetOpen(open);
109
+ if (!open) Keyboard.dismiss();
110
110
  }, []);
111
111
 
112
+ const closeSheet = React.useCallback(() => {
113
+ handleSheetOpenChange(false);
114
+ }, [handleSheetOpenChange]);
115
+
112
116
  const openSheet = React.useCallback(() => setSheetOpen(true), []);
113
117
 
114
118
  const goToChat = React.useCallback(() => {
@@ -178,7 +182,7 @@ export function StudioOverlay({
178
182
  {/* Testing glow around runtime */}
179
183
  <EdgeGlowFrame visible={isTesting} role="accent" thickness={40} intensity={1} />
180
184
 
181
- <StudioBottomSheet open={sheetOpen} onOpenChange={setSheetOpen}>
185
+ <StudioBottomSheet open={sheetOpen} onOpenChange={handleSheetOpenChange}>
182
186
  <StudioSheetPager
183
187
  activePage={activePage}
184
188
  width={width}