Commit Graph

126 Commits

Author SHA1 Message Date
lodev09
48d8ceb788
docs: add docs about autofocus input behavior 2025-12-27 02:59:31 +08:00
lodev09
582cee009d
docs: improve liquid glass documentation
- Make UIDesignRequiresCompatibility a sub-section of Disabling Liquid Glass
- Add backgroundColor/backgroundBlur as first option to disable Liquid Glass per-sheet
- Add note about iOS 26.1+ requirement for per-sheet disabling
- Add Apple documentation reference for UIDesignRequiresCompatibility
- Add Liquid Glass info to backgroundColor and backgroundBlur props in configuration
- Move backgroundBlur and blurOptions next to backgroundColor in configuration
2025-12-26 16:05:43 +08:00
Jovanni Lo
917775ee07
feat: add elevation prop for Android and Web (#355)
* feat(android): add elevation prop

* feat(web): add elevation prop support
2025-12-26 00:52:40 +08:00
Jovanni Lo
b09440d548
fix(ios): use native backgroundEffect for blur on iOS 26.1+ (#350)
* fix(ios): use native backgroundEffect for blur on iOS 26.1+

- Extract blur style mapping into BlurUtil
- Refactor setupBackground and setupGrabber into helper methods
- Add sheet getter for cleaner code
- Use native UIBlurEffect on backgroundEffect when only blurTint is set (iOS 26.1+)

* refactor: rename blurTint to backgroundBlur
2025-12-25 17:59:55 +08:00
lodev09
b6bd082bc8
feat: add headerStyle and footerStyle props 2025-12-25 01:10:34 +08:00
lodev09
e66a9b491b
feat(web): add 'none' option to stackBehavior prop
- When stackBehavior is 'none', uses regular BottomSheet instead of BottomSheetModal
- Bypasses the modal stack entirely for non-modal sheet behavior
- Updated types, web implementation, and documentation
2025-12-24 22:56:56 +08:00
lodev09
2e4494024f
docs: update docs 2025-12-22 00:57:12 +08:00
Jovanni Lo
4b02ca77f6
refactor(android): replace DialogFragment with CoordinatorLayout (#344)
* docs: add planning doc

* refactor(android): migrate from DialogFragment to CoordinatorLayout

This solves the touch lag issue when TrueSheet is presented over interactive
components like Maps. The sheet now stays in the same activity window instead
of a separate dialog window.

Changes:
- Add TrueSheetCoordinatorLayout to host sheet and dim view
- Add TrueSheetBottomSheetView with BottomSheetBehavior
- Refactor TrueSheetViewController to use CoordinatorLayout approach
- Update TrueSheetDimView for in-hierarchy usage with touch handling
- Remove TrueSheetDialogFragment (no longer needed)
- Remove unused dialog styles and animations

* fix(android): animate sheet on present using BottomSheetBehavior

* fix(android): animate sheet on present when not dismissible

* refactor(android): simplify dismiss animation using ViewPropertyAnimator

* docs: update AGENTS.md with new Android architecture

* fix(android): prevent duplicate initial present on re-mount

* fix(android): fix keyboard handling and parent sheet translation

* fix(android): prevent parent sheet layout reset when keyboard shows

- Add TrueSheetBottomSheetViewDelegate with isTopmostSheet property
- Skip onLayout for parent sheets to prevent BottomSheetBehavior from
  resetting translationY during system layout passes
- Refactor TrueSheetCoordinatorLayout.Delegate to standalone interface

* fix(android): preserve parent sheet translation during keyboard transitions

Override setTranslationY in TrueSheetBottomSheetView to prevent
keyboard inset animations from resetting parent sheet translation to 0.
Parent sheets (non-topmost) now maintain their translation value.

* refactor(android): rename TrueSheetDialogObserver to TrueSheetStackManager

* refactor(android): remove edgeToEdgeFullScreen prop

* fix(android): prevent sheet from showing during navigation within modal

* fix(android): clamp detent heights to available screen space

* fix(android): post when initialDetentAnimated is false
2025-12-21 16:10:23 +08:00
lodev09
f0ecafca37
docs: add android stacking and dimming blog 2025-12-16 17:58:28 +08:00
Jovanni Lo
98694a3228
refactor: export mocks per module (#329)
* refactor(android): parent handles own translation in stack

* refactor: export mocks per module instead of __mocks__ directory

- Add src/mock.ts for main TrueSheet exports
- Add src/navigation/mock.ts for navigation module
- Add src/reanimated/mock.ts for reanimated module
- Remove src/__mocks__ directory
- Update tsconfig.json and package.json to remove __mocks__ references
- Update tests to use new mock imports

* refactor: consolidate mocks into src/mocks folder

- Move mock files into src/mocks/ directory
- Export as /mock, /navigation/mock, /reanimated/mock
- Update package.json exports
- Update tests and documentation

* chore: simplify jest.setup.js mocks

* test: add navigation mock tests

* ci: extract platform builds to separate workflow
2025-12-16 15:28:40 +08:00
lodev09
139d2611f4
refactor(docs): organize guides into flat structure with shared assets
- Move guide mdx files from subfolders to guides root
- Consolidate all guide images into guides/assets folder
- Update image import paths in guide files
- Fix blog post reference to navigation.gif
2025-12-15 23:47:28 +08:00
lodev09
bcd3e5ac1a
docs: update intro doc image sizes 2025-12-15 08:27:51 +08:00
Jovanni Lo
f3df5e2681
feat: add adaptive grabber color for light/dark mode (#325)
* feat(android): adaptive grabber color based on light/dark mode

* feat: add adaptive option to grabber for light/dark mode support
2025-12-15 05:20:07 +08:00
lodev09
b32a5ed610
docs: fix broken links, update features 2025-12-14 15:41:55 +08:00
lodev09
c922263dbe
docs: add web checks to docs 2025-12-14 15:27:53 +08:00
lodev09
7f4bb3810a
docs: update docs 2025-12-14 09:33:48 +08:00
Jovanni Lo
c8cc19fc44
fix: batch dismiss behavior for stacked sheets (#322)
* fix(android): dismiss stacked sheets like iOS

* fix(android): fix dismiss animated

* docs: update stacking docs

* feat(example): add names to example sheets

* fix(web): dismiss stacked sheets like iOS
2025-12-14 09:05:50 +08:00
lodev09
21727c96f0
docs: add keyboard guide 2025-12-13 10:46:14 +08:00
Jovanni Lo
0c7d983483
feat: improve keyboard handling for Android and iOS (#317)
* fix(android): improve keyboard handling with translationY

* refactor(android): remove keyboardMode prop

* fix(android): cap keyboard translation to screen height

* refactor(android): add TrueSheetKeyboardHandler with API < 30 fallback

* feat(ios): add keyboard handler for footer view
2025-12-13 08:41:05 +08:00
lodev09
f08c9d811d
docs: update events doc 2025-12-13 05:44:07 +08:00
lodev09
14af1dd484
docs: add scrollable content notes for web 2025-12-13 04:59:43 +08:00
Jovanni Lo
69f0dba353
feat(web): add stackBehavior prop for sheet stacking control (#307)
* chore: tidy clean script

* fix: implement TrueSheetProvider for web

* refactor(example): move TrueSheetProvider to screen level and improve web support

- Move TrueSheetProvider and ReanimatedTrueSheetProvider from root layout to individual screens
- Remove (sheet) folder and rename route to 'sheet'
- Improve web grabber defaults and container layout
- Fix Platform.select to use 'default' instead of 'android' for web compatibility
- Update Input placeholder color and add text color for web visibility
- Add backgroundComponent={null} and fix handle zIndex in web implementation

* feat(web): add stackBehavior prop for sheet stacking control

* docs: simplify Expo Router example with proper types
2025-12-12 07:10:15 +08:00
Jovanni Lo
456b6c21dc
feat: add web support (#302)
* feat: add expo-example workspace with SDK 54

* fix: use relative imports and fix metro config for expo-example

* feat(expo-example): add native tabs and TrueSheet demo with stacking

* feat(web): add web support with TrueSheetProvider and useTrueSheet hook

* refactor: consolidate TrueSheetRef type and remove TrueSheetInstanceMethods

* chore: add gorhom/bottom-sheet as peerDependency

* feat(web): add gorhom/bottom-sheet as optional dependency and web guide

* chore: exclude expo-example

* chore: update expo-example to use web

* docs: add demo gif

* feat(web): add reanimated support for web

* chore: remove expo-example tests
2025-12-11 06:38:13 +08:00
lodev09
18d7e140fe
feat(navigation): rename reanimatedPositionChangeHandler to positionChangeHandler
- Simplify API: accept worklet function directly
- Add positionChangeHandler to regular TrueSheetScreen
- When reanimated enabled, handler must be a worklet
- Remove ReanimatedTrueSheetScreenProps type
- Update documentation
2025-12-09 04:03:17 +08:00
Jovanni Lo
dc10c4e528
feat(navigation): add per-screen reanimated option (#291)
* feat(navigation): add reanimated config option

* feat(navigation): use reanimated position change handler

* refactor(navigation): extract screen components to separate files

* refactor(navigation): move screen components to screen folder

* refactor(navigation): simplify useSheetScreenState return with eventHandlers spread

* feat(navigation): add reanimated support with ReanimatedTrueSheet

* refactor(navigation): extract screen types and fix resizeKey dependency

* feat(navigation): make reanimated integration optional with lazy require

* refactor(navigation): convert functions to arrow functions

* feat(navigation): add per-screen reanimated option with position change handler

* docs: add reanimated integration to navigation guide

* refactor: move spread below
2025-12-09 03:15:52 +08:00
Jovanni Lo
24b84a6b2e
docs: add troubleshooting for Android touch events (#290)
Closes #288
2025-12-09 00:14:23 +08:00
lodev09
1df8e942ac
docs: update types doc 2025-12-08 07:17:38 +08:00
Jovanni Lo
e69a0c152e
fix: Android layout calculations and add insetAdjustment prop (#285)
* feat(android): adjust android layout calculations

* fix(android): fix footer positioning

* fix(android): emit correct position relative to js screen height

* fix(android): fix halfExpandedRatio calculation with 3 detents

* refactor(android): pre-calculate positions by index

* chore: restore examples

* fix(android): fix halfExpandedRatio calculation

* feat(android): add bottomInset to detent heights for iOS consistency

- Add bottomInset to auto and fractional detent heights to match iOS behavior
- Update ScreenUtils to use ReactContext instead of View for reliable inset retrieval
- Remove unused getScreenY method
- Simplify currentSheetTop to use view.top directly

* fix(android): adjust halfExpandedRatio and expandedOffset for edgeToEdgeFullScreen

- Use maxOf(edgeToEdgeTopInset, realHeight - detentHeight) for expandedOffset
- Subtract edgeToEdgeTopInset from detent heights when calculating halfExpandedRatio
- Ensures sheet respects top inset when edgeToEdgeFullScreen is disabled

* fix(android): emit position on dismiss and sheet stacking

- Add emitDismissedPosition() for dismiss scenarios
- Add emitPosition parameter to hideDialog/showDialog
- Emit position when sheet is hidden/shown due to sheet stacking
- Skip position emission for RN Screens modal show/hide

* refactor(android): simplify setupSheetDetents calculation

- Extract common pattern for peekHeight, halfExpandedRatio, expandedOffset
- Fix halfExpandedRatio to cap at maxAvailableHeight instead of subtracting edgeToEdgeTopInset
- Remove redundant when block with unified calculation logic

* feat: add insetAdjustment prop for controlling bottom inset behavior

* fix(ios): fix ios insetAdjustment logic

* fix(ios): add pending layout update flag for detents and insetAdjustment changes

* refactor(ios): rename to detentBottomInsetForHeight, skip for iOS 26 floating sheets

* docs: add insetAdjustment prop documentation
2025-12-08 05:28:35 +08:00
lodev09
8642239962
docs: add sheet navigator blog post and simplify sidebar categories 2025-12-06 19:55:20 +08:00
lodev09
6c8244033d
feat: add guard to resize method to check if sheet is presented 2025-12-06 15:36:51 +08:00
Jovanni Lo
26008cbc8f
feat: add sheet navigator for react-navigation integration (#279)
* docs: fix broken links

* feat: add react-navigation integration

- Add createTrueSheetNavigator for custom sheet navigator
- Add TrueSheetRouter with snapTo action creator
- Add TrueSheetView component for rendering sheet screens
- Add useTrueSheetNavigation hook
- Export as separate optional import via /navigation
- Add optional peer dependencies for @react-navigation/native, nanoid

* docs: add expo-router support section to navigation guide

* feat: add sheet navigator for react-navigation integration

- Add createTrueSheetNavigator for react-navigation support
- Add TrueSheetRouter with RESIZE action
- Add TrueSheetView to render first screen as content, rest as sheets
- Add useTrueSheetNavigation hook with resize method
- Add navigation module as separate import (@lodev09/react-native-true-sheet/navigation)
- Refactor example to use navigators folder structure
- Update documentation with usage examples and Expo Router support

* fix: wait for sheet dismiss animation before removing route

- Intercept GO_BACK/POP actions to mark route as closing instead of removing
- Add DISMISS and REMOVE custom actions to TrueSheetRouter
- Sheet stays in navigation state until dismiss animation completes
- Handle user swipe dismiss by calling goBack then skipping dismiss
- Refactor example: rename NavigationScreen to StandardScreen
- Remove MapView from SheetNavigator example
- Add navigation examples to SheetNavigator (Test screen, Modal)

* refactor(navigation): use Pick for TrueSheetNavigationOptions type

* fix(android): prevent state reset during resize animation

* refactor(navigation): clean up types and remove redundancies

- Remove unused TrueSheetNavigationConfig type
- Combine GO_BACK, POP, and DISMISS action handling in router
- Remove unused navigation prop from TrueSheetView
- Remove unused rest spread from TrueSheetNavigator
- Export TrueSheetActionType and TrueSheetNavigationState types

* refactor(navigation): simplify detentIndex logic and use initialDetentIndex

- Use initialDetentIndex prop for faster initial presentation (no JS-native roundtrip)
- Capture initialDetentIndex in ref to prevent prop changes on resize
- Extract clampDetentIndex helper for cleaner index calculation
- Apply detent defaults in destructuring instead of inline nullish coalescing

* feat(navigation): add sheet-specific navigation events

- Add sheetWillPresent, sheetDidPresent events
- Add sheetWillDismiss, sheetDidDismiss events
- Add sheetDetentChange event
- Add sheetDragBegin, sheetDragChange, sheetDragEnd events
- Add sheetPositionChange event with realtime flag
- Add sheetWillFocus, sheetDidFocus, sheetWillBlur, sheetDidBlur events
- Export DetentChangeEventData and PositionChangeEventData types
- Add example usage in SheetNavigator

* refactor(navigation): reuse event payload types from TrueSheet.types

- Replace DetentChangeEventData with DetentInfoEventPayload
- Replace PositionChangeEventData with PositionChangeEventPayload
- Re-export payload types from TrueSheet.types in navigation index

* refactor(navigation): use nested pattern instead of independent tree

- First screen in Sheet.Navigator is base content (existing app/navigator)
- Subsequent screens are presented as sheets on top
- Prevents dismissing base screen in router
- Updated docs to show wrapping existing navigation pattern
- Updated Expo Router example with (main)/ route group structure

* feat(navigation): support initialRouteName to determine base screen

- Base screen is determined by initialRouteName (defaults to first screen)
- Updated docs and example to reflect the new pattern

* docs: simplify navigation doc

* docs: update navigation doc

* docs: tidy

* chore(example): restore example

* fix(navigation): bubble goBack to parent when on base screen

- Return null instead of state when goBack is called on base screen
- Allows navigation actions to propagate to parent navigator
- Simplified navigation docs
2025-12-06 14:32:55 +08:00
lodev09
7e9b56a146
feat(ios): bring back position tracking from layout 2025-12-05 07:07:49 +08:00
Jovanni Lo
9cc50f5167
feat: emit focus/blur events during present/dismiss (#278)
* feat: emit focus/blur events during present/dismiss

* docs: update focus/blur events documentation

* feat(android): emit focus/blur events during present/dismiss

- Add willFocus/didFocus events with willPresent/didPresent
- Add willBlur/didBlur events with willDismiss/didDismiss
- Use postDelayed with animation duration for did* events after animation
- Handle both programmatic dismiss (STATE_HIDDEN) and user-initiated cancel
- Use isDismissing flag to prevent duplicate events

* refactor(android): extract dismiss event helpers to reduce redundancy

- Add emitWillDismissEvents() helper for willBlur/willDismiss + parent focus
- Add emitDidDismissEvents() helper for didBlur/didDismiss + parent focus + promise
- Update dismiss(), STATE_HIDDEN, and setOnCancelListener to use helpers

* fix(android): emit position change on user-initiated dismiss

onSlide isn't triggered for user-initiated dismiss (back button, tap outside),
so manually emit off-screen position after dismiss animation completes.

* test: add focus/blur event callback tests

* fix: add animated param to mock present/dismiss methods
2025-12-05 01:17:21 +08:00
Jovanni Lo
b87f0570d1
feat: add animated parameter to present and dismiss methods (#276) 2025-12-04 01:24:10 +08:00
lodev09
0c3f56c0ea
docs: update navigation docs for focus/blur support 2025-12-03 10:29:37 +08:00
Jovanni Lo
f5028f9469
fix: make react-native-reanimated truly optional (#271)
- Remove unconditional reanimated export from main index
- Add separate export path for reanimated integration
- Update example app to use new import path

Users can now import reanimated features via:
import { ReanimatedTrueSheet } from '@lodev09/react-native-true-sheet/reanimated'
2025-12-03 00:01:42 +08:00
Jovanni Lo
83d58fb59d
feat(android): add onBackPress event (#269)
* feat(android): add onBackPress event

* docs: add onBackPress event documentation
2025-12-02 22:58:43 +08:00
Jovanni Lo
3cad4d7b6d
fix(ios): skip presenting VC that is being dismissed (#265)
* fix(ios): skip presenting VC that is being dismissed

- Update findPresentingViewController to check isBeingDismissed flag
- Add documentation for presenting sheet on screen focus
- Add requestAnimationFrame workaround in example

* chore: revert MapScreen.tsx example changes
2025-12-02 05:39:30 +08:00
Jovanni Lo
b426723084
feat: iOS blur and grabber improvements (#259)
* feat(ios): add custom grabber view with vibrancy effect

* refactor(ios): simplify blur and grabber view setup

* feat: add grabberOptions prop for customizing grabber appearance

- Add GrabberOptions type with width, height, topMargin, and color options
- iOS: Use system grabber by default, custom grabber when options provided
- Android: Pass options to TrueSheetGrabberView
- Update docs with new prop and type reference

* fix(ios): fix grabberOptions color handling

- Use Int32 for color in codegen spec (like background prop)
- Process color with processColor in TrueSheet.tsx
- Apply color to vibrancy view backgroundColor

* refactor(ios): consolidate blur options into blurOptions prop

- Add BlurOptions type with intensity and interaction properties
- Use -1 as sentinel value for intensity to support value of 0
- Keep blurTint as separate prop
- Update docs

* refactor: use WithDefault in codegen for blurOptions

* feat: add cornerRadius option to grabberOptions
2025-12-01 21:31:48 +08:00
lodev09
6d47b46d4d
docs: update migration/release docs 2025-12-01 08:42:16 +08:00
lodev09
d50e873448
docs: add v3.0 release blog and announcement banner 2025-12-01 07:55:01 +08:00
Jovanni Lo
72d625727f
fix: correct interpolated index and detent values for position changes (#258)
* feat(ios): emit consistent position values for lifecycle events

- Update delegate protocol to pass index, position, and detent params
- Use dispatch_async for willPresent, didPresent, detentChange events
- Remove unused methods from public header
- Update TrueSheetView to use delegate params directly

* refactor(ios): remove layoutTransitioning property

* fix(ios): correct interpolated index and detent values for position changes

- Store actual Y positions when sheet settles at each detent
- Use stored positions for accurate interpolation instead of estimating from detent fractions
- Add estimatedPositionForIndex helper to calculate positions with offset correction
- Fixes incorrect interpolated values caused by iOS safe area insets

Fixes #255

* fix(ios): update resolved position in viewDidLayoutSubviews

- Move position storage to viewDidLayoutSubviews for centralized handling
- Handles content size changes correctly
- Remove duplicate storage from detent change delegate

* feat(example): add content toggle to MapScreen for testing dynamic height

* fix(android): correct interpolated index and detent values for position changes

* refactor(ios): extract findSegmentForPosition helper to reduce duplication

* fix(ios): emit detent change after sheet settles for programmatic resize

* refactor(ios): simplify position tracking and remove transition animation tracking

* fix(ios): emit realtime position changes when another controller is presented

* fix(android): adjust sheet position when content size changes at auto detent

* docs: remove auto detent placement restriction note
2025-12-01 07:37:45 +08:00
Jovanni Lo
94b883a737
feat(android): add bottom inset adjustment to match iOS behavior (#257)
* feat(android): add bottom inset adjustment to match iOS behavior

Adds native bottom safe area inset handling on Android to align with iOS changes from #256.

- Add getNavigationBarHeight() to ScreenUtils
- Add bottomInset to TrueSheetViewController
- Update getDetentHeight() to include bottom inset
- Update getDetentValueForIndex() for consistent interpolation
- Refactor ScreenUtils to reduce redundancy

* docs: update footer and migration docs for Android bottom inset support
2025-11-30 09:21:02 +08:00
Jovanni Lo
be79298767
fix: improve detent precision, interpolation, and native safe area handling (#256)
* fix: use Double instead of Float for detent values to preserve precision

* fix(ios): remove dispatch_after when emitting position after drag

* feat: interpolate detent value during position changes

- Use Double instead of Float for detent values to preserve precision
- Add interpolatedDetentForPosition method on iOS and Android
- Rename detent to animatedDetent in Reanimated provider
- animatedDetent now animates smoothly like animatedIndex

* refactor: remove insetAdjustment and let iOS handle bottom insets natively

* fix: update example Footer to handle bottom safe area inset

* docs: add safe area handling for footer and migration guide

* chore: remove unused import in MapScreen
2025-11-30 08:00:45 +08:00
lodev09
4e3498993b
docs: update minimum React Native version to 0.76 and add Expo install instructions 2025-11-30 03:33:03 +08:00
Jovanni Lo
4e3d219e45
docs: add RefreshControl limitation note for Android (#254)
* docs: add RefreshControl limitation note for Android

* feat(android): add native grabber view with JS hitbox for drag handling
2025-11-30 00:18:27 +08:00
Jovanni Lo
928fc14e39
fix(ios): use __typeof instead of typeof in TrueSheetBlurView (#253)
* fix(ios): use __typeof instead of typeof in TrueSheetBlurView

Also adds note about react-native-screens patch for navigation.

Closes #251

* chore: update podlock

* ci: re-enable build jobs and add common to turbo inputs
2025-11-29 23:04:38 +08:00
lodev09
23a9020292
docs: update docs related to scrollable 2025-11-29 12:51:47 +08:00
Jovanni Lo
546eb603e7
feat(ios): add blurIntensity and blurInteraction props (#250)
* feat(ios): add blurIntensity and blurInteraction props

* refactor(ios): extract blur logic into TrueSheetBlurView class

* chore: revert UIDesignRequiresCompatibility enabled
2025-11-29 12:27:02 +08:00
Jovanni Lo
49c7f9c709
feat: add draggable prop to disable sheet dragging (#246) (#249) 2025-11-29 11:07:26 +08:00