Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/pluggableWidgets/bottom-sheet-native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- Fixed the "non‑worklet function called on the UI thread” error in bottom sheet coming from @gorhom/bottom-sheet usage.

## [5.0.3] - 2025-12-15

- Updated react-native-reanimated to v3.17.5. This addresses compatibility issues with React Native 0.78 and later versions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ appId: "${APP_ID}"
text: "Modal basic non native"
- tapOn:
text: "Open"
# Because the image loading can take some time due to resources on emulator, we need to wait for the image to be visible
- extendedWaitUntil:
visible: randText # Any random text that does not exist in the UI
optional: true # This should be true so that the test won't fail
timeout: 10000 # 10 seconds

# Wait until the sheet is actually open (button label changes)
- extendedWaitUntil:
visible: randText
optional: true
timeout: 50000

- takeScreenshot:
path: "maestro/images/actual/${PLATFORM}/bottom_sheet_modal_basic_non_native"
path: "maestro/images/actual/${PLATFORM}/bottom_sheet_modal_basic_non_native"
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bottom-sheet-native",
"widgetName": "BottomSheet",
"version": "5.0.3",
"version": "5.0.4",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactElement, ReactNode, useEffect, useRef, useState } from "react";
import { ReactElement, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { InteractionManager, LayoutChangeEvent, Modal, Pressable, SafeAreaView, StyleSheet, View } from "react-native";
import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetView } from "@gorhom/bottom-sheet";
import { EditableValue, ValueStatus } from "mendix";
Expand All @@ -9,21 +9,74 @@ interface CustomModalSheetProps {
content?: ReactNode;
styles: BottomSheetStyle;
}

let lastIndexRef = -1;

export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement => {
const bottomSheetRef = useRef<BottomSheet>(null);
const [height, setHeight] = useState(0);
const [currentStatus, setCurrentStatus] = useState(false);

const isAvailable = props.triggerAttribute && props.triggerAttribute.status === ValueStatus.Available;

const isOpen =
props.triggerAttribute &&
props.triggerAttribute.status === ValueStatus.Available &&
props.triggerAttribute.value;

const onLayoutFullscreenHandler = (event: LayoutChangeEvent): void => {
const layoutHeight = event.nativeEvent.layout.height;
if (layoutHeight > 0 && layoutHeight !== height) {
setHeight(layoutHeight);
}
};

const close = useCallback(() => {
bottomSheetRef.current?.close();
}, []);

const renderBackdrop = useCallback(
(backdropProps: BottomSheetBackdropProps) => (
<Pressable style={{ flex: 1 }} onPress={close}>
<BottomSheetBackdrop
{...backdropProps}
pressBehavior={"close"}
opacity={0.3}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
</Pressable>
),
[close]
);

const snapPoints = useMemo(() => {
if (height === 0) {
return [0];
}
return [height - Number(defaultPaddings.paddingBottom)];
}, [height]);

const handleSheetChanges = useCallback(
(index: number) => {
if (!isAvailable) {
return;
}

const hasOpened = lastIndexRef === -1 && index === 0;
const hasClosed = index === -1;
lastIndexRef = index;

if (hasOpened) {
props.triggerAttribute?.setValue(true);
}
if (hasClosed) {
props.triggerAttribute?.setValue(false);
}
},
[isAvailable, props.triggerAttribute]
);

useEffect(() => {
if (!isAvailable) {
return;
Expand All @@ -34,7 +87,7 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
bottomSheetRef.current?.close();
setCurrentStatus(false);
}
}, [props.triggerAttribute, currentStatus]);
}, [props.triggerAttribute, currentStatus, isAvailable]);

if (height === 0) {
return (
Expand All @@ -44,47 +97,8 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
);
}

const snapPoints = [height - Number(defaultPaddings.paddingBottom)];

const isOpen =
props.triggerAttribute &&
props.triggerAttribute.status === ValueStatus.Available &&
props.triggerAttribute.value;

const renderBackdrop = (backdropProps: BottomSheetBackdropProps) => (
<Pressable style={{ flex: 1 }} onPress={close}>
<BottomSheetBackdrop
{...backdropProps}
pressBehavior={"close"}
opacity={0.3}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
</Pressable>
);

const handleSheetChanges = (index: number) => {
if (!isAvailable) {
return;
}
const hasOpened = lastIndexRef === -1 && index === 0;
const hasClosed = index === -1;
lastIndexRef = index;

if (hasOpened) {
props.triggerAttribute?.setValue(true);
}
if (hasClosed) {
props.triggerAttribute?.setValue(false);
}
};

const close = () => {
bottomSheetRef.current?.close();
};

return (
<Modal onRequestClose={close} transparent visible={isOpen}>
<Modal onRequestClose={close} transparent visible={!!isOpen}>
<BottomSheet
ref={bottomSheetRef}
index={isOpen ? 0 : -1}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactNode, ReactElement, useCallback, useState, useRef, Children } from "react";
import { ReactNode, ReactElement, useCallback, useMemo, useState, useRef, Children } from "react";
import { Dimensions, LayoutChangeEvent, SafeAreaView, StyleSheet, View } from "react-native";
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
import { BottomSheetStyle } from "../ui/Styles";
Expand Down Expand Up @@ -79,26 +79,22 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
return content;
}, [props.smallContent, props.largeContent, props.fullscreenContent, isOpen, fullscreenHeight]);

if (props.fullscreenContent && fullscreenHeight === 0) {
return (
<View style={{ ...StyleSheet.absoluteFillObject, opacity: 0 }}>
<SafeAreaView style={{ flex: 1 }} onLayout={onLayoutFullscreenHandler} />
</View>
);
}

if (heightHeader === 0 || (isLargeContentValid && heightContent === 0)) {
return <View style={{ position: "absolute", bottom: -maxHeight }}>{renderContent()}</View>;
}
const snapPoints = useMemo(() => {
if (props.fullscreenContent && heightContent) {
return [fullscreenHeight, heightContent, heightHeader];
}
if (props.fullscreenContent) {
return [fullscreenHeight, heightHeader];
}
if (isLargeContentValid) {
return [heightContent, heightHeader];
}
return [heightHeader];
}, [props.fullscreenContent, fullscreenHeight, heightContent, heightHeader, isLargeContentValid]);

const snapPoints =
props.fullscreenContent && heightContent
? [fullscreenHeight, heightContent, heightHeader]
: props.fullscreenContent
? [fullscreenHeight, heightHeader]
: isLargeContentValid
? [heightContent, heightHeader]
: [heightHeader];
const snapPointsWithOffset = useMemo(() => {
return snapPoints.map(p => p + OFFSET_BOTTOM_SHEET);
}, [snapPoints]);

const collapsedIndex = 0;

Expand All @@ -117,13 +113,25 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
lastIndexRef = index;
};

if (props.fullscreenContent && fullscreenHeight === 0) {
return (
<View style={{ ...StyleSheet.absoluteFillObject, opacity: 0 }}>
<SafeAreaView style={{ flex: 1 }} onLayout={onLayoutFullscreenHandler} />
</View>
);
}

if (heightHeader === 0 || (isLargeContentValid && heightContent === 0)) {
return <View style={{ position: "absolute", bottom: -maxHeight }}>{renderContent()}</View>;
}

return (
<View style={StyleSheet.absoluteFillObject} pointerEvents="box-none">
{snapPoints.length > 1 && (
<BottomSheet
ref={bottomSheetRef}
index={collapsedIndex}
snapPoints={snapPoints.map(p => p + OFFSET_BOTTOM_SHEET)}
snapPoints={snapPointsWithOffset}
onClose={() => setIsOpen(false)}
enablePanDownToClose={false}
onChange={onChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
TouchableHighlight,
View
} from "react-native";
import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetView } from "@gorhom/bottom-sheet";
import BottomSheet, {
BottomSheetBackdrop,
BottomSheetBackdropProps,
BottomSheetScrollView
} from "@gorhom/bottom-sheet";
import { EditableValue, ValueStatus } from "mendix";
import { ItemsBasicType } from "../../typings/BottomSheetProps";
import { BottomSheetStyle, ModalItemContainerStyle } from "../ui/Styles";
Expand Down Expand Up @@ -78,16 +82,23 @@ export const NativeBottomSheet = (props: NativeBottomSheetProps): ReactElement =
}
}, [isOpen]);

const renderBackdrop = (backdropProps: BottomSheetBackdropProps) => (
<Pressable style={{ flex: 1 }} onPress={close}>
<BottomSheetBackdrop
{...backdropProps}
pressBehavior={"close"}
opacity={0.3}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
</Pressable>
const close = useCallback(() => {
bottomSheetRef.current?.close();
}, []);

const renderBackdrop = useCallback(
(backdropProps: BottomSheetBackdropProps) => (
<Pressable style={{ flex: 1 }} onPress={close}>
<BottomSheetBackdrop
{...backdropProps}
pressBehavior="close"
opacity={0.3}
appearsOnIndex={0}
disappearsOnIndex={-1}
/>
</Pressable>
),
[close]
);

const actionHandler = useCallback(
Expand Down Expand Up @@ -166,10 +177,6 @@ export const NativeBottomSheet = (props: NativeBottomSheetProps): ReactElement =
return <View></View>;
}

const close = () => {
bottomSheetRef.current?.close();
};

return (
<Modal onRequestClose={close} transparent visible={isOpen}>
<BottomSheet
Expand All @@ -185,9 +192,9 @@ export const NativeBottomSheet = (props: NativeBottomSheetProps): ReactElement =
handleComponent={null}
handleStyle={{ display: "none" }}
>
<BottomSheetView style={[{ flex: 1, paddingBottom: 16 }]}>
<BottomSheetScrollView style={[{ flex: 1, paddingBottom: 16 }]}>
{props.itemsBasic.map((item, index) => renderItem(item, index))}
</BottomSheetView>
</BottomSheetScrollView>
</BottomSheet>
</Modal>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<package xmlns="http://www.mendix.com/package/1.0/">
<clientModule name="BottomSheet" version="5.0.3" xmlns="http://www.mendix.com/clientModule/1.0/">
<clientModule name="BottomSheet" version="5.0.4" xmlns="http://www.mendix.com/clientModule/1.0/">
<widgetFiles>
<widgetFile path="BottomSheet.xml" />
</widgetFiles>
Expand Down
Loading