react-native-header-motion 0.2.0 → 1.0.0-alpha.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 +126 -18
- package/lib/module/components/FlatList.js +12 -2
- package/lib/module/components/FlatList.js.map +1 -1
- package/lib/module/components/HeaderBase.js +53 -5
- package/lib/module/components/HeaderBase.js.map +1 -1
- package/lib/module/components/HeaderMotion.js +66 -24
- package/lib/module/components/HeaderMotion.js.map +1 -1
- package/lib/module/components/ScrollManager.js +10 -2
- package/lib/module/components/ScrollManager.js.map +1 -1
- package/lib/module/components/ScrollView.js +8 -0
- package/lib/module/components/ScrollView.js.map +1 -1
- package/lib/module/context.js.map +1 -1
- package/lib/module/hooks/useMotionProgress.js +6 -2
- package/lib/module/hooks/useMotionProgress.js.map +1 -1
- package/lib/module/hooks/useScrollManager.js +91 -29
- package/lib/module/hooks/useScrollManager.js.map +1 -1
- package/lib/module/utils/index.js +1 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/refreshControl.js +93 -0
- package/lib/module/utils/refreshControl.js.map +1 -0
- package/lib/module/utils/values.js +36 -0
- package/lib/module/utils/values.js.map +1 -1
- package/lib/typescript/src/components/FlatList.d.ts +2 -4
- package/lib/typescript/src/components/FlatList.d.ts.map +1 -1
- package/lib/typescript/src/components/HeaderBase.d.ts +9 -2
- package/lib/typescript/src/components/HeaderBase.d.ts.map +1 -1
- package/lib/typescript/src/components/HeaderMotion.d.ts +5 -1
- package/lib/typescript/src/components/HeaderMotion.d.ts.map +1 -1
- package/lib/typescript/src/components/ScrollManager.d.ts +6 -10
- package/lib/typescript/src/components/ScrollManager.d.ts.map +1 -1
- package/lib/typescript/src/components/ScrollView.d.ts +3 -3
- package/lib/typescript/src/components/ScrollView.d.ts.map +1 -1
- package/lib/typescript/src/context.d.ts +7 -3
- package/lib/typescript/src/context.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useMotionProgress.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useScrollManager.d.ts +10 -3
- package/lib/typescript/src/hooks/useScrollManager.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +20 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/index.d.ts +1 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/refreshControl.d.ts +150 -0
- package/lib/typescript/src/utils/refreshControl.d.ts.map +1 -0
- package/lib/typescript/src/utils/values.d.ts +4 -1
- package/lib/typescript/src/utils/values.d.ts.map +1 -1
- package/package.json +7 -5
- package/src/components/FlatList.tsx +23 -9
- package/src/components/HeaderBase.tsx +93 -4
- package/src/components/HeaderMotion.tsx +102 -26
- package/src/components/ScrollManager.tsx +27 -17
- package/src/components/ScrollView.tsx +17 -3
- package/src/context.ts +9 -2
- package/src/hooks/useMotionProgress.ts +10 -2
- package/src/hooks/useScrollManager.ts +127 -35
- package/src/types.ts +22 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/refreshControl.tsx +118 -0
- package/src/utils/values.ts +57 -1
package/README.md
CHANGED
|
@@ -8,6 +8,19 @@ This library is **100% a wrapper around Reanimated**. All the credit for the und
|
|
|
8
8
|
<img src="https://github.com/user-attachments/assets/b673349a-f26a-4cc8-bfe1-60d77deb4390" width="70%" />
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
+
## v1 alpha status
|
|
12
|
+
|
|
13
|
+
`v1.0.0-alpha.x` is pre-release quality.
|
|
14
|
+
|
|
15
|
+
- Expect additional API changes (including breaking ones) before stable `1.0.0`.
|
|
16
|
+
- If you are upgrading from `0.3.x`, use the migration doc: [MIGRATION-v1.md](./MIGRATION-v1.md).
|
|
17
|
+
|
|
18
|
+
## What changed since `v0.3.0`
|
|
19
|
+
|
|
20
|
+
- **Performance-focused internals:** motion threshold + header height now flow through `SharedValue`s to reduce JS-side churn.
|
|
21
|
+
- **Pannable header support:** new `enableHeaderPan` on `HeaderMotion` and required `animatedHeaderBaseProps` on `AnimatedHeaderBase`.
|
|
22
|
+
- **Ecosystem update:** example app moved to Expo 55 + Reanimated 4.2; `react-native-gesture-handler` is now a peer dependency.
|
|
23
|
+
|
|
11
24
|
## What this is (and isn’t)
|
|
12
25
|
|
|
13
26
|
**✅ This is**
|
|
@@ -25,6 +38,7 @@ You build any header motion you want by animating based on `progress`.
|
|
|
25
38
|
|
|
26
39
|
You must have these installed in your app:
|
|
27
40
|
|
|
41
|
+
- `react-native-gesture-handler` **>= 2.0.0**
|
|
28
42
|
- `react-native-reanimated` **>= 4.0.0**
|
|
29
43
|
- `react-native-worklets` **>= 0.4.0**
|
|
30
44
|
|
|
@@ -57,17 +71,20 @@ There are three key concepts:
|
|
|
57
71
|
- `0` → animation start (initial state)
|
|
58
72
|
- `1` → animation end (final state)
|
|
59
73
|
|
|
60
|
-
### 2) `progressThreshold`
|
|
74
|
+
### 2) `progressThreshold` (prop vs runtime value)
|
|
61
75
|
|
|
62
76
|
`progressThreshold` is the distance needed for `progress` to move from `0 → 1`.
|
|
63
77
|
|
|
64
|
-
|
|
78
|
+
As a `HeaderMotion` prop, you can provide:
|
|
65
79
|
|
|
66
80
|
- a number, or
|
|
67
81
|
- a function `(measuredDynamic) => threshold`
|
|
68
82
|
|
|
69
83
|
If you provide a function, it uses the value measured by `measureDynamic`.
|
|
70
84
|
|
|
85
|
+
When you read `progressThreshold` from `useMotionProgress()` / `HeaderMotion.Header`, it is a `SharedValue<number>`.
|
|
86
|
+
Read it inside worklets via `progressThreshold.get()` (or `progressThreshold.value`).
|
|
87
|
+
|
|
71
88
|
### 3) Measurement functions
|
|
72
89
|
|
|
73
90
|
The library gives you two measurement callbacks that you pass to your header layout:
|
|
@@ -163,14 +180,16 @@ function MyHeader({
|
|
|
163
180
|
measureTotalHeight,
|
|
164
181
|
measureDynamic,
|
|
165
182
|
progressThreshold,
|
|
183
|
+
animatedHeaderBaseProps,
|
|
166
184
|
}: WithCollapsibleHeaderProps) {
|
|
167
185
|
const insets = useSafeAreaInsets();
|
|
168
186
|
|
|
169
187
|
const containerStyle = useAnimatedStyle(() => {
|
|
188
|
+
const threshold = progressThreshold.get();
|
|
170
189
|
const translateY = interpolate(
|
|
171
|
-
progress.
|
|
190
|
+
progress.get(),
|
|
172
191
|
[0, 1],
|
|
173
|
-
[0, -
|
|
192
|
+
[0, -threshold],
|
|
174
193
|
Extrapolation.CLAMP
|
|
175
194
|
);
|
|
176
195
|
return { transform: [{ translateY }] };
|
|
@@ -178,6 +197,7 @@ function MyHeader({
|
|
|
178
197
|
|
|
179
198
|
return (
|
|
180
199
|
<AnimatedHeaderBase
|
|
200
|
+
animatedHeaderBaseProps={animatedHeaderBaseProps}
|
|
181
201
|
onLayout={measureTotalHeight}
|
|
182
202
|
style={[{ paddingTop: insets.top }, containerStyle]}
|
|
183
203
|
>
|
|
@@ -209,6 +229,7 @@ import Animated, {
|
|
|
209
229
|
interpolate,
|
|
210
230
|
useAnimatedStyle,
|
|
211
231
|
} from 'react-native-reanimated';
|
|
232
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
212
233
|
import { View } from 'react-native';
|
|
213
234
|
|
|
214
235
|
export function MyScreen() {
|
|
@@ -245,14 +266,16 @@ function MyHeader({
|
|
|
245
266
|
measureTotalHeight,
|
|
246
267
|
measureDynamic,
|
|
247
268
|
progressThreshold,
|
|
269
|
+
animatedHeaderBaseProps,
|
|
248
270
|
}: WithCollapsibleHeaderProps) {
|
|
249
271
|
const insets = useSafeAreaInsets();
|
|
250
272
|
|
|
251
273
|
const containerStyle = useAnimatedStyle(() => {
|
|
274
|
+
const threshold = progressThreshold.get();
|
|
252
275
|
const translateY = interpolate(
|
|
253
|
-
progress.
|
|
276
|
+
progress.get(),
|
|
254
277
|
[0, 1],
|
|
255
|
-
[0, -
|
|
278
|
+
[0, -threshold],
|
|
256
279
|
Extrapolation.CLAMP
|
|
257
280
|
);
|
|
258
281
|
return { transform: [{ translateY }] };
|
|
@@ -260,6 +283,7 @@ function MyHeader({
|
|
|
260
283
|
|
|
261
284
|
return (
|
|
262
285
|
<AnimatedHeaderBase
|
|
286
|
+
animatedHeaderBaseProps={animatedHeaderBaseProps}
|
|
263
287
|
onLayout={measureTotalHeight}
|
|
264
288
|
style={[{ paddingTop: insets.top }, containerStyle]}
|
|
265
289
|
>
|
|
@@ -323,21 +347,31 @@ export default function Screen() {
|
|
|
323
347
|
}
|
|
324
348
|
|
|
325
349
|
function InlineAnimatedHeader() {
|
|
326
|
-
const {
|
|
327
|
-
|
|
350
|
+
const {
|
|
351
|
+
progress,
|
|
352
|
+
measureTotalHeight,
|
|
353
|
+
measureDynamic,
|
|
354
|
+
progressThreshold,
|
|
355
|
+
animatedHeaderBaseProps,
|
|
356
|
+
} = useMotionProgress();
|
|
328
357
|
|
|
329
358
|
const containerStyle = useAnimatedStyle(() => {
|
|
359
|
+
const threshold = progressThreshold.get();
|
|
330
360
|
const translateY = interpolate(
|
|
331
|
-
progress.
|
|
361
|
+
progress.get(),
|
|
332
362
|
[0, 1],
|
|
333
|
-
[0, -
|
|
363
|
+
[0, -threshold],
|
|
334
364
|
Extrapolation.CLAMP
|
|
335
365
|
);
|
|
336
366
|
return { transform: [{ translateY }] };
|
|
337
367
|
});
|
|
338
368
|
|
|
339
369
|
return (
|
|
340
|
-
<AnimatedHeaderBase
|
|
370
|
+
<AnimatedHeaderBase
|
|
371
|
+
animatedHeaderBaseProps={animatedHeaderBaseProps}
|
|
372
|
+
onLayout={measureTotalHeight}
|
|
373
|
+
style={containerStyle}
|
|
374
|
+
>
|
|
341
375
|
<Animated.View onLayout={measureDynamic}>
|
|
342
376
|
{/* custom animated header content below the native header */}
|
|
343
377
|
</Animated.View>
|
|
@@ -374,6 +408,8 @@ The package exports a default compound component plus hooks, types, and a couple
|
|
|
374
408
|
- Enables multi-scroll orchestration (tabs/pager).
|
|
375
409
|
- `progressExtrapolation?: ExtrapolationType`
|
|
376
410
|
- Controls how progress behaves outside the threshold range (useful for overscroll).
|
|
411
|
+
- `enableHeaderPan?: boolean`
|
|
412
|
+
- Enables direct pan gestures on `AnimatedHeaderBase` (`false` by default).
|
|
377
413
|
|
|
378
414
|
#### `HeaderMotion.Header`
|
|
379
415
|
|
|
@@ -407,19 +443,61 @@ Supports `scrollId?: string` for multi-scroll scenarios.
|
|
|
407
443
|
|
|
408
444
|
Render-prop API for custom scrollables (pager pages, 3rd party lists, etc.).
|
|
409
445
|
|
|
446
|
+
If you use `HeaderMotion.ScrollManager` directly for custom integrations, pass refresh-related props to `ScrollManager` (instead of your inner scrollable):
|
|
447
|
+
|
|
448
|
+
- `refreshControl`
|
|
449
|
+
- `refreshing`
|
|
450
|
+
- `onRefresh`
|
|
451
|
+
- optional `progressViewOffset` if you want to force your offset.
|
|
452
|
+
|
|
453
|
+
This is required, as the positioning of scrollables is affecting Refresh Control and has to be coupled with the header heights.
|
|
454
|
+
|
|
410
455
|
```tsx
|
|
411
456
|
<HeaderMotion.ScrollManager scrollId="A">
|
|
412
457
|
{(
|
|
413
458
|
scrollableProps,
|
|
414
459
|
{ originalHeaderHeight, minHeightContentContainerStyle }
|
|
460
|
+
) => (
|
|
461
|
+
<Animated.ScrollView {...scrollableProps}>
|
|
462
|
+
<Animated.View
|
|
463
|
+
style={[
|
|
464
|
+
minHeightContentContainerStyle,
|
|
465
|
+
{ paddingTop: originalHeaderHeight },
|
|
466
|
+
]}
|
|
467
|
+
>
|
|
468
|
+
{/* content */}
|
|
469
|
+
</Animated.View>
|
|
470
|
+
</Animated.ScrollView>
|
|
471
|
+
)}
|
|
472
|
+
</HeaderMotion.ScrollManager>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Refresh example with explicit props on `ScrollManager`:
|
|
476
|
+
|
|
477
|
+
```tsx
|
|
478
|
+
<HeaderMotion.ScrollManager
|
|
479
|
+
scrollId="A"
|
|
480
|
+
refreshing={refreshing}
|
|
481
|
+
onRefresh={onRefresh}
|
|
482
|
+
>
|
|
483
|
+
{(
|
|
484
|
+
{ onScroll, refreshControl: managedRefreshControl, ...scrollableProps },
|
|
485
|
+
{ originalHeaderHeight, minHeightContentContainerStyle }
|
|
415
486
|
) => (
|
|
416
487
|
<Animated.ScrollView
|
|
417
488
|
{...scrollableProps}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
489
|
+
onScroll={onScroll}
|
|
490
|
+
refreshControl={managedRefreshControl}
|
|
491
|
+
>
|
|
492
|
+
<Animated.View
|
|
493
|
+
style={[
|
|
494
|
+
minHeightContentContainerStyle,
|
|
495
|
+
{ paddingTop: originalHeaderHeight },
|
|
496
|
+
]}
|
|
497
|
+
>
|
|
498
|
+
{/* content */}
|
|
499
|
+
</Animated.View>
|
|
500
|
+
</Animated.ScrollView>
|
|
423
501
|
)}
|
|
424
502
|
</HeaderMotion.ScrollManager>
|
|
425
503
|
```
|
|
@@ -431,9 +509,11 @@ Render-prop API for custom scrollables (pager pages, 3rd party lists, etc.).
|
|
|
431
509
|
Returns:
|
|
432
510
|
|
|
433
511
|
- `progress` (`SharedValue<number>`)
|
|
434
|
-
- `progressThreshold` (`number
|
|
512
|
+
- `progressThreshold` (`SharedValue<number>`)
|
|
435
513
|
- `measureTotalHeight` (`onLayout` callback)
|
|
436
514
|
- `measureDynamic` (`onLayout` callback)
|
|
515
|
+
- `animatedHeaderBaseProps` (required by `AnimatedHeaderBase`)
|
|
516
|
+
- `activeScrollId` (`SharedValue<string> | undefined`)
|
|
437
517
|
|
|
438
518
|
Only use inside the `HeaderMotion` provider tree.
|
|
439
519
|
|
|
@@ -443,7 +523,7 @@ Lower-level orchestration hook that powers the component APIs. Returns:
|
|
|
443
523
|
|
|
444
524
|
- `scrollableProps`: `{ onScroll, scrollEventThrottle, ref }`
|
|
445
525
|
- `headerMotionContext`:
|
|
446
|
-
- `originalHeaderHeight`
|
|
526
|
+
- `originalHeaderHeight` (`SharedValue<number>`)
|
|
447
527
|
- `minHeightContentContainerStyle` (helps when content is shorter than the threshold)
|
|
448
528
|
|
|
449
529
|
#### `useActiveScrollId(initialId)`
|
|
@@ -464,11 +544,39 @@ Non-animated absolutely positioned header base.
|
|
|
464
544
|
|
|
465
545
|
Reanimated-powered, absolutely positioned header base.
|
|
466
546
|
|
|
547
|
+
- Requires `animatedHeaderBaseProps` from `useMotionProgress()` / `HeaderMotion.Header`.
|
|
548
|
+
- It is required for header panning functionality.
|
|
549
|
+
- Optional `withGestureHandlerRootView` can wrap this header in `GestureHandlerRootView` when needed.
|
|
550
|
+
|
|
467
551
|
### Types
|
|
468
552
|
|
|
469
553
|
- `WithCollapsibleHeaderProps` – convenience type for headers using motion progress props.
|
|
470
554
|
- `WithCollapsiblePagedHeaderProps` – like above, plus `activeTab` and `onTabChange`.
|
|
471
555
|
|
|
556
|
+
## Additional notes
|
|
557
|
+
|
|
558
|
+
### Refresh Control (v.0.3.0+)
|
|
559
|
+
|
|
560
|
+
Refresh control support was improved in `v0.3.0+`.
|
|
561
|
+
|
|
562
|
+
- If you use `HeaderMotion.ScrollView` or `HeaderMotion.FlatList`, your refresh-control usage stays the same as in React Native.
|
|
563
|
+
- If you use `HeaderMotion.ScrollManager` directly for custom integrations, pass refresh-related props to `ScrollManager`:
|
|
564
|
+
- `refreshControl`
|
|
565
|
+
- `refreshing`
|
|
566
|
+
- `onRefresh`
|
|
567
|
+
- optional `progressViewOffset`
|
|
568
|
+
|
|
569
|
+
This is important because scrollable positioning affects refresh-control behavior and needs to stay coupled with measured header height.
|
|
570
|
+
|
|
571
|
+
#### Platform support note:
|
|
572
|
+
|
|
573
|
+
- Support for Refresh Control is currently partial.
|
|
574
|
+
- Android works well with the current implementation.
|
|
575
|
+
- iOS behavior is still not fully deterministic.
|
|
576
|
+
- `progressViewOffset` does not seem to be reliable on iOS in all scenarios.
|
|
577
|
+
- Other iOS approaches tried so far introduced different issues.
|
|
578
|
+
- Additional iOS support improvements are planned for future releases.
|
|
579
|
+
|
|
472
580
|
## Contributing
|
|
473
581
|
|
|
474
582
|
- Development workflow: see [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
@@ -30,8 +30,14 @@ export function HeaderMotionFlatList({
|
|
|
30
30
|
return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
|
|
31
31
|
scrollId: scrollId,
|
|
32
32
|
animatedRef: animatedRef,
|
|
33
|
+
refreshControl: props.refreshControl,
|
|
34
|
+
refreshing: props.refreshing,
|
|
35
|
+
onRefresh: props.onRefresh,
|
|
36
|
+
progressViewOffset: props.progressViewOffset,
|
|
33
37
|
children: ({
|
|
34
38
|
onScroll,
|
|
39
|
+
refreshControl: managedRefreshControl,
|
|
40
|
+
ref,
|
|
35
41
|
...scrollViewProps
|
|
36
42
|
}, {
|
|
37
43
|
originalHeaderHeight,
|
|
@@ -39,9 +45,13 @@ export function HeaderMotionFlatList({
|
|
|
39
45
|
}) => /*#__PURE__*/_jsx(Animated.FlatList, {
|
|
40
46
|
...scrollViewProps,
|
|
41
47
|
...props,
|
|
48
|
+
ref: ref,
|
|
42
49
|
onScroll: onScroll,
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
...(managedRefreshControl && {
|
|
51
|
+
refreshControl: managedRefreshControl
|
|
52
|
+
}),
|
|
53
|
+
renderScrollComponent: scrollComponentProps => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
|
|
54
|
+
...scrollComponentProps,
|
|
45
55
|
contentContainerStyle: [minHeightContentContainerStyle, {
|
|
46
56
|
paddingTop: originalHeaderHeight
|
|
47
57
|
}, contentContainerStyle]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionFlatList","scrollId","animatedRef","contentContainerStyle","props","children","onScroll","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","FlatList","renderScrollComponent","
|
|
1
|
+
{"version":3,"names":["forwardRef","Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionFlatList","scrollId","animatedRef","contentContainerStyle","props","refreshControl","refreshing","onRefresh","progressViewOffset","children","onScroll","managedRefreshControl","ref","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","FlatList","renderScrollComponent","scrollComponentProps","AnimatedScrollContainer","paddingTop","rest","ScrollView","View","style"],"sourceRoot":"../../../src","sources":["components/FlatList.tsx"],"mappings":";;AAAA,SAASA,UAAU,QAAgD,OAAO;AAC1E,OAAOC,QAAQ,MAA4B,yBAAyB;AACpE,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAmB5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAAU;EAC5CC,QAAQ;EACRC,WAAW;EACXC,qBAAqB;EACrB,GAAGC;AACyB,CAAC,EAAE;EAC/B,oBACEL,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAiD;IAC9DG,cAAc,EAAED,KAAK,CAACC,cAAe;IACrCC,UAAU,EAAEF,KAAK,CAACE,UAAW;IAC7BC,SAAS,EAAEH,KAAK,CAACG,SAAU;IAC3BC,kBAAkB,EAAEJ,KAAK,CAACI,kBAAmB;IAAAC,QAAA,EAE5CA,CACC;MACEC,QAAQ;MACRL,cAAc,EAAEM,qBAAqB;MACrCC,GAAG;MACH,GAAGC;IACL,CAAC,EACD;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDhB,IAAA,CAACH,QAAQ,CAACoB,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfT,KAAK;MACTQ,GAAG,EAAEA,GAAI;MACTF,QAAQ,EAAEA,QAAS;MAAA,IACdC,qBAAqB,IAAI;QAC5BN,cAAc,EAAEM;MAClB,CAAC;MACDM,qBAAqB,EAAGC,oBAAoB,iBAC1CnB,IAAA,CAACoB,uBAAuB;QAAA,GAClBD,oBAAoB;QACxBf,qBAAqB,EAAE,CACrBY,8BAA8B,EAC9B;UAAEK,UAAU,EAAEN;QAAqB,CAAC,EACpCX,qBAAqB;MACrB,CACH;IACD,CACH;EACF,CACwB,CAAC;AAEhC;AAEA,MAAMgB,uBAAuB,gBAAGxB,UAAU,CAGxC,CAAC;EAAEc,QAAQ;EAAEN,qBAAqB;EAAE,GAAGkB;AAAK,CAAC,EAAET,GAAG,KAAK;EACvD,oBACEb,IAAA,CAACH,QAAQ,CAAC0B,UAAU;IAAA,GAAKD,IAAI;IAAET,GAAG,EAAEA,GAAI;IAAAH,QAAA,eACtCV,IAAA,CAACH,QAAQ,CAAC2B,IAAI;MAACC,KAAK,EAAErB,qBAAsB;MAAAM,QAAA,EAAEA;IAAQ,CAAgB;EAAC,CACpD,CAAC;AAE1B,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { Platform, StyleSheet, View } from 'react-native';
|
|
5
|
+
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
6
|
+
import Animated, { useAnimatedReaction, withDecay } from 'react-native-reanimated';
|
|
5
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const PLATFORM_PANNING_ENABLED = Platform.select({
|
|
9
|
+
default: true,
|
|
10
|
+
android: false
|
|
11
|
+
});
|
|
6
12
|
/**
|
|
7
13
|
* Base header component with absolute positioning.
|
|
8
14
|
* Provides a foundation for building headers that need to be positioned absolutely.
|
|
@@ -40,13 +46,53 @@ export function HeaderBase({
|
|
|
40
46
|
* </AnimatedHeaderBase>
|
|
41
47
|
* ```
|
|
42
48
|
*/
|
|
49
|
+
|
|
50
|
+
// TODO: Thinking about DX, perhaps creating another context in AnimatedHeaderBase or somewhere else could make sense
|
|
51
|
+
// Note: Depending on feedback, there might be a need to intercept ongoing scroll when starting to pan (perhaps even on the tap itself but to be checked what feels better when using)
|
|
52
|
+
// Note: Depending on feedback, there might be a need to block momentum by forcing scrollTo
|
|
43
53
|
export function AnimatedHeaderBase({
|
|
44
54
|
style,
|
|
55
|
+
animatedHeaderBaseProps,
|
|
56
|
+
withGestureHandlerRootView = false,
|
|
45
57
|
...rest
|
|
46
58
|
}) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
if (!animatedHeaderBaseProps) {
|
|
60
|
+
throw new Error('AnimatedHeaderBase requires `animatedHeaderBaseProps`. Pass the value from HeaderMotion.Header or useMotionProgress.');
|
|
61
|
+
}
|
|
62
|
+
const {
|
|
63
|
+
enableHeaderPan,
|
|
64
|
+
scrollToRef,
|
|
65
|
+
headerPanMomentumOffset: momentumScrollOffset
|
|
66
|
+
} = animatedHeaderBaseProps;
|
|
67
|
+
useAnimatedReaction(() => momentumScrollOffset.get(), (offset, prevOffset) => {
|
|
68
|
+
if (offset !== null) {
|
|
69
|
+
const dy = offset - (prevOffset ?? 0);
|
|
70
|
+
scrollToRef.current?.(dy);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const isPanEnabled = PLATFORM_PANNING_ENABLED && enableHeaderPan;
|
|
74
|
+
const pan = useMemo(() => Gesture.Pan().enabled(isPanEnabled).onChange(e => {
|
|
75
|
+
const dy = e.changeY;
|
|
76
|
+
scrollToRef.current?.(dy);
|
|
77
|
+
}).onEnd(e => {
|
|
78
|
+
momentumScrollOffset.set(withDecay({
|
|
79
|
+
velocity: e.velocityY
|
|
80
|
+
}, () => momentumScrollOffset.set(null)));
|
|
81
|
+
}).shouldCancelWhenOutside(false),
|
|
82
|
+
// Note: In first testing Android works without gesture handler whatsoever. If this functionality is needed, we can further control it with a prop in the future
|
|
83
|
+
[isPanEnabled, scrollToRef, momentumScrollOffset]);
|
|
84
|
+
const content = /*#__PURE__*/_jsx(GestureDetector, {
|
|
85
|
+
gesture: pan,
|
|
86
|
+
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
87
|
+
style: [style, styles.container],
|
|
88
|
+
...rest
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
if (!withGestureHandlerRootView) {
|
|
92
|
+
return content;
|
|
93
|
+
}
|
|
94
|
+
return /*#__PURE__*/_jsx(GestureHandlerRootView, {
|
|
95
|
+
children: content
|
|
50
96
|
});
|
|
51
97
|
}
|
|
52
98
|
const styles = StyleSheet.create({
|
|
@@ -56,4 +102,6 @@ const styles = StyleSheet.create({
|
|
|
56
102
|
right: 0
|
|
57
103
|
}
|
|
58
104
|
});
|
|
105
|
+
|
|
106
|
+
// TODO: Lib refactor: context repetition, make people use less boilerplate by just wrapping the header with <HeaderBaseOrSomethingElse ctx={headerProps} /> that does everything under the hood (measuring total for example). That will then allow for people to use context inside
|
|
59
107
|
//# sourceMappingURL=HeaderBase.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["StyleSheet","View","Animated","jsx","_jsx","HeaderBase","style","rest","styles","container","AnimatedHeaderBase","create","position","left","right"],"sourceRoot":"../../../src","sources":["components/HeaderBase.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,IAAI,QAAwB,cAAc;
|
|
1
|
+
{"version":3,"names":["useMemo","Platform","StyleSheet","View","Gesture","GestureDetector","GestureHandlerRootView","Animated","useAnimatedReaction","withDecay","jsx","_jsx","PLATFORM_PANNING_ENABLED","select","default","android","HeaderBase","style","rest","styles","container","AnimatedHeaderBase","animatedHeaderBaseProps","withGestureHandlerRootView","Error","enableHeaderPan","scrollToRef","headerPanMomentumOffset","momentumScrollOffset","get","offset","prevOffset","dy","current","isPanEnabled","pan","Pan","enabled","onChange","e","changeY","onEnd","set","velocity","velocityY","shouldCancelWhenOutside","content","gesture","children","create","position","left","right"],"sourceRoot":"../../../src","sources":["components/HeaderBase.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useCallback,
|
|
3
|
+
import { useCallback, useRef, useEffect, useMemo } from 'react';
|
|
4
4
|
import { Extrapolation, interpolate, useAnimatedReaction, useDerivedValue, useSharedValue } from 'react-native-reanimated';
|
|
5
5
|
import { HeaderMotionContext } from "../context.js";
|
|
6
6
|
import { DEFAULT_MEASURE_DYNAMIC, DEFAULT_PROGRESS_THRESHOLD, DEFAULT_SCROLL_ID, getInitialScrollValue } from "../utils/index.js";
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
const resolveScrollIdForProgress = (scrollValues, activeScrollIdValue) => {
|
|
9
|
+
'worklet';
|
|
10
|
+
|
|
11
|
+
if (activeScrollIdValue) {
|
|
12
|
+
return activeScrollIdValue;
|
|
13
|
+
}
|
|
14
|
+
let onlyNonDefaultId = null;
|
|
15
|
+
for (const key in scrollValues) {
|
|
16
|
+
if (key === DEFAULT_SCROLL_ID) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (onlyNonDefaultId !== null) {
|
|
20
|
+
return DEFAULT_SCROLL_ID;
|
|
21
|
+
}
|
|
22
|
+
onlyNonDefaultId = key;
|
|
23
|
+
}
|
|
24
|
+
return onlyNonDefaultId ?? DEFAULT_SCROLL_ID;
|
|
25
|
+
};
|
|
8
26
|
/**
|
|
9
27
|
* Context provider component for HeaderMotion.
|
|
10
28
|
* Manages header animation state and provides it to child components via context.
|
|
@@ -16,32 +34,40 @@ function HeaderMotionContextProvider({
|
|
|
16
34
|
measureDynamicMode = 'mount',
|
|
17
35
|
activeScrollId,
|
|
18
36
|
progressExtrapolation = Extrapolation.CLAMP,
|
|
37
|
+
enableHeaderPan = false,
|
|
19
38
|
children
|
|
20
39
|
}) {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
40
|
+
const dynamicMeasurement = useSharedValue(undefined);
|
|
41
|
+
const originalHeaderHeight = useSharedValue(0);
|
|
42
|
+
const progressThresholdValue = useSharedValue(typeof progressThreshold === 'number' ? progressThreshold : Infinity);
|
|
43
|
+
const headerPanMomentumOffset = useSharedValue(null);
|
|
23
44
|
const setOrUpdateDynamicMeasurement = useCallback(e => {
|
|
45
|
+
const prevMeasurement = dynamicMeasurement.get();
|
|
46
|
+
if (prevMeasurement !== undefined && measureDynamicMode === 'mount') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
24
49
|
const measured = measureDynamic(e);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return prevMeasurement;
|
|
28
|
-
}
|
|
29
|
-
return measured;
|
|
30
|
-
});
|
|
31
|
-
}, [measureDynamicMode, measureDynamic, setDynamicMeasurement]);
|
|
32
|
-
const calculatedProgressThreshold = useMemo(() => {
|
|
33
|
-
if (typeof progressThreshold === 'number') {
|
|
34
|
-
return progressThreshold;
|
|
50
|
+
if (prevMeasurement === measured) {
|
|
51
|
+
return;
|
|
35
52
|
}
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
dynamicMeasurement.set(measured);
|
|
54
|
+
progressThresholdValue.set(typeof progressThreshold === 'number' ? progressThreshold : progressThreshold(measured));
|
|
55
|
+
}, [measureDynamicMode, measureDynamic, dynamicMeasurement, progressThreshold, progressThresholdValue]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (typeof progressThreshold === 'number') {
|
|
58
|
+
progressThresholdValue.set(progressThreshold);
|
|
59
|
+
return;
|
|
38
60
|
}
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
const measured = dynamicMeasurement.get();
|
|
62
|
+
progressThresholdValue.set(measured === undefined ? Infinity : progressThreshold(measured));
|
|
63
|
+
}, [progressThreshold, dynamicMeasurement, progressThresholdValue]);
|
|
41
64
|
const measureTotalHeight = useCallback(e => {
|
|
42
65
|
const measuredValue = e.nativeEvent.layout.height;
|
|
43
|
-
|
|
44
|
-
|
|
66
|
+
if (originalHeaderHeight.get() === measuredValue) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
originalHeaderHeight.set(measuredValue);
|
|
70
|
+
}, [originalHeaderHeight]);
|
|
45
71
|
const scrollValues = useSharedValue({
|
|
46
72
|
[DEFAULT_SCROLL_ID]: getInitialScrollValue()
|
|
47
73
|
});
|
|
@@ -55,8 +81,10 @@ function HeaderMotionContextProvider({
|
|
|
55
81
|
});
|
|
56
82
|
});
|
|
57
83
|
const progress = useDerivedValue(() => {
|
|
58
|
-
const
|
|
59
|
-
const
|
|
84
|
+
const values = scrollValues.get();
|
|
85
|
+
const id = resolveScrollIdForProgress(values, activeScrollId?.get());
|
|
86
|
+
const scrollValue = values[id];
|
|
87
|
+
const threshold = progressThresholdValue.get();
|
|
60
88
|
if (!scrollValue) {
|
|
61
89
|
return 0;
|
|
62
90
|
}
|
|
@@ -64,17 +92,31 @@ function HeaderMotionContextProvider({
|
|
|
64
92
|
min,
|
|
65
93
|
current
|
|
66
94
|
} = scrollValue;
|
|
67
|
-
return interpolate(current, [min, min +
|
|
95
|
+
return interpolate(current, [min, min + threshold], [0, 1], progressExtrapolation);
|
|
68
96
|
});
|
|
97
|
+
const scrollToRef = useRef(null);
|
|
98
|
+
// FUTURE: SharedValue-based scrollTo was removed for now because function updates
|
|
99
|
+
// were not propagating reliably, while it works for refs. Revisit later.
|
|
100
|
+
// We need to be updating the scrollTo on active scroll ID changes and doing it via state would cause re-renders.
|
|
101
|
+
// It's a bit of an anti-pattern to use refs for this as well, but I am yet to figure out a better way to pass those if SV won't work.
|
|
102
|
+
const animatedHeaderBaseProps = useMemo(() => ({
|
|
103
|
+
enableHeaderPan,
|
|
104
|
+
scrollToRef,
|
|
105
|
+
headerPanMomentumOffset
|
|
106
|
+
}), [enableHeaderPan, headerPanMomentumOffset]);
|
|
69
107
|
const ctxValue = useMemo(() => ({
|
|
70
108
|
progress,
|
|
71
109
|
originalHeaderHeight,
|
|
72
110
|
measureDynamic: setOrUpdateDynamicMeasurement,
|
|
73
111
|
measureTotalHeight,
|
|
74
|
-
|
|
112
|
+
enableHeaderPan,
|
|
113
|
+
headerPanMomentumOffset,
|
|
114
|
+
animatedHeaderBaseProps,
|
|
115
|
+
progressThreshold: progressThresholdValue,
|
|
75
116
|
scrollValues,
|
|
117
|
+
scrollToRef,
|
|
76
118
|
activeScrollId: activeScrollId
|
|
77
|
-
}), [originalHeaderHeight, progress, measureTotalHeight, setOrUpdateDynamicMeasurement, scrollValues, activeScrollId,
|
|
119
|
+
}), [originalHeaderHeight, progress, measureTotalHeight, enableHeaderPan, headerPanMomentumOffset, animatedHeaderBaseProps, setOrUpdateDynamicMeasurement, scrollValues, activeScrollId, progressThresholdValue]);
|
|
78
120
|
return /*#__PURE__*/_jsx(HeaderMotionContext.Provider, {
|
|
79
121
|
value: ctxValue,
|
|
80
122
|
children: children
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","
|
|
1
|
+
{"version":3,"names":["useCallback","useRef","useEffect","useMemo","Extrapolation","interpolate","useAnimatedReaction","useDerivedValue","useSharedValue","HeaderMotionContext","DEFAULT_MEASURE_DYNAMIC","DEFAULT_PROGRESS_THRESHOLD","DEFAULT_SCROLL_ID","getInitialScrollValue","jsx","_jsx","resolveScrollIdForProgress","scrollValues","activeScrollIdValue","onlyNonDefaultId","key","HeaderMotionContextProvider","progressThreshold","measureDynamic","measureDynamicMode","activeScrollId","progressExtrapolation","CLAMP","enableHeaderPan","children","dynamicMeasurement","undefined","originalHeaderHeight","progressThresholdValue","Infinity","headerPanMomentumOffset","setOrUpdateDynamicMeasurement","e","prevMeasurement","get","measured","set","measureTotalHeight","measuredValue","nativeEvent","layout","height","id","modify","value","progress","values","scrollValue","threshold","min","current","scrollToRef","animatedHeaderBaseProps","ctxValue","Provider"],"sourceRoot":"../../../src","sources":["components/HeaderMotion.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -26,7 +26,11 @@ import { useScrollManager } from "../hooks/index.js";
|
|
|
26
26
|
export function HeaderMotionScrollManager({
|
|
27
27
|
children,
|
|
28
28
|
scrollId,
|
|
29
|
-
animatedRef
|
|
29
|
+
animatedRef,
|
|
30
|
+
refreshControl,
|
|
31
|
+
refreshing,
|
|
32
|
+
onRefresh,
|
|
33
|
+
progressViewOffset
|
|
30
34
|
}) {
|
|
31
35
|
if (typeof children !== 'function') {
|
|
32
36
|
throw new Error('HeaderMotion.ScrollManager only accepts render function as the only child.');
|
|
@@ -35,7 +39,11 @@ export function HeaderMotionScrollManager({
|
|
|
35
39
|
scrollableProps,
|
|
36
40
|
headerMotionContext
|
|
37
41
|
} = useScrollManager(scrollId, {
|
|
38
|
-
animatedRef
|
|
42
|
+
animatedRef,
|
|
43
|
+
refreshControl,
|
|
44
|
+
refreshing,
|
|
45
|
+
onRefresh,
|
|
46
|
+
progressViewOffset
|
|
39
47
|
});
|
|
40
48
|
return children(scrollableProps, headerMotionContext);
|
|
41
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","animatedRef","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,
|
|
1
|
+
{"version":3,"names":["useScrollManager","HeaderMotionScrollManager","children","scrollId","animatedRef","refreshControl","refreshing","onRefresh","progressViewOffset","Error","scrollableProps","headerMotionContext"],"sourceRoot":"../../../src","sources":["components/ScrollManager.tsx"],"mappings":";;AAAA,SAASA,gBAAgB,QAAsC,mBAAU;AAyBzE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,yBAAyBA,CAEvC;EACAC,QAAQ;EACRC,QAAQ;EACRC,WAAW;EACXC,cAAc;EACdC,UAAU;EACVC,SAAS;EACTC;AACoC,CAAC,EAAE;EACvC,IAAI,OAAON,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIO,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGX,gBAAgB,CAC/DG,QAAQ,EACR;IACEC,WAAW;IACXC,cAAc;IACdC,UAAU;IACVC,SAAS;IACTC;EACF,CACF,CAAC;EAED,OAAON,QAAQ,CAACQ,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
|
|
@@ -22,13 +22,17 @@ export function HeaderMotionScrollView({
|
|
|
22
22
|
animatedRef,
|
|
23
23
|
children,
|
|
24
24
|
contentContainerStyle,
|
|
25
|
+
refreshControl,
|
|
25
26
|
...props
|
|
26
27
|
}) {
|
|
27
28
|
return /*#__PURE__*/_jsx(HeaderMotionScrollManager, {
|
|
28
29
|
scrollId: scrollId,
|
|
29
30
|
animatedRef: animatedRef,
|
|
31
|
+
refreshControl: refreshControl,
|
|
30
32
|
children: ({
|
|
31
33
|
onScroll,
|
|
34
|
+
ref,
|
|
35
|
+
refreshControl: managedRefreshControl,
|
|
32
36
|
...scrollViewProps
|
|
33
37
|
}, {
|
|
34
38
|
originalHeaderHeight,
|
|
@@ -36,7 +40,11 @@ export function HeaderMotionScrollView({
|
|
|
36
40
|
}) => /*#__PURE__*/_jsx(Animated.ScrollView, {
|
|
37
41
|
...scrollViewProps,
|
|
38
42
|
...props,
|
|
43
|
+
ref: ref,
|
|
39
44
|
onScroll: onScroll,
|
|
45
|
+
...(managedRefreshControl && {
|
|
46
|
+
refreshControl: managedRefreshControl
|
|
47
|
+
}),
|
|
40
48
|
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
41
49
|
style: [minHeightContentContainerStyle, {
|
|
42
50
|
paddingTop: originalHeaderHeight
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionScrollView","scrollId","animatedRef","children","contentContainerStyle","props","onScroll","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","ScrollView","View","style","paddingTop"],"sourceRoot":"../../../src","sources":["components/ScrollView.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAGR,yBAAyB;AAChC,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAe5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CAAC;EACrCC,QAAQ;EACRC,WAAW;EACXC,QAAQ;EACRC,qBAAqB;
|
|
1
|
+
{"version":3,"names":["Animated","HeaderMotionScrollManager","jsx","_jsx","HeaderMotionScrollView","scrollId","animatedRef","children","contentContainerStyle","refreshControl","props","onScroll","ref","managedRefreshControl","scrollViewProps","originalHeaderHeight","minHeightContentContainerStyle","ScrollView","View","style","paddingTop"],"sourceRoot":"../../../src","sources":["components/ScrollView.tsx"],"mappings":";;AAAA,OAAOA,QAAQ,MAGR,yBAAyB;AAChC,SAASC,yBAAyB,QAAQ,oBAAiB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAe5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CAAC;EACrCC,QAAQ;EACRC,WAAW;EACXC,QAAQ;EACRC,qBAAqB;EACrBC,cAAc;EACd,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEP,IAAA,CAACF,yBAAyB;IACxBI,QAAQ,EAAEA,QAAS;IACnBC,WAAW,EAAEA,WAAgD;IAC7DG,cAAc,EAAEA,cAAe;IAAAF,QAAA,EAE9BA,CACC;MACEI,QAAQ;MACRC,GAAG;MACHH,cAAc,EAAEI,qBAAqB;MACrC,GAAGC;IACL,CAAC,EACD;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDb,IAAA,CAACH,QAAQ,CAACiB,UAAU;MAAA,GACdH,eAAe;MAAA,GACfJ,KAAK;MACTE,GAAG,EAAEA,GAAI;MACTD,QAAQ,EAAEA,QAAS;MAAA,IACdE,qBAAqB,IAAI;QAC5BJ,cAAc,EAAEI;MAClB,CAAC;MAAAN,QAAA,eAEDJ,IAAA,CAACH,QAAQ,CAACkB,IAAI;QACZC,KAAK,EAAE,CACLH,8BAA8B,EAC9B;UAAEI,UAAU,EAAEL;QAAqB,CAAC,EACpCP,qBAAqB,CACrB;QAAAD,QAAA,EAEDA;MAAQ,CACI;IAAC,CACG;EACtB,CACwB,CAAC;AAEhC","ignoreList":[]}
|