framer-motion 5.4.1 → 5.4.4
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/dist/cjs/index.js +3721 -0
- package/dist/cjs/three-entry.js +362 -0
- package/dist/{framer-motion-three.cjs.js → cjs/use-motion-value-73ed7c77.js} +2961 -1318
- package/dist/es/components/MotionCanvas/index.mjs +61 -7
- package/package.json +8 -6
- package/types/components/MotionCanvas/index.d.ts +3 -2
- package/dist/framer-motion.cjs.js +0 -8340
|
@@ -0,0 +1,3721 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var useMotionValue = require('./use-motion-value-73ed7c77.js');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var styleValueTypes = require('style-value-types');
|
|
9
|
+
var popmotion = require('popmotion');
|
|
10
|
+
var heyListen = require('hey-listen');
|
|
11
|
+
var sync = require('framesync');
|
|
12
|
+
|
|
13
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
|
+
|
|
15
|
+
function _interopNamespace(e) {
|
|
16
|
+
if (e && e.__esModule) return e;
|
|
17
|
+
var n = Object.create(null);
|
|
18
|
+
if (e) {
|
|
19
|
+
Object.keys(e).forEach(function (k) {
|
|
20
|
+
if (k !== 'default') {
|
|
21
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
22
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function () { return e[k]; }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
n["default"] = e;
|
|
30
|
+
return Object.freeze(n);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
34
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
35
|
+
var sync__default = /*#__PURE__*/_interopDefaultLegacy(sync);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Convert any React component into a `motion` component. The provided component
|
|
39
|
+
* **must** use `React.forwardRef` to the underlying DOM component you want to animate.
|
|
40
|
+
*
|
|
41
|
+
* ```jsx
|
|
42
|
+
* const Component = React.forwardRef((props, ref) => {
|
|
43
|
+
* return <div ref={ref} />
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* const MotionComponent = motion(Component)
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
function createMotionProxy(createConfig) {
|
|
52
|
+
function custom(Component, customMotionComponentConfig) {
|
|
53
|
+
if (customMotionComponentConfig === void 0) { customMotionComponentConfig = {}; }
|
|
54
|
+
return useMotionValue.createMotionComponent(createConfig(Component, customMotionComponentConfig));
|
|
55
|
+
}
|
|
56
|
+
if (typeof Proxy === "undefined") {
|
|
57
|
+
return custom;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A cache of generated `motion` components, e.g `motion.div`, `motion.input` etc.
|
|
61
|
+
* Rather than generating them anew every render.
|
|
62
|
+
*/
|
|
63
|
+
var componentCache = new Map();
|
|
64
|
+
return new Proxy(custom, {
|
|
65
|
+
/**
|
|
66
|
+
* Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
|
|
67
|
+
* The prop name is passed through as `key` and we can use that to generate a `motion`
|
|
68
|
+
* DOM component with that name.
|
|
69
|
+
*/
|
|
70
|
+
get: function (_target, key) {
|
|
71
|
+
/**
|
|
72
|
+
* If this element doesn't exist in the component cache, create it and cache.
|
|
73
|
+
*/
|
|
74
|
+
if (!componentCache.has(key)) {
|
|
75
|
+
componentCache.set(key, custom(key));
|
|
76
|
+
}
|
|
77
|
+
return componentCache.get(key);
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* We keep these listed seperately as we use the lowercase tag names as part
|
|
84
|
+
* of the runtime bundle to detect SVG components
|
|
85
|
+
*/
|
|
86
|
+
var lowercaseSVGElements = [
|
|
87
|
+
"animate",
|
|
88
|
+
"circle",
|
|
89
|
+
"defs",
|
|
90
|
+
"desc",
|
|
91
|
+
"ellipse",
|
|
92
|
+
"g",
|
|
93
|
+
"image",
|
|
94
|
+
"line",
|
|
95
|
+
"filter",
|
|
96
|
+
"marker",
|
|
97
|
+
"mask",
|
|
98
|
+
"metadata",
|
|
99
|
+
"path",
|
|
100
|
+
"pattern",
|
|
101
|
+
"polygon",
|
|
102
|
+
"polyline",
|
|
103
|
+
"rect",
|
|
104
|
+
"stop",
|
|
105
|
+
"svg",
|
|
106
|
+
"switch",
|
|
107
|
+
"symbol",
|
|
108
|
+
"text",
|
|
109
|
+
"tspan",
|
|
110
|
+
"use",
|
|
111
|
+
"view",
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
function isSVGComponent(Component) {
|
|
115
|
+
if (
|
|
116
|
+
/**
|
|
117
|
+
* If it's not a string, it's a custom React component. Currently we only support
|
|
118
|
+
* HTML custom React components.
|
|
119
|
+
*/
|
|
120
|
+
typeof Component !== "string" ||
|
|
121
|
+
/**
|
|
122
|
+
* If it contains a dash, the element is a custom HTML webcomponent.
|
|
123
|
+
*/
|
|
124
|
+
Component.includes("-")) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
else if (
|
|
128
|
+
/**
|
|
129
|
+
* If it's in our list of lowercase SVG tags, it's an SVG component
|
|
130
|
+
*/
|
|
131
|
+
lowercaseSVGElements.indexOf(Component) > -1 ||
|
|
132
|
+
/**
|
|
133
|
+
* If it contains a capital letter, it's an SVG component
|
|
134
|
+
*/
|
|
135
|
+
/[A-Z]/.test(Component)) {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function isForcedMotionValue(key, _a) {
|
|
142
|
+
var layout = _a.layout, layoutId = _a.layoutId;
|
|
143
|
+
return (useMotionValue.isTransformProp(key) ||
|
|
144
|
+
useMotionValue.isTransformOriginProp(key) ||
|
|
145
|
+
((layout || layoutId !== undefined) &&
|
|
146
|
+
(!!useMotionValue.scaleCorrectors[key] || key === "opacity")));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
var translateAlias = {
|
|
150
|
+
x: "translateX",
|
|
151
|
+
y: "translateY",
|
|
152
|
+
z: "translateZ",
|
|
153
|
+
transformPerspective: "perspective",
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Build a CSS transform style from individual x/y/scale etc properties.
|
|
157
|
+
*
|
|
158
|
+
* This outputs with a default order of transforms/scales/rotations, this can be customised by
|
|
159
|
+
* providing a transformTemplate function.
|
|
160
|
+
*/
|
|
161
|
+
function buildTransform(_a, _b, transformIsDefault, transformTemplate) {
|
|
162
|
+
var transform = _a.transform, transformKeys = _a.transformKeys;
|
|
163
|
+
var _c = _b.enableHardwareAcceleration, enableHardwareAcceleration = _c === void 0 ? true : _c, _d = _b.allowTransformNone, allowTransformNone = _d === void 0 ? true : _d;
|
|
164
|
+
// The transform string we're going to build into.
|
|
165
|
+
var transformString = "";
|
|
166
|
+
// Transform keys into their default order - this will determine the output order.
|
|
167
|
+
transformKeys.sort(useMotionValue.sortTransformProps);
|
|
168
|
+
// Track whether the defined transform has a defined z so we don't add a
|
|
169
|
+
// second to enable hardware acceleration
|
|
170
|
+
var transformHasZ = false;
|
|
171
|
+
// Loop over each transform and build them into transformString
|
|
172
|
+
var numTransformKeys = transformKeys.length;
|
|
173
|
+
for (var i = 0; i < numTransformKeys; i++) {
|
|
174
|
+
var key = transformKeys[i];
|
|
175
|
+
transformString += "".concat(translateAlias[key] || key, "(").concat(transform[key], ") ");
|
|
176
|
+
if (key === "z")
|
|
177
|
+
transformHasZ = true;
|
|
178
|
+
}
|
|
179
|
+
if (!transformHasZ && enableHardwareAcceleration) {
|
|
180
|
+
transformString += "translateZ(0)";
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
transformString = transformString.trim();
|
|
184
|
+
}
|
|
185
|
+
// If we have a custom `transform` template, pass our transform values and
|
|
186
|
+
// generated transformString to that before returning
|
|
187
|
+
if (transformTemplate) {
|
|
188
|
+
transformString = transformTemplate(transform, transformIsDefault ? "" : transformString);
|
|
189
|
+
}
|
|
190
|
+
else if (allowTransformNone && transformIsDefault) {
|
|
191
|
+
transformString = "none";
|
|
192
|
+
}
|
|
193
|
+
return transformString;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Build a transformOrigin style. Uses the same defaults as the browser for
|
|
197
|
+
* undefined origins.
|
|
198
|
+
*/
|
|
199
|
+
function buildTransformOrigin(_a) {
|
|
200
|
+
var _b = _a.originX, originX = _b === void 0 ? "50%" : _b, _c = _a.originY, originY = _c === void 0 ? "50%" : _c, _d = _a.originZ, originZ = _d === void 0 ? 0 : _d;
|
|
201
|
+
return "".concat(originX, " ").concat(originY, " ").concat(originZ);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Returns true if the provided key is a CSS variable
|
|
206
|
+
*/
|
|
207
|
+
function isCSSVariable$1(key) {
|
|
208
|
+
return key.startsWith("--");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Provided a value and a ValueType, returns the value as that value type.
|
|
213
|
+
*/
|
|
214
|
+
var getValueAsType = function (value, type) {
|
|
215
|
+
return type && typeof value === "number"
|
|
216
|
+
? type.transform(value)
|
|
217
|
+
: value;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
function buildHTMLStyles(state, latestValues, options, transformTemplate) {
|
|
221
|
+
var _a;
|
|
222
|
+
var style = state.style, vars = state.vars, transform = state.transform, transformKeys = state.transformKeys, transformOrigin = state.transformOrigin;
|
|
223
|
+
// Empty the transformKeys array. As we're throwing out refs to its items
|
|
224
|
+
// this might not be as cheap as suspected. Maybe using the array as a buffer
|
|
225
|
+
// with a manual incrementation would be better.
|
|
226
|
+
transformKeys.length = 0;
|
|
227
|
+
// Track whether we encounter any transform or transformOrigin values.
|
|
228
|
+
var hasTransform = false;
|
|
229
|
+
var hasTransformOrigin = false;
|
|
230
|
+
// Does the calculated transform essentially equal "none"?
|
|
231
|
+
var transformIsNone = true;
|
|
232
|
+
/**
|
|
233
|
+
* Loop over all our latest animated values and decide whether to handle them
|
|
234
|
+
* as a style or CSS variable.
|
|
235
|
+
*
|
|
236
|
+
* Transforms and transform origins are kept seperately for further processing.
|
|
237
|
+
*/
|
|
238
|
+
for (var key in latestValues) {
|
|
239
|
+
var value = latestValues[key];
|
|
240
|
+
/**
|
|
241
|
+
* If this is a CSS variable we don't do any further processing.
|
|
242
|
+
*/
|
|
243
|
+
if (isCSSVariable$1(key)) {
|
|
244
|
+
vars[key] = value;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
// Convert the value to its default value type, ie 0 -> "0px"
|
|
248
|
+
var valueType = useMotionValue.numberValueTypes[key];
|
|
249
|
+
var valueAsType = getValueAsType(value, valueType);
|
|
250
|
+
if (useMotionValue.isTransformProp(key)) {
|
|
251
|
+
// If this is a transform, flag to enable further transform processing
|
|
252
|
+
hasTransform = true;
|
|
253
|
+
transform[key] = valueAsType;
|
|
254
|
+
transformKeys.push(key);
|
|
255
|
+
// If we already know we have a non-default transform, early return
|
|
256
|
+
if (!transformIsNone)
|
|
257
|
+
continue;
|
|
258
|
+
// Otherwise check to see if this is a default transform
|
|
259
|
+
if (value !== ((_a = valueType.default) !== null && _a !== void 0 ? _a : 0))
|
|
260
|
+
transformIsNone = false;
|
|
261
|
+
}
|
|
262
|
+
else if (useMotionValue.isTransformOriginProp(key)) {
|
|
263
|
+
transformOrigin[key] = valueAsType;
|
|
264
|
+
// If this is a transform origin, flag and enable further transform-origin processing
|
|
265
|
+
hasTransformOrigin = true;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
style[key] = valueAsType;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (hasTransform) {
|
|
272
|
+
style.transform = buildTransform(state, options, transformIsNone, transformTemplate);
|
|
273
|
+
}
|
|
274
|
+
else if (transformTemplate) {
|
|
275
|
+
style.transform = transformTemplate({}, "");
|
|
276
|
+
}
|
|
277
|
+
if (hasTransformOrigin) {
|
|
278
|
+
style.transformOrigin = buildTransformOrigin(transformOrigin);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
var createHtmlRenderState = function () { return ({
|
|
283
|
+
style: {},
|
|
284
|
+
transform: {},
|
|
285
|
+
transformKeys: [],
|
|
286
|
+
transformOrigin: {},
|
|
287
|
+
vars: {},
|
|
288
|
+
}); };
|
|
289
|
+
|
|
290
|
+
function copyRawValuesOnly(target, source, props) {
|
|
291
|
+
for (var key in source) {
|
|
292
|
+
if (!useMotionValue.isMotionValue(source[key]) && !isForcedMotionValue(key, props)) {
|
|
293
|
+
target[key] = source[key];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function useInitialMotionValues(_a, visualState, isStatic) {
|
|
298
|
+
var transformTemplate = _a.transformTemplate;
|
|
299
|
+
return React.useMemo(function () {
|
|
300
|
+
var state = createHtmlRenderState();
|
|
301
|
+
buildHTMLStyles(state, visualState, { enableHardwareAcceleration: !isStatic }, transformTemplate);
|
|
302
|
+
var vars = state.vars, style = state.style;
|
|
303
|
+
return tslib.__assign(tslib.__assign({}, vars), style);
|
|
304
|
+
}, [visualState]);
|
|
305
|
+
}
|
|
306
|
+
function useStyle(props, visualState, isStatic) {
|
|
307
|
+
var styleProp = props.style || {};
|
|
308
|
+
var style = {};
|
|
309
|
+
/**
|
|
310
|
+
* Copy non-Motion Values straight into style
|
|
311
|
+
*/
|
|
312
|
+
copyRawValuesOnly(style, styleProp, props);
|
|
313
|
+
Object.assign(style, useInitialMotionValues(props, visualState, isStatic));
|
|
314
|
+
if (props.transformValues) {
|
|
315
|
+
style = props.transformValues(style);
|
|
316
|
+
}
|
|
317
|
+
return style;
|
|
318
|
+
}
|
|
319
|
+
function useHTMLProps(props, visualState, isStatic) {
|
|
320
|
+
// The `any` isn't ideal but it is the type of createElement props argument
|
|
321
|
+
var htmlProps = {};
|
|
322
|
+
var style = useStyle(props, visualState, isStatic);
|
|
323
|
+
if (Boolean(props.drag) && props.dragListener !== false) {
|
|
324
|
+
// Disable the ghost element when a user drags
|
|
325
|
+
htmlProps.draggable = false;
|
|
326
|
+
// Disable text selection
|
|
327
|
+
style.userSelect =
|
|
328
|
+
style.WebkitUserSelect =
|
|
329
|
+
style.WebkitTouchCallout =
|
|
330
|
+
"none";
|
|
331
|
+
// Disable scrolling on the draggable direction
|
|
332
|
+
style.touchAction =
|
|
333
|
+
props.drag === true
|
|
334
|
+
? "none"
|
|
335
|
+
: "pan-".concat(props.drag === "x" ? "y" : "x");
|
|
336
|
+
}
|
|
337
|
+
htmlProps.style = style;
|
|
338
|
+
return htmlProps;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function calcOrigin$1(origin, offset, size) {
|
|
342
|
+
return typeof origin === "string"
|
|
343
|
+
? origin
|
|
344
|
+
: styleValueTypes.px.transform(offset + size * origin);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The SVG transform origin defaults are different to CSS and is less intuitive,
|
|
348
|
+
* so we use the measured dimensions of the SVG to reconcile these.
|
|
349
|
+
*/
|
|
350
|
+
function calcSVGTransformOrigin(dimensions, originX, originY) {
|
|
351
|
+
var pxOriginX = calcOrigin$1(originX, dimensions.x, dimensions.width);
|
|
352
|
+
var pxOriginY = calcOrigin$1(originY, dimensions.y, dimensions.height);
|
|
353
|
+
return "".concat(pxOriginX, " ").concat(pxOriginY);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
var dashKeys = {
|
|
357
|
+
offset: "stroke-dashoffset",
|
|
358
|
+
array: "stroke-dasharray",
|
|
359
|
+
};
|
|
360
|
+
var camelKeys = {
|
|
361
|
+
offset: "strokeDashoffset",
|
|
362
|
+
array: "strokeDasharray",
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* Build SVG path properties. Uses the path's measured length to convert
|
|
366
|
+
* our custom pathLength, pathSpacing and pathOffset into stroke-dashoffset
|
|
367
|
+
* and stroke-dasharray attributes.
|
|
368
|
+
*
|
|
369
|
+
* This function is mutative to reduce per-frame GC.
|
|
370
|
+
*/
|
|
371
|
+
function buildSVGPath(attrs, length, spacing, offset, useDashCase) {
|
|
372
|
+
if (spacing === void 0) { spacing = 1; }
|
|
373
|
+
if (offset === void 0) { offset = 0; }
|
|
374
|
+
if (useDashCase === void 0) { useDashCase = true; }
|
|
375
|
+
// Normalise path length by setting SVG attribute pathLength to 1
|
|
376
|
+
attrs.pathLength = 1;
|
|
377
|
+
// We use dash case when setting attributes directly to the DOM node and camel case
|
|
378
|
+
// when defining props on a React component.
|
|
379
|
+
var keys = useDashCase ? dashKeys : camelKeys;
|
|
380
|
+
// Build the dash offset
|
|
381
|
+
attrs[keys.offset] = styleValueTypes.px.transform(-offset);
|
|
382
|
+
// Build the dash array
|
|
383
|
+
var pathLength = styleValueTypes.px.transform(length);
|
|
384
|
+
var pathSpacing = styleValueTypes.px.transform(spacing);
|
|
385
|
+
attrs[keys.array] = "".concat(pathLength, " ").concat(pathSpacing);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Build SVG visual attrbutes, like cx and style.transform
|
|
390
|
+
*/
|
|
391
|
+
function buildSVGAttrs(state, _a, options, transformTemplate) {
|
|
392
|
+
var attrX = _a.attrX, attrY = _a.attrY, originX = _a.originX, originY = _a.originY, pathLength = _a.pathLength, _b = _a.pathSpacing, pathSpacing = _b === void 0 ? 1 : _b, _c = _a.pathOffset, pathOffset = _c === void 0 ? 0 : _c,
|
|
393
|
+
// This is object creation, which we try to avoid per-frame.
|
|
394
|
+
latest = tslib.__rest(_a, ["attrX", "attrY", "originX", "originY", "pathLength", "pathSpacing", "pathOffset"]);
|
|
395
|
+
buildHTMLStyles(state, latest, options, transformTemplate);
|
|
396
|
+
state.attrs = state.style;
|
|
397
|
+
state.style = {};
|
|
398
|
+
var attrs = state.attrs, style = state.style, dimensions = state.dimensions;
|
|
399
|
+
/**
|
|
400
|
+
* However, we apply transforms as CSS transforms. So if we detect a transform we take it from attrs
|
|
401
|
+
* and copy it into style.
|
|
402
|
+
*/
|
|
403
|
+
if (attrs.transform) {
|
|
404
|
+
if (dimensions)
|
|
405
|
+
style.transform = attrs.transform;
|
|
406
|
+
delete attrs.transform;
|
|
407
|
+
}
|
|
408
|
+
// Parse transformOrigin
|
|
409
|
+
if (dimensions &&
|
|
410
|
+
(originX !== undefined || originY !== undefined || style.transform)) {
|
|
411
|
+
style.transformOrigin = calcSVGTransformOrigin(dimensions, originX !== undefined ? originX : 0.5, originY !== undefined ? originY : 0.5);
|
|
412
|
+
}
|
|
413
|
+
// Treat x/y not as shortcuts but as actual attributes
|
|
414
|
+
if (attrX !== undefined)
|
|
415
|
+
attrs.x = attrX;
|
|
416
|
+
if (attrY !== undefined)
|
|
417
|
+
attrs.y = attrY;
|
|
418
|
+
// Build SVG path if one has been defined
|
|
419
|
+
if (pathLength !== undefined) {
|
|
420
|
+
buildSVGPath(attrs, pathLength, pathSpacing, pathOffset, false);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
var createSvgRenderState = function () { return (tslib.__assign(tslib.__assign({}, createHtmlRenderState()), { attrs: {} })); };
|
|
425
|
+
|
|
426
|
+
function useSVGProps(props, visualState) {
|
|
427
|
+
var visualProps = React.useMemo(function () {
|
|
428
|
+
var state = createSvgRenderState();
|
|
429
|
+
buildSVGAttrs(state, visualState, { enableHardwareAcceleration: false }, props.transformTemplate);
|
|
430
|
+
return tslib.__assign(tslib.__assign({}, state.attrs), { style: tslib.__assign({}, state.style) });
|
|
431
|
+
}, [visualState]);
|
|
432
|
+
if (props.style) {
|
|
433
|
+
var rawStyles = {};
|
|
434
|
+
copyRawValuesOnly(rawStyles, props.style, props);
|
|
435
|
+
visualProps.style = tslib.__assign(tslib.__assign({}, rawStyles), visualProps.style);
|
|
436
|
+
}
|
|
437
|
+
return visualProps;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function createUseRender(forwardMotionProps) {
|
|
441
|
+
if (forwardMotionProps === void 0) { forwardMotionProps = false; }
|
|
442
|
+
var useRender = function (Component, props, projectionId, ref, _a, isStatic) {
|
|
443
|
+
var latestValues = _a.latestValues;
|
|
444
|
+
var useVisualProps = isSVGComponent(Component)
|
|
445
|
+
? useSVGProps
|
|
446
|
+
: useHTMLProps;
|
|
447
|
+
var visualProps = useVisualProps(props, latestValues, isStatic);
|
|
448
|
+
var filteredProps = useMotionValue.filterProps(props, typeof Component === "string", forwardMotionProps);
|
|
449
|
+
var elementProps = tslib.__assign(tslib.__assign(tslib.__assign({}, filteredProps), visualProps), { ref: ref });
|
|
450
|
+
if (projectionId) {
|
|
451
|
+
elementProps["data-projection-id"] = projectionId;
|
|
452
|
+
}
|
|
453
|
+
return React.createElement(Component, elementProps);
|
|
454
|
+
};
|
|
455
|
+
return useRender;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
var CAMEL_CASE_PATTERN = /([a-z])([A-Z])/g;
|
|
459
|
+
var REPLACE_TEMPLATE = "$1-$2";
|
|
460
|
+
/**
|
|
461
|
+
* Convert camelCase to dash-case properties.
|
|
462
|
+
*/
|
|
463
|
+
var camelToDash = function (str) {
|
|
464
|
+
return str.replace(CAMEL_CASE_PATTERN, REPLACE_TEMPLATE).toLowerCase();
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
function renderHTML(element, _a, styleProp, projection) {
|
|
468
|
+
var style = _a.style, vars = _a.vars;
|
|
469
|
+
Object.assign(element.style, style, projection && projection.getProjectionStyles(styleProp));
|
|
470
|
+
// Loop over any CSS variables and assign those.
|
|
471
|
+
for (var key in vars) {
|
|
472
|
+
element.style.setProperty(key, vars[key]);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* A set of attribute names that are always read/written as camel case.
|
|
478
|
+
*/
|
|
479
|
+
var camelCaseAttributes = new Set([
|
|
480
|
+
"baseFrequency",
|
|
481
|
+
"diffuseConstant",
|
|
482
|
+
"kernelMatrix",
|
|
483
|
+
"kernelUnitLength",
|
|
484
|
+
"keySplines",
|
|
485
|
+
"keyTimes",
|
|
486
|
+
"limitingConeAngle",
|
|
487
|
+
"markerHeight",
|
|
488
|
+
"markerWidth",
|
|
489
|
+
"numOctaves",
|
|
490
|
+
"targetX",
|
|
491
|
+
"targetY",
|
|
492
|
+
"surfaceScale",
|
|
493
|
+
"specularConstant",
|
|
494
|
+
"specularExponent",
|
|
495
|
+
"stdDeviation",
|
|
496
|
+
"tableValues",
|
|
497
|
+
"viewBox",
|
|
498
|
+
"gradientTransform",
|
|
499
|
+
"pathLength",
|
|
500
|
+
]);
|
|
501
|
+
|
|
502
|
+
function renderSVG(element, renderState) {
|
|
503
|
+
renderHTML(element, renderState);
|
|
504
|
+
for (var key in renderState.attrs) {
|
|
505
|
+
element.setAttribute(!camelCaseAttributes.has(key) ? camelToDash(key) : key, renderState.attrs[key]);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function scrapeMotionValuesFromProps$1(props) {
|
|
510
|
+
var style = props.style;
|
|
511
|
+
var newValues = {};
|
|
512
|
+
for (var key in style) {
|
|
513
|
+
if (useMotionValue.isMotionValue(style[key]) || isForcedMotionValue(key, props)) {
|
|
514
|
+
newValues[key] = style[key];
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return newValues;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function scrapeMotionValuesFromProps(props) {
|
|
521
|
+
var newValues = scrapeMotionValuesFromProps$1(props);
|
|
522
|
+
for (var key in props) {
|
|
523
|
+
if (useMotionValue.isMotionValue(props[key])) {
|
|
524
|
+
var targetKey = key === "x" || key === "y" ? "attr" + key.toUpperCase() : key;
|
|
525
|
+
newValues[targetKey] = props[key];
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return newValues;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
var svgMotionConfig = {
|
|
532
|
+
useVisualState: useMotionValue.makeUseVisualState({
|
|
533
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps,
|
|
534
|
+
createRenderState: createSvgRenderState,
|
|
535
|
+
onMount: function (props, instance, _a) {
|
|
536
|
+
var renderState = _a.renderState, latestValues = _a.latestValues;
|
|
537
|
+
try {
|
|
538
|
+
renderState.dimensions =
|
|
539
|
+
typeof instance.getBBox ===
|
|
540
|
+
"function"
|
|
541
|
+
? instance.getBBox()
|
|
542
|
+
: instance.getBoundingClientRect();
|
|
543
|
+
}
|
|
544
|
+
catch (e) {
|
|
545
|
+
// Most likely trying to measure an unrendered element under Firefox
|
|
546
|
+
renderState.dimensions = {
|
|
547
|
+
x: 0,
|
|
548
|
+
y: 0,
|
|
549
|
+
width: 0,
|
|
550
|
+
height: 0,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
buildSVGAttrs(renderState, latestValues, { enableHardwareAcceleration: false }, props.transformTemplate);
|
|
554
|
+
// TODO: Replace with direct assignment
|
|
555
|
+
renderSVG(instance, renderState);
|
|
556
|
+
},
|
|
557
|
+
}),
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
var htmlMotionConfig = {
|
|
561
|
+
useVisualState: useMotionValue.makeUseVisualState({
|
|
562
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
563
|
+
createRenderState: createHtmlRenderState,
|
|
564
|
+
}),
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
function createDomMotionConfig(Component, _a, preloadedFeatures, createVisualElement, projectionNodeConstructor) {
|
|
568
|
+
var _b = _a.forwardMotionProps, forwardMotionProps = _b === void 0 ? false : _b;
|
|
569
|
+
var baseConfig = isSVGComponent(Component)
|
|
570
|
+
? svgMotionConfig
|
|
571
|
+
: htmlMotionConfig;
|
|
572
|
+
return tslib.__assign(tslib.__assign({}, baseConfig), { preloadedFeatures: preloadedFeatures, useRender: createUseRender(forwardMotionProps), createVisualElement: createVisualElement, projectionNodeConstructor: projectionNodeConstructor, Component: Component });
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
*
|
|
577
|
+
* @param props
|
|
578
|
+
* @param ref
|
|
579
|
+
* @internal
|
|
580
|
+
*/
|
|
581
|
+
function useFocusGesture(_a) {
|
|
582
|
+
var whileFocus = _a.whileFocus, visualElement = _a.visualElement;
|
|
583
|
+
var onFocus = function () {
|
|
584
|
+
var _a;
|
|
585
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Focus, true);
|
|
586
|
+
};
|
|
587
|
+
var onBlur = function () {
|
|
588
|
+
var _a;
|
|
589
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Focus, false);
|
|
590
|
+
};
|
|
591
|
+
useMotionValue.useDomEvent(visualElement, "focus", whileFocus ? onFocus : undefined);
|
|
592
|
+
useMotionValue.useDomEvent(visualElement, "blur", whileFocus ? onBlur : undefined);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function createHoverEvent(visualElement, isActive, callback) {
|
|
596
|
+
return function (event, info) {
|
|
597
|
+
var _a;
|
|
598
|
+
if (!useMotionValue.isMouseEvent(event) || useMotionValue.isDragActive())
|
|
599
|
+
return;
|
|
600
|
+
/**
|
|
601
|
+
* Ensure we trigger animations before firing event callback
|
|
602
|
+
*/
|
|
603
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Hover, isActive);
|
|
604
|
+
callback === null || callback === void 0 ? void 0 : callback(event, info);
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
function useHoverGesture(_a) {
|
|
608
|
+
var onHoverStart = _a.onHoverStart, onHoverEnd = _a.onHoverEnd, whileHover = _a.whileHover, visualElement = _a.visualElement;
|
|
609
|
+
useMotionValue.usePointerEvent(visualElement, "pointerenter", onHoverStart || whileHover
|
|
610
|
+
? createHoverEvent(visualElement, true, onHoverStart)
|
|
611
|
+
: undefined);
|
|
612
|
+
useMotionValue.usePointerEvent(visualElement, "pointerleave", onHoverEnd || whileHover
|
|
613
|
+
? createHoverEvent(visualElement, false, onHoverEnd)
|
|
614
|
+
: undefined);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Recursively traverse up the tree to check whether the provided child node
|
|
619
|
+
* is the parent or a descendant of it.
|
|
620
|
+
*
|
|
621
|
+
* @param parent - Element to find
|
|
622
|
+
* @param child - Element to test against parent
|
|
623
|
+
*/
|
|
624
|
+
var isNodeOrChild = function (parent, child) {
|
|
625
|
+
if (!child) {
|
|
626
|
+
return false;
|
|
627
|
+
}
|
|
628
|
+
else if (parent === child) {
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
return isNodeOrChild(parent, child.parentElement);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
function useUnmountEffect(callback) {
|
|
637
|
+
return React.useEffect(function () { return function () { return callback(); }; }, []);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* @param handlers -
|
|
642
|
+
* @internal
|
|
643
|
+
*/
|
|
644
|
+
function useTapGesture(_a) {
|
|
645
|
+
var onTap = _a.onTap, onTapStart = _a.onTapStart, onTapCancel = _a.onTapCancel, whileTap = _a.whileTap, visualElement = _a.visualElement;
|
|
646
|
+
var hasPressListeners = onTap || onTapStart || onTapCancel || whileTap;
|
|
647
|
+
var isPressing = React.useRef(false);
|
|
648
|
+
var cancelPointerEndListeners = React.useRef(null);
|
|
649
|
+
function removePointerEndListener() {
|
|
650
|
+
var _a;
|
|
651
|
+
(_a = cancelPointerEndListeners.current) === null || _a === void 0 ? void 0 : _a.call(cancelPointerEndListeners);
|
|
652
|
+
cancelPointerEndListeners.current = null;
|
|
653
|
+
}
|
|
654
|
+
function checkPointerEnd() {
|
|
655
|
+
var _a;
|
|
656
|
+
removePointerEndListener();
|
|
657
|
+
isPressing.current = false;
|
|
658
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Tap, false);
|
|
659
|
+
return !useMotionValue.isDragActive();
|
|
660
|
+
}
|
|
661
|
+
function onPointerUp(event, info) {
|
|
662
|
+
if (!checkPointerEnd())
|
|
663
|
+
return;
|
|
664
|
+
/**
|
|
665
|
+
* We only count this as a tap gesture if the event.target is the same
|
|
666
|
+
* as, or a child of, this component's element
|
|
667
|
+
*/
|
|
668
|
+
!isNodeOrChild(visualElement.getInstance(), event.target)
|
|
669
|
+
? onTapCancel === null || onTapCancel === void 0 ? void 0 : onTapCancel(event, info)
|
|
670
|
+
: onTap === null || onTap === void 0 ? void 0 : onTap(event, info);
|
|
671
|
+
}
|
|
672
|
+
function onPointerCancel(event, info) {
|
|
673
|
+
if (!checkPointerEnd())
|
|
674
|
+
return;
|
|
675
|
+
onTapCancel === null || onTapCancel === void 0 ? void 0 : onTapCancel(event, info);
|
|
676
|
+
}
|
|
677
|
+
function onPointerDown(event, info) {
|
|
678
|
+
var _a;
|
|
679
|
+
removePointerEndListener();
|
|
680
|
+
if (isPressing.current)
|
|
681
|
+
return;
|
|
682
|
+
isPressing.current = true;
|
|
683
|
+
cancelPointerEndListeners.current = popmotion.pipe(useMotionValue.addPointerEvent(window, "pointerup", onPointerUp), useMotionValue.addPointerEvent(window, "pointercancel", onPointerCancel));
|
|
684
|
+
/**
|
|
685
|
+
* Ensure we trigger animations before firing event callback
|
|
686
|
+
*/
|
|
687
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Tap, true);
|
|
688
|
+
onTapStart === null || onTapStart === void 0 ? void 0 : onTapStart(event, info);
|
|
689
|
+
}
|
|
690
|
+
useMotionValue.usePointerEvent(visualElement, "pointerdown", hasPressListeners ? onPointerDown : undefined);
|
|
691
|
+
useUnmountEffect(removePointerEndListener);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
var warned = new Set();
|
|
695
|
+
function warnOnce(condition, message, element) {
|
|
696
|
+
if (condition || warned.has(message))
|
|
697
|
+
return;
|
|
698
|
+
console.warn(message);
|
|
699
|
+
if (element)
|
|
700
|
+
console.warn(element);
|
|
701
|
+
warned.add(message);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Map an IntersectionHandler callback to an element. We only ever make one handler for one
|
|
706
|
+
* element, so even though these handlers might all be triggered by different
|
|
707
|
+
* observers, we can keep them in the same map.
|
|
708
|
+
*/
|
|
709
|
+
var observerCallbacks = new WeakMap();
|
|
710
|
+
/**
|
|
711
|
+
* Multiple observers can be created for multiple element/document roots. Each with
|
|
712
|
+
* different settings. So here we store dictionaries of observers to each root,
|
|
713
|
+
* using serialised settings (threshold/margin) as lookup keys.
|
|
714
|
+
*/
|
|
715
|
+
var observers = new WeakMap();
|
|
716
|
+
var fireObserverCallback = function (entry) {
|
|
717
|
+
var _a;
|
|
718
|
+
(_a = observerCallbacks.get(entry.target)) === null || _a === void 0 ? void 0 : _a(entry);
|
|
719
|
+
};
|
|
720
|
+
var fireAllObserverCallbacks = function (entries) {
|
|
721
|
+
entries.forEach(fireObserverCallback);
|
|
722
|
+
};
|
|
723
|
+
function initIntersectionObserver(_a) {
|
|
724
|
+
var root = _a.root, options = tslib.__rest(_a, ["root"]);
|
|
725
|
+
var lookupRoot = root || document;
|
|
726
|
+
/**
|
|
727
|
+
* If we don't have an observer lookup map for this root, create one.
|
|
728
|
+
*/
|
|
729
|
+
if (!observers.has(lookupRoot)) {
|
|
730
|
+
observers.set(lookupRoot, {});
|
|
731
|
+
}
|
|
732
|
+
var rootObservers = observers.get(lookupRoot);
|
|
733
|
+
var key = JSON.stringify(options);
|
|
734
|
+
/**
|
|
735
|
+
* If we don't have an observer for this combination of root and settings,
|
|
736
|
+
* create one.
|
|
737
|
+
*/
|
|
738
|
+
if (!rootObservers[key]) {
|
|
739
|
+
rootObservers[key] = new IntersectionObserver(fireAllObserverCallbacks, tslib.__assign({ root: root }, options));
|
|
740
|
+
}
|
|
741
|
+
return rootObservers[key];
|
|
742
|
+
}
|
|
743
|
+
function observeIntersection(element, options, callback) {
|
|
744
|
+
var rootInteresectionObserver = initIntersectionObserver(options);
|
|
745
|
+
observerCallbacks.set(element, callback);
|
|
746
|
+
rootInteresectionObserver.observe(element);
|
|
747
|
+
return function () {
|
|
748
|
+
observerCallbacks.delete(element);
|
|
749
|
+
rootInteresectionObserver.unobserve(element);
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function useViewport(_a) {
|
|
754
|
+
var visualElement = _a.visualElement, whileInView = _a.whileInView, onViewportEnter = _a.onViewportEnter, onViewportLeave = _a.onViewportLeave, _b = _a.viewport, viewport = _b === void 0 ? {} : _b;
|
|
755
|
+
var state = React.useRef({
|
|
756
|
+
hasEnteredView: false,
|
|
757
|
+
isInView: false,
|
|
758
|
+
});
|
|
759
|
+
var shouldObserve = Boolean(whileInView || onViewportEnter || onViewportLeave);
|
|
760
|
+
if (viewport.once && state.current.hasEnteredView)
|
|
761
|
+
shouldObserve = false;
|
|
762
|
+
var useObserver = typeof IntersectionObserver === "undefined"
|
|
763
|
+
? useMissingIntersectionObserver
|
|
764
|
+
: useIntersectionObserver;
|
|
765
|
+
useObserver(shouldObserve, state.current, visualElement, viewport);
|
|
766
|
+
}
|
|
767
|
+
var thresholdNames = {
|
|
768
|
+
some: 0,
|
|
769
|
+
all: 1,
|
|
770
|
+
};
|
|
771
|
+
function useIntersectionObserver(shouldObserve, state, visualElement, _a) {
|
|
772
|
+
var root = _a.root, rootMargin = _a.margin, _b = _a.amount, amount = _b === void 0 ? "some" : _b, once = _a.once;
|
|
773
|
+
React.useEffect(function () {
|
|
774
|
+
if (!shouldObserve)
|
|
775
|
+
return;
|
|
776
|
+
var options = {
|
|
777
|
+
root: root === null || root === void 0 ? void 0 : root.current,
|
|
778
|
+
rootMargin: rootMargin,
|
|
779
|
+
threshold: typeof amount === "number" ? amount : thresholdNames[amount],
|
|
780
|
+
};
|
|
781
|
+
var intersectionCallback = function (entry) {
|
|
782
|
+
var _a;
|
|
783
|
+
var isIntersecting = entry.isIntersecting;
|
|
784
|
+
/**
|
|
785
|
+
* If there's been no change in the viewport state, early return.
|
|
786
|
+
*/
|
|
787
|
+
if (state.isInView === isIntersecting)
|
|
788
|
+
return;
|
|
789
|
+
state.isInView = isIntersecting;
|
|
790
|
+
/**
|
|
791
|
+
* Handle hasEnteredView. If this is only meant to run once, and
|
|
792
|
+
* element isn't visible, early return. Otherwise set hasEnteredView to true.
|
|
793
|
+
*/
|
|
794
|
+
if (once && !isIntersecting && state.hasEnteredView) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
else if (isIntersecting) {
|
|
798
|
+
state.hasEnteredView = true;
|
|
799
|
+
}
|
|
800
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.InView, isIntersecting);
|
|
801
|
+
/**
|
|
802
|
+
* Use the latest committed props rather than the ones in scope
|
|
803
|
+
* when this observer is created
|
|
804
|
+
*/
|
|
805
|
+
var props = visualElement.getProps();
|
|
806
|
+
var callback = isIntersecting
|
|
807
|
+
? props.onViewportEnter
|
|
808
|
+
: props.onViewportLeave;
|
|
809
|
+
callback === null || callback === void 0 ? void 0 : callback(entry);
|
|
810
|
+
};
|
|
811
|
+
return observeIntersection(visualElement.getInstance(), options, intersectionCallback);
|
|
812
|
+
}, [shouldObserve, root, rootMargin, amount]);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* If IntersectionObserver is missing, we activate inView and fire onViewportEnter
|
|
816
|
+
* on mount. This way, the page will be in the state the author expects users
|
|
817
|
+
* to see it in for everyone.
|
|
818
|
+
*/
|
|
819
|
+
function useMissingIntersectionObserver(shouldObserve, state, visualElement) {
|
|
820
|
+
React.useEffect(function () {
|
|
821
|
+
if (!shouldObserve)
|
|
822
|
+
return;
|
|
823
|
+
if (process.env.NODE_ENV !== "production") {
|
|
824
|
+
warnOnce(false, "IntersectionObserver not available on this device. whileInView animations will trigger on mount.");
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Fire this in an rAF because, at this point, the animation state
|
|
828
|
+
* won't have flushed for the first time and there's certain logic in
|
|
829
|
+
* there that behaves differently on the initial animation.
|
|
830
|
+
*
|
|
831
|
+
* This hook should be quite rarely called so setting this in an rAF
|
|
832
|
+
* is preferred to changing the behaviour of the animation state.
|
|
833
|
+
*/
|
|
834
|
+
requestAnimationFrame(function () {
|
|
835
|
+
var _a;
|
|
836
|
+
state.hasEnteredView = true;
|
|
837
|
+
var onViewportEnter = visualElement.getProps().onViewportEnter;
|
|
838
|
+
onViewportEnter === null || onViewportEnter === void 0 ? void 0 : onViewportEnter(null);
|
|
839
|
+
(_a = visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.InView, true);
|
|
840
|
+
});
|
|
841
|
+
}, [shouldObserve]);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
var gestureAnimations = {
|
|
845
|
+
inView: useMotionValue.makeRenderlessComponent(useViewport),
|
|
846
|
+
tap: useMotionValue.makeRenderlessComponent(useTapGesture),
|
|
847
|
+
focus: useMotionValue.makeRenderlessComponent(useFocusGesture),
|
|
848
|
+
hover: useMotionValue.makeRenderlessComponent(useHoverGesture),
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* @internal
|
|
853
|
+
*/
|
|
854
|
+
var PanSession = /** @class */ (function () {
|
|
855
|
+
function PanSession(event, handlers, _a) {
|
|
856
|
+
var _this = this;
|
|
857
|
+
var _b = _a === void 0 ? {} : _a, transformPagePoint = _b.transformPagePoint;
|
|
858
|
+
/**
|
|
859
|
+
* @internal
|
|
860
|
+
*/
|
|
861
|
+
this.startEvent = null;
|
|
862
|
+
/**
|
|
863
|
+
* @internal
|
|
864
|
+
*/
|
|
865
|
+
this.lastMoveEvent = null;
|
|
866
|
+
/**
|
|
867
|
+
* @internal
|
|
868
|
+
*/
|
|
869
|
+
this.lastMoveEventInfo = null;
|
|
870
|
+
/**
|
|
871
|
+
* @internal
|
|
872
|
+
*/
|
|
873
|
+
this.handlers = {};
|
|
874
|
+
this.updatePoint = function () {
|
|
875
|
+
if (!(_this.lastMoveEvent && _this.lastMoveEventInfo))
|
|
876
|
+
return;
|
|
877
|
+
var info = getPanInfo(_this.lastMoveEventInfo, _this.history);
|
|
878
|
+
var isPanStarted = _this.startEvent !== null;
|
|
879
|
+
// Only start panning if the offset is larger than 3 pixels. If we make it
|
|
880
|
+
// any larger than this we'll want to reset the pointer history
|
|
881
|
+
// on the first update to avoid visual snapping to the cursoe.
|
|
882
|
+
var isDistancePastThreshold = popmotion.distance(info.offset, { x: 0, y: 0 }) >= 3;
|
|
883
|
+
if (!isPanStarted && !isDistancePastThreshold)
|
|
884
|
+
return;
|
|
885
|
+
var point = info.point;
|
|
886
|
+
var timestamp = sync.getFrameData().timestamp;
|
|
887
|
+
_this.history.push(tslib.__assign(tslib.__assign({}, point), { timestamp: timestamp }));
|
|
888
|
+
var _a = _this.handlers, onStart = _a.onStart, onMove = _a.onMove;
|
|
889
|
+
if (!isPanStarted) {
|
|
890
|
+
onStart && onStart(_this.lastMoveEvent, info);
|
|
891
|
+
_this.startEvent = _this.lastMoveEvent;
|
|
892
|
+
}
|
|
893
|
+
onMove && onMove(_this.lastMoveEvent, info);
|
|
894
|
+
};
|
|
895
|
+
this.handlePointerMove = function (event, info) {
|
|
896
|
+
_this.lastMoveEvent = event;
|
|
897
|
+
_this.lastMoveEventInfo = transformPoint(info, _this.transformPagePoint);
|
|
898
|
+
// Because Safari doesn't trigger mouseup events when it's above a `<select>`
|
|
899
|
+
if (useMotionValue.isMouseEvent(event) && event.buttons === 0) {
|
|
900
|
+
_this.handlePointerUp(event, info);
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
// Throttle mouse move event to once per frame
|
|
904
|
+
sync__default["default"].update(_this.updatePoint, true);
|
|
905
|
+
};
|
|
906
|
+
this.handlePointerUp = function (event, info) {
|
|
907
|
+
_this.end();
|
|
908
|
+
var _a = _this.handlers, onEnd = _a.onEnd, onSessionEnd = _a.onSessionEnd;
|
|
909
|
+
var panInfo = getPanInfo(transformPoint(info, _this.transformPagePoint), _this.history);
|
|
910
|
+
if (_this.startEvent && onEnd) {
|
|
911
|
+
onEnd(event, panInfo);
|
|
912
|
+
}
|
|
913
|
+
onSessionEnd && onSessionEnd(event, panInfo);
|
|
914
|
+
};
|
|
915
|
+
// If we have more than one touch, don't start detecting this gesture
|
|
916
|
+
if (useMotionValue.isTouchEvent(event) && event.touches.length > 1)
|
|
917
|
+
return;
|
|
918
|
+
this.handlers = handlers;
|
|
919
|
+
this.transformPagePoint = transformPagePoint;
|
|
920
|
+
var info = useMotionValue.extractEventInfo(event);
|
|
921
|
+
var initialInfo = transformPoint(info, this.transformPagePoint);
|
|
922
|
+
var point = initialInfo.point;
|
|
923
|
+
var timestamp = sync.getFrameData().timestamp;
|
|
924
|
+
this.history = [tslib.__assign(tslib.__assign({}, point), { timestamp: timestamp })];
|
|
925
|
+
var onSessionStart = handlers.onSessionStart;
|
|
926
|
+
onSessionStart &&
|
|
927
|
+
onSessionStart(event, getPanInfo(initialInfo, this.history));
|
|
928
|
+
this.removeListeners = popmotion.pipe(useMotionValue.addPointerEvent(window, "pointermove", this.handlePointerMove), useMotionValue.addPointerEvent(window, "pointerup", this.handlePointerUp), useMotionValue.addPointerEvent(window, "pointercancel", this.handlePointerUp));
|
|
929
|
+
}
|
|
930
|
+
PanSession.prototype.updateHandlers = function (handlers) {
|
|
931
|
+
this.handlers = handlers;
|
|
932
|
+
};
|
|
933
|
+
PanSession.prototype.end = function () {
|
|
934
|
+
this.removeListeners && this.removeListeners();
|
|
935
|
+
sync.cancelSync.update(this.updatePoint);
|
|
936
|
+
};
|
|
937
|
+
return PanSession;
|
|
938
|
+
}());
|
|
939
|
+
function transformPoint(info, transformPagePoint) {
|
|
940
|
+
return transformPagePoint ? { point: transformPagePoint(info.point) } : info;
|
|
941
|
+
}
|
|
942
|
+
function subtractPoint(a, b) {
|
|
943
|
+
return { x: a.x - b.x, y: a.y - b.y };
|
|
944
|
+
}
|
|
945
|
+
function getPanInfo(_a, history) {
|
|
946
|
+
var point = _a.point;
|
|
947
|
+
return {
|
|
948
|
+
point: point,
|
|
949
|
+
delta: subtractPoint(point, lastDevicePoint(history)),
|
|
950
|
+
offset: subtractPoint(point, startDevicePoint(history)),
|
|
951
|
+
velocity: getVelocity(history, 0.1),
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
function startDevicePoint(history) {
|
|
955
|
+
return history[0];
|
|
956
|
+
}
|
|
957
|
+
function lastDevicePoint(history) {
|
|
958
|
+
return history[history.length - 1];
|
|
959
|
+
}
|
|
960
|
+
function getVelocity(history, timeDelta) {
|
|
961
|
+
if (history.length < 2) {
|
|
962
|
+
return { x: 0, y: 0 };
|
|
963
|
+
}
|
|
964
|
+
var i = history.length - 1;
|
|
965
|
+
var timestampedPoint = null;
|
|
966
|
+
var lastPoint = lastDevicePoint(history);
|
|
967
|
+
while (i >= 0) {
|
|
968
|
+
timestampedPoint = history[i];
|
|
969
|
+
if (lastPoint.timestamp - timestampedPoint.timestamp >
|
|
970
|
+
useMotionValue.secondsToMilliseconds(timeDelta)) {
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
i--;
|
|
974
|
+
}
|
|
975
|
+
if (!timestampedPoint) {
|
|
976
|
+
return { x: 0, y: 0 };
|
|
977
|
+
}
|
|
978
|
+
var time = (lastPoint.timestamp - timestampedPoint.timestamp) / 1000;
|
|
979
|
+
if (time === 0) {
|
|
980
|
+
return { x: 0, y: 0 };
|
|
981
|
+
}
|
|
982
|
+
var currentVelocity = {
|
|
983
|
+
x: (lastPoint.x - timestampedPoint.x) / time,
|
|
984
|
+
y: (lastPoint.y - timestampedPoint.y) / time,
|
|
985
|
+
};
|
|
986
|
+
if (currentVelocity.x === Infinity) {
|
|
987
|
+
currentVelocity.x = 0;
|
|
988
|
+
}
|
|
989
|
+
if (currentVelocity.y === Infinity) {
|
|
990
|
+
currentVelocity.y = 0;
|
|
991
|
+
}
|
|
992
|
+
return currentVelocity;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* Apply constraints to a point. These constraints are both physical along an
|
|
997
|
+
* axis, and an elastic factor that determines how much to constrain the point
|
|
998
|
+
* by if it does lie outside the defined parameters.
|
|
999
|
+
*/
|
|
1000
|
+
function applyConstraints(point, _a, elastic) {
|
|
1001
|
+
var min = _a.min, max = _a.max;
|
|
1002
|
+
if (min !== undefined && point < min) {
|
|
1003
|
+
// If we have a min point defined, and this is outside of that, constrain
|
|
1004
|
+
point = elastic ? popmotion.mix(min, point, elastic.min) : Math.max(point, min);
|
|
1005
|
+
}
|
|
1006
|
+
else if (max !== undefined && point > max) {
|
|
1007
|
+
// If we have a max point defined, and this is outside of that, constrain
|
|
1008
|
+
point = elastic ? popmotion.mix(max, point, elastic.max) : Math.min(point, max);
|
|
1009
|
+
}
|
|
1010
|
+
return point;
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Calculate constraints in terms of the viewport when defined relatively to the
|
|
1014
|
+
* measured axis. This is measured from the nearest edge, so a max constraint of 200
|
|
1015
|
+
* on an axis with a max value of 300 would return a constraint of 500 - axis length
|
|
1016
|
+
*/
|
|
1017
|
+
function calcRelativeAxisConstraints(axis, min, max) {
|
|
1018
|
+
return {
|
|
1019
|
+
min: min !== undefined ? axis.min + min : undefined,
|
|
1020
|
+
max: max !== undefined
|
|
1021
|
+
? axis.max + max - (axis.max - axis.min)
|
|
1022
|
+
: undefined,
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Calculate constraints in terms of the viewport when
|
|
1027
|
+
* defined relatively to the measured bounding box.
|
|
1028
|
+
*/
|
|
1029
|
+
function calcRelativeConstraints(layoutBox, _a) {
|
|
1030
|
+
var top = _a.top, left = _a.left, bottom = _a.bottom, right = _a.right;
|
|
1031
|
+
return {
|
|
1032
|
+
x: calcRelativeAxisConstraints(layoutBox.x, left, right),
|
|
1033
|
+
y: calcRelativeAxisConstraints(layoutBox.y, top, bottom),
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Calculate viewport constraints when defined as another viewport-relative axis
|
|
1038
|
+
*/
|
|
1039
|
+
function calcViewportAxisConstraints(layoutAxis, constraintsAxis) {
|
|
1040
|
+
var _a;
|
|
1041
|
+
var min = constraintsAxis.min - layoutAxis.min;
|
|
1042
|
+
var max = constraintsAxis.max - layoutAxis.max;
|
|
1043
|
+
// If the constraints axis is actually smaller than the layout axis then we can
|
|
1044
|
+
// flip the constraints
|
|
1045
|
+
if (constraintsAxis.max - constraintsAxis.min <
|
|
1046
|
+
layoutAxis.max - layoutAxis.min) {
|
|
1047
|
+
_a = tslib.__read([max, min], 2), min = _a[0], max = _a[1];
|
|
1048
|
+
}
|
|
1049
|
+
return { min: min, max: max };
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Calculate viewport constraints when defined as another viewport-relative box
|
|
1053
|
+
*/
|
|
1054
|
+
function calcViewportConstraints(layoutBox, constraintsBox) {
|
|
1055
|
+
return {
|
|
1056
|
+
x: calcViewportAxisConstraints(layoutBox.x, constraintsBox.x),
|
|
1057
|
+
y: calcViewportAxisConstraints(layoutBox.y, constraintsBox.y),
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Calculate a transform origin relative to the source axis, between 0-1, that results
|
|
1062
|
+
* in an asthetically pleasing scale/transform needed to project from source to target.
|
|
1063
|
+
*/
|
|
1064
|
+
function calcOrigin(source, target) {
|
|
1065
|
+
var origin = 0.5;
|
|
1066
|
+
var sourceLength = useMotionValue.calcLength(source);
|
|
1067
|
+
var targetLength = useMotionValue.calcLength(target);
|
|
1068
|
+
if (targetLength > sourceLength) {
|
|
1069
|
+
origin = popmotion.progress(target.min, target.max - sourceLength, source.min);
|
|
1070
|
+
}
|
|
1071
|
+
else if (sourceLength > targetLength) {
|
|
1072
|
+
origin = popmotion.progress(source.min, source.max - targetLength, target.min);
|
|
1073
|
+
}
|
|
1074
|
+
return popmotion.clamp(0, 1, origin);
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Rebase the calculated viewport constraints relative to the layout.min point.
|
|
1078
|
+
*/
|
|
1079
|
+
function rebaseAxisConstraints(layout, constraints) {
|
|
1080
|
+
var relativeConstraints = {};
|
|
1081
|
+
if (constraints.min !== undefined) {
|
|
1082
|
+
relativeConstraints.min = constraints.min - layout.min;
|
|
1083
|
+
}
|
|
1084
|
+
if (constraints.max !== undefined) {
|
|
1085
|
+
relativeConstraints.max = constraints.max - layout.min;
|
|
1086
|
+
}
|
|
1087
|
+
return relativeConstraints;
|
|
1088
|
+
}
|
|
1089
|
+
var defaultElastic = 0.35;
|
|
1090
|
+
/**
|
|
1091
|
+
* Accepts a dragElastic prop and returns resolved elastic values for each axis.
|
|
1092
|
+
*/
|
|
1093
|
+
function resolveDragElastic(dragElastic) {
|
|
1094
|
+
if (dragElastic === void 0) { dragElastic = defaultElastic; }
|
|
1095
|
+
if (dragElastic === false) {
|
|
1096
|
+
dragElastic = 0;
|
|
1097
|
+
}
|
|
1098
|
+
else if (dragElastic === true) {
|
|
1099
|
+
dragElastic = defaultElastic;
|
|
1100
|
+
}
|
|
1101
|
+
return {
|
|
1102
|
+
x: resolveAxisElastic(dragElastic, "left", "right"),
|
|
1103
|
+
y: resolveAxisElastic(dragElastic, "top", "bottom"),
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function resolveAxisElastic(dragElastic, minLabel, maxLabel) {
|
|
1107
|
+
return {
|
|
1108
|
+
min: resolvePointElastic(dragElastic, minLabel),
|
|
1109
|
+
max: resolvePointElastic(dragElastic, maxLabel),
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
function resolvePointElastic(dragElastic, label) {
|
|
1113
|
+
var _a;
|
|
1114
|
+
return typeof dragElastic === "number"
|
|
1115
|
+
? dragElastic
|
|
1116
|
+
: (_a = dragElastic[label]) !== null && _a !== void 0 ? _a : 0;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Bounding boxes tend to be defined as top, left, right, bottom. For various operations
|
|
1121
|
+
* it's easier to consider each axis individually. This function returns a bounding box
|
|
1122
|
+
* as a map of single-axis min/max values.
|
|
1123
|
+
*/
|
|
1124
|
+
function convertBoundingBoxToBox(_a) {
|
|
1125
|
+
var top = _a.top, left = _a.left, right = _a.right, bottom = _a.bottom;
|
|
1126
|
+
return {
|
|
1127
|
+
x: { min: left, max: right },
|
|
1128
|
+
y: { min: top, max: bottom },
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
function convertBoxToBoundingBox(_a) {
|
|
1132
|
+
var x = _a.x, y = _a.y;
|
|
1133
|
+
return { top: y.min, right: x.max, bottom: y.max, left: x.min };
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Applies a TransformPoint function to a bounding box. TransformPoint is usually a function
|
|
1137
|
+
* provided by Framer to allow measured points to be corrected for device scaling. This is used
|
|
1138
|
+
* when measuring DOM elements and DOM event points.
|
|
1139
|
+
*/
|
|
1140
|
+
function transformBoxPoints(point, transformPoint) {
|
|
1141
|
+
if (!transformPoint)
|
|
1142
|
+
return point;
|
|
1143
|
+
var topLeft = transformPoint({ x: point.left, y: point.top });
|
|
1144
|
+
var bottomRight = transformPoint({ x: point.right, y: point.bottom });
|
|
1145
|
+
return {
|
|
1146
|
+
top: topLeft.y,
|
|
1147
|
+
left: topLeft.x,
|
|
1148
|
+
bottom: bottomRight.y,
|
|
1149
|
+
right: bottomRight.x,
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function measureViewportBox(instance, transformPoint) {
|
|
1154
|
+
return convertBoundingBoxToBox(transformBoxPoints(instance.getBoundingClientRect(), transformPoint));
|
|
1155
|
+
}
|
|
1156
|
+
function measurePageBox(element, rootProjectionNode, transformPagePoint) {
|
|
1157
|
+
var viewportBox = measureViewportBox(element, transformPagePoint);
|
|
1158
|
+
var scroll = rootProjectionNode.scroll;
|
|
1159
|
+
if (scroll) {
|
|
1160
|
+
useMotionValue.translateAxis(viewportBox.x, scroll.x);
|
|
1161
|
+
useMotionValue.translateAxis(viewportBox.y, scroll.y);
|
|
1162
|
+
}
|
|
1163
|
+
return viewportBox;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
var elementDragControls = new WeakMap();
|
|
1167
|
+
/**
|
|
1168
|
+
*
|
|
1169
|
+
*/
|
|
1170
|
+
// let latestPointerEvent: AnyPointerEvent
|
|
1171
|
+
var VisualElementDragControls = /** @class */ (function () {
|
|
1172
|
+
function VisualElementDragControls(visualElement) {
|
|
1173
|
+
// This is a reference to the global drag gesture lock, ensuring only one component
|
|
1174
|
+
// can "capture" the drag of one or both axes.
|
|
1175
|
+
// TODO: Look into moving this into pansession?
|
|
1176
|
+
this.openGlobalLock = null;
|
|
1177
|
+
this.isDragging = false;
|
|
1178
|
+
this.currentDirection = null;
|
|
1179
|
+
this.originPoint = { x: 0, y: 0 };
|
|
1180
|
+
/**
|
|
1181
|
+
* The permitted boundaries of travel, in pixels.
|
|
1182
|
+
*/
|
|
1183
|
+
this.constraints = false;
|
|
1184
|
+
this.hasMutatedConstraints = false;
|
|
1185
|
+
/**
|
|
1186
|
+
* The per-axis resolved elastic values.
|
|
1187
|
+
*/
|
|
1188
|
+
this.elastic = useMotionValue.createBox();
|
|
1189
|
+
this.visualElement = visualElement;
|
|
1190
|
+
}
|
|
1191
|
+
VisualElementDragControls.prototype.start = function (originEvent, _a) {
|
|
1192
|
+
var _this = this;
|
|
1193
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.snapToCursor, snapToCursor = _c === void 0 ? false : _c;
|
|
1194
|
+
/**
|
|
1195
|
+
* Don't start dragging if this component is exiting
|
|
1196
|
+
*/
|
|
1197
|
+
if (this.visualElement.isPresent === false)
|
|
1198
|
+
return;
|
|
1199
|
+
var onSessionStart = function (event) {
|
|
1200
|
+
// Stop any animations on both axis values immediately. This allows the user to throw and catch
|
|
1201
|
+
// the component.
|
|
1202
|
+
_this.stopAnimation();
|
|
1203
|
+
if (snapToCursor) {
|
|
1204
|
+
_this.snapToCursor(useMotionValue.extractEventInfo(event, "page").point);
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
var onStart = function (event, info) {
|
|
1208
|
+
var _a;
|
|
1209
|
+
// Attempt to grab the global drag gesture lock - maybe make this part of PanSession
|
|
1210
|
+
var _b = _this.getProps(), drag = _b.drag, dragPropagation = _b.dragPropagation, onDragStart = _b.onDragStart;
|
|
1211
|
+
if (drag && !dragPropagation) {
|
|
1212
|
+
if (_this.openGlobalLock)
|
|
1213
|
+
_this.openGlobalLock();
|
|
1214
|
+
_this.openGlobalLock = useMotionValue.getGlobalLock(drag);
|
|
1215
|
+
// If we don 't have the lock, don't start dragging
|
|
1216
|
+
if (!_this.openGlobalLock)
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
_this.isDragging = true;
|
|
1220
|
+
_this.currentDirection = null;
|
|
1221
|
+
_this.resolveConstraints();
|
|
1222
|
+
if (_this.visualElement.projection) {
|
|
1223
|
+
_this.visualElement.projection.isAnimationBlocked = true;
|
|
1224
|
+
_this.visualElement.projection.target = undefined;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Record gesture origin
|
|
1228
|
+
*/
|
|
1229
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1230
|
+
var _a, _b;
|
|
1231
|
+
var current = _this.getAxisMotionValue(axis).get() || 0;
|
|
1232
|
+
/**
|
|
1233
|
+
* If the MotionValue is a percentage value convert to px
|
|
1234
|
+
*/
|
|
1235
|
+
if (styleValueTypes.percent.test(current)) {
|
|
1236
|
+
var measuredAxis = (_b = (_a = _this.visualElement.projection) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.actual[axis];
|
|
1237
|
+
if (measuredAxis) {
|
|
1238
|
+
var length_1 = useMotionValue.calcLength(measuredAxis);
|
|
1239
|
+
current = length_1 * (parseFloat(current) / 100);
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
_this.originPoint[axis] = current;
|
|
1243
|
+
});
|
|
1244
|
+
// Fire onDragStart event
|
|
1245
|
+
onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(event, info);
|
|
1246
|
+
(_a = _this.visualElement.animationState) === null || _a === void 0 ? void 0 : _a.setActive(useMotionValue.AnimationType.Drag, true);
|
|
1247
|
+
};
|
|
1248
|
+
var onMove = function (event, info) {
|
|
1249
|
+
// latestPointerEvent = event
|
|
1250
|
+
var _a = _this.getProps(), dragPropagation = _a.dragPropagation, dragDirectionLock = _a.dragDirectionLock, onDirectionLock = _a.onDirectionLock, onDrag = _a.onDrag;
|
|
1251
|
+
// If we didn't successfully receive the gesture lock, early return.
|
|
1252
|
+
if (!dragPropagation && !_this.openGlobalLock)
|
|
1253
|
+
return;
|
|
1254
|
+
var offset = info.offset;
|
|
1255
|
+
// Attempt to detect drag direction if directionLock is true
|
|
1256
|
+
if (dragDirectionLock && _this.currentDirection === null) {
|
|
1257
|
+
_this.currentDirection = getCurrentDirection(offset);
|
|
1258
|
+
// If we've successfully set a direction, notify listener
|
|
1259
|
+
if (_this.currentDirection !== null) {
|
|
1260
|
+
onDirectionLock === null || onDirectionLock === void 0 ? void 0 : onDirectionLock(_this.currentDirection);
|
|
1261
|
+
}
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
// Update each point with the latest position
|
|
1265
|
+
_this.updateAxis("x", info.point, offset);
|
|
1266
|
+
_this.updateAxis("y", info.point, offset);
|
|
1267
|
+
/**
|
|
1268
|
+
* Ideally we would leave the renderer to fire naturally at the end of
|
|
1269
|
+
* this frame but if the element is about to change layout as the result
|
|
1270
|
+
* of a re-render we want to ensure the browser can read the latest
|
|
1271
|
+
* bounding box to ensure the pointer and element don't fall out of sync.
|
|
1272
|
+
*/
|
|
1273
|
+
_this.visualElement.syncRender();
|
|
1274
|
+
/**
|
|
1275
|
+
* This must fire after the syncRender call as it might trigger a state
|
|
1276
|
+
* change which itself might trigger a layout update.
|
|
1277
|
+
*/
|
|
1278
|
+
onDrag === null || onDrag === void 0 ? void 0 : onDrag(event, info);
|
|
1279
|
+
};
|
|
1280
|
+
var onSessionEnd = function (event, info) {
|
|
1281
|
+
return _this.stop(event, info);
|
|
1282
|
+
};
|
|
1283
|
+
this.panSession = new PanSession(originEvent, {
|
|
1284
|
+
onSessionStart: onSessionStart,
|
|
1285
|
+
onStart: onStart,
|
|
1286
|
+
onMove: onMove,
|
|
1287
|
+
onSessionEnd: onSessionEnd,
|
|
1288
|
+
}, { transformPagePoint: this.visualElement.getTransformPagePoint() });
|
|
1289
|
+
};
|
|
1290
|
+
VisualElementDragControls.prototype.stop = function (event, info) {
|
|
1291
|
+
var isDragging = this.isDragging;
|
|
1292
|
+
this.cancel();
|
|
1293
|
+
if (!isDragging)
|
|
1294
|
+
return;
|
|
1295
|
+
var velocity = info.velocity;
|
|
1296
|
+
this.startAnimation(velocity);
|
|
1297
|
+
var onDragEnd = this.getProps().onDragEnd;
|
|
1298
|
+
onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd(event, info);
|
|
1299
|
+
};
|
|
1300
|
+
VisualElementDragControls.prototype.cancel = function () {
|
|
1301
|
+
var _a, _b;
|
|
1302
|
+
this.isDragging = false;
|
|
1303
|
+
if (this.visualElement.projection) {
|
|
1304
|
+
this.visualElement.projection.isAnimationBlocked = false;
|
|
1305
|
+
}
|
|
1306
|
+
(_a = this.panSession) === null || _a === void 0 ? void 0 : _a.end();
|
|
1307
|
+
this.panSession = undefined;
|
|
1308
|
+
var dragPropagation = this.getProps().dragPropagation;
|
|
1309
|
+
if (!dragPropagation && this.openGlobalLock) {
|
|
1310
|
+
this.openGlobalLock();
|
|
1311
|
+
this.openGlobalLock = null;
|
|
1312
|
+
}
|
|
1313
|
+
(_b = this.visualElement.animationState) === null || _b === void 0 ? void 0 : _b.setActive(useMotionValue.AnimationType.Drag, false);
|
|
1314
|
+
};
|
|
1315
|
+
VisualElementDragControls.prototype.updateAxis = function (axis, _point, offset) {
|
|
1316
|
+
var drag = this.getProps().drag;
|
|
1317
|
+
// If we're not dragging this axis, do an early return.
|
|
1318
|
+
if (!offset || !shouldDrag(axis, drag, this.currentDirection))
|
|
1319
|
+
return;
|
|
1320
|
+
var axisValue = this.getAxisMotionValue(axis);
|
|
1321
|
+
var next = this.originPoint[axis] + offset[axis];
|
|
1322
|
+
// Apply constraints
|
|
1323
|
+
if (this.constraints && this.constraints[axis]) {
|
|
1324
|
+
next = applyConstraints(next, this.constraints[axis], this.elastic[axis]);
|
|
1325
|
+
}
|
|
1326
|
+
axisValue.set(next);
|
|
1327
|
+
};
|
|
1328
|
+
VisualElementDragControls.prototype.resolveConstraints = function () {
|
|
1329
|
+
var _this = this;
|
|
1330
|
+
var _a = this.getProps(), dragConstraints = _a.dragConstraints, dragElastic = _a.dragElastic;
|
|
1331
|
+
var layout = (this.visualElement.projection || {}).layout;
|
|
1332
|
+
var prevConstraints = this.constraints;
|
|
1333
|
+
if (dragConstraints && useMotionValue.isRefObject(dragConstraints)) {
|
|
1334
|
+
if (!this.constraints) {
|
|
1335
|
+
this.constraints = this.resolveRefConstraints();
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
else {
|
|
1339
|
+
if (dragConstraints && layout) {
|
|
1340
|
+
this.constraints = calcRelativeConstraints(layout.actual, dragConstraints);
|
|
1341
|
+
}
|
|
1342
|
+
else {
|
|
1343
|
+
this.constraints = false;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
this.elastic = resolveDragElastic(dragElastic);
|
|
1347
|
+
/**
|
|
1348
|
+
* If we're outputting to external MotionValues, we want to rebase the measured constraints
|
|
1349
|
+
* from viewport-relative to component-relative.
|
|
1350
|
+
*/
|
|
1351
|
+
if (prevConstraints !== this.constraints &&
|
|
1352
|
+
layout &&
|
|
1353
|
+
this.constraints &&
|
|
1354
|
+
!this.hasMutatedConstraints) {
|
|
1355
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1356
|
+
if (_this.getAxisMotionValue(axis)) {
|
|
1357
|
+
_this.constraints[axis] = rebaseAxisConstraints(layout.actual[axis], _this.constraints[axis]);
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
VisualElementDragControls.prototype.resolveRefConstraints = function () {
|
|
1363
|
+
var _a = this.getProps(), constraints = _a.dragConstraints, onMeasureDragConstraints = _a.onMeasureDragConstraints;
|
|
1364
|
+
if (!constraints || !useMotionValue.isRefObject(constraints))
|
|
1365
|
+
return false;
|
|
1366
|
+
var constraintsElement = constraints.current;
|
|
1367
|
+
heyListen.invariant(constraintsElement !== null, "If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.");
|
|
1368
|
+
var projection = this.visualElement.projection;
|
|
1369
|
+
// TODO
|
|
1370
|
+
if (!projection || !projection.layout)
|
|
1371
|
+
return false;
|
|
1372
|
+
var constraintsBox = measurePageBox(constraintsElement, projection.root, this.visualElement.getTransformPagePoint());
|
|
1373
|
+
var measuredConstraints = calcViewportConstraints(projection.layout.actual, constraintsBox);
|
|
1374
|
+
/**
|
|
1375
|
+
* If there's an onMeasureDragConstraints listener we call it and
|
|
1376
|
+
* if different constraints are returned, set constraints to that
|
|
1377
|
+
*/
|
|
1378
|
+
if (onMeasureDragConstraints) {
|
|
1379
|
+
var userConstraints = onMeasureDragConstraints(convertBoxToBoundingBox(measuredConstraints));
|
|
1380
|
+
this.hasMutatedConstraints = !!userConstraints;
|
|
1381
|
+
if (userConstraints) {
|
|
1382
|
+
measuredConstraints = convertBoundingBoxToBox(userConstraints);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
return measuredConstraints;
|
|
1386
|
+
};
|
|
1387
|
+
VisualElementDragControls.prototype.startAnimation = function (velocity) {
|
|
1388
|
+
var _this = this;
|
|
1389
|
+
var _a = this.getProps(), drag = _a.drag, dragMomentum = _a.dragMomentum, dragElastic = _a.dragElastic, dragTransition = _a.dragTransition, dragSnapToOrigin = _a.dragSnapToOrigin, onDragTransitionEnd = _a.onDragTransitionEnd;
|
|
1390
|
+
var constraints = this.constraints || {};
|
|
1391
|
+
var momentumAnimations = useMotionValue.eachAxis(function (axis) {
|
|
1392
|
+
var _a;
|
|
1393
|
+
if (!shouldDrag(axis, drag, _this.currentDirection)) {
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
var transition = (_a = constraints === null || constraints === void 0 ? void 0 : constraints[axis]) !== null && _a !== void 0 ? _a : {};
|
|
1397
|
+
if (dragSnapToOrigin)
|
|
1398
|
+
transition = { min: 0, max: 0 };
|
|
1399
|
+
/**
|
|
1400
|
+
* Overdamp the boundary spring if `dragElastic` is disabled. There's still a frame
|
|
1401
|
+
* of spring animations so we should look into adding a disable spring option to `inertia`.
|
|
1402
|
+
* We could do something here where we affect the `bounceStiffness` and `bounceDamping`
|
|
1403
|
+
* using the value of `dragElastic`.
|
|
1404
|
+
*/
|
|
1405
|
+
var bounceStiffness = dragElastic ? 200 : 1000000;
|
|
1406
|
+
var bounceDamping = dragElastic ? 40 : 10000000;
|
|
1407
|
+
var inertia = tslib.__assign(tslib.__assign({ type: "inertia", velocity: dragMomentum ? velocity[axis] : 0, bounceStiffness: bounceStiffness, bounceDamping: bounceDamping, timeConstant: 750, restDelta: 1, restSpeed: 10 }, dragTransition), transition);
|
|
1408
|
+
// If we're not animating on an externally-provided `MotionValue` we can use the
|
|
1409
|
+
// component's animation controls which will handle interactions with whileHover (etc),
|
|
1410
|
+
// otherwise we just have to animate the `MotionValue` itself.
|
|
1411
|
+
return _this.startAxisValueAnimation(axis, inertia);
|
|
1412
|
+
});
|
|
1413
|
+
// Run all animations and then resolve the new drag constraints.
|
|
1414
|
+
return Promise.all(momentumAnimations).then(onDragTransitionEnd);
|
|
1415
|
+
};
|
|
1416
|
+
VisualElementDragControls.prototype.startAxisValueAnimation = function (axis, transition) {
|
|
1417
|
+
var axisValue = this.getAxisMotionValue(axis);
|
|
1418
|
+
return useMotionValue.startAnimation(axis, axisValue, 0, transition);
|
|
1419
|
+
};
|
|
1420
|
+
VisualElementDragControls.prototype.stopAnimation = function () {
|
|
1421
|
+
var _this = this;
|
|
1422
|
+
useMotionValue.eachAxis(function (axis) { return _this.getAxisMotionValue(axis).stop(); });
|
|
1423
|
+
};
|
|
1424
|
+
/**
|
|
1425
|
+
* Drag works differently depending on which props are provided.
|
|
1426
|
+
*
|
|
1427
|
+
* - If _dragX and _dragY are provided, we output the gesture delta directly to those motion values.
|
|
1428
|
+
* - Otherwise, we apply the delta to the x/y motion values.
|
|
1429
|
+
*/
|
|
1430
|
+
VisualElementDragControls.prototype.getAxisMotionValue = function (axis) {
|
|
1431
|
+
var _a, _b;
|
|
1432
|
+
var dragKey = "_drag" + axis.toUpperCase();
|
|
1433
|
+
var externalMotionValue = this.visualElement.getProps()[dragKey];
|
|
1434
|
+
return externalMotionValue
|
|
1435
|
+
? externalMotionValue
|
|
1436
|
+
: this.visualElement.getValue(axis, (_b = (_a = this.visualElement.getProps().initial) === null || _a === void 0 ? void 0 : _a[axis]) !== null && _b !== void 0 ? _b : 0);
|
|
1437
|
+
};
|
|
1438
|
+
VisualElementDragControls.prototype.snapToCursor = function (point) {
|
|
1439
|
+
var _this = this;
|
|
1440
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1441
|
+
var drag = _this.getProps().drag;
|
|
1442
|
+
// If we're not dragging this axis, do an early return.
|
|
1443
|
+
if (!shouldDrag(axis, drag, _this.currentDirection))
|
|
1444
|
+
return;
|
|
1445
|
+
var projection = _this.visualElement.projection;
|
|
1446
|
+
var axisValue = _this.getAxisMotionValue(axis);
|
|
1447
|
+
if (projection && projection.layout) {
|
|
1448
|
+
var _a = projection.layout.actual[axis], min = _a.min, max = _a.max;
|
|
1449
|
+
axisValue.set(point[axis] - popmotion.mix(min, max, 0.5));
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
};
|
|
1453
|
+
/**
|
|
1454
|
+
* When the viewport resizes we want to check if the measured constraints
|
|
1455
|
+
* have changed and, if so, reposition the element within those new constraints
|
|
1456
|
+
* relative to where it was before the resize.
|
|
1457
|
+
*/
|
|
1458
|
+
VisualElementDragControls.prototype.scalePositionWithinConstraints = function () {
|
|
1459
|
+
var _this = this;
|
|
1460
|
+
var _a;
|
|
1461
|
+
var _b = this.getProps(), drag = _b.drag, dragConstraints = _b.dragConstraints;
|
|
1462
|
+
var projection = this.visualElement.projection;
|
|
1463
|
+
if (!useMotionValue.isRefObject(dragConstraints) || !projection || !this.constraints)
|
|
1464
|
+
return;
|
|
1465
|
+
/**
|
|
1466
|
+
* Stop current animations as there can be visual glitching if we try to do
|
|
1467
|
+
* this mid-animation
|
|
1468
|
+
*/
|
|
1469
|
+
this.stopAnimation();
|
|
1470
|
+
/**
|
|
1471
|
+
* Record the relative position of the dragged element relative to the
|
|
1472
|
+
* constraints box and save as a progress value.
|
|
1473
|
+
*/
|
|
1474
|
+
var boxProgress = { x: 0, y: 0 };
|
|
1475
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1476
|
+
var axisValue = _this.getAxisMotionValue(axis);
|
|
1477
|
+
if (axisValue) {
|
|
1478
|
+
var latest = axisValue.get();
|
|
1479
|
+
boxProgress[axis] = calcOrigin({ min: latest, max: latest }, _this.constraints[axis]);
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
/**
|
|
1483
|
+
* Update the layout of this element and resolve the latest drag constraints
|
|
1484
|
+
*/
|
|
1485
|
+
var transformTemplate = this.visualElement.getProps().transformTemplate;
|
|
1486
|
+
this.visualElement.getInstance().style.transform = transformTemplate
|
|
1487
|
+
? transformTemplate({}, "")
|
|
1488
|
+
: "none";
|
|
1489
|
+
(_a = projection.root) === null || _a === void 0 ? void 0 : _a.updateScroll();
|
|
1490
|
+
projection.updateLayout();
|
|
1491
|
+
this.resolveConstraints();
|
|
1492
|
+
/**
|
|
1493
|
+
* For each axis, calculate the current progress of the layout axis
|
|
1494
|
+
* within the new constraints.
|
|
1495
|
+
*/
|
|
1496
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1497
|
+
if (!shouldDrag(axis, drag, null))
|
|
1498
|
+
return;
|
|
1499
|
+
/**
|
|
1500
|
+
* Calculate a new transform based on the previous box progress
|
|
1501
|
+
*/
|
|
1502
|
+
var axisValue = _this.getAxisMotionValue(axis);
|
|
1503
|
+
var _a = _this.constraints[axis], min = _a.min, max = _a.max;
|
|
1504
|
+
axisValue.set(popmotion.mix(min, max, boxProgress[axis]));
|
|
1505
|
+
});
|
|
1506
|
+
};
|
|
1507
|
+
VisualElementDragControls.prototype.addListeners = function () {
|
|
1508
|
+
var _this = this;
|
|
1509
|
+
var _a;
|
|
1510
|
+
elementDragControls.set(this.visualElement, this);
|
|
1511
|
+
var element = this.visualElement.getInstance();
|
|
1512
|
+
/**
|
|
1513
|
+
* Attach a pointerdown event listener on this DOM element to initiate drag tracking.
|
|
1514
|
+
*/
|
|
1515
|
+
var stopPointerListener = useMotionValue.addPointerEvent(element, "pointerdown", function (event) {
|
|
1516
|
+
var _a = _this.getProps(), drag = _a.drag, _b = _a.dragListener, dragListener = _b === void 0 ? true : _b;
|
|
1517
|
+
drag && dragListener && _this.start(event);
|
|
1518
|
+
});
|
|
1519
|
+
var measureDragConstraints = function () {
|
|
1520
|
+
var dragConstraints = _this.getProps().dragConstraints;
|
|
1521
|
+
if (useMotionValue.isRefObject(dragConstraints)) {
|
|
1522
|
+
_this.constraints = _this.resolveRefConstraints();
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
var projection = this.visualElement.projection;
|
|
1526
|
+
var stopMeasureLayoutListener = projection.addEventListener("measure", measureDragConstraints);
|
|
1527
|
+
if (projection && !projection.layout) {
|
|
1528
|
+
(_a = projection.root) === null || _a === void 0 ? void 0 : _a.updateScroll();
|
|
1529
|
+
projection.updateLayout();
|
|
1530
|
+
}
|
|
1531
|
+
measureDragConstraints();
|
|
1532
|
+
/**
|
|
1533
|
+
* Attach a window resize listener to scale the draggable target within its defined
|
|
1534
|
+
* constraints as the window resizes.
|
|
1535
|
+
*/
|
|
1536
|
+
var stopResizeListener = useMotionValue.addDomEvent(window, "resize", function () {
|
|
1537
|
+
_this.scalePositionWithinConstraints();
|
|
1538
|
+
});
|
|
1539
|
+
/**
|
|
1540
|
+
* If the element's layout changes, calculate the delta and apply that to
|
|
1541
|
+
* the drag gesture's origin point.
|
|
1542
|
+
*/
|
|
1543
|
+
projection.addEventListener("didUpdate", (function (_a) {
|
|
1544
|
+
var delta = _a.delta, hasLayoutChanged = _a.hasLayoutChanged;
|
|
1545
|
+
if (_this.isDragging && hasLayoutChanged) {
|
|
1546
|
+
useMotionValue.eachAxis(function (axis) {
|
|
1547
|
+
var motionValue = _this.getAxisMotionValue(axis);
|
|
1548
|
+
if (!motionValue)
|
|
1549
|
+
return;
|
|
1550
|
+
_this.originPoint[axis] += delta[axis].translate;
|
|
1551
|
+
motionValue.set(motionValue.get() + delta[axis].translate);
|
|
1552
|
+
});
|
|
1553
|
+
_this.visualElement.syncRender();
|
|
1554
|
+
}
|
|
1555
|
+
}));
|
|
1556
|
+
return function () {
|
|
1557
|
+
stopResizeListener();
|
|
1558
|
+
stopPointerListener();
|
|
1559
|
+
stopMeasureLayoutListener();
|
|
1560
|
+
};
|
|
1561
|
+
};
|
|
1562
|
+
VisualElementDragControls.prototype.getProps = function () {
|
|
1563
|
+
var props = this.visualElement.getProps();
|
|
1564
|
+
var _a = props.drag, drag = _a === void 0 ? false : _a, _b = props.dragDirectionLock, dragDirectionLock = _b === void 0 ? false : _b, _c = props.dragPropagation, dragPropagation = _c === void 0 ? false : _c, _d = props.dragConstraints, dragConstraints = _d === void 0 ? false : _d, _e = props.dragElastic, dragElastic = _e === void 0 ? defaultElastic : _e, _f = props.dragMomentum, dragMomentum = _f === void 0 ? true : _f;
|
|
1565
|
+
return tslib.__assign(tslib.__assign({}, props), { drag: drag, dragDirectionLock: dragDirectionLock, dragPropagation: dragPropagation, dragConstraints: dragConstraints, dragElastic: dragElastic, dragMomentum: dragMomentum });
|
|
1566
|
+
};
|
|
1567
|
+
return VisualElementDragControls;
|
|
1568
|
+
}());
|
|
1569
|
+
function shouldDrag(direction, drag, currentDirection) {
|
|
1570
|
+
return ((drag === true || drag === direction) &&
|
|
1571
|
+
(currentDirection === null || currentDirection === direction));
|
|
1572
|
+
}
|
|
1573
|
+
/**
|
|
1574
|
+
* Based on an x/y offset determine the current drag direction. If both axis' offsets are lower
|
|
1575
|
+
* than the provided threshold, return `null`.
|
|
1576
|
+
*
|
|
1577
|
+
* @param offset - The x/y offset from origin.
|
|
1578
|
+
* @param lockThreshold - (Optional) - the minimum absolute offset before we can determine a drag direction.
|
|
1579
|
+
*/
|
|
1580
|
+
function getCurrentDirection(offset, lockThreshold) {
|
|
1581
|
+
if (lockThreshold === void 0) { lockThreshold = 10; }
|
|
1582
|
+
var direction = null;
|
|
1583
|
+
if (Math.abs(offset.y) > lockThreshold) {
|
|
1584
|
+
direction = "y";
|
|
1585
|
+
}
|
|
1586
|
+
else if (Math.abs(offset.x) > lockThreshold) {
|
|
1587
|
+
direction = "x";
|
|
1588
|
+
}
|
|
1589
|
+
return direction;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* A hook that allows an element to be dragged.
|
|
1594
|
+
*
|
|
1595
|
+
* @internal
|
|
1596
|
+
*/
|
|
1597
|
+
function useDrag(props) {
|
|
1598
|
+
var groupDragControls = props.dragControls, visualElement = props.visualElement;
|
|
1599
|
+
var dragControls = useMotionValue.useConstant(function () { return new VisualElementDragControls(visualElement); });
|
|
1600
|
+
// If we've been provided a DragControls for manual control over the drag gesture,
|
|
1601
|
+
// subscribe this component to it on mount.
|
|
1602
|
+
React.useEffect(function () { return groupDragControls && groupDragControls.subscribe(dragControls); }, [dragControls, groupDragControls]);
|
|
1603
|
+
// Apply the event listeners to the element
|
|
1604
|
+
React.useEffect(function () { return dragControls.addListeners(); }, [dragControls]);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
/**
|
|
1608
|
+
*
|
|
1609
|
+
* @param handlers -
|
|
1610
|
+
* @param ref -
|
|
1611
|
+
*
|
|
1612
|
+
* @internalremarks
|
|
1613
|
+
* Currently this sets new pan gesture functions every render. The memo route has been explored
|
|
1614
|
+
* in the past but ultimately we're still creating new functions every render. An optimisation
|
|
1615
|
+
* to explore is creating the pan gestures and loading them into a `ref`.
|
|
1616
|
+
*
|
|
1617
|
+
* @internal
|
|
1618
|
+
*/
|
|
1619
|
+
function usePanGesture(_a) {
|
|
1620
|
+
var onPan = _a.onPan, onPanStart = _a.onPanStart, onPanEnd = _a.onPanEnd, onPanSessionStart = _a.onPanSessionStart, visualElement = _a.visualElement;
|
|
1621
|
+
var hasPanEvents = onPan || onPanStart || onPanEnd || onPanSessionStart;
|
|
1622
|
+
var panSession = React.useRef(null);
|
|
1623
|
+
var transformPagePoint = React.useContext(useMotionValue.MotionConfigContext).transformPagePoint;
|
|
1624
|
+
var handlers = {
|
|
1625
|
+
onSessionStart: onPanSessionStart,
|
|
1626
|
+
onStart: onPanStart,
|
|
1627
|
+
onMove: onPan,
|
|
1628
|
+
onEnd: function (event, info) {
|
|
1629
|
+
panSession.current = null;
|
|
1630
|
+
onPanEnd && onPanEnd(event, info);
|
|
1631
|
+
},
|
|
1632
|
+
};
|
|
1633
|
+
React.useEffect(function () {
|
|
1634
|
+
if (panSession.current !== null) {
|
|
1635
|
+
panSession.current.updateHandlers(handlers);
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
function onPointerDown(event) {
|
|
1639
|
+
panSession.current = new PanSession(event, handlers, {
|
|
1640
|
+
transformPagePoint: transformPagePoint,
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
useMotionValue.usePointerEvent(visualElement, "pointerdown", hasPanEvents && onPointerDown);
|
|
1644
|
+
useUnmountEffect(function () { return panSession.current && panSession.current.end(); });
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
var drag = {
|
|
1648
|
+
pan: useMotionValue.makeRenderlessComponent(usePanGesture),
|
|
1649
|
+
drag: useMotionValue.makeRenderlessComponent(useDrag),
|
|
1650
|
+
};
|
|
1651
|
+
|
|
1652
|
+
function isCSSVariable(value) {
|
|
1653
|
+
return typeof value === "string" && value.startsWith("var(--");
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Parse Framer's special CSS variable format into a CSS token and a fallback.
|
|
1657
|
+
*
|
|
1658
|
+
* ```
|
|
1659
|
+
* `var(--foo, #fff)` => [`--foo`, '#fff']
|
|
1660
|
+
* ```
|
|
1661
|
+
*
|
|
1662
|
+
* @param current
|
|
1663
|
+
*/
|
|
1664
|
+
var cssVariableRegex = /var\((--[a-zA-Z0-9-_]+),? ?([a-zA-Z0-9 ()%#.,-]+)?\)/;
|
|
1665
|
+
function parseCSSVariable(current) {
|
|
1666
|
+
var match = cssVariableRegex.exec(current);
|
|
1667
|
+
if (!match)
|
|
1668
|
+
return [,];
|
|
1669
|
+
var _a = tslib.__read(match, 3), token = _a[1], fallback = _a[2];
|
|
1670
|
+
return [token, fallback];
|
|
1671
|
+
}
|
|
1672
|
+
var maxDepth = 4;
|
|
1673
|
+
function getVariableValue(current, element, depth) {
|
|
1674
|
+
if (depth === void 0) { depth = 1; }
|
|
1675
|
+
heyListen.invariant(depth <= maxDepth, "Max CSS variable fallback depth detected in property \"".concat(current, "\". This may indicate a circular fallback dependency."));
|
|
1676
|
+
var _a = tslib.__read(parseCSSVariable(current), 2), token = _a[0], fallback = _a[1];
|
|
1677
|
+
// No CSS variable detected
|
|
1678
|
+
if (!token)
|
|
1679
|
+
return;
|
|
1680
|
+
// Attempt to read this CSS variable off the element
|
|
1681
|
+
var resolved = window.getComputedStyle(element).getPropertyValue(token);
|
|
1682
|
+
if (resolved) {
|
|
1683
|
+
return resolved.trim();
|
|
1684
|
+
}
|
|
1685
|
+
else if (isCSSVariable(fallback)) {
|
|
1686
|
+
// The fallback might itself be a CSS variable, in which case we attempt to resolve it too.
|
|
1687
|
+
return getVariableValue(fallback, element, depth + 1);
|
|
1688
|
+
}
|
|
1689
|
+
else {
|
|
1690
|
+
return fallback;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Resolve CSS variables from
|
|
1695
|
+
*
|
|
1696
|
+
* @internal
|
|
1697
|
+
*/
|
|
1698
|
+
function resolveCSSVariables(visualElement, _a, transitionEnd) {
|
|
1699
|
+
var _b;
|
|
1700
|
+
var target = tslib.__rest(_a, []);
|
|
1701
|
+
var element = visualElement.getInstance();
|
|
1702
|
+
if (!(element instanceof Element))
|
|
1703
|
+
return { target: target, transitionEnd: transitionEnd };
|
|
1704
|
+
// If `transitionEnd` isn't `undefined`, clone it. We could clone `target` and `transitionEnd`
|
|
1705
|
+
// only if they change but I think this reads clearer and this isn't a performance-critical path.
|
|
1706
|
+
if (transitionEnd) {
|
|
1707
|
+
transitionEnd = tslib.__assign({}, transitionEnd);
|
|
1708
|
+
}
|
|
1709
|
+
// Go through existing `MotionValue`s and ensure any existing CSS variables are resolved
|
|
1710
|
+
visualElement.forEachValue(function (value) {
|
|
1711
|
+
var current = value.get();
|
|
1712
|
+
if (!isCSSVariable(current))
|
|
1713
|
+
return;
|
|
1714
|
+
var resolved = getVariableValue(current, element);
|
|
1715
|
+
if (resolved)
|
|
1716
|
+
value.set(resolved);
|
|
1717
|
+
});
|
|
1718
|
+
// Cycle through every target property and resolve CSS variables. Currently
|
|
1719
|
+
// we only read single-var properties like `var(--foo)`, not `calc(var(--foo) + 20px)`
|
|
1720
|
+
for (var key in target) {
|
|
1721
|
+
var current = target[key];
|
|
1722
|
+
if (!isCSSVariable(current))
|
|
1723
|
+
continue;
|
|
1724
|
+
var resolved = getVariableValue(current, element);
|
|
1725
|
+
if (!resolved)
|
|
1726
|
+
continue;
|
|
1727
|
+
// Clone target if it hasn't already been
|
|
1728
|
+
target[key] = resolved;
|
|
1729
|
+
// If the user hasn't already set this key on `transitionEnd`, set it to the unresolved
|
|
1730
|
+
// CSS variable. This will ensure that after the animation the component will reflect
|
|
1731
|
+
// changes in the value of the CSS variable.
|
|
1732
|
+
if (transitionEnd)
|
|
1733
|
+
(_b = transitionEnd[key]) !== null && _b !== void 0 ? _b : (transitionEnd[key] = current);
|
|
1734
|
+
}
|
|
1735
|
+
return { target: target, transitionEnd: transitionEnd };
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
var positionalKeys = new Set([
|
|
1739
|
+
"width",
|
|
1740
|
+
"height",
|
|
1741
|
+
"top",
|
|
1742
|
+
"left",
|
|
1743
|
+
"right",
|
|
1744
|
+
"bottom",
|
|
1745
|
+
"x",
|
|
1746
|
+
"y",
|
|
1747
|
+
]);
|
|
1748
|
+
var isPositionalKey = function (key) { return positionalKeys.has(key); };
|
|
1749
|
+
var hasPositionalKey = function (target) {
|
|
1750
|
+
return Object.keys(target).some(isPositionalKey);
|
|
1751
|
+
};
|
|
1752
|
+
var setAndResetVelocity = function (value, to) {
|
|
1753
|
+
// Looks odd but setting it twice doesn't render, it'll just
|
|
1754
|
+
// set both prev and current to the latest value
|
|
1755
|
+
value.set(to, false);
|
|
1756
|
+
value.set(to);
|
|
1757
|
+
};
|
|
1758
|
+
var isNumOrPxType = function (v) {
|
|
1759
|
+
return v === styleValueTypes.number || v === styleValueTypes.px;
|
|
1760
|
+
};
|
|
1761
|
+
var BoundingBoxDimension;
|
|
1762
|
+
(function (BoundingBoxDimension) {
|
|
1763
|
+
BoundingBoxDimension["width"] = "width";
|
|
1764
|
+
BoundingBoxDimension["height"] = "height";
|
|
1765
|
+
BoundingBoxDimension["left"] = "left";
|
|
1766
|
+
BoundingBoxDimension["right"] = "right";
|
|
1767
|
+
BoundingBoxDimension["top"] = "top";
|
|
1768
|
+
BoundingBoxDimension["bottom"] = "bottom";
|
|
1769
|
+
})(BoundingBoxDimension || (BoundingBoxDimension = {}));
|
|
1770
|
+
var getPosFromMatrix = function (matrix, pos) {
|
|
1771
|
+
return parseFloat(matrix.split(", ")[pos]);
|
|
1772
|
+
};
|
|
1773
|
+
var getTranslateFromMatrix = function (pos2, pos3) {
|
|
1774
|
+
return function (_bbox, _a) {
|
|
1775
|
+
var transform = _a.transform;
|
|
1776
|
+
if (transform === "none" || !transform)
|
|
1777
|
+
return 0;
|
|
1778
|
+
var matrix3d = transform.match(/^matrix3d\((.+)\)$/);
|
|
1779
|
+
if (matrix3d) {
|
|
1780
|
+
return getPosFromMatrix(matrix3d[1], pos3);
|
|
1781
|
+
}
|
|
1782
|
+
else {
|
|
1783
|
+
var matrix = transform.match(/^matrix\((.+)\)$/);
|
|
1784
|
+
if (matrix) {
|
|
1785
|
+
return getPosFromMatrix(matrix[1], pos2);
|
|
1786
|
+
}
|
|
1787
|
+
else {
|
|
1788
|
+
return 0;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
};
|
|
1793
|
+
var transformKeys = new Set(["x", "y", "z"]);
|
|
1794
|
+
var nonTranslationalTransformKeys = useMotionValue.transformProps.filter(function (key) { return !transformKeys.has(key); });
|
|
1795
|
+
function removeNonTranslationalTransform(visualElement) {
|
|
1796
|
+
var removedTransforms = [];
|
|
1797
|
+
nonTranslationalTransformKeys.forEach(function (key) {
|
|
1798
|
+
var value = visualElement.getValue(key);
|
|
1799
|
+
if (value !== undefined) {
|
|
1800
|
+
removedTransforms.push([key, value.get()]);
|
|
1801
|
+
value.set(key.startsWith("scale") ? 1 : 0);
|
|
1802
|
+
}
|
|
1803
|
+
});
|
|
1804
|
+
// Apply changes to element before measurement
|
|
1805
|
+
if (removedTransforms.length)
|
|
1806
|
+
visualElement.syncRender();
|
|
1807
|
+
return removedTransforms;
|
|
1808
|
+
}
|
|
1809
|
+
var positionalValues = {
|
|
1810
|
+
// Dimensions
|
|
1811
|
+
width: function (_a, _b) {
|
|
1812
|
+
var x = _a.x;
|
|
1813
|
+
var _c = _b.paddingLeft, paddingLeft = _c === void 0 ? "0" : _c, _d = _b.paddingRight, paddingRight = _d === void 0 ? "0" : _d;
|
|
1814
|
+
return x.max - x.min - parseFloat(paddingLeft) - parseFloat(paddingRight);
|
|
1815
|
+
},
|
|
1816
|
+
height: function (_a, _b) {
|
|
1817
|
+
var y = _a.y;
|
|
1818
|
+
var _c = _b.paddingTop, paddingTop = _c === void 0 ? "0" : _c, _d = _b.paddingBottom, paddingBottom = _d === void 0 ? "0" : _d;
|
|
1819
|
+
return y.max - y.min - parseFloat(paddingTop) - parseFloat(paddingBottom);
|
|
1820
|
+
},
|
|
1821
|
+
top: function (_bbox, _a) {
|
|
1822
|
+
var top = _a.top;
|
|
1823
|
+
return parseFloat(top);
|
|
1824
|
+
},
|
|
1825
|
+
left: function (_bbox, _a) {
|
|
1826
|
+
var left = _a.left;
|
|
1827
|
+
return parseFloat(left);
|
|
1828
|
+
},
|
|
1829
|
+
bottom: function (_a, _b) {
|
|
1830
|
+
var y = _a.y;
|
|
1831
|
+
var top = _b.top;
|
|
1832
|
+
return parseFloat(top) + (y.max - y.min);
|
|
1833
|
+
},
|
|
1834
|
+
right: function (_a, _b) {
|
|
1835
|
+
var x = _a.x;
|
|
1836
|
+
var left = _b.left;
|
|
1837
|
+
return parseFloat(left) + (x.max - x.min);
|
|
1838
|
+
},
|
|
1839
|
+
// Transform
|
|
1840
|
+
x: getTranslateFromMatrix(4, 13),
|
|
1841
|
+
y: getTranslateFromMatrix(5, 14),
|
|
1842
|
+
};
|
|
1843
|
+
var convertChangedValueTypes = function (target, visualElement, changedKeys) {
|
|
1844
|
+
var originBbox = visualElement.measureViewportBox();
|
|
1845
|
+
var element = visualElement.getInstance();
|
|
1846
|
+
var elementComputedStyle = getComputedStyle(element);
|
|
1847
|
+
var display = elementComputedStyle.display;
|
|
1848
|
+
var origin = {};
|
|
1849
|
+
// If the element is currently set to display: "none", make it visible before
|
|
1850
|
+
// measuring the target bounding box
|
|
1851
|
+
if (display === "none") {
|
|
1852
|
+
visualElement.setStaticValue("display", target.display || "block");
|
|
1853
|
+
}
|
|
1854
|
+
/**
|
|
1855
|
+
* Record origins before we render and update styles
|
|
1856
|
+
*/
|
|
1857
|
+
changedKeys.forEach(function (key) {
|
|
1858
|
+
origin[key] = positionalValues[key](originBbox, elementComputedStyle);
|
|
1859
|
+
});
|
|
1860
|
+
// Apply the latest values (as set in checkAndConvertChangedValueTypes)
|
|
1861
|
+
visualElement.syncRender();
|
|
1862
|
+
var targetBbox = visualElement.measureViewportBox();
|
|
1863
|
+
changedKeys.forEach(function (key) {
|
|
1864
|
+
// Restore styles to their **calculated computed style**, not their actual
|
|
1865
|
+
// originally set style. This allows us to animate between equivalent pixel units.
|
|
1866
|
+
var value = visualElement.getValue(key);
|
|
1867
|
+
setAndResetVelocity(value, origin[key]);
|
|
1868
|
+
target[key] = positionalValues[key](targetBbox, elementComputedStyle);
|
|
1869
|
+
});
|
|
1870
|
+
return target;
|
|
1871
|
+
};
|
|
1872
|
+
var checkAndConvertChangedValueTypes = function (visualElement, target, origin, transitionEnd) {
|
|
1873
|
+
if (origin === void 0) { origin = {}; }
|
|
1874
|
+
if (transitionEnd === void 0) { transitionEnd = {}; }
|
|
1875
|
+
target = tslib.__assign({}, target);
|
|
1876
|
+
transitionEnd = tslib.__assign({}, transitionEnd);
|
|
1877
|
+
var targetPositionalKeys = Object.keys(target).filter(isPositionalKey);
|
|
1878
|
+
// We want to remove any transform values that could affect the element's bounding box before
|
|
1879
|
+
// it's measured. We'll reapply these later.
|
|
1880
|
+
var removedTransformValues = [];
|
|
1881
|
+
var hasAttemptedToRemoveTransformValues = false;
|
|
1882
|
+
var changedValueTypeKeys = [];
|
|
1883
|
+
targetPositionalKeys.forEach(function (key) {
|
|
1884
|
+
var value = visualElement.getValue(key);
|
|
1885
|
+
if (!visualElement.hasValue(key))
|
|
1886
|
+
return;
|
|
1887
|
+
var from = origin[key];
|
|
1888
|
+
var fromType = useMotionValue.findDimensionValueType(from);
|
|
1889
|
+
var to = target[key];
|
|
1890
|
+
var toType;
|
|
1891
|
+
// TODO: The current implementation of this basically throws an error
|
|
1892
|
+
// if you try and do value conversion via keyframes. There's probably
|
|
1893
|
+
// a way of doing this but the performance implications would need greater scrutiny,
|
|
1894
|
+
// as it'd be doing multiple resize-remeasure operations.
|
|
1895
|
+
if (useMotionValue.isKeyframesTarget(to)) {
|
|
1896
|
+
var numKeyframes = to.length;
|
|
1897
|
+
var fromIndex = to[0] === null ? 1 : 0;
|
|
1898
|
+
from = to[fromIndex];
|
|
1899
|
+
fromType = useMotionValue.findDimensionValueType(from);
|
|
1900
|
+
for (var i = fromIndex; i < numKeyframes; i++) {
|
|
1901
|
+
if (!toType) {
|
|
1902
|
+
toType = useMotionValue.findDimensionValueType(to[i]);
|
|
1903
|
+
heyListen.invariant(toType === fromType ||
|
|
1904
|
+
(isNumOrPxType(fromType) && isNumOrPxType(toType)), "Keyframes must be of the same dimension as the current value");
|
|
1905
|
+
}
|
|
1906
|
+
else {
|
|
1907
|
+
heyListen.invariant(useMotionValue.findDimensionValueType(to[i]) === toType, "All keyframes must be of the same type");
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
else {
|
|
1912
|
+
toType = useMotionValue.findDimensionValueType(to);
|
|
1913
|
+
}
|
|
1914
|
+
if (fromType !== toType) {
|
|
1915
|
+
// If they're both just number or px, convert them both to numbers rather than
|
|
1916
|
+
// relying on resize/remeasure to convert (which is wasteful in this situation)
|
|
1917
|
+
if (isNumOrPxType(fromType) && isNumOrPxType(toType)) {
|
|
1918
|
+
var current = value.get();
|
|
1919
|
+
if (typeof current === "string") {
|
|
1920
|
+
value.set(parseFloat(current));
|
|
1921
|
+
}
|
|
1922
|
+
if (typeof to === "string") {
|
|
1923
|
+
target[key] = parseFloat(to);
|
|
1924
|
+
}
|
|
1925
|
+
else if (Array.isArray(to) && toType === styleValueTypes.px) {
|
|
1926
|
+
target[key] = to.map(parseFloat);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
else if ((fromType === null || fromType === void 0 ? void 0 : fromType.transform) &&
|
|
1930
|
+
(toType === null || toType === void 0 ? void 0 : toType.transform) &&
|
|
1931
|
+
(from === 0 || to === 0)) {
|
|
1932
|
+
// If one or the other value is 0, it's safe to coerce it to the
|
|
1933
|
+
// type of the other without measurement
|
|
1934
|
+
if (from === 0) {
|
|
1935
|
+
value.set(toType.transform(from));
|
|
1936
|
+
}
|
|
1937
|
+
else {
|
|
1938
|
+
target[key] = fromType.transform(to);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
else {
|
|
1942
|
+
// If we're going to do value conversion via DOM measurements, we first
|
|
1943
|
+
// need to remove non-positional transform values that could affect the bbox measurements.
|
|
1944
|
+
if (!hasAttemptedToRemoveTransformValues) {
|
|
1945
|
+
removedTransformValues =
|
|
1946
|
+
removeNonTranslationalTransform(visualElement);
|
|
1947
|
+
hasAttemptedToRemoveTransformValues = true;
|
|
1948
|
+
}
|
|
1949
|
+
changedValueTypeKeys.push(key);
|
|
1950
|
+
transitionEnd[key] =
|
|
1951
|
+
transitionEnd[key] !== undefined
|
|
1952
|
+
? transitionEnd[key]
|
|
1953
|
+
: target[key];
|
|
1954
|
+
setAndResetVelocity(value, to);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
if (changedValueTypeKeys.length) {
|
|
1959
|
+
var convertedTarget = convertChangedValueTypes(target, visualElement, changedValueTypeKeys);
|
|
1960
|
+
// If we removed transform values, reapply them before the next render
|
|
1961
|
+
if (removedTransformValues.length) {
|
|
1962
|
+
removedTransformValues.forEach(function (_a) {
|
|
1963
|
+
var _b = tslib.__read(_a, 2), key = _b[0], value = _b[1];
|
|
1964
|
+
visualElement.getValue(key).set(value);
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
// Reapply original values
|
|
1968
|
+
visualElement.syncRender();
|
|
1969
|
+
return { target: convertedTarget, transitionEnd: transitionEnd };
|
|
1970
|
+
}
|
|
1971
|
+
else {
|
|
1972
|
+
return { target: target, transitionEnd: transitionEnd };
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
/**
|
|
1976
|
+
* Convert value types for x/y/width/height/top/left/bottom/right
|
|
1977
|
+
*
|
|
1978
|
+
* Allows animation between `'auto'` -> `'100%'` or `0` -> `'calc(50% - 10vw)'`
|
|
1979
|
+
*
|
|
1980
|
+
* @internal
|
|
1981
|
+
*/
|
|
1982
|
+
function unitConversion(visualElement, target, origin, transitionEnd) {
|
|
1983
|
+
return hasPositionalKey(target)
|
|
1984
|
+
? checkAndConvertChangedValueTypes(visualElement, target, origin, transitionEnd)
|
|
1985
|
+
: { target: target, transitionEnd: transitionEnd };
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Parse a DOM variant to make it animatable. This involves resolving CSS variables
|
|
1990
|
+
* and ensuring animations like "20%" => "calc(50vw)" are performed in pixels.
|
|
1991
|
+
*/
|
|
1992
|
+
var parseDomVariant = function (visualElement, target, origin, transitionEnd) {
|
|
1993
|
+
var resolved = resolveCSSVariables(visualElement, target, transitionEnd);
|
|
1994
|
+
target = resolved.target;
|
|
1995
|
+
transitionEnd = resolved.transitionEnd;
|
|
1996
|
+
return unitConversion(visualElement, target, origin, transitionEnd);
|
|
1997
|
+
};
|
|
1998
|
+
|
|
1999
|
+
function getComputedStyle$1(element) {
|
|
2000
|
+
return window.getComputedStyle(element);
|
|
2001
|
+
}
|
|
2002
|
+
var htmlConfig = {
|
|
2003
|
+
treeType: "dom",
|
|
2004
|
+
readValueFromInstance: function (domElement, key) {
|
|
2005
|
+
if (useMotionValue.isTransformProp(key)) {
|
|
2006
|
+
var defaultType = useMotionValue.getDefaultValueType(key);
|
|
2007
|
+
return defaultType ? defaultType.default || 0 : 0;
|
|
2008
|
+
}
|
|
2009
|
+
else {
|
|
2010
|
+
var computedStyle = getComputedStyle$1(domElement);
|
|
2011
|
+
return ((isCSSVariable$1(key)
|
|
2012
|
+
? computedStyle.getPropertyValue(key)
|
|
2013
|
+
: computedStyle[key]) || 0);
|
|
2014
|
+
}
|
|
2015
|
+
},
|
|
2016
|
+
sortNodePosition: function (a, b) {
|
|
2017
|
+
/**
|
|
2018
|
+
* compareDocumentPosition returns a bitmask, by using the bitwise &
|
|
2019
|
+
* we're returning true if 2 in that bitmask is set to true. 2 is set
|
|
2020
|
+
* to true if b preceeds a.
|
|
2021
|
+
*/
|
|
2022
|
+
return a.compareDocumentPosition(b) & 2 ? 1 : -1;
|
|
2023
|
+
},
|
|
2024
|
+
getBaseTarget: function (props, key) {
|
|
2025
|
+
var _a;
|
|
2026
|
+
return (_a = props.style) === null || _a === void 0 ? void 0 : _a[key];
|
|
2027
|
+
},
|
|
2028
|
+
measureViewportBox: function (element, _a) {
|
|
2029
|
+
var transformPagePoint = _a.transformPagePoint;
|
|
2030
|
+
return measureViewportBox(element, transformPagePoint);
|
|
2031
|
+
},
|
|
2032
|
+
/**
|
|
2033
|
+
* Reset the transform on the current Element. This is called as part
|
|
2034
|
+
* of a batched process across the entire layout tree. To remove this write
|
|
2035
|
+
* cycle it'd be interesting to see if it's possible to "undo" all the current
|
|
2036
|
+
* layout transforms up the tree in the same way this.getBoundingBoxWithoutTransforms
|
|
2037
|
+
* works
|
|
2038
|
+
*/
|
|
2039
|
+
resetTransform: function (element, domElement, props) {
|
|
2040
|
+
var transformTemplate = props.transformTemplate;
|
|
2041
|
+
domElement.style.transform = transformTemplate
|
|
2042
|
+
? transformTemplate({}, "")
|
|
2043
|
+
: "none";
|
|
2044
|
+
// Ensure that whatever happens next, we restore our transform on the next frame
|
|
2045
|
+
element.scheduleRender();
|
|
2046
|
+
},
|
|
2047
|
+
restoreTransform: function (instance, mutableState) {
|
|
2048
|
+
instance.style.transform = mutableState.style.transform;
|
|
2049
|
+
},
|
|
2050
|
+
removeValueFromRenderState: function (key, _a) {
|
|
2051
|
+
var vars = _a.vars, style = _a.style;
|
|
2052
|
+
delete vars[key];
|
|
2053
|
+
delete style[key];
|
|
2054
|
+
},
|
|
2055
|
+
/**
|
|
2056
|
+
* Ensure that HTML and Framer-specific value types like `px`->`%` and `Color`
|
|
2057
|
+
* can be animated by Motion.
|
|
2058
|
+
*/
|
|
2059
|
+
makeTargetAnimatable: function (element, _a, _b, isMounted) {
|
|
2060
|
+
var transformValues = _b.transformValues;
|
|
2061
|
+
if (isMounted === void 0) { isMounted = true; }
|
|
2062
|
+
var transition = _a.transition, transitionEnd = _a.transitionEnd, target = tslib.__rest(_a, ["transition", "transitionEnd"]);
|
|
2063
|
+
var origin = useMotionValue.getOrigin(target, transition || {}, element);
|
|
2064
|
+
/**
|
|
2065
|
+
* If Framer has provided a function to convert `Color` etc value types, convert them
|
|
2066
|
+
*/
|
|
2067
|
+
if (transformValues) {
|
|
2068
|
+
if (transitionEnd)
|
|
2069
|
+
transitionEnd = transformValues(transitionEnd);
|
|
2070
|
+
if (target)
|
|
2071
|
+
target = transformValues(target);
|
|
2072
|
+
if (origin)
|
|
2073
|
+
origin = transformValues(origin);
|
|
2074
|
+
}
|
|
2075
|
+
if (isMounted) {
|
|
2076
|
+
useMotionValue.checkTargetForNewValues(element, target, origin);
|
|
2077
|
+
var parsed = parseDomVariant(element, target, origin, transitionEnd);
|
|
2078
|
+
transitionEnd = parsed.transitionEnd;
|
|
2079
|
+
target = parsed.target;
|
|
2080
|
+
}
|
|
2081
|
+
return tslib.__assign({ transition: transition, transitionEnd: transitionEnd }, target);
|
|
2082
|
+
},
|
|
2083
|
+
scrapeMotionValuesFromProps: scrapeMotionValuesFromProps$1,
|
|
2084
|
+
build: function (element, renderState, latestValues, options, props) {
|
|
2085
|
+
if (element.isVisible !== undefined) {
|
|
2086
|
+
renderState.style.visibility = element.isVisible
|
|
2087
|
+
? "visible"
|
|
2088
|
+
: "hidden";
|
|
2089
|
+
}
|
|
2090
|
+
buildHTMLStyles(renderState, latestValues, options, props.transformTemplate);
|
|
2091
|
+
},
|
|
2092
|
+
render: renderHTML,
|
|
2093
|
+
};
|
|
2094
|
+
var htmlVisualElement = useMotionValue.visualElement(htmlConfig);
|
|
2095
|
+
|
|
2096
|
+
var svgVisualElement = useMotionValue.visualElement(tslib.__assign(tslib.__assign({}, htmlConfig), { getBaseTarget: function (props, key) {
|
|
2097
|
+
return props[key];
|
|
2098
|
+
}, readValueFromInstance: function (domElement, key) {
|
|
2099
|
+
var _a;
|
|
2100
|
+
if (useMotionValue.isTransformProp(key)) {
|
|
2101
|
+
return ((_a = useMotionValue.getDefaultValueType(key)) === null || _a === void 0 ? void 0 : _a.default) || 0;
|
|
2102
|
+
}
|
|
2103
|
+
key = !camelCaseAttributes.has(key) ? camelToDash(key) : key;
|
|
2104
|
+
return domElement.getAttribute(key);
|
|
2105
|
+
}, scrapeMotionValuesFromProps: scrapeMotionValuesFromProps, build: function (_element, renderState, latestValues, options, props) {
|
|
2106
|
+
buildSVGAttrs(renderState, latestValues, options, props.transformTemplate);
|
|
2107
|
+
}, render: renderSVG }));
|
|
2108
|
+
|
|
2109
|
+
var createDomVisualElement = function (Component, options) {
|
|
2110
|
+
return isSVGComponent(Component)
|
|
2111
|
+
? svgVisualElement(options, { enableHardwareAcceleration: false })
|
|
2112
|
+
: htmlVisualElement(options, { enableHardwareAcceleration: true });
|
|
2113
|
+
};
|
|
2114
|
+
|
|
2115
|
+
function pixelsToPercent(pixels, axis) {
|
|
2116
|
+
if (axis.max === axis.min)
|
|
2117
|
+
return 0;
|
|
2118
|
+
return (pixels / (axis.max - axis.min)) * 100;
|
|
2119
|
+
}
|
|
2120
|
+
/**
|
|
2121
|
+
* We always correct borderRadius as a percentage rather than pixels to reduce paints.
|
|
2122
|
+
* For example, if you are projecting a box that is 100px wide with a 10px borderRadius
|
|
2123
|
+
* into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
|
|
2124
|
+
* borderRadius in both states. If we animate between the two in pixels that will trigger
|
|
2125
|
+
* a paint each time. If we animate between the two in percentage we'll avoid a paint.
|
|
2126
|
+
*/
|
|
2127
|
+
var correctBorderRadius = {
|
|
2128
|
+
correct: function (latest, node) {
|
|
2129
|
+
if (!node.target)
|
|
2130
|
+
return latest;
|
|
2131
|
+
/**
|
|
2132
|
+
* If latest is a string, if it's a percentage we can return immediately as it's
|
|
2133
|
+
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
2134
|
+
*/
|
|
2135
|
+
if (typeof latest === "string") {
|
|
2136
|
+
if (styleValueTypes.px.test(latest)) {
|
|
2137
|
+
latest = parseFloat(latest);
|
|
2138
|
+
}
|
|
2139
|
+
else {
|
|
2140
|
+
return latest;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
/**
|
|
2144
|
+
* If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
|
|
2145
|
+
* pixel value as a percentage of each axis
|
|
2146
|
+
*/
|
|
2147
|
+
var x = pixelsToPercent(latest, node.target.x);
|
|
2148
|
+
var y = pixelsToPercent(latest, node.target.y);
|
|
2149
|
+
return "".concat(x, "% ").concat(y, "%");
|
|
2150
|
+
},
|
|
2151
|
+
};
|
|
2152
|
+
|
|
2153
|
+
var varToken = "_$css";
|
|
2154
|
+
var correctBoxShadow = {
|
|
2155
|
+
correct: function (latest, _a) {
|
|
2156
|
+
var treeScale = _a.treeScale, projectionDelta = _a.projectionDelta;
|
|
2157
|
+
var original = latest;
|
|
2158
|
+
/**
|
|
2159
|
+
* We need to first strip and store CSS variables from the string.
|
|
2160
|
+
*/
|
|
2161
|
+
var containsCSSVariables = latest.includes("var(");
|
|
2162
|
+
var cssVariables = [];
|
|
2163
|
+
if (containsCSSVariables) {
|
|
2164
|
+
latest = latest.replace(cssVariableRegex, function (match) {
|
|
2165
|
+
cssVariables.push(match);
|
|
2166
|
+
return varToken;
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
var shadow = styleValueTypes.complex.parse(latest);
|
|
2170
|
+
// TODO: Doesn't support multiple shadows
|
|
2171
|
+
if (shadow.length > 5)
|
|
2172
|
+
return original;
|
|
2173
|
+
var template = styleValueTypes.complex.createTransformer(latest);
|
|
2174
|
+
var offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
2175
|
+
// Calculate the overall context scale
|
|
2176
|
+
var xScale = projectionDelta.x.scale * treeScale.x;
|
|
2177
|
+
var yScale = projectionDelta.y.scale * treeScale.y;
|
|
2178
|
+
shadow[0 + offset] /= xScale;
|
|
2179
|
+
shadow[1 + offset] /= yScale;
|
|
2180
|
+
/**
|
|
2181
|
+
* Ideally we'd correct x and y scales individually, but because blur and
|
|
2182
|
+
* spread apply to both we have to take a scale average and apply that instead.
|
|
2183
|
+
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
2184
|
+
* the two scales.
|
|
2185
|
+
*/
|
|
2186
|
+
var averageScale = popmotion.mix(xScale, yScale, 0.5);
|
|
2187
|
+
// Blur
|
|
2188
|
+
if (typeof shadow[2 + offset] === "number")
|
|
2189
|
+
shadow[2 + offset] /= averageScale;
|
|
2190
|
+
// Spread
|
|
2191
|
+
if (typeof shadow[3 + offset] === "number")
|
|
2192
|
+
shadow[3 + offset] /= averageScale;
|
|
2193
|
+
var output = template(shadow);
|
|
2194
|
+
if (containsCSSVariables) {
|
|
2195
|
+
var i_1 = 0;
|
|
2196
|
+
output = output.replace(varToken, function () {
|
|
2197
|
+
var cssVariable = cssVariables[i_1];
|
|
2198
|
+
i_1++;
|
|
2199
|
+
return cssVariable;
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
return output;
|
|
2203
|
+
},
|
|
2204
|
+
};
|
|
2205
|
+
|
|
2206
|
+
var MeasureLayoutWithContext = /** @class */ (function (_super) {
|
|
2207
|
+
tslib.__extends(MeasureLayoutWithContext, _super);
|
|
2208
|
+
function MeasureLayoutWithContext() {
|
|
2209
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* This only mounts projection nodes for components that
|
|
2213
|
+
* need measuring, we might want to do it for all components
|
|
2214
|
+
* in order to incorporate transforms
|
|
2215
|
+
*/
|
|
2216
|
+
MeasureLayoutWithContext.prototype.componentDidMount = function () {
|
|
2217
|
+
var _this = this;
|
|
2218
|
+
var _a = this.props, visualElement = _a.visualElement, layoutGroup = _a.layoutGroup, switchLayoutGroup = _a.switchLayoutGroup, layoutId = _a.layoutId;
|
|
2219
|
+
var projection = visualElement.projection;
|
|
2220
|
+
useMotionValue.addScaleCorrector(defaultScaleCorrectors);
|
|
2221
|
+
if (projection) {
|
|
2222
|
+
if (layoutGroup === null || layoutGroup === void 0 ? void 0 : layoutGroup.group)
|
|
2223
|
+
layoutGroup.group.add(projection);
|
|
2224
|
+
if ((switchLayoutGroup === null || switchLayoutGroup === void 0 ? void 0 : switchLayoutGroup.register) && layoutId) {
|
|
2225
|
+
switchLayoutGroup.register(projection);
|
|
2226
|
+
}
|
|
2227
|
+
projection.root.didUpdate();
|
|
2228
|
+
projection.addEventListener("animationComplete", function () {
|
|
2229
|
+
_this.safeToRemove();
|
|
2230
|
+
});
|
|
2231
|
+
projection.setOptions(tslib.__assign(tslib.__assign({}, projection.options), { onExitComplete: function () { return _this.safeToRemove(); } }));
|
|
2232
|
+
}
|
|
2233
|
+
useMotionValue.globalProjectionState.hasEverUpdated = true;
|
|
2234
|
+
};
|
|
2235
|
+
MeasureLayoutWithContext.prototype.getSnapshotBeforeUpdate = function (prevProps) {
|
|
2236
|
+
var _this = this;
|
|
2237
|
+
var _a = this.props, layoutDependency = _a.layoutDependency, visualElement = _a.visualElement, drag = _a.drag, isPresent = _a.isPresent;
|
|
2238
|
+
var projection = visualElement.projection;
|
|
2239
|
+
if (!projection)
|
|
2240
|
+
return null;
|
|
2241
|
+
/**
|
|
2242
|
+
* TODO: We use this data in relegate to determine whether to
|
|
2243
|
+
* promote a previous element. There's no guarantee its presence data
|
|
2244
|
+
* will have updated by this point - if a bug like this arises it will
|
|
2245
|
+
* have to be that we markForRelegation and then find a new lead some other way,
|
|
2246
|
+
* perhaps in didUpdate
|
|
2247
|
+
*/
|
|
2248
|
+
projection.isPresent = isPresent;
|
|
2249
|
+
if (drag ||
|
|
2250
|
+
prevProps.layoutDependency !== layoutDependency ||
|
|
2251
|
+
layoutDependency === undefined) {
|
|
2252
|
+
projection.willUpdate();
|
|
2253
|
+
}
|
|
2254
|
+
else {
|
|
2255
|
+
this.safeToRemove();
|
|
2256
|
+
}
|
|
2257
|
+
if (prevProps.isPresent !== isPresent) {
|
|
2258
|
+
if (isPresent) {
|
|
2259
|
+
projection.promote();
|
|
2260
|
+
}
|
|
2261
|
+
else if (!projection.relegate()) {
|
|
2262
|
+
/**
|
|
2263
|
+
* If there's another stack member taking over from this one,
|
|
2264
|
+
* it's in charge of the exit animation and therefore should
|
|
2265
|
+
* be in charge of the safe to remove. Otherwise we call it here.
|
|
2266
|
+
*/
|
|
2267
|
+
sync__default["default"].postRender(function () {
|
|
2268
|
+
var _a;
|
|
2269
|
+
if (!((_a = projection.getStack()) === null || _a === void 0 ? void 0 : _a.members.length)) {
|
|
2270
|
+
_this.safeToRemove();
|
|
2271
|
+
}
|
|
2272
|
+
});
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
return null;
|
|
2276
|
+
};
|
|
2277
|
+
MeasureLayoutWithContext.prototype.componentDidUpdate = function () {
|
|
2278
|
+
var projection = this.props.visualElement.projection;
|
|
2279
|
+
if (projection) {
|
|
2280
|
+
projection.root.didUpdate();
|
|
2281
|
+
if (!projection.currentAnimation && projection.isLead()) {
|
|
2282
|
+
this.safeToRemove();
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
2286
|
+
MeasureLayoutWithContext.prototype.componentWillUnmount = function () {
|
|
2287
|
+
var _a = this.props, visualElement = _a.visualElement, layoutGroup = _a.layoutGroup, promoteContext = _a.switchLayoutGroup;
|
|
2288
|
+
var projection = visualElement.projection;
|
|
2289
|
+
if (projection) {
|
|
2290
|
+
projection.scheduleCheckAfterUnmount();
|
|
2291
|
+
if (layoutGroup === null || layoutGroup === void 0 ? void 0 : layoutGroup.group)
|
|
2292
|
+
layoutGroup.group.remove(projection);
|
|
2293
|
+
if (promoteContext === null || promoteContext === void 0 ? void 0 : promoteContext.deregister)
|
|
2294
|
+
promoteContext.deregister(projection);
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
MeasureLayoutWithContext.prototype.safeToRemove = function () {
|
|
2298
|
+
var safeToRemove = this.props.safeToRemove;
|
|
2299
|
+
safeToRemove === null || safeToRemove === void 0 ? void 0 : safeToRemove();
|
|
2300
|
+
};
|
|
2301
|
+
MeasureLayoutWithContext.prototype.render = function () {
|
|
2302
|
+
return null;
|
|
2303
|
+
};
|
|
2304
|
+
return MeasureLayoutWithContext;
|
|
2305
|
+
}(React__default["default"].Component));
|
|
2306
|
+
function MeasureLayout(props) {
|
|
2307
|
+
var _a = tslib.__read(useMotionValue.usePresence(), 2), isPresent = _a[0], safeToRemove = _a[1];
|
|
2308
|
+
var layoutGroup = React.useContext(useMotionValue.LayoutGroupContext);
|
|
2309
|
+
return (React__default["default"].createElement(MeasureLayoutWithContext, tslib.__assign({}, props, { layoutGroup: layoutGroup, switchLayoutGroup: React.useContext(useMotionValue.SwitchLayoutGroupContext), isPresent: isPresent, safeToRemove: safeToRemove })));
|
|
2310
|
+
}
|
|
2311
|
+
var defaultScaleCorrectors = {
|
|
2312
|
+
borderRadius: tslib.__assign(tslib.__assign({}, correctBorderRadius), { applyTo: [
|
|
2313
|
+
"borderTopLeftRadius",
|
|
2314
|
+
"borderTopRightRadius",
|
|
2315
|
+
"borderBottomLeftRadius",
|
|
2316
|
+
"borderBottomRightRadius",
|
|
2317
|
+
] }),
|
|
2318
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
2319
|
+
borderTopRightRadius: correctBorderRadius,
|
|
2320
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
2321
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
2322
|
+
boxShadow: correctBoxShadow,
|
|
2323
|
+
};
|
|
2324
|
+
|
|
2325
|
+
var layoutFeatures = {
|
|
2326
|
+
measureLayout: MeasureLayout,
|
|
2327
|
+
};
|
|
2328
|
+
|
|
2329
|
+
var DocumentProjectionNode = useMotionValue.createProjectionNode({
|
|
2330
|
+
attachResizeListener: function (ref, notify) {
|
|
2331
|
+
ref.addEventListener("resize", notify, { passive: true });
|
|
2332
|
+
return function () { return ref.removeEventListener("resize", notify); };
|
|
2333
|
+
},
|
|
2334
|
+
measureScroll: function () { return ({
|
|
2335
|
+
x: document.documentElement.scrollLeft || document.body.scrollLeft,
|
|
2336
|
+
y: document.documentElement.scrollTop || document.body.scrollTop,
|
|
2337
|
+
}); },
|
|
2338
|
+
});
|
|
2339
|
+
|
|
2340
|
+
var rootProjectionNode = {
|
|
2341
|
+
current: undefined,
|
|
2342
|
+
};
|
|
2343
|
+
var HTMLProjectionNode = useMotionValue.createProjectionNode({
|
|
2344
|
+
measureScroll: function (instance) { return ({
|
|
2345
|
+
x: instance.scrollLeft,
|
|
2346
|
+
y: instance.scrollTop,
|
|
2347
|
+
}); },
|
|
2348
|
+
defaultParent: function () {
|
|
2349
|
+
if (!rootProjectionNode.current) {
|
|
2350
|
+
var documentNode = new DocumentProjectionNode(0, {});
|
|
2351
|
+
documentNode.mount(window);
|
|
2352
|
+
documentNode.setOptions({ layoutScroll: true });
|
|
2353
|
+
rootProjectionNode.current = documentNode;
|
|
2354
|
+
}
|
|
2355
|
+
return rootProjectionNode.current;
|
|
2356
|
+
},
|
|
2357
|
+
resetTransform: function (instance, value) {
|
|
2358
|
+
instance.style.transform = value !== null && value !== void 0 ? value : "none";
|
|
2359
|
+
},
|
|
2360
|
+
});
|
|
2361
|
+
|
|
2362
|
+
var featureBundle = tslib.__assign(tslib.__assign(tslib.__assign(tslib.__assign({}, useMotionValue.animations), gestureAnimations), drag), layoutFeatures);
|
|
2363
|
+
/**
|
|
2364
|
+
* HTML & SVG components, optimised for use with gestures and animation. These can be used as
|
|
2365
|
+
* drop-in replacements for any HTML & SVG component, all CSS & SVG properties are supported.
|
|
2366
|
+
*
|
|
2367
|
+
* @public
|
|
2368
|
+
*/
|
|
2369
|
+
var motion = /*@__PURE__*/ createMotionProxy(function (Component, config) {
|
|
2370
|
+
return createDomMotionConfig(Component, config, featureBundle, createDomVisualElement, HTMLProjectionNode);
|
|
2371
|
+
});
|
|
2372
|
+
/**
|
|
2373
|
+
* Create a DOM `motion` component with the provided string. This is primarily intended
|
|
2374
|
+
* as a full alternative to `motion` for consumers who have to support environments that don't
|
|
2375
|
+
* support `Proxy`.
|
|
2376
|
+
*
|
|
2377
|
+
* ```javascript
|
|
2378
|
+
* import { createDomMotionComponent } from "framer-motion"
|
|
2379
|
+
*
|
|
2380
|
+
* const motion = {
|
|
2381
|
+
* div: createDomMotionComponent('div')
|
|
2382
|
+
* }
|
|
2383
|
+
* ```
|
|
2384
|
+
*
|
|
2385
|
+
* @public
|
|
2386
|
+
*/
|
|
2387
|
+
function createDomMotionComponent(key) {
|
|
2388
|
+
return useMotionValue.createMotionComponent(createDomMotionConfig(key, { forwardMotionProps: false }, featureBundle, createDomVisualElement, HTMLProjectionNode));
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
/**
|
|
2392
|
+
* @public
|
|
2393
|
+
*/
|
|
2394
|
+
var m = createMotionProxy(createDomMotionConfig);
|
|
2395
|
+
|
|
2396
|
+
function useForceUpdate() {
|
|
2397
|
+
var isUnmountingRef = React.useRef(false);
|
|
2398
|
+
var _a = tslib.__read(React.useState(0), 2), forcedRenderCount = _a[0], setForcedRenderCount = _a[1];
|
|
2399
|
+
useUnmountEffect(function () { return (isUnmountingRef.current = true); });
|
|
2400
|
+
var forceRender = React.useCallback(function () {
|
|
2401
|
+
!isUnmountingRef.current && setForcedRenderCount(forcedRenderCount + 1);
|
|
2402
|
+
}, [forcedRenderCount]);
|
|
2403
|
+
/**
|
|
2404
|
+
* Defer this to the end of the next animation frame in case there are multiple
|
|
2405
|
+
* synchronous calls.
|
|
2406
|
+
*/
|
|
2407
|
+
var deferredForceRender = React.useCallback(function () { return sync__default["default"].postRender(forceRender); }, [forceRender]);
|
|
2408
|
+
return [deferredForceRender, forcedRenderCount];
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
var presenceId = 0;
|
|
2412
|
+
function getPresenceId() {
|
|
2413
|
+
var id = presenceId;
|
|
2414
|
+
presenceId++;
|
|
2415
|
+
return id;
|
|
2416
|
+
}
|
|
2417
|
+
var PresenceChild = function (_a) {
|
|
2418
|
+
var children = _a.children, initial = _a.initial, isPresent = _a.isPresent, onExitComplete = _a.onExitComplete, custom = _a.custom, presenceAffectsLayout = _a.presenceAffectsLayout;
|
|
2419
|
+
var presenceChildren = useMotionValue.useConstant(newChildrenMap);
|
|
2420
|
+
var id = useMotionValue.useConstant(getPresenceId);
|
|
2421
|
+
var context = React.useMemo(function () { return ({
|
|
2422
|
+
id: id,
|
|
2423
|
+
initial: initial,
|
|
2424
|
+
isPresent: isPresent,
|
|
2425
|
+
custom: custom,
|
|
2426
|
+
onExitComplete: function (childId) {
|
|
2427
|
+
var e_1, _a;
|
|
2428
|
+
presenceChildren.set(childId, true);
|
|
2429
|
+
try {
|
|
2430
|
+
for (var _b = tslib.__values(presenceChildren.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
2431
|
+
var isComplete = _c.value;
|
|
2432
|
+
if (!isComplete)
|
|
2433
|
+
return; // can stop searching when any is incomplete
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
2437
|
+
finally {
|
|
2438
|
+
try {
|
|
2439
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
2440
|
+
}
|
|
2441
|
+
finally { if (e_1) throw e_1.error; }
|
|
2442
|
+
}
|
|
2443
|
+
onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete();
|
|
2444
|
+
},
|
|
2445
|
+
register: function (childId) {
|
|
2446
|
+
presenceChildren.set(childId, false);
|
|
2447
|
+
return function () { return presenceChildren.delete(childId); };
|
|
2448
|
+
},
|
|
2449
|
+
}); },
|
|
2450
|
+
/**
|
|
2451
|
+
* If the presence of a child affects the layout of the components around it,
|
|
2452
|
+
* we want to make a new context value to ensure they get re-rendered
|
|
2453
|
+
* so they can detect that layout change.
|
|
2454
|
+
*/
|
|
2455
|
+
presenceAffectsLayout ? undefined : [isPresent]);
|
|
2456
|
+
React.useMemo(function () {
|
|
2457
|
+
presenceChildren.forEach(function (_, key) { return presenceChildren.set(key, false); });
|
|
2458
|
+
}, [isPresent]);
|
|
2459
|
+
/**
|
|
2460
|
+
* If there's no `motion` components to fire exit animations, we want to remove this
|
|
2461
|
+
* component immediately.
|
|
2462
|
+
*/
|
|
2463
|
+
React__namespace.useEffect(function () {
|
|
2464
|
+
!isPresent && !presenceChildren.size && (onExitComplete === null || onExitComplete === void 0 ? void 0 : onExitComplete());
|
|
2465
|
+
}, [isPresent]);
|
|
2466
|
+
return (React__namespace.createElement(useMotionValue.PresenceContext.Provider, { value: context }, children));
|
|
2467
|
+
};
|
|
2468
|
+
function newChildrenMap() {
|
|
2469
|
+
return new Map();
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
function getChildKey(child) {
|
|
2473
|
+
return child.key || "";
|
|
2474
|
+
}
|
|
2475
|
+
function updateChildLookup(children, allChildren) {
|
|
2476
|
+
var seenChildren = process.env.NODE_ENV !== "production" ? new Set() : null;
|
|
2477
|
+
children.forEach(function (child) {
|
|
2478
|
+
var key = getChildKey(child);
|
|
2479
|
+
if (process.env.NODE_ENV !== "production" && seenChildren) {
|
|
2480
|
+
if (seenChildren.has(key)) {
|
|
2481
|
+
console.warn("Children of AnimatePresence require unique keys. \"".concat(key, "\" is a duplicate."));
|
|
2482
|
+
}
|
|
2483
|
+
seenChildren.add(key);
|
|
2484
|
+
}
|
|
2485
|
+
allChildren.set(key, child);
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
function onlyElements(children) {
|
|
2489
|
+
var filtered = [];
|
|
2490
|
+
// We use forEach here instead of map as map mutates the component key by preprending `.$`
|
|
2491
|
+
React.Children.forEach(children, function (child) {
|
|
2492
|
+
if (React.isValidElement(child))
|
|
2493
|
+
filtered.push(child);
|
|
2494
|
+
});
|
|
2495
|
+
return filtered;
|
|
2496
|
+
}
|
|
2497
|
+
/**
|
|
2498
|
+
* `AnimatePresence` enables the animation of components that have been removed from the tree.
|
|
2499
|
+
*
|
|
2500
|
+
* When adding/removing more than a single child, every child **must** be given a unique `key` prop.
|
|
2501
|
+
*
|
|
2502
|
+
* Any `motion` components that have an `exit` property defined will animate out when removed from
|
|
2503
|
+
* the tree.
|
|
2504
|
+
*
|
|
2505
|
+
* ```jsx
|
|
2506
|
+
* import { motion, AnimatePresence } from 'framer-motion'
|
|
2507
|
+
*
|
|
2508
|
+
* export const Items = ({ items }) => (
|
|
2509
|
+
* <AnimatePresence>
|
|
2510
|
+
* {items.map(item => (
|
|
2511
|
+
* <motion.div
|
|
2512
|
+
* key={item.id}
|
|
2513
|
+
* initial={{ opacity: 0 }}
|
|
2514
|
+
* animate={{ opacity: 1 }}
|
|
2515
|
+
* exit={{ opacity: 0 }}
|
|
2516
|
+
* />
|
|
2517
|
+
* ))}
|
|
2518
|
+
* </AnimatePresence>
|
|
2519
|
+
* )
|
|
2520
|
+
* ```
|
|
2521
|
+
*
|
|
2522
|
+
* You can sequence exit animations throughout a tree using variants.
|
|
2523
|
+
*
|
|
2524
|
+
* If a child contains multiple `motion` components with `exit` props, it will only unmount the child
|
|
2525
|
+
* once all `motion` components have finished animating out. Likewise, any components using
|
|
2526
|
+
* `usePresence` all need to call `safeToRemove`.
|
|
2527
|
+
*
|
|
2528
|
+
* @public
|
|
2529
|
+
*/
|
|
2530
|
+
var AnimatePresence = function (_a) {
|
|
2531
|
+
var children = _a.children, custom = _a.custom, _b = _a.initial, initial = _b === void 0 ? true : _b, onExitComplete = _a.onExitComplete, exitBeforeEnter = _a.exitBeforeEnter, _c = _a.presenceAffectsLayout, presenceAffectsLayout = _c === void 0 ? true : _c;
|
|
2532
|
+
// We want to force a re-render once all exiting animations have finished. We
|
|
2533
|
+
// either use a local forceRender function, or one from a parent context if it exists.
|
|
2534
|
+
var _d = tslib.__read(useForceUpdate(), 1), forceRender = _d[0];
|
|
2535
|
+
var forceRenderLayoutGroup = React.useContext(useMotionValue.LayoutGroupContext).forceRender;
|
|
2536
|
+
if (forceRenderLayoutGroup)
|
|
2537
|
+
forceRender = forceRenderLayoutGroup;
|
|
2538
|
+
var isInitialRender = React.useRef(true);
|
|
2539
|
+
var isMounted = React.useRef(true);
|
|
2540
|
+
React.useEffect(function () { return function () {
|
|
2541
|
+
isMounted.current = false;
|
|
2542
|
+
}; }, []);
|
|
2543
|
+
// Filter out any children that aren't ReactElements. We can only track ReactElements with a props.key
|
|
2544
|
+
var filteredChildren = onlyElements(children);
|
|
2545
|
+
// Keep a living record of the children we're actually rendering so we
|
|
2546
|
+
// can diff to figure out which are entering and exiting
|
|
2547
|
+
var presentChildren = React.useRef(filteredChildren);
|
|
2548
|
+
// A lookup table to quickly reference components by key
|
|
2549
|
+
var allChildren = React.useRef(new Map()).current;
|
|
2550
|
+
// A living record of all currently exiting components.
|
|
2551
|
+
var exiting = React.useRef(new Set()).current;
|
|
2552
|
+
updateChildLookup(filteredChildren, allChildren);
|
|
2553
|
+
// If this is the initial component render, just deal with logic surrounding whether
|
|
2554
|
+
// we play onMount animations or not.
|
|
2555
|
+
if (isInitialRender.current) {
|
|
2556
|
+
isInitialRender.current = false;
|
|
2557
|
+
return (React__namespace.createElement(React__namespace.Fragment, null, filteredChildren.map(function (child) { return (React__namespace.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, initial: initial ? undefined : false, presenceAffectsLayout: presenceAffectsLayout }, child)); })));
|
|
2558
|
+
}
|
|
2559
|
+
// If this is a subsequent render, deal with entering and exiting children
|
|
2560
|
+
var childrenToRender = tslib.__spreadArray([], tslib.__read(filteredChildren), false);
|
|
2561
|
+
// Diff the keys of the currently-present and target children to update our
|
|
2562
|
+
// exiting list.
|
|
2563
|
+
var presentKeys = presentChildren.current.map(getChildKey);
|
|
2564
|
+
var targetKeys = filteredChildren.map(getChildKey);
|
|
2565
|
+
// Diff the present children with our target children and mark those that are exiting
|
|
2566
|
+
var numPresent = presentKeys.length;
|
|
2567
|
+
for (var i = 0; i < numPresent; i++) {
|
|
2568
|
+
var key = presentKeys[i];
|
|
2569
|
+
if (targetKeys.indexOf(key) === -1) {
|
|
2570
|
+
exiting.add(key);
|
|
2571
|
+
}
|
|
2572
|
+
else {
|
|
2573
|
+
// In case this key has re-entered, remove from the exiting list
|
|
2574
|
+
exiting.delete(key);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
// If we currently have exiting children, and we're deferring rendering incoming children
|
|
2578
|
+
// until after all current children have exiting, empty the childrenToRender array
|
|
2579
|
+
if (exitBeforeEnter && exiting.size) {
|
|
2580
|
+
childrenToRender = [];
|
|
2581
|
+
}
|
|
2582
|
+
// Loop through all currently exiting components and clone them to overwrite `animate`
|
|
2583
|
+
// with any `exit` prop they might have defined.
|
|
2584
|
+
exiting.forEach(function (key) {
|
|
2585
|
+
// If this component is actually entering again, early return
|
|
2586
|
+
if (targetKeys.indexOf(key) !== -1)
|
|
2587
|
+
return;
|
|
2588
|
+
var child = allChildren.get(key);
|
|
2589
|
+
if (!child)
|
|
2590
|
+
return;
|
|
2591
|
+
var insertionIndex = presentKeys.indexOf(key);
|
|
2592
|
+
var onExit = function () {
|
|
2593
|
+
allChildren.delete(key);
|
|
2594
|
+
exiting.delete(key);
|
|
2595
|
+
// Remove this child from the present children
|
|
2596
|
+
var removeIndex = presentChildren.current.findIndex(function (presentChild) { return presentChild.key === key; });
|
|
2597
|
+
presentChildren.current.splice(removeIndex, 1);
|
|
2598
|
+
// Defer re-rendering until all exiting children have indeed left
|
|
2599
|
+
if (!exiting.size) {
|
|
2600
|
+
presentChildren.current = filteredChildren;
|
|
2601
|
+
if (isMounted.current === false) {
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
forceRender();
|
|
2605
|
+
onExitComplete && onExitComplete();
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
childrenToRender.splice(insertionIndex, 0, React__namespace.createElement(PresenceChild, { key: getChildKey(child), isPresent: false, onExitComplete: onExit, custom: custom, presenceAffectsLayout: presenceAffectsLayout }, child));
|
|
2609
|
+
});
|
|
2610
|
+
// Add `MotionContext` even to children that don't need it to ensure we're rendering
|
|
2611
|
+
// the same tree between renders
|
|
2612
|
+
childrenToRender = childrenToRender.map(function (child) {
|
|
2613
|
+
var key = child.key;
|
|
2614
|
+
return exiting.has(key) ? (child) : (React__namespace.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, presenceAffectsLayout: presenceAffectsLayout }, child));
|
|
2615
|
+
});
|
|
2616
|
+
presentChildren.current = childrenToRender;
|
|
2617
|
+
if (process.env.NODE_ENV !== "production" &&
|
|
2618
|
+
exitBeforeEnter &&
|
|
2619
|
+
childrenToRender.length > 1) {
|
|
2620
|
+
console.warn("You're attempting to animate multiple children within AnimatePresence, but its exitBeforeEnter prop is set to true. This will lead to odd visual behaviour.");
|
|
2621
|
+
}
|
|
2622
|
+
return (React__namespace.createElement(React__namespace.Fragment, null, exiting.size
|
|
2623
|
+
? childrenToRender
|
|
2624
|
+
: childrenToRender.map(function (child) { return React.cloneElement(child); })));
|
|
2625
|
+
};
|
|
2626
|
+
|
|
2627
|
+
/**
|
|
2628
|
+
* @internal
|
|
2629
|
+
* @deprecated
|
|
2630
|
+
*/
|
|
2631
|
+
var DeprecatedLayoutGroupContext = React.createContext(null);
|
|
2632
|
+
|
|
2633
|
+
var notify = function (node) {
|
|
2634
|
+
return !node.isLayoutDirty && node.willUpdate(false);
|
|
2635
|
+
};
|
|
2636
|
+
function nodeGroup() {
|
|
2637
|
+
var nodes = new Set();
|
|
2638
|
+
var subscriptions = new WeakMap();
|
|
2639
|
+
var dirtyAll = function () { return nodes.forEach(notify); };
|
|
2640
|
+
return {
|
|
2641
|
+
add: function (node) {
|
|
2642
|
+
nodes.add(node);
|
|
2643
|
+
subscriptions.set(node, node.addEventListener("willUpdate", dirtyAll));
|
|
2644
|
+
},
|
|
2645
|
+
remove: function (node) {
|
|
2646
|
+
var _a;
|
|
2647
|
+
nodes.delete(node);
|
|
2648
|
+
(_a = subscriptions.get(node)) === null || _a === void 0 ? void 0 : _a();
|
|
2649
|
+
subscriptions.delete(node);
|
|
2650
|
+
dirtyAll();
|
|
2651
|
+
},
|
|
2652
|
+
dirty: dirtyAll,
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
var LayoutGroup = function (_a) {
|
|
2657
|
+
var _b, _c;
|
|
2658
|
+
var children = _a.children, id = _a.id, _d = _a.inheritId, inheritId = _d === void 0 ? true : _d;
|
|
2659
|
+
var layoutGroupContext = React.useContext(useMotionValue.LayoutGroupContext);
|
|
2660
|
+
var deprecatedLayoutGroupContext = React.useContext(DeprecatedLayoutGroupContext);
|
|
2661
|
+
var _e = tslib.__read(useForceUpdate(), 2), forceRender = _e[0], key = _e[1];
|
|
2662
|
+
var context = React.useRef(null);
|
|
2663
|
+
var upstreamId = (_b = layoutGroupContext.id) !== null && _b !== void 0 ? _b : deprecatedLayoutGroupContext;
|
|
2664
|
+
if (context.current === null) {
|
|
2665
|
+
if (inheritId && upstreamId) {
|
|
2666
|
+
id = id ? upstreamId + "-" + id : upstreamId;
|
|
2667
|
+
}
|
|
2668
|
+
context.current = {
|
|
2669
|
+
id: id,
|
|
2670
|
+
group: inheritId
|
|
2671
|
+
? (_c = layoutGroupContext === null || layoutGroupContext === void 0 ? void 0 : layoutGroupContext.group) !== null && _c !== void 0 ? _c : nodeGroup()
|
|
2672
|
+
: nodeGroup(),
|
|
2673
|
+
};
|
|
2674
|
+
}
|
|
2675
|
+
var memoizedContext = React.useMemo(function () { return (tslib.__assign(tslib.__assign({}, context.current), { forceRender: forceRender })); }, [key]);
|
|
2676
|
+
return (React__namespace.createElement(useMotionValue.LayoutGroupContext.Provider, { value: memoizedContext }, children));
|
|
2677
|
+
};
|
|
2678
|
+
|
|
2679
|
+
var id = 0;
|
|
2680
|
+
var AnimateSharedLayout = function (_a) {
|
|
2681
|
+
var children = _a.children;
|
|
2682
|
+
return (React__namespace.createElement(LayoutGroup, { id: useMotionValue.useConstant(function () { return "asl-".concat(id++); }) }, children));
|
|
2683
|
+
};
|
|
2684
|
+
|
|
2685
|
+
/**
|
|
2686
|
+
* `MotionConfig` is used to set configuration options for all children `motion` components.
|
|
2687
|
+
*
|
|
2688
|
+
* ```jsx
|
|
2689
|
+
* import { motion, MotionConfig } from "framer-motion"
|
|
2690
|
+
*
|
|
2691
|
+
* export function App() {
|
|
2692
|
+
* return (
|
|
2693
|
+
* <MotionConfig transition={{ type: "spring" }}>
|
|
2694
|
+
* <motion.div animate={{ x: 100 }} />
|
|
2695
|
+
* </MotionConfig>
|
|
2696
|
+
* )
|
|
2697
|
+
* }
|
|
2698
|
+
* ```
|
|
2699
|
+
*
|
|
2700
|
+
* @public
|
|
2701
|
+
*/
|
|
2702
|
+
function MotionConfig(_a) {
|
|
2703
|
+
var children = _a.children, config = tslib.__rest(_a, ["children"]);
|
|
2704
|
+
/**
|
|
2705
|
+
* Inherit props from any parent MotionConfig components
|
|
2706
|
+
*/
|
|
2707
|
+
config = tslib.__assign(tslib.__assign({}, React.useContext(useMotionValue.MotionConfigContext)), config);
|
|
2708
|
+
/**
|
|
2709
|
+
* Don't allow isStatic to change between renders as it affects how many hooks
|
|
2710
|
+
* motion components fire.
|
|
2711
|
+
*/
|
|
2712
|
+
config.isStatic = useMotionValue.useConstant(function () { return config.isStatic; });
|
|
2713
|
+
/**
|
|
2714
|
+
* Creating a new config context object will re-render every `motion` component
|
|
2715
|
+
* every time it renders. So we only want to create a new one sparingly.
|
|
2716
|
+
*/
|
|
2717
|
+
var transitionDependency = typeof config.transition === "object"
|
|
2718
|
+
? config.transition.toString()
|
|
2719
|
+
: "";
|
|
2720
|
+
var context = React.useMemo(function () { return config; }, [
|
|
2721
|
+
transitionDependency,
|
|
2722
|
+
config.transformPagePoint,
|
|
2723
|
+
]);
|
|
2724
|
+
return (React__namespace.createElement(useMotionValue.MotionConfigContext.Provider, { value: context }, children));
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
/**
|
|
2728
|
+
* Used in conjunction with the `m` component to reduce bundle size.
|
|
2729
|
+
*
|
|
2730
|
+
* `m` is a version of the `motion` component that only loads functionality
|
|
2731
|
+
* critical for the initial render.
|
|
2732
|
+
*
|
|
2733
|
+
* `LazyMotion` can then be used to either synchronously or asynchronously
|
|
2734
|
+
* load animation and gesture support.
|
|
2735
|
+
*
|
|
2736
|
+
* ```jsx
|
|
2737
|
+
* // Synchronous loading
|
|
2738
|
+
* import { LazyMotion, m, domAnimations } from "framer-motion"
|
|
2739
|
+
*
|
|
2740
|
+
* function App() {
|
|
2741
|
+
* return (
|
|
2742
|
+
* <LazyMotion features={domAnimations}>
|
|
2743
|
+
* <m.div animate={{ scale: 2 }} />
|
|
2744
|
+
* </LazyMotion>
|
|
2745
|
+
* )
|
|
2746
|
+
* }
|
|
2747
|
+
*
|
|
2748
|
+
* // Asynchronous loading
|
|
2749
|
+
* import { LazyMotion, m } from "framer-motion"
|
|
2750
|
+
*
|
|
2751
|
+
* function App() {
|
|
2752
|
+
* return (
|
|
2753
|
+
* <LazyMotion features={() => import('./path/to/domAnimations')}>
|
|
2754
|
+
* <m.div animate={{ scale: 2 }} />
|
|
2755
|
+
* </LazyMotion>
|
|
2756
|
+
* )
|
|
2757
|
+
* }
|
|
2758
|
+
* ```
|
|
2759
|
+
*
|
|
2760
|
+
* @public
|
|
2761
|
+
*/
|
|
2762
|
+
function LazyMotion(_a) {
|
|
2763
|
+
var children = _a.children, features = _a.features, _b = _a.strict, strict = _b === void 0 ? false : _b;
|
|
2764
|
+
var _c = tslib.__read(React.useState(!isLazyBundle(features)), 2), setIsLoaded = _c[1];
|
|
2765
|
+
var loadedRenderer = React.useRef(undefined);
|
|
2766
|
+
/**
|
|
2767
|
+
* If this is a synchronous load, load features immediately
|
|
2768
|
+
*/
|
|
2769
|
+
if (!isLazyBundle(features)) {
|
|
2770
|
+
var renderer = features.renderer, loadedFeatures = tslib.__rest(features, ["renderer"]);
|
|
2771
|
+
loadedRenderer.current = renderer;
|
|
2772
|
+
useMotionValue.loadFeatures(loadedFeatures);
|
|
2773
|
+
}
|
|
2774
|
+
React.useEffect(function () {
|
|
2775
|
+
if (isLazyBundle(features)) {
|
|
2776
|
+
features().then(function (_a) {
|
|
2777
|
+
var renderer = _a.renderer, loadedFeatures = tslib.__rest(_a, ["renderer"]);
|
|
2778
|
+
useMotionValue.loadFeatures(loadedFeatures);
|
|
2779
|
+
loadedRenderer.current = renderer;
|
|
2780
|
+
setIsLoaded(true);
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2783
|
+
}, []);
|
|
2784
|
+
return (React__namespace.createElement(useMotionValue.LazyContext.Provider, { value: { renderer: loadedRenderer.current, strict: strict } }, children));
|
|
2785
|
+
}
|
|
2786
|
+
function isLazyBundle(features) {
|
|
2787
|
+
return typeof features === "function";
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
var ReorderContext = React.createContext(null);
|
|
2791
|
+
|
|
2792
|
+
function checkReorder(order, value, offset, velocity) {
|
|
2793
|
+
if (!velocity)
|
|
2794
|
+
return order;
|
|
2795
|
+
var index = order.findIndex(function (item) { return item.value === value; });
|
|
2796
|
+
if (index === -1)
|
|
2797
|
+
return order;
|
|
2798
|
+
var nextOffset = velocity > 0 ? 1 : -1;
|
|
2799
|
+
var nextItem = order[index + nextOffset];
|
|
2800
|
+
if (!nextItem)
|
|
2801
|
+
return order;
|
|
2802
|
+
var item = order[index];
|
|
2803
|
+
var nextLayout = nextItem.layout;
|
|
2804
|
+
var nextItemCenter = popmotion.mix(nextLayout.min, nextLayout.max, 0.5);
|
|
2805
|
+
if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
|
|
2806
|
+
(nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
|
|
2807
|
+
return useMotionValue.moveItem(order, index, index + nextOffset);
|
|
2808
|
+
}
|
|
2809
|
+
return order;
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
function ReorderGroup(_a, externalRef) {
|
|
2813
|
+
var children = _a.children, _b = _a.as, as = _b === void 0 ? "ul" : _b, _c = _a.axis, axis = _c === void 0 ? "y" : _c, onReorder = _a.onReorder, values = _a.values, props = tslib.__rest(_a, ["children", "as", "axis", "onReorder", "values"]);
|
|
2814
|
+
var Component = useMotionValue.useConstant(function () { return motion(as); });
|
|
2815
|
+
var order = [];
|
|
2816
|
+
var isReordering = React.useRef(false);
|
|
2817
|
+
heyListen.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
|
|
2818
|
+
var context = {
|
|
2819
|
+
axis: axis,
|
|
2820
|
+
registerItem: function (value, layout) {
|
|
2821
|
+
/**
|
|
2822
|
+
* Ensure entries can't add themselves more than once
|
|
2823
|
+
*/
|
|
2824
|
+
if (layout &&
|
|
2825
|
+
order.findIndex(function (entry) { return value === entry.value; }) === -1) {
|
|
2826
|
+
order.push({ value: value, layout: layout[axis] });
|
|
2827
|
+
order.sort(compareMin);
|
|
2828
|
+
}
|
|
2829
|
+
},
|
|
2830
|
+
updateOrder: function (id, offset, velocity) {
|
|
2831
|
+
if (isReordering.current)
|
|
2832
|
+
return;
|
|
2833
|
+
var newOrder = checkReorder(order, id, offset, velocity);
|
|
2834
|
+
if (order !== newOrder) {
|
|
2835
|
+
isReordering.current = true;
|
|
2836
|
+
onReorder(newOrder
|
|
2837
|
+
.map(getValue)
|
|
2838
|
+
.filter(function (value) { return values.indexOf(value) !== -1; }));
|
|
2839
|
+
}
|
|
2840
|
+
},
|
|
2841
|
+
};
|
|
2842
|
+
React.useEffect(function () {
|
|
2843
|
+
isReordering.current = false;
|
|
2844
|
+
});
|
|
2845
|
+
return (React__namespace.createElement(Component, tslib.__assign({}, props, { ref: externalRef }),
|
|
2846
|
+
React__namespace.createElement(ReorderContext.Provider, { value: context }, children)));
|
|
2847
|
+
}
|
|
2848
|
+
var Group = React.forwardRef(ReorderGroup);
|
|
2849
|
+
function getValue(item) {
|
|
2850
|
+
return item.value;
|
|
2851
|
+
}
|
|
2852
|
+
function compareMin(a, b) {
|
|
2853
|
+
return a.layout.min - b.layout.min;
|
|
2854
|
+
}
|
|
2855
|
+
|
|
2856
|
+
var isCustomValueType = function (v) {
|
|
2857
|
+
return typeof v === "object" && v.mix;
|
|
2858
|
+
};
|
|
2859
|
+
var getMixer = function (v) { return (isCustomValueType(v) ? v.mix : undefined); };
|
|
2860
|
+
function transform() {
|
|
2861
|
+
var args = [];
|
|
2862
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2863
|
+
args[_i] = arguments[_i];
|
|
2864
|
+
}
|
|
2865
|
+
var useImmediate = !Array.isArray(args[0]);
|
|
2866
|
+
var argOffset = useImmediate ? 0 : -1;
|
|
2867
|
+
var inputValue = args[0 + argOffset];
|
|
2868
|
+
var inputRange = args[1 + argOffset];
|
|
2869
|
+
var outputRange = args[2 + argOffset];
|
|
2870
|
+
var options = args[3 + argOffset];
|
|
2871
|
+
var interpolator = popmotion.interpolate(inputRange, outputRange, tslib.__assign({ mixer: getMixer(outputRange[0]) }, options));
|
|
2872
|
+
return useImmediate ? interpolator(inputValue) : interpolator;
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
function useOnChange(value, callback) {
|
|
2876
|
+
React.useEffect(function () {
|
|
2877
|
+
if (useMotionValue.isMotionValue(value))
|
|
2878
|
+
return value.onChange(callback);
|
|
2879
|
+
}, [callback]);
|
|
2880
|
+
}
|
|
2881
|
+
function useMultiOnChange(values, handler) {
|
|
2882
|
+
React.useEffect(function () {
|
|
2883
|
+
var subscriptions = values.map(function (value) { return value.onChange(handler); });
|
|
2884
|
+
return function () { return subscriptions.forEach(function (unsubscribe) { return unsubscribe(); }); };
|
|
2885
|
+
});
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
function useCombineMotionValues(values, combineValues) {
|
|
2889
|
+
/**
|
|
2890
|
+
* Initialise the returned motion value. This remains the same between renders.
|
|
2891
|
+
*/
|
|
2892
|
+
var value = useMotionValue.useMotionValue(combineValues());
|
|
2893
|
+
/**
|
|
2894
|
+
* Create a function that will update the template motion value with the latest values.
|
|
2895
|
+
* This is pre-bound so whenever a motion value updates it can schedule its
|
|
2896
|
+
* execution in Framesync. If it's already been scheduled it won't be fired twice
|
|
2897
|
+
* in a single frame.
|
|
2898
|
+
*/
|
|
2899
|
+
var updateValue = function () { return value.set(combineValues()); };
|
|
2900
|
+
/**
|
|
2901
|
+
* Synchronously update the motion value with the latest values during the render.
|
|
2902
|
+
* This ensures that within a React render, the styles applied to the DOM are up-to-date.
|
|
2903
|
+
*/
|
|
2904
|
+
updateValue();
|
|
2905
|
+
/**
|
|
2906
|
+
* Subscribe to all motion values found within the template. Whenever any of them change,
|
|
2907
|
+
* schedule an update.
|
|
2908
|
+
*/
|
|
2909
|
+
useMultiOnChange(values, function () { return sync__default["default"].update(updateValue, false, true); });
|
|
2910
|
+
return value;
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
function useTransform(input, inputRangeOrTransformer, outputRange, options) {
|
|
2914
|
+
var transformer = typeof inputRangeOrTransformer === "function"
|
|
2915
|
+
? inputRangeOrTransformer
|
|
2916
|
+
: transform(inputRangeOrTransformer, outputRange, options);
|
|
2917
|
+
return Array.isArray(input)
|
|
2918
|
+
? useListTransform(input, transformer)
|
|
2919
|
+
: useListTransform([input], function (_a) {
|
|
2920
|
+
var _b = tslib.__read(_a, 1), latest = _b[0];
|
|
2921
|
+
return transformer(latest);
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
function useListTransform(values, transformer) {
|
|
2925
|
+
var latest = useMotionValue.useConstant(function () { return []; });
|
|
2926
|
+
return useCombineMotionValues(values, function () {
|
|
2927
|
+
latest.length = 0;
|
|
2928
|
+
var numValues = values.length;
|
|
2929
|
+
for (var i = 0; i < numValues; i++) {
|
|
2930
|
+
latest[i] = values[i].get();
|
|
2931
|
+
}
|
|
2932
|
+
return transformer(latest);
|
|
2933
|
+
});
|
|
2934
|
+
}
|
|
2935
|
+
|
|
2936
|
+
function useDefaultMotionValue(value, defaultValue) {
|
|
2937
|
+
if (defaultValue === void 0) { defaultValue = 0; }
|
|
2938
|
+
return useMotionValue.isMotionValue(value) ? value : useMotionValue.useMotionValue(defaultValue);
|
|
2939
|
+
}
|
|
2940
|
+
function ReorderItem(_a, externalRef) {
|
|
2941
|
+
var children = _a.children, style = _a.style, value = _a.value, _b = _a.as, as = _b === void 0 ? "li" : _b, onDrag = _a.onDrag, props = tslib.__rest(_a, ["children", "style", "value", "as", "onDrag"]);
|
|
2942
|
+
var Component = useMotionValue.useConstant(function () { return motion(as); });
|
|
2943
|
+
var context = React.useContext(ReorderContext);
|
|
2944
|
+
var point = {
|
|
2945
|
+
x: useDefaultMotionValue(style === null || style === void 0 ? void 0 : style.x),
|
|
2946
|
+
y: useDefaultMotionValue(style === null || style === void 0 ? void 0 : style.y),
|
|
2947
|
+
};
|
|
2948
|
+
var zIndex = useTransform([point.x, point.y], function (_a) {
|
|
2949
|
+
var _b = tslib.__read(_a, 2), latestX = _b[0], latestY = _b[1];
|
|
2950
|
+
return latestX || latestY ? 1 : "unset";
|
|
2951
|
+
});
|
|
2952
|
+
var layout = React.useRef(null);
|
|
2953
|
+
heyListen.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
|
|
2954
|
+
var _c = context, axis = _c.axis, registerItem = _c.registerItem, updateOrder = _c.updateOrder;
|
|
2955
|
+
React.useEffect(function () {
|
|
2956
|
+
registerItem(value, layout.current);
|
|
2957
|
+
}, [context]);
|
|
2958
|
+
return (React__namespace.createElement(Component, tslib.__assign({ drag: axis }, props, { dragSnapToOrigin: true, style: tslib.__assign(tslib.__assign({}, style), { x: point.x, y: point.y, zIndex: zIndex }), layout: true, onDrag: function (event, gesturePoint) {
|
|
2959
|
+
var velocity = gesturePoint.velocity;
|
|
2960
|
+
velocity[axis] &&
|
|
2961
|
+
updateOrder(value, point[axis].get(), velocity[axis]);
|
|
2962
|
+
onDrag === null || onDrag === void 0 ? void 0 : onDrag(event, gesturePoint);
|
|
2963
|
+
}, onLayoutMeasure: function (measured) {
|
|
2964
|
+
layout.current = measured;
|
|
2965
|
+
}, ref: externalRef }), children));
|
|
2966
|
+
}
|
|
2967
|
+
var Item = React.forwardRef(ReorderItem);
|
|
2968
|
+
|
|
2969
|
+
var Reorder = {
|
|
2970
|
+
Group: Group,
|
|
2971
|
+
Item: Item,
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2974
|
+
/**
|
|
2975
|
+
* @public
|
|
2976
|
+
*/
|
|
2977
|
+
var domAnimation = tslib.__assign(tslib.__assign({ renderer: createDomVisualElement }, useMotionValue.animations), gestureAnimations);
|
|
2978
|
+
|
|
2979
|
+
/**
|
|
2980
|
+
* @public
|
|
2981
|
+
*/
|
|
2982
|
+
var domMax = tslib.__assign(tslib.__assign(tslib.__assign(tslib.__assign({}, domAnimation), drag), layoutFeatures), { projectionNodeConstructor: HTMLProjectionNode });
|
|
2983
|
+
|
|
2984
|
+
/**
|
|
2985
|
+
* Combine multiple motion values into a new one using a string template literal.
|
|
2986
|
+
*
|
|
2987
|
+
* ```jsx
|
|
2988
|
+
* import {
|
|
2989
|
+
* motion,
|
|
2990
|
+
* useSpring,
|
|
2991
|
+
* useMotionValue,
|
|
2992
|
+
* useMotionTemplate
|
|
2993
|
+
* } from "framer-motion"
|
|
2994
|
+
*
|
|
2995
|
+
* function Component() {
|
|
2996
|
+
* const shadowX = useSpring(0)
|
|
2997
|
+
* const shadowY = useMotionValue(0)
|
|
2998
|
+
* const shadow = useMotionTemplate`drop-shadow(${shadowX}px ${shadowY}px 20px rgba(0,0,0,0.3))`
|
|
2999
|
+
*
|
|
3000
|
+
* return <motion.div style={{ filter: shadow }} />
|
|
3001
|
+
* }
|
|
3002
|
+
* ```
|
|
3003
|
+
*
|
|
3004
|
+
* @public
|
|
3005
|
+
*/
|
|
3006
|
+
function useMotionTemplate(fragments) {
|
|
3007
|
+
var values = [];
|
|
3008
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
3009
|
+
values[_i - 1] = arguments[_i];
|
|
3010
|
+
}
|
|
3011
|
+
/**
|
|
3012
|
+
* Create a function that will build a string from the latest motion values.
|
|
3013
|
+
*/
|
|
3014
|
+
var numFragments = fragments.length;
|
|
3015
|
+
function buildValue() {
|
|
3016
|
+
var output = "";
|
|
3017
|
+
for (var i = 0; i < numFragments; i++) {
|
|
3018
|
+
output += fragments[i];
|
|
3019
|
+
var value = values[i];
|
|
3020
|
+
if (value)
|
|
3021
|
+
output += values[i].get();
|
|
3022
|
+
}
|
|
3023
|
+
return output;
|
|
3024
|
+
}
|
|
3025
|
+
return useCombineMotionValues(values, buildValue);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
/**
|
|
3029
|
+
* Creates a `MotionValue` that, when `set`, will use a spring animation to animate to its new state.
|
|
3030
|
+
*
|
|
3031
|
+
* It can either work as a stand-alone `MotionValue` by initialising it with a value, or as a subscriber
|
|
3032
|
+
* to another `MotionValue`.
|
|
3033
|
+
*
|
|
3034
|
+
* @remarks
|
|
3035
|
+
*
|
|
3036
|
+
* ```jsx
|
|
3037
|
+
* const x = useSpring(0, { stiffness: 300 })
|
|
3038
|
+
* const y = useSpring(x, { damping: 10 })
|
|
3039
|
+
* ```
|
|
3040
|
+
*
|
|
3041
|
+
* @param inputValue - `MotionValue` or number. If provided a `MotionValue`, when the input `MotionValue` changes, the created `MotionValue` will spring towards that value.
|
|
3042
|
+
* @param springConfig - Configuration options for the spring.
|
|
3043
|
+
* @returns `MotionValue`
|
|
3044
|
+
*
|
|
3045
|
+
* @public
|
|
3046
|
+
*/
|
|
3047
|
+
function useSpring(source, config) {
|
|
3048
|
+
if (config === void 0) { config = {}; }
|
|
3049
|
+
var isStatic = React.useContext(useMotionValue.MotionConfigContext).isStatic;
|
|
3050
|
+
var activeSpringAnimation = React.useRef(null);
|
|
3051
|
+
var value = useMotionValue.useMotionValue(useMotionValue.isMotionValue(source) ? source.get() : source);
|
|
3052
|
+
React.useMemo(function () {
|
|
3053
|
+
return value.attach(function (v, set) {
|
|
3054
|
+
/**
|
|
3055
|
+
* A more hollistic approach to this might be to use isStatic to fix VisualElement animations
|
|
3056
|
+
* at that level, but this will work for now
|
|
3057
|
+
*/
|
|
3058
|
+
if (isStatic)
|
|
3059
|
+
return set(v);
|
|
3060
|
+
if (activeSpringAnimation.current) {
|
|
3061
|
+
activeSpringAnimation.current.stop();
|
|
3062
|
+
}
|
|
3063
|
+
activeSpringAnimation.current = popmotion.animate(tslib.__assign(tslib.__assign({ from: value.get(), to: v, velocity: value.getVelocity() }, config), { onUpdate: set }));
|
|
3064
|
+
return value.get();
|
|
3065
|
+
});
|
|
3066
|
+
}, Object.values(config));
|
|
3067
|
+
useOnChange(source, function (v) { return value.set(parseFloat(v)); });
|
|
3068
|
+
return value;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
/**
|
|
3072
|
+
* Creates a `MotionValue` that updates when the velocity of the provided `MotionValue` changes.
|
|
3073
|
+
*
|
|
3074
|
+
* ```javascript
|
|
3075
|
+
* const x = useMotionValue(0)
|
|
3076
|
+
* const xVelocity = useVelocity(x)
|
|
3077
|
+
* const xAcceleration = useVelocity(xVelocity)
|
|
3078
|
+
* ```
|
|
3079
|
+
*
|
|
3080
|
+
* @public
|
|
3081
|
+
*/
|
|
3082
|
+
function useVelocity(value) {
|
|
3083
|
+
var velocity = useMotionValue.useMotionValue(value.getVelocity());
|
|
3084
|
+
React.useEffect(function () {
|
|
3085
|
+
return value.velocityUpdateSubscribers.add(function (newVelocity) {
|
|
3086
|
+
velocity.set(newVelocity);
|
|
3087
|
+
});
|
|
3088
|
+
}, [value]);
|
|
3089
|
+
return velocity;
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
function createScrollMotionValues() {
|
|
3093
|
+
return {
|
|
3094
|
+
scrollX: useMotionValue.motionValue(0),
|
|
3095
|
+
scrollY: useMotionValue.motionValue(0),
|
|
3096
|
+
scrollXProgress: useMotionValue.motionValue(0),
|
|
3097
|
+
scrollYProgress: useMotionValue.motionValue(0),
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
function setProgress(offset, maxOffset, value) {
|
|
3101
|
+
value.set(!offset || !maxOffset ? 0 : offset / maxOffset);
|
|
3102
|
+
}
|
|
3103
|
+
function createScrollUpdater(values, getOffsets) {
|
|
3104
|
+
var update = function () {
|
|
3105
|
+
var _a = getOffsets(), xOffset = _a.xOffset, yOffset = _a.yOffset, xMaxOffset = _a.xMaxOffset, yMaxOffset = _a.yMaxOffset;
|
|
3106
|
+
// Set absolute positions
|
|
3107
|
+
values.scrollX.set(xOffset);
|
|
3108
|
+
values.scrollY.set(yOffset);
|
|
3109
|
+
// Set 0-1 progress
|
|
3110
|
+
setProgress(xOffset, xMaxOffset, values.scrollXProgress);
|
|
3111
|
+
setProgress(yOffset, yMaxOffset, values.scrollYProgress);
|
|
3112
|
+
};
|
|
3113
|
+
update();
|
|
3114
|
+
return update;
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
var getElementScrollOffsets = function (element) { return function () {
|
|
3118
|
+
return {
|
|
3119
|
+
xOffset: element.scrollLeft,
|
|
3120
|
+
yOffset: element.scrollTop,
|
|
3121
|
+
xMaxOffset: element.scrollWidth - element.offsetWidth,
|
|
3122
|
+
yMaxOffset: element.scrollHeight - element.offsetHeight,
|
|
3123
|
+
};
|
|
3124
|
+
}; };
|
|
3125
|
+
/**
|
|
3126
|
+
* Returns MotionValues that update when the provided element scrolls:
|
|
3127
|
+
*
|
|
3128
|
+
* - `scrollX` — Horizontal scroll distance in pixels.
|
|
3129
|
+
* - `scrollY` — Vertical scroll distance in pixels.
|
|
3130
|
+
* - `scrollXProgress` — Horizontal scroll progress between `0` and `1`.
|
|
3131
|
+
* - `scrollYProgress` — Vertical scroll progress between `0` and `1`.
|
|
3132
|
+
*
|
|
3133
|
+
* This element must be set to `overflow: scroll` on either or both axes to report scroll offset.
|
|
3134
|
+
*
|
|
3135
|
+
* ```jsx
|
|
3136
|
+
* export const MyComponent = () => {
|
|
3137
|
+
* const ref = useRef()
|
|
3138
|
+
* const { scrollYProgress } = useElementScroll(ref)
|
|
3139
|
+
*
|
|
3140
|
+
* return (
|
|
3141
|
+
* <div ref={ref}>
|
|
3142
|
+
* <motion.div style={{ scaleX: scrollYProgress }} />
|
|
3143
|
+
* </div>
|
|
3144
|
+
* )
|
|
3145
|
+
* }
|
|
3146
|
+
* ```
|
|
3147
|
+
*
|
|
3148
|
+
* @public
|
|
3149
|
+
*/
|
|
3150
|
+
function useElementScroll(ref) {
|
|
3151
|
+
var values = useMotionValue.useConstant(createScrollMotionValues);
|
|
3152
|
+
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
3153
|
+
var element = ref.current;
|
|
3154
|
+
heyListen.invariant(!!element, "ref provided to useScroll must be passed into a HTML element.");
|
|
3155
|
+
if (!element)
|
|
3156
|
+
return;
|
|
3157
|
+
var updateScrollValues = createScrollUpdater(values, getElementScrollOffsets(element));
|
|
3158
|
+
var scrollListener = useMotionValue.addDomEvent(element, "scroll", updateScrollValues, { passive: true });
|
|
3159
|
+
var resizeListener = useMotionValue.addDomEvent(element, "resize", updateScrollValues);
|
|
3160
|
+
return function () {
|
|
3161
|
+
scrollListener && scrollListener();
|
|
3162
|
+
resizeListener && resizeListener();
|
|
3163
|
+
};
|
|
3164
|
+
}, []);
|
|
3165
|
+
return values;
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
var viewportScrollValues;
|
|
3169
|
+
function getViewportScrollOffsets() {
|
|
3170
|
+
return {
|
|
3171
|
+
xOffset: window.pageXOffset,
|
|
3172
|
+
yOffset: window.pageYOffset,
|
|
3173
|
+
xMaxOffset: document.body.clientWidth - window.innerWidth,
|
|
3174
|
+
yMaxOffset: document.body.clientHeight - window.innerHeight,
|
|
3175
|
+
};
|
|
3176
|
+
}
|
|
3177
|
+
var hasListeners = false;
|
|
3178
|
+
function addEventListeners() {
|
|
3179
|
+
hasListeners = true;
|
|
3180
|
+
if (typeof window === "undefined")
|
|
3181
|
+
return;
|
|
3182
|
+
var updateScrollValues = createScrollUpdater(viewportScrollValues, getViewportScrollOffsets);
|
|
3183
|
+
useMotionValue.addDomEvent(window, "scroll", updateScrollValues, { passive: true });
|
|
3184
|
+
useMotionValue.addDomEvent(window, "resize", updateScrollValues);
|
|
3185
|
+
}
|
|
3186
|
+
/**
|
|
3187
|
+
* Returns MotionValues that update when the viewport scrolls:
|
|
3188
|
+
*
|
|
3189
|
+
* - `scrollX` — Horizontal scroll distance in pixels.
|
|
3190
|
+
* - `scrollY` — Vertical scroll distance in pixels.
|
|
3191
|
+
* - `scrollXProgress` — Horizontal scroll progress between `0` and `1`.
|
|
3192
|
+
* - `scrollYProgress` — Vertical scroll progress between `0` and `1`.
|
|
3193
|
+
*
|
|
3194
|
+
* **Warning:** Setting `body` or `html` to `height: 100%` or similar will break the `Progress`
|
|
3195
|
+
* values as this breaks the browser's capability to accurately measure the page length.
|
|
3196
|
+
*
|
|
3197
|
+
* ```jsx
|
|
3198
|
+
* export const MyComponent = () => {
|
|
3199
|
+
* const { scrollYProgress } = useViewportScroll()
|
|
3200
|
+
* return <motion.div style={{ scaleX: scrollYProgress }} />
|
|
3201
|
+
* }
|
|
3202
|
+
* ```
|
|
3203
|
+
*
|
|
3204
|
+
* @public
|
|
3205
|
+
*/
|
|
3206
|
+
function useViewportScroll() {
|
|
3207
|
+
/**
|
|
3208
|
+
* Lazy-initialise the viewport scroll values
|
|
3209
|
+
*/
|
|
3210
|
+
if (!viewportScrollValues) {
|
|
3211
|
+
viewportScrollValues = createScrollMotionValues();
|
|
3212
|
+
}
|
|
3213
|
+
useMotionValue.useIsomorphicLayoutEffect(function () {
|
|
3214
|
+
!hasListeners && addEventListeners();
|
|
3215
|
+
}, []);
|
|
3216
|
+
return viewportScrollValues;
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
var getCurrentTime = typeof performance !== "undefined"
|
|
3220
|
+
? function () { return performance.now(); }
|
|
3221
|
+
: function () { return Date.now(); };
|
|
3222
|
+
function useAnimationFrame(callback) {
|
|
3223
|
+
var initialTimestamp = useMotionValue.useConstant(getCurrentTime);
|
|
3224
|
+
React.useEffect(function () {
|
|
3225
|
+
var provideTimeSinceStart = function (_a) {
|
|
3226
|
+
var timestamp = _a.timestamp;
|
|
3227
|
+
callback(timestamp - initialTimestamp);
|
|
3228
|
+
};
|
|
3229
|
+
sync__default["default"].update(provideTimeSinceStart, true);
|
|
3230
|
+
return function () { return sync.cancelSync.update(provideTimeSinceStart); };
|
|
3231
|
+
}, [callback]);
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3234
|
+
function useTime() {
|
|
3235
|
+
var time = useMotionValue.useMotionValue(0);
|
|
3236
|
+
useAnimationFrame(function (t) { return time.set(t); });
|
|
3237
|
+
return time;
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
// Does this device prefer reduced motion? Returns `null` server-side.
|
|
3241
|
+
var prefersReducedMotion;
|
|
3242
|
+
function initPrefersReducedMotion() {
|
|
3243
|
+
prefersReducedMotion = useMotionValue.motionValue(null);
|
|
3244
|
+
if (typeof window === "undefined")
|
|
3245
|
+
return;
|
|
3246
|
+
if (window.matchMedia) {
|
|
3247
|
+
var motionMediaQuery_1 = window.matchMedia("(prefers-reduced-motion)");
|
|
3248
|
+
var setReducedMotionPreferences = function () {
|
|
3249
|
+
return prefersReducedMotion.set(motionMediaQuery_1.matches);
|
|
3250
|
+
};
|
|
3251
|
+
motionMediaQuery_1.addListener(setReducedMotionPreferences);
|
|
3252
|
+
setReducedMotionPreferences();
|
|
3253
|
+
}
|
|
3254
|
+
else {
|
|
3255
|
+
prefersReducedMotion.set(false);
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
/**
|
|
3259
|
+
* A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
|
|
3260
|
+
*
|
|
3261
|
+
* This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
|
|
3262
|
+
* `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
|
|
3263
|
+
*
|
|
3264
|
+
* It will actively respond to changes and re-render your components with the latest setting.
|
|
3265
|
+
*
|
|
3266
|
+
* ```jsx
|
|
3267
|
+
* export function Sidebar({ isOpen }) {
|
|
3268
|
+
* const shouldReduceMotion = useReducedMotion()
|
|
3269
|
+
* const closedX = shouldReduceMotion ? 0 : "-100%"
|
|
3270
|
+
*
|
|
3271
|
+
* return (
|
|
3272
|
+
* <motion.div animate={{
|
|
3273
|
+
* opacity: isOpen ? 1 : 0,
|
|
3274
|
+
* x: isOpen ? 0 : closedX
|
|
3275
|
+
* }} />
|
|
3276
|
+
* )
|
|
3277
|
+
* }
|
|
3278
|
+
* ```
|
|
3279
|
+
*
|
|
3280
|
+
* @return boolean
|
|
3281
|
+
*
|
|
3282
|
+
* @public
|
|
3283
|
+
*/
|
|
3284
|
+
function useReducedMotion() {
|
|
3285
|
+
/**
|
|
3286
|
+
* Lazy initialisation of prefersReducedMotion
|
|
3287
|
+
*/
|
|
3288
|
+
!prefersReducedMotion && initPrefersReducedMotion();
|
|
3289
|
+
var _a = tslib.__read(React.useState(prefersReducedMotion.get()), 2), shouldReduceMotion = _a[0], setShouldReduceMotion = _a[1];
|
|
3290
|
+
useOnChange(prefersReducedMotion, setShouldReduceMotion);
|
|
3291
|
+
return shouldReduceMotion;
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
/**
|
|
3295
|
+
* @public
|
|
3296
|
+
*/
|
|
3297
|
+
function animationControls() {
|
|
3298
|
+
/**
|
|
3299
|
+
* Track whether the host component has mounted.
|
|
3300
|
+
*/
|
|
3301
|
+
var hasMounted = false;
|
|
3302
|
+
/**
|
|
3303
|
+
* Pending animations that are started before a component is mounted.
|
|
3304
|
+
* TODO: Remove this as animations should only run in effects
|
|
3305
|
+
*/
|
|
3306
|
+
var pendingAnimations = [];
|
|
3307
|
+
/**
|
|
3308
|
+
* A collection of linked component animation controls.
|
|
3309
|
+
*/
|
|
3310
|
+
var subscribers = new Set();
|
|
3311
|
+
var controls = {
|
|
3312
|
+
subscribe: function (visualElement) {
|
|
3313
|
+
subscribers.add(visualElement);
|
|
3314
|
+
return function () { return void subscribers.delete(visualElement); };
|
|
3315
|
+
},
|
|
3316
|
+
start: function (definition, transitionOverride) {
|
|
3317
|
+
/**
|
|
3318
|
+
* TODO: We only perform this hasMounted check because in Framer we used to
|
|
3319
|
+
* encourage the ability to start an animation within the render phase. This
|
|
3320
|
+
* isn't behaviour concurrent-safe so when we make Framer concurrent-safe
|
|
3321
|
+
* we can ditch this.
|
|
3322
|
+
*/
|
|
3323
|
+
if (hasMounted) {
|
|
3324
|
+
var animations_1 = [];
|
|
3325
|
+
subscribers.forEach(function (visualElement) {
|
|
3326
|
+
animations_1.push(useMotionValue.animateVisualElement(visualElement, definition, {
|
|
3327
|
+
transitionOverride: transitionOverride,
|
|
3328
|
+
}));
|
|
3329
|
+
});
|
|
3330
|
+
return Promise.all(animations_1);
|
|
3331
|
+
}
|
|
3332
|
+
else {
|
|
3333
|
+
return new Promise(function (resolve) {
|
|
3334
|
+
pendingAnimations.push({
|
|
3335
|
+
animation: [definition, transitionOverride],
|
|
3336
|
+
resolve: resolve,
|
|
3337
|
+
});
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3340
|
+
},
|
|
3341
|
+
set: function (definition) {
|
|
3342
|
+
heyListen.invariant(hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.");
|
|
3343
|
+
return subscribers.forEach(function (visualElement) {
|
|
3344
|
+
useMotionValue.setValues(visualElement, definition);
|
|
3345
|
+
});
|
|
3346
|
+
},
|
|
3347
|
+
stop: function () {
|
|
3348
|
+
subscribers.forEach(function (visualElement) {
|
|
3349
|
+
useMotionValue.stopAnimation(visualElement);
|
|
3350
|
+
});
|
|
3351
|
+
},
|
|
3352
|
+
mount: function () {
|
|
3353
|
+
hasMounted = true;
|
|
3354
|
+
pendingAnimations.forEach(function (_a) {
|
|
3355
|
+
var animation = _a.animation, resolve = _a.resolve;
|
|
3356
|
+
controls.start.apply(controls, tslib.__spreadArray([], tslib.__read(animation), false)).then(resolve);
|
|
3357
|
+
});
|
|
3358
|
+
return function () {
|
|
3359
|
+
hasMounted = false;
|
|
3360
|
+
controls.stop();
|
|
3361
|
+
};
|
|
3362
|
+
},
|
|
3363
|
+
};
|
|
3364
|
+
return controls;
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
/**
|
|
3368
|
+
* Creates `AnimationControls`, which can be used to manually start, stop
|
|
3369
|
+
* and sequence animations on one or more components.
|
|
3370
|
+
*
|
|
3371
|
+
* The returned `AnimationControls` should be passed to the `animate` property
|
|
3372
|
+
* of the components you want to animate.
|
|
3373
|
+
*
|
|
3374
|
+
* These components can then be animated with the `start` method.
|
|
3375
|
+
*
|
|
3376
|
+
* ```jsx
|
|
3377
|
+
* import * as React from 'react'
|
|
3378
|
+
* import { motion, useAnimation } from 'framer-motion'
|
|
3379
|
+
*
|
|
3380
|
+
* export function MyComponent(props) {
|
|
3381
|
+
* const controls = useAnimation()
|
|
3382
|
+
*
|
|
3383
|
+
* controls.start({
|
|
3384
|
+
* x: 100,
|
|
3385
|
+
* transition: { duration: 0.5 },
|
|
3386
|
+
* })
|
|
3387
|
+
*
|
|
3388
|
+
* return <motion.div animate={controls} />
|
|
3389
|
+
* }
|
|
3390
|
+
* ```
|
|
3391
|
+
*
|
|
3392
|
+
* @returns Animation controller with `start` and `stop` methods
|
|
3393
|
+
*
|
|
3394
|
+
* @public
|
|
3395
|
+
*/
|
|
3396
|
+
function useAnimation() {
|
|
3397
|
+
var controls = useMotionValue.useConstant(animationControls);
|
|
3398
|
+
React.useEffect(controls.mount, []);
|
|
3399
|
+
return controls;
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
/**
|
|
3403
|
+
* Cycles through a series of visual properties. Can be used to toggle between or cycle through animations. It works similar to `useState` in React. It is provided an initial array of possible states, and returns an array of two arguments.
|
|
3404
|
+
*
|
|
3405
|
+
* An index value can be passed to the returned `cycle` function to cycle to a specific index.
|
|
3406
|
+
*
|
|
3407
|
+
* ```jsx
|
|
3408
|
+
* import * as React from "react"
|
|
3409
|
+
* import { motion, useCycle } from "framer-motion"
|
|
3410
|
+
*
|
|
3411
|
+
* export const MyComponent = () => {
|
|
3412
|
+
* const [x, cycleX] = useCycle(0, 50, 100)
|
|
3413
|
+
*
|
|
3414
|
+
* return (
|
|
3415
|
+
* <motion.div
|
|
3416
|
+
* animate={{ x: x }}
|
|
3417
|
+
* onTap={() => cycleX()}
|
|
3418
|
+
* />
|
|
3419
|
+
* )
|
|
3420
|
+
* }
|
|
3421
|
+
* ```
|
|
3422
|
+
*
|
|
3423
|
+
* @param items - items to cycle through
|
|
3424
|
+
* @returns [currentState, cycleState]
|
|
3425
|
+
*
|
|
3426
|
+
* @public
|
|
3427
|
+
*/
|
|
3428
|
+
function useCycle() {
|
|
3429
|
+
var items = [];
|
|
3430
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
3431
|
+
items[_i] = arguments[_i];
|
|
3432
|
+
}
|
|
3433
|
+
var index = React.useRef(0);
|
|
3434
|
+
var _a = tslib.__read(React.useState(items[index.current]), 2), item = _a[0], setItem = _a[1];
|
|
3435
|
+
return [
|
|
3436
|
+
item,
|
|
3437
|
+
function (next) {
|
|
3438
|
+
index.current =
|
|
3439
|
+
typeof next !== "number"
|
|
3440
|
+
? popmotion.wrap(0, items.length, index.current + 1)
|
|
3441
|
+
: next;
|
|
3442
|
+
setItem(items[index.current]);
|
|
3443
|
+
},
|
|
3444
|
+
];
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
/**
|
|
3448
|
+
* Can manually trigger a drag gesture on one or more `drag`-enabled `motion` components.
|
|
3449
|
+
*
|
|
3450
|
+
* ```jsx
|
|
3451
|
+
* const dragControls = useDragControls()
|
|
3452
|
+
*
|
|
3453
|
+
* function startDrag(event) {
|
|
3454
|
+
* dragControls.start(event, { snapToCursor: true })
|
|
3455
|
+
* }
|
|
3456
|
+
*
|
|
3457
|
+
* return (
|
|
3458
|
+
* <>
|
|
3459
|
+
* <div onPointerDown={startDrag} />
|
|
3460
|
+
* <motion.div drag="x" dragControls={dragControls} />
|
|
3461
|
+
* </>
|
|
3462
|
+
* )
|
|
3463
|
+
* ```
|
|
3464
|
+
*
|
|
3465
|
+
* @public
|
|
3466
|
+
*/
|
|
3467
|
+
var DragControls = /** @class */ (function () {
|
|
3468
|
+
function DragControls() {
|
|
3469
|
+
this.componentControls = new Set();
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Subscribe a component's internal `VisualElementDragControls` to the user-facing API.
|
|
3473
|
+
*
|
|
3474
|
+
* @internal
|
|
3475
|
+
*/
|
|
3476
|
+
DragControls.prototype.subscribe = function (controls) {
|
|
3477
|
+
var _this = this;
|
|
3478
|
+
this.componentControls.add(controls);
|
|
3479
|
+
return function () { return _this.componentControls.delete(controls); };
|
|
3480
|
+
};
|
|
3481
|
+
/**
|
|
3482
|
+
* Start a drag gesture on every `motion` component that has this set of drag controls
|
|
3483
|
+
* passed into it via the `dragControls` prop.
|
|
3484
|
+
*
|
|
3485
|
+
* ```jsx
|
|
3486
|
+
* dragControls.start(e, {
|
|
3487
|
+
* snapToCursor: true
|
|
3488
|
+
* })
|
|
3489
|
+
* ```
|
|
3490
|
+
*
|
|
3491
|
+
* @param event - PointerEvent
|
|
3492
|
+
* @param options - Options
|
|
3493
|
+
*
|
|
3494
|
+
* @public
|
|
3495
|
+
*/
|
|
3496
|
+
DragControls.prototype.start = function (event, options) {
|
|
3497
|
+
this.componentControls.forEach(function (controls) {
|
|
3498
|
+
controls.start(event.nativeEvent || event, options);
|
|
3499
|
+
});
|
|
3500
|
+
};
|
|
3501
|
+
return DragControls;
|
|
3502
|
+
}());
|
|
3503
|
+
var createDragControls = function () { return new DragControls(); };
|
|
3504
|
+
/**
|
|
3505
|
+
* Usually, dragging is initiated by pressing down on a `motion` component with a `drag` prop
|
|
3506
|
+
* and moving it. For some use-cases, for instance clicking at an arbitrary point on a video scrubber, we
|
|
3507
|
+
* might want to initiate that dragging from a different component than the draggable one.
|
|
3508
|
+
*
|
|
3509
|
+
* By creating a `dragControls` using the `useDragControls` hook, we can pass this into
|
|
3510
|
+
* the draggable component's `dragControls` prop. It exposes a `start` method
|
|
3511
|
+
* that can start dragging from pointer events on other components.
|
|
3512
|
+
*
|
|
3513
|
+
* ```jsx
|
|
3514
|
+
* const dragControls = useDragControls()
|
|
3515
|
+
*
|
|
3516
|
+
* function startDrag(event) {
|
|
3517
|
+
* dragControls.start(event, { snapToCursor: true })
|
|
3518
|
+
* }
|
|
3519
|
+
*
|
|
3520
|
+
* return (
|
|
3521
|
+
* <>
|
|
3522
|
+
* <div onPointerDown={startDrag} />
|
|
3523
|
+
* <motion.div drag="x" dragControls={dragControls} />
|
|
3524
|
+
* </>
|
|
3525
|
+
* )
|
|
3526
|
+
* ```
|
|
3527
|
+
*
|
|
3528
|
+
* @public
|
|
3529
|
+
*/
|
|
3530
|
+
function useDragControls() {
|
|
3531
|
+
return useMotionValue.useConstant(createDragControls);
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3534
|
+
function useInstantLayoutTransition() {
|
|
3535
|
+
return startTransition;
|
|
3536
|
+
}
|
|
3537
|
+
function startTransition(cb) {
|
|
3538
|
+
if (!rootProjectionNode.current)
|
|
3539
|
+
return;
|
|
3540
|
+
rootProjectionNode.current.isUpdating = false;
|
|
3541
|
+
rootProjectionNode.current.blockUpdate();
|
|
3542
|
+
cb === null || cb === void 0 ? void 0 : cb();
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
function useInstantTransition() {
|
|
3546
|
+
var _a = tslib.__read(useForceUpdate(), 2), forceUpdate = _a[0], forcedRenderCount = _a[1];
|
|
3547
|
+
var startInstantLayoutTransition = useInstantLayoutTransition();
|
|
3548
|
+
React.useEffect(function () {
|
|
3549
|
+
/**
|
|
3550
|
+
* Unblock after two animation frames, otherwise this will unblock too soon.
|
|
3551
|
+
*/
|
|
3552
|
+
sync__default["default"].postRender(function () {
|
|
3553
|
+
return sync__default["default"].postRender(function () { return (useMotionValue.instantAnimationState.current = false); });
|
|
3554
|
+
});
|
|
3555
|
+
}, [forcedRenderCount]);
|
|
3556
|
+
return function (callback) {
|
|
3557
|
+
startInstantLayoutTransition(function () {
|
|
3558
|
+
useMotionValue.instantAnimationState.current = true;
|
|
3559
|
+
forceUpdate();
|
|
3560
|
+
callback();
|
|
3561
|
+
});
|
|
3562
|
+
};
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
function useResetProjection() {
|
|
3566
|
+
var reset = React__namespace.useCallback(function () {
|
|
3567
|
+
var root = rootProjectionNode.current;
|
|
3568
|
+
if (!root)
|
|
3569
|
+
return;
|
|
3570
|
+
root.resetTree();
|
|
3571
|
+
}, []);
|
|
3572
|
+
return reset;
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3575
|
+
var createObject = function () { return ({}); };
|
|
3576
|
+
var stateVisualElement = useMotionValue.visualElement({
|
|
3577
|
+
build: function () { },
|
|
3578
|
+
measureViewportBox: useMotionValue.createBox,
|
|
3579
|
+
resetTransform: function () { },
|
|
3580
|
+
restoreTransform: function () { },
|
|
3581
|
+
removeValueFromRenderState: function () { },
|
|
3582
|
+
render: function () { },
|
|
3583
|
+
scrapeMotionValuesFromProps: createObject,
|
|
3584
|
+
readValueFromInstance: function (_state, key, options) {
|
|
3585
|
+
return options.initialState[key] || 0;
|
|
3586
|
+
},
|
|
3587
|
+
makeTargetAnimatable: function (element, _a) {
|
|
3588
|
+
var transition = _a.transition, transitionEnd = _a.transitionEnd, target = tslib.__rest(_a, ["transition", "transitionEnd"]);
|
|
3589
|
+
var origin = useMotionValue.getOrigin(target, transition || {}, element);
|
|
3590
|
+
useMotionValue.checkTargetForNewValues(element, target, origin);
|
|
3591
|
+
return tslib.__assign({ transition: transition, transitionEnd: transitionEnd }, target);
|
|
3592
|
+
},
|
|
3593
|
+
});
|
|
3594
|
+
var useVisualState = useMotionValue.makeUseVisualState({
|
|
3595
|
+
scrapeMotionValuesFromProps: createObject,
|
|
3596
|
+
createRenderState: createObject,
|
|
3597
|
+
});
|
|
3598
|
+
/**
|
|
3599
|
+
* This is not an officially supported API and may be removed
|
|
3600
|
+
* on any version.
|
|
3601
|
+
* @internal
|
|
3602
|
+
*/
|
|
3603
|
+
function useAnimatedState(initialState) {
|
|
3604
|
+
var _a = tslib.__read(React.useState(initialState), 2), animationState = _a[0], setAnimationState = _a[1];
|
|
3605
|
+
var visualState = useVisualState({}, false);
|
|
3606
|
+
var element = useMotionValue.useConstant(function () {
|
|
3607
|
+
return stateVisualElement({ props: {}, visualState: visualState }, { initialState: initialState });
|
|
3608
|
+
});
|
|
3609
|
+
React.useEffect(function () {
|
|
3610
|
+
element.mount({});
|
|
3611
|
+
return element.unmount();
|
|
3612
|
+
}, []);
|
|
3613
|
+
React.useEffect(function () {
|
|
3614
|
+
element.setProps({
|
|
3615
|
+
onUpdate: function (v) { return setAnimationState(tslib.__assign({}, v)); },
|
|
3616
|
+
});
|
|
3617
|
+
});
|
|
3618
|
+
var startAnimation = useMotionValue.useConstant(function () { return function (animationDefinition) {
|
|
3619
|
+
return useMotionValue.animateVisualElement(element, animationDefinition);
|
|
3620
|
+
}; });
|
|
3621
|
+
return [animationState, startAnimation];
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
// Keep things reasonable and avoid scale: Infinity. In practise we might need
|
|
3625
|
+
// to add another value, opacity, that could interpolate scaleX/Y [0,0.01] => [0,1]
|
|
3626
|
+
// to simply hide content at unreasonable scales.
|
|
3627
|
+
var maxScale = 100000;
|
|
3628
|
+
var invertScale = function (scale) {
|
|
3629
|
+
return scale > 0.001 ? 1 / scale : maxScale;
|
|
3630
|
+
};
|
|
3631
|
+
var hasWarned = false;
|
|
3632
|
+
/**
|
|
3633
|
+
* Returns a `MotionValue` each for `scaleX` and `scaleY` that update with the inverse
|
|
3634
|
+
* of their respective parent scales.
|
|
3635
|
+
*
|
|
3636
|
+
* This is useful for undoing the distortion of content when scaling a parent component.
|
|
3637
|
+
*
|
|
3638
|
+
* By default, `useInvertedScale` will automatically fetch `scaleX` and `scaleY` from the nearest parent.
|
|
3639
|
+
* By passing other `MotionValue`s in as `useInvertedScale({ scaleX, scaleY })`, it will invert the output
|
|
3640
|
+
* of those instead.
|
|
3641
|
+
*
|
|
3642
|
+
* ```jsx
|
|
3643
|
+
* const MyComponent = () => {
|
|
3644
|
+
* const { scaleX, scaleY } = useInvertedScale()
|
|
3645
|
+
* return <motion.div style={{ scaleX, scaleY }} />
|
|
3646
|
+
* }
|
|
3647
|
+
* ```
|
|
3648
|
+
*
|
|
3649
|
+
* @deprecated
|
|
3650
|
+
* @internal
|
|
3651
|
+
*/
|
|
3652
|
+
function useInvertedScale(scale) {
|
|
3653
|
+
var parentScaleX = useMotionValue.useMotionValue(1);
|
|
3654
|
+
var parentScaleY = useMotionValue.useMotionValue(1);
|
|
3655
|
+
var visualElement = useMotionValue.useVisualElementContext();
|
|
3656
|
+
heyListen.invariant(!!(scale || visualElement), "If no scale values are provided, useInvertedScale must be used within a child of another motion component.");
|
|
3657
|
+
heyListen.warning(hasWarned, "useInvertedScale is deprecated and will be removed in 3.0. Use the layout prop instead.");
|
|
3658
|
+
hasWarned = true;
|
|
3659
|
+
if (scale) {
|
|
3660
|
+
parentScaleX = scale.scaleX || parentScaleX;
|
|
3661
|
+
parentScaleY = scale.scaleY || parentScaleY;
|
|
3662
|
+
}
|
|
3663
|
+
else if (visualElement) {
|
|
3664
|
+
parentScaleX = visualElement.getValue("scaleX", 1);
|
|
3665
|
+
parentScaleY = visualElement.getValue("scaleY", 1);
|
|
3666
|
+
}
|
|
3667
|
+
var scaleX = useTransform(parentScaleX, invertScale);
|
|
3668
|
+
var scaleY = useTransform(parentScaleY, invertScale);
|
|
3669
|
+
return { scaleX: scaleX, scaleY: scaleY };
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
exports.FlatTree = useMotionValue.FlatTree;
|
|
3673
|
+
exports.LayoutGroupContext = useMotionValue.LayoutGroupContext;
|
|
3674
|
+
exports.MotionConfigContext = useMotionValue.MotionConfigContext;
|
|
3675
|
+
exports.MotionValue = useMotionValue.MotionValue;
|
|
3676
|
+
exports.PresenceContext = useMotionValue.PresenceContext;
|
|
3677
|
+
exports.SwitchLayoutGroupContext = useMotionValue.SwitchLayoutGroupContext;
|
|
3678
|
+
exports.addScaleCorrector = useMotionValue.addScaleCorrector;
|
|
3679
|
+
exports.animate = useMotionValue.animate;
|
|
3680
|
+
exports.animateVisualElement = useMotionValue.animateVisualElement;
|
|
3681
|
+
exports.createMotionComponent = useMotionValue.createMotionComponent;
|
|
3682
|
+
exports.isValidMotionProp = useMotionValue.isValidMotionProp;
|
|
3683
|
+
exports.motionValue = useMotionValue.motionValue;
|
|
3684
|
+
exports.resolveMotionValue = useMotionValue.resolveMotionValue;
|
|
3685
|
+
exports.useDomEvent = useMotionValue.useDomEvent;
|
|
3686
|
+
exports.useIsPresent = useMotionValue.useIsPresent;
|
|
3687
|
+
exports.useMotionValue = useMotionValue.useMotionValue;
|
|
3688
|
+
exports.usePresence = useMotionValue.usePresence;
|
|
3689
|
+
exports.visualElement = useMotionValue.visualElement;
|
|
3690
|
+
exports.AnimatePresence = AnimatePresence;
|
|
3691
|
+
exports.AnimateSharedLayout = AnimateSharedLayout;
|
|
3692
|
+
exports.DeprecatedLayoutGroupContext = DeprecatedLayoutGroupContext;
|
|
3693
|
+
exports.DragControls = DragControls;
|
|
3694
|
+
exports.LayoutGroup = LayoutGroup;
|
|
3695
|
+
exports.LazyMotion = LazyMotion;
|
|
3696
|
+
exports.MotionConfig = MotionConfig;
|
|
3697
|
+
exports.Reorder = Reorder;
|
|
3698
|
+
exports.animationControls = animationControls;
|
|
3699
|
+
exports.createDomMotionComponent = createDomMotionComponent;
|
|
3700
|
+
exports.domAnimation = domAnimation;
|
|
3701
|
+
exports.domMax = domMax;
|
|
3702
|
+
exports.m = m;
|
|
3703
|
+
exports.motion = motion;
|
|
3704
|
+
exports.transform = transform;
|
|
3705
|
+
exports.useAnimation = useAnimation;
|
|
3706
|
+
exports.useAnimationFrame = useAnimationFrame;
|
|
3707
|
+
exports.useCycle = useCycle;
|
|
3708
|
+
exports.useDeprecatedAnimatedState = useAnimatedState;
|
|
3709
|
+
exports.useDeprecatedInvertedScale = useInvertedScale;
|
|
3710
|
+
exports.useDragControls = useDragControls;
|
|
3711
|
+
exports.useElementScroll = useElementScroll;
|
|
3712
|
+
exports.useInstantLayoutTransition = useInstantLayoutTransition;
|
|
3713
|
+
exports.useInstantTransition = useInstantTransition;
|
|
3714
|
+
exports.useMotionTemplate = useMotionTemplate;
|
|
3715
|
+
exports.useReducedMotion = useReducedMotion;
|
|
3716
|
+
exports.useResetProjection = useResetProjection;
|
|
3717
|
+
exports.useSpring = useSpring;
|
|
3718
|
+
exports.useTime = useTime;
|
|
3719
|
+
exports.useTransform = useTransform;
|
|
3720
|
+
exports.useVelocity = useVelocity;
|
|
3721
|
+
exports.useViewportScroll = useViewportScroll;
|