@fluentui/react-motion
Advanced tools
Comparing version 0.0.0-nightly-20240611-0405.1 to 0.0.0-nightly-20240612-0406.1
# Change Log - @fluentui/react-motion | ||
This log was last generated on Tue, 11 Jun 2024 04:27:07 GMT and should not be manually modified. | ||
This log was last generated on Wed, 12 Jun 2024 04:38:03 GMT and should not be manually modified. | ||
<!-- Start content --> | ||
## [0.0.0-nightly-20240611-0405.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v0.0.0-nightly-20240611-0405.1) | ||
## [0.0.0-nightly-20240612-0406.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v0.0.0-nightly-20240612-0406.1) | ||
Tue, 11 Jun 2024 04:27:07 GMT | ||
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.0.0..@fluentui/react-motion_v0.0.0-nightly-20240611-0405.1) | ||
Wed, 12 Jun 2024 04:38:03 GMT | ||
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.0.0..@fluentui/react-motion_v0.0.0-nightly-20240612-0406.1) | ||
@@ -15,6 +15,6 @@ ### Changes | ||
- Release nightly v9 ([commit](https://github.com/microsoft/fluentui/commit/not available) by fluentui-internal@service.microsoft.com) | ||
- Bump @fluentui/react-shared-contexts to v0.0.0-nightly-20240611-0405.1 ([commit](https://github.com/microsoft/fluentui/commit/4ef532d4ea602209862433c87282ba8a014e7cc7) by beachball) | ||
- Bump @fluentui/react-utilities to v0.0.0-nightly-20240611-0405.1 ([commit](https://github.com/microsoft/fluentui/commit/4ef532d4ea602209862433c87282ba8a014e7cc7) by beachball) | ||
- Bump @fluentui/react-conformance to v0.0.0-nightly-20240611-0405.1 ([commit](https://github.com/microsoft/fluentui/commit/4ef532d4ea602209862433c87282ba8a014e7cc7) by beachball) | ||
- Bump @fluentui/react-conformance-griffel to v0.0.0-nightly-20240611-0405.1 ([commit](https://github.com/microsoft/fluentui/commit/4ef532d4ea602209862433c87282ba8a014e7cc7) by beachball) | ||
- Bump @fluentui/react-shared-contexts to v0.0.0-nightly-20240612-0406.1 ([commit](https://github.com/microsoft/fluentui/commit/5e64ebc04978f88db6123a96a08163c1f1bede48) by beachball) | ||
- Bump @fluentui/react-utilities to v0.0.0-nightly-20240612-0406.1 ([commit](https://github.com/microsoft/fluentui/commit/5e64ebc04978f88db6123a96a08163c1f1bede48) by beachball) | ||
- Bump @fluentui/react-conformance to v0.0.0-nightly-20240612-0406.1 ([commit](https://github.com/microsoft/fluentui/commit/5e64ebc04978f88db6123a96a08163c1f1bede48) by beachball) | ||
- Bump @fluentui/react-conformance-griffel to v0.0.0-nightly-20240612-0406.1 ([commit](https://github.com/microsoft/fluentui/commit/5e64ebc04978f88db6123a96a08163c1f1bede48) by beachball) | ||
@@ -21,0 +21,0 @@ ## [9.0.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.0.0) |
@@ -7,5 +7,5 @@ import * as React_2 from 'react'; | ||
export declare type AtomMotionFn = (params: { | ||
export declare type AtomMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (params: { | ||
element: HTMLElement; | ||
}) => AtomMotion | AtomMotion[]; | ||
} & MotionParams) => AtomMotion | AtomMotion[]; | ||
@@ -17,5 +17,5 @@ /** | ||
*/ | ||
export declare function createMotionComponent(value: AtomMotion | AtomMotion[] | AtomMotionFn): React_2.FC<MotionComponentProps>; | ||
export declare function createMotionComponent<MotionParams extends Record<string, MotionParam> = {}>(value: AtomMotion | AtomMotion[] | AtomMotionFn<MotionParams>): React_2.FC<MotionComponentProps & MotionParams>; | ||
export declare function createPresenceComponent(value: PresenceMotion | PresenceMotionFn): React_2.FC<PresenceComponentProps>; | ||
export declare function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(value: PresenceMotion | PresenceMotionFn<MotionParams>): React_2.FC<PresenceComponentProps & MotionParams>; | ||
@@ -49,2 +49,17 @@ export declare const curves: { | ||
imperativeRef?: React_2.Ref<MotionImperativeRef | undefined>; | ||
/** | ||
* Callback that is called when the whole motion finishes. | ||
* | ||
* A motion definition can contain multiple animations and therefore multiple "finish" events. The callback is | ||
* triggered once all animations have finished with "null" instead of an event object to avoid ambiguity. | ||
*/ | ||
onMotionFinish?: (ev: null) => void; | ||
/** | ||
* Callback that is called when the whole motion starts. | ||
* | ||
* A motion definition can contain multiple animations and therefore multiple "start" events. The callback is | ||
* triggered when the first animation is started. There is no official "start" event with the Web Animations API. | ||
* so the callback is triggered with "null". | ||
*/ | ||
onMotionStart?: (ev: null) => void; | ||
}; | ||
@@ -59,2 +74,10 @@ | ||
/** | ||
* @internal | ||
* | ||
* A motion param should be a primitive value that can be serialized to JSON and could be potentially used a plain | ||
* dependency for React hooks. | ||
*/ | ||
declare type MotionParam = boolean | number | string; | ||
export declare const motionTokens: { | ||
@@ -99,2 +122,12 @@ curveAccelerateMax: "cubic-bezier(0.9,0.1,1,0.2)"; | ||
}) => void; | ||
/** | ||
* Callback that is called when the whole motion starts. | ||
* | ||
* A motion definition can contain multiple animations and therefore multiple "start" events. The callback is | ||
* triggered when the first animation is started. There is no official "start" event with the Web Animations API. | ||
* so the callback is triggered with "null". | ||
*/ | ||
onMotionStart?: (ev: null, data: { | ||
direction: 'enter' | 'exit'; | ||
}) => void; | ||
/** Defines whether a component is visible; triggers the "enter" or "exit" motions. */ | ||
@@ -145,6 +178,6 @@ visible?: boolean; | ||
export declare type PresenceMotionFn = (params: { | ||
export declare type PresenceMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (params: { | ||
element: HTMLElement; | ||
}) => PresenceMotion; | ||
} & MotionParams) => PresenceMotion; | ||
export { } |
@@ -20,16 +20,32 @@ "use strict"; | ||
const Atom = (props)=>{ | ||
const { children, imperativeRef } = props; | ||
const { children, imperativeRef, onMotionFinish: onMotionFinishProp, onMotionStart: onMotionStartProp, ..._rest } = props; | ||
const params = _rest; | ||
const child = (0, _getChildElement.getChildElement)(children); | ||
const handleRef = (0, _useMotionImperativeRef.useMotionImperativeRef)(imperativeRef); | ||
const elementRef = _react.useRef(); | ||
const paramsRef = _react.useRef(params); | ||
const isReducedMotion = (0, _useIsReducedMotion.useIsReducedMotion)(); | ||
const onMotionStart = (0, _reactutilities.useEventCallback)(()=>{ | ||
onMotionStartProp === null || onMotionStartProp === void 0 ? void 0 : onMotionStartProp(null); | ||
}); | ||
const onMotionFinish = (0, _reactutilities.useEventCallback)(()=>{ | ||
onMotionFinishProp === null || onMotionFinishProp === void 0 ? void 0 : onMotionFinishProp(null); | ||
}); | ||
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{ | ||
// Heads up! | ||
// We store the params in a ref to avoid re-rendering the component when the params change. | ||
paramsRef.current = params; | ||
}); | ||
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{ | ||
const element = elementRef.current; | ||
if (element) { | ||
const atoms = typeof value === 'function' ? value({ | ||
element | ||
element, | ||
...paramsRef.current | ||
}) : value; | ||
onMotionStart(); | ||
const handle = (0, _animateAtoms.animateAtoms)(element, atoms, { | ||
isReducedMotion: isReducedMotion() | ||
}); | ||
handle.onfinish = onMotionFinish; | ||
handleRef.current = handle; | ||
@@ -42,3 +58,5 @@ return ()=>{ | ||
handleRef, | ||
isReducedMotion | ||
isReducedMotion, | ||
onMotionFinish, | ||
onMotionStart | ||
]); | ||
@@ -45,0 +63,0 @@ return /*#__PURE__*/ _react.cloneElement(children, { |
@@ -21,3 +21,3 @@ "use strict"; | ||
function shouldSkipAnimation(appear, isFirstMount, visible) { | ||
return !appear && isFirstMount && visible; | ||
return !appear && isFirstMount && !!visible; | ||
} | ||
@@ -27,6 +27,8 @@ function createPresenceComponent(value) { | ||
const itemContext = _react.useContext(_PresenceGroupChildContext.PresenceGroupChildContext); | ||
const { appear, children, imperativeRef, onMotionFinish, visible, unmountOnExit } = { | ||
const merged = { | ||
...itemContext, | ||
...props | ||
}; | ||
const { appear, children, imperativeRef, onExit, onMotionFinish, onMotionStart, visible, unmountOnExit, ..._rest } = merged; | ||
const params = _rest; | ||
const [mounted, setMounted] = (0, _useMountedState.useMountedState)(visible, unmountOnExit); | ||
@@ -37,22 +39,28 @@ const child = (0, _getChildElement.getChildElement)(children); | ||
const ref = (0, _reactutilities.useMergedRefs)(elementRef, child.ref); | ||
const optionsRef = _react.useRef({}); | ||
const optionsRef = _react.useRef({ | ||
appear, | ||
params | ||
}); | ||
const isFirstMount = (0, _reactutilities.useFirstMount)(); | ||
const isReducedMotion = (0, _useIsReducedMotion.useIsReducedMotion)(); | ||
const onEnterFinish = (0, _reactutilities.useEventCallback)(()=>{ | ||
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, { | ||
direction: 'enter' | ||
const handleMotionStart = (0, _reactutilities.useEventCallback)((direction)=>{ | ||
onMotionStart === null || onMotionStart === void 0 ? void 0 : onMotionStart(null, { | ||
direction | ||
}); | ||
}); | ||
const onExitFinish = (0, _reactutilities.useEventCallback)(()=>{ | ||
const handleMotionFinish = (0, _reactutilities.useEventCallback)((direction)=>{ | ||
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, { | ||
direction: 'exit' | ||
direction | ||
}); | ||
if (unmountOnExit) { | ||
if (direction === 'exit' && unmountOnExit) { | ||
setMounted(false); | ||
itemContext === null || itemContext === void 0 ? void 0 : itemContext.onExit(); | ||
onExit === null || onExit === void 0 ? void 0 : onExit(); | ||
} | ||
}); | ||
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{ | ||
// Heads up! | ||
// We store the params in a ref to avoid re-rendering the component when the params change. | ||
optionsRef.current = { | ||
appear | ||
appear, | ||
params | ||
}; | ||
@@ -66,9 +74,15 @@ }); | ||
const presenceMotion = typeof value === 'function' ? value({ | ||
element | ||
element, | ||
...optionsRef.current.params | ||
}) : value; | ||
const atoms = visible ? presenceMotion.enter : presenceMotion.exit; | ||
const direction = visible ? 'enter' : 'exit'; | ||
const forceFinishMotion = !visible && isFirstMount; | ||
if (!forceFinishMotion) { | ||
handleMotionStart(direction); | ||
} | ||
const handle = (0, _animateAtoms.animateAtoms)(element, atoms, { | ||
isReducedMotion: isReducedMotion() | ||
}); | ||
if (!visible && isFirstMount) { | ||
if (forceFinishMotion) { | ||
// Heads up! | ||
@@ -80,3 +94,5 @@ // .finish() is used there to skip animation on first mount, but apply animation styles immediately | ||
handleRef.current = handle; | ||
handle.onfinish = visible ? onEnterFinish : onExitFinish; | ||
handle.onfinish = ()=>{ | ||
handleMotionFinish(direction); | ||
}; | ||
return ()=>{ | ||
@@ -89,4 +105,4 @@ handle.cancel(); | ||
isReducedMotion, | ||
onEnterFinish, | ||
onExitFinish, | ||
handleMotionFinish, | ||
handleMotionStart, | ||
visible | ||
@@ -93,0 +109,0 @@ ]); |
@@ -1,2 +0,2 @@ | ||
import { useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities'; | ||
import { useEventCallback, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities'; | ||
import * as React from 'react'; | ||
@@ -13,16 +13,32 @@ import { useIsReducedMotion } from '../hooks/useIsReducedMotion'; | ||
const Atom = (props)=>{ | ||
const { children, imperativeRef } = props; | ||
const { children, imperativeRef, onMotionFinish: onMotionFinishProp, onMotionStart: onMotionStartProp, ..._rest } = props; | ||
const params = _rest; | ||
const child = getChildElement(children); | ||
const handleRef = useMotionImperativeRef(imperativeRef); | ||
const elementRef = React.useRef(); | ||
const paramsRef = React.useRef(params); | ||
const isReducedMotion = useIsReducedMotion(); | ||
const onMotionStart = useEventCallback(()=>{ | ||
onMotionStartProp === null || onMotionStartProp === void 0 ? void 0 : onMotionStartProp(null); | ||
}); | ||
const onMotionFinish = useEventCallback(()=>{ | ||
onMotionFinishProp === null || onMotionFinishProp === void 0 ? void 0 : onMotionFinishProp(null); | ||
}); | ||
useIsomorphicLayoutEffect(()=>{ | ||
// Heads up! | ||
// We store the params in a ref to avoid re-rendering the component when the params change. | ||
paramsRef.current = params; | ||
}); | ||
useIsomorphicLayoutEffect(()=>{ | ||
const element = elementRef.current; | ||
if (element) { | ||
const atoms = typeof value === 'function' ? value({ | ||
element | ||
element, | ||
...paramsRef.current | ||
}) : value; | ||
onMotionStart(); | ||
const handle = animateAtoms(element, atoms, { | ||
isReducedMotion: isReducedMotion() | ||
}); | ||
handle.onfinish = onMotionFinish; | ||
handleRef.current = handle; | ||
@@ -35,3 +51,5 @@ return ()=>{ | ||
handleRef, | ||
isReducedMotion | ||
isReducedMotion, | ||
onMotionFinish, | ||
onMotionStart | ||
]); | ||
@@ -38,0 +56,0 @@ return React.cloneElement(children, { |
@@ -10,3 +10,3 @@ import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities'; | ||
function shouldSkipAnimation(appear, isFirstMount, visible) { | ||
return !appear && isFirstMount && visible; | ||
return !appear && isFirstMount && !!visible; | ||
} | ||
@@ -16,6 +16,8 @@ export function createPresenceComponent(value) { | ||
const itemContext = React.useContext(PresenceGroupChildContext); | ||
const { appear, children, imperativeRef, onMotionFinish, visible, unmountOnExit } = { | ||
const merged = { | ||
...itemContext, | ||
...props | ||
}; | ||
const { appear, children, imperativeRef, onExit, onMotionFinish, onMotionStart, visible, unmountOnExit, ..._rest } = merged; | ||
const params = _rest; | ||
const [mounted, setMounted] = useMountedState(visible, unmountOnExit); | ||
@@ -26,22 +28,28 @@ const child = getChildElement(children); | ||
const ref = useMergedRefs(elementRef, child.ref); | ||
const optionsRef = React.useRef({}); | ||
const optionsRef = React.useRef({ | ||
appear, | ||
params | ||
}); | ||
const isFirstMount = useFirstMount(); | ||
const isReducedMotion = useIsReducedMotion(); | ||
const onEnterFinish = useEventCallback(()=>{ | ||
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, { | ||
direction: 'enter' | ||
const handleMotionStart = useEventCallback((direction)=>{ | ||
onMotionStart === null || onMotionStart === void 0 ? void 0 : onMotionStart(null, { | ||
direction | ||
}); | ||
}); | ||
const onExitFinish = useEventCallback(()=>{ | ||
const handleMotionFinish = useEventCallback((direction)=>{ | ||
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, { | ||
direction: 'exit' | ||
direction | ||
}); | ||
if (unmountOnExit) { | ||
if (direction === 'exit' && unmountOnExit) { | ||
setMounted(false); | ||
itemContext === null || itemContext === void 0 ? void 0 : itemContext.onExit(); | ||
onExit === null || onExit === void 0 ? void 0 : onExit(); | ||
} | ||
}); | ||
useIsomorphicLayoutEffect(()=>{ | ||
// Heads up! | ||
// We store the params in a ref to avoid re-rendering the component when the params change. | ||
optionsRef.current = { | ||
appear | ||
appear, | ||
params | ||
}; | ||
@@ -55,9 +63,15 @@ }); | ||
const presenceMotion = typeof value === 'function' ? value({ | ||
element | ||
element, | ||
...optionsRef.current.params | ||
}) : value; | ||
const atoms = visible ? presenceMotion.enter : presenceMotion.exit; | ||
const direction = visible ? 'enter' : 'exit'; | ||
const forceFinishMotion = !visible && isFirstMount; | ||
if (!forceFinishMotion) { | ||
handleMotionStart(direction); | ||
} | ||
const handle = animateAtoms(element, atoms, { | ||
isReducedMotion: isReducedMotion() | ||
}); | ||
if (!visible && isFirstMount) { | ||
if (forceFinishMotion) { | ||
// Heads up! | ||
@@ -69,3 +83,5 @@ // .finish() is used there to skip animation on first mount, but apply animation styles immediately | ||
handleRef.current = handle; | ||
handle.onfinish = visible ? onEnterFinish : onExitFinish; | ||
handle.onfinish = ()=>{ | ||
handleMotionFinish(direction); | ||
}; | ||
return ()=>{ | ||
@@ -79,4 +95,4 @@ handle.cancel(); | ||
isReducedMotion, | ||
onEnterFinish, | ||
onExitFinish, | ||
handleMotionFinish, | ||
handleMotionStart, | ||
visible | ||
@@ -83,0 +99,0 @@ ]); |
{ | ||
"name": "@fluentui/react-motion", | ||
"version": "0.0.0-nightly-20240611-0405.1", | ||
"version": "0.0.0-nightly-20240612-0406.1", | ||
"description": "A package with utilities & motion definitions using Web Animations API", | ||
@@ -32,4 +32,4 @@ "main": "lib-commonjs/index.js", | ||
"@fluentui/eslint-plugin": "*", | ||
"@fluentui/react-conformance": "0.0.0-nightly-20240611-0405.1", | ||
"@fluentui/react-conformance-griffel": "0.0.0-nightly-20240611-0405.1", | ||
"@fluentui/react-conformance": "0.0.0-nightly-20240612-0406.1", | ||
"@fluentui/react-conformance-griffel": "0.0.0-nightly-20240612-0406.1", | ||
"@fluentui/scripts-api-extractor": "*", | ||
@@ -39,4 +39,4 @@ "@fluentui/scripts-tasks": "*" | ||
"dependencies": { | ||
"@fluentui/react-shared-contexts": "0.0.0-nightly-20240611-0405.1", | ||
"@fluentui/react-utilities": "0.0.0-nightly-20240611-0405.1", | ||
"@fluentui/react-shared-contexts": "0.0.0-nightly-20240612-0406.1", | ||
"@fluentui/react-utilities": "0.0.0-nightly-20240612-0406.1", | ||
"@swc/helpers": "^0.5.1", | ||
@@ -43,0 +43,0 @@ "react-is": "^17.0.2" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
150150
1428
+ Added@fluentui/keyboard-keys@0.0.0-nightly-20240612-0406.1(transitive)
+ Added@fluentui/react-shared-contexts@0.0.0-nightly-20240612-0406.1(transitive)
+ Added@fluentui/react-theme@0.0.0-nightly-20240612-0406.1(transitive)
+ Added@fluentui/react-utilities@0.0.0-nightly-20240612-0406.1(transitive)
+ Added@fluentui/tokens@0.0.0-nightly-20240612-0406.1(transitive)
- Removed@fluentui/keyboard-keys@0.0.0-nightly-20240611-0405.1(transitive)
- Removed@fluentui/react-shared-contexts@0.0.0-nightly-20240611-0405.1(transitive)
- Removed@fluentui/react-theme@0.0.0-nightly-20240611-0405.1(transitive)
- Removed@fluentui/react-utilities@0.0.0-nightly-20240611-0405.1(transitive)
- Removed@fluentui/tokens@0.0.0-nightly-20240611-0405.1(transitive)
Updated@fluentui/react-shared-contexts@0.0.0-nightly-20240612-0406.1
Updated@fluentui/react-utilities@0.0.0-nightly-20240612-0406.1