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.
Files changed (58) hide show
  1. package/README.md +126 -18
  2. package/lib/module/components/FlatList.js +12 -2
  3. package/lib/module/components/FlatList.js.map +1 -1
  4. package/lib/module/components/HeaderBase.js +53 -5
  5. package/lib/module/components/HeaderBase.js.map +1 -1
  6. package/lib/module/components/HeaderMotion.js +66 -24
  7. package/lib/module/components/HeaderMotion.js.map +1 -1
  8. package/lib/module/components/ScrollManager.js +10 -2
  9. package/lib/module/components/ScrollManager.js.map +1 -1
  10. package/lib/module/components/ScrollView.js +8 -0
  11. package/lib/module/components/ScrollView.js.map +1 -1
  12. package/lib/module/context.js.map +1 -1
  13. package/lib/module/hooks/useMotionProgress.js +6 -2
  14. package/lib/module/hooks/useMotionProgress.js.map +1 -1
  15. package/lib/module/hooks/useScrollManager.js +91 -29
  16. package/lib/module/hooks/useScrollManager.js.map +1 -1
  17. package/lib/module/utils/index.js +1 -0
  18. package/lib/module/utils/index.js.map +1 -1
  19. package/lib/module/utils/refreshControl.js +93 -0
  20. package/lib/module/utils/refreshControl.js.map +1 -0
  21. package/lib/module/utils/values.js +36 -0
  22. package/lib/module/utils/values.js.map +1 -1
  23. package/lib/typescript/src/components/FlatList.d.ts +2 -4
  24. package/lib/typescript/src/components/FlatList.d.ts.map +1 -1
  25. package/lib/typescript/src/components/HeaderBase.d.ts +9 -2
  26. package/lib/typescript/src/components/HeaderBase.d.ts.map +1 -1
  27. package/lib/typescript/src/components/HeaderMotion.d.ts +5 -1
  28. package/lib/typescript/src/components/HeaderMotion.d.ts.map +1 -1
  29. package/lib/typescript/src/components/ScrollManager.d.ts +6 -10
  30. package/lib/typescript/src/components/ScrollManager.d.ts.map +1 -1
  31. package/lib/typescript/src/components/ScrollView.d.ts +3 -3
  32. package/lib/typescript/src/components/ScrollView.d.ts.map +1 -1
  33. package/lib/typescript/src/context.d.ts +7 -3
  34. package/lib/typescript/src/context.d.ts.map +1 -1
  35. package/lib/typescript/src/hooks/useMotionProgress.d.ts.map +1 -1
  36. package/lib/typescript/src/hooks/useScrollManager.d.ts +10 -3
  37. package/lib/typescript/src/hooks/useScrollManager.d.ts.map +1 -1
  38. package/lib/typescript/src/types.d.ts +20 -4
  39. package/lib/typescript/src/types.d.ts.map +1 -1
  40. package/lib/typescript/src/utils/index.d.ts +1 -0
  41. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  42. package/lib/typescript/src/utils/refreshControl.d.ts +150 -0
  43. package/lib/typescript/src/utils/refreshControl.d.ts.map +1 -0
  44. package/lib/typescript/src/utils/values.d.ts +4 -1
  45. package/lib/typescript/src/utils/values.d.ts.map +1 -1
  46. package/package.json +7 -5
  47. package/src/components/FlatList.tsx +23 -9
  48. package/src/components/HeaderBase.tsx +93 -4
  49. package/src/components/HeaderMotion.tsx +102 -26
  50. package/src/components/ScrollManager.tsx +27 -17
  51. package/src/components/ScrollView.tsx +17 -3
  52. package/src/context.ts +9 -2
  53. package/src/hooks/useMotionProgress.ts +10 -2
  54. package/src/hooks/useScrollManager.ts +127 -35
  55. package/src/types.ts +22 -4
  56. package/src/utils/index.ts +1 -0
  57. package/src/utils/refreshControl.tsx +118 -0
  58. 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
- You can provide it as:
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.value,
190
+ progress.get(),
172
191
  [0, 1],
173
- [0, -progressThreshold],
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.value,
276
+ progress.get(),
254
277
  [0, 1],
255
- [0, -progressThreshold],
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 { progress, measureTotalHeight, measureDynamic, progressThreshold } =
327
- useMotionProgress();
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.value,
361
+ progress.get(),
332
362
  [0, 1],
333
- [0, -progressThreshold],
363
+ [0, -threshold],
334
364
  Extrapolation.CLAMP
335
365
  );
336
366
  return { transform: [{ translateY }] };
337
367
  });
338
368
 
339
369
  return (
340
- <AnimatedHeaderBase onLayout={measureTotalHeight} style={containerStyle}>
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
- contentContainerStyle={[
419
- minHeightContentContainerStyle,
420
- { paddingTop: originalHeaderHeight },
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
- renderScrollComponent: propsz => /*#__PURE__*/_jsx(AnimatedScrollContainer, {
44
- ...propsz,
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","propsz","AnimatedScrollContainer","paddingTop","rest","ref","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;AAqB5D;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;IAACI,QAAQ,EAAEA,QAAS;IAACC,WAAW,EAAEA,WAAY;IAAAG,QAAA,EACrEA,CACC;MAAEC,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDV,IAAA,CAACH,QAAQ,CAACc,QAAQ;MAAA,GACZH,eAAe;MAAA,GACfH,KAAK;MACTE,QAAQ,EAAEA,QAAS;MACnBK,qBAAqB,EAAGC,MAAM,iBAC5Bb,IAAA,CAACc,uBAAuB;QAAA,GAClBD,MAAM;QACVT,qBAAqB,EAAE,CACrBM,8BAA8B,EAC9B;UAAEK,UAAU,EAAEN;QAAqB,CAAC,EACpCL,qBAAqB;MACrB,CACH;IACD,CACH;EACF,CACwB,CAAC;AAEhC;AAEA,MAAMU,uBAAuB,gBAAGlB,UAAU,CAGxC,CAAC;EAAEU,QAAQ;EAAEF,qBAAqB;EAAE,GAAGY;AAAK,CAAC,EAAEC,GAAG,KAAK;EACvD,oBACEjB,IAAA,CAACH,QAAQ,CAACqB,UAAU;IAAA,GAAKF,IAAI;IAAEC,GAAG,EAAEA,GAAI;IAAAX,QAAA,eACtCN,IAAA,CAACH,QAAQ,CAACsB,IAAI;MAACC,KAAK,EAAEhB,qBAAsB;MAAAE,QAAA,EAAEA;IAAQ,CAAgB;EAAC,CACpD,CAAC;AAE1B,CAAC,CAAC","ignoreList":[]}
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 { StyleSheet, View } from 'react-native';
4
- import Animated from 'react-native-reanimated';
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
- return /*#__PURE__*/_jsx(Animated.View, {
48
- style: [style, styles.container],
49
- ...rest
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;AAC/D,OAAOC,QAAQ,MAA8B,yBAAyB;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAKvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAAC;EAAEC,KAAK;EAAE,GAAGC;AAAsB,CAAC,EAAE;EAC9D,oBAAOH,IAAA,CAACH,IAAI;IAACK,KAAK,EAAE,CAACA,KAAK,EAAEE,MAAM,CAACC,SAAS,CAAE;IAAA,GAAKF;EAAI,CAAG,CAAC;AAC7D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,kBAAkBA,CAAC;EACjCJ,KAAK;EACL,GAAGC;AACoB,CAAC,EAAE;EAC1B,oBAAOH,IAAA,CAACF,QAAQ,CAACD,IAAI;IAACK,KAAK,EAAE,CAACA,KAAK,EAAEE,MAAM,CAACC,SAAS,CAAE;IAAA,GAAKF;EAAI,CAAG,CAAC;AACtE;AAEA,MAAMC,MAAM,GAAGR,UAAU,CAACW,MAAM,CAAC;EAC/BF,SAAS,EAAE;IACTG,QAAQ,EAAE,UAAU;IACpBC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE;EACT;AACF,CAAC,CAAC","ignoreList":[]}
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, useMemo, useState } from 'react';
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 [dynamicMeasurement, setDynamicMeasurement] = useState(undefined);
22
- const [originalHeaderHeight, setOriginalHeaderHeight] = useState(0);
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
- setDynamicMeasurement(prevMeasurement => {
26
- if (prevMeasurement !== undefined && measureDynamicMode === 'mount') {
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
- if (dynamicMeasurement === undefined) {
37
- return Infinity;
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
- return progressThreshold(dynamicMeasurement);
40
- }, [dynamicMeasurement, progressThreshold]);
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
- setOriginalHeaderHeight(measuredValue);
44
- }, [setOriginalHeaderHeight]);
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 id = activeScrollId?.get() ?? DEFAULT_SCROLL_ID;
59
- const scrollValue = scrollValues.get()[id];
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 + calculatedProgressThreshold], [0, 1], progressExtrapolation);
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
- progressThreshold: calculatedProgressThreshold,
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, calculatedProgressThreshold]);
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","useMemo","useState","Extrapolation","interpolate","useAnimatedReaction","useDerivedValue","useSharedValue","HeaderMotionContext","DEFAULT_MEASURE_DYNAMIC","DEFAULT_PROGRESS_THRESHOLD","DEFAULT_SCROLL_ID","getInitialScrollValue","jsx","_jsx","HeaderMotionContextProvider","progressThreshold","measureDynamic","measureDynamicMode","activeScrollId","progressExtrapolation","CLAMP","children","dynamicMeasurement","setDynamicMeasurement","undefined","originalHeaderHeight","setOriginalHeaderHeight","setOrUpdateDynamicMeasurement","e","measured","prevMeasurement","calculatedProgressThreshold","Infinity","measureTotalHeight","measuredValue","nativeEvent","layout","height","scrollValues","get","id","modify","value","progress","scrollValue","min","current","ctxValue","Provider"],"sourceRoot":"../../../src","sources":["components/HeaderMotion.tsx"],"mappings":"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","ignoreList":[]}
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,QAAQ,mBAAU;AA4B3C;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,CAAC;EACxCC,QAAQ;EACRC,QAAQ;EACRC;AAC8B,CAAC,EAAE;EACjC,IAAI,OAAOF,QAAQ,KAAK,UAAU,EAAE;IAClC,MAAM,IAAIG,KAAK,CACb,4EACF,CAAC;EACH;EAEA,MAAM;IAAEC,eAAe;IAAEC;EAAoB,CAAC,GAAGP,gBAAgB,CAACG,QAAQ,EAAE;IAC1EC;EACF,CAAC,CAAC;EAEF,OAAOF,QAAQ,CAACI,eAAe,EAAEC,mBAAmB,CAAC;AACvD","ignoreList":[]}
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;EACrB,GAAGC;AACwB,CAAC,EAAE;EAC9B,oBACEN,IAAA,CAACF,yBAAyB;IAACI,QAAQ,EAAEA,QAAS;IAACC,WAAW,EAAEA,WAAY;IAAAC,QAAA,EACrEA,CACC;MAAEG,QAAQ;MAAE,GAAGC;IAAgB,CAAC,EAChC;MAAEC,oBAAoB;MAAEC;IAA+B,CAAC,kBAExDV,IAAA,CAACH,QAAQ,CAACc,UAAU;MAAA,GACdH,eAAe;MAAA,GACfF,KAAK;MACTC,QAAQ,EAAEA,QAAS;MAAAH,QAAA,eAEnBJ,IAAA,CAACH,QAAQ,CAACe,IAAI;QACZC,KAAK,EAAE,CACLH,8BAA8B,EAC9B;UAAEI,UAAU,EAAEL;QAAqB,CAAC,EACpCJ,qBAAqB,CACrB;QAAAD,QAAA,EAEDA;MAAQ,CACI;IAAC,CACG;EACtB,CACwB,CAAC;AAEhC","ignoreList":[]}
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":[]}