@fluentui/react-motion 9.2.2 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -2
- package/dist/index.d.ts +72 -8
- package/lib/factories/createPresenceComponent.js +9 -3
- package/lib/factories/createPresenceComponent.js.map +1 -1
- package/lib/factories/createPresenceComponentVariant.js +23 -0
- package/lib/factories/createPresenceComponentVariant.js.map +1 -0
- package/lib/hooks/useAnimateAtoms.js +56 -49
- package/lib/hooks/useAnimateAtoms.js.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/slots/presenceMotionSlot.js +40 -0
- package/lib/slots/presenceMotionSlot.js.map +1 -0
- package/lib/types.js.map +1 -1
- package/lib-commonjs/factories/createPresenceComponent.js +18 -6
- package/lib-commonjs/factories/createPresenceComponent.js.map +1 -1
- package/lib-commonjs/factories/createPresenceComponentVariant.js +39 -0
- package/lib-commonjs/factories/createPresenceComponentVariant.js.map +1 -0
- package/lib-commonjs/hooks/useAnimateAtoms.js +54 -47
- package/lib-commonjs/hooks/useAnimateAtoms.js.map +1 -1
- package/lib-commonjs/index.js +8 -0
- package/lib-commonjs/index.js.map +1 -1
- package/lib-commonjs/slots/presenceMotionSlot.js +51 -0
- package/lib-commonjs/slots/presenceMotionSlot.js.map +1 -0
- package/lib-commonjs/types.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
@@ -1,12 +1,43 @@
|
|
1
1
|
# Change Log - @fluentui/react-motion
|
2
2
|
|
3
|
-
This log was last generated on
|
3
|
+
This log was last generated on Tue, 23 Jul 2024 20:09:18 GMT and should not be manually modified.
|
4
4
|
|
5
5
|
<!-- Start content -->
|
6
6
|
|
7
|
+
## [9.4.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.4.0)
|
8
|
+
|
9
|
+
Tue, 23 Jul 2024 20:09:18 GMT
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.3.0..@fluentui/react-motion_v9.4.0)
|
11
|
+
|
12
|
+
### Minor changes
|
13
|
+
|
14
|
+
- feat: add presenceMotionSlot() API ([PR #31984](https://github.com/microsoft/fluentui/pull/31984) by olfedias@microsoft.com)
|
15
|
+
- Bump @fluentui/react-shared-contexts to v9.20.0 ([PR #32067](https://github.com/microsoft/fluentui/pull/32067) by beachball)
|
16
|
+
- Bump @fluentui/react-utilities to v9.18.13 ([PR #32067](https://github.com/microsoft/fluentui/pull/32067) by beachball)
|
17
|
+
|
18
|
+
### Patches
|
19
|
+
|
20
|
+
- fix: improve Web Animations API detection in tests ([PR #32029](https://github.com/microsoft/fluentui/pull/32029) by olfedias@microsoft.com)
|
21
|
+
|
22
|
+
## [9.3.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.3.0)
|
23
|
+
|
24
|
+
Mon, 15 Jul 2024 17:25:35 GMT
|
25
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.2.2..@fluentui/react-motion_v9.3.0)
|
26
|
+
|
27
|
+
### Minor changes
|
28
|
+
|
29
|
+
- feat(motion): add PresenceDirection type ([PR #31958](https://github.com/microsoft/fluentui/pull/31958) by olfedias@microsoft.com)
|
30
|
+
- Bump @fluentui/react-shared-contexts to v9.19.1 ([PR #31998](https://github.com/microsoft/fluentui/pull/31998) by beachball)
|
31
|
+
- Bump @fluentui/react-utilities to v9.18.12 ([PR #31998](https://github.com/microsoft/fluentui/pull/31998) by beachball)
|
32
|
+
|
33
|
+
### Patches
|
34
|
+
|
35
|
+
- fix: revert incorectly set npm versions in all packages ([PR #31937](https://github.com/microsoft/fluentui/pull/31937) by martinhochel@microsoft.com)
|
36
|
+
- feat: add createPresenceComponentVariant() ([PR #31943](https://github.com/microsoft/fluentui/pull/31943) by olfedias@microsoft.com)
|
37
|
+
|
7
38
|
## [9.2.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.2.2)
|
8
39
|
|
9
|
-
Thu, 04 Jul 2024 15:
|
40
|
+
Thu, 04 Jul 2024 15:14:35 GMT
|
10
41
|
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.2.1..@fluentui/react-motion_v9.2.2)
|
11
42
|
|
12
43
|
### Patches
|
package/dist/index.d.ts
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
import * as React_2 from 'react';
|
2
|
+
import { SlotComponentType } from '@fluentui/react-utilities';
|
3
|
+
import { SlotRenderFunction } from '@fluentui/react-utilities';
|
2
4
|
|
3
5
|
export declare type AtomMotion = {
|
4
6
|
keyframes: Keyframe[];
|
@@ -15,7 +17,9 @@ export declare type AtomMotionFn<MotionParams extends Record<string, MotionParam
|
|
15
17
|
*/
|
16
18
|
export declare function createMotionComponent<MotionParams extends Record<string, MotionParam> = {}>(value: AtomMotion | AtomMotion[] | AtomMotionFn<MotionParams>): React_2.FC<MotionComponentProps & MotionParams>;
|
17
19
|
|
18
|
-
export declare function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(value: PresenceMotion | PresenceMotionFn<MotionParams>):
|
20
|
+
export declare function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(value: PresenceMotion | PresenceMotionFn<MotionParams>): PresenceComponent<MotionParams>;
|
21
|
+
|
22
|
+
export declare function createPresenceComponentVariant<MotionParams extends Record<string, MotionParam> = {}>(component: PresenceComponent<MotionParams>, override: PresenceOverride): PresenceComponent<MotionParams>;
|
19
23
|
|
20
24
|
export declare const curves: {
|
21
25
|
readonly curveAccelerateMax: "cubic-bezier(0.9,0.1,1,0.2)";
|
@@ -40,6 +44,11 @@ export declare const durations: {
|
|
40
44
|
readonly durationUltraSlow: 500;
|
41
45
|
};
|
42
46
|
|
47
|
+
/**
|
48
|
+
* @internal A private symbol to store the motion definition on the component for variants.
|
49
|
+
*/
|
50
|
+
declare const MOTION_DEFINITION: unique symbol;
|
51
|
+
|
43
52
|
export declare type MotionComponentProps = {
|
44
53
|
children: React_2.ReactElement;
|
45
54
|
/** Provides imperative controls for the animation. */
|
@@ -103,6 +112,11 @@ export declare const motionTokens: {
|
|
103
112
|
durationUltraSlow: 500;
|
104
113
|
};
|
105
114
|
|
115
|
+
export declare type PresenceComponent<MotionParams extends Record<string, MotionParam> = {}> = {
|
116
|
+
(props: PresenceComponentProps & MotionParams): React_2.ReactElement | null;
|
117
|
+
[MOTION_DEFINITION]: PresenceMotionFn<MotionParams>;
|
118
|
+
};
|
119
|
+
|
106
120
|
export declare type PresenceComponentProps = {
|
107
121
|
/**
|
108
122
|
* By default, the child component won't execute the "enter" motion when it initially mounts, regardless of the value
|
@@ -120,7 +134,7 @@ export declare type PresenceComponentProps = {
|
|
120
134
|
* triggered once all animations have finished with "null" instead of an event object to avoid ambiguity.
|
121
135
|
*/
|
122
136
|
onMotionFinish?: (ev: null, data: {
|
123
|
-
direction:
|
137
|
+
direction: PresenceDirection;
|
124
138
|
}) => void;
|
125
139
|
/**
|
126
140
|
* Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not
|
@@ -130,7 +144,7 @@ export declare type PresenceComponentProps = {
|
|
130
144
|
* triggered once all animations have finished with "null" instead of an event object to avoid ambiguity.
|
131
145
|
*/
|
132
146
|
onMotionCancel?: (ev: null, data: {
|
133
|
-
direction:
|
147
|
+
direction: PresenceDirection;
|
134
148
|
}) => void;
|
135
149
|
/**
|
136
150
|
* Callback that is called when the whole motion starts.
|
@@ -140,7 +154,7 @@ export declare type PresenceComponentProps = {
|
|
140
154
|
* so the callback is triggered with "null".
|
141
155
|
*/
|
142
156
|
onMotionStart?: (ev: null, data: {
|
143
|
-
direction:
|
157
|
+
direction: PresenceDirection;
|
144
158
|
}) => void;
|
145
159
|
/** Defines whether a component is visible; triggers the "enter" or "exit" motions. */
|
146
160
|
visible?: boolean;
|
@@ -151,6 +165,8 @@ export declare type PresenceComponentProps = {
|
|
151
165
|
unmountOnExit?: boolean;
|
152
166
|
};
|
153
167
|
|
168
|
+
export declare type PresenceDirection = 'enter' | 'exit';
|
169
|
+
|
154
170
|
export declare class PresenceGroup extends React_2.Component<PresenceGroupProps, PresenceGroupState> {
|
155
171
|
private mounted;
|
156
172
|
static getDerivedStateFromProps(nextProps: PresenceGroupProps, { childMapping: prevChildMapping, firstRender }: PresenceGroupState): {
|
@@ -182,13 +198,61 @@ declare type PresenceGroupState = {
|
|
182
198
|
firstRender: boolean;
|
183
199
|
};
|
184
200
|
|
185
|
-
export declare type PresenceMotion =
|
186
|
-
enter: AtomMotion | AtomMotion[];
|
187
|
-
exit: AtomMotion | AtomMotion[];
|
188
|
-
};
|
201
|
+
export declare type PresenceMotion = Record<PresenceDirection, AtomMotion | AtomMotion[]>;
|
189
202
|
|
190
203
|
export declare type PresenceMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (params: {
|
191
204
|
element: HTMLElement;
|
192
205
|
} & MotionParams) => PresenceMotion;
|
193
206
|
|
207
|
+
export declare function presenceMotionSlot<MotionParams extends Record<string, MotionParam> = {}>(motion: PresenceMotionSlotProps<MotionParams> | null | undefined, options: {
|
208
|
+
elementType: React_2.FC<PresenceComponentProps & MotionParams>;
|
209
|
+
defaultProps: PresenceMotionSlotRenderProps & MotionParams;
|
210
|
+
}): SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;
|
211
|
+
|
212
|
+
export declare type PresenceMotionSlotProps<MotionParams extends Record<string, MotionParam> = {}> = Pick<PresenceComponentProps, 'imperativeRef' | 'onMotionFinish' | 'onMotionStart'> & {
|
213
|
+
/**
|
214
|
+
* @deprecated Do not use. Presence Motion Slots do not support intrinsic elements.
|
215
|
+
*
|
216
|
+
* If you want to override the animation, use the children render function instead.
|
217
|
+
*/
|
218
|
+
as?: keyof JSX.IntrinsicElements;
|
219
|
+
children?: SlotRenderFunction<PresenceMotionSlotRenderProps & MotionParams & {
|
220
|
+
children: React_2.ReactElement;
|
221
|
+
}>;
|
222
|
+
};
|
223
|
+
|
224
|
+
/**
|
225
|
+
* @internal
|
226
|
+
*/
|
227
|
+
declare type PresenceMotionSlotRenderProps = Pick<PresenceComponentProps, 'appear' | 'onMotionFinish' | 'onMotionStart' | 'unmountOnExit' | 'visible'>;
|
228
|
+
|
229
|
+
/**
|
230
|
+
* @internal
|
231
|
+
*
|
232
|
+
* Override properties for presence transitions.
|
233
|
+
*
|
234
|
+
* @example <caption>Override duration for all transitions</caption>
|
235
|
+
* ```
|
236
|
+
* const override: PresenceOverride = {
|
237
|
+
* all: { duration: 1000 },
|
238
|
+
* };
|
239
|
+
* ```
|
240
|
+
*
|
241
|
+
* @example <caption>Override easing for exit transition</caption>
|
242
|
+
* ```
|
243
|
+
* const override: PresenceOverride = {
|
244
|
+
* exit: { easing: 'ease-out' },
|
245
|
+
* };
|
246
|
+
* ```
|
247
|
+
*/
|
248
|
+
declare type PresenceOverride = Partial<Record<PresenceDirection | 'all', Partial<PresenceOverrideFields>>>;
|
249
|
+
|
250
|
+
/**
|
251
|
+
* @internal
|
252
|
+
*/
|
253
|
+
declare type PresenceOverrideFields = {
|
254
|
+
duration: KeyframeEffectOptions['duration'];
|
255
|
+
easing: KeyframeEffectOptions['easing'];
|
256
|
+
};
|
257
|
+
|
194
258
|
export { }
|
@@ -6,11 +6,14 @@ import { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';
|
|
6
6
|
import { useMountedState } from '../hooks/useMountedState';
|
7
7
|
import { useIsReducedMotion } from '../hooks/useIsReducedMotion';
|
8
8
|
import { getChildElement } from '../utils/getChildElement';
|
9
|
+
/**
|
10
|
+
* @internal A private symbol to store the motion definition on the component for variants.
|
11
|
+
*/ export const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');
|
9
12
|
function shouldSkipAnimation(appear, isFirstMount, visible) {
|
10
13
|
return !appear && isFirstMount && !!visible;
|
11
14
|
}
|
12
15
|
export function createPresenceComponent(value) {
|
13
|
-
|
16
|
+
return Object.assign((props)=>{
|
14
17
|
'use no memo';
|
15
18
|
const itemContext = React.useContext(PresenceGroupChildContext);
|
16
19
|
const merged = {
|
@@ -104,6 +107,9 @@ export function createPresenceComponent(value) {
|
|
104
107
|
});
|
105
108
|
}
|
106
109
|
return null;
|
107
|
-
}
|
108
|
-
|
110
|
+
}, {
|
111
|
+
// Heads up!
|
112
|
+
// Always normalize it to a function to simplify types
|
113
|
+
[MOTION_DEFINITION]: typeof value === 'function' ? value : ()=>value
|
114
|
+
});
|
109
115
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["createPresenceComponent.ts"],"sourcesContent":["import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport { useAnimateAtoms } from '../hooks/useAnimateAtoms';\nimport { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';\nimport { useMountedState } from '../hooks/useMountedState';\nimport { useIsReducedMotion } from '../hooks/useIsReducedMotion';\nimport { getChildElement } from '../utils/getChildElement';\nimport type { MotionParam, PresenceMotion, MotionImperativeRef, PresenceMotionFn } from '../types';\n\nexport type PresenceComponentProps = {\n /**\n * By default, the child component won't execute the \"enter\" motion when it initially mounts, regardless of the value\n * of \"visible\". If you desire this behavior, ensure both \"appear\" and \"visible\" are set to \"true\".\n */\n appear?: boolean;\n\n /** A React element that will be cloned and will have motion effects applied to it. */\n children: React.ReactElement;\n\n /** Provides imperative controls for the animation. */\n imperativeRef?: React.Ref<MotionImperativeRef | undefined>;\n\n /**\n * Callback that is called when the whole motion finishes.\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionFinish?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /**\n * Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not\n * emit a finish event but a specific cancel event\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionCancel?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /**\n * Callback that is called when the whole motion starts.\n *\n * A motion definition can contain multiple animations and therefore multiple \"start\" events. The callback is\n * triggered when the first animation is started. There is no official \"start\" event with the Web Animations API.\n * so the callback is triggered with \"null\".\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionStart?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /** Defines whether a component is visible; triggers the \"enter\" or \"exit\" motions. */\n visible?: boolean;\n\n /**\n * By default, the child component remains mounted after it reaches the \"finished\" state. Set \"unmountOnExit\" if\n * you prefer to unmount the component after it finishes exiting.\n */\n unmountOnExit?: boolean;\n};\n\nfunction shouldSkipAnimation(appear: boolean | undefined, isFirstMount: boolean, visible: boolean | undefined) {\n return !appear && isFirstMount && !!visible;\n}\n\nexport function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(\n value: PresenceMotion | PresenceMotionFn<MotionParams>,\n) {\n const Presence: React.FC<PresenceComponentProps & MotionParams> = props => {\n 'use no memo';\n\n const itemContext = React.useContext(PresenceGroupChildContext);\n const merged = { ...itemContext, ...props };\n\n const {\n appear,\n children,\n imperativeRef,\n onExit,\n onMotionFinish,\n onMotionStart,\n onMotionCancel,\n visible,\n unmountOnExit,\n ..._rest\n } = merged;\n const params = _rest as Exclude<typeof merged, PresenceComponentProps | typeof itemContext>;\n\n const [mounted, setMounted] = useMountedState(visible, unmountOnExit);\n const child = getChildElement(children);\n\n const handleRef = useMotionImperativeRef(imperativeRef);\n const elementRef = React.useRef<HTMLElement>();\n const ref = useMergedRefs(elementRef, child.ref);\n const optionsRef = React.useRef<{ appear?: boolean; params: MotionParams }>({ appear, params });\n\n const animateAtoms = useAnimateAtoms();\n const isFirstMount = useFirstMount();\n const isReducedMotion = useIsReducedMotion();\n\n const handleMotionStart = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionStart?.(null, { direction });\n });\n const handleMotionFinish = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionFinish?.(null, { direction });\n\n if (direction === 'exit' && unmountOnExit) {\n setMounted(false);\n onExit?.();\n }\n });\n\n const handleMotionCancel = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionCancel?.(null, { direction });\n });\n\n useIsomorphicLayoutEffect(() => {\n // Heads up!\n // We store the params in a ref to avoid re-rendering the component when the params change.\n optionsRef.current = { appear, params };\n });\n\n useIsomorphicLayoutEffect(\n () => {\n const element = elementRef.current;\n\n if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {\n return;\n }\n\n const presenceMotion = typeof value === 'function' ? value({ element, ...optionsRef.current.params }) : value;\n const atoms = visible ? presenceMotion.enter : presenceMotion.exit;\n\n const direction = visible ? 'enter' : 'exit';\n const forceFinishMotion = !visible && isFirstMount;\n\n if (!forceFinishMotion) {\n handleMotionStart(direction);\n }\n\n const handle = animateAtoms(element, atoms, { isReducedMotion: isReducedMotion() });\n\n if (forceFinishMotion) {\n // Heads up!\n // .finish() is used there to skip animation on first mount, but apply animation styles immediately\n handle.finish();\n return;\n }\n\n handleRef.current = handle;\n handle.setMotionEndCallbacks(\n () => handleMotionFinish(direction),\n () => handleMotionCancel(direction),\n );\n\n return () => {\n handle.cancel();\n };\n },\n // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [animateAtoms, handleRef, isReducedMotion, handleMotionFinish, handleMotionStart, handleMotionCancel, visible],\n );\n\n if (mounted) {\n return React.cloneElement(child, { ref });\n }\n\n return null;\n };\n\n return Presence;\n}\n"],"names":["useEventCallback","useFirstMount","useIsomorphicLayoutEffect","useMergedRefs","React","PresenceGroupChildContext","useAnimateAtoms","useMotionImperativeRef","useMountedState","useIsReducedMotion","getChildElement","shouldSkipAnimation","appear","isFirstMount","visible","createPresenceComponent","value","Presence","props","itemContext","useContext","merged","children","imperativeRef","onExit","onMotionFinish","onMotionStart","onMotionCancel","unmountOnExit","_rest","params","mounted","setMounted","child","handleRef","elementRef","useRef","ref","optionsRef","animateAtoms","isReducedMotion","handleMotionStart","direction","handleMotionFinish","handleMotionCancel","current","element","presenceMotion","atoms","enter","exit","forceFinishMotion","handle","finish","setMotionEndCallbacks","cancel","cloneElement"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
1
|
+
{"version":3,"sources":["createPresenceComponent.ts"],"sourcesContent":["import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport { useAnimateAtoms } from '../hooks/useAnimateAtoms';\nimport { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';\nimport { useMountedState } from '../hooks/useMountedState';\nimport { useIsReducedMotion } from '../hooks/useIsReducedMotion';\nimport { getChildElement } from '../utils/getChildElement';\nimport type { MotionParam, PresenceMotion, MotionImperativeRef, PresenceMotionFn, PresenceDirection } from '../types';\n\n/**\n * @internal A private symbol to store the motion definition on the component for variants.\n */\nexport const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');\n\nexport type PresenceComponentProps = {\n /**\n * By default, the child component won't execute the \"enter\" motion when it initially mounts, regardless of the value\n * of \"visible\". If you desire this behavior, ensure both \"appear\" and \"visible\" are set to \"true\".\n */\n appear?: boolean;\n\n /** A React element that will be cloned and will have motion effects applied to it. */\n children: React.ReactElement;\n\n /** Provides imperative controls for the animation. */\n imperativeRef?: React.Ref<MotionImperativeRef | undefined>;\n\n /**\n * Callback that is called when the whole motion finishes.\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionFinish?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /**\n * Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not\n * emit a finish event but a specific cancel event\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionCancel?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /**\n * Callback that is called when the whole motion starts.\n *\n * A motion definition can contain multiple animations and therefore multiple \"start\" events. The callback is\n * triggered when the first animation is started. There is no official \"start\" event with the Web Animations API.\n * so the callback is triggered with \"null\".\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionStart?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /** Defines whether a component is visible; triggers the \"enter\" or \"exit\" motions. */\n visible?: boolean;\n\n /**\n * By default, the child component remains mounted after it reaches the \"finished\" state. Set \"unmountOnExit\" if\n * you prefer to unmount the component after it finishes exiting.\n */\n unmountOnExit?: boolean;\n};\n\nexport type PresenceComponent<MotionParams extends Record<string, MotionParam> = {}> = {\n (props: PresenceComponentProps & MotionParams): React.ReactElement | null;\n [MOTION_DEFINITION]: PresenceMotionFn<MotionParams>;\n};\n\nfunction shouldSkipAnimation(appear: boolean | undefined, isFirstMount: boolean, visible: boolean | undefined) {\n return !appear && isFirstMount && !!visible;\n}\n\nexport function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(\n value: PresenceMotion | PresenceMotionFn<MotionParams>,\n): PresenceComponent<MotionParams> {\n return Object.assign(\n (props: PresenceComponentProps & MotionParams) => {\n 'use no memo';\n\n const itemContext = React.useContext(PresenceGroupChildContext);\n const merged = { ...itemContext, ...props };\n\n const {\n appear,\n children,\n imperativeRef,\n onExit,\n onMotionFinish,\n onMotionStart,\n onMotionCancel,\n visible,\n unmountOnExit,\n ..._rest\n } = merged;\n const params = _rest as Exclude<typeof merged, PresenceComponentProps | typeof itemContext>;\n\n const [mounted, setMounted] = useMountedState(visible, unmountOnExit);\n const child = getChildElement(children);\n\n const handleRef = useMotionImperativeRef(imperativeRef);\n const elementRef = React.useRef<HTMLElement>();\n const ref = useMergedRefs(elementRef, child.ref);\n const optionsRef = React.useRef<{ appear?: boolean; params: MotionParams }>({ appear, params });\n\n const animateAtoms = useAnimateAtoms();\n const isFirstMount = useFirstMount();\n const isReducedMotion = useIsReducedMotion();\n\n const handleMotionStart = useEventCallback((direction: PresenceDirection) => {\n onMotionStart?.(null, { direction });\n });\n const handleMotionFinish = useEventCallback((direction: PresenceDirection) => {\n onMotionFinish?.(null, { direction });\n\n if (direction === 'exit' && unmountOnExit) {\n setMounted(false);\n onExit?.();\n }\n });\n\n const handleMotionCancel = useEventCallback((direction: PresenceDirection) => {\n onMotionCancel?.(null, { direction });\n });\n\n useIsomorphicLayoutEffect(() => {\n // Heads up!\n // We store the params in a ref to avoid re-rendering the component when the params change.\n optionsRef.current = { appear, params };\n });\n\n useIsomorphicLayoutEffect(\n () => {\n const element = elementRef.current;\n\n if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {\n return;\n }\n\n const presenceMotion =\n typeof value === 'function' ? value({ element, ...optionsRef.current.params }) : (value as PresenceMotion);\n const atoms = visible ? presenceMotion.enter : presenceMotion.exit;\n\n const direction: PresenceDirection = visible ? 'enter' : 'exit';\n const forceFinishMotion = !visible && isFirstMount;\n\n if (!forceFinishMotion) {\n handleMotionStart(direction);\n }\n\n const handle = animateAtoms(element, atoms, { isReducedMotion: isReducedMotion() });\n\n if (forceFinishMotion) {\n // Heads up!\n // .finish() is used there to skip animation on first mount, but apply animation styles immediately\n handle.finish();\n return;\n }\n\n handleRef.current = handle;\n handle.setMotionEndCallbacks(\n () => handleMotionFinish(direction),\n () => handleMotionCancel(direction),\n );\n\n return () => {\n handle.cancel();\n };\n },\n // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [animateAtoms, handleRef, isReducedMotion, handleMotionFinish, handleMotionStart, handleMotionCancel, visible],\n );\n\n if (mounted) {\n return React.cloneElement(child, { ref });\n }\n\n return null;\n },\n {\n // Heads up!\n // Always normalize it to a function to simplify types\n [MOTION_DEFINITION]: typeof value === 'function' ? value : () => value,\n },\n );\n}\n"],"names":["useEventCallback","useFirstMount","useIsomorphicLayoutEffect","useMergedRefs","React","PresenceGroupChildContext","useAnimateAtoms","useMotionImperativeRef","useMountedState","useIsReducedMotion","getChildElement","MOTION_DEFINITION","Symbol","shouldSkipAnimation","appear","isFirstMount","visible","createPresenceComponent","value","Object","assign","props","itemContext","useContext","merged","children","imperativeRef","onExit","onMotionFinish","onMotionStart","onMotionCancel","unmountOnExit","_rest","params","mounted","setMounted","child","handleRef","elementRef","useRef","ref","optionsRef","animateAtoms","isReducedMotion","handleMotionStart","direction","handleMotionFinish","handleMotionCancel","current","element","presenceMotion","atoms","enter","exit","forceFinishMotion","handle","finish","setMotionEndCallbacks","cancel","cloneElement"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { MOTION_DEFINITION, createPresenceComponent } from './createPresenceComponent';
|
2
|
+
/**
|
3
|
+
* @internal
|
4
|
+
*/ export function overridePresenceMotion(presenceMotion, override) {
|
5
|
+
return (...args)=>{
|
6
|
+
const { enter, exit } = presenceMotion(...args);
|
7
|
+
return {
|
8
|
+
enter: {
|
9
|
+
...enter,
|
10
|
+
...override.all,
|
11
|
+
...override.enter
|
12
|
+
},
|
13
|
+
exit: {
|
14
|
+
...exit,
|
15
|
+
...override.all,
|
16
|
+
...override.exit
|
17
|
+
}
|
18
|
+
};
|
19
|
+
};
|
20
|
+
}
|
21
|
+
export function createPresenceComponentVariant(component, override) {
|
22
|
+
return createPresenceComponent(overridePresenceMotion(component[MOTION_DEFINITION], override));
|
23
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["createPresenceComponentVariant.ts"],"sourcesContent":["import type { MotionParam, PresenceDirection, PresenceMotionFn } from '../types';\nimport { MOTION_DEFINITION, createPresenceComponent, PresenceComponent } from './createPresenceComponent';\n\n/**\n * @internal\n */\ntype PresenceOverrideFields = {\n duration: KeyframeEffectOptions['duration'];\n easing: KeyframeEffectOptions['easing'];\n};\n\n/**\n * @internal\n *\n * Override properties for presence transitions.\n *\n * @example <caption>Override duration for all transitions</caption>\n * ```\n * const override: PresenceOverride = {\n * all: { duration: 1000 },\n * };\n * ```\n *\n * @example <caption>Override easing for exit transition</caption>\n * ```\n * const override: PresenceOverride = {\n * exit: { easing: 'ease-out' },\n * };\n * ```\n */\ntype PresenceOverride = Partial<Record<PresenceDirection | 'all', Partial<PresenceOverrideFields>>>;\n\n/**\n * @internal\n */\nexport function overridePresenceMotion<MotionParams extends Record<string, MotionParam> = {}>(\n presenceMotion: PresenceMotionFn<MotionParams>,\n override: PresenceOverride,\n): PresenceMotionFn<MotionParams> {\n return (...args: Parameters<PresenceMotionFn<MotionParams>>) => {\n const { enter, exit } = presenceMotion(...args);\n\n return {\n enter: { ...enter, ...override.all, ...override.enter },\n exit: { ...exit, ...override.all, ...override.exit },\n };\n };\n}\n\nexport function createPresenceComponentVariant<MotionParams extends Record<string, MotionParam> = {}>(\n component: PresenceComponent<MotionParams>,\n override: PresenceOverride,\n): PresenceComponent<MotionParams> {\n return createPresenceComponent(overridePresenceMotion(component[MOTION_DEFINITION], override));\n}\n"],"names":["MOTION_DEFINITION","createPresenceComponent","overridePresenceMotion","presenceMotion","override","args","enter","exit","all","createPresenceComponentVariant","component"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;","mappings":"AACA,SAASA,iBAAiB,EAAEC,uBAAuB,QAA2B,4BAA4B;AA+B1G;;CAEC,GACD,OAAO,SAASC,uBACdC,cAA8C,EAC9CC,QAA0B;IAE1B,OAAO,CAAC,GAAGC;QACT,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGJ,kBAAkBE;QAE1C,OAAO;YACLC,OAAO;gBAAE,GAAGA,KAAK;gBAAE,GAAGF,SAASI,GAAG;gBAAE,GAAGJ,SAASE,KAAK;YAAC;YACtDC,MAAM;gBAAE,GAAGA,IAAI;gBAAE,GAAGH,SAASI,GAAG;gBAAE,GAAGJ,SAASG,IAAI;YAAC;QACrD;IACF;AACF;AAEA,OAAO,SAASE,+BACdC,SAA0C,EAC1CN,QAA0B;IAE1B,OAAOH,wBAAwBC,uBAAuBQ,SAAS,CAACV,kBAAkB,EAAEI;AACtF"}
|
@@ -1,53 +1,5 @@
|
|
1
|
-
var _document_defaultView;
|
2
1
|
import * as React from 'react';
|
3
|
-
|
4
|
-
const win = typeof document === 'object' ? (_document_defaultView = document.defaultView) === null || _document_defaultView === void 0 ? void 0 : _document_defaultView.window : undefined;
|
5
|
-
// Heads up! "Element." is a side-effect for minifiers, should be kept as IIFE to avoid leaking after minification.
|
6
|
-
const SUPPORTS_WEB_ANIMATIONS = /*@__PURE__*/ (()=>win && typeof win.Element.prototype.animate === 'function')();
|
7
|
-
/**
|
8
|
-
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
|
9
|
-
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
|
10
|
-
*
|
11
|
-
* @see https://github.com/microsoft/fluentui/issues/31701
|
12
|
-
*/ function useAnimateAtomsInTestEnvironment() {
|
13
|
-
const [count, setCount] = React.useState(0);
|
14
|
-
const callbackRef = React.useRef();
|
15
|
-
React.useEffect(()=>{
|
16
|
-
if (count > 0) {
|
17
|
-
var _callbackRef_current;
|
18
|
-
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
|
19
|
-
}
|
20
|
-
}, [
|
21
|
-
count
|
22
|
-
]);
|
23
|
-
return React.useCallback(()=>{
|
24
|
-
return {
|
25
|
-
setMotionEndCallbacks (onfinish) {
|
26
|
-
callbackRef.current = onfinish;
|
27
|
-
setCount((v)=>v + 1);
|
28
|
-
},
|
29
|
-
set playbackRate (rate){
|
30
|
-
/* no-op */ },
|
31
|
-
cancel () {
|
32
|
-
/* no-op */ },
|
33
|
-
pause () {
|
34
|
-
/* no-op */ },
|
35
|
-
play () {
|
36
|
-
/* no-op */ },
|
37
|
-
finish () {
|
38
|
-
/* no-op */ }
|
39
|
-
};
|
40
|
-
}, []);
|
41
|
-
}
|
42
|
-
/**
|
43
|
-
* @internal
|
44
|
-
*/ export function useAnimateAtoms() {
|
45
|
-
'use no memo';
|
46
|
-
if (process.env.NODE_ENV === 'test' && !SUPPORTS_WEB_ANIMATIONS) {
|
47
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
48
|
-
return useAnimateAtomsInTestEnvironment();
|
49
|
-
}
|
50
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
2
|
+
function useAnimateAtomsInSupportedEnvironment() {
|
51
3
|
return React.useCallback((element, value, options)=>{
|
52
4
|
const atoms = Array.isArray(value) ? value : [
|
53
5
|
value
|
@@ -108,3 +60,58 @@ const SUPPORTS_WEB_ANIMATIONS = /*@__PURE__*/ (()=>win && typeof win.Element.pro
|
|
108
60
|
};
|
109
61
|
}, []);
|
110
62
|
}
|
63
|
+
/**
|
64
|
+
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
|
65
|
+
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
|
66
|
+
*
|
67
|
+
* @see https://github.com/microsoft/fluentui/issues/31701
|
68
|
+
*/ function useAnimateAtomsInTestEnvironment() {
|
69
|
+
const [count, setCount] = React.useState(0);
|
70
|
+
const callbackRef = React.useRef();
|
71
|
+
const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();
|
72
|
+
React.useEffect(()=>{
|
73
|
+
if (count > 0) {
|
74
|
+
var _callbackRef_current;
|
75
|
+
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
|
76
|
+
}
|
77
|
+
}, [
|
78
|
+
count
|
79
|
+
]);
|
80
|
+
return React.useCallback((element, value, options)=>{
|
81
|
+
const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';
|
82
|
+
// Heads up!
|
83
|
+
// If the environment supports Web Animations API, we can use the native implementation.
|
84
|
+
if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {
|
85
|
+
return realAnimateAtoms(element, value, options);
|
86
|
+
}
|
87
|
+
return {
|
88
|
+
setMotionEndCallbacks (onfinish) {
|
89
|
+
callbackRef.current = onfinish;
|
90
|
+
setCount((v)=>v + 1);
|
91
|
+
},
|
92
|
+
set playbackRate (rate){
|
93
|
+
/* no-op */ },
|
94
|
+
cancel () {
|
95
|
+
/* no-op */ },
|
96
|
+
pause () {
|
97
|
+
/* no-op */ },
|
98
|
+
play () {
|
99
|
+
/* no-op */ },
|
100
|
+
finish () {
|
101
|
+
/* no-op */ }
|
102
|
+
};
|
103
|
+
}, [
|
104
|
+
realAnimateAtoms
|
105
|
+
]);
|
106
|
+
}
|
107
|
+
/**
|
108
|
+
* @internal
|
109
|
+
*/ export function useAnimateAtoms() {
|
110
|
+
'use no memo';
|
111
|
+
if (process.env.NODE_ENV === 'test') {
|
112
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
113
|
+
return useAnimateAtomsInTestEnvironment();
|
114
|
+
}
|
115
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
116
|
+
return useAnimateAtomsInSupportedEnvironment();
|
117
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["useAnimateAtoms.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, AtomMotion } from '../types';\n\
|
1
|
+
{"version":3,"sources":["useAnimateAtoms.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, AtomMotion } from '../types';\n\nfunction useAnimateAtomsInSupportedEnvironment() {\n return React.useCallback(\n (\n element: HTMLElement,\n value: AtomMotion | AtomMotion[],\n options: {\n isReducedMotion: boolean;\n },\n ): AnimationHandle => {\n const atoms = Array.isArray(value) ? value : [value];\n const { isReducedMotion } = options;\n\n const animations = atoms.map(motion => {\n const { keyframes, ...params } = motion;\n const animation = element.animate(keyframes, {\n fill: 'forwards',\n\n ...params,\n ...(isReducedMotion && { duration: 1 }),\n });\n\n animation.persist();\n\n return animation;\n });\n\n return {\n set playbackRate(rate: number) {\n animations.forEach(animation => {\n animation.playbackRate = rate;\n });\n },\n setMotionEndCallbacks(onfinish: () => void, oncancel: () => void) {\n Promise.all(animations.map(animation => animation.finished))\n .then(() => {\n onfinish();\n })\n .catch((err: unknown) => {\n const DOMException = element.ownerDocument.defaultView?.DOMException;\n\n // Ignores \"DOMException: The user aborted a request\" that appears if animations are cancelled\n if (DOMException && err instanceof DOMException && err.name === 'AbortError') {\n oncancel();\n return;\n }\n\n throw err;\n });\n },\n\n cancel: () => {\n animations.forEach(animation => {\n animation.cancel();\n });\n },\n pause: () => {\n animations.forEach(animation => {\n animation.pause();\n });\n },\n play: () => {\n animations.forEach(animation => {\n animation.play();\n });\n },\n finish: () => {\n animations.forEach(animation => {\n animation.finish();\n });\n },\n };\n },\n [],\n );\n}\n\n/**\n * In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary\n * to ensure that the callback is not executed synchronously, which would cause the test to fail.\n *\n * @see https://github.com/microsoft/fluentui/issues/31701\n */\nfunction useAnimateAtomsInTestEnvironment() {\n const [count, setCount] = React.useState(0);\n const callbackRef = React.useRef<() => void>();\n\n const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();\n\n React.useEffect(() => {\n if (count > 0) {\n callbackRef.current?.();\n }\n }, [count]);\n\n return React.useCallback(\n (\n element: HTMLElement,\n value: AtomMotion | AtomMotion[],\n options: {\n isReducedMotion: boolean;\n },\n ): AnimationHandle => {\n const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';\n\n // Heads up!\n // If the environment supports Web Animations API, we can use the native implementation.\n if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {\n return realAnimateAtoms(element, value, options);\n }\n\n return {\n setMotionEndCallbacks(onfinish: () => void) {\n callbackRef.current = onfinish;\n setCount(v => v + 1);\n },\n\n set playbackRate(rate: number) {\n /* no-op */\n },\n cancel() {\n /* no-op */\n },\n pause() {\n /* no-op */\n },\n play() {\n /* no-op */\n },\n finish() {\n /* no-op */\n },\n };\n },\n [realAnimateAtoms],\n );\n}\n\n/**\n * @internal\n */\nexport function useAnimateAtoms() {\n 'use no memo';\n\n if (process.env.NODE_ENV === 'test') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useAnimateAtomsInTestEnvironment();\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useAnimateAtomsInSupportedEnvironment();\n}\n"],"names":["React","useAnimateAtomsInSupportedEnvironment","useCallback","element","value","options","atoms","Array","isArray","isReducedMotion","animations","map","motion","keyframes","params","animation","animate","fill","duration","persist","playbackRate","rate","forEach","setMotionEndCallbacks","onfinish","oncancel","Promise","all","finished","then","catch","err","DOMException","ownerDocument","defaultView","name","cancel","pause","play","finish","useAnimateAtomsInTestEnvironment","count","setCount","useState","callbackRef","useRef","realAnimateAtoms","useEffect","current","ELEMENT_SUPPORTS_WEB_ANIMATIONS","v","useAnimateAtoms","process","env","NODE_ENV"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B,SAASC;IACP,OAAOD,MAAME,WAAW,CACtB,CACEC,SACAC,OACAC;QAIA,MAAMC,QAAQC,MAAMC,OAAO,CAACJ,SAASA,QAAQ;YAACA;SAAM;QACpD,MAAM,EAAEK,eAAe,EAAE,GAAGJ;QAE5B,MAAMK,aAAaJ,MAAMK,GAAG,CAACC,CAAAA;YAC3B,MAAM,EAAEC,SAAS,EAAE,GAAGC,QAAQ,GAAGF;YACjC,MAAMG,YAAYZ,QAAQa,OAAO,CAACH,WAAW;gBAC3CI,MAAM;gBAEN,GAAGH,MAAM;gBACT,GAAIL,mBAAmB;oBAAES,UAAU;gBAAE,CAAC;YACxC;YAEAH,UAAUI,OAAO;YAEjB,OAAOJ;QACT;QAEA,OAAO;YACL,IAAIK,cAAaC,KAAc;gBAC7BX,WAAWY,OAAO,CAACP,CAAAA;oBACjBA,UAAUK,YAAY,GAAGC;gBAC3B;YACF;YACAE,uBAAsBC,QAAoB,EAAEC,QAAoB;gBAC9DC,QAAQC,GAAG,CAACjB,WAAWC,GAAG,CAACI,CAAAA,YAAaA,UAAUa,QAAQ,GACvDC,IAAI,CAAC;oBACJL;gBACF,GACCM,KAAK,CAAC,CAACC;wBACe5B;oBAArB,MAAM6B,gBAAe7B,qCAAAA,QAAQ8B,aAAa,CAACC,WAAW,cAAjC/B,yDAAAA,mCAAmC6B,YAAY;oBAEpE,8FAA8F;oBAC9F,IAAIA,gBAAgBD,eAAeC,gBAAgBD,IAAII,IAAI,KAAK,cAAc;wBAC5EV;wBACA;oBACF;oBAEA,MAAMM;gBACR;YACJ;YAEAK,QAAQ;gBACN1B,WAAWY,OAAO,CAACP,CAAAA;oBACjBA,UAAUqB,MAAM;gBAClB;YACF;YACAC,OAAO;gBACL3B,WAAWY,OAAO,CAACP,CAAAA;oBACjBA,UAAUsB,KAAK;gBACjB;YACF;YACAC,MAAM;gBACJ5B,WAAWY,OAAO,CAACP,CAAAA;oBACjBA,UAAUuB,IAAI;gBAChB;YACF;YACAC,QAAQ;gBACN7B,WAAWY,OAAO,CAACP,CAAAA;oBACjBA,UAAUwB,MAAM;gBAClB;YACF;QACF;IACF,GACA,EAAE;AAEN;AAEA;;;;;CAKC,GACD,SAASC;IACP,MAAM,CAACC,OAAOC,SAAS,GAAG1C,MAAM2C,QAAQ,CAAC;IACzC,MAAMC,cAAc5C,MAAM6C,MAAM;IAEhC,MAAMC,mBAAmB7C;IAEzBD,MAAM+C,SAAS,CAAC;QACd,IAAIN,QAAQ,GAAG;gBACbG;aAAAA,uBAAAA,YAAYI,OAAO,cAAnBJ,2CAAAA,0BAAAA;QACF;IACF,GAAG;QAACH;KAAM;IAEV,OAAOzC,MAAME,WAAW,CACtB,CACEC,SACAC,OACAC;QAIA,MAAM4C,kCAAkC,OAAO9C,QAAQa,OAAO,KAAK;QAEnE,YAAY;QACZ,wFAAwF;QACxF,IAAIiC,iCAAiC;YACnC,OAAOH,iBAAiB3C,SAASC,OAAOC;QAC1C;QAEA,OAAO;YACLkB,uBAAsBC,QAAoB;gBACxCoB,YAAYI,OAAO,GAAGxB;gBACtBkB,SAASQ,CAAAA,IAAKA,IAAI;YACpB;YAEA,IAAI9B,cAAaC,KAAc;YAC7B,SAAS,GACX;YACAe;YACE,SAAS,GACX;YACAC;YACE,SAAS,GACX;YACAC;YACE,SAAS,GACX;YACAC;YACE,SAAS,GACX;QACF;IACF,GACA;QAACO;KAAiB;AAEtB;AAEA;;CAEC,GACD,OAAO,SAASK;IACd;IAEA,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,QAAQ;QACnC,sDAAsD;QACtD,OAAOd;IACT;IAEA,sDAAsD;IACtD,OAAOvC;AACT"}
|
package/lib/index.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
export { motionTokens, durations, curves } from './motions/motionTokens';
|
2
2
|
export { createMotionComponent } from './factories/createMotionComponent';
|
3
3
|
export { createPresenceComponent } from './factories/createPresenceComponent';
|
4
|
+
export { createPresenceComponentVariant } from './factories/createPresenceComponentVariant';
|
4
5
|
export { PresenceGroup } from './components/PresenceGroup';
|
6
|
+
export { presenceMotionSlot } from './slots/presenceMotionSlot';
|
package/lib/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["index.ts"],"sourcesContent":["export { motionTokens, durations, curves } from './motions/motionTokens';\n\nexport { createMotionComponent, type MotionComponentProps } from './factories/createMotionComponent';\nexport {
|
1
|
+
{"version":3,"sources":["index.ts"],"sourcesContent":["export { motionTokens, durations, curves } from './motions/motionTokens';\n\nexport { createMotionComponent, type MotionComponentProps } from './factories/createMotionComponent';\nexport {\n createPresenceComponent,\n type PresenceComponentProps,\n type PresenceComponent,\n} from './factories/createPresenceComponent';\nexport { createPresenceComponentVariant } from './factories/createPresenceComponentVariant';\n\nexport { PresenceGroup } from './components/PresenceGroup';\n\nexport { presenceMotionSlot, type PresenceMotionSlotProps } from './slots/presenceMotionSlot';\n\nexport type {\n AtomMotion,\n AtomMotionFn,\n PresenceMotion,\n PresenceMotionFn,\n PresenceDirection,\n MotionImperativeRef,\n} from './types';\n"],"names":["motionTokens","durations","curves","createMotionComponent","createPresenceComponent","createPresenceComponentVariant","PresenceGroup","presenceMotionSlot"],"rangeMappings":";;;;;","mappings":"AAAA,SAASA,YAAY,EAAEC,SAAS,EAAEC,MAAM,QAAQ,yBAAyB;AAEzE,SAASC,qBAAqB,QAAmC,oCAAoC;AACrG,SACEC,uBAAuB,QAGlB,sCAAsC;AAC7C,SAASC,8BAA8B,QAAQ,6CAA6C;AAE5F,SAASC,aAAa,QAAQ,6BAA6B;AAE3D,SAASC,kBAAkB,QAAsC,6BAA6B"}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from '@fluentui/react-utilities';
|
2
|
+
import * as React from 'react';
|
3
|
+
export function presenceMotionSlot(motion, options) {
|
4
|
+
// eslint-disable-next-line deprecation/deprecation
|
5
|
+
const { as, children, ...rest } = motion !== null && motion !== void 0 ? motion : {};
|
6
|
+
if (process.env.NODE_ENV !== 'production') {
|
7
|
+
if (typeof as !== 'undefined') {
|
8
|
+
throw new Error(`@fluentui/react-motion: "as" property is not supported on motion slots.`);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
if (motion === null) {
|
12
|
+
// Heads up!
|
13
|
+
// Render function is used there to avoid rendering a motion component and handle unmounting logic
|
14
|
+
const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;
|
15
|
+
const renderFn = (_, props)=>isUnmounted ? null : /*#__PURE__*/ React.createElement(React.Fragment, null, props.children);
|
16
|
+
/**
|
17
|
+
* Casting is required here as SlotComponentType is a function, not an object.
|
18
|
+
* Although SlotComponentType has a function signature, it is still just an object.
|
19
|
+
* This is required to make a slot callable (JSX compatible), this is the exact same approach
|
20
|
+
* that is used on `@types/react` components
|
21
|
+
*/ return {
|
22
|
+
[SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,
|
23
|
+
[SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
|
24
|
+
};
|
25
|
+
}
|
26
|
+
/**
|
27
|
+
* Casting is required here as SlotComponentType is a function, not an object.
|
28
|
+
* Although SlotComponentType has a function signature, it is still just an object.
|
29
|
+
* This is required to make a slot callable (JSX compatible), this is the exact same approach
|
30
|
+
* that is used on `@types/react` components
|
31
|
+
*/ const propsWithMetadata = {
|
32
|
+
...options.defaultProps,
|
33
|
+
...rest,
|
34
|
+
[SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
|
35
|
+
};
|
36
|
+
if (typeof children === 'function') {
|
37
|
+
propsWithMetadata[SLOT_RENDER_FUNCTION_SYMBOL] = children;
|
38
|
+
}
|
39
|
+
return propsWithMetadata;
|
40
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["presenceMotionSlot.tsx"],"sourcesContent":["import {\n SLOT_ELEMENT_TYPE_SYMBOL,\n SLOT_RENDER_FUNCTION_SYMBOL,\n type SlotComponentType,\n type SlotRenderFunction,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { PresenceComponentProps } from '../factories/createPresenceComponent';\nimport type { MotionParam } from '../types';\n\n/**\n * @internal\n */\ntype PresenceMotionSlotRenderProps = Pick<\n PresenceComponentProps,\n 'appear' | 'onMotionFinish' | 'onMotionStart' | 'unmountOnExit' | 'visible'\n>;\n\nexport type PresenceMotionSlotProps<MotionParams extends Record<string, MotionParam> = {}> = Pick<\n PresenceComponentProps,\n 'imperativeRef' | 'onMotionFinish' | 'onMotionStart'\n> & {\n // FIXME: 'as' property is required by design on the slot AP but it does not support components, only intrinsic\n // elements motion slots do not support intrinsic elements, only custom components.\n /**\n * @deprecated Do not use. Presence Motion Slots do not support intrinsic elements.\n *\n * If you want to override the animation, use the children render function instead.\n */\n as?: keyof JSX.IntrinsicElements;\n\n // TODO: remove once React v18 slot API is modified ComponentProps is not properly adding render function as a\n // possible value for children\n children?: SlotRenderFunction<PresenceMotionSlotRenderProps & MotionParams & { children: React.ReactElement }>;\n};\n\nexport function presenceMotionSlot<MotionParams extends Record<string, MotionParam> = {}>(\n motion: PresenceMotionSlotProps<MotionParams> | null | undefined,\n options: {\n elementType: React.FC<PresenceComponentProps & MotionParams>;\n defaultProps: PresenceMotionSlotRenderProps & MotionParams;\n },\n): SlotComponentType<PresenceMotionSlotRenderProps & MotionParams> {\n // eslint-disable-next-line deprecation/deprecation\n const { as, children, ...rest } = motion ?? {};\n\n if (process.env.NODE_ENV !== 'production') {\n if (typeof as !== 'undefined') {\n throw new Error(`@fluentui/react-motion: \"as\" property is not supported on motion slots.`);\n }\n }\n\n if (motion === null) {\n // Heads up!\n // Render function is used there to avoid rendering a motion component and handle unmounting logic\n const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;\n const renderFn: SlotRenderFunction<\n PresenceMotionSlotRenderProps & MotionParams & { children: React.ReactElement }\n > = (_, props) => (isUnmounted ? null : <>{props.children}</>);\n\n /**\n * Casting is required here as SlotComponentType is a function, not an object.\n * Although SlotComponentType has a function signature, it is still just an object.\n * This is required to make a slot callable (JSX compatible), this is the exact same approach\n * that is used on `@types/react` components\n */\n return {\n [SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,\n [SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType,\n } as SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;\n }\n\n /**\n * Casting is required here as SlotComponentType is a function, not an object.\n * Although SlotComponentType has a function signature, it is still just an object.\n * This is required to make a slot callable (JSX compatible), this is the exact same approach\n * that is used on `@types/react` components\n */\n const propsWithMetadata = {\n ...options.defaultProps,\n ...rest,\n [SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType,\n } as SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;\n\n if (typeof children === 'function') {\n propsWithMetadata[SLOT_RENDER_FUNCTION_SYMBOL] = children as SlotRenderFunction<\n PresenceMotionSlotRenderProps & MotionParams\n >;\n }\n\n return propsWithMetadata;\n}\n"],"names":["SLOT_ELEMENT_TYPE_SYMBOL","SLOT_RENDER_FUNCTION_SYMBOL","React","presenceMotionSlot","motion","options","as","children","rest","process","env","NODE_ENV","Error","isUnmounted","defaultProps","visible","unmountOnExit","renderFn","_","props","elementType","propsWithMetadata"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SACEA,wBAAwB,EACxBC,2BAA2B,QAGtB,4BAA4B;AACnC,YAAYC,WAAW,QAAQ;AA+B/B,OAAO,SAASC,mBACdC,MAAgE,EAChEC,OAGC;IAED,mDAAmD;IACnD,MAAM,EAAEC,EAAE,EAAEC,QAAQ,EAAE,GAAGC,MAAM,GAAGJ,mBAAAA,oBAAAA,SAAU,CAAC;IAE7C,IAAIK,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,IAAI,OAAOL,OAAO,aAAa;YAC7B,MAAM,IAAIM,MAAM,CAAC,uEAAuE,CAAC;QAC3F;IACF;IAEA,IAAIR,WAAW,MAAM;QACnB,YAAY;QACZ,kGAAkG;QAClG,MAAMS,cAAc,CAACR,QAAQS,YAAY,CAACC,OAAO,IAAIV,QAAQS,YAAY,CAACE,aAAa;QACvF,MAAMC,WAEF,CAACC,GAAGC,QAAWN,cAAc,qBAAO,0CAAGM,MAAMZ,QAAQ;QAEzD;;;;;KAKC,GACD,OAAO;YACL,CAACN,4BAA4B,EAAEgB;YAC/B,CAACjB,yBAAyB,EAAEK,QAAQe,WAAW;QACjD;IACF;IAEA;;;;;GAKC,GACD,MAAMC,oBAAoB;QACxB,GAAGhB,QAAQS,YAAY;QACvB,GAAGN,IAAI;QACP,CAACR,yBAAyB,EAAEK,QAAQe,WAAW;IACjD;IAEA,IAAI,OAAOb,aAAa,YAAY;QAClCc,iBAAiB,CAACpB,4BAA4B,GAAGM;IAGnD;IAEA,OAAOc;AACT"}
|
package/lib/types.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["types.ts"],"sourcesContent":["export type AtomMotion = { keyframes: Keyframe[] } & KeyframeEffectOptions;\n\nexport type
|
1
|
+
{"version":3,"sources":["types.ts"],"sourcesContent":["export type AtomMotion = { keyframes: Keyframe[] } & KeyframeEffectOptions;\n\nexport type PresenceDirection = 'enter' | 'exit';\n\nexport type PresenceMotion = Record<PresenceDirection, AtomMotion | AtomMotion[]>;\n\n/**\n * @internal\n *\n * A motion param should be a primitive value that can be serialized to JSON and could be potentially used a plain\n * dependency for React hooks.\n */\nexport type MotionParam = boolean | number | string;\n\nexport type AtomMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (\n params: { element: HTMLElement } & MotionParams,\n) => AtomMotion | AtomMotion[];\n\nexport type PresenceMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (\n params: { element: HTMLElement } & MotionParams,\n) => PresenceMotion;\n\n// ---\n\nexport type AnimationHandle = Pick<Animation, 'cancel' | 'finish' | 'pause' | 'play' | 'playbackRate'> & {\n setMotionEndCallbacks: (onfinish: () => void, oncancel: () => void) => void;\n};\n\nexport type MotionImperativeRef = {\n /** Sets the playback rate of the animation, where 1 is normal speed. */\n setPlaybackRate: (rate: number) => void;\n\n /** Sets the state of the animation to running or paused. */\n setPlayState: (state: 'running' | 'paused') => void;\n};\n"],"names":[],"rangeMappings":"","mappings":"AA4BA,WAME"}
|
@@ -2,9 +2,17 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
3
3
|
value: true
|
4
4
|
});
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
function _export(target, all) {
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
7
|
+
enumerable: true,
|
8
|
+
get: all[name]
|
9
|
+
});
|
10
|
+
}
|
11
|
+
_export(exports, {
|
12
|
+
MOTION_DEFINITION: function() {
|
13
|
+
return MOTION_DEFINITION;
|
14
|
+
},
|
15
|
+
createPresenceComponent: function() {
|
8
16
|
return createPresenceComponent;
|
9
17
|
}
|
10
18
|
});
|
@@ -17,11 +25,12 @@ const _useMotionImperativeRef = require("../hooks/useMotionImperativeRef");
|
|
17
25
|
const _useMountedState = require("../hooks/useMountedState");
|
18
26
|
const _useIsReducedMotion = require("../hooks/useIsReducedMotion");
|
19
27
|
const _getChildElement = require("../utils/getChildElement");
|
28
|
+
const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');
|
20
29
|
function shouldSkipAnimation(appear, isFirstMount, visible) {
|
21
30
|
return !appear && isFirstMount && !!visible;
|
22
31
|
}
|
23
32
|
function createPresenceComponent(value) {
|
24
|
-
|
33
|
+
return Object.assign((props)=>{
|
25
34
|
'use no memo';
|
26
35
|
const itemContext = _react.useContext(_PresenceGroupChildContext.PresenceGroupChildContext);
|
27
36
|
const merged = {
|
@@ -114,6 +123,9 @@ function createPresenceComponent(value) {
|
|
114
123
|
});
|
115
124
|
}
|
116
125
|
return null;
|
117
|
-
}
|
118
|
-
|
126
|
+
}, {
|
127
|
+
// Heads up!
|
128
|
+
// Always normalize it to a function to simplify types
|
129
|
+
[MOTION_DEFINITION]: typeof value === 'function' ? value : ()=>value
|
130
|
+
});
|
119
131
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["createPresenceComponent.ts"],"sourcesContent":["import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport { useAnimateAtoms } from '../hooks/useAnimateAtoms';\nimport { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';\nimport { useMountedState } from '../hooks/useMountedState';\nimport { useIsReducedMotion } from '../hooks/useIsReducedMotion';\nimport { getChildElement } from '../utils/getChildElement';\nimport type { MotionParam, PresenceMotion, MotionImperativeRef, PresenceMotionFn } from '../types';\n\nexport type PresenceComponentProps = {\n /**\n * By default, the child component won't execute the \"enter\" motion when it initially mounts, regardless of the value\n * of \"visible\". If you desire this behavior, ensure both \"appear\" and \"visible\" are set to \"true\".\n */\n appear?: boolean;\n\n /** A React element that will be cloned and will have motion effects applied to it. */\n children: React.ReactElement;\n\n /** Provides imperative controls for the animation. */\n imperativeRef?: React.Ref<MotionImperativeRef | undefined>;\n\n /**\n * Callback that is called when the whole motion finishes.\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionFinish?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /**\n * Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not\n * emit a finish event but a specific cancel event\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionCancel?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /**\n * Callback that is called when the whole motion starts.\n *\n * A motion definition can contain multiple animations and therefore multiple \"start\" events. The callback is\n * triggered when the first animation is started. There is no official \"start\" event with the Web Animations API.\n * so the callback is triggered with \"null\".\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionStart?: (ev: null, data: { direction: 'enter' | 'exit' }) => void;\n\n /** Defines whether a component is visible; triggers the \"enter\" or \"exit\" motions. */\n visible?: boolean;\n\n /**\n * By default, the child component remains mounted after it reaches the \"finished\" state. Set \"unmountOnExit\" if\n * you prefer to unmount the component after it finishes exiting.\n */\n unmountOnExit?: boolean;\n};\n\nfunction shouldSkipAnimation(appear: boolean | undefined, isFirstMount: boolean, visible: boolean | undefined) {\n return !appear && isFirstMount && !!visible;\n}\n\nexport function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(\n value: PresenceMotion | PresenceMotionFn<MotionParams>,\n) {\n const Presence: React.FC<PresenceComponentProps & MotionParams> = props => {\n 'use no memo';\n\n const itemContext = React.useContext(PresenceGroupChildContext);\n const merged = { ...itemContext, ...props };\n\n const {\n appear,\n children,\n imperativeRef,\n onExit,\n onMotionFinish,\n onMotionStart,\n onMotionCancel,\n visible,\n unmountOnExit,\n ..._rest\n } = merged;\n const params = _rest as Exclude<typeof merged, PresenceComponentProps | typeof itemContext>;\n\n const [mounted, setMounted] = useMountedState(visible, unmountOnExit);\n const child = getChildElement(children);\n\n const handleRef = useMotionImperativeRef(imperativeRef);\n const elementRef = React.useRef<HTMLElement>();\n const ref = useMergedRefs(elementRef, child.ref);\n const optionsRef = React.useRef<{ appear?: boolean; params: MotionParams }>({ appear, params });\n\n const animateAtoms = useAnimateAtoms();\n const isFirstMount = useFirstMount();\n const isReducedMotion = useIsReducedMotion();\n\n const handleMotionStart = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionStart?.(null, { direction });\n });\n const handleMotionFinish = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionFinish?.(null, { direction });\n\n if (direction === 'exit' && unmountOnExit) {\n setMounted(false);\n onExit?.();\n }\n });\n\n const handleMotionCancel = useEventCallback((direction: 'enter' | 'exit') => {\n onMotionCancel?.(null, { direction });\n });\n\n useIsomorphicLayoutEffect(() => {\n // Heads up!\n // We store the params in a ref to avoid re-rendering the component when the params change.\n optionsRef.current = { appear, params };\n });\n\n useIsomorphicLayoutEffect(\n () => {\n const element = elementRef.current;\n\n if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {\n return;\n }\n\n const presenceMotion = typeof value === 'function' ? value({ element, ...optionsRef.current.params }) : value;\n const atoms = visible ? presenceMotion.enter : presenceMotion.exit;\n\n const direction = visible ? 'enter' : 'exit';\n const forceFinishMotion = !visible && isFirstMount;\n\n if (!forceFinishMotion) {\n handleMotionStart(direction);\n }\n\n const handle = animateAtoms(element, atoms, { isReducedMotion: isReducedMotion() });\n\n if (forceFinishMotion) {\n // Heads up!\n // .finish() is used there to skip animation on first mount, but apply animation styles immediately\n handle.finish();\n return;\n }\n\n handleRef.current = handle;\n handle.setMotionEndCallbacks(\n () => handleMotionFinish(direction),\n () => handleMotionCancel(direction),\n );\n\n return () => {\n handle.cancel();\n };\n },\n // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [animateAtoms, handleRef, isReducedMotion, handleMotionFinish, handleMotionStart, handleMotionCancel, visible],\n );\n\n if (mounted) {\n return React.cloneElement(child, { ref });\n }\n\n return null;\n };\n\n return Presence;\n}\n"],"names":["createPresenceComponent","shouldSkipAnimation","appear","isFirstMount","visible","value","Presence","props","itemContext","React","useContext","PresenceGroupChildContext","merged","children","imperativeRef","onExit","onMotionFinish","onMotionStart","onMotionCancel","unmountOnExit","_rest","params","mounted","setMounted","useMountedState","child","getChildElement","handleRef","useMotionImperativeRef","elementRef","useRef","ref","useMergedRefs","optionsRef","animateAtoms","useAnimateAtoms","useFirstMount","isReducedMotion","useIsReducedMotion","handleMotionStart","useEventCallback","direction","handleMotionFinish","handleMotionCancel","useIsomorphicLayoutEffect","current","element","presenceMotion","atoms","enter","exit","forceFinishMotion","handle","finish","setMotionEndCallbacks","cancel","cloneElement"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
1
|
+
{"version":3,"sources":["createPresenceComponent.ts"],"sourcesContent":["import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport { useAnimateAtoms } from '../hooks/useAnimateAtoms';\nimport { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';\nimport { useMountedState } from '../hooks/useMountedState';\nimport { useIsReducedMotion } from '../hooks/useIsReducedMotion';\nimport { getChildElement } from '../utils/getChildElement';\nimport type { MotionParam, PresenceMotion, MotionImperativeRef, PresenceMotionFn, PresenceDirection } from '../types';\n\n/**\n * @internal A private symbol to store the motion definition on the component for variants.\n */\nexport const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');\n\nexport type PresenceComponentProps = {\n /**\n * By default, the child component won't execute the \"enter\" motion when it initially mounts, regardless of the value\n * of \"visible\". If you desire this behavior, ensure both \"appear\" and \"visible\" are set to \"true\".\n */\n appear?: boolean;\n\n /** A React element that will be cloned and will have motion effects applied to it. */\n children: React.ReactElement;\n\n /** Provides imperative controls for the animation. */\n imperativeRef?: React.Ref<MotionImperativeRef | undefined>;\n\n /**\n * Callback that is called when the whole motion finishes.\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionFinish?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /**\n * Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not\n * emit a finish event but a specific cancel event\n *\n * A motion definition can contain multiple animations and therefore multiple \"finish\" events. The callback is\n * triggered once all animations have finished with \"null\" instead of an event object to avoid ambiguity.\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionCancel?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /**\n * Callback that is called when the whole motion starts.\n *\n * A motion definition can contain multiple animations and therefore multiple \"start\" events. The callback is\n * triggered when the first animation is started. There is no official \"start\" event with the Web Animations API.\n * so the callback is triggered with \"null\".\n */\n // eslint-disable-next-line @nx/workspace-consistent-callback-type -- EventHandler<T> does not support \"null\"\n onMotionStart?: (ev: null, data: { direction: PresenceDirection }) => void;\n\n /** Defines whether a component is visible; triggers the \"enter\" or \"exit\" motions. */\n visible?: boolean;\n\n /**\n * By default, the child component remains mounted after it reaches the \"finished\" state. Set \"unmountOnExit\" if\n * you prefer to unmount the component after it finishes exiting.\n */\n unmountOnExit?: boolean;\n};\n\nexport type PresenceComponent<MotionParams extends Record<string, MotionParam> = {}> = {\n (props: PresenceComponentProps & MotionParams): React.ReactElement | null;\n [MOTION_DEFINITION]: PresenceMotionFn<MotionParams>;\n};\n\nfunction shouldSkipAnimation(appear: boolean | undefined, isFirstMount: boolean, visible: boolean | undefined) {\n return !appear && isFirstMount && !!visible;\n}\n\nexport function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(\n value: PresenceMotion | PresenceMotionFn<MotionParams>,\n): PresenceComponent<MotionParams> {\n return Object.assign(\n (props: PresenceComponentProps & MotionParams) => {\n 'use no memo';\n\n const itemContext = React.useContext(PresenceGroupChildContext);\n const merged = { ...itemContext, ...props };\n\n const {\n appear,\n children,\n imperativeRef,\n onExit,\n onMotionFinish,\n onMotionStart,\n onMotionCancel,\n visible,\n unmountOnExit,\n ..._rest\n } = merged;\n const params = _rest as Exclude<typeof merged, PresenceComponentProps | typeof itemContext>;\n\n const [mounted, setMounted] = useMountedState(visible, unmountOnExit);\n const child = getChildElement(children);\n\n const handleRef = useMotionImperativeRef(imperativeRef);\n const elementRef = React.useRef<HTMLElement>();\n const ref = useMergedRefs(elementRef, child.ref);\n const optionsRef = React.useRef<{ appear?: boolean; params: MotionParams }>({ appear, params });\n\n const animateAtoms = useAnimateAtoms();\n const isFirstMount = useFirstMount();\n const isReducedMotion = useIsReducedMotion();\n\n const handleMotionStart = useEventCallback((direction: PresenceDirection) => {\n onMotionStart?.(null, { direction });\n });\n const handleMotionFinish = useEventCallback((direction: PresenceDirection) => {\n onMotionFinish?.(null, { direction });\n\n if (direction === 'exit' && unmountOnExit) {\n setMounted(false);\n onExit?.();\n }\n });\n\n const handleMotionCancel = useEventCallback((direction: PresenceDirection) => {\n onMotionCancel?.(null, { direction });\n });\n\n useIsomorphicLayoutEffect(() => {\n // Heads up!\n // We store the params in a ref to avoid re-rendering the component when the params change.\n optionsRef.current = { appear, params };\n });\n\n useIsomorphicLayoutEffect(\n () => {\n const element = elementRef.current;\n\n if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {\n return;\n }\n\n const presenceMotion =\n typeof value === 'function' ? value({ element, ...optionsRef.current.params }) : (value as PresenceMotion);\n const atoms = visible ? presenceMotion.enter : presenceMotion.exit;\n\n const direction: PresenceDirection = visible ? 'enter' : 'exit';\n const forceFinishMotion = !visible && isFirstMount;\n\n if (!forceFinishMotion) {\n handleMotionStart(direction);\n }\n\n const handle = animateAtoms(element, atoms, { isReducedMotion: isReducedMotion() });\n\n if (forceFinishMotion) {\n // Heads up!\n // .finish() is used there to skip animation on first mount, but apply animation styles immediately\n handle.finish();\n return;\n }\n\n handleRef.current = handle;\n handle.setMotionEndCallbacks(\n () => handleMotionFinish(direction),\n () => handleMotionCancel(direction),\n );\n\n return () => {\n handle.cancel();\n };\n },\n // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [animateAtoms, handleRef, isReducedMotion, handleMotionFinish, handleMotionStart, handleMotionCancel, visible],\n );\n\n if (mounted) {\n return React.cloneElement(child, { ref });\n }\n\n return null;\n },\n {\n // Heads up!\n // Always normalize it to a function to simplify types\n [MOTION_DEFINITION]: typeof value === 'function' ? value : () => value,\n },\n );\n}\n"],"names":["MOTION_DEFINITION","createPresenceComponent","Symbol","shouldSkipAnimation","appear","isFirstMount","visible","value","Object","assign","props","itemContext","React","useContext","PresenceGroupChildContext","merged","children","imperativeRef","onExit","onMotionFinish","onMotionStart","onMotionCancel","unmountOnExit","_rest","params","mounted","setMounted","useMountedState","child","getChildElement","handleRef","useMotionImperativeRef","elementRef","useRef","ref","useMergedRefs","optionsRef","animateAtoms","useAnimateAtoms","useFirstMount","isReducedMotion","useIsReducedMotion","handleMotionStart","useEventCallback","direction","handleMotionFinish","handleMotionCancel","useIsomorphicLayoutEffect","current","element","presenceMotion","atoms","enter","exit","forceFinishMotion","handle","finish","setMotionEndCallbacks","cancel","cloneElement"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
3
|
+
value: true
|
4
|
+
});
|
5
|
+
function _export(target, all) {
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
7
|
+
enumerable: true,
|
8
|
+
get: all[name]
|
9
|
+
});
|
10
|
+
}
|
11
|
+
_export(exports, {
|
12
|
+
createPresenceComponentVariant: function() {
|
13
|
+
return createPresenceComponentVariant;
|
14
|
+
},
|
15
|
+
overridePresenceMotion: function() {
|
16
|
+
return overridePresenceMotion;
|
17
|
+
}
|
18
|
+
});
|
19
|
+
const _createPresenceComponent = require("./createPresenceComponent");
|
20
|
+
function overridePresenceMotion(presenceMotion, override) {
|
21
|
+
return (...args)=>{
|
22
|
+
const { enter, exit } = presenceMotion(...args);
|
23
|
+
return {
|
24
|
+
enter: {
|
25
|
+
...enter,
|
26
|
+
...override.all,
|
27
|
+
...override.enter
|
28
|
+
},
|
29
|
+
exit: {
|
30
|
+
...exit,
|
31
|
+
...override.all,
|
32
|
+
...override.exit
|
33
|
+
}
|
34
|
+
};
|
35
|
+
};
|
36
|
+
}
|
37
|
+
function createPresenceComponentVariant(component, override) {
|
38
|
+
return (0, _createPresenceComponent.createPresenceComponent)(overridePresenceMotion(component[_createPresenceComponent.MOTION_DEFINITION], override));
|
39
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["createPresenceComponentVariant.ts"],"sourcesContent":["import type { MotionParam, PresenceDirection, PresenceMotionFn } from '../types';\nimport { MOTION_DEFINITION, createPresenceComponent, PresenceComponent } from './createPresenceComponent';\n\n/**\n * @internal\n */\ntype PresenceOverrideFields = {\n duration: KeyframeEffectOptions['duration'];\n easing: KeyframeEffectOptions['easing'];\n};\n\n/**\n * @internal\n *\n * Override properties for presence transitions.\n *\n * @example <caption>Override duration for all transitions</caption>\n * ```\n * const override: PresenceOverride = {\n * all: { duration: 1000 },\n * };\n * ```\n *\n * @example <caption>Override easing for exit transition</caption>\n * ```\n * const override: PresenceOverride = {\n * exit: { easing: 'ease-out' },\n * };\n * ```\n */\ntype PresenceOverride = Partial<Record<PresenceDirection | 'all', Partial<PresenceOverrideFields>>>;\n\n/**\n * @internal\n */\nexport function overridePresenceMotion<MotionParams extends Record<string, MotionParam> = {}>(\n presenceMotion: PresenceMotionFn<MotionParams>,\n override: PresenceOverride,\n): PresenceMotionFn<MotionParams> {\n return (...args: Parameters<PresenceMotionFn<MotionParams>>) => {\n const { enter, exit } = presenceMotion(...args);\n\n return {\n enter: { ...enter, ...override.all, ...override.enter },\n exit: { ...exit, ...override.all, ...override.exit },\n };\n };\n}\n\nexport function createPresenceComponentVariant<MotionParams extends Record<string, MotionParam> = {}>(\n component: PresenceComponent<MotionParams>,\n override: PresenceOverride,\n): PresenceComponent<MotionParams> {\n return createPresenceComponent(overridePresenceMotion(component[MOTION_DEFINITION], override));\n}\n"],"names":["createPresenceComponentVariant","overridePresenceMotion","presenceMotion","override","args","enter","exit","all","component","createPresenceComponent","MOTION_DEFINITION"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IAiDgBA,8BAAAA;eAAAA;;IAdAC,sBAAAA;eAAAA;;;yCAlC8D;AAkCvE,SAASA,uBACdC,cAA8C,EAC9CC,QAA0B;IAE1B,OAAO,CAAC,GAAGC;QACT,MAAM,EAAEC,KAAK,EAAEC,IAAI,EAAE,GAAGJ,kBAAkBE;QAE1C,OAAO;YACLC,OAAO;gBAAE,GAAGA,KAAK;gBAAE,GAAGF,SAASI,GAAG;gBAAE,GAAGJ,SAASE,KAAK;YAAC;YACtDC,MAAM;gBAAE,GAAGA,IAAI;gBAAE,GAAGH,SAASI,GAAG;gBAAE,GAAGJ,SAASG,IAAI;YAAC;QACrD;IACF;AACF;AAEO,SAASN,+BACdQ,SAA0C,EAC1CL,QAA0B;IAE1B,OAAOM,IAAAA,gDAAAA,EAAwBR,uBAAuBO,SAAS,CAACE,0CAAAA,CAAkB,EAAEP;AACtF"}
|
@@ -10,53 +10,7 @@ Object.defineProperty(exports, "useAnimateAtoms", {
|
|
10
10
|
});
|
11
11
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
12
12
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
13
|
-
|
14
|
-
// eslint-disable-next-line no-restricted-globals
|
15
|
-
const win = typeof document === 'object' ? (_document_defaultView = document.defaultView) === null || _document_defaultView === void 0 ? void 0 : _document_defaultView.window : undefined;
|
16
|
-
// Heads up! "Element." is a side-effect for minifiers, should be kept as IIFE to avoid leaking after minification.
|
17
|
-
const SUPPORTS_WEB_ANIMATIONS = /*@__PURE__*/ (()=>win && typeof win.Element.prototype.animate === 'function')();
|
18
|
-
/**
|
19
|
-
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
|
20
|
-
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
|
21
|
-
*
|
22
|
-
* @see https://github.com/microsoft/fluentui/issues/31701
|
23
|
-
*/ function useAnimateAtomsInTestEnvironment() {
|
24
|
-
const [count, setCount] = _react.useState(0);
|
25
|
-
const callbackRef = _react.useRef();
|
26
|
-
_react.useEffect(()=>{
|
27
|
-
if (count > 0) {
|
28
|
-
var _callbackRef_current;
|
29
|
-
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
|
30
|
-
}
|
31
|
-
}, [
|
32
|
-
count
|
33
|
-
]);
|
34
|
-
return _react.useCallback(()=>{
|
35
|
-
return {
|
36
|
-
setMotionEndCallbacks (onfinish) {
|
37
|
-
callbackRef.current = onfinish;
|
38
|
-
setCount((v)=>v + 1);
|
39
|
-
},
|
40
|
-
set playbackRate (rate){
|
41
|
-
/* no-op */ },
|
42
|
-
cancel () {
|
43
|
-
/* no-op */ },
|
44
|
-
pause () {
|
45
|
-
/* no-op */ },
|
46
|
-
play () {
|
47
|
-
/* no-op */ },
|
48
|
-
finish () {
|
49
|
-
/* no-op */ }
|
50
|
-
};
|
51
|
-
}, []);
|
52
|
-
}
|
53
|
-
function useAnimateAtoms() {
|
54
|
-
'use no memo';
|
55
|
-
if (process.env.NODE_ENV === 'test' && !SUPPORTS_WEB_ANIMATIONS) {
|
56
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
57
|
-
return useAnimateAtomsInTestEnvironment();
|
58
|
-
}
|
59
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
13
|
+
function useAnimateAtomsInSupportedEnvironment() {
|
60
14
|
return _react.useCallback((element, value, options)=>{
|
61
15
|
const atoms = Array.isArray(value) ? value : [
|
62
16
|
value
|
@@ -117,3 +71,56 @@ function useAnimateAtoms() {
|
|
117
71
|
};
|
118
72
|
}, []);
|
119
73
|
}
|
74
|
+
/**
|
75
|
+
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
|
76
|
+
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
|
77
|
+
*
|
78
|
+
* @see https://github.com/microsoft/fluentui/issues/31701
|
79
|
+
*/ function useAnimateAtomsInTestEnvironment() {
|
80
|
+
const [count, setCount] = _react.useState(0);
|
81
|
+
const callbackRef = _react.useRef();
|
82
|
+
const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();
|
83
|
+
_react.useEffect(()=>{
|
84
|
+
if (count > 0) {
|
85
|
+
var _callbackRef_current;
|
86
|
+
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
|
87
|
+
}
|
88
|
+
}, [
|
89
|
+
count
|
90
|
+
]);
|
91
|
+
return _react.useCallback((element, value, options)=>{
|
92
|
+
const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';
|
93
|
+
// Heads up!
|
94
|
+
// If the environment supports Web Animations API, we can use the native implementation.
|
95
|
+
if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {
|
96
|
+
return realAnimateAtoms(element, value, options);
|
97
|
+
}
|
98
|
+
return {
|
99
|
+
setMotionEndCallbacks (onfinish) {
|
100
|
+
callbackRef.current = onfinish;
|
101
|
+
setCount((v)=>v + 1);
|
102
|
+
},
|
103
|
+
set playbackRate (rate){
|
104
|
+
/* no-op */ },
|
105
|
+
cancel () {
|
106
|
+
/* no-op */ },
|
107
|
+
pause () {
|
108
|
+
/* no-op */ },
|
109
|
+
play () {
|
110
|
+
/* no-op */ },
|
111
|
+
finish () {
|
112
|
+
/* no-op */ }
|
113
|
+
};
|
114
|
+
}, [
|
115
|
+
realAnimateAtoms
|
116
|
+
]);
|
117
|
+
}
|
118
|
+
function useAnimateAtoms() {
|
119
|
+
'use no memo';
|
120
|
+
if (process.env.NODE_ENV === 'test') {
|
121
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
122
|
+
return useAnimateAtomsInTestEnvironment();
|
123
|
+
}
|
124
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
125
|
+
return useAnimateAtomsInSupportedEnvironment();
|
126
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["useAnimateAtoms.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, AtomMotion } from '../types';\n\
|
1
|
+
{"version":3,"sources":["useAnimateAtoms.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, AtomMotion } from '../types';\n\nfunction useAnimateAtomsInSupportedEnvironment() {\n return React.useCallback(\n (\n element: HTMLElement,\n value: AtomMotion | AtomMotion[],\n options: {\n isReducedMotion: boolean;\n },\n ): AnimationHandle => {\n const atoms = Array.isArray(value) ? value : [value];\n const { isReducedMotion } = options;\n\n const animations = atoms.map(motion => {\n const { keyframes, ...params } = motion;\n const animation = element.animate(keyframes, {\n fill: 'forwards',\n\n ...params,\n ...(isReducedMotion && { duration: 1 }),\n });\n\n animation.persist();\n\n return animation;\n });\n\n return {\n set playbackRate(rate: number) {\n animations.forEach(animation => {\n animation.playbackRate = rate;\n });\n },\n setMotionEndCallbacks(onfinish: () => void, oncancel: () => void) {\n Promise.all(animations.map(animation => animation.finished))\n .then(() => {\n onfinish();\n })\n .catch((err: unknown) => {\n const DOMException = element.ownerDocument.defaultView?.DOMException;\n\n // Ignores \"DOMException: The user aborted a request\" that appears if animations are cancelled\n if (DOMException && err instanceof DOMException && err.name === 'AbortError') {\n oncancel();\n return;\n }\n\n throw err;\n });\n },\n\n cancel: () => {\n animations.forEach(animation => {\n animation.cancel();\n });\n },\n pause: () => {\n animations.forEach(animation => {\n animation.pause();\n });\n },\n play: () => {\n animations.forEach(animation => {\n animation.play();\n });\n },\n finish: () => {\n animations.forEach(animation => {\n animation.finish();\n });\n },\n };\n },\n [],\n );\n}\n\n/**\n * In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary\n * to ensure that the callback is not executed synchronously, which would cause the test to fail.\n *\n * @see https://github.com/microsoft/fluentui/issues/31701\n */\nfunction useAnimateAtomsInTestEnvironment() {\n const [count, setCount] = React.useState(0);\n const callbackRef = React.useRef<() => void>();\n\n const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();\n\n React.useEffect(() => {\n if (count > 0) {\n callbackRef.current?.();\n }\n }, [count]);\n\n return React.useCallback(\n (\n element: HTMLElement,\n value: AtomMotion | AtomMotion[],\n options: {\n isReducedMotion: boolean;\n },\n ): AnimationHandle => {\n const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';\n\n // Heads up!\n // If the environment supports Web Animations API, we can use the native implementation.\n if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {\n return realAnimateAtoms(element, value, options);\n }\n\n return {\n setMotionEndCallbacks(onfinish: () => void) {\n callbackRef.current = onfinish;\n setCount(v => v + 1);\n },\n\n set playbackRate(rate: number) {\n /* no-op */\n },\n cancel() {\n /* no-op */\n },\n pause() {\n /* no-op */\n },\n play() {\n /* no-op */\n },\n finish() {\n /* no-op */\n },\n };\n },\n [realAnimateAtoms],\n );\n}\n\n/**\n * @internal\n */\nexport function useAnimateAtoms() {\n 'use no memo';\n\n if (process.env.NODE_ENV === 'test') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useAnimateAtomsInTestEnvironment();\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useAnimateAtomsInSupportedEnvironment();\n}\n"],"names":["useAnimateAtoms","useAnimateAtomsInSupportedEnvironment","React","useCallback","element","value","options","atoms","Array","isArray","isReducedMotion","animations","map","motion","keyframes","params","animation","animate","fill","duration","persist","playbackRate","rate","forEach","setMotionEndCallbacks","onfinish","oncancel","Promise","all","finished","then","catch","err","DOMException","ownerDocument","defaultView","name","cancel","pause","play","finish","useAnimateAtomsInTestEnvironment","count","setCount","useState","callbackRef","useRef","realAnimateAtoms","useEffect","current","ELEMENT_SUPPORTS_WEB_ANIMATIONS","v","process","env","NODE_ENV"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
package/lib-commonjs/index.js
CHANGED
@@ -18,6 +18,9 @@ _export(exports, {
|
|
18
18
|
createPresenceComponent: function() {
|
19
19
|
return _createPresenceComponent.createPresenceComponent;
|
20
20
|
},
|
21
|
+
createPresenceComponentVariant: function() {
|
22
|
+
return _createPresenceComponentVariant.createPresenceComponentVariant;
|
23
|
+
},
|
21
24
|
curves: function() {
|
22
25
|
return _motionTokens.curves;
|
23
26
|
},
|
@@ -26,9 +29,14 @@ _export(exports, {
|
|
26
29
|
},
|
27
30
|
motionTokens: function() {
|
28
31
|
return _motionTokens.motionTokens;
|
32
|
+
},
|
33
|
+
presenceMotionSlot: function() {
|
34
|
+
return _presenceMotionSlot.presenceMotionSlot;
|
29
35
|
}
|
30
36
|
});
|
31
37
|
const _motionTokens = require("./motions/motionTokens");
|
32
38
|
const _createMotionComponent = require("./factories/createMotionComponent");
|
33
39
|
const _createPresenceComponent = require("./factories/createPresenceComponent");
|
40
|
+
const _createPresenceComponentVariant = require("./factories/createPresenceComponentVariant");
|
34
41
|
const _PresenceGroup = require("./components/PresenceGroup");
|
42
|
+
const _presenceMotionSlot = require("./slots/presenceMotionSlot");
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["index.ts"],"sourcesContent":["export { motionTokens, durations, curves } from './motions/motionTokens';\n\nexport { createMotionComponent, type MotionComponentProps } from './factories/createMotionComponent';\nexport {
|
1
|
+
{"version":3,"sources":["index.ts"],"sourcesContent":["export { motionTokens, durations, curves } from './motions/motionTokens';\n\nexport { createMotionComponent, type MotionComponentProps } from './factories/createMotionComponent';\nexport {\n createPresenceComponent,\n type PresenceComponentProps,\n type PresenceComponent,\n} from './factories/createPresenceComponent';\nexport { createPresenceComponentVariant } from './factories/createPresenceComponentVariant';\n\nexport { PresenceGroup } from './components/PresenceGroup';\n\nexport { presenceMotionSlot, type PresenceMotionSlotProps } from './slots/presenceMotionSlot';\n\nexport type {\n AtomMotion,\n AtomMotionFn,\n PresenceMotion,\n PresenceMotionFn,\n PresenceDirection,\n MotionImperativeRef,\n} from './types';\n"],"names":["PresenceGroup","createMotionComponent","createPresenceComponent","createPresenceComponentVariant","curves","durations","motionTokens","presenceMotionSlot"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IAUSA,aAAa;eAAbA,4BAAa;;IARbC,qBAAqB;eAArBA,4CAAqB;;IAE5BC,uBAAuB;eAAvBA,gDAAuB;;IAIhBC,8BAA8B;eAA9BA,8DAA8B;;IARLC,MAAM;eAANA,oBAAM;;IAAjBC,SAAS;eAATA,uBAAS;;IAAvBC,YAAY;eAAZA,0BAAY;;IAYZC,kBAAkB;eAAlBA,sCAAkB;;;8BAZqB;uCAEiB;yCAK1D;gDACwC;+BAEjB;oCAEmC"}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
3
|
+
value: true
|
4
|
+
});
|
5
|
+
Object.defineProperty(exports, "presenceMotionSlot", {
|
6
|
+
enumerable: true,
|
7
|
+
get: function() {
|
8
|
+
return presenceMotionSlot;
|
9
|
+
}
|
10
|
+
});
|
11
|
+
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
12
|
+
const _reactutilities = require("@fluentui/react-utilities");
|
13
|
+
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
14
|
+
function presenceMotionSlot(motion, options) {
|
15
|
+
// eslint-disable-next-line deprecation/deprecation
|
16
|
+
const { as, children, ...rest } = motion !== null && motion !== void 0 ? motion : {};
|
17
|
+
if (process.env.NODE_ENV !== 'production') {
|
18
|
+
if (typeof as !== 'undefined') {
|
19
|
+
throw new Error(`@fluentui/react-motion: "as" property is not supported on motion slots.`);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
if (motion === null) {
|
23
|
+
// Heads up!
|
24
|
+
// Render function is used there to avoid rendering a motion component and handle unmounting logic
|
25
|
+
const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;
|
26
|
+
const renderFn = (_, props)=>isUnmounted ? null : /*#__PURE__*/ _react.createElement(_react.Fragment, null, props.children);
|
27
|
+
/**
|
28
|
+
* Casting is required here as SlotComponentType is a function, not an object.
|
29
|
+
* Although SlotComponentType has a function signature, it is still just an object.
|
30
|
+
* This is required to make a slot callable (JSX compatible), this is the exact same approach
|
31
|
+
* that is used on `@types/react` components
|
32
|
+
*/ return {
|
33
|
+
[_reactutilities.SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,
|
34
|
+
[_reactutilities.SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
|
35
|
+
};
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Casting is required here as SlotComponentType is a function, not an object.
|
39
|
+
* Although SlotComponentType has a function signature, it is still just an object.
|
40
|
+
* This is required to make a slot callable (JSX compatible), this is the exact same approach
|
41
|
+
* that is used on `@types/react` components
|
42
|
+
*/ const propsWithMetadata = {
|
43
|
+
...options.defaultProps,
|
44
|
+
...rest,
|
45
|
+
[_reactutilities.SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
|
46
|
+
};
|
47
|
+
if (typeof children === 'function') {
|
48
|
+
propsWithMetadata[_reactutilities.SLOT_RENDER_FUNCTION_SYMBOL] = children;
|
49
|
+
}
|
50
|
+
return propsWithMetadata;
|
51
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["presenceMotionSlot.tsx"],"sourcesContent":["import {\n SLOT_ELEMENT_TYPE_SYMBOL,\n SLOT_RENDER_FUNCTION_SYMBOL,\n type SlotComponentType,\n type SlotRenderFunction,\n} from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nimport type { PresenceComponentProps } from '../factories/createPresenceComponent';\nimport type { MotionParam } from '../types';\n\n/**\n * @internal\n */\ntype PresenceMotionSlotRenderProps = Pick<\n PresenceComponentProps,\n 'appear' | 'onMotionFinish' | 'onMotionStart' | 'unmountOnExit' | 'visible'\n>;\n\nexport type PresenceMotionSlotProps<MotionParams extends Record<string, MotionParam> = {}> = Pick<\n PresenceComponentProps,\n 'imperativeRef' | 'onMotionFinish' | 'onMotionStart'\n> & {\n // FIXME: 'as' property is required by design on the slot AP but it does not support components, only intrinsic\n // elements motion slots do not support intrinsic elements, only custom components.\n /**\n * @deprecated Do not use. Presence Motion Slots do not support intrinsic elements.\n *\n * If you want to override the animation, use the children render function instead.\n */\n as?: keyof JSX.IntrinsicElements;\n\n // TODO: remove once React v18 slot API is modified ComponentProps is not properly adding render function as a\n // possible value for children\n children?: SlotRenderFunction<PresenceMotionSlotRenderProps & MotionParams & { children: React.ReactElement }>;\n};\n\nexport function presenceMotionSlot<MotionParams extends Record<string, MotionParam> = {}>(\n motion: PresenceMotionSlotProps<MotionParams> | null | undefined,\n options: {\n elementType: React.FC<PresenceComponentProps & MotionParams>;\n defaultProps: PresenceMotionSlotRenderProps & MotionParams;\n },\n): SlotComponentType<PresenceMotionSlotRenderProps & MotionParams> {\n // eslint-disable-next-line deprecation/deprecation\n const { as, children, ...rest } = motion ?? {};\n\n if (process.env.NODE_ENV !== 'production') {\n if (typeof as !== 'undefined') {\n throw new Error(`@fluentui/react-motion: \"as\" property is not supported on motion slots.`);\n }\n }\n\n if (motion === null) {\n // Heads up!\n // Render function is used there to avoid rendering a motion component and handle unmounting logic\n const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;\n const renderFn: SlotRenderFunction<\n PresenceMotionSlotRenderProps & MotionParams & { children: React.ReactElement }\n > = (_, props) => (isUnmounted ? null : <>{props.children}</>);\n\n /**\n * Casting is required here as SlotComponentType is a function, not an object.\n * Although SlotComponentType has a function signature, it is still just an object.\n * This is required to make a slot callable (JSX compatible), this is the exact same approach\n * that is used on `@types/react` components\n */\n return {\n [SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,\n [SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType,\n } as SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;\n }\n\n /**\n * Casting is required here as SlotComponentType is a function, not an object.\n * Although SlotComponentType has a function signature, it is still just an object.\n * This is required to make a slot callable (JSX compatible), this is the exact same approach\n * that is used on `@types/react` components\n */\n const propsWithMetadata = {\n ...options.defaultProps,\n ...rest,\n [SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType,\n } as SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;\n\n if (typeof children === 'function') {\n propsWithMetadata[SLOT_RENDER_FUNCTION_SYMBOL] = children as SlotRenderFunction<\n PresenceMotionSlotRenderProps & MotionParams\n >;\n }\n\n return propsWithMetadata;\n}\n"],"names":["presenceMotionSlot","motion","options","as","children","rest","process","env","NODE_ENV","Error","isUnmounted","defaultProps","visible","unmountOnExit","renderFn","_","props","React","createElement","Fragment","SLOT_RENDER_FUNCTION_SYMBOL","SLOT_ELEMENT_TYPE_SYMBOL","elementType","propsWithMetadata"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAqCgBA;;;eAAAA;;;;gCAhCT;iEACgB;AA+BhB,SAASA,mBACdC,MAAgE,EAChEC,OAGC;IAED,mDAAmD;IACnD,MAAM,EAAEC,EAAE,EAAEC,QAAQ,EAAE,GAAGC,MAAM,GAAGJ,WAAAA,QAAAA,WAAAA,KAAAA,IAAAA,SAAU,CAAC;IAE7C,IAAIK,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,IAAI,OAAOL,OAAO,aAAa;YAC7B,MAAM,IAAIM,MAAM,CAAC,uEAAuE,CAAC;QAC3F;IACF;IAEA,IAAIR,WAAW,MAAM;QACnB,YAAY;QACZ,kGAAkG;QAClG,MAAMS,cAAc,CAACR,QAAQS,YAAY,CAACC,OAAO,IAAIV,QAAQS,YAAY,CAACE,aAAa;QACvF,MAAMC,WAEF,CAACC,GAAGC,QAAWN,cAAc,OAAA,WAAA,GAAOO,OAAAC,aAAA,CAAAD,OAAAE,QAAA,EAAA,MAAGH,MAAMZ,QAAQ;QAEzD;;;;;KAKC,GACD,OAAO;YACL,CAACgB,2CAAAA,CAA4B,EAAEN;YAC/B,CAACO,wCAAAA,CAAyB,EAAEnB,QAAQoB,WAAW;QACjD;IACF;IAEA;;;;;GAKC,GACD,MAAMC,oBAAoB;QACxB,GAAGrB,QAAQS,YAAY;QACvB,GAAGN,IAAI;QACP,CAACgB,wCAAAA,CAAyB,EAAEnB,QAAQoB,WAAW;IACjD;IAEA,IAAI,OAAOlB,aAAa,YAAY;QAClCmB,iBAAiB,CAACH,2CAAAA,CAA4B,GAAGhB;IAGnD;IAEA,OAAOmB;AACT"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["types.ts"],"sourcesContent":["export type AtomMotion = { keyframes: Keyframe[] } & KeyframeEffectOptions;\n\nexport type
|
1
|
+
{"version":3,"sources":["types.ts"],"sourcesContent":["export type AtomMotion = { keyframes: Keyframe[] } & KeyframeEffectOptions;\n\nexport type PresenceDirection = 'enter' | 'exit';\n\nexport type PresenceMotion = Record<PresenceDirection, AtomMotion | AtomMotion[]>;\n\n/**\n * @internal\n *\n * A motion param should be a primitive value that can be serialized to JSON and could be potentially used a plain\n * dependency for React hooks.\n */\nexport type MotionParam = boolean | number | string;\n\nexport type AtomMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (\n params: { element: HTMLElement } & MotionParams,\n) => AtomMotion | AtomMotion[];\n\nexport type PresenceMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (\n params: { element: HTMLElement } & MotionParams,\n) => PresenceMotion;\n\n// ---\n\nexport type AnimationHandle = Pick<Animation, 'cancel' | 'finish' | 'pause' | 'play' | 'playbackRate'> & {\n setMotionEndCallbacks: (onfinish: () => void, oncancel: () => void) => void;\n};\n\nexport type MotionImperativeRef = {\n /** Sets the playback rate of the animation, where 1 is normal speed. */\n setPlaybackRate: (rate: number) => void;\n\n /** Sets the state of the animation to running or paused. */\n setPlayState: (state: 'running' | 'paused') => void;\n};\n"],"names":[],"rangeMappings":"","mappings":""}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fluentui/react-motion",
|
3
|
-
"version": "9.
|
3
|
+
"version": "9.4.0",
|
4
4
|
"description": "A package with utilities & motion definitions using Web Animations API",
|
5
5
|
"main": "lib-commonjs/index.js",
|
6
6
|
"module": "lib/index.js",
|
@@ -39,15 +39,15 @@
|
|
39
39
|
"@fluentui/scripts-cypress": "*"
|
40
40
|
},
|
41
41
|
"dependencies": {
|
42
|
-
"@fluentui/react-shared-contexts": "^9.
|
43
|
-
"@fluentui/react-utilities": "^9.18.
|
42
|
+
"@fluentui/react-shared-contexts": "^9.20.0",
|
43
|
+
"@fluentui/react-utilities": "^9.18.13",
|
44
44
|
"@swc/helpers": "^0.5.1",
|
45
45
|
"react-is": "^17.0.2"
|
46
46
|
},
|
47
47
|
"peerDependencies": {
|
48
48
|
"@types/react": ">=16.8.0 <19.0.0",
|
49
49
|
"@types/react-dom": ">=16.8.0 <19.0.0",
|
50
|
-
"react": ">=16.
|
50
|
+
"react": ">=16.14.0 <19.0.0",
|
51
51
|
"react-dom": ">=16.8.0 <19.0.0"
|
52
52
|
},
|
53
53
|
"exports": {
|