@rootnative/inertia 0.0.5 → 0.0.7
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/CHANGELOG.md +69 -1
- package/README.md +7 -1
- package/dist/{chunk-OAUWLPQH.mjs → chunk-52QSN2VQ.mjs} +1 -1
- package/dist/{chunk-VQ5D35UA.js → chunk-6V7MOBXO.js} +93 -33
- package/dist/{chunk-RIVVBABB.mjs → chunk-HPJMIBBK.mjs} +93 -34
- package/dist/{chunk-XSK5MNUH.mjs → chunk-KBFN4TRO.mjs} +1 -1
- package/dist/chunk-NPJ46457.js +8 -0
- package/dist/chunk-QJYFTTM2.js +28 -0
- package/dist/{chunk-QQVDZKSD.js → chunk-QYR66E2G.js} +2 -2
- package/dist/{chunk-GTJ6VAH5.mjs → chunk-RUIOM2YZ.mjs} +1 -1
- package/dist/{chunk-27MKBTSG.mjs → chunk-VSK2E35J.mjs} +1 -1
- package/dist/{chunk-27U6766G.js → chunk-WGCF3WQG.js} +2 -2
- package/dist/{chunk-COEJVWRZ.mjs → chunk-WMLS4TMX.mjs} +1 -1
- package/dist/chunk-YUTS6JRU.js +8 -0
- package/dist/chunk-ZOBOKLAS.mjs +22 -0
- package/dist/chunk-ZSOCRHU3.js +8 -0
- package/dist/gestureLayer/index.d.mts +2 -2
- package/dist/gestureLayer/index.d.ts +2 -2
- package/dist/index.d.mts +45 -9
- package/dist/index.d.ts +45 -9
- package/dist/index.js +32 -22
- package/dist/index.mjs +16 -13
- package/dist/motion/FlatList.d.mts +53 -0
- package/dist/motion/FlatList.d.ts +53 -0
- package/dist/motion/FlatList.js +13 -0
- package/dist/motion/FlatList.mjs +4 -0
- package/dist/motion/Image.d.mts +1 -1
- package/dist/motion/Image.d.ts +1 -1
- package/dist/motion/Image.js +3 -3
- package/dist/motion/Image.mjs +2 -2
- package/dist/motion/Pressable.d.mts +1 -1
- package/dist/motion/Pressable.d.ts +1 -1
- package/dist/motion/Pressable.js +3 -3
- package/dist/motion/Pressable.mjs +2 -2
- package/dist/motion/ScrollView.d.mts +1 -1
- package/dist/motion/ScrollView.d.ts +1 -1
- package/dist/motion/ScrollView.js +3 -3
- package/dist/motion/ScrollView.mjs +2 -2
- package/dist/motion/Text.d.mts +1 -1
- package/dist/motion/Text.d.ts +1 -1
- package/dist/motion/Text.js +3 -3
- package/dist/motion/Text.mjs +2 -2
- package/dist/motion/View.d.mts +1 -1
- package/dist/motion/View.d.ts +1 -1
- package/dist/motion/View.js +3 -3
- package/dist/motion/View.mjs +2 -2
- package/dist/touch/index.d.mts +1 -1
- package/dist/touch/index.d.ts +1 -1
- package/dist/{types-BQgLJeQG.d.mts → types-DyJpG64F.d.mts} +1 -1
- package/dist/{types-BQgLJeQG.d.ts → types-DyJpG64F.d.ts} +1 -1
- package/dist/{useGesture-DfaTx-3t.d.mts → useGesture-CnZQnYHH.d.mts} +1 -1
- package/dist/{useGesture-B0_CzOUz.d.ts → useGesture-DbH46EBp.d.ts} +1 -1
- package/jest-setup.js +7 -1
- package/llms.txt +8 -3
- package/package.json +8 -1
- package/src/index.ts +5 -0
- package/src/internal/boxShadow.ts +71 -9
- package/src/internal/color.ts +70 -0
- package/src/motion/FlatList.tsx +77 -0
- package/src/motion/createMotionComponent.tsx +116 -47
- package/src/motion/index.ts +3 -0
- package/src/values/useScroll.ts +9 -5
- package/dist/chunk-67GHRCF6.js +0 -8
- package/dist/chunk-GPOMFIIU.js +0 -8
- package/dist/chunk-K63LXGKS.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,72 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.0.7] - 2026-08-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`Motion.FlatList` — a virtualized animated scroller.** Reachable from the `Motion` namespace, as the named export `MotionFlatList`, and through the new `@rootnative/inertia/flat-list` subpath.
|
|
12
|
+
|
|
13
|
+
It closes a gap that forced a real architectural compromise on consumers: `useScroll`'s `onScroll` is a worklet handler, which only functions on a Reanimated animated component, and until now the only animated scroller was `Motion.ScrollView` — which mounts every row. A long list could virtualize (a plain `FlatList`, no animation) or animate from scroll position (`Motion.ScrollView`, every row mounted), not both. Nothing about `useScroll` was ever specific to `ScrollView`; the primitive was simply missing.
|
|
14
|
+
|
|
15
|
+
Animation props apply to the scroll **container**, matching `Motion.ScrollView`. Rows animate via a `Motion.*` primitive inside `renderItem`, which is what makes scroll-driven row effects work. The `layout` prop animates the list frame; Reanimated's `itemLayoutAnimation` is forwarded untouched for per-row layout animation.
|
|
16
|
+
|
|
17
|
+
Typing keeps both inference paths that a naive wrapper loses. `createMotionComponent<C>` returns a non-generic component, so `data` / `renderItem` would collapse to `any` — the item type is restored with a generic call signature, the same fix Reanimated applies to its own `Animated.FlatList`. The variants map is a **second** generic on that one signature, so `animate="typo"` against a `variants` prop stays a compile error here exactly as on every other primitive; declaring only the item generic would have silently dropped that narrowing on this primitive alone.
|
|
18
|
+
|
|
19
|
+
Built on Reanimated's `Animated.FlatList` rather than RN's `FlatList`, which supplies the `CellRendererComponent` injection behind `itemLayoutAnimation` and defaults `scrollEventThrottle` to 1 — so a `useScroll` handler reports every frame with no extra prop.
|
|
20
|
+
|
|
21
|
+
**Bundle cost: 9.10 kB for the new subpath, +0.04 kB on the root entry**, and nothing on existing subpaths. The cheapest primitive added so far: it is almost entirely the shared factory, adding no parser, no interpolation, and no worklet branch.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **`gesture={{ pressed: … }}` now responds to a mouse on web.** On any primitive that isn't a `Pressable` — a plain `Motion.View`, `Motion.Text`, `Motion.Image` — the pressed layer never engaged under a desktop click. It has been inert on web since the `gesture` prop shipped in `0.0.1`.
|
|
26
|
+
|
|
27
|
+
The cause is which events the layer was wired to. `pressed` was driven by `onTouchStart` / `onTouchEnd` plus `onPressIn` / `onPressOut`. The press pair only exists on `Pressable`-style hosts, and react-native-web forwards `onTouchStart` to the DOM as a real `touchstart` listener — which a mouse never fires. So `Motion.Pressable` worked (it has the press path) while every other primitive had no live path at all for a pointer that isn't a finger.
|
|
28
|
+
|
|
29
|
+
The layer now also listens on `onPointerDown` / `onPointerUp` / `onPointerCancel`, which react-native-web forwards and which cover mouse, pen, and touch alike. `pressed` means "any pointer" on every platform. `onPointerCancel` is included so a browser-initiated takeover (a scroll or drag beginning mid-press) releases the layer instead of leaving it stuck on.
|
|
30
|
+
|
|
31
|
+
A web touch emits both `touchstart` and `pointerdown`; both set the same flag to the same value, so the overlap is idempotent rather than a double-toggle. React Native has no pointer props, so the added handlers are inert on iOS and Android. `hovered`, `focused`, and `focusVisible` were never affected — their events are forwarded on every primitive.
|
|
32
|
+
|
|
33
|
+
**Bundle cost: +0.06 kB (+0.7%) per primitive subpath**, 9.05 → 9.11 kB brotlied, +0.04 kB on the root entry. No `size-limit` cap moved. Handlers are still mounted only when `pressed` is declared, so the gesture-less path is unchanged.
|
|
34
|
+
|
|
35
|
+
### Internal
|
|
36
|
+
|
|
37
|
+
- **`pressed-modalities.test.tsx` asserts each input modality separately.** Every pre-existing gesture test fires `pressIn` — the one path that already worked on every platform — which is why a six-release gap in the touch and pointer paths went unseen. The new file drives touch, pointer, and press independently, plus the cancel path, the both-events-at-once overlap, composition with a consumer's own pointer handlers, and the guarantee that no pointer handler is mounted when `pressed` isn't declared.
|
|
38
|
+
|
|
39
|
+
## [0.0.6] - 2026-08-08
|
|
40
|
+
|
|
41
|
+
**Defect release: two animations that never ran.** Both trace to one assumption about what Reanimated accepts as an animatable value, and both were hidden by the same thing — `type: 'timing'` snaps to its target when the duration elapses, so a total interpolation failure still produced the right end state. `animate={{ boxShadow }}` was inert under the default spring; every colour key was inert when it rested at its default, which is the far more common path. Neither is caught by a mocked test suite, so this release also adds a test file that runs Reanimated's real drivers.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **`animate={{ boxShadow }}` now animates under `type: 'spring'`** — the library default, and the documented recommendation, so `animate={{ boxShadow }}` with no `transition` prop at all was the broken path. The key worked under `type: 'timing'` and was inert under spring, from its introduction in `0.0.4` until now.
|
|
46
|
+
|
|
47
|
+
The cause was the shape of the value handed to Reanimated. Its animation drivers walk a structured value by dispatching on each leaf's runtime shape, but the two container branches are **not symmetrical** (`animation/util.ts`): `objectOnStart` re-assigns the decorated `onStart` onto each child, so a child that is itself an object or a colour is dispatched again, recursively — while `arrayOnStart` does not, handing every element straight to the scalar spring/timing maths. `boxShadow`'s payload was an array of layer objects, so each layer was evaluated as `object - object` → `NaN`.
|
|
48
|
+
|
|
49
|
+
Why only spring broke: `withTiming` snaps to its target once the duration elapses, whatever the interpolation produced along the way, so the shadow still arrived and the fault stayed hidden. `withSpring` decides it has settled via `isAnimationTerminatingCalculation`, and every comparison against `NaN` is false — so the animation never finished, the shared value held `'[object Object]NaN'` indefinitely, `onAnimationEnd` never fired, and the frame loop never stopped.
|
|
50
|
+
|
|
51
|
+
The payload is now keyed by index (`{ 0: layer, 1: layer }`), which routes it down the object branch where the recursion works and each layer's colour reaches the RGBA-channel path. The change is internal: `animate={{ boxShadow }}` accepts the same CSS string and `BoxShadowValue[]` forms, endpoint padding is unchanged, and `onAnimationEnd`'s `value` is still reported as a layer list.
|
|
52
|
+
|
|
53
|
+
- **Colour keys can now animate away from their resting default.** `'transparent'` is the one CSS colour name Reanimated's `isColor()` rejects — its colour table maps the keyword to `undefined` while every other name maps to a packed integer. A value that fails that gate but is still a string falls to the prefix-number-suffix branch built for values like `'100%'`, producing `'transparentNaN'` and, under spring, never settling.
|
|
54
|
+
|
|
55
|
+
`'transparent'` was Inertia's resting default for `backgroundColor`, `borderColor`, `color`, `tintColor`, and `shadowColor`, so `<Motion.View animate={{ backgroundColor: '#4f46e5' }} />` on an element with no static colour and no `initial` never animated. All five defaults are now `'rgba(0, 0, 0, 0)'` — the identical colour, recognised by the gate — and the keyword is rewritten to it wherever it would enter a colour slot: `initial`, `animate` (including keyframe sequences and `{ to }` steps), and the static `style` a never-driven key rests at.
|
|
56
|
+
|
|
57
|
+
Only values handed to `withSpring` / `withTiming` are affected. `interpolateColor` parses the keyword correctly, so the `gesture` cascade, the `layoutId` style carry, and `useShadow` were never affected and keep the consumer's own spelling.
|
|
58
|
+
|
|
59
|
+
**Visible difference:** a colour key resting at its default now renders `'rgba(0, 0, 0, 0)'` where it used to render `'transparent'`. Same colour, but a snapshot test asserting the literal string will need updating.
|
|
60
|
+
|
|
61
|
+
- **`boxShadow`'s transparent padding layer** — added when the two endpoints have different layer counts — used the same keyword, so a single padding layer was enough to hang a whole shadow animation. It is now `'rgba(0, 0, 0, 0)'`.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- **`TRANSPARENT`** — the colour a custom animated component should seed a colour shared value with when it has no other source. Exported alongside `resolveTransition` and the other building blocks for custom components, because the obvious choice (`'transparent'`) is the one spelling Reanimated cannot animate away from, and nothing about the failure points at the cause.
|
|
66
|
+
|
|
67
|
+
**Bundle cost: +0.13 kB (+1.5%) per primitive subpath**, 8.92 → 9.05 kB brotlied, +0.18 kB on the root entry (12.10 → 12.28 kB). No `size-limit` cap moved. The payload reshape is close to free — one index-keying pass on the JS thread and one loop in the worklet, replacing an array that crossed over by reference — and most of the delta is the colour normalization, which has to run on four separate paths into a slot.
|
|
68
|
+
|
|
69
|
+
### Internal
|
|
70
|
+
|
|
71
|
+
- **`reanimated-drivers.test.ts` runs Reanimated's real animation drivers**, imported by deep path, instead of the static mock the rest of the suite uses. Both defects above were invisible to that mock — `withSpring` and `withTiming` are the identity function there, so the payload Inertia produced looked correct in every assertion while being unanimatable in fact. The new file drives Reanimated's own `onStart` / `onFrame` protocol (the one its `valueSetter` runs) and asserts that leaves converge, that a spring settles, and that mid-flight frames carry numbers. It also pins the two upstream behaviours the fixes work around, so a Reanimated upgrade that changes either fails loudly rather than silently leaving dead workarounds behind.
|
|
72
|
+
|
|
7
73
|
## [0.0.5] - 2026-07-31
|
|
8
74
|
|
|
9
75
|
**Correctness release for the `animate` type surface.** The 40 layout and text-metric style keys that typechecked but were silently dropped at runtime now either animate or fail to compile. No API removals; the type narrowing is technically breaking for code that passed a never-driven key, but that code was already a no-op.
|
|
@@ -191,7 +257,9 @@ Initial alpha publish. The full initial surface is in place; APIs are still subj
|
|
|
191
257
|
- SVG path morphing, gradient interpolation, and shared-element transitions across screens are out of scope until `0.2.x` / `1.x` per the roadmap.
|
|
192
258
|
- `react-native-gesture-handler` integration (drag, pan, swipe sub-states) lands in `0.2` via the optional `@rootnative/inertia-gestures` adapter.
|
|
193
259
|
|
|
194
|
-
[unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.
|
|
260
|
+
[unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.7...HEAD
|
|
261
|
+
[0.0.7]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.7
|
|
262
|
+
[0.0.6]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.6
|
|
195
263
|
[0.0.5]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.5
|
|
196
264
|
[0.0.4]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.4
|
|
197
265
|
[0.0.3]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.3
|
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Absolute URL, not a relative path: this README is the npm package page, and
|
|
3
|
+
npm does not resolve repository-relative image paths.
|
|
4
|
+
-->
|
|
5
|
+
<img src="https://raw.githubusercontent.com/rootnative/inertia/main/assets/brand/inertia-mark.png" alt="" width="88" height="88" />
|
|
6
|
+
|
|
1
7
|
# @rootnative/inertia
|
|
2
8
|
|
|
3
9
|
[](https://www.npmjs.com/package/@rootnative/inertia)
|
|
@@ -6,7 +12,7 @@
|
|
|
6
12
|
|
|
7
13
|
Declarative animation primitives for React Native, built as a thin wrapper around [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/). Inspired by Framer Motion (web) and react-spring (cross-platform).
|
|
8
14
|
|
|
9
|
-
> **Status:** `0.0.
|
|
15
|
+
> **Status:** `0.0.7` — stable. Pre-`1.0.0` minor versions may break — see the root [README](https://github.com/rootnative/inertia#versioning--release).
|
|
10
16
|
|
|
11
17
|
## Install
|
|
12
18
|
|
|
@@ -11,6 +11,30 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
11
11
|
|
|
12
12
|
var Animated__default = /*#__PURE__*/_interopDefault(Animated);
|
|
13
13
|
|
|
14
|
+
// src/internal/color.ts
|
|
15
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16
|
+
function normalizeAnimatableColor(value) {
|
|
17
|
+
return value === "transparent" ? TRANSPARENT : value;
|
|
18
|
+
}
|
|
19
|
+
function normalizeAnimatableColorTarget(target) {
|
|
20
|
+
if (typeof target === "string") {
|
|
21
|
+
return normalizeAnimatableColor(target);
|
|
22
|
+
}
|
|
23
|
+
if (!Array.isArray(target)) return target;
|
|
24
|
+
let changed = false;
|
|
25
|
+
const next = target.map((step) => {
|
|
26
|
+
if (step === "transparent") {
|
|
27
|
+
changed = true;
|
|
28
|
+
return TRANSPARENT;
|
|
29
|
+
}
|
|
30
|
+
if (step !== null && typeof step === "object" && step.to === "transparent") {
|
|
31
|
+
changed = true;
|
|
32
|
+
return { ...step, to: TRANSPARENT };
|
|
33
|
+
}
|
|
34
|
+
return step;
|
|
35
|
+
});
|
|
36
|
+
return changed ? next : target;
|
|
37
|
+
}
|
|
14
38
|
var PresenceContext = react.createContext(null);
|
|
15
39
|
function usePresence() {
|
|
16
40
|
return react.useContext(PresenceContext);
|
|
@@ -250,7 +274,7 @@ function invisibleLayer(inset) {
|
|
|
250
274
|
offsetY: 0,
|
|
251
275
|
blurRadius: 0,
|
|
252
276
|
spreadDistance: 0,
|
|
253
|
-
color:
|
|
277
|
+
color: TRANSPARENT,
|
|
254
278
|
inset
|
|
255
279
|
};
|
|
256
280
|
}
|
|
@@ -266,8 +290,8 @@ function coerceLength(value, field) {
|
|
|
266
290
|
return parseFloat(trimmed);
|
|
267
291
|
}
|
|
268
292
|
function strip(layer) {
|
|
269
|
-
const { inset: _inset, ...rest } = layer;
|
|
270
|
-
return rest;
|
|
293
|
+
const { inset: _inset, color, ...rest } = layer;
|
|
294
|
+
return { ...rest, color: normalizeAnimatableColor(color) };
|
|
271
295
|
}
|
|
272
296
|
function markInset(insets, i, count) {
|
|
273
297
|
const list = insets ?? new Array(count).fill(false);
|
|
@@ -304,6 +328,17 @@ function prepareBoxShadowAnimation(current, target) {
|
|
|
304
328
|
}
|
|
305
329
|
return { from, to, insets };
|
|
306
330
|
}
|
|
331
|
+
function layersToPayload(layers) {
|
|
332
|
+
const payload = {};
|
|
333
|
+
for (let i = 0; i < layers.length; i++) payload[i] = layers[i];
|
|
334
|
+
return payload;
|
|
335
|
+
}
|
|
336
|
+
function payloadToLayers(payload) {
|
|
337
|
+
"worklet";
|
|
338
|
+
const layers = [];
|
|
339
|
+
for (let i = 0; payload[i] !== void 0; i++) layers.push(payload[i]);
|
|
340
|
+
return layers;
|
|
341
|
+
}
|
|
307
342
|
function resolveLayoutTransition(layout) {
|
|
308
343
|
if (!layout) return void 0;
|
|
309
344
|
const cfg = layout === true ? { type: "spring" } : layout;
|
|
@@ -703,7 +738,7 @@ var COLOR_KEY_SET = new Set(COLOR_KEYS);
|
|
|
703
738
|
var SHADOW_OFFSET_KEY_SET = new Set(SHADOW_OFFSET_KEYS);
|
|
704
739
|
var STRUCTURED_KEY_SET = new Set(STRUCTURED_KEYS);
|
|
705
740
|
var SHARED_STYLE_KEY_SET = new Set(SHARED_STYLE_KEYS);
|
|
706
|
-
var NO_BOX_SHADOW = Object.freeze(
|
|
741
|
+
var NO_BOX_SHADOW = Object.freeze({});
|
|
707
742
|
var GESTURE_LAYER_NAMES = [
|
|
708
743
|
"hovered",
|
|
709
744
|
"focused",
|
|
@@ -776,15 +811,21 @@ var DEFAULT_RESTING = {
|
|
|
776
811
|
gap: 0,
|
|
777
812
|
rowGap: 0,
|
|
778
813
|
columnGap: 0,
|
|
779
|
-
//
|
|
780
|
-
// an initial seed for any color animation (no jarring opaque flash
|
|
781
|
-
// when `initial` is omitted) and
|
|
782
|
-
//
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
color
|
|
786
|
-
|
|
787
|
-
|
|
814
|
+
// Fully transparent black is the only safe universal default for colors: it
|
|
815
|
+
// works as an initial seed for any color animation (no jarring opaque flash
|
|
816
|
+
// on mount when `initial` is omitted) and interpolates cleanly into any
|
|
817
|
+
// opaque target.
|
|
818
|
+
//
|
|
819
|
+
// Spelled `rgba(0, 0, 0, 0)` and NOT `'transparent'`, which is not optional.
|
|
820
|
+
// Reanimated's color-name table maps `transparent` to `undefined`, so it is
|
|
821
|
+
// the one named color `isColor()` rejects — a slot resting at the keyword
|
|
822
|
+
// takes the prefix-number-suffix branch on its next animation and produces
|
|
823
|
+
// `NaN` instead of a color. See `TRANSPARENT` in `internal/boxShadow.ts`.
|
|
824
|
+
backgroundColor: TRANSPARENT,
|
|
825
|
+
borderColor: TRANSPARENT,
|
|
826
|
+
color: TRANSPARENT,
|
|
827
|
+
tintColor: TRANSPARENT,
|
|
828
|
+
shadowColor: TRANSPARENT,
|
|
788
829
|
shadowOffsetWidth: 0,
|
|
789
830
|
shadowOffsetHeight: 0,
|
|
790
831
|
boxShadow: NO_BOX_SHADOW
|
|
@@ -971,25 +1012,28 @@ function createMotionComponent(Component) {
|
|
|
971
1012
|
const raw = flat.boxShadow;
|
|
972
1013
|
if (raw !== void 0) {
|
|
973
1014
|
styleRestingShadow = normalizeBoxShadow(raw);
|
|
974
|
-
styleResting.boxShadow =
|
|
1015
|
+
styleResting.boxShadow = layersToPayload(
|
|
1016
|
+
styleRestingShadow.layers
|
|
1017
|
+
);
|
|
975
1018
|
}
|
|
976
1019
|
continue;
|
|
977
1020
|
}
|
|
978
1021
|
const v = styleValueFor(flat, key);
|
|
979
|
-
if (v !== void 0)
|
|
1022
|
+
if (v !== void 0) {
|
|
1023
|
+
styleResting[key] = COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(v) : v;
|
|
1024
|
+
}
|
|
980
1025
|
}
|
|
981
1026
|
}
|
|
982
1027
|
}
|
|
983
1028
|
const boxShadowSeedRef = react.useRef(null);
|
|
984
1029
|
if (boxShadowSeedRef.current === null) {
|
|
985
1030
|
const source = initial === false ? animateRecord.boxShadow : initialRecord?.boxShadow ?? animateRecord.boxShadow;
|
|
986
|
-
boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? {
|
|
987
|
-
layers: [...NO_BOX_SHADOW],
|
|
988
|
-
insets: null
|
|
989
|
-
};
|
|
1031
|
+
boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? { layers: [], insets: null };
|
|
990
1032
|
}
|
|
991
1033
|
const sharedValues = useAnimatableSharedValues((key) => {
|
|
992
|
-
if (key === "boxShadow")
|
|
1034
|
+
if (key === "boxShadow") {
|
|
1035
|
+
return layersToPayload(boxShadowSeedRef.current.layers);
|
|
1036
|
+
}
|
|
993
1037
|
if (SHADOW_OFFSET_KEY_SET.has(key)) {
|
|
994
1038
|
const axis = shadowOffsetAxisFor(key);
|
|
995
1039
|
if (initial === false) {
|
|
@@ -1002,9 +1046,11 @@ function createMotionComponent(Component) {
|
|
|
1002
1046
|
}
|
|
1003
1047
|
if (initial === false) {
|
|
1004
1048
|
const a = animateRecord[key];
|
|
1005
|
-
|
|
1049
|
+
const seed2 = restValue(a) ?? styleResting[key] ?? DEFAULT_RESTING[key];
|
|
1050
|
+
return COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(seed2) : seed2;
|
|
1006
1051
|
}
|
|
1007
|
-
|
|
1052
|
+
const seed = initialRecord?.[key] ?? restValue(animateRecord[key]) ?? styleResting[key] ?? DEFAULT_RESTING[key];
|
|
1053
|
+
return COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(seed) : seed;
|
|
1008
1054
|
});
|
|
1009
1055
|
const boxShadowInsets = Animated.useSharedValue(
|
|
1010
1056
|
boxShadowSeedRef.current.insets
|
|
@@ -1117,7 +1163,7 @@ function createMotionComponent(Component) {
|
|
|
1117
1163
|
TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
|
|
1118
1164
|
);
|
|
1119
1165
|
sharedValues[key].value = chunkPM6CVGXJ_js.resolveAnimatableValue(
|
|
1120
|
-
target,
|
|
1166
|
+
COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
|
|
1121
1167
|
cfg,
|
|
1122
1168
|
factory
|
|
1123
1169
|
);
|
|
@@ -1254,14 +1300,14 @@ function createMotionComponent(Component) {
|
|
|
1254
1300
|
out.shadowOffset = { width: shadowOffsetW, height: shadowOffsetH };
|
|
1255
1301
|
}
|
|
1256
1302
|
if (hasBoxShadow) {
|
|
1257
|
-
const
|
|
1303
|
+
const payload = sharedValues.boxShadow.value;
|
|
1258
1304
|
const insets = boxShadowInsets.value;
|
|
1259
1305
|
if (insets === null) {
|
|
1260
|
-
out.boxShadow =
|
|
1306
|
+
out.boxShadow = payloadToLayers(payload);
|
|
1261
1307
|
} else {
|
|
1262
1308
|
const withInset = [];
|
|
1263
|
-
for (let i = 0; i
|
|
1264
|
-
withInset.push({ ...
|
|
1309
|
+
for (let i = 0; payload[i] !== void 0; i++) {
|
|
1310
|
+
withInset.push({ ...payload[i], inset: insets[i] });
|
|
1265
1311
|
}
|
|
1266
1312
|
out.boxShadow = withInset;
|
|
1267
1313
|
}
|
|
@@ -1377,6 +1423,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1377
1423
|
}
|
|
1378
1424
|
const reportedIteration = state.iteration;
|
|
1379
1425
|
if (phase === "sequence" || phase === "repeat") state.iteration++;
|
|
1426
|
+
const reportedValue = key === "boxShadow" && value !== void 0 ? payloadToLayers(value) : value;
|
|
1380
1427
|
const fn = onAnimationEndRef.current;
|
|
1381
1428
|
if (fn) {
|
|
1382
1429
|
if (isTransformKey && transformGroup && phase === "animation") {
|
|
@@ -1385,7 +1432,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1385
1432
|
fn({
|
|
1386
1433
|
key: "transform",
|
|
1387
1434
|
finished,
|
|
1388
|
-
value,
|
|
1435
|
+
value: reportedValue,
|
|
1389
1436
|
target,
|
|
1390
1437
|
phase,
|
|
1391
1438
|
step,
|
|
@@ -1396,7 +1443,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1396
1443
|
fn({
|
|
1397
1444
|
key,
|
|
1398
1445
|
finished,
|
|
1399
|
-
value,
|
|
1446
|
+
value: reportedValue,
|
|
1400
1447
|
target,
|
|
1401
1448
|
phase,
|
|
1402
1449
|
step,
|
|
@@ -1421,16 +1468,16 @@ function shadowOffsetAxisValue(source, axis) {
|
|
|
1421
1468
|
return source?.[axis];
|
|
1422
1469
|
}
|
|
1423
1470
|
function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
|
|
1424
|
-
const currentLayers =
|
|
1471
|
+
const currentLayers = payloadToLayers(slot.value);
|
|
1425
1472
|
const { from, to, insets } = prepareBoxShadowAnimation(
|
|
1426
|
-
{ layers:
|
|
1473
|
+
{ layers: currentLayers, insets: insetSlot.value },
|
|
1427
1474
|
target
|
|
1428
1475
|
);
|
|
1429
1476
|
insetSlot.value = insets;
|
|
1430
|
-
if (from.length !== currentLayers.length) slot.value = from;
|
|
1477
|
+
if (from.length !== currentLayers.length) slot.value = layersToPayload(from);
|
|
1431
1478
|
slot.value = chunkPM6CVGXJ_js.resolveTransition(
|
|
1432
1479
|
cfg,
|
|
1433
|
-
to,
|
|
1480
|
+
layersToPayload(to),
|
|
1434
1481
|
factory?.("animation", void 0)
|
|
1435
1482
|
);
|
|
1436
1483
|
}
|
|
@@ -1605,6 +1652,15 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
|
|
|
1605
1652
|
);
|
|
1606
1653
|
handlers.onPressIn = compose(rest.onPressIn, () => setPressed(true));
|
|
1607
1654
|
handlers.onPressOut = compose(rest.onPressOut, () => setPressed(false));
|
|
1655
|
+
handlers.onPointerDown = compose(
|
|
1656
|
+
rest.onPointerDown,
|
|
1657
|
+
() => setPressed(true)
|
|
1658
|
+
);
|
|
1659
|
+
handlers.onPointerUp = compose(rest.onPointerUp, () => setPressed(false));
|
|
1660
|
+
handlers.onPointerCancel = compose(
|
|
1661
|
+
rest.onPointerCancel,
|
|
1662
|
+
() => setPressed(false)
|
|
1663
|
+
);
|
|
1608
1664
|
}
|
|
1609
1665
|
if (gesture.focused || gesture.focusVisible) {
|
|
1610
1666
|
handlers.onFocus = compose(rest.onFocus, () => {
|
|
@@ -1634,6 +1690,9 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
|
|
|
1634
1690
|
rest.onTouchCancel,
|
|
1635
1691
|
rest.onPressIn,
|
|
1636
1692
|
rest.onPressOut,
|
|
1693
|
+
rest.onPointerDown,
|
|
1694
|
+
rest.onPointerUp,
|
|
1695
|
+
rest.onPointerCancel,
|
|
1637
1696
|
rest.onFocus,
|
|
1638
1697
|
rest.onBlur,
|
|
1639
1698
|
rest.onMouseEnter,
|
|
@@ -1649,6 +1708,7 @@ function compose(user, ours) {
|
|
|
1649
1708
|
}
|
|
1650
1709
|
|
|
1651
1710
|
exports.Presence = Presence;
|
|
1711
|
+
exports.TRANSPARENT = TRANSPARENT;
|
|
1652
1712
|
exports.createMotionComponent = createMotionComponent;
|
|
1653
1713
|
exports.pairBoxShadowLayers = pairBoxShadowLayers;
|
|
1654
1714
|
exports.resolveBoxShadowInput = resolveBoxShadowInput;
|
|
@@ -5,6 +5,30 @@ import { jsx, Fragment } from 'react/jsx-runtime';
|
|
|
5
5
|
import Animated, { useSharedValue, cancelAnimation, useAnimatedStyle, interpolateColor, reanimatedVersion, runOnJS, LinearTransition, withSequence, withTiming, withSpring } from 'react-native-reanimated';
|
|
6
6
|
import { StyleSheet } from 'react-native';
|
|
7
7
|
|
|
8
|
+
// src/internal/color.ts
|
|
9
|
+
var TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
10
|
+
function normalizeAnimatableColor(value) {
|
|
11
|
+
return value === "transparent" ? TRANSPARENT : value;
|
|
12
|
+
}
|
|
13
|
+
function normalizeAnimatableColorTarget(target) {
|
|
14
|
+
if (typeof target === "string") {
|
|
15
|
+
return normalizeAnimatableColor(target);
|
|
16
|
+
}
|
|
17
|
+
if (!Array.isArray(target)) return target;
|
|
18
|
+
let changed = false;
|
|
19
|
+
const next = target.map((step) => {
|
|
20
|
+
if (step === "transparent") {
|
|
21
|
+
changed = true;
|
|
22
|
+
return TRANSPARENT;
|
|
23
|
+
}
|
|
24
|
+
if (step !== null && typeof step === "object" && step.to === "transparent") {
|
|
25
|
+
changed = true;
|
|
26
|
+
return { ...step, to: TRANSPARENT };
|
|
27
|
+
}
|
|
28
|
+
return step;
|
|
29
|
+
});
|
|
30
|
+
return changed ? next : target;
|
|
31
|
+
}
|
|
8
32
|
var PresenceContext = createContext(null);
|
|
9
33
|
function usePresence() {
|
|
10
34
|
return useContext(PresenceContext);
|
|
@@ -244,7 +268,7 @@ function invisibleLayer(inset) {
|
|
|
244
268
|
offsetY: 0,
|
|
245
269
|
blurRadius: 0,
|
|
246
270
|
spreadDistance: 0,
|
|
247
|
-
color:
|
|
271
|
+
color: TRANSPARENT,
|
|
248
272
|
inset
|
|
249
273
|
};
|
|
250
274
|
}
|
|
@@ -260,8 +284,8 @@ function coerceLength(value, field) {
|
|
|
260
284
|
return parseFloat(trimmed);
|
|
261
285
|
}
|
|
262
286
|
function strip(layer) {
|
|
263
|
-
const { inset: _inset, ...rest } = layer;
|
|
264
|
-
return rest;
|
|
287
|
+
const { inset: _inset, color, ...rest } = layer;
|
|
288
|
+
return { ...rest, color: normalizeAnimatableColor(color) };
|
|
265
289
|
}
|
|
266
290
|
function markInset(insets, i, count) {
|
|
267
291
|
const list = insets ?? new Array(count).fill(false);
|
|
@@ -298,6 +322,17 @@ function prepareBoxShadowAnimation(current, target) {
|
|
|
298
322
|
}
|
|
299
323
|
return { from, to, insets };
|
|
300
324
|
}
|
|
325
|
+
function layersToPayload(layers) {
|
|
326
|
+
const payload = {};
|
|
327
|
+
for (let i = 0; i < layers.length; i++) payload[i] = layers[i];
|
|
328
|
+
return payload;
|
|
329
|
+
}
|
|
330
|
+
function payloadToLayers(payload) {
|
|
331
|
+
"worklet";
|
|
332
|
+
const layers = [];
|
|
333
|
+
for (let i = 0; payload[i] !== void 0; i++) layers.push(payload[i]);
|
|
334
|
+
return layers;
|
|
335
|
+
}
|
|
301
336
|
function resolveLayoutTransition(layout) {
|
|
302
337
|
if (!layout) return void 0;
|
|
303
338
|
const cfg = layout === true ? { type: "spring" } : layout;
|
|
@@ -697,7 +732,7 @@ var COLOR_KEY_SET = new Set(COLOR_KEYS);
|
|
|
697
732
|
var SHADOW_OFFSET_KEY_SET = new Set(SHADOW_OFFSET_KEYS);
|
|
698
733
|
var STRUCTURED_KEY_SET = new Set(STRUCTURED_KEYS);
|
|
699
734
|
var SHARED_STYLE_KEY_SET = new Set(SHARED_STYLE_KEYS);
|
|
700
|
-
var NO_BOX_SHADOW = Object.freeze(
|
|
735
|
+
var NO_BOX_SHADOW = Object.freeze({});
|
|
701
736
|
var GESTURE_LAYER_NAMES = [
|
|
702
737
|
"hovered",
|
|
703
738
|
"focused",
|
|
@@ -770,15 +805,21 @@ var DEFAULT_RESTING = {
|
|
|
770
805
|
gap: 0,
|
|
771
806
|
rowGap: 0,
|
|
772
807
|
columnGap: 0,
|
|
773
|
-
//
|
|
774
|
-
// an initial seed for any color animation (no jarring opaque flash
|
|
775
|
-
// when `initial` is omitted) and
|
|
776
|
-
//
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
color
|
|
780
|
-
|
|
781
|
-
|
|
808
|
+
// Fully transparent black is the only safe universal default for colors: it
|
|
809
|
+
// works as an initial seed for any color animation (no jarring opaque flash
|
|
810
|
+
// on mount when `initial` is omitted) and interpolates cleanly into any
|
|
811
|
+
// opaque target.
|
|
812
|
+
//
|
|
813
|
+
// Spelled `rgba(0, 0, 0, 0)` and NOT `'transparent'`, which is not optional.
|
|
814
|
+
// Reanimated's color-name table maps `transparent` to `undefined`, so it is
|
|
815
|
+
// the one named color `isColor()` rejects — a slot resting at the keyword
|
|
816
|
+
// takes the prefix-number-suffix branch on its next animation and produces
|
|
817
|
+
// `NaN` instead of a color. See `TRANSPARENT` in `internal/boxShadow.ts`.
|
|
818
|
+
backgroundColor: TRANSPARENT,
|
|
819
|
+
borderColor: TRANSPARENT,
|
|
820
|
+
color: TRANSPARENT,
|
|
821
|
+
tintColor: TRANSPARENT,
|
|
822
|
+
shadowColor: TRANSPARENT,
|
|
782
823
|
shadowOffsetWidth: 0,
|
|
783
824
|
shadowOffsetHeight: 0,
|
|
784
825
|
boxShadow: NO_BOX_SHADOW
|
|
@@ -965,25 +1006,28 @@ function createMotionComponent(Component) {
|
|
|
965
1006
|
const raw = flat.boxShadow;
|
|
966
1007
|
if (raw !== void 0) {
|
|
967
1008
|
styleRestingShadow = normalizeBoxShadow(raw);
|
|
968
|
-
styleResting.boxShadow =
|
|
1009
|
+
styleResting.boxShadow = layersToPayload(
|
|
1010
|
+
styleRestingShadow.layers
|
|
1011
|
+
);
|
|
969
1012
|
}
|
|
970
1013
|
continue;
|
|
971
1014
|
}
|
|
972
1015
|
const v = styleValueFor(flat, key);
|
|
973
|
-
if (v !== void 0)
|
|
1016
|
+
if (v !== void 0) {
|
|
1017
|
+
styleResting[key] = COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(v) : v;
|
|
1018
|
+
}
|
|
974
1019
|
}
|
|
975
1020
|
}
|
|
976
1021
|
}
|
|
977
1022
|
const boxShadowSeedRef = useRef(null);
|
|
978
1023
|
if (boxShadowSeedRef.current === null) {
|
|
979
1024
|
const source = initial === false ? animateRecord.boxShadow : initialRecord?.boxShadow ?? animateRecord.boxShadow;
|
|
980
|
-
boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? {
|
|
981
|
-
layers: [...NO_BOX_SHADOW],
|
|
982
|
-
insets: null
|
|
983
|
-
};
|
|
1025
|
+
boxShadowSeedRef.current = source !== void 0 ? normalizeBoxShadow(source) : styleRestingShadow ?? { layers: [], insets: null };
|
|
984
1026
|
}
|
|
985
1027
|
const sharedValues = useAnimatableSharedValues((key) => {
|
|
986
|
-
if (key === "boxShadow")
|
|
1028
|
+
if (key === "boxShadow") {
|
|
1029
|
+
return layersToPayload(boxShadowSeedRef.current.layers);
|
|
1030
|
+
}
|
|
987
1031
|
if (SHADOW_OFFSET_KEY_SET.has(key)) {
|
|
988
1032
|
const axis = shadowOffsetAxisFor(key);
|
|
989
1033
|
if (initial === false) {
|
|
@@ -996,9 +1040,11 @@ function createMotionComponent(Component) {
|
|
|
996
1040
|
}
|
|
997
1041
|
if (initial === false) {
|
|
998
1042
|
const a = animateRecord[key];
|
|
999
|
-
|
|
1043
|
+
const seed2 = restValue(a) ?? styleResting[key] ?? DEFAULT_RESTING[key];
|
|
1044
|
+
return COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(seed2) : seed2;
|
|
1000
1045
|
}
|
|
1001
|
-
|
|
1046
|
+
const seed = initialRecord?.[key] ?? restValue(animateRecord[key]) ?? styleResting[key] ?? DEFAULT_RESTING[key];
|
|
1047
|
+
return COLOR_KEY_SET.has(key) ? normalizeAnimatableColor(seed) : seed;
|
|
1002
1048
|
});
|
|
1003
1049
|
const boxShadowInsets = useSharedValue(
|
|
1004
1050
|
boxShadowSeedRef.current.insets
|
|
@@ -1111,7 +1157,7 @@ function createMotionComponent(Component) {
|
|
|
1111
1157
|
TRANSFORM_KEY_SET.has(key) ? transformGroup : void 0
|
|
1112
1158
|
);
|
|
1113
1159
|
sharedValues[key].value = resolveAnimatableValue(
|
|
1114
|
-
target,
|
|
1160
|
+
COLOR_KEY_SET.has(key) ? normalizeAnimatableColorTarget(target) : target,
|
|
1115
1161
|
cfg,
|
|
1116
1162
|
factory
|
|
1117
1163
|
);
|
|
@@ -1248,14 +1294,14 @@ function createMotionComponent(Component) {
|
|
|
1248
1294
|
out.shadowOffset = { width: shadowOffsetW, height: shadowOffsetH };
|
|
1249
1295
|
}
|
|
1250
1296
|
if (hasBoxShadow) {
|
|
1251
|
-
const
|
|
1297
|
+
const payload = sharedValues.boxShadow.value;
|
|
1252
1298
|
const insets = boxShadowInsets.value;
|
|
1253
1299
|
if (insets === null) {
|
|
1254
|
-
out.boxShadow =
|
|
1300
|
+
out.boxShadow = payloadToLayers(payload);
|
|
1255
1301
|
} else {
|
|
1256
1302
|
const withInset = [];
|
|
1257
|
-
for (let i = 0; i
|
|
1258
|
-
withInset.push({ ...
|
|
1303
|
+
for (let i = 0; payload[i] !== void 0; i++) {
|
|
1304
|
+
withInset.push({ ...payload[i], inset: insets[i] });
|
|
1259
1305
|
}
|
|
1260
1306
|
out.boxShadow = withInset;
|
|
1261
1307
|
}
|
|
@@ -1371,6 +1417,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1371
1417
|
}
|
|
1372
1418
|
const reportedIteration = state.iteration;
|
|
1373
1419
|
if (phase === "sequence" || phase === "repeat") state.iteration++;
|
|
1420
|
+
const reportedValue = key === "boxShadow" && value !== void 0 ? payloadToLayers(value) : value;
|
|
1374
1421
|
const fn = onAnimationEndRef.current;
|
|
1375
1422
|
if (fn) {
|
|
1376
1423
|
if (isTransformKey && transformGroup && phase === "animation") {
|
|
@@ -1379,7 +1426,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1379
1426
|
fn({
|
|
1380
1427
|
key: "transform",
|
|
1381
1428
|
finished,
|
|
1382
|
-
value,
|
|
1429
|
+
value: reportedValue,
|
|
1383
1430
|
target,
|
|
1384
1431
|
phase,
|
|
1385
1432
|
step,
|
|
@@ -1390,7 +1437,7 @@ function makeKeyCallbackFactory(key, sharedValue, target, onAnimationEndRef, met
|
|
|
1390
1437
|
fn({
|
|
1391
1438
|
key,
|
|
1392
1439
|
finished,
|
|
1393
|
-
value,
|
|
1440
|
+
value: reportedValue,
|
|
1394
1441
|
target,
|
|
1395
1442
|
phase,
|
|
1396
1443
|
step,
|
|
@@ -1415,16 +1462,16 @@ function shadowOffsetAxisValue(source, axis) {
|
|
|
1415
1462
|
return source?.[axis];
|
|
1416
1463
|
}
|
|
1417
1464
|
function driveBoxShadow(slot, insetSlot, target, cfg, factory) {
|
|
1418
|
-
const currentLayers =
|
|
1465
|
+
const currentLayers = payloadToLayers(slot.value);
|
|
1419
1466
|
const { from, to, insets } = prepareBoxShadowAnimation(
|
|
1420
|
-
{ layers:
|
|
1467
|
+
{ layers: currentLayers, insets: insetSlot.value },
|
|
1421
1468
|
target
|
|
1422
1469
|
);
|
|
1423
1470
|
insetSlot.value = insets;
|
|
1424
|
-
if (from.length !== currentLayers.length) slot.value = from;
|
|
1471
|
+
if (from.length !== currentLayers.length) slot.value = layersToPayload(from);
|
|
1425
1472
|
slot.value = resolveTransition(
|
|
1426
1473
|
cfg,
|
|
1427
|
-
to,
|
|
1474
|
+
layersToPayload(to),
|
|
1428
1475
|
factory?.("animation", void 0)
|
|
1429
1476
|
);
|
|
1430
1477
|
}
|
|
@@ -1599,6 +1646,15 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
|
|
|
1599
1646
|
);
|
|
1600
1647
|
handlers.onPressIn = compose(rest.onPressIn, () => setPressed(true));
|
|
1601
1648
|
handlers.onPressOut = compose(rest.onPressOut, () => setPressed(false));
|
|
1649
|
+
handlers.onPointerDown = compose(
|
|
1650
|
+
rest.onPointerDown,
|
|
1651
|
+
() => setPressed(true)
|
|
1652
|
+
);
|
|
1653
|
+
handlers.onPointerUp = compose(rest.onPointerUp, () => setPressed(false));
|
|
1654
|
+
handlers.onPointerCancel = compose(
|
|
1655
|
+
rest.onPointerCancel,
|
|
1656
|
+
() => setPressed(false)
|
|
1657
|
+
);
|
|
1602
1658
|
}
|
|
1603
1659
|
if (gesture.focused || gesture.focusVisible) {
|
|
1604
1660
|
handlers.onFocus = compose(rest.onFocus, () => {
|
|
@@ -1628,6 +1684,9 @@ function useGestureHandlers(gesture, rest, setPressed, setFocused, setFocusVisib
|
|
|
1628
1684
|
rest.onTouchCancel,
|
|
1629
1685
|
rest.onPressIn,
|
|
1630
1686
|
rest.onPressOut,
|
|
1687
|
+
rest.onPointerDown,
|
|
1688
|
+
rest.onPointerUp,
|
|
1689
|
+
rest.onPointerCancel,
|
|
1631
1690
|
rest.onFocus,
|
|
1632
1691
|
rest.onBlur,
|
|
1633
1692
|
rest.onMouseEnter,
|
|
@@ -1642,4 +1701,4 @@ function compose(user, ours) {
|
|
|
1642
1701
|
};
|
|
1643
1702
|
}
|
|
1644
1703
|
|
|
1645
|
-
export { Presence, createMotionComponent, pairBoxShadowLayers, resolveBoxShadowInput, usePresence };
|
|
1704
|
+
export { Presence, TRANSPARENT, createMotionComponent, pairBoxShadowLayers, resolveBoxShadowInput, usePresence };
|