react-native-header-motion 1.0.0-beta.0 → 1.0.0

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/README.md CHANGED
@@ -1,172 +1,69 @@
1
1
  # React Native Header Motion
2
2
 
3
- High-level APIs for orchestrating scroll-driven header motion in React Native.
3
+ Scroll-driven animated headers for React Native.
4
4
 
5
- This library is a wrapper around:
5
+ React Native Header Motion gives you the plumbing for collapsible, progress-driven headers without forcing a prebuilt UI on you. It measures the header, derives a shared `progress` value, keeps multiple scrollables in sync, and bridges that state into navigation-rendered headers when needed.
6
6
 
7
- - [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/) & [React Native Worklets](https://docs.swmansion.com/react-native-worklets/docs/)
8
- - [React Native Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/docs/)
9
-
10
- All credit for the underlying animation engine, worklets, gestures, and low-level primitives goes to those libraries. This package focuses on composing them into a specific higher-level use case: header motion and scroll orchestration.
11
-
12
- This library does not ship a predesigned "collapsible header" UI. It gives you the pieces to:
13
-
14
- - measure the parts of a header that matter
15
- - derive a shared `progress` value from scroll
16
- - keep multiple scrollables in sync when one header is shared across them
17
- - bridge that state into navigation-rendered headers
7
+ Built on top of:
18
8
 
19
- You build the visuals yourself on top of that.
9
+ - [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/)
10
+ - [React Native Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/docs/)
11
+ - [React Native Worklets](https://docs.swmansion.com/react-native-worklets/docs/)
20
12
 
21
13
  <div align="center">
22
14
  <img src="https://github.com/user-attachments/assets/b673349a-f26a-4cc8-bfe1-60d77deb4390" width="70%" />
23
15
  </div>
24
16
 
25
- ## Version notes
26
-
27
- - If you are upgrading from `v0.3.x`, read [MIGRATION-v1.md](./MIGRATION-v1.md).
28
- - If you are still on the pre-v1 API and need the old docs, use the `v0` README:
29
- [README on branch `v0`](https://github.com/pawicao/react-native-header-motion/blob/v0/README.md)
17
+ ## Documentation
30
18
 
31
- ## What's new in v1
19
+ Full documentation lives here:
32
20
 
33
- The API change in v1 is quite substantial, but the migration is usually straightforward and the end result gives a much better developer experience.
21
+ - [Docs home](https://pawicao.github.io/react-native-header-motion/)
22
+ - [Overview](https://pawicao.github.io/react-native-header-motion/docs/overview)
23
+ - [Installation](https://pawicao.github.io/react-native-header-motion/docs/installation)
24
+ - [Quick Start](https://pawicao.github.io/react-native-header-motion/docs/quick-start)
25
+ - [Guides](https://pawicao.github.io/react-native-header-motion/docs/guides/dynamic-header-measurement)
26
+ - [API Reference](https://pawicao.github.io/react-native-header-motion/docs/api/header-motion)
34
27
 
35
- - Header panning built on top of `react-native-gesture-handler`. Dragging on the header itself can initiate or continue the scroll interaction naturally instead of forcing the user to only use the scrollables.
36
- - Context-first header API built around `HeaderMotion.Header` and `HeaderMotion.Header.Dynamic`
37
- - Explicit navigation bridging with `HeaderMotion.Bridge` and `HeaderMotion.NavigationBridge`
38
- - Narrower `useMotionProgress()` that focuses on `progress` and `progressThreshold`
39
- - Reusable custom-scrollable factory via `createHeaderMotionScrollable()`
40
- - It's now easier than ever to wire up LegendList and FlashList to Header Motion!
41
- - `react-native-gesture-handler` added to the peer dependency surface
42
-
43
- ## What this library is good at
28
+ ## What it helps with
44
29
 
45
30
  - Scroll-driven animated headers
46
- - Shared header state across tabs / pagers / multiple scrollables
47
- - Navigation headers rendered outside the provider subtree
48
- - Reusable wrappers around custom scrollables
31
+ - Shared header state across tabs, pagers, and multiple scrollables
32
+ - Navigation-rendered headers in Expo Router or React Navigation
33
+ - Custom scrollables via `createHeaderMotionScrollable()`
34
+ - Optional header panning
49
35
 
50
- ## What this library is not trying to be
36
+ ## What it is not
51
37
 
52
38
  - A fully styled header component
53
39
  - A page layout framework
54
40
  - A general-purpose animation abstraction on top of Reanimated
55
41
 
56
- ## Requirements
57
-
58
- Your app must provide:
59
-
60
- - `react-native-gesture-handler >= 2.0.0`
61
- - `react-native-reanimated >= 4.0.0`
62
- - `react-native-worklets >= 0.4.0`
63
-
64
- These are peer dependencies.
65
-
66
42
  ## Installation
67
43
 
68
44
  ```bash
69
- npm i react-native-header-motion
45
+ npm install react-native-header-motion
70
46
  ```
71
47
 
72
- or
48
+ Peer dependencies:
73
49
 
74
- ```bash
75
- yarn add react-native-header-motion
76
- ```
50
+ - `react-native-reanimated@^4.0.0`
51
+ - `react-native-gesture-handler@^2.0.0`
52
+ - `react-native-worklets@>=0.4.0`
77
53
 
78
- Then follow the normal setup instructions for:
54
+ Then complete the standard setup for:
79
55
 
80
- - [Reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation)
56
+ - [Reanimated and Worklets](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation)
81
57
  - [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation)
82
- - [Worklets](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation)
83
-
84
- ## Mental model
85
-
86
- There are four concepts to understand:
87
-
88
- ### 1. `progress`
89
-
90
- `progress` is a `SharedValue<number>`.
91
-
92
- - `0` means "expanded"
93
- - `1` means "collapsed"
94
-
95
- Most header animations should be derived from this value.
96
-
97
- ### 2. `progressThreshold`
98
-
99
- `progressThreshold` is the collapse distance in pixels.
100
-
101
- It can be:
102
-
103
- - a fixed number
104
- - a function derived from the measured dynamic part of the header
105
-
106
- At runtime, `useMotionProgress()` gives you `progressThreshold` as a `SharedValue<number>`.
107
-
108
- In practice, `progress` is calculated by mapping scroll distance across that threshold:
109
58
 
110
- - before the threshold, `progress` moves from `0` toward `1`
111
- - at the threshold, `progress` reaches `1`
112
- - past the threshold, behavior depends on `progressExtrapolation`
59
+ For other package managers and full setup notes, see the [installation guide](https://pawicao.github.io/react-native-header-motion/docs/installation).
113
60
 
114
- ### 3. Total header height vs dynamic header height
115
-
116
- The library measures two different things:
117
-
118
- - the total header height
119
- - the dynamic part of the header that should define the collapse distance
120
-
121
- `HeaderMotion.Header` wires the total-height measurement.
122
-
123
- `HeaderMotion.Header.Dynamic` wires the dynamic measurement.
124
-
125
- In many designs:
126
-
127
- - the sticky/top part stays visible
128
- - the dynamic part slides away
129
- - the dynamic part is what should feed `progressThreshold`
130
-
131
- ### 4. Navigation headers are a separate tree
132
-
133
- When a navigation library renders a header outside your screen subtree, it cannot read the `HeaderMotion` context directly.
134
-
135
- That is why the library has:
136
-
137
- - `HeaderMotion.Bridge`
138
- - `HeaderMotion.NavigationBridge`
139
-
140
- Use them only to move HeaderMotion context across that boundary.
141
-
142
- ## Recommended integration order
143
-
144
- The library allows (and requires) you to integrate your scrollables with headers to provide animation behavior.
145
-
146
- Use the simplest integration that fits your case:
147
-
148
- 1. `HeaderMotion.ScrollView` or `HeaderMotion.FlatList` - exported directly from the library
149
- 2. `createHeaderMotionScrollable()` - to easily create custom integrated scrollables on top of other scrollables (e.g. LegendList or FlashList)
150
- 3. `HeaderMotion.ScrollManager` / `useScrollManager()` - for even more custom scenarios
151
-
152
- For custom scrollables, prefer `createHeaderMotionScrollable()` first.
153
-
154
- Use the scroll managers only when the factory approach is not flexible enough.
155
-
156
- ## Quick start: navigation header
157
-
158
- This is the core v1 pattern when your header is rendered by Expo Router / React Navigation.
61
+ ## Quick example
159
62
 
160
63
  ```tsx
161
- import HeaderMotion, { useMotionProgress } from 'react-native-header-motion';
64
+ import HeaderMotion from 'react-native-header-motion';
162
65
  import { Stack } from 'expo-router';
163
- import { StyleSheet, View } from 'react-native';
164
- import Animated, {
165
- Extrapolation,
166
- interpolate,
167
- useAnimatedStyle,
168
- } from 'react-native-reanimated';
169
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
66
+ import { View } from 'react-native';
170
67
 
171
68
  export default function Screen() {
172
69
  return (
@@ -191,413 +88,38 @@ export default function Screen() {
191
88
  }
192
89
 
193
90
  function AppHeader() {
194
- const { progress, progressThreshold } = useMotionProgress();
195
- const insets = useSafeAreaInsets();
196
-
197
- const containerStyle = useAnimatedStyle(() => {
198
- const threshold = progressThreshold.get();
199
-
200
- return {
201
- transform: [
202
- {
203
- translateY: interpolate(
204
- progress.get(),
205
- [0, 1],
206
- [0, -threshold],
207
- Extrapolation.CLAMP
208
- ),
209
- },
210
- ],
211
- };
212
- });
213
-
214
- return (
215
- <HeaderMotion.Header
216
- style={[styles.header, { paddingTop: insets.top }, containerStyle]}
217
- >
218
- <HeaderMotion.Header.Dynamic>
219
- {/* collapsible part */}
220
- </HeaderMotion.Header.Dynamic>
221
-
222
- <View>{/* sticky part */}</View>
223
- </HeaderMotion.Header>
224
- );
225
- }
226
-
227
- const styles = StyleSheet.create({
228
- header: {
229
- backgroundColor: '#304077',
230
- },
231
- });
232
- ```
233
-
234
- ## Quick start: inline header inside the screen
235
-
236
- If your animated header lives in the same subtree as `HeaderMotion`, you do not need bridging at all.
237
-
238
- ```tsx
239
- function Screen() {
240
- return (
241
- <HeaderMotion>
242
- <InlineHeader />
243
- <HeaderMotion.ScrollView>{/* content */}</HeaderMotion.ScrollView>
244
- </HeaderMotion>
245
- );
246
- }
247
-
248
- function InlineHeader() {
249
- const { progress, progressThreshold } = useMotionProgress();
250
-
251
91
  return (
252
92
  <HeaderMotion.Header>
253
93
  <HeaderMotion.Header.Dynamic>
254
- {/* collapsible section */}
94
+ <View>{/* collapsible content */}</View>
255
95
  </HeaderMotion.Header.Dynamic>
256
- </HeaderMotion.Header>
257
- );
258
- }
259
- ```
260
-
261
- ## Shared header across multiple scrollables
262
-
263
- If one header is shared across tabs or pager pages:
264
-
265
- 1. Create an active scroll id with `useActiveScrollId()`
266
- 2. Pass `activeScrollId.sv` to `HeaderMotion`
267
- 3. Give each scrollable a unique `scrollId`
268
-
269
- ```tsx
270
- import { useRef } from 'react';
271
- import PagerView from 'react-native-pager-view';
272
96
 
273
- const indexToKey = new Map([
274
- [0, 'A'],
275
- [1, 'B'],
276
- ]);
277
-
278
- function Screen() {
279
- const [activeScrollId, setActiveScrollId] = useActiveScrollId<'A' | 'B'>('A');
280
- const pagerRef = useRef<PagerView>(null);
281
-
282
- return (
283
- <HeaderMotion activeScrollId={activeScrollId.sv}>
284
- <HeaderMotion.Bridge>
285
- {(ctx) => (
286
- <Stack.Screen
287
- options={{
288
- header: () => (
289
- <HeaderMotion.NavigationBridge value={ctx}>
290
- <Header />
291
- </HeaderMotion.NavigationBridge>
292
- ),
293
- }}
294
- />
295
- )}
296
- </HeaderMotion.Bridge>
297
-
298
- <PagerView
299
- ref={pagerRef}
300
- style={{ flex: 1 }}
301
- initialPage={0}
302
- onPageSelected={(e) => {
303
- setActiveScrollId(indexToKey.get(e.nativeEvent.position)!);
304
- }}
305
- >
306
- <View key="A">
307
- <HeaderMotion.ScrollView scrollId="A">
308
- {/* page A content */}
309
- </HeaderMotion.ScrollView>
310
- </View>
311
-
312
- <View key="B">
313
- <HeaderMotion.ScrollView scrollId="B">
314
- {/* page B content */}
315
- </HeaderMotion.ScrollView>
316
- </View>
317
- </PagerView>
318
- </HeaderMotion>
319
- );
320
- }
321
- ```
322
-
323
- ## Header panning
324
-
325
- Sometimes the header itself takes up a large part of the screen, so forcing the user to move their finger back down to the scrollable can feel awkward.
326
-
327
- In those cases, you can make the header surface itself drive the scroll interaction as well:
328
-
329
- ```tsx
330
- function Header() {
331
- return (
332
- <HeaderMotion.Header pannable>
333
- <HeaderMotion.Header.Dynamic>
334
- {/* collapsible content */}
335
- </HeaderMotion.Header.Dynamic>
97
+ <View>{/* sticky content */}</View>
336
98
  </HeaderMotion.Header>
337
99
  );
338
100
  }
339
101
  ```
340
102
 
341
- ## Public API
342
-
343
- ### Default export: `HeaderMotion`
344
-
345
- Compound component with:
346
-
347
- - `HeaderMotion.Header`
348
- - `HeaderMotion.Bridge`
349
- - `HeaderMotion.NavigationBridge`
350
- - `HeaderMotion.ScrollView`
351
- - `HeaderMotion.FlatList`
352
- - `HeaderMotion.ScrollManager`
353
-
354
- Provider props:
355
-
356
- - `progressThreshold?: number | ((measuredDynamic: number) => number)`: collapse distance in pixels; when passed as a function, it is derived from the value measured by `HeaderMotion.Header.Dynamic`
357
- - `measureDynamic?: (e) => number`: controls what value is read from the dynamic section's layout event; defaults to its height
358
- - `measureDynamicMode?: 'mount' | 'update'`: `'mount'` measures once; `'update'` re-measures when the dynamic section lays out again
359
- - `activeScrollId?: SharedValue<string>`: identifies which scrollable currently owns header progress in multi-scroll setups
360
- - `progressExtrapolation?: ExtrapolationType`: controls how `progress` behaves outside the normal collapse range
361
-
362
- ### `HeaderMotion.Header`
363
-
364
- Main header container.
365
-
366
- Responsibilities:
367
-
368
- - measures total header height
369
- - applies overlay positioning by default
370
- - can make the header surface pannable
371
-
372
- Props:
373
-
374
- - all normal `Animated.View` props in default mode: styles, accessibility props, pointer events, and other normal animated view props work as expected
375
- - `overlay?: boolean`: keeps the header absolutely positioned above content; disable only if you intentionally want it in normal layout flow
376
- - `pannable?: boolean`: allows dragging directly on the header surface to continue the scroll interaction
377
- - `panDecayConfig?: WithDecayConfig | ((event) => WithDecayConfig)`: customizes the momentum animation after a header pan ends
378
- - `withGestureHandlerRootView?: boolean`: wraps the gesture subtree in `GestureHandlerRootView` when that part of the tree is not already under one
379
- - `asChild?: boolean`: injects the total-height measurement into a single child instead of rendering the default `Animated.View`
380
-
381
- Use `asChild` when you want to inject the total-height measurement into a single child instead of rendering the default `Animated.View`.
382
-
383
- ### `HeaderMotion.Header.Dynamic`
384
-
385
- Marks the part of the header whose layout should define the collapsible distance.
386
-
387
- Use this for the section that visually disappears during collapse.
388
-
389
- Props:
390
-
391
- - all normal `Animated.View` props in default mode: use these as you would on any animated view
392
- - `asChild?: boolean`: injects the dynamic measurement into a single child instead of rendering the default `Animated.View`
393
-
394
- ### `HeaderMotion.Bridge`
395
-
396
- Reads the current HeaderMotion context and exposes it through a render function.
397
-
398
- Use it to move the context into a navigation-rendered header subtree.
399
-
400
- Props:
401
-
402
- - `children: (value) => ReactNode`: receives the bridged HeaderMotion context value that should usually be passed into `HeaderMotion.NavigationBridge`
403
-
404
- ### `HeaderMotion.NavigationBridge`
405
-
406
- Re-provides a previously captured HeaderMotion context value in another subtree.
407
-
408
- Use it together with `HeaderMotion.Bridge`.
409
-
410
- Props:
411
-
412
- - `value`: the bridged HeaderMotion context captured by `HeaderMotion.Bridge`
413
- - `children`: the subtree that should regain access to HeaderMotion context
414
-
415
- ### `HeaderMotion.ScrollView`
416
-
417
- Pre-wired `Animated.ScrollView`.
418
-
419
- Supports:
420
-
421
- - `scrollId?: string`: unique id for this scrollable when one header is shared across multiple scrollables
422
- - `headerOffsetStrategy?: 'padding' | 'margin' | 'top' | 'translate' | 'none'`: controls how content is pushed below the measured header
423
- - `ensureScrollableContentMinHeight?: boolean`: experimental fallback for short content that otherwise could not scroll far enough to collapse the header fully
424
- - `animatedRef?: AnimatedRef`: lets you reuse your own animated ref instead of letting HeaderMotion create one
425
-
426
- ### `HeaderMotion.FlatList`
427
-
428
- Pre-wired `Animated.FlatList`.
429
-
430
- Supports the same HeaderMotion-specific props as `HeaderMotion.ScrollView`.
431
-
432
- ### `createHeaderMotionScrollable(Component, options?)`
433
-
434
- Factory for creating reusable HeaderMotion-aware wrappers around custom scrollables.
435
-
436
- Prefer this over the scroll managers whenever it is enough.
437
-
438
- Useful options:
439
-
440
- - `displayName`: custom component name shown in React DevTools
441
- - `isComponentAnimated`: set this when the input component is already animated and should not be wrapped again
442
- - `contentContainerMode: 'children' | 'renderScrollComponent'`: tells HeaderMotion how to inject content offsetting for that scrollable shape
443
-
444
- Use:
445
-
446
- - `'children'` for ScrollView-like components
447
- - `'renderScrollComponent'` for FlatList-like components
448
-
449
- Examples:
450
-
451
- `FlashList`
452
-
453
- ```tsx
454
- import { FlashList } from '@shopify/flash-list';
455
- import { createHeaderMotionScrollable } from 'react-native-header-motion';
456
-
457
- const HeaderMotionFlashList = createHeaderMotionScrollable(FlashList, {
458
- displayName: 'HeaderMotionFlashList',
459
- contentContainerMode: 'renderScrollComponent',
460
- });
461
- ```
462
-
463
- `LegendList`
103
+ In a real header, use `useMotionProgress()` to drive your Reanimated styles. See the [Quick Start](https://pawicao.github.io/react-native-header-motion/docs/quick-start) for the full walkthrough, animation examples, and styling details.
464
104
 
465
- ```tsx
466
- import { LegendList } from '@legendapp/list';
467
- import { createHeaderMotionScrollable } from 'react-native-header-motion';
468
-
469
- const HeaderMotionLegendList = createHeaderMotionScrollable(LegendList, {
470
- displayName: 'HeaderMotionLegendList',
471
- isComponentAnimated: true,
472
- contentContainerMode: 'renderScrollComponent',
473
- });
474
- ```
475
-
476
- ### `HeaderMotion.ScrollManager`
477
-
478
- Render-prop fallback for complex custom integrations.
479
-
480
- Most code should prefer `createHeaderMotionScrollable()`.
481
-
482
- Use `ScrollManager` only when you need a custom composition that the factory API cannot express cleanly.
483
-
484
- Props:
485
-
486
- - `scrollId?: string`: unique id for this scrollable when one header is shared across multiple scrollables
487
- - `children`: render function that receives `scrollableProps` and `headerMotionContext`
488
- - plus the same refresh / ref options accepted by `useScrollManager()`
489
-
490
- ### Hooks
491
-
492
- #### `useMotionProgress()`
493
-
494
- Returns:
495
-
496
- - `progress`: `SharedValue<number>` that typically moves from `0` at expanded state to `1` at collapsed state
497
- - `progressThreshold`: `SharedValue<number>` representing the collapse distance in pixels
498
-
499
- This is the primary animation hook for header UI.
500
-
501
- #### `useHeaderMotionBridge()`
502
-
503
- Returns the full internal bridge value.
504
-
505
- Most app code should not need this. Prefer `useMotionProgress()` unless you are explicitly bridging context across a tree boundary.
506
-
507
- Returns:
508
-
509
- - full HeaderMotion context value, including measurement callbacks and scroll synchronization internals
510
-
511
- #### `useActiveScrollId(initialId)`
512
-
513
- Returns:
514
-
515
- - `{ state, sv }`: `state` is the React value for UI logic, `sv` is the matching shared value for HeaderMotion
516
- - setter function: updates both in sync
517
-
518
- Use this for multi-scroll setups.
519
-
520
- #### `useScrollManager(scrollId?, options?)`
521
-
522
- Hook-level fallback for complex custom scrollables.
523
-
524
- Most code should prefer `createHeaderMotionScrollable()`.
525
-
526
- Parameters:
527
-
528
- - `scrollId`: unique id for this scrollable when one header is shared across multiple scrollables
529
- - `options`: optional ref, refresh, and event-handler configuration
530
-
531
- Returns:
532
-
533
- - `scrollableProps`: props to spread onto the scrollable itself, including the managed ref, scroll handlers, and resolved refresh control
534
- - `headerMotionContext`: layout values for offsetting content below the measured header, including `originalHeaderHeight` and optional `contentContainerMinHeight`
535
-
536
- ## Notes
537
-
538
- ### Why `HeaderMotion.Header` is absolute by default
539
-
540
- Headers rendered by navigation are often easier to animate and interact with when they are visually overlayed above content rather than participating in normal layout flow.
541
-
542
- That is why `overlay` defaults to `true`.
543
-
544
- Disable it only when you intentionally want the header in normal layout flow.
545
-
546
- ### `ensureScrollableContentMinHeight` (experimental)
547
-
548
- This is available on the pre-wired scrollables and the custom-scrollable APIs.
549
-
550
- It is useful when content is too short to naturally scroll through the full collapse distance.
551
-
552
- This feature is still experimental.
553
-
554
- ### Scroll event frequency
555
-
556
- `scrollEventThrottle` is intentionally not managed by this library.
557
-
558
- Pass it directly to your scrollable when you need it.
559
-
560
- If you run into performance issues, try adjusting `scrollEventThrottle` to reduce how many scroll events this library processes.
561
-
562
- ### Refresh control
563
-
564
- If you use `HeaderMotion.ScrollView` or `HeaderMotion.FlatList`, your refresh-control usage stays the same as in React Native.
565
-
566
- If you use `HeaderMotion.ScrollManager` directly for custom integrations, pass refresh-related props to `ScrollManager` itself:
567
-
568
- - `refreshControl`
569
- - `refreshing`
570
- - `onRefresh`
571
- - optional `progressViewOffset`
572
-
573
- This matters because scrollable positioning affects refresh-control behavior and needs to stay coupled with the measured header height.
574
-
575
- Platform support note:
105
+ ## Version notes
576
106
 
577
- - Support for Refresh Control is currently partial.
578
- - Android works well with the current implementation.
579
- - iOS behavior is still not fully deterministic.
580
- - `progressViewOffset` does not seem to be reliable on iOS in all scenarios.
581
- - Other iOS approaches tried so far introduced different issues.
582
- - Additional iOS support improvements are planned for future releases.
107
+ - Upgrading from `v0.3.x`? Read [MIGRATION-v1.md](./MIGRATION-v1.md).
108
+ - Need the old API docs? See the [README on branch `v0`](https://github.com/pawicao/react-native-header-motion/blob/v0/README.md).
583
109
 
584
- ## Examples
110
+ ## Example app
585
111
 
586
- See the example app in [`example/`](./example/).
112
+ The repository includes an Expo Router example app covering simple headers, navigation bridging, shared headers across pages, custom scrollables, overscroll, pull to refresh, and more.
587
113
 
588
- Useful files:
114
+ See:
589
115
 
590
- - [`example/src/app/simple.tsx`](./example/src/app/simple.tsx)
591
- - [`example/src/app/flashlist.tsx`](./example/src/app/flashlist.tsx)
592
- - [`example/src/app/legend-list.tsx`](./example/src/app/legend-list.tsx)
593
- - [`example/src/app/pager-header-pan.tsx`](./example/src/app/pager-header-pan.tsx)
594
- - [`example/src/app/collapsible-pager.tsx`](./example/src/app/collapsible-pager.tsx)
116
+ - [`example/`](./example/)
117
+ - [Example app docs](https://pawicao.github.io/react-native-header-motion/docs/other/example-app)
595
118
 
596
119
  ## Contributing
597
120
 
598
- Development workflow: see [CONTRIBUTING.md](./CONTRIBUTING.md)
599
-
600
- Code of conduct: see [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)
121
+ - [Contributing guide](./CONTRIBUTING.md)
122
+ - [Code of conduct](./CODE_OF_CONDUCT.md)
601
123
 
602
124
  ## License
603
125
 
@@ -0,0 +1,4 @@
1
+ import type { Config } from '@docusaurus/types';
2
+ declare const config: Config;
3
+ export default config;
4
+ //# sourceMappingURL=docusaurus.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docusaurus.config.d.ts","sourceRoot":"","sources":["../../../docs/docusaurus.config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAGhD,QAAA,MAAM,MAAM,EAAE,MAwIb,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
2
+ declare const sidebars: SidebarsConfig;
3
+ export default sidebars;
4
+ //# sourceMappingURL=sidebars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebars.d.ts","sourceRoot":"","sources":["../../../docs/sidebars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,QAAA,MAAM,QAAQ,EAAE,cA8Ef,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export default function Home(): React.JSX.Element;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../docs/src/pages/index.tsx"],"names":[],"mappings":"AA0LA,MAAM,CAAC,OAAO,UAAU,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAUhD"}
@@ -7,7 +7,7 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
7
7
  onLayout?: ((event: import("react-native").LayoutChangeEvent) => unknown) | undefined;
8
8
  onMagicTap?: (() => unknown) | undefined;
9
9
  onAccessibilityEscape?: (() => unknown) | undefined;
10
- }>, "onMoveShouldSetResponder" | "onMoveShouldSetResponderCapture" | "onResponderGrant" | "onResponderMove" | "onResponderReject" | "onResponderRelease" | "onResponderStart" | "onResponderEnd" | "onResponderTerminate" | "onResponderTerminationRequest" | "onStartShouldSetResponder" | "onStartShouldSetResponderCapture" | "onMouseEnter" | "onMouseLeave" | "onClick" | "onClickCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onBlur" | "onBlurCapture" | "onFocus" | "onFocusCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
10
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onClick" | "onClickCapture" | "onMouseEnter" | "onMouseLeave" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onMoveShouldSetResponder" | "onMoveShouldSetResponderCapture" | "onResponderGrant" | "onResponderMove" | "onResponderReject" | "onResponderRelease" | "onResponderStart" | "onResponderEnd" | "onResponderTerminate" | "onResponderTerminationRequest" | "onStartShouldSetResponder" | "onStartShouldSetResponderCapture" | "onPointerEnterCapture" | "onPointerLeaveCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
11
11
  onMoveShouldSetResponder?: ((e: import("react-native").GestureResponderEvent) => boolean) | undefined;
12
12
  onMoveShouldSetResponderCapture?: ((e: import("react-native").GestureResponderEvent) => boolean) | undefined;
13
13
  onResponderGrant?: ((e: import("react-native").GestureResponderEvent) => void | boolean) | undefined;
@@ -20,10 +20,10 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
20
20
  onResponderTerminationRequest?: ((e: import("react-native").GestureResponderEvent) => boolean) | undefined;
21
21
  onStartShouldSetResponder?: ((e: import("react-native").GestureResponderEvent) => boolean) | undefined;
22
22
  onStartShouldSetResponderCapture?: ((e: import("react-native").GestureResponderEvent) => boolean) | undefined;
23
- }>, "onMouseEnter" | "onMouseLeave" | "onClick" | "onClickCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onBlur" | "onBlurCapture" | "onFocus" | "onFocusCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
23
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onClick" | "onClickCapture" | "onMouseEnter" | "onMouseLeave" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onPointerEnterCapture" | "onPointerLeaveCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
24
24
  onMouseEnter?: ((event: import("react-native").MouseEvent) => void) | undefined;
25
25
  onMouseLeave?: ((event: import("react-native").MouseEvent) => void) | undefined;
26
- }>, "onClick" | "onClickCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onBlur" | "onBlurCapture" | "onFocus" | "onFocusCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
26
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onClick" | "onClickCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onPointerEnterCapture" | "onPointerLeaveCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
27
27
  onClick?: ((event: import("react-native").PointerEvent) => void) | undefined;
28
28
  onClickCapture?: ((event: import("react-native").PointerEvent) => void) | undefined;
29
29
  onPointerEnter?: ((event: import("react-native").PointerEvent) => void) | undefined;
@@ -46,12 +46,12 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
46
46
  onGotPointerCaptureCapture?: ((e: import("react-native").PointerEvent) => void) | undefined;
47
47
  onLostPointerCapture?: ((e: import("react-native").PointerEvent) => void) | undefined;
48
48
  onLostPointerCaptureCapture?: ((e: import("react-native").PointerEvent) => void) | undefined;
49
- }>, "onClick" | "onBlur" | "onBlurCapture" | "onFocus" | "onFocusCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
49
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onClick" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
50
50
  onBlur?: ((event: import("react-native").BlurEvent) => void) | undefined;
51
51
  onBlurCapture?: ((event: import("react-native").BlurEvent) => void) | undefined;
52
52
  onFocus?: ((event: import("react-native").FocusEvent) => void) | undefined;
53
53
  onFocusCapture?: ((event: import("react-native").FocusEvent) => void) | undefined;
54
- }>, "onClick" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
54
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onClick" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
55
55
  onTouchCancel?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
56
56
  onTouchCancelCapture?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
57
57
  onTouchEnd?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
@@ -60,7 +60,7 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
60
60
  onTouchMoveCapture?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
61
61
  onTouchStart?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
62
62
  onTouchStartCapture?: ((e: import("react-native").GestureResponderEvent) => void) | undefined;
63
- }>, "onClick" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "tabIndex" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
63
+ }>, "id" | "style" | "children" | "tabIndex" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "onClick" | "nativeBackgroundAndroid" | "nativeForegroundAndroid" | "renderToHardwareTextureAndroid" | "hasTVPreferredFocus" | "nextFocusDown" | "nextFocusForward" | "nextFocusLeft" | "nextFocusRight" | "nextFocusUp" | "focusable" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
64
64
  nativeBackgroundAndroid?: import("react-native/types_generated/Libraries/Components/View/ViewPropTypes").AndroidDrawable | undefined;
65
65
  nativeForegroundAndroid?: import("react-native/types_generated/Libraries/Components/View/ViewPropTypes").AndroidDrawable | undefined;
66
66
  renderToHardwareTextureAndroid?: boolean | undefined;
@@ -73,16 +73,16 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
73
73
  focusable?: boolean | undefined;
74
74
  tabIndex?: 0 | -1;
75
75
  onClick?: ((event: import("react-native").GestureResponderEvent) => unknown) | undefined;
76
- }>, "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
76
+ }>, "id" | "style" | "children" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "shouldRasterizeIOS" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
77
77
  shouldRasterizeIOS?: boolean | undefined;
78
- }>, "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden" | "accessibilityLabelledBy" | "aria-labelledby" | "accessibilityLiveRegion" | "aria-live" | "importantForAccessibility" | "screenReaderFocusable" | "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<Omit<Readonly<{
78
+ }>, "id" | "style" | "children" | "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions" | "accessibilityLabelledBy" | "accessibilityLiveRegion" | "importantForAccessibility" | "screenReaderFocusable" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<Omit<Readonly<{
79
79
  accessibilityLabelledBy?: (string | undefined) | (Array<string> | undefined);
80
80
  "aria-labelledby"?: string | undefined;
81
81
  accessibilityLiveRegion?: ("none" | "polite" | "assertive") | undefined;
82
82
  "aria-live"?: ("polite" | "assertive" | "off") | undefined;
83
83
  importantForAccessibility?: ("auto" | "yes" | "no" | "no-hide-descendants") | undefined;
84
84
  screenReaderFocusable?: boolean;
85
- }>, "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "aria-modal" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden"> & Omit<Readonly<{
85
+ }>, "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-modal" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityIgnoresInvertColors" | "accessibilityViewIsModal" | "accessibilityShowsLargeContentViewer" | "accessibilityLargeContentTitle" | "accessibilityElementsHidden" | "accessibilityLanguage" | "accessibilityRespondsToUserInteraction" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions"> & Omit<Readonly<{
86
86
  accessibilityIgnoresInvertColors?: boolean | undefined;
87
87
  accessibilityViewIsModal?: boolean | undefined;
88
88
  accessibilityShowsLargeContentViewer?: boolean | undefined;
@@ -91,7 +91,7 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
91
91
  accessibilityElementsHidden?: boolean | undefined;
92
92
  accessibilityLanguage?: string | undefined;
93
93
  accessibilityRespondsToUserInteraction?: boolean | undefined;
94
- }>, "accessible" | "accessibilityLabel" | "accessibilityHint" | "aria-label" | "accessibilityRole" | "role" | "accessibilityState" | "accessibilityValue" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessibilityActions" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-selected" | "aria-hidden"> & {
94
+ }>, "role" | "aria-busy" | "aria-checked" | "aria-disabled" | "aria-expanded" | "aria-hidden" | "aria-label" | "aria-selected" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "accessible" | "accessibilityLabel" | "accessibilityHint" | "accessibilityRole" | "accessibilityState" | "accessibilityValue" | "accessibilityActions"> & {
95
95
  accessible?: boolean | undefined;
96
96
  accessibilityLabel?: string | undefined;
97
97
  accessibilityHint?: string | undefined;
@@ -111,8 +111,8 @@ declare const AnimatedRefreshControl: import("react-native-reanimated/lib/typesc
111
111
  "aria-expanded"?: boolean | undefined;
112
112
  "aria-selected"?: boolean | undefined;
113
113
  "aria-hidden"?: boolean | undefined;
114
- }>, "children" | "style" | "collapsable" | "collapsableChildren" | "id" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
115
- children?: React.ReactNode;
114
+ }>, "id" | "style" | "children" | "collapsable" | "collapsableChildren" | "testID" | "nativeID" | "needsOffscreenAlphaCompositing" | "hitSlop" | "pointerEvents" | "removeClippedSubviews" | "experimental_accessibilityOrder"> & Omit<Readonly<{
115
+ children?: import("react").ReactNode;
116
116
  style?: import("react-native/types_generated/Libraries/StyleSheet/StyleSheet").ViewStyleProp | undefined;
117
117
  collapsable?: boolean | undefined;
118
118
  collapsableChildren?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-header-motion",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0",
4
4
  "description": "Smooth, animated collapsible headers with scroll-based motion control in React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -38,7 +38,7 @@
38
38
  "typecheck": "tsc",
39
39
  "test": "jest",
40
40
  "release": "release-it --only-version",
41
- "lint": "eslint \"**/*.{js,ts,tsx}\""
41
+ "lint": "eslint src example docs/src docs/*.ts *.js"
42
42
  },
43
43
  "keywords": [
44
44
  "react-native",
@@ -54,7 +54,7 @@
54
54
  "bugs": {
55
55
  "url": "https://github.com/pawicao/react-native-header-motion/issues"
56
56
  },
57
- "homepage": "https://github.com/pawicao/react-native-header-motion#readme",
57
+ "homepage": "https://pawicao.github.io/react-native-header-motion/",
58
58
  "publishConfig": {
59
59
  "registry": "https://registry.npmjs.org/"
60
60
  },
@@ -89,11 +89,12 @@
89
89
  "react": "*",
90
90
  "react-native": "*",
91
91
  "react-native-gesture-handler": "^2.0.0",
92
- "react-native-reanimated": ">=4.0.0",
92
+ "react-native-reanimated": "^4.0.0",
93
93
  "react-native-worklets": ">=0.4.0"
94
94
  },
95
95
  "workspaces": [
96
- "example"
96
+ "example",
97
+ "docs"
97
98
  ],
98
99
  "packageManager": "yarn@4.11.0",
99
100
  "react-native-builder-bob": {