npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ebykdrms/react-native-portal-modal

v0.3.1

Published

JS düzeyinde portal ve reanimated destekli bir modal

Readme

react-native-portal-modal

Bu paket, React Native'deki modal kullanımında yaşanan sorunlara karşı minimal bir çözüm olarak geliştirildi.

React Native'in modal'ı tüm proje katmanının üzerinde bir katman üzerinde çalışırken bu paket JS düzeyinde portal açarak üst katmanlara ulaşma mantığını kullanır. (Not: RNModal bileeninde portal kullanımına gerek yoktur.)

Paket tek başına portal mantığı için de kullanılabileceği gibi asıl amacı modal'dır.

Paket İçeriği

  • PortalProvider: Portal'ın açıldığı katmanını oluşturur.
  • Portal: Verilen children içeriğinin PortalProvider düzeyinde render edilmesini sağlar.
  • PortalModal: Portal üzerinde modal açmak için kullanılır.
  • RNModal: React Native Modal tabanlı alternatif; PortalProvider gerektirmez.

Bağımlılıklar

Bu portal sistemi aşağıdaki paketleri kullanır:

  • react
  • react-native
  • react-native-reanimated (v4+)
  • react-native-gesture-handler
  • react-native-worklets

Kurulum

Bu paket artık react-native-reanimated v4 API'lerine bağımlıdır; v3 desteklenmez.

Kurulumdan önce aşağıdaki bağımlılıkların proje tarafında kurulu ve yapılandırılmış olduğundan emin olun:

  • react-native-reanimated@^4
  • react-native-gesture-handler
  • react-native-worklets

Kurulum için resmi dokümanlar:

  • Reanimated: https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation
  • Gesture Handler: https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation
  • Worklets: https://docs.swmansion.com/react-native-worklets/docs/#installation

Özellikle React Native Community CLI kullanan projelerde aşağıdaki adımlar zorunludur:

  1. babel.config.js içinde react-native-worklets/plugin eklensin.
  2. react-native-worklets/plugin plugins dizisinde en sonda olsun.
  3. Gesture'ların stabil çalışması için uygulama kökü GestureHandlerRootView ile sarılsın.
  4. Native bağımlılıklar güncellendikten sonra iOS için pod kurulumu ve Metro cache temizliği yapılsın.

Bağımlılıklar hazırsa paketimizi kurabilirsiniz:

npm install @ebykdrms/react-native-portal-modal

Kullanım

Portal yapısının çalışması için uygulama ağacında (tercihen üst seviyelerde) bir PortalProvider olmalıdır.

Örnek:

import { PortalProvider } from '@ebykdrms/react-native-portal-modal';

export default function AppRoot() {
  return <PortalProvider>{/* uygulamanız */}</PortalProvider>;
}

React Navigation ile Doğru Kullanım

react-navigation kullanıyorsanız navigation.navigate(...) gibi komutların sorunsuz çalışması için PortalProvider yerleşimi önemlidir.

Doğru Konum (önerilen)

PortalProviderNavigationContainer içinde ve navigator ağacını saracak şekilde konumlandırın.

import { NavigationContainer } from '@react-navigation/native';
import { PortalProvider } from '@ebykdrms/react-native-portal-modal';

export default function Root() {
  return (
    <NavigationContainer>
      <PortalProvider>
        <Tab.Navigator>{/* ekranlar */}</Tab.Navigator>
      </PortalProvider>
    </NavigationContainer>
  );
}

Bu yapı, portal içinden açılan modal içeriklerinin navigation lifecycle'ına ve navigator bağlamına erişimini daha güvenli hale getirir.

Temel Kullanım

1) Portal kullanımı

import { Portal } from '@ebykdrms/react-native-portal-modal';

function ExampleOverlay({ visible }: { visible: boolean }) {
  if (!visible) return null;

  return (
    <Portal>
      <View
        style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
      >
        <Text>Overlay İçeriği</Text>
      </View>
    </Portal>
  );
}

2) PortalModal kullanımı

import { PortalModal } from '@ebykdrms/react-native-portal-modal';

<PortalModal
  isVisible={isVisible}
  extraKeyboardHeight={12}
  dismissKeyboardOnBackdropPress
  onBackdropPress={() => setIsVisible(false)}
  onBackButtonPress={() => setIsVisible(false)}
  enteringAnimation="slideInDown"
  exitingAnimation="slideOutDown"
>
  <View>{/* modal içeriği */}</View>
</PortalModal>;

3) RNModal kullanımı (Provider gerektirmez)

Bu bileşen PortalModal'a alternatif olarak doğrudan react-native'in Modal bileşenini kullanır. Böylece en üst katmanda görüntülenme konusunu çözer. Ancak tüm swipe, backdrop, açılma/kapanma animasyonları yine reanimated ile gerçekleştirilmiştir.

import { RNModal } from '@ebykdrms/react-native-portal-modal';

<RNModal
  isVisible={isVisible}
  extraKeyboardHeight={12}
  dismissKeyboardOnBackdropPress
  onBackdropPress={() => setIsVisible(false)}
  onBackButtonPress={() => setIsVisible(false)}
  enteringAnimation="slideInDown"
  exitingAnimation="slideOutDown"
>
  <View>{/* modal içeriği */}</View>
</RNModal>;

Keyboard Davranışı

PortalModal ve RNModal artık keyboard davranışında aynı API'yi sunar.

  • Keyboard açıldığında modal içeriği keyboard yüksekliği kadar yukarı taşınabilir.
  • Ek offset için extraKeyboardHeight kullanılabilir.
  • Backdrop'e basıldığında önce keyboard'ı kapatmak için dismissKeyboardOnBackdropPress kullanılabilir.
  • Keyboard transform animasyonu disableKeyboardTransforming ile kapatılabilir.
  • Show/hide animasyon süreleri keyboardEnteringDuration ve keyboardExitingDuration ile override edilebilir.

PortalModal Props

| Prop | Açıklama | Varsayılan / Notlar | | -------------------------------- | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | isVisible | Modal açık/kapalı durumu. | zorunlu | | enteringTimeout | Açılış animasyon süresi (ms). | 500 | | exitingTimeout | Kapanış animasyon süresi (ms). | 300 | | onModalHide | Kapanış animasyonu sonrası callback. | - | | onBackdropPress | Backdrop dokunma callback'i. | - | | onBackButtonPress | Android geri tuşu callback'i. | - | | extraKeyboardHeight | Keyboard açıldığında içeriğe eklenecek ekstra yukarı offset (px). | 0 | | keyboardEnteringDuration | Keyboard açılırken modal içeriğinin yukarı taşınma animasyon süresi (ms). | Platform/event bazlı; fallback 250 | | keyboardExitingDuration | Keyboard kapanırken modal içeriğinin geri gelme animasyon süresi (ms). | Platform/event bazlı; fallback 250 | | disableKeyboardTransforming | true olduğunda keyboard'a göre içerik transform'u devre dışı kalır. | false | | dismissKeyboardOnBackdropPress | true olduğunda backdrop press önce keyboard'ı kapatır; keyboard kapalıysa onBackdropPress tetiklenir. | false | | style | Modal kök container stili. | - | | backdropStyle | Backdrop stili (opacity hariç). | - | | contentContainerStyle | İçerik container stili (opacity ve transform hariç). | - | | enteringAnimation | Açılış animasyonu. | fadeIn, slideInDown, slideInUp, slideInLeft, slideInRight, zoomFadeIn, zoomIn | | exitingAnimation | Kapanış animasyonu. | fadeOut, slideOutDown, slideOutUp, slideOutLeft, slideOutRight, zoomFadeOut, zoomOut |

RNModal props set'i PortalModal ile aynıdır.

PortalModal.Swiper

PortalModal.Swiper, Modal'a swipe özelliği kazandırır. Kullanıcı bu bileşenin bulunduğu alana basılı tutarak modal'ı kaydırabilir.

Özellikler

  • Swipe alanı tüm modal content'ini sarabileceği gibi belli bir alanda da olabilir (ör: yalnızca header).
  • Hangi yönde kaydırma yapacağı swipeDirections prop'unda belirtilmelidir.
  • Threshold geçilince onDismiss prop'u tetiklenir.
  • İç scroll ile çakışmayı azaltmak için nested scroll önceliği sunar.

Props

| Prop | Açıklama | Varsayılan / Notlar | | ------------------------ | -------------------------------------------------- | -------------------------------------------------------------------------- | | onDismiss | Swipe dismiss tetiklenince çağrılır. | zorunlu | | threshold | Kapatma eşiği (piksel). | 120 | | style | Swipe yakalama alanı stili. | - | | disabled | Swipe davranışını kapatır. | - | | isScrollAtStart | İç scroll sınır kontrolü için dışarıdan bayrak. | - | | prioritizeNestedScroll | true ise küçük hareketlerde iç scroll öncelikli. | - | | swipeDirections | Kaydırma yönleri; tek değer veya dizi alır. | Tek: "right"; Çoklu örnek: ["right", "bottom"]; Varsayılan: "bottom" |

Örnek

<PortalModal
  isVisible={visible}
  onBackdropPress={close}
  onBackButtonPress={close}
>
  <PortalModal.Swiper
    onDismiss={close}
    swipeDirections={['right', 'bottom']}
    threshold={100}
    style={{ paddingTop: 12 }}
  >
    <View>
      <Text>---</Text>
    </View>
  </PortalModal.Swiper>
  <View>{/* modal body */}</View>
</PortalModal>

RNModal.Swiper API'si PortalModal.Swiper ile aynıdır.

Context ile İlgili Önemli Not

Portal host, içeriği uygulama ağacında farklı bir katmanda render eder. Bu nedenle bazı ekran-spesifik context'ler portal içinde undefined olabilir.

Bu durumda modal içeriğini ilgili context provider ile tekrar sarmalayarak context köprüsü kurabilirsiniz:

const value = useContext(MyContext);

<PortalModal isVisible={visible} onBackdropPress={close}>
  <MyContext.Provider value={value}>
    <ModalContent />
  </MyContext.Provider>
</PortalModal>;

Sorun Giderme

  • Modal görünmüyorsa: PortalProvider üst ağaçta tanımlı mı kontrol edin.
  • RNModal kullanıyorsanız PortalProvider gerekmez.
  • Swipe çalışmıyorsa: PortalModal.Swiper gerçekten modal içinde mi ve disabled false mu kontrol edin.
  • Scroll ile çakışıyorsa: prioritizeNestedScroll değerini ve isScrollAtStart akışını kontrol edin.
  • Context undefined ise: ilgili context'i modal içinde tekrar provider ile köprüleyin.
  • React Navigation kullanıyorsanız ve navigation.navigate çalışmıyorsa: PortalProvider konumunu kontrol edin; NavigationContainer içinde navigator'ı saracak şekilde yerleştirin.