framer-motion 5.4.0 → 5.4.3

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.
@@ -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;