Initial commit

This commit is contained in:
2025-03-07 19:22:02 +01:00
commit 4a98255d83
55743 changed files with 5280367 additions and 0 deletions
+340
View File
@@ -0,0 +1,340 @@
# Change Log - @fluentui/react-motion
This log was last generated on Wed, 22 Jan 2025 13:55:29 GMT and should not be manually modified.
<!-- Start content -->
## [9.6.7](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.7)
Wed, 22 Jan 2025 13:55:29 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.6..@fluentui/react-motion_v9.6.7)
### Patches
- feat: add extended support for reduced motion ([PR #33353](https://github.com/microsoft/fluentui/pull/33353) by olfedias@microsoft.com)
- Bump @fluentui/react-utilities to v9.18.20 ([PR #33631](https://github.com/microsoft/fluentui/pull/33631) by beachball)
## [9.6.6](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.6)
Wed, 08 Jan 2025 18:33:34 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.5..@fluentui/react-motion_v9.6.6)
### Patches
- fix: handle case when Animation.persist() does not exist ([PR #33282](https://github.com/microsoft/fluentui/pull/33282) by seanmonahan@microsoft.com)
## [9.6.5](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.5)
Mon, 16 Dec 2024 16:26:49 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.4..@fluentui/react-motion_v9.6.5)
### Patches
- Bump @fluentui/react-shared-contexts to v9.21.2 ([PR #33468](https://github.com/microsoft/fluentui/pull/33468) by beachball)
- Bump @fluentui/react-utilities to v9.18.19 ([PR #33468](https://github.com/microsoft/fluentui/pull/33468) by beachball)
## [9.6.4](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.4)
Mon, 09 Dec 2024 17:38:13 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.3..@fluentui/react-motion_v9.6.4)
### Patches
- fix: avoid memory leak in Animation:finished ([PR #33431](https://github.com/microsoft/fluentui/pull/33431) by olfedias@microsoft.com)
## [9.6.3](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.3)
Fri, 06 Dec 2024 12:53:46 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.2..@fluentui/react-motion_v9.6.3)
### Patches
- Bump @fluentui/react-shared-contexts to v9.21.1 ([PR #33372](https://github.com/microsoft/fluentui/pull/33372) by beachball)
- Bump @fluentui/react-utilities to v9.18.18 ([PR #33372](https://github.com/microsoft/fluentui/pull/33372) by beachball)
## [9.6.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.2)
Thu, 28 Nov 2024 09:30:51 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.1..@fluentui/react-motion_v9.6.2)
### Patches
- fix: respect reduced motion in createMotionComponent() ([PR #33357](https://github.com/microsoft/fluentui/pull/33357) by olfedias@microsoft.com)
## [9.6.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.1)
Mon, 11 Nov 2024 10:00:45 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.6.0..@fluentui/react-motion_v9.6.1)
### Patches
- chore: replace npm-scripts and just-scrtips with nx inferred tasks ([PR #33074](https://github.com/microsoft/fluentui/pull/33074) by martinhochel@microsoft.com)
- Bump @fluentui/react-shared-contexts to v9.21.0 ([PR #33238](https://github.com/microsoft/fluentui/pull/33238) by beachball)
- Bump @fluentui/react-utilities to v9.18.17 ([PR #33238](https://github.com/microsoft/fluentui/pull/33238) by beachball)
## [9.6.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.6.0)
Tue, 15 Oct 2024 17:17:53 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.5.2..@fluentui/react-motion_v9.6.0)
### Minor changes
- feat: export MotionParam type ([PR #32939](https://github.com/microsoft/fluentui/pull/32939) by robertpenner@microsoft.com)
- Bump @fluentui/react-shared-contexts to v9.20.2 ([PR #32999](https://github.com/microsoft/fluentui/pull/32999) by beachball)
- Bump @fluentui/react-utilities to v9.18.16 ([PR #32999](https://github.com/microsoft/fluentui/pull/32999) by beachball)
## [9.5.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.5.2)
Mon, 23 Sep 2024 12:40:17 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.5.1..@fluentui/react-motion_v9.5.2)
### Patches
- Bump @fluentui/react-shared-contexts to v9.20.1 ([PR #32840](https://github.com/microsoft/fluentui/pull/32840) by beachball)
- Bump @fluentui/react-utilities to v9.18.15 ([PR #32840](https://github.com/microsoft/fluentui/pull/32840) by beachball)
## [9.5.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.5.1)
Tue, 10 Sep 2024 10:19:12 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.5.0..@fluentui/react-motion_v9.5.1)
### Patches
- Bump @fluentui/react-utilities to v9.18.14 ([PR #32494](https://github.com/microsoft/fluentui/pull/32494) by beachball)
## [9.5.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.5.0)
Fri, 16 Aug 2024 10:24:17 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.4.0..@fluentui/react-motion_v9.5.0)
### Minor changes
- feat: Add context to configure motion behaviour ([PR #32316](https://github.com/microsoft/fluentui/pull/32316) by lingfangao@hotmail.com)
## [9.4.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.4.0)
Tue, 23 Jul 2024 20:13:12 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.3.0..@fluentui/react-motion_v9.4.0)
### Minor changes
- feat: add presenceMotionSlot() API ([PR #31984](https://github.com/microsoft/fluentui/pull/31984) by olfedias@microsoft.com)
- Bump @fluentui/react-shared-contexts to v9.20.0 ([PR #32067](https://github.com/microsoft/fluentui/pull/32067) by beachball)
- Bump @fluentui/react-utilities to v9.18.13 ([PR #32067](https://github.com/microsoft/fluentui/pull/32067) by beachball)
### Patches
- fix: improve Web Animations API detection in tests ([PR #32029](https://github.com/microsoft/fluentui/pull/32029) by olfedias@microsoft.com)
## [9.3.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.3.0)
Mon, 15 Jul 2024 17:25:35 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.2.2..@fluentui/react-motion_v9.3.0)
### Minor changes
- feat(motion): add PresenceDirection type ([PR #31958](https://github.com/microsoft/fluentui/pull/31958) by olfedias@microsoft.com)
- Bump @fluentui/react-shared-contexts to v9.19.1 ([PR #31998](https://github.com/microsoft/fluentui/pull/31998) by beachball)
- Bump @fluentui/react-utilities to v9.18.12 ([PR #31998](https://github.com/microsoft/fluentui/pull/31998) by beachball)
### Patches
- fix: revert incorectly set npm versions in all packages ([PR #31937](https://github.com/microsoft/fluentui/pull/31937) by martinhochel@microsoft.com)
- feat: add createPresenceComponentVariant() ([PR #31943](https://github.com/microsoft/fluentui/pull/31943) by olfedias@microsoft.com)
## [9.2.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.2.2)
Thu, 04 Jul 2024 15:14:35 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.2.1..@fluentui/react-motion_v9.2.2)
### Patches
- fix: Check if DOM is available before using Element global to avoid breaks in build. ([PR #31907](https://github.com/microsoft/fluentui/pull/31907) by estebanmu@microsoft.com)
## [9.2.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.2.1)
Mon, 01 Jul 2024 20:30:22 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.2.0..@fluentui/react-motion_v9.2.1)
### Patches
- chore: add eslint react-compiler ([PR #31457](https://github.com/microsoft/fluentui/pull/31457) by seanmonahan@microsoft.com)
- fix: improve Jest compat ([PR #31715](https://github.com/microsoft/fluentui/pull/31715) by olfedias@microsoft.com)
- chore: adds 'use no memo' directive ([PR #31787](https://github.com/microsoft/fluentui/pull/31787) by seanmonahan@microsoft.com)
- Bump @fluentui/react-utilities to v9.18.11 ([PR #31861](https://github.com/microsoft/fluentui/pull/31861) by beachball)
## [9.2.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.2.0)
Mon, 17 Jun 2024 07:34:16 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.1.0..@fluentui/react-motion_v9.2.0)
### Minor changes
- feat: Implement `onMotionCancel` callback handler ([PR #31698](https://github.com/microsoft/fluentui/pull/31698) by lingfangao@hotmail.com)
## [9.1.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.1.0)
Wed, 12 Jun 2024 13:17:19 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motion_v9.0.0..@fluentui/react-motion_v9.1.0)
### Minor changes
- feat: add support for params ([PR #31566](https://github.com/microsoft/fluentui/pull/31566) by olfedias@microsoft.com)
- feat: Add consistent start and finish lifecycle callbacks ([PR #31644](https://github.com/microsoft/fluentui/pull/31644) by lingfangao@hotmail.com)
### Patches
- fix(motions): improve compat for jsdom & jest ([PR #31602](https://github.com/microsoft/fluentui/pull/31602) by olfedias@microsoft.com)
## [9.0.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motion_v9.0.0)
Thu, 06 Jun 2024 15:26:35 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.3.2..@fluentui/react-motion_v9.0.0)
### Minor changes
- feat: release stable ([PR #31574](https://github.com/microsoft/fluentui/pull/31574) by olfedias@microsoft.com)
- Bump @fluentui/react-utilities to v9.18.10 ([PR #31586](https://github.com/microsoft/fluentui/pull/31586) by beachball)
## [0.3.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.3.2)
Mon, 20 May 2024 12:44:59 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.3.1..@fluentui/react-motions-preview_v0.3.2)
### Patches
- chore(motions): add mock for .animate() calls ([PR #31390](https://github.com/microsoft/fluentui/pull/31390) by olfedias@microsoft.com)
- Bump @fluentui/react-shared-contexts to v9.19.0 ([PR #26682](https://github.com/microsoft/fluentui/pull/26682) by beachball)
- Bump @fluentui/react-utilities to v9.18.9 ([PR #26682](https://github.com/microsoft/fluentui/pull/26682) by beachball)
## [0.3.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.3.1)
Thu, 16 May 2024 09:25:16 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.3.0..@fluentui/react-motions-preview_v0.3.1)
### Patches
- fix(motions): use useFirstMount() in createPresenceComponent() ([PR #31379](https://github.com/microsoft/fluentui/pull/31379) by olfedias@microsoft.com)
## [0.3.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.3.0)
Thu, 09 May 2024 19:35:11 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.8..@fluentui/react-motions-preview_v0.3.0)
### Minor changes
- BREAKING: fix motion token values and adjust structure to match original source ([PR #31262](https://github.com/microsoft/fluentui/pull/31262) by robert@robertpenner.com)
## [0.2.8](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.8)
Mon, 06 May 2024 12:55:02 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.7..@fluentui/react-motions-preview_v0.2.8)
### Patches
- Bump @fluentui/react-shared-contexts to v9.18.0 ([PR #31271](https://github.com/microsoft/fluentui/pull/31271) by beachball)
- Bump @fluentui/react-utilities to v9.18.8 ([PR #31271](https://github.com/microsoft/fluentui/pull/31271) by beachball)
## [0.2.7](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.7)
Thu, 02 May 2024 11:36:35 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.6..@fluentui/react-motions-preview_v0.2.7)
### Patches
- fix(PresenceGroup): cleanup children properly ([PR #31175](https://github.com/microsoft/fluentui/pull/31175) by olfedias@microsoft.com)
- chore: improve state handling in createPresenceComponent() ([PR #31143](https://github.com/microsoft/fluentui/pull/31143) by olfedias@microsoft.com)
## [0.2.6](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.6)
Tue, 23 Apr 2024 08:17:49 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.5..@fluentui/react-motions-preview_v0.2.6)
### Patches
- Bump @fluentui/react-shared-contexts to v9.17.0 ([PR #31113](https://github.com/microsoft/fluentui/pull/31113) by beachball)
- Bump @fluentui/react-utilities to v9.18.7 ([PR #31113](https://github.com/microsoft/fluentui/pull/31113) by beachball)
## [0.2.5](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.5)
Tue, 02 Apr 2024 09:48:01 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.4..@fluentui/react-motions-preview_v0.2.5)
### Patches
- Bump @fluentui/react-shared-contexts to v9.16.0 ([PR #30644](https://github.com/microsoft/fluentui/pull/30644) by beachball)
- Bump @fluentui/react-utilities to v9.18.6 ([PR #30644](https://github.com/microsoft/fluentui/pull/30644) by beachball)
## [0.2.4](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.4)
Mon, 18 Mar 2024 19:50:46 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.3..@fluentui/react-motions-preview_v0.2.4)
### Patches
- Bump @fluentui/react-shared-contexts to v9.15.2 ([PR #30600](https://github.com/microsoft/fluentui/pull/30600) by beachball)
- Bump @fluentui/react-utilities to v9.18.5 ([PR #30600](https://github.com/microsoft/fluentui/pull/30600) by beachball)
## [0.2.3](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.3)
Fri, 15 Mar 2024 21:43:49 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.2..@fluentui/react-motions-preview_v0.2.3)
### Patches
- Bump @fluentui/react-shared-contexts to v9.15.1 ([PR #30740](https://github.com/microsoft/fluentui/pull/30740) by beachball)
- Bump @fluentui/react-utilities to v9.18.4 ([PR #30740](https://github.com/microsoft/fluentui/pull/30740) by beachball)
## [0.2.2](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.2)
Thu, 07 Mar 2024 19:33:27 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.1..@fluentui/react-motions-preview_v0.2.2)
### Patches
- Bump @fluentui/react-shared-contexts to v9.15.0 ([PR #30687](https://github.com/microsoft/fluentui/pull/30687) by beachball)
- Bump @fluentui/react-utilities to v9.18.3 ([PR #30687](https://github.com/microsoft/fluentui/pull/30687) by beachball)
## [0.2.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.1)
Wed, 28 Feb 2024 02:34:19 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.2.0..@fluentui/react-motions-preview_v0.2.1)
### Patches
- Bump @fluentui/react-shared-contexts to v9.14.1 ([PR #30639](https://github.com/microsoft/fluentui/pull/30639) by beachball)
- Bump @fluentui/react-utilities to v9.18.2 ([PR #30639](https://github.com/microsoft/fluentui/pull/30639) by beachball)
## [0.2.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.2.0)
Tue, 20 Feb 2024 14:22:22 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.1.1..@fluentui/react-motions-preview_v0.2.0)
### Minor changes
- BREAKING: rename createAtom() to createMotionComponent() & createPresence() to createPresenceMotion() ([PR #30550](https://github.com/microsoft/fluentui/pull/30550) by olfedias@microsoft.com)
- BREAKING: remove exports for atom & presence definitions ([PR #30548](https://github.com/microsoft/fluentui/pull/30548) by olfedias@microsoft.com)
- Bump @fluentui/react-utilities to v9.18.1 ([PR #30543](https://github.com/microsoft/fluentui/pull/30543) by beachball)
### Patches
- feat: add onMotionFinish() callback to createPresenceComponent() ([PR #30529](https://github.com/microsoft/fluentui/pull/30529) by olfedias@microsoft.com)
- feat: add PresenceGroup component ([PR #30543](https://github.com/microsoft/fluentui/pull/30543) by olfedias@microsoft.com)
## [0.1.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.1.1)
Tue, 30 Jan 2024 23:16:54 GMT
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-motions-preview_v0.1.0..@fluentui/react-motions-preview_v0.1.1)
### Patches
- Bump @fluentui/react-utilities to v9.18.0 ([PR #29983](https://github.com/microsoft/fluentui/pull/29983) by beachball)
## [0.1.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-motions-preview_v0.1.0)
Tue, 23 Jan 2024 15:10:59 GMT
### Minor changes
- chore: initial release ([PR #30359](https://github.com/microsoft/fluentui/pull/30359) by olfedias@microsoft.com)
- Bump @fluentui/react-utilities to v9.17.0 ([PR #30359](https://github.com/microsoft/fluentui/pull/30359) by beachball)
+15
View File
@@ -0,0 +1,15 @@
@fluentui/react-motions-preview
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Note: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license
+5
View File
@@ -0,0 +1,5 @@
# @fluentui/react-motion
**React Motions components for [Fluent UI React](https://react.fluentui.dev/)**
These are not production-ready components and **should never be used in product**. This space is useful for testing new components whose APIs might change before final release.
+274
View File
@@ -0,0 +1,274 @@
import * as React_2 from 'react';
import { SlotComponentType } from '@fluentui/react-utilities';
import { SlotRenderFunction } from '@fluentui/react-utilities';
declare type AtomCore = {
keyframes: Keyframe[];
} & KeyframeEffectOptions;
export declare type AtomMotion = AtomCore & {
/**
* Allows to specify a reduced motion version of the animation. If provided, the settings will be used when the
* user has enabled the reduced motion setting in the operating system (i.e `prefers-reduced-motion` media query is
* active). If not provided, the duration of the animation will be overridden to be 1ms.
*
* Note, if `keyframes` are provided, they will be used instead of the regular `keyframes`.
*/
reducedMotion?: Partial<AtomCore>;
};
export declare type AtomMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (params: {
element: HTMLElement;
} & MotionParams) => AtomMotion | AtomMotion[];
/**
* Creates a component that will animate the children using the provided motion.
*
* @param value - A motion definition.
*/
export declare function createMotionComponent<MotionParams extends Record<string, MotionParam> = {}>(value: AtomMotion | AtomMotion[] | AtomMotionFn<MotionParams>): React_2.FC<MotionComponentProps & MotionParams>;
export declare function createPresenceComponent<MotionParams extends Record<string, MotionParam> = {}>(value: PresenceMotion | PresenceMotionFn<MotionParams>): PresenceComponent<MotionParams>;
export declare function createPresenceComponentVariant<MotionParams extends Record<string, MotionParam> = {}>(component: PresenceComponent<MotionParams>, override: PresenceOverride): PresenceComponent<MotionParams>;
export declare const curves: {
readonly curveAccelerateMax: "cubic-bezier(0.9,0.1,1,0.2)";
readonly curveAccelerateMid: "cubic-bezier(1,0,1,1)";
readonly curveAccelerateMin: "cubic-bezier(0.8,0,0.78,1)";
readonly curveDecelerateMax: "cubic-bezier(0.1,0.9,0.2,1)";
readonly curveDecelerateMid: "cubic-bezier(0,0,0,1)";
readonly curveDecelerateMin: "cubic-bezier(0.33,0,0.1,1)";
readonly curveEasyEaseMax: "cubic-bezier(0.8,0,0.2,1)";
readonly curveEasyEase: "cubic-bezier(0.33,0,0.67,1)";
readonly curveLinear: "cubic-bezier(0,0,1,1)";
};
export declare const durations: {
readonly durationUltraFast: 50;
readonly durationFaster: 100;
readonly durationFast: 150;
readonly durationNormal: 200;
readonly durationGentle: 250;
readonly durationSlow: 300;
readonly durationSlower: 400;
readonly durationUltraSlow: 500;
};
/**
* @internal A private symbol to store the motion definition on the component for variants.
*/
declare const MOTION_DEFINITION: unique symbol;
export declare const MotionBehaviourProvider: React_2.Provider<MotionBehaviourType | undefined>;
/**
* Specifies the behaviour of child motion component under @see MotionBehaviourProvider.
*/
declare type MotionBehaviourType = 'skip' | 'default';
export declare type MotionComponentProps = {
children: React_2.ReactElement;
/** Provides imperative controls for the animation. */
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 is cancelled.
*
* A motion definition can contain multiple animations and therefore multiple "cancel" events. The callback is
* triggered once all animations have been cancelled with "null" instead of an event object to avoid ambiguity.
*/
onMotionCancel?: (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;
};
export declare type MotionImperativeRef = {
/** Sets the playback rate of the animation, where 1 is normal speed. */
setPlaybackRate: (rate: number) => void;
/** Sets the state of the animation to running or paused. */
setPlayState: (state: 'running' | 'paused') => void;
};
/**
* 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.
*/
export declare type MotionParam = boolean | number | string;
export declare const motionTokens: {
curveAccelerateMax: "cubic-bezier(0.9,0.1,1,0.2)";
curveAccelerateMid: "cubic-bezier(1,0,1,1)";
curveAccelerateMin: "cubic-bezier(0.8,0,0.78,1)";
curveDecelerateMax: "cubic-bezier(0.1,0.9,0.2,1)";
curveDecelerateMid: "cubic-bezier(0,0,0,1)";
curveDecelerateMin: "cubic-bezier(0.33,0,0.1,1)";
curveEasyEaseMax: "cubic-bezier(0.8,0,0.2,1)";
curveEasyEase: "cubic-bezier(0.33,0,0.67,1)";
curveLinear: "cubic-bezier(0,0,1,1)";
durationUltraFast: 50;
durationFaster: 100;
durationFast: 150;
durationNormal: 200;
durationGentle: 250;
durationSlow: 300;
durationSlower: 400;
durationUltraSlow: 500;
};
export declare type PresenceComponent<MotionParams extends Record<string, MotionParam> = {}> = {
(props: PresenceComponentProps & MotionParams): React_2.ReactElement | null;
[MOTION_DEFINITION]: PresenceMotionFn<MotionParams>;
};
export declare type PresenceComponentProps = {
/**
* By default, the child component won't execute the "enter" motion when it initially mounts, regardless of the value
* of "visible". If you desire this behavior, ensure both "appear" and "visible" are set to "true".
*/
appear?: boolean;
/** A React element that will be cloned and will have motion effects applied to it. */
children: React_2.ReactElement;
/** Provides imperative controls for the animation. */
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, data: {
direction: PresenceDirection;
}) => void;
/**
* Callback that is called when the whole motion is cancelled. When a motion is cancelled it does not
* emit a finish event but a specific cancel event
*
* 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.
*/
onMotionCancel?: (ev: null, data: {
direction: PresenceDirection;
}) => 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: PresenceDirection;
}) => void;
/** Defines whether a component is visible; triggers the "enter" or "exit" motions. */
visible?: boolean;
/**
* By default, the child component remains mounted after it reaches the "finished" state. Set "unmountOnExit" if
* you prefer to unmount the component after it finishes exiting.
*/
unmountOnExit?: boolean;
};
export declare type PresenceDirection = 'enter' | 'exit';
export declare class PresenceGroup extends React_2.Component<PresenceGroupProps, PresenceGroupState> {
private mounted;
static getDerivedStateFromProps(nextProps: PresenceGroupProps, { childMapping: prevChildMapping, firstRender }: PresenceGroupState): {
childMapping: PresenceGroupChildMapping;
firstRender: boolean;
};
constructor(props: PresenceGroupProps, context: unknown);
private handleExit;
componentDidMount(): void;
componentWillUnmount(): void;
render(): JSX.Element;
}
declare type PresenceGroupChild = {
element: React_2.ReactElement;
appear: boolean;
visible: boolean;
unmountOnExit: boolean;
};
declare type PresenceGroupChildMapping = Record<string, PresenceGroupChild>;
declare type PresenceGroupProps = {
children: React_2.ReactNode;
};
declare type PresenceGroupState = {
childMapping: PresenceGroupChildMapping;
firstRender: boolean;
};
export declare type PresenceMotion = Record<PresenceDirection, AtomMotion | AtomMotion[]>;
export declare type PresenceMotionFn<MotionParams extends Record<string, MotionParam> = {}> = (params: {
element: HTMLElement;
} & MotionParams) => PresenceMotion;
export declare function presenceMotionSlot<MotionParams extends Record<string, MotionParam> = {}>(motion: PresenceMotionSlotProps<MotionParams> | null | undefined, options: {
elementType: React_2.FC<PresenceComponentProps & MotionParams>;
defaultProps: PresenceMotionSlotRenderProps & MotionParams;
}): SlotComponentType<PresenceMotionSlotRenderProps & MotionParams>;
export declare type PresenceMotionSlotProps<MotionParams extends Record<string, MotionParam> = {}> = Pick<PresenceComponentProps, 'imperativeRef' | 'onMotionFinish' | 'onMotionStart'> & {
/**
* @deprecated Do not use. Presence Motion Slots do not support intrinsic elements.
*
* If you want to override the animation, use the children render function instead.
*/
as?: keyof JSX.IntrinsicElements;
children?: SlotRenderFunction<PresenceMotionSlotRenderProps & MotionParams & {
children: React_2.ReactElement;
}>;
};
/**
* @internal
*/
declare type PresenceMotionSlotRenderProps = Pick<PresenceComponentProps, 'appear' | 'onMotionFinish' | 'onMotionStart' | 'unmountOnExit' | 'visible'>;
/**
* @internal
*
* Override properties for presence transitions.
*
* @example <caption>Override duration for all transitions</caption>
* ```
* const override: PresenceOverride = {
* all: { duration: 1000 },
* };
* ```
*
* @example <caption>Override easing for exit transition</caption>
* ```
* const override: PresenceOverride = {
* exit: { easing: 'ease-out' },
* };
* ```
*/
declare type PresenceOverride = Partial<Record<PresenceDirection | 'all', Partial<PresenceOverrideFields>>>;
/**
* @internal
*/
declare type PresenceOverrideFields = {
duration: KeyframeEffectOptions['duration'];
easing: KeyframeEffectOptions['easing'];
};
export { }
@@ -0,0 +1,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "PresenceGroup", {
enumerable: true,
get: function() {
return PresenceGroup;
}
});
const _define_property = require("@swc/helpers/_/_define_property");
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _getNextChildMapping = require("../utils/groups/getNextChildMapping");
const _getChildMapping = require("../utils/groups/getChildMapping");
const _PresenceGroupItemProvider = require("./PresenceGroupItemProvider");
class PresenceGroup extends _react.Component {
static getDerivedStateFromProps(nextProps, { childMapping: prevChildMapping, firstRender }) {
const nextChildMapping = (0, _getChildMapping.getChildMapping)(nextProps.children);
return {
childMapping: firstRender ? nextChildMapping : (0, _getNextChildMapping.getNextChildMapping)(prevChildMapping, nextChildMapping),
firstRender: false
};
}
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
render() {
return /*#__PURE__*/ _react.createElement(_react.Fragment, null, Object.entries(this.state.childMapping).map(([childKey, childProps])=>/*#__PURE__*/ _react.createElement(_PresenceGroupItemProvider.PresenceGroupItemProvider, {
...childProps,
childKey: childKey,
key: childKey,
onExit: this.handleExit
}, childProps.element)));
}
constructor(props, context){
super(props, context);
_define_property._(this, "mounted", false);
_define_property._(this, "handleExit", (childKey)=>{
const currentChildMapping = (0, _getChildMapping.getChildMapping)(this.props.children);
if (childKey in currentChildMapping) {
return;
}
if (this.mounted) {
this.setState((state)=>{
const childMapping = {
...state.childMapping
};
delete childMapping[childKey];
return {
childMapping
};
});
}
});
this.state = {
childMapping: {},
firstRender: true
};
}
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/PresenceGroup.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { getNextChildMapping } from '../utils/groups/getNextChildMapping';\nimport { getChildMapping } from '../utils/groups/getChildMapping';\nimport type { PresenceGroupChildMapping } from '../utils/groups/types';\nimport { PresenceGroupItemProvider } from './PresenceGroupItemProvider';\n\ntype PresenceGroupProps = {\n children: React.ReactNode;\n};\n\ntype PresenceGroupState = {\n childMapping: PresenceGroupChildMapping;\n firstRender: boolean;\n};\n\n/* eslint-disable @typescript-eslint/explicit-member-accessibility */\n/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable @typescript-eslint/member-ordering */\n\nexport class PresenceGroup extends React.Component<PresenceGroupProps, PresenceGroupState> {\n private mounted: boolean = false;\n\n static getDerivedStateFromProps(\n nextProps: PresenceGroupProps,\n { childMapping: prevChildMapping, firstRender }: PresenceGroupState,\n ) {\n const nextChildMapping = getChildMapping(nextProps.children);\n\n return {\n childMapping: firstRender ? nextChildMapping : getNextChildMapping(prevChildMapping, nextChildMapping),\n firstRender: false,\n };\n }\n\n constructor(props: PresenceGroupProps, context: unknown) {\n super(props, context);\n\n this.state = {\n childMapping: {},\n firstRender: true,\n };\n }\n\n private handleExit = (childKey: string) => {\n const currentChildMapping = getChildMapping(this.props.children);\n\n if (childKey in currentChildMapping) {\n return;\n }\n\n if (this.mounted) {\n this.setState(state => {\n const childMapping = { ...state.childMapping };\n delete childMapping[childKey];\n\n return { childMapping };\n });\n }\n };\n\n componentDidMount() {\n this.mounted = true;\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n render() {\n return (\n <>\n {Object.entries(this.state.childMapping).map(([childKey, childProps]) => (\n <PresenceGroupItemProvider {...childProps} childKey={childKey} key={childKey} onExit={this.handleExit}>\n {childProps.element}\n </PresenceGroupItemProvider>\n ))}\n </>\n );\n }\n}\n"],"names":["PresenceGroup","React","Component","getDerivedStateFromProps","nextProps","childMapping","prevChildMapping","firstRender","nextChildMapping","getChildMapping","children","getNextChildMapping","componentDidMount","mounted","componentWillUnmount","render","Object","entries","state","map","childKey","childProps","PresenceGroupItemProvider","key","onExit","handleExit","element","constructor","props","context","currentChildMapping","setState"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAoBaA;;;eAAAA;;;;;iEApBU;qCAEa;iCACJ;2CAEU;AAenC,MAAMA,sBAAsBC,OAAMC,SAAS;IAGhD,OAAOC,yBACLC,SAA6B,EAC7B,EAAEC,cAAcC,gBAAgB,EAAEC,WAAW,EAAsB,EACnE;QACA,MAAMC,mBAAmBC,IAAAA,gCAAe,EAACL,UAAUM,QAAQ;QAE3D,OAAO;YACLL,cAAcE,cAAcC,mBAAmBG,IAAAA,wCAAmB,EAACL,kBAAkBE;YACrFD,aAAa;QACf;IACF;IA4BAK,oBAAoB;QAClB,IAAI,CAACC,OAAO,GAAG;IACjB;IAEAC,uBAAuB;QACrB,IAAI,CAACD,OAAO,GAAG;IACjB;IAEAE,SAAS;QACP,qBACE,4CACGC,OAAOC,OAAO,CAAC,IAAI,CAACC,KAAK,CAACb,YAAY,EAAEc,GAAG,CAAC,CAAC,CAACC,UAAUC,WAAW,iBAClE,qBAACC,oDAAyB;gBAAE,GAAGD,UAAU;gBAAED,UAAUA;gBAAUG,KAAKH;gBAAUI,QAAQ,IAAI,CAACC,UAAU;eAClGJ,WAAWK,OAAO;IAK7B;IA5CAC,YAAYC,KAAyB,EAAEC,OAAgB,CAAE;QACvD,KAAK,CAACD,OAAOC;QAff,yBAAQhB,WAAmB;QAuB3B,yBAAQY,cAAa,CAACL;YACpB,MAAMU,sBAAsBrB,IAAAA,gCAAe,EAAC,IAAI,CAACmB,KAAK,CAAClB,QAAQ;YAE/D,IAAIU,YAAYU,qBAAqB;gBACnC;YACF;YAEA,IAAI,IAAI,CAACjB,OAAO,EAAE;gBAChB,IAAI,CAACkB,QAAQ,CAACb,CAAAA;oBACZ,MAAMb,eAAe;wBAAE,GAAGa,MAAMb,YAAY;oBAAC;oBAC7C,OAAOA,YAAY,CAACe,SAAS;oBAE7B,OAAO;wBAAEf;oBAAa;gBACxB;YACF;QACF;QArBE,IAAI,CAACa,KAAK,GAAG;YACXb,cAAc,CAAC;YACfE,aAAa;QACf;IACF;AAsCF"}
@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "PresenceGroupItemProvider", {
enumerable: true,
get: function() {
return PresenceGroupItemProvider;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _PresenceGroupChildContext = require("../contexts/PresenceGroupChildContext");
const PresenceGroupItemProvider = (props)=>{
const { appear, childKey, onExit, visible, unmountOnExit } = props;
const contextValue = _react.useMemo(()=>({
appear,
visible,
onExit: ()=>onExit(childKey),
unmountOnExit
}), [
appear,
childKey,
onExit,
visible,
unmountOnExit
]);
return /*#__PURE__*/ _react.createElement(_PresenceGroupChildContext.PresenceGroupChildContext.Provider, {
value: contextValue
}, props.children);
};
@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/PresenceGroupItemProvider.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport type { PresenceGroupChildContextValue } from '../contexts/PresenceGroupChildContext';\n\ntype PresenceGroupItemProviderProps = Omit<PresenceGroupChildContextValue, 'onExit'> & {\n children: React.ReactElement;\n childKey: string;\n // That's an internal callback, so we don't need to enforce the type here\n // eslint-disable-next-line @nx/workspace-consistent-callback-type\n onExit: (childKey: string) => void;\n};\n\n/**\n * @internal\n *\n * Provides context for a single child of a `PresenceGroup`. Exists only to make a stable context value for a child.\n * Not intended for direct use.\n */\nexport const PresenceGroupItemProvider: React.FC<PresenceGroupItemProviderProps> = props => {\n const { appear, childKey, onExit, visible, unmountOnExit } = props;\n const contextValue = React.useMemo(\n () => ({\n appear,\n visible,\n onExit: () => onExit(childKey),\n unmountOnExit,\n }),\n [appear, childKey, onExit, visible, unmountOnExit],\n );\n\n return <PresenceGroupChildContext.Provider value={contextValue}>{props.children}</PresenceGroupChildContext.Provider>;\n};\n"],"names":["PresenceGroupItemProvider","props","appear","childKey","onExit","visible","unmountOnExit","contextValue","React","useMemo","PresenceGroupChildContext","Provider","value","children"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAmBaA;;;eAAAA;;;;iEAnBU;2CAEmB;AAiBnC,MAAMA,4BAAsEC,CAAAA;IACjF,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAEC,aAAa,EAAE,GAAGL;IAC7D,MAAMM,eAAeC,OAAMC,OAAO,CAChC,IAAO,CAAA;YACLP;YACAG;YACAD,QAAQ,IAAMA,OAAOD;YACrBG;QACF,CAAA,GACA;QAACJ;QAAQC;QAAUC;QAAQC;QAASC;KAAc;IAGpD,qBAAO,qBAACI,oDAAyB,CAACC,QAAQ;QAACC,OAAOL;OAAeN,MAAMY,QAAQ;AACjF"}
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
MotionBehaviourProvider: function() {
return MotionBehaviourProvider;
},
useMotionBehaviourContext: function() {
return useMotionBehaviourContext;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const MotionBehaviourContext = _react.createContext(undefined);
const MotionBehaviourProvider = MotionBehaviourContext.Provider;
const useMotionBehaviourContext = ()=>{
var _React_useContext;
return (_React_useContext = _react.useContext(MotionBehaviourContext)) !== null && _React_useContext !== void 0 ? _React_useContext : 'default';
};
@@ -0,0 +1 @@
{"version":3,"sources":["../src/contexts/MotionBehaviourContext.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * Specifies the behaviour of child motion component under @see MotionBehaviourProvider.\n */\nexport type MotionBehaviourType = 'skip' | 'default';\n\nconst MotionBehaviourContext = React.createContext<MotionBehaviourType | undefined>(undefined);\n\nexport const MotionBehaviourProvider = MotionBehaviourContext.Provider;\nexport const useMotionBehaviourContext = () => React.useContext(MotionBehaviourContext) ?? 'default';\n"],"names":["MotionBehaviourProvider","useMotionBehaviourContext","MotionBehaviourContext","React","createContext","undefined","Provider","useContext"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IASaA,uBAAuB;eAAvBA;;IACAC,yBAAyB;eAAzBA;;;;iEAVU;AAOvB,MAAMC,yBAAyBC,OAAMC,aAAa,CAAkCC;AAE7E,MAAML,0BAA0BE,uBAAuBI,QAAQ;AAC/D,MAAML,4BAA4B;QAAME;WAAAA,CAAAA,oBAAAA,OAAMI,UAAU,CAACL,qCAAjBC,+BAAAA,oBAA4C;AAAQ"}
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "PresenceGroupChildContext", {
enumerable: true,
get: function() {
return PresenceGroupChildContext;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const PresenceGroupChildContext = _react.createContext(undefined);
@@ -0,0 +1 @@
{"version":3,"sources":["../src/contexts/PresenceGroupChildContext.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * @internal\n */\nexport type PresenceGroupChildContextValue = {\n appear: boolean;\n visible: boolean;\n unmountOnExit: boolean;\n\n onExit: () => void;\n};\n\n/**\n * @internal\n */\nexport const PresenceGroupChildContext = React.createContext<PresenceGroupChildContextValue | undefined>(undefined);\n"],"names":["PresenceGroupChildContext","React","createContext","undefined"],"rangeMappings":";;;;;;;;;;;;","mappings":";;;;+BAgBaA;;;eAAAA;;;;iEAhBU;AAgBhB,MAAMA,4BAA4BC,OAAMC,aAAa,CAA6CC"}
@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createMotionComponent", {
enumerable: true,
get: function() {
return createMotionComponent;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _useAnimateAtoms = require("../hooks/useAnimateAtoms");
const _useMotionImperativeRef = require("../hooks/useMotionImperativeRef");
const _useIsReducedMotion = require("../hooks/useIsReducedMotion");
const _getChildElement = require("../utils/getChildElement");
const _MotionBehaviourContext = require("../contexts/MotionBehaviourContext");
function createMotionComponent(value) {
const Atom = (props)=>{
'use no memo';
const { children, imperativeRef, onMotionFinish: onMotionFinishProp, onMotionStart: onMotionStartProp, onMotionCancel: onMotionCancelProp, ..._rest } = props;
const params = _rest;
const child = (0, _getChildElement.getChildElement)(children);
const handleRef = (0, _useMotionImperativeRef.useMotionImperativeRef)(imperativeRef);
const elementRef = _react.useRef();
const skipMotions = (0, _MotionBehaviourContext.useMotionBehaviourContext)() === 'skip';
const optionsRef = _react.useRef({
skipMotions,
params
});
const animateAtoms = (0, _useAnimateAtoms.useAnimateAtoms)();
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);
});
const onMotionCancel = (0, _reactutilities.useEventCallback)(()=>{
onMotionCancelProp === null || onMotionCancelProp === void 0 ? void 0 : onMotionCancelProp(null);
});
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
// Heads up!
// We store the params in a ref to avoid re-rendering the component when the params change.
optionsRef.current = {
skipMotions,
params
};
});
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
const element = elementRef.current;
if (element) {
const atoms = typeof value === 'function' ? value({
element,
...optionsRef.current.params
}) : value;
onMotionStart();
const handle = animateAtoms(element, atoms, {
isReducedMotion: isReducedMotion()
});
handleRef.current = handle;
handle.setMotionEndCallbacks(onMotionFinish, onMotionCancel);
if (optionsRef.current.skipMotions) {
handle.finish();
}
return ()=>{
handle.cancel();
};
}
}, [
animateAtoms,
handleRef,
isReducedMotion,
onMotionFinish,
onMotionStart,
onMotionCancel
]);
return _react.cloneElement(children, {
ref: (0, _reactutilities.useMergedRefs)(elementRef, child.ref)
});
};
return Atom;
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
MOTION_DEFINITION: function() {
return MOTION_DEFINITION;
},
createPresenceComponent: function() {
return createPresenceComponent;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _PresenceGroupChildContext = require("../contexts/PresenceGroupChildContext");
const _useAnimateAtoms = require("../hooks/useAnimateAtoms");
const _useMotionImperativeRef = require("../hooks/useMotionImperativeRef");
const _useMountedState = require("../hooks/useMountedState");
const _useIsReducedMotion = require("../hooks/useIsReducedMotion");
const _getChildElement = require("../utils/getChildElement");
const _MotionBehaviourContext = require("../contexts/MotionBehaviourContext");
const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');
function shouldSkipAnimation(appear, isFirstMount, visible) {
return !appear && isFirstMount && !!visible;
}
function createPresenceComponent(value) {
return Object.assign((props)=>{
'use no memo';
const itemContext = _react.useContext(_PresenceGroupChildContext.PresenceGroupChildContext);
const merged = {
...itemContext,
...props
};
const skipMotions = (0, _MotionBehaviourContext.useMotionBehaviourContext)() === 'skip';
const { appear, children, imperativeRef, onExit, onMotionFinish, onMotionStart, onMotionCancel, visible, unmountOnExit, ..._rest } = merged;
const params = _rest;
const [mounted, setMounted] = (0, _useMountedState.useMountedState)(visible, unmountOnExit);
const child = (0, _getChildElement.getChildElement)(children);
const handleRef = (0, _useMotionImperativeRef.useMotionImperativeRef)(imperativeRef);
const elementRef = _react.useRef();
const ref = (0, _reactutilities.useMergedRefs)(elementRef, child.ref);
const optionsRef = _react.useRef({
appear,
params,
skipMotions
});
const animateAtoms = (0, _useAnimateAtoms.useAnimateAtoms)();
const isFirstMount = (0, _reactutilities.useFirstMount)();
const isReducedMotion = (0, _useIsReducedMotion.useIsReducedMotion)();
const handleMotionStart = (0, _reactutilities.useEventCallback)((direction)=>{
onMotionStart === null || onMotionStart === void 0 ? void 0 : onMotionStart(null, {
direction
});
});
const handleMotionFinish = (0, _reactutilities.useEventCallback)((direction)=>{
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, {
direction
});
if (direction === 'exit' && unmountOnExit) {
setMounted(false);
onExit === null || onExit === void 0 ? void 0 : onExit();
}
});
const handleMotionCancel = (0, _reactutilities.useEventCallback)((direction)=>{
onMotionCancel === null || onMotionCancel === void 0 ? void 0 : onMotionCancel(null, {
direction
});
});
(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,
params,
skipMotions
};
});
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
const element = elementRef.current;
if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {
return;
}
const presenceMotion = typeof value === 'function' ? value({
element,
...optionsRef.current.params
}) : value;
const atoms = visible ? presenceMotion.enter : presenceMotion.exit;
const direction = visible ? 'enter' : 'exit';
const applyInitialStyles = !visible && isFirstMount;
const skipAnimation = optionsRef.current.skipMotions;
if (!applyInitialStyles) {
handleMotionStart(direction);
}
const handle = animateAtoms(element, atoms, {
isReducedMotion: isReducedMotion()
});
if (applyInitialStyles) {
// Heads up!
// .finish() is used in this case to skip animation and apply animation styles immediately
handle.finish();
return;
}
handleRef.current = handle;
handle.setMotionEndCallbacks(()=>handleMotionFinish(direction), ()=>handleMotionCancel(direction));
if (skipAnimation) {
handle.finish();
}
return ()=>{
handle.cancel();
};
}, // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders
// eslint-disable-next-line react-hooks/exhaustive-deps
[
animateAtoms,
handleRef,
isReducedMotion,
handleMotionFinish,
handleMotionStart,
handleMotionCancel,
visible
]);
if (mounted) {
return _react.cloneElement(child, {
ref
});
}
return null;
}, {
// Heads up!
// Always normalize it to a function to simplify types
[MOTION_DEFINITION]: typeof value === 'function' ? value : ()=>value
});
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createPresenceComponentVariant: function() {
return createPresenceComponentVariant;
},
overridePresenceMotion: function() {
return overridePresenceMotion;
}
});
const _createPresenceComponent = require("./createPresenceComponent");
function overridePresenceMotion(presenceMotion, override) {
return (...args)=>{
const { enter, exit } = presenceMotion(...args);
return {
enter: {
...enter,
...override.all,
...override.enter
},
exit: {
...exit,
...override.all,
...override.exit
}
};
};
}
function createPresenceComponentVariant(component, override) {
return (0, _createPresenceComponent.createPresenceComponent)(overridePresenceMotion(component[_createPresenceComponent.MOTION_DEFINITION], override));
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/factories/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,8BAA8B;eAA9BA;;IAdAC,sBAAsB;eAAtBA;;;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,gDAAuB,EAACR,uBAAuBO,SAAS,CAACE,0CAAiB,CAAC,EAAEP;AACtF"}
@@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
DEFAULT_ANIMATION_OPTIONS: function() {
return DEFAULT_ANIMATION_OPTIONS;
},
useAnimateAtoms: function() {
return useAnimateAtoms;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const DEFAULT_ANIMATION_OPTIONS = {
fill: 'forwards'
};
// A motion atom's default reduced motion is a simple 1 ms duration.
// But an atom can define a custom reduced motion, overriding keyframes and/or params like duration, easing, iterations, etc.
const DEFAULT_REDUCED_MOTION_ATOM = {
duration: 1
};
function useAnimateAtomsInSupportedEnvironment() {
var _window_Animation;
// eslint-disable-next-line @nx/workspace-no-restricted-globals
const SUPPORTS_PERSIST = typeof window !== 'undefined' && typeof ((_window_Animation = window.Animation) === null || _window_Animation === void 0 ? void 0 : _window_Animation.prototype.persist) === 'function';
return _react.useCallback((element, value, options)=>{
const atoms = Array.isArray(value) ? value : [
value
];
const { isReducedMotion } = options;
const animations = atoms.map((motion)=>{
// Grab the custom reduced motion definition if it exists, or fall back to the default reduced motion.
const { keyframes: motionKeyframes, reducedMotion = DEFAULT_REDUCED_MOTION_ATOM, ...params } = motion;
// Grab the reduced motion keyframes if they exist, or fall back to the regular keyframes.
const { keyframes: reducedMotionKeyframes = motionKeyframes, ...reducedMotionParams } = reducedMotion;
const animationKeyframes = isReducedMotion ? reducedMotionKeyframes : motionKeyframes;
const animationParams = {
...DEFAULT_ANIMATION_OPTIONS,
...params,
// Use reduced motion overrides (e.g. duration, easing) when reduced motion is enabled
...isReducedMotion && reducedMotionParams
};
const animation = element.animate(animationKeyframes, animationParams);
if (SUPPORTS_PERSIST) {
animation.persist();
} else {
const resultKeyframe = animationKeyframes[animationKeyframes.length - 1];
var _element_style;
Object.assign((_element_style = element.style) !== null && _element_style !== void 0 ? _element_style : {}, resultKeyframe);
}
return animation;
});
return {
set playbackRate (rate){
animations.forEach((animation)=>{
animation.playbackRate = rate;
});
},
setMotionEndCallbacks (onfinish, oncancel) {
// Heads up!
// This could use "Animation:finished", but it's causing a memory leak in Chromium.
// See: https://issues.chromium.org/u/2/issues/383016426
const promises = animations.map((animation)=>{
return new Promise((resolve, reject)=>{
animation.onfinish = ()=>resolve();
animation.oncancel = ()=>reject();
});
});
Promise.all(promises).then(()=>{
onfinish();
}).catch(()=>{
oncancel();
});
},
cancel: ()=>{
animations.forEach((animation)=>{
animation.cancel();
});
},
pause: ()=>{
animations.forEach((animation)=>{
animation.pause();
});
},
play: ()=>{
animations.forEach((animation)=>{
animation.play();
});
},
finish: ()=>{
animations.forEach((animation)=>{
animation.finish();
});
}
};
}, [
SUPPORTS_PERSIST
]);
}
/**
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
*
* @see https://github.com/microsoft/fluentui/issues/31701
*/ function useAnimateAtomsInTestEnvironment() {
const [count, setCount] = _react.useState(0);
const callbackRef = _react.useRef();
const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();
_react.useEffect(()=>{
if (count > 0) {
var _callbackRef_current;
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
}
}, [
count
]);
return _react.useCallback((element, value, options)=>{
const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';
// Heads up!
// If the environment supports Web Animations API, we can use the native implementation.
if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {
return realAnimateAtoms(element, value, options);
}
return {
setMotionEndCallbacks (onfinish) {
callbackRef.current = onfinish;
setCount((v)=>v + 1);
},
set playbackRate (rate){
/* no-op */ },
cancel () {
/* no-op */ },
pause () {
/* no-op */ },
play () {
/* no-op */ },
finish () {
/* no-op */ }
};
}, [
realAnimateAtoms
]);
}
function useAnimateAtoms() {
'use no memo';
if (process.env.NODE_ENV === 'test') {
// eslint-disable-next-line react-hooks/rules-of-hooks
return useAnimateAtomsInTestEnvironment();
}
// eslint-disable-next-line react-hooks/rules-of-hooks
return useAnimateAtomsInSupportedEnvironment();
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useIsReducedMotion", {
enumerable: true,
get: function() {
return useIsReducedMotion;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactsharedcontexts = require("@fluentui/react-shared-contexts");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const REDUCED_MEDIA_QUERY = 'screen and (prefers-reduced-motion: reduce)';
function useIsReducedMotion() {
const { targetDocument } = (0, _reactsharedcontexts.useFluent_unstable)();
var _targetDocument_defaultView;
const targetWindow = (_targetDocument_defaultView = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) !== null && _targetDocument_defaultView !== void 0 ? _targetDocument_defaultView : null;
const queryValue = _react.useRef(false);
const isEnabled = _react.useCallback(()=>queryValue.current, []);
(0, _reactutilities.useIsomorphicLayoutEffect)(()=>{
if (targetWindow === null || typeof targetWindow.matchMedia !== 'function') {
return;
}
const queryMatch = targetWindow.matchMedia(REDUCED_MEDIA_QUERY);
if (queryMatch.matches) {
queryValue.current = true;
}
const matchListener = (e)=>{
queryValue.current = e.matches;
};
queryMatch.addEventListener('change', matchListener);
return ()=>{
queryMatch.removeEventListener('change', matchListener);
};
}, [
targetWindow
]);
return isEnabled;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useIsReducedMotion.ts"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nconst REDUCED_MEDIA_QUERY = 'screen and (prefers-reduced-motion: reduce)';\n\n// TODO: find a better approach there as each hook creates a separate subscription\n\nexport function useIsReducedMotion(): () => boolean {\n const { targetDocument } = useFluent();\n const targetWindow: Window | null = targetDocument?.defaultView ?? null;\n\n const queryValue = React.useRef<boolean>(false);\n const isEnabled = React.useCallback(() => queryValue.current, []);\n\n useIsomorphicLayoutEffect(() => {\n if (targetWindow === null || typeof targetWindow.matchMedia !== 'function') {\n return;\n }\n\n const queryMatch = targetWindow.matchMedia(REDUCED_MEDIA_QUERY);\n\n if (queryMatch.matches) {\n queryValue.current = true;\n }\n\n const matchListener = (e: MediaQueryListEvent) => {\n queryValue.current = e.matches;\n };\n\n queryMatch.addEventListener('change', matchListener);\n\n return () => {\n queryMatch.removeEventListener('change', matchListener);\n };\n }, [targetWindow]);\n\n return isEnabled;\n}\n"],"names":["useIsReducedMotion","REDUCED_MEDIA_QUERY","targetDocument","useFluent","targetWindow","defaultView","queryValue","React","useRef","isEnabled","useCallback","current","useIsomorphicLayoutEffect","matchMedia","queryMatch","matches","matchListener","e","addEventListener","removeEventListener"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAQgBA;;;eAAAA;;;;qCARgC;gCACN;iEACnB;AAEvB,MAAMC,sBAAsB;AAIrB,SAASD;IACd,MAAM,EAAEE,cAAc,EAAE,GAAGC,IAAAA,uCAAS;QACAD;IAApC,MAAME,eAA8BF,CAAAA,8BAAAA,2BAAAA,qCAAAA,eAAgBG,WAAW,cAA3BH,yCAAAA,8BAA+B;IAEnE,MAAMI,aAAaC,OAAMC,MAAM,CAAU;IACzC,MAAMC,YAAYF,OAAMG,WAAW,CAAC,IAAMJ,WAAWK,OAAO,EAAE,EAAE;IAEhEC,IAAAA,yCAAyB,EAAC;QACxB,IAAIR,iBAAiB,QAAQ,OAAOA,aAAaS,UAAU,KAAK,YAAY;YAC1E;QACF;QAEA,MAAMC,aAAaV,aAAaS,UAAU,CAACZ;QAE3C,IAAIa,WAAWC,OAAO,EAAE;YACtBT,WAAWK,OAAO,GAAG;QACvB;QAEA,MAAMK,gBAAgB,CAACC;YACrBX,WAAWK,OAAO,GAAGM,EAAEF,OAAO;QAChC;QAEAD,WAAWI,gBAAgB,CAAC,UAAUF;QAEtC,OAAO;YACLF,WAAWK,mBAAmB,CAAC,UAAUH;QAC3C;IACF,GAAG;QAACZ;KAAa;IAEjB,OAAOK;AACT"}
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useMotionImperativeRef", {
enumerable: true,
get: function() {
return useMotionImperativeRef;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
function useMotionImperativeRef(imperativeRef) {
const animationRef = _react.useRef();
_react.useImperativeHandle(imperativeRef, ()=>({
setPlayState: (state)=>{
if (state === 'running') {
var _animationRef_current;
(_animationRef_current = animationRef.current) === null || _animationRef_current === void 0 ? void 0 : _animationRef_current.play();
}
if (state === 'paused') {
var _animationRef_current1;
(_animationRef_current1 = animationRef.current) === null || _animationRef_current1 === void 0 ? void 0 : _animationRef_current1.pause();
}
},
setPlaybackRate: (rate)=>{
if (animationRef.current) {
animationRef.current.playbackRate = rate;
}
}
}));
return animationRef;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMotionImperativeRef.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, MotionImperativeRef } from '../types';\n\nexport function useMotionImperativeRef(imperativeRef: React.Ref<MotionImperativeRef | undefined> | undefined) {\n const animationRef = React.useRef<AnimationHandle | undefined>();\n\n React.useImperativeHandle(imperativeRef, () => ({\n setPlayState: state => {\n if (state === 'running') {\n animationRef.current?.play();\n }\n\n if (state === 'paused') {\n animationRef.current?.pause();\n }\n },\n setPlaybackRate: rate => {\n if (animationRef.current) {\n animationRef.current.playbackRate = rate;\n }\n },\n }));\n\n return animationRef;\n}\n"],"names":["useMotionImperativeRef","imperativeRef","animationRef","React","useRef","useImperativeHandle","setPlayState","state","current","play","pause","setPlaybackRate","rate","playbackRate"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAGgBA;;;eAAAA;;;;iEAHO;AAGhB,SAASA,uBAAuBC,aAAqE;IAC1G,MAAMC,eAAeC,OAAMC,MAAM;IAEjCD,OAAME,mBAAmB,CAACJ,eAAe,IAAO,CAAA;YAC9CK,cAAcC,CAAAA;gBACZ,IAAIA,UAAU,WAAW;wBACvBL;qBAAAA,wBAAAA,aAAaM,OAAO,cAApBN,4CAAAA,sBAAsBO,IAAI;gBAC5B;gBAEA,IAAIF,UAAU,UAAU;wBACtBL;qBAAAA,yBAAAA,aAAaM,OAAO,cAApBN,6CAAAA,uBAAsBQ,KAAK;gBAC7B;YACF;YACAC,iBAAiBC,CAAAA;gBACf,IAAIV,aAAaM,OAAO,EAAE;oBACxBN,aAAaM,OAAO,CAACK,YAAY,GAAGD;gBACtC;YACF;QACF,CAAA;IAEA,OAAOV;AACT"}
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "useMountedState", {
enumerable: true,
get: function() {
return useMountedState;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
function useMountedState(visible = false, unmountOnExit = false) {
const mountedRef = _react.useRef(unmountOnExit ? visible : true);
const forceUpdate = (0, _reactutilities.useForceUpdate)();
const setMounted = _react.useCallback((newValue)=>{
if (mountedRef.current !== newValue) {
mountedRef.current = newValue;
forceUpdate();
}
}, [
forceUpdate
]);
_react.useEffect(()=>{
if (visible) {
mountedRef.current = visible;
}
});
return [
visible || mountedRef.current,
setMounted
];
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMountedState.ts"],"sourcesContent":["import { useForceUpdate } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\n/**\n * This hook manages the mounted state of a component, based on the \"visible\" and \"unmountOnExit\" props.\n * It simulates the behavior of getDerivedStateFromProps(), which is not available in functional components.\n */\nexport function useMountedState(\n visible: boolean = false,\n unmountOnExit: boolean = false,\n): [boolean, (value: boolean) => void] {\n const mountedRef = React.useRef<boolean>(unmountOnExit ? visible : true);\n const forceUpdate = useForceUpdate();\n\n const setMounted = React.useCallback(\n (newValue: boolean) => {\n if (mountedRef.current !== newValue) {\n mountedRef.current = newValue;\n forceUpdate();\n }\n },\n [forceUpdate],\n );\n\n React.useEffect(() => {\n if (visible) {\n mountedRef.current = visible;\n }\n });\n\n return [visible || mountedRef.current, setMounted];\n}\n"],"names":["useMountedState","visible","unmountOnExit","mountedRef","React","useRef","forceUpdate","useForceUpdate","setMounted","useCallback","newValue","current","useEffect"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAOgBA;;;eAAAA;;;;gCAPe;iEACR;AAMhB,SAASA,gBACdC,UAAmB,KAAK,EACxBC,gBAAyB,KAAK;IAE9B,MAAMC,aAAaC,OAAMC,MAAM,CAAUH,gBAAgBD,UAAU;IACnE,MAAMK,cAAcC,IAAAA,8BAAc;IAElC,MAAMC,aAAaJ,OAAMK,WAAW,CAClC,CAACC;QACC,IAAIP,WAAWQ,OAAO,KAAKD,UAAU;YACnCP,WAAWQ,OAAO,GAAGD;YACrBJ;QACF;IACF,GACA;QAACA;KAAY;IAGfF,OAAMQ,SAAS,CAAC;QACd,IAAIX,SAAS;YACXE,WAAWQ,OAAO,GAAGV;QACvB;IACF;IAEA,OAAO;QAACA,WAAWE,WAAWQ,OAAO;QAAEH;KAAW;AACpD"}
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
MotionBehaviourProvider: function() {
return _MotionBehaviourContext.MotionBehaviourProvider;
},
PresenceGroup: function() {
return _PresenceGroup.PresenceGroup;
},
createMotionComponent: function() {
return _createMotionComponent.createMotionComponent;
},
createPresenceComponent: function() {
return _createPresenceComponent.createPresenceComponent;
},
createPresenceComponentVariant: function() {
return _createPresenceComponentVariant.createPresenceComponentVariant;
},
curves: function() {
return _motionTokens.curves;
},
durations: function() {
return _motionTokens.durations;
},
motionTokens: function() {
return _motionTokens.motionTokens;
},
presenceMotionSlot: function() {
return _presenceMotionSlot.presenceMotionSlot;
}
});
const _motionTokens = require("./motions/motionTokens");
const _createMotionComponent = require("./factories/createMotionComponent");
const _createPresenceComponent = require("./factories/createPresenceComponent");
const _createPresenceComponentVariant = require("./factories/createPresenceComponentVariant");
const _PresenceGroup = require("./components/PresenceGroup");
const _presenceMotionSlot = require("./slots/presenceMotionSlot");
const _MotionBehaviourContext = require("./contexts/MotionBehaviourContext");
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/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 MotionParam,\n} from './types';\n\nexport { MotionBehaviourProvider } from './contexts/MotionBehaviourContext';\n"],"names":["MotionBehaviourProvider","PresenceGroup","createMotionComponent","createPresenceComponent","createPresenceComponentVariant","curves","durations","motionTokens","presenceMotionSlot"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IAwBSA,uBAAuB;eAAvBA,+CAAuB;;IAdvBC,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;wCAYzB"}
@@ -0,0 +1,58 @@
// Copied from packages/tokens/src/global/durations.ts
// Values are numeric in milliseconds for ease of use in Web Animations API
// (rather than parsing '__ms')
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
curves: function() {
return curves;
},
durations: function() {
return durations;
},
motionTokens: function() {
return motionTokens;
}
});
const durations = {
durationUltraFast: 50,
durationFaster: 100,
durationFast: 150,
durationNormal: 200,
durationGentle: 250,
durationSlow: 300,
durationSlower: 400,
durationUltraSlow: 500
};
const curves = {
curveAccelerateMax: 'cubic-bezier(0.9,0.1,1,0.2)',
curveAccelerateMid: 'cubic-bezier(1,0,1,1)',
curveAccelerateMin: 'cubic-bezier(0.8,0,0.78,1)',
curveDecelerateMax: 'cubic-bezier(0.1,0.9,0.2,1)',
curveDecelerateMid: 'cubic-bezier(0,0,0,1)',
curveDecelerateMin: 'cubic-bezier(0.33,0,0.1,1)',
curveEasyEaseMax: 'cubic-bezier(0.8,0,0.2,1)',
curveEasyEase: 'cubic-bezier(0.33,0,0.67,1)',
curveLinear: 'cubic-bezier(0,0,1,1)'
};
const motionTokens = {
...durations,
...curves
}; /*
TODO: enforce naming conventions when TypeScript 4.4 features are supported in Fluent:
type DurationKey = `duration${Capitalize<string>}`;
type CurveKey = `curve${Capitalize<string>}`;
type CurveValue = `cubic-bezier(${number},${number},${number},${number})`;
type DurationTokens = Record<DurationKey, number>;
type CurveTokens = Record<CurveKey, CurveValue>;
*/
@@ -0,0 +1 @@
{"version":3,"sources":["../src/motions/motionTokens.ts"],"sourcesContent":["// Copied from packages/tokens/src/global/durations.ts\n// Values are numeric in milliseconds for ease of use in Web Animations API\n// (rather than parsing '__ms')\nexport const durations = {\n durationUltraFast: 50,\n durationFaster: 100,\n durationFast: 150,\n durationNormal: 200,\n durationGentle: 250,\n durationSlow: 300,\n durationSlower: 400,\n durationUltraSlow: 500,\n} as const;\n\n// Copied from packages/tokens/src/global/curves.ts\n// Names and values are preserved exactly\nexport const curves = {\n curveAccelerateMax: 'cubic-bezier(0.9,0.1,1,0.2)',\n curveAccelerateMid: 'cubic-bezier(1,0,1,1)',\n curveAccelerateMin: 'cubic-bezier(0.8,0,0.78,1)',\n curveDecelerateMax: 'cubic-bezier(0.1,0.9,0.2,1)',\n curveDecelerateMid: 'cubic-bezier(0,0,0,1)',\n curveDecelerateMin: 'cubic-bezier(0.33,0,0.1,1)',\n curveEasyEaseMax: 'cubic-bezier(0.8,0,0.2,1)',\n curveEasyEase: 'cubic-bezier(0.33,0,0.67,1)',\n curveLinear: 'cubic-bezier(0,0,1,1)',\n} as const;\n\n// A merged flat lookup for convenience\nexport const motionTokens = {\n ...durations,\n ...curves,\n};\n\n/*\nTODO: enforce naming conventions when TypeScript 4.4 features are supported in Fluent:\n\ntype DurationKey = `duration${Capitalize<string>}`;\ntype CurveKey = `curve${Capitalize<string>}`;\ntype CurveValue = `cubic-bezier(${number},${number},${number},${number})`;\n\ntype DurationTokens = Record<DurationKey, number>;\ntype CurveTokens = Record<CurveKey, CurveValue>;\n*/\n"],"names":["curves","durations","motionTokens","durationUltraFast","durationFaster","durationFast","durationNormal","durationGentle","durationSlow","durationSlower","durationUltraSlow","curveAccelerateMax","curveAccelerateMid","curveAccelerateMin","curveDecelerateMax","curveDecelerateMid","curveDecelerateMin","curveEasyEaseMax","curveEasyEase","curveLinear"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,sDAAsD;AACtD,2EAA2E;AAC3E,+BAA+B;;;;;;;;;;;;IAclBA,MAAM;eAANA;;IAbAC,SAAS;eAATA;;IA0BAC,YAAY;eAAZA;;;AA1BN,MAAMD,YAAY;IACvBE,mBAAmB;IACnBC,gBAAgB;IAChBC,cAAc;IACdC,gBAAgB;IAChBC,gBAAgB;IAChBC,cAAc;IACdC,gBAAgB;IAChBC,mBAAmB;AACrB;AAIO,MAAMV,SAAS;IACpBW,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,kBAAkB;IAClBC,eAAe;IACfC,aAAa;AACf;AAGO,MAAMjB,eAAe;IAC1B,GAAGD,SAAS;IACZ,GAAGD,MAAM;AACX,GAEA;;;;;;;;;AASA"}
@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "presenceMotionSlot", {
enumerable: true,
get: function() {
return presenceMotionSlot;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _reactutilities = require("@fluentui/react-utilities");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
function presenceMotionSlot(motion, options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const { as, children, ...rest } = motion !== null && motion !== void 0 ? motion : {};
if (process.env.NODE_ENV !== 'production') {
if (typeof as !== 'undefined') {
throw new Error(`@fluentui/react-motion: "as" property is not supported on motion slots.`);
}
}
if (motion === null) {
// Heads up!
// Render function is used there to avoid rendering a motion component and handle unmounting logic
const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;
const renderFn = (_, props)=>isUnmounted ? null : /*#__PURE__*/ _react.createElement(_react.Fragment, null, props.children);
/**
* Casting is required here as SlotComponentType is a function, not an object.
* Although SlotComponentType has a function signature, it is still just an object.
* This is required to make a slot callable (JSX compatible), this is the exact same approach
* that is used on `@types/react` components
*/ return {
[_reactutilities.SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,
[_reactutilities.SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
};
}
/**
* Casting is required here as SlotComponentType is a function, not an object.
* Although SlotComponentType has a function signature, it is still just an object.
* This is required to make a slot callable (JSX compatible), this is the exact same approach
* that is used on `@types/react` components
*/ const propsWithMetadata = {
...options.defaultProps,
...rest,
[_reactutilities.SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
};
if (typeof children === 'function') {
propsWithMetadata[_reactutilities.SLOT_RENDER_FUNCTION_SYMBOL] = children;
}
return propsWithMetadata;
}
File diff suppressed because one or more lines are too long
+4
View File
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"rangeMappings":"","mappings":""}
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getChildElement", {
enumerable: true,
get: function() {
return getChildElement;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
const _reactis = /*#__PURE__*/ _interop_require_wildcard._(require("react-is"));
function getChildElement(children) {
try {
const child = _react.Children.only(children);
if (typeof child.type === 'string' || _reactis.isForwardRef(child)) {
return child;
}
// We don't need to do anything here: we catch the exception from React to throw a more meaningful error
// eslint-disable-next-line no-empty
} catch {}
throw new Error([
'@fluentui/react-motion: Invalid child element.',
'\n',
'Motion factories require a single child element to be passed. ',
'That element element should support ref forwarding i.e. it should be either an intrinsic element (e.g. div) or a component that uses React.forwardRef().'
].join(''));
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getChildElement.ts"],"sourcesContent":["import * as React from 'react';\nimport * as ReactIs from 'react-is';\n\nexport function getChildElement(children: React.ReactElement) {\n try {\n const child = React.Children.only(children) as React.ReactElement & { ref: React.Ref<HTMLElement> };\n\n if (typeof child.type === 'string' || ReactIs.isForwardRef(child)) {\n return child as React.ReactElement & { ref: React.Ref<HTMLElement> };\n }\n\n // We don't need to do anything here: we catch the exception from React to throw a more meaningful error\n // eslint-disable-next-line no-empty\n } catch {}\n\n throw new Error(\n [\n '@fluentui/react-motion: Invalid child element.',\n '\\n',\n 'Motion factories require a single child element to be passed. ',\n 'That element element should support ref forwarding i.e. it should be either an intrinsic element (e.g. div) or a component that uses React.forwardRef().',\n ].join(''),\n );\n}\n"],"names":["getChildElement","children","child","React","Children","only","type","ReactIs","isForwardRef","Error","join"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAGgBA;;;eAAAA;;;;iEAHO;mEACE;AAElB,SAASA,gBAAgBC,QAA4B;IAC1D,IAAI;QACF,MAAMC,QAAQC,OAAMC,QAAQ,CAACC,IAAI,CAACJ;QAElC,IAAI,OAAOC,MAAMI,IAAI,KAAK,YAAYC,SAAQC,YAAY,CAACN,QAAQ;YACjE,OAAOA;QACT;IAEA,wGAAwG;IACxG,oCAAoC;IACtC,EAAE,OAAM,CAAC;IAET,MAAM,IAAIO,MACR;QACE;QACA;QACA;QACA;KACD,CAACC,IAAI,CAAC;AAEX"}
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getChildMapping", {
enumerable: true,
get: function() {
return getChildMapping;
}
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
function getChildMapping(children) {
const childMapping = {};
if (children) {
_react.Children.toArray(children).forEach((child)=>{
if (_react.isValidElement(child)) {
var _child_key;
childMapping[(_child_key = child.key) !== null && _child_key !== void 0 ? _child_key : ''] = {
appear: false,
element: child,
visible: true,
unmountOnExit: true
};
}
});
}
return childMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/getChildMapping.ts"],"sourcesContent":["import * as React from 'react';\nimport type { PresenceGroupChildMapping } from './types';\n\n/**\n * Given `children`, return an object mapping key to child.\n */\nexport function getChildMapping(children: React.ReactNode | undefined) {\n const childMapping: PresenceGroupChildMapping = {};\n\n if (children) {\n React.Children.toArray(children).forEach(child => {\n if (React.isValidElement(child)) {\n childMapping[child.key ?? ''] = {\n appear: false,\n element: child,\n visible: true,\n unmountOnExit: true,\n };\n }\n });\n }\n\n return childMapping;\n}\n"],"names":["getChildMapping","children","childMapping","React","Children","toArray","forEach","child","isValidElement","key","appear","element","visible","unmountOnExit"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAMgBA;;;eAAAA;;;;iEANO;AAMhB,SAASA,gBAAgBC,QAAqC;IACnE,MAAMC,eAA0C,CAAC;IAEjD,IAAID,UAAU;QACZE,OAAMC,QAAQ,CAACC,OAAO,CAACJ,UAAUK,OAAO,CAACC,CAAAA;YACvC,IAAIJ,OAAMK,cAAc,CAACD,QAAQ;oBAClBA;gBAAbL,YAAY,CAACK,CAAAA,aAAAA,MAAME,GAAG,cAATF,wBAAAA,aAAa,GAAG,GAAG;oBAC9BG,QAAQ;oBACRC,SAASJ;oBACTK,SAAS;oBACTC,eAAe;gBACjB;YACF;QACF;IACF;IAEA,OAAOX;AACT"}
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getNextChildMapping", {
enumerable: true,
get: function() {
return getNextChildMapping;
}
});
const _mergeChildMappings = require("./mergeChildMappings");
function getNextChildMapping(prevChildMapping, nextChildMapping) {
const childrenMapping = (0, _mergeChildMappings.mergeChildMappings)(prevChildMapping, nextChildMapping);
Object.entries(childrenMapping).forEach(([key, childDefinition])=>{
const hasPrev = key in prevChildMapping;
const hasNext = key in nextChildMapping;
if (hasNext) {
// Case 1: item hasn't changed transition states
if (hasPrev) {
childrenMapping[key] = {
...childDefinition
};
return;
}
// Case 2: item is new (entering)
childrenMapping[key] = {
...childDefinition,
appear: true,
visible: true
};
return;
}
// Case 3: item is leaving
childrenMapping[key] = {
...childDefinition,
visible: false
};
});
return childrenMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/getNextChildMapping.ts"],"sourcesContent":["import { mergeChildMappings } from './mergeChildMappings';\nimport type { PresenceGroupChildMapping } from './types';\n\nexport function getNextChildMapping(\n prevChildMapping: PresenceGroupChildMapping,\n nextChildMapping: PresenceGroupChildMapping,\n) {\n const childrenMapping = mergeChildMappings(prevChildMapping, nextChildMapping);\n\n Object.entries(childrenMapping).forEach(([key, childDefinition]) => {\n const hasPrev = key in prevChildMapping;\n const hasNext = key in nextChildMapping;\n\n if (hasNext) {\n // Case 1: item hasn't changed transition states\n if (hasPrev) {\n childrenMapping[key] = { ...childDefinition };\n return;\n }\n\n // Case 2: item is new (entering)\n childrenMapping[key] = {\n ...childDefinition,\n appear: true,\n visible: true,\n };\n return;\n }\n\n // Case 3: item is leaving\n childrenMapping[key] = {\n ...childDefinition,\n visible: false,\n };\n });\n\n return childrenMapping;\n}\n"],"names":["getNextChildMapping","prevChildMapping","nextChildMapping","childrenMapping","mergeChildMappings","Object","entries","forEach","key","childDefinition","hasPrev","hasNext","appear","visible"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAGgBA;;;eAAAA;;;oCAHmB;AAG5B,SAASA,oBACdC,gBAA2C,EAC3CC,gBAA2C;IAE3C,MAAMC,kBAAkBC,IAAAA,sCAAkB,EAACH,kBAAkBC;IAE7DG,OAAOC,OAAO,CAACH,iBAAiBI,OAAO,CAAC,CAAC,CAACC,KAAKC,gBAAgB;QAC7D,MAAMC,UAAUF,OAAOP;QACvB,MAAMU,UAAUH,OAAON;QAEvB,IAAIS,SAAS;YACX,gDAAgD;YAChD,IAAID,SAAS;gBACXP,eAAe,CAACK,IAAI,GAAG;oBAAE,GAAGC,eAAe;gBAAC;gBAC5C;YACF;YAEA,iCAAiC;YACjCN,eAAe,CAACK,IAAI,GAAG;gBACrB,GAAGC,eAAe;gBAClBG,QAAQ;gBACRC,SAAS;YACX;YACA;QACF;QAEA,0BAA0B;QAC1BV,eAAe,CAACK,IAAI,GAAG;YACrB,GAAGC,eAAe;YAClBI,SAAS;QACX;IACF;IAEA,OAAOV;AACT"}
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "mergeChildMappings", {
enumerable: true,
get: function() {
return mergeChildMappings;
}
});
function mergeChildMappings(prevMapping, nextMapping) {
function getValueForKey(key) {
return key in nextMapping ? nextMapping[key] : prevMapping[key];
}
// For each key of `next`, the list of keys to insert before that key in
// the combined list
const nextKeysPending = {};
let pendingKeys = [];
// eslint-disable-next-line guard-for-in
for(const prevKey in prevMapping){
if (prevKey in nextMapping) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys;
pendingKeys = [];
}
continue;
}
pendingKeys.push(prevKey);
}
const childMapping = {};
// eslint-disable-next-line guard-for-in
for(const nextKey in nextMapping){
if (nextKeysPending[nextKey]) {
for (const pendingNextKey of nextKeysPending[nextKey]){
childMapping[pendingNextKey] = getValueForKey(pendingNextKey);
}
}
childMapping[nextKey] = getValueForKey(nextKey);
}
// Finally, add the keys which didn't appear before any key in `next`
for (const pendingKey of pendingKeys){
childMapping[pendingKey] = getValueForKey(pendingKey);
}
return childMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/mergeChildMappings.ts"],"sourcesContent":["import type { PresenceGroupChildMapping } from './types';\n\n/**\n * When you're adding or removing children some may be added or removed in the same render pass. We want to show *both*\n * since we want to simultaneously animate elements in and out. This function takes a previous set of keys and a new set\n * of keys and merges them with its best guess of the correct ordering.\n */\nexport function mergeChildMappings(\n prevMapping: PresenceGroupChildMapping,\n nextMapping: PresenceGroupChildMapping,\n): PresenceGroupChildMapping {\n function getValueForKey(key: string) {\n return key in nextMapping ? nextMapping[key] : prevMapping[key];\n }\n\n // For each key of `next`, the list of keys to insert before that key in\n // the combined list\n const nextKeysPending: Record<string, string[]> = {};\n let pendingKeys: string[] = [];\n\n // eslint-disable-next-line guard-for-in\n for (const prevKey in prevMapping) {\n if (prevKey in nextMapping) {\n if (pendingKeys.length) {\n nextKeysPending[prevKey] = pendingKeys;\n pendingKeys = [];\n }\n\n continue;\n }\n\n pendingKeys.push(prevKey);\n }\n\n const childMapping: PresenceGroupChildMapping = {};\n\n // eslint-disable-next-line guard-for-in\n for (const nextKey in nextMapping) {\n if (nextKeysPending[nextKey]) {\n for (const pendingNextKey of nextKeysPending[nextKey]) {\n childMapping[pendingNextKey] = getValueForKey(pendingNextKey);\n }\n }\n\n childMapping[nextKey] = getValueForKey(nextKey);\n }\n\n // Finally, add the keys which didn't appear before any key in `next`\n for (const pendingKey of pendingKeys) {\n childMapping[pendingKey] = getValueForKey(pendingKey);\n }\n\n return childMapping;\n}\n"],"names":["mergeChildMappings","prevMapping","nextMapping","getValueForKey","key","nextKeysPending","pendingKeys","prevKey","length","push","childMapping","nextKey","pendingNextKey","pendingKey"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;+BAOgBA;;;eAAAA;;;AAAT,SAASA,mBACdC,WAAsC,EACtCC,WAAsC;IAEtC,SAASC,eAAeC,GAAW;QACjC,OAAOA,OAAOF,cAAcA,WAAW,CAACE,IAAI,GAAGH,WAAW,CAACG,IAAI;IACjE;IAEA,wEAAwE;IACxE,oBAAoB;IACpB,MAAMC,kBAA4C,CAAC;IACnD,IAAIC,cAAwB,EAAE;IAE9B,wCAAwC;IACxC,IAAK,MAAMC,WAAWN,YAAa;QACjC,IAAIM,WAAWL,aAAa;YAC1B,IAAII,YAAYE,MAAM,EAAE;gBACtBH,eAAe,CAACE,QAAQ,GAAGD;gBAC3BA,cAAc,EAAE;YAClB;YAEA;QACF;QAEAA,YAAYG,IAAI,CAACF;IACnB;IAEA,MAAMG,eAA0C,CAAC;IAEjD,wCAAwC;IACxC,IAAK,MAAMC,WAAWT,YAAa;QACjC,IAAIG,eAAe,CAACM,QAAQ,EAAE;YAC5B,KAAK,MAAMC,kBAAkBP,eAAe,CAACM,QAAQ,CAAE;gBACrDD,YAAY,CAACE,eAAe,GAAGT,eAAeS;YAChD;QACF;QAEAF,YAAY,CAACC,QAAQ,GAAGR,eAAeQ;IACzC;IAEA,qEAAqE;IACrE,KAAK,MAAME,cAAcP,YAAa;QACpCI,YAAY,CAACG,WAAW,GAAGV,eAAeU;IAC5C;IAEA,OAAOH;AACT"}
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/types.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type PresenceGroupChild = {\n element: React.ReactElement;\n\n appear: boolean;\n visible: boolean;\n unmountOnExit: boolean;\n};\n\nexport type PresenceGroupChildMapping = Record<string, PresenceGroupChild>;\n"],"names":[],"rangeMappings":";;;;;","mappings":";;;;;iEAAuB"}
+53
View File
@@ -0,0 +1,53 @@
import { _ as _define_property } from "@swc/helpers/_/_define_property";
import * as React from 'react';
import { getNextChildMapping } from '../utils/groups/getNextChildMapping';
import { getChildMapping } from '../utils/groups/getChildMapping';
import { PresenceGroupItemProvider } from './PresenceGroupItemProvider';
/* eslint-disable @typescript-eslint/explicit-member-accessibility */ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/member-ordering */ export class PresenceGroup extends React.Component {
static getDerivedStateFromProps(nextProps, { childMapping: prevChildMapping, firstRender }) {
const nextChildMapping = getChildMapping(nextProps.children);
return {
childMapping: firstRender ? nextChildMapping : getNextChildMapping(prevChildMapping, nextChildMapping),
firstRender: false
};
}
componentDidMount() {
this.mounted = true;
}
componentWillUnmount() {
this.mounted = false;
}
render() {
return /*#__PURE__*/ React.createElement(React.Fragment, null, Object.entries(this.state.childMapping).map(([childKey, childProps])=>/*#__PURE__*/ React.createElement(PresenceGroupItemProvider, {
...childProps,
childKey: childKey,
key: childKey,
onExit: this.handleExit
}, childProps.element)));
}
constructor(props, context){
super(props, context);
_define_property(this, "mounted", false);
_define_property(this, "handleExit", (childKey)=>{
const currentChildMapping = getChildMapping(this.props.children);
if (childKey in currentChildMapping) {
return;
}
if (this.mounted) {
this.setState((state)=>{
const childMapping = {
...state.childMapping
};
delete childMapping[childKey];
return {
childMapping
};
});
}
});
this.state = {
childMapping: {},
firstRender: true
};
}
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/PresenceGroup.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { getNextChildMapping } from '../utils/groups/getNextChildMapping';\nimport { getChildMapping } from '../utils/groups/getChildMapping';\nimport type { PresenceGroupChildMapping } from '../utils/groups/types';\nimport { PresenceGroupItemProvider } from './PresenceGroupItemProvider';\n\ntype PresenceGroupProps = {\n children: React.ReactNode;\n};\n\ntype PresenceGroupState = {\n childMapping: PresenceGroupChildMapping;\n firstRender: boolean;\n};\n\n/* eslint-disable @typescript-eslint/explicit-member-accessibility */\n/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable @typescript-eslint/member-ordering */\n\nexport class PresenceGroup extends React.Component<PresenceGroupProps, PresenceGroupState> {\n private mounted: boolean = false;\n\n static getDerivedStateFromProps(\n nextProps: PresenceGroupProps,\n { childMapping: prevChildMapping, firstRender }: PresenceGroupState,\n ) {\n const nextChildMapping = getChildMapping(nextProps.children);\n\n return {\n childMapping: firstRender ? nextChildMapping : getNextChildMapping(prevChildMapping, nextChildMapping),\n firstRender: false,\n };\n }\n\n constructor(props: PresenceGroupProps, context: unknown) {\n super(props, context);\n\n this.state = {\n childMapping: {},\n firstRender: true,\n };\n }\n\n private handleExit = (childKey: string) => {\n const currentChildMapping = getChildMapping(this.props.children);\n\n if (childKey in currentChildMapping) {\n return;\n }\n\n if (this.mounted) {\n this.setState(state => {\n const childMapping = { ...state.childMapping };\n delete childMapping[childKey];\n\n return { childMapping };\n });\n }\n };\n\n componentDidMount() {\n this.mounted = true;\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n render() {\n return (\n <>\n {Object.entries(this.state.childMapping).map(([childKey, childProps]) => (\n <PresenceGroupItemProvider {...childProps} childKey={childKey} key={childKey} onExit={this.handleExit}>\n {childProps.element}\n </PresenceGroupItemProvider>\n ))}\n </>\n );\n }\n}\n"],"names":["React","getNextChildMapping","getChildMapping","PresenceGroupItemProvider","PresenceGroup","Component","getDerivedStateFromProps","nextProps","childMapping","prevChildMapping","firstRender","nextChildMapping","children","componentDidMount","mounted","componentWillUnmount","render","Object","entries","state","map","childKey","childProps","key","onExit","handleExit","element","constructor","props","context","currentChildMapping","setState"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,mBAAmB,QAAQ,sCAAsC;AAC1E,SAASC,eAAe,QAAQ,kCAAkC;AAElE,SAASC,yBAAyB,QAAQ,8BAA8B;AAWxE,mEAAmE,GACnE,uDAAuD,GACvD,qDAAqD,GAErD,OAAO,MAAMC,sBAAsBJ,MAAMK,SAAS;IAGhD,OAAOC,yBACLC,SAA6B,EAC7B,EAAEC,cAAcC,gBAAgB,EAAEC,WAAW,EAAsB,EACnE;QACA,MAAMC,mBAAmBT,gBAAgBK,UAAUK,QAAQ;QAE3D,OAAO;YACLJ,cAAcE,cAAcC,mBAAmBV,oBAAoBQ,kBAAkBE;YACrFD,aAAa;QACf;IACF;IA4BAG,oBAAoB;QAClB,IAAI,CAACC,OAAO,GAAG;IACjB;IAEAC,uBAAuB;QACrB,IAAI,CAACD,OAAO,GAAG;IACjB;IAEAE,SAAS;QACP,qBACE,0CACGC,OAAOC,OAAO,CAAC,IAAI,CAACC,KAAK,CAACX,YAAY,EAAEY,GAAG,CAAC,CAAC,CAACC,UAAUC,WAAW,iBAClE,oBAACnB;gBAA2B,GAAGmB,UAAU;gBAAED,UAAUA;gBAAUE,KAAKF;gBAAUG,QAAQ,IAAI,CAACC,UAAU;eAClGH,WAAWI,OAAO;IAK7B;IA5CAC,YAAYC,KAAyB,EAAEC,OAAgB,CAAE;QACvD,KAAK,CAACD,OAAOC;QAff,uBAAQf,WAAmB;QAuB3B,uBAAQW,cAAa,CAACJ;YACpB,MAAMS,sBAAsB5B,gBAAgB,IAAI,CAAC0B,KAAK,CAAChB,QAAQ;YAE/D,IAAIS,YAAYS,qBAAqB;gBACnC;YACF;YAEA,IAAI,IAAI,CAAChB,OAAO,EAAE;gBAChB,IAAI,CAACiB,QAAQ,CAACZ,CAAAA;oBACZ,MAAMX,eAAe;wBAAE,GAAGW,MAAMX,YAAY;oBAAC;oBAC7C,OAAOA,YAAY,CAACa,SAAS;oBAE7B,OAAO;wBAAEb;oBAAa;gBACxB;YACF;QACF;QArBE,IAAI,CAACW,KAAK,GAAG;YACXX,cAAc,CAAC;YACfE,aAAa;QACf;IACF;AAsCF"}
@@ -0,0 +1,25 @@
import * as React from 'react';
import { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';
/**
* @internal
*
* Provides context for a single child of a `PresenceGroup`. Exists only to make a stable context value for a child.
* Not intended for direct use.
*/ export const PresenceGroupItemProvider = (props)=>{
const { appear, childKey, onExit, visible, unmountOnExit } = props;
const contextValue = React.useMemo(()=>({
appear,
visible,
onExit: ()=>onExit(childKey),
unmountOnExit
}), [
appear,
childKey,
onExit,
visible,
unmountOnExit
]);
return /*#__PURE__*/ React.createElement(PresenceGroupChildContext.Provider, {
value: contextValue
}, props.children);
};
@@ -0,0 +1 @@
{"version":3,"sources":["../src/components/PresenceGroupItemProvider.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';\nimport type { PresenceGroupChildContextValue } from '../contexts/PresenceGroupChildContext';\n\ntype PresenceGroupItemProviderProps = Omit<PresenceGroupChildContextValue, 'onExit'> & {\n children: React.ReactElement;\n childKey: string;\n // That's an internal callback, so we don't need to enforce the type here\n // eslint-disable-next-line @nx/workspace-consistent-callback-type\n onExit: (childKey: string) => void;\n};\n\n/**\n * @internal\n *\n * Provides context for a single child of a `PresenceGroup`. Exists only to make a stable context value for a child.\n * Not intended for direct use.\n */\nexport const PresenceGroupItemProvider: React.FC<PresenceGroupItemProviderProps> = props => {\n const { appear, childKey, onExit, visible, unmountOnExit } = props;\n const contextValue = React.useMemo(\n () => ({\n appear,\n visible,\n onExit: () => onExit(childKey),\n unmountOnExit,\n }),\n [appear, childKey, onExit, visible, unmountOnExit],\n );\n\n return <PresenceGroupChildContext.Provider value={contextValue}>{props.children}</PresenceGroupChildContext.Provider>;\n};\n"],"names":["React","PresenceGroupChildContext","PresenceGroupItemProvider","props","appear","childKey","onExit","visible","unmountOnExit","contextValue","useMemo","Provider","value","children"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,yBAAyB,QAAQ,wCAAwC;AAWlF;;;;;CAKC,GACD,OAAO,MAAMC,4BAAsEC,CAAAA;IACjF,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,OAAO,EAAEC,aAAa,EAAE,GAAGL;IAC7D,MAAMM,eAAeT,MAAMU,OAAO,CAChC,IAAO,CAAA;YACLN;YACAG;YACAD,QAAQ,IAAMA,OAAOD;YACrBG;QACF,CAAA,GACA;QAACJ;QAAQC;QAAUC;QAAQC;QAASC;KAAc;IAGpD,qBAAO,oBAACP,0BAA0BU,QAAQ;QAACC,OAAOH;OAAeN,MAAMU,QAAQ;AACjF,EAAE"}
@@ -0,0 +1,7 @@
import * as React from 'react';
const MotionBehaviourContext = React.createContext(undefined);
export const MotionBehaviourProvider = MotionBehaviourContext.Provider;
export const useMotionBehaviourContext = ()=>{
var _React_useContext;
return (_React_useContext = React.useContext(MotionBehaviourContext)) !== null && _React_useContext !== void 0 ? _React_useContext : 'default';
};
@@ -0,0 +1 @@
{"version":3,"sources":["../src/contexts/MotionBehaviourContext.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * Specifies the behaviour of child motion component under @see MotionBehaviourProvider.\n */\nexport type MotionBehaviourType = 'skip' | 'default';\n\nconst MotionBehaviourContext = React.createContext<MotionBehaviourType | undefined>(undefined);\n\nexport const MotionBehaviourProvider = MotionBehaviourContext.Provider;\nexport const useMotionBehaviourContext = () => React.useContext(MotionBehaviourContext) ?? 'default';\n"],"names":["React","MotionBehaviourContext","createContext","undefined","MotionBehaviourProvider","Provider","useMotionBehaviourContext","useContext"],"rangeMappings":";;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAO/B,MAAMC,yBAAyBD,MAAME,aAAa,CAAkCC;AAEpF,OAAO,MAAMC,0BAA0BH,uBAAuBI,QAAQ,CAAC;AACvE,OAAO,MAAMC,4BAA4B;QAAMN;WAAAA,CAAAA,oBAAAA,MAAMO,UAAU,CAACN,qCAAjBD,+BAAAA,oBAA4C;AAAQ,EAAE"}
@@ -0,0 +1,4 @@
import * as React from 'react';
/**
* @internal
*/ export const PresenceGroupChildContext = React.createContext(undefined);
@@ -0,0 +1 @@
{"version":3,"sources":["../src/contexts/PresenceGroupChildContext.ts"],"sourcesContent":["import * as React from 'react';\n\n/**\n * @internal\n */\nexport type PresenceGroupChildContextValue = {\n appear: boolean;\n visible: boolean;\n unmountOnExit: boolean;\n\n onExit: () => void;\n};\n\n/**\n * @internal\n */\nexport const PresenceGroupChildContext = React.createContext<PresenceGroupChildContextValue | undefined>(undefined);\n"],"names":["React","PresenceGroupChildContext","createContext","undefined"],"rangeMappings":";;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAa/B;;CAEC,GACD,OAAO,MAAMC,4BAA4BD,MAAME,aAAa,CAA6CC,WAAW"}
@@ -0,0 +1,77 @@
import { useEventCallback, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';
import * as React from 'react';
import { useAnimateAtoms } from '../hooks/useAnimateAtoms';
import { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';
import { useIsReducedMotion } from '../hooks/useIsReducedMotion';
import { getChildElement } from '../utils/getChildElement';
import { useMotionBehaviourContext } from '../contexts/MotionBehaviourContext';
/**
* Creates a component that will animate the children using the provided motion.
*
* @param value - A motion definition.
*/ export function createMotionComponent(value) {
const Atom = (props)=>{
'use no memo';
const { children, imperativeRef, onMotionFinish: onMotionFinishProp, onMotionStart: onMotionStartProp, onMotionCancel: onMotionCancelProp, ..._rest } = props;
const params = _rest;
const child = getChildElement(children);
const handleRef = useMotionImperativeRef(imperativeRef);
const elementRef = React.useRef();
const skipMotions = useMotionBehaviourContext() === 'skip';
const optionsRef = React.useRef({
skipMotions,
params
});
const animateAtoms = useAnimateAtoms();
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);
});
const onMotionCancel = useEventCallback(()=>{
onMotionCancelProp === null || onMotionCancelProp === void 0 ? void 0 : onMotionCancelProp(null);
});
useIsomorphicLayoutEffect(()=>{
// Heads up!
// We store the params in a ref to avoid re-rendering the component when the params change.
optionsRef.current = {
skipMotions,
params
};
});
useIsomorphicLayoutEffect(()=>{
const element = elementRef.current;
if (element) {
const atoms = typeof value === 'function' ? value({
element,
...optionsRef.current.params
}) : value;
onMotionStart();
const handle = animateAtoms(element, atoms, {
isReducedMotion: isReducedMotion()
});
handleRef.current = handle;
handle.setMotionEndCallbacks(onMotionFinish, onMotionCancel);
if (optionsRef.current.skipMotions) {
handle.finish();
}
return ()=>{
handle.cancel();
};
}
}, [
animateAtoms,
handleRef,
isReducedMotion,
onMotionFinish,
onMotionStart,
onMotionCancel
]);
return React.cloneElement(children, {
ref: useMergedRefs(elementRef, child.ref)
});
};
return Atom;
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,123 @@
import { useEventCallback, useFirstMount, useIsomorphicLayoutEffect, useMergedRefs } from '@fluentui/react-utilities';
import * as React from 'react';
import { PresenceGroupChildContext } from '../contexts/PresenceGroupChildContext';
import { useAnimateAtoms } from '../hooks/useAnimateAtoms';
import { useMotionImperativeRef } from '../hooks/useMotionImperativeRef';
import { useMountedState } from '../hooks/useMountedState';
import { useIsReducedMotion } from '../hooks/useIsReducedMotion';
import { getChildElement } from '../utils/getChildElement';
import { useMotionBehaviourContext } from '../contexts/MotionBehaviourContext';
/**
* @internal A private symbol to store the motion definition on the component for variants.
*/ export const MOTION_DEFINITION = Symbol('MOTION_DEFINITION');
function shouldSkipAnimation(appear, isFirstMount, visible) {
return !appear && isFirstMount && !!visible;
}
export function createPresenceComponent(value) {
return Object.assign((props)=>{
'use no memo';
const itemContext = React.useContext(PresenceGroupChildContext);
const merged = {
...itemContext,
...props
};
const skipMotions = useMotionBehaviourContext() === 'skip';
const { appear, children, imperativeRef, onExit, onMotionFinish, onMotionStart, onMotionCancel, visible, unmountOnExit, ..._rest } = merged;
const params = _rest;
const [mounted, setMounted] = useMountedState(visible, unmountOnExit);
const child = getChildElement(children);
const handleRef = useMotionImperativeRef(imperativeRef);
const elementRef = React.useRef();
const ref = useMergedRefs(elementRef, child.ref);
const optionsRef = React.useRef({
appear,
params,
skipMotions
});
const animateAtoms = useAnimateAtoms();
const isFirstMount = useFirstMount();
const isReducedMotion = useIsReducedMotion();
const handleMotionStart = useEventCallback((direction)=>{
onMotionStart === null || onMotionStart === void 0 ? void 0 : onMotionStart(null, {
direction
});
});
const handleMotionFinish = useEventCallback((direction)=>{
onMotionFinish === null || onMotionFinish === void 0 ? void 0 : onMotionFinish(null, {
direction
});
if (direction === 'exit' && unmountOnExit) {
setMounted(false);
onExit === null || onExit === void 0 ? void 0 : onExit();
}
});
const handleMotionCancel = useEventCallback((direction)=>{
onMotionCancel === null || onMotionCancel === void 0 ? void 0 : onMotionCancel(null, {
direction
});
});
useIsomorphicLayoutEffect(()=>{
// Heads up!
// We store the params in a ref to avoid re-rendering the component when the params change.
optionsRef.current = {
appear,
params,
skipMotions
};
});
useIsomorphicLayoutEffect(()=>{
const element = elementRef.current;
if (!element || shouldSkipAnimation(optionsRef.current.appear, isFirstMount, visible)) {
return;
}
const presenceMotion = typeof value === 'function' ? value({
element,
...optionsRef.current.params
}) : value;
const atoms = visible ? presenceMotion.enter : presenceMotion.exit;
const direction = visible ? 'enter' : 'exit';
const applyInitialStyles = !visible && isFirstMount;
const skipAnimation = optionsRef.current.skipMotions;
if (!applyInitialStyles) {
handleMotionStart(direction);
}
const handle = animateAtoms(element, atoms, {
isReducedMotion: isReducedMotion()
});
if (applyInitialStyles) {
// Heads up!
// .finish() is used in this case to skip animation and apply animation styles immediately
handle.finish();
return;
}
handleRef.current = handle;
handle.setMotionEndCallbacks(()=>handleMotionFinish(direction), ()=>handleMotionCancel(direction));
if (skipAnimation) {
handle.finish();
}
return ()=>{
handle.cancel();
};
}, // Excluding `isFirstMount` from deps to prevent re-triggering the animation on subsequent renders
// eslint-disable-next-line react-hooks/exhaustive-deps
[
animateAtoms,
handleRef,
isReducedMotion,
handleMotionFinish,
handleMotionStart,
handleMotionCancel,
visible
]);
if (mounted) {
return React.cloneElement(child, {
ref
});
}
return null;
}, {
// Heads up!
// Always normalize it to a function to simplify types
[MOTION_DEFINITION]: typeof value === 'function' ? value : ()=>value
});
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
import { MOTION_DEFINITION, createPresenceComponent } from './createPresenceComponent';
/**
* @internal
*/ export function overridePresenceMotion(presenceMotion, override) {
return (...args)=>{
const { enter, exit } = presenceMotion(...args);
return {
enter: {
...enter,
...override.all,
...override.enter
},
exit: {
...exit,
...override.all,
...override.exit
}
};
};
}
export function createPresenceComponentVariant(component, override) {
return createPresenceComponent(overridePresenceMotion(component[MOTION_DEFINITION], override));
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/factories/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"}
+142
View File
@@ -0,0 +1,142 @@
import * as React from 'react';
export const DEFAULT_ANIMATION_OPTIONS = {
fill: 'forwards'
};
// A motion atom's default reduced motion is a simple 1 ms duration.
// But an atom can define a custom reduced motion, overriding keyframes and/or params like duration, easing, iterations, etc.
const DEFAULT_REDUCED_MOTION_ATOM = {
duration: 1
};
function useAnimateAtomsInSupportedEnvironment() {
var _window_Animation;
// eslint-disable-next-line @nx/workspace-no-restricted-globals
const SUPPORTS_PERSIST = typeof window !== 'undefined' && typeof ((_window_Animation = window.Animation) === null || _window_Animation === void 0 ? void 0 : _window_Animation.prototype.persist) === 'function';
return React.useCallback((element, value, options)=>{
const atoms = Array.isArray(value) ? value : [
value
];
const { isReducedMotion } = options;
const animations = atoms.map((motion)=>{
// Grab the custom reduced motion definition if it exists, or fall back to the default reduced motion.
const { keyframes: motionKeyframes, reducedMotion = DEFAULT_REDUCED_MOTION_ATOM, ...params } = motion;
// Grab the reduced motion keyframes if they exist, or fall back to the regular keyframes.
const { keyframes: reducedMotionKeyframes = motionKeyframes, ...reducedMotionParams } = reducedMotion;
const animationKeyframes = isReducedMotion ? reducedMotionKeyframes : motionKeyframes;
const animationParams = {
...DEFAULT_ANIMATION_OPTIONS,
...params,
// Use reduced motion overrides (e.g. duration, easing) when reduced motion is enabled
...isReducedMotion && reducedMotionParams
};
const animation = element.animate(animationKeyframes, animationParams);
if (SUPPORTS_PERSIST) {
animation.persist();
} else {
const resultKeyframe = animationKeyframes[animationKeyframes.length - 1];
var _element_style;
Object.assign((_element_style = element.style) !== null && _element_style !== void 0 ? _element_style : {}, resultKeyframe);
}
return animation;
});
return {
set playbackRate (rate){
animations.forEach((animation)=>{
animation.playbackRate = rate;
});
},
setMotionEndCallbacks (onfinish, oncancel) {
// Heads up!
// This could use "Animation:finished", but it's causing a memory leak in Chromium.
// See: https://issues.chromium.org/u/2/issues/383016426
const promises = animations.map((animation)=>{
return new Promise((resolve, reject)=>{
animation.onfinish = ()=>resolve();
animation.oncancel = ()=>reject();
});
});
Promise.all(promises).then(()=>{
onfinish();
}).catch(()=>{
oncancel();
});
},
cancel: ()=>{
animations.forEach((animation)=>{
animation.cancel();
});
},
pause: ()=>{
animations.forEach((animation)=>{
animation.pause();
});
},
play: ()=>{
animations.forEach((animation)=>{
animation.play();
});
},
finish: ()=>{
animations.forEach((animation)=>{
animation.finish();
});
}
};
}, [
SUPPORTS_PERSIST
]);
}
/**
* In test environments, this hook is used to delay the execution of a callback until the next render. This is necessary
* to ensure that the callback is not executed synchronously, which would cause the test to fail.
*
* @see https://github.com/microsoft/fluentui/issues/31701
*/ function useAnimateAtomsInTestEnvironment() {
const [count, setCount] = React.useState(0);
const callbackRef = React.useRef();
const realAnimateAtoms = useAnimateAtomsInSupportedEnvironment();
React.useEffect(()=>{
if (count > 0) {
var _callbackRef_current;
(_callbackRef_current = callbackRef.current) === null || _callbackRef_current === void 0 ? void 0 : _callbackRef_current.call(callbackRef);
}
}, [
count
]);
return React.useCallback((element, value, options)=>{
const ELEMENT_SUPPORTS_WEB_ANIMATIONS = typeof element.animate === 'function';
// Heads up!
// If the environment supports Web Animations API, we can use the native implementation.
if (ELEMENT_SUPPORTS_WEB_ANIMATIONS) {
return realAnimateAtoms(element, value, options);
}
return {
setMotionEndCallbacks (onfinish) {
callbackRef.current = onfinish;
setCount((v)=>v + 1);
},
set playbackRate (rate){
/* no-op */ },
cancel () {
/* no-op */ },
pause () {
/* no-op */ },
play () {
/* no-op */ },
finish () {
/* no-op */ }
};
}, [
realAnimateAtoms
]);
}
/**
* @internal
*/ export function useAnimateAtoms() {
'use no memo';
if (process.env.NODE_ENV === 'test') {
// eslint-disable-next-line react-hooks/rules-of-hooks
return useAnimateAtomsInTestEnvironment();
}
// eslint-disable-next-line react-hooks/rules-of-hooks
return useAnimateAtomsInSupportedEnvironment();
}
File diff suppressed because one or more lines are too long
+31
View File
@@ -0,0 +1,31 @@
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
import * as React from 'react';
const REDUCED_MEDIA_QUERY = 'screen and (prefers-reduced-motion: reduce)';
// TODO: find a better approach there as each hook creates a separate subscription
export function useIsReducedMotion() {
const { targetDocument } = useFluent();
var _targetDocument_defaultView;
const targetWindow = (_targetDocument_defaultView = targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView) !== null && _targetDocument_defaultView !== void 0 ? _targetDocument_defaultView : null;
const queryValue = React.useRef(false);
const isEnabled = React.useCallback(()=>queryValue.current, []);
useIsomorphicLayoutEffect(()=>{
if (targetWindow === null || typeof targetWindow.matchMedia !== 'function') {
return;
}
const queryMatch = targetWindow.matchMedia(REDUCED_MEDIA_QUERY);
if (queryMatch.matches) {
queryValue.current = true;
}
const matchListener = (e)=>{
queryValue.current = e.matches;
};
queryMatch.addEventListener('change', matchListener);
return ()=>{
queryMatch.removeEventListener('change', matchListener);
};
}, [
targetWindow
]);
return isEnabled;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useIsReducedMotion.ts"],"sourcesContent":["import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport { useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\nconst REDUCED_MEDIA_QUERY = 'screen and (prefers-reduced-motion: reduce)';\n\n// TODO: find a better approach there as each hook creates a separate subscription\n\nexport function useIsReducedMotion(): () => boolean {\n const { targetDocument } = useFluent();\n const targetWindow: Window | null = targetDocument?.defaultView ?? null;\n\n const queryValue = React.useRef<boolean>(false);\n const isEnabled = React.useCallback(() => queryValue.current, []);\n\n useIsomorphicLayoutEffect(() => {\n if (targetWindow === null || typeof targetWindow.matchMedia !== 'function') {\n return;\n }\n\n const queryMatch = targetWindow.matchMedia(REDUCED_MEDIA_QUERY);\n\n if (queryMatch.matches) {\n queryValue.current = true;\n }\n\n const matchListener = (e: MediaQueryListEvent) => {\n queryValue.current = e.matches;\n };\n\n queryMatch.addEventListener('change', matchListener);\n\n return () => {\n queryMatch.removeEventListener('change', matchListener);\n };\n }, [targetWindow]);\n\n return isEnabled;\n}\n"],"names":["useFluent_unstable","useFluent","useIsomorphicLayoutEffect","React","REDUCED_MEDIA_QUERY","useIsReducedMotion","targetDocument","targetWindow","defaultView","queryValue","useRef","isEnabled","useCallback","current","matchMedia","queryMatch","matches","matchListener","e","addEventListener","removeEventListener"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,sBAAsBC,SAAS,QAAQ,kCAAkC;AAClF,SAASC,yBAAyB,QAAQ,4BAA4B;AACtE,YAAYC,WAAW,QAAQ;AAE/B,MAAMC,sBAAsB;AAE5B,kFAAkF;AAElF,OAAO,SAASC;IACd,MAAM,EAAEC,cAAc,EAAE,GAAGL;QACSK;IAApC,MAAMC,eAA8BD,CAAAA,8BAAAA,2BAAAA,qCAAAA,eAAgBE,WAAW,cAA3BF,yCAAAA,8BAA+B;IAEnE,MAAMG,aAAaN,MAAMO,MAAM,CAAU;IACzC,MAAMC,YAAYR,MAAMS,WAAW,CAAC,IAAMH,WAAWI,OAAO,EAAE,EAAE;IAEhEX,0BAA0B;QACxB,IAAIK,iBAAiB,QAAQ,OAAOA,aAAaO,UAAU,KAAK,YAAY;YAC1E;QACF;QAEA,MAAMC,aAAaR,aAAaO,UAAU,CAACV;QAE3C,IAAIW,WAAWC,OAAO,EAAE;YACtBP,WAAWI,OAAO,GAAG;QACvB;QAEA,MAAMI,gBAAgB,CAACC;YACrBT,WAAWI,OAAO,GAAGK,EAAEF,OAAO;QAChC;QAEAD,WAAWI,gBAAgB,CAAC,UAAUF;QAEtC,OAAO;YACLF,WAAWK,mBAAmB,CAAC,UAAUH;QAC3C;IACF,GAAG;QAACV;KAAa;IAEjB,OAAOI;AACT"}
@@ -0,0 +1,22 @@
import * as React from 'react';
export function useMotionImperativeRef(imperativeRef) {
const animationRef = React.useRef();
React.useImperativeHandle(imperativeRef, ()=>({
setPlayState: (state)=>{
if (state === 'running') {
var _animationRef_current;
(_animationRef_current = animationRef.current) === null || _animationRef_current === void 0 ? void 0 : _animationRef_current.play();
}
if (state === 'paused') {
var _animationRef_current1;
(_animationRef_current1 = animationRef.current) === null || _animationRef_current1 === void 0 ? void 0 : _animationRef_current1.pause();
}
},
setPlaybackRate: (rate)=>{
if (animationRef.current) {
animationRef.current.playbackRate = rate;
}
}
}));
return animationRef;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMotionImperativeRef.ts"],"sourcesContent":["import * as React from 'react';\nimport type { AnimationHandle, MotionImperativeRef } from '../types';\n\nexport function useMotionImperativeRef(imperativeRef: React.Ref<MotionImperativeRef | undefined> | undefined) {\n const animationRef = React.useRef<AnimationHandle | undefined>();\n\n React.useImperativeHandle(imperativeRef, () => ({\n setPlayState: state => {\n if (state === 'running') {\n animationRef.current?.play();\n }\n\n if (state === 'paused') {\n animationRef.current?.pause();\n }\n },\n setPlaybackRate: rate => {\n if (animationRef.current) {\n animationRef.current.playbackRate = rate;\n }\n },\n }));\n\n return animationRef;\n}\n"],"names":["React","useMotionImperativeRef","imperativeRef","animationRef","useRef","useImperativeHandle","setPlayState","state","current","play","pause","setPlaybackRate","rate","playbackRate"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B,OAAO,SAASC,uBAAuBC,aAAqE;IAC1G,MAAMC,eAAeH,MAAMI,MAAM;IAEjCJ,MAAMK,mBAAmB,CAACH,eAAe,IAAO,CAAA;YAC9CI,cAAcC,CAAAA;gBACZ,IAAIA,UAAU,WAAW;wBACvBJ;qBAAAA,wBAAAA,aAAaK,OAAO,cAApBL,4CAAAA,sBAAsBM,IAAI;gBAC5B;gBAEA,IAAIF,UAAU,UAAU;wBACtBJ;qBAAAA,yBAAAA,aAAaK,OAAO,cAApBL,6CAAAA,uBAAsBO,KAAK;gBAC7B;YACF;YACAC,iBAAiBC,CAAAA;gBACf,IAAIT,aAAaK,OAAO,EAAE;oBACxBL,aAAaK,OAAO,CAACK,YAAY,GAAGD;gBACtC;YACF;QACF,CAAA;IAEA,OAAOT;AACT"}
+26
View File
@@ -0,0 +1,26 @@
import { useForceUpdate } from '@fluentui/react-utilities';
import * as React from 'react';
/**
* This hook manages the mounted state of a component, based on the "visible" and "unmountOnExit" props.
* It simulates the behavior of getDerivedStateFromProps(), which is not available in functional components.
*/ export function useMountedState(visible = false, unmountOnExit = false) {
const mountedRef = React.useRef(unmountOnExit ? visible : true);
const forceUpdate = useForceUpdate();
const setMounted = React.useCallback((newValue)=>{
if (mountedRef.current !== newValue) {
mountedRef.current = newValue;
forceUpdate();
}
}, [
forceUpdate
]);
React.useEffect(()=>{
if (visible) {
mountedRef.current = visible;
}
});
return [
visible || mountedRef.current,
setMounted
];
}
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/hooks/useMountedState.ts"],"sourcesContent":["import { useForceUpdate } from '@fluentui/react-utilities';\nimport * as React from 'react';\n\n/**\n * This hook manages the mounted state of a component, based on the \"visible\" and \"unmountOnExit\" props.\n * It simulates the behavior of getDerivedStateFromProps(), which is not available in functional components.\n */\nexport function useMountedState(\n visible: boolean = false,\n unmountOnExit: boolean = false,\n): [boolean, (value: boolean) => void] {\n const mountedRef = React.useRef<boolean>(unmountOnExit ? visible : true);\n const forceUpdate = useForceUpdate();\n\n const setMounted = React.useCallback(\n (newValue: boolean) => {\n if (mountedRef.current !== newValue) {\n mountedRef.current = newValue;\n forceUpdate();\n }\n },\n [forceUpdate],\n );\n\n React.useEffect(() => {\n if (visible) {\n mountedRef.current = visible;\n }\n });\n\n return [visible || mountedRef.current, setMounted];\n}\n"],"names":["useForceUpdate","React","useMountedState","visible","unmountOnExit","mountedRef","useRef","forceUpdate","setMounted","useCallback","newValue","current","useEffect"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,cAAc,QAAQ,4BAA4B;AAC3D,YAAYC,WAAW,QAAQ;AAE/B;;;CAGC,GACD,OAAO,SAASC,gBACdC,UAAmB,KAAK,EACxBC,gBAAyB,KAAK;IAE9B,MAAMC,aAAaJ,MAAMK,MAAM,CAAUF,gBAAgBD,UAAU;IACnE,MAAMI,cAAcP;IAEpB,MAAMQ,aAAaP,MAAMQ,WAAW,CAClC,CAACC;QACC,IAAIL,WAAWM,OAAO,KAAKD,UAAU;YACnCL,WAAWM,OAAO,GAAGD;YACrBH;QACF;IACF,GACA;QAACA;KAAY;IAGfN,MAAMW,SAAS,CAAC;QACd,IAAIT,SAAS;YACXE,WAAWM,OAAO,GAAGR;QACvB;IACF;IAEA,OAAO;QAACA,WAAWE,WAAWM,OAAO;QAAEH;KAAW;AACpD"}
+7
View File
@@ -0,0 +1,7 @@
export { motionTokens, durations, curves } from './motions/motionTokens';
export { createMotionComponent } from './factories/createMotionComponent';
export { createPresenceComponent } from './factories/createPresenceComponent';
export { createPresenceComponentVariant } from './factories/createPresenceComponentVariant';
export { PresenceGroup } from './components/PresenceGroup';
export { presenceMotionSlot } from './slots/presenceMotionSlot';
export { MotionBehaviourProvider } from './contexts/MotionBehaviourContext';
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/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 MotionParam,\n} from './types';\n\nexport { MotionBehaviourProvider } from './contexts/MotionBehaviourContext';\n"],"names":["motionTokens","durations","curves","createMotionComponent","createPresenceComponent","createPresenceComponentVariant","PresenceGroup","presenceMotionSlot","MotionBehaviourProvider"],"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;AAY9F,SAASC,uBAAuB,QAAQ,oCAAoC"}
+40
View File
@@ -0,0 +1,40 @@
// Copied from packages/tokens/src/global/durations.ts
// Values are numeric in milliseconds for ease of use in Web Animations API
// (rather than parsing '__ms')
export const durations = {
durationUltraFast: 50,
durationFaster: 100,
durationFast: 150,
durationNormal: 200,
durationGentle: 250,
durationSlow: 300,
durationSlower: 400,
durationUltraSlow: 500
};
// Copied from packages/tokens/src/global/curves.ts
// Names and values are preserved exactly
export const curves = {
curveAccelerateMax: 'cubic-bezier(0.9,0.1,1,0.2)',
curveAccelerateMid: 'cubic-bezier(1,0,1,1)',
curveAccelerateMin: 'cubic-bezier(0.8,0,0.78,1)',
curveDecelerateMax: 'cubic-bezier(0.1,0.9,0.2,1)',
curveDecelerateMid: 'cubic-bezier(0,0,0,1)',
curveDecelerateMin: 'cubic-bezier(0.33,0,0.1,1)',
curveEasyEaseMax: 'cubic-bezier(0.8,0,0.2,1)',
curveEasyEase: 'cubic-bezier(0.33,0,0.67,1)',
curveLinear: 'cubic-bezier(0,0,1,1)'
};
// A merged flat lookup for convenience
export const motionTokens = {
...durations,
...curves
}; /*
TODO: enforce naming conventions when TypeScript 4.4 features are supported in Fluent:
type DurationKey = `duration${Capitalize<string>}`;
type CurveKey = `curve${Capitalize<string>}`;
type CurveValue = `cubic-bezier(${number},${number},${number},${number})`;
type DurationTokens = Record<DurationKey, number>;
type CurveTokens = Record<CurveKey, CurveValue>;
*/
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/motions/motionTokens.ts"],"sourcesContent":["// Copied from packages/tokens/src/global/durations.ts\n// Values are numeric in milliseconds for ease of use in Web Animations API\n// (rather than parsing '__ms')\nexport const durations = {\n durationUltraFast: 50,\n durationFaster: 100,\n durationFast: 150,\n durationNormal: 200,\n durationGentle: 250,\n durationSlow: 300,\n durationSlower: 400,\n durationUltraSlow: 500,\n} as const;\n\n// Copied from packages/tokens/src/global/curves.ts\n// Names and values are preserved exactly\nexport const curves = {\n curveAccelerateMax: 'cubic-bezier(0.9,0.1,1,0.2)',\n curveAccelerateMid: 'cubic-bezier(1,0,1,1)',\n curveAccelerateMin: 'cubic-bezier(0.8,0,0.78,1)',\n curveDecelerateMax: 'cubic-bezier(0.1,0.9,0.2,1)',\n curveDecelerateMid: 'cubic-bezier(0,0,0,1)',\n curveDecelerateMin: 'cubic-bezier(0.33,0,0.1,1)',\n curveEasyEaseMax: 'cubic-bezier(0.8,0,0.2,1)',\n curveEasyEase: 'cubic-bezier(0.33,0,0.67,1)',\n curveLinear: 'cubic-bezier(0,0,1,1)',\n} as const;\n\n// A merged flat lookup for convenience\nexport const motionTokens = {\n ...durations,\n ...curves,\n};\n\n/*\nTODO: enforce naming conventions when TypeScript 4.4 features are supported in Fluent:\n\ntype DurationKey = `duration${Capitalize<string>}`;\ntype CurveKey = `curve${Capitalize<string>}`;\ntype CurveValue = `cubic-bezier(${number},${number},${number},${number})`;\n\ntype DurationTokens = Record<DurationKey, number>;\ntype CurveTokens = Record<CurveKey, CurveValue>;\n*/\n"],"names":["durations","durationUltraFast","durationFaster","durationFast","durationNormal","durationGentle","durationSlow","durationSlower","durationUltraSlow","curves","curveAccelerateMax","curveAccelerateMid","curveAccelerateMin","curveDecelerateMax","curveDecelerateMid","curveDecelerateMin","curveEasyEaseMax","curveEasyEase","curveLinear","motionTokens"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,sDAAsD;AACtD,2EAA2E;AAC3E,+BAA+B;AAC/B,OAAO,MAAMA,YAAY;IACvBC,mBAAmB;IACnBC,gBAAgB;IAChBC,cAAc;IACdC,gBAAgB;IAChBC,gBAAgB;IAChBC,cAAc;IACdC,gBAAgB;IAChBC,mBAAmB;AACrB,EAAW;AAEX,mDAAmD;AACnD,yCAAyC;AACzC,OAAO,MAAMC,SAAS;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,oBAAoB;IACpBC,kBAAkB;IAClBC,eAAe;IACfC,aAAa;AACf,EAAW;AAEX,uCAAuC;AACvC,OAAO,MAAMC,eAAe;IAC1B,GAAGnB,SAAS;IACZ,GAAGS,MAAM;AACX,EAAE,CAEF;;;;;;;;;AASA"}
+40
View File
@@ -0,0 +1,40 @@
import { SLOT_ELEMENT_TYPE_SYMBOL, SLOT_RENDER_FUNCTION_SYMBOL } from '@fluentui/react-utilities';
import * as React from 'react';
export function presenceMotionSlot(motion, options) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
const { as, children, ...rest } = motion !== null && motion !== void 0 ? motion : {};
if (process.env.NODE_ENV !== 'production') {
if (typeof as !== 'undefined') {
throw new Error(`@fluentui/react-motion: "as" property is not supported on motion slots.`);
}
}
if (motion === null) {
// Heads up!
// Render function is used there to avoid rendering a motion component and handle unmounting logic
const isUnmounted = !options.defaultProps.visible && options.defaultProps.unmountOnExit;
const renderFn = (_, props)=>isUnmounted ? null : /*#__PURE__*/ React.createElement(React.Fragment, null, props.children);
/**
* Casting is required here as SlotComponentType is a function, not an object.
* Although SlotComponentType has a function signature, it is still just an object.
* This is required to make a slot callable (JSX compatible), this is the exact same approach
* that is used on `@types/react` components
*/ return {
[SLOT_RENDER_FUNCTION_SYMBOL]: renderFn,
[SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
};
}
/**
* Casting is required here as SlotComponentType is a function, not an object.
* Although SlotComponentType has a function signature, it is still just an object.
* This is required to make a slot callable (JSX compatible), this is the exact same approach
* that is used on `@types/react` components
*/ const propsWithMetadata = {
...options.defaultProps,
...rest,
[SLOT_ELEMENT_TYPE_SYMBOL]: options.elementType
};
if (typeof children === 'function') {
propsWithMetadata[SLOT_RENDER_FUNCTION_SYMBOL] = children;
}
return propsWithMetadata;
}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
export { };
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["type AtomCore = { keyframes: Keyframe[] } & KeyframeEffectOptions;\n\nexport type AtomMotion = AtomCore & {\n /**\n * Allows to specify a reduced motion version of the animation. If provided, the settings will be used when the\n * user has enabled the reduced motion setting in the operating system (i.e `prefers-reduced-motion` media query is\n * active). If not provided, the duration of the animation will be overridden to be 1ms.\n *\n * Note, if `keyframes` are provided, they will be used instead of the regular `keyframes`.\n */\n reducedMotion?: Partial<AtomCore>;\n};\n\nexport type PresenceDirection = 'enter' | 'exit';\n\nexport type PresenceMotion = Record<PresenceDirection, AtomMotion | AtomMotion[]>;\n\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":"AAqCA,WAME"}
+18
View File
@@ -0,0 +1,18 @@
import * as React from 'react';
import * as ReactIs from 'react-is';
export function getChildElement(children) {
try {
const child = React.Children.only(children);
if (typeof child.type === 'string' || ReactIs.isForwardRef(child)) {
return child;
}
// We don't need to do anything here: we catch the exception from React to throw a more meaningful error
// eslint-disable-next-line no-empty
} catch {}
throw new Error([
'@fluentui/react-motion: Invalid child element.',
'\n',
'Motion factories require a single child element to be passed. ',
'That element element should support ref forwarding i.e. it should be either an intrinsic element (e.g. div) or a component that uses React.forwardRef().'
].join(''));
}
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/getChildElement.ts"],"sourcesContent":["import * as React from 'react';\nimport * as ReactIs from 'react-is';\n\nexport function getChildElement(children: React.ReactElement) {\n try {\n const child = React.Children.only(children) as React.ReactElement & { ref: React.Ref<HTMLElement> };\n\n if (typeof child.type === 'string' || ReactIs.isForwardRef(child)) {\n return child as React.ReactElement & { ref: React.Ref<HTMLElement> };\n }\n\n // We don't need to do anything here: we catch the exception from React to throw a more meaningful error\n // eslint-disable-next-line no-empty\n } catch {}\n\n throw new Error(\n [\n '@fluentui/react-motion: Invalid child element.',\n '\\n',\n 'Motion factories require a single child element to be passed. ',\n 'That element element should support ref forwarding i.e. it should be either an intrinsic element (e.g. div) or a component that uses React.forwardRef().',\n ].join(''),\n );\n}\n"],"names":["React","ReactIs","getChildElement","children","child","Children","only","type","isForwardRef","Error","join"],"rangeMappings":";;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,YAAYC,aAAa,WAAW;AAEpC,OAAO,SAASC,gBAAgBC,QAA4B;IAC1D,IAAI;QACF,MAAMC,QAAQJ,MAAMK,QAAQ,CAACC,IAAI,CAACH;QAElC,IAAI,OAAOC,MAAMG,IAAI,KAAK,YAAYN,QAAQO,YAAY,CAACJ,QAAQ;YACjE,OAAOA;QACT;IAEA,wGAAwG;IACxG,oCAAoC;IACtC,EAAE,OAAM,CAAC;IAET,MAAM,IAAIK,MACR;QACE;QACA;QACA;QACA;KACD,CAACC,IAAI,CAAC;AAEX"}
@@ -0,0 +1,20 @@
import * as React from 'react';
/**
* Given `children`, return an object mapping key to child.
*/ export function getChildMapping(children) {
const childMapping = {};
if (children) {
React.Children.toArray(children).forEach((child)=>{
if (React.isValidElement(child)) {
var _child_key;
childMapping[(_child_key = child.key) !== null && _child_key !== void 0 ? _child_key : ''] = {
appear: false,
element: child,
visible: true,
unmountOnExit: true
};
}
});
}
return childMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/getChildMapping.ts"],"sourcesContent":["import * as React from 'react';\nimport type { PresenceGroupChildMapping } from './types';\n\n/**\n * Given `children`, return an object mapping key to child.\n */\nexport function getChildMapping(children: React.ReactNode | undefined) {\n const childMapping: PresenceGroupChildMapping = {};\n\n if (children) {\n React.Children.toArray(children).forEach(child => {\n if (React.isValidElement(child)) {\n childMapping[child.key ?? ''] = {\n appear: false,\n element: child,\n visible: true,\n unmountOnExit: true,\n };\n }\n });\n }\n\n return childMapping;\n}\n"],"names":["React","getChildMapping","children","childMapping","Children","toArray","forEach","child","isValidElement","key","appear","element","visible","unmountOnExit"],"rangeMappings":";;;;;;;;;;;;;;;;;;;","mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B;;CAEC,GACD,OAAO,SAASC,gBAAgBC,QAAqC;IACnE,MAAMC,eAA0C,CAAC;IAEjD,IAAID,UAAU;QACZF,MAAMI,QAAQ,CAACC,OAAO,CAACH,UAAUI,OAAO,CAACC,CAAAA;YACvC,IAAIP,MAAMQ,cAAc,CAACD,QAAQ;oBAClBA;gBAAbJ,YAAY,CAACI,CAAAA,aAAAA,MAAME,GAAG,cAATF,wBAAAA,aAAa,GAAG,GAAG;oBAC9BG,QAAQ;oBACRC,SAASJ;oBACTK,SAAS;oBACTC,eAAe;gBACjB;YACF;QACF;IACF;IAEA,OAAOV;AACT"}
@@ -0,0 +1,30 @@
import { mergeChildMappings } from './mergeChildMappings';
export function getNextChildMapping(prevChildMapping, nextChildMapping) {
const childrenMapping = mergeChildMappings(prevChildMapping, nextChildMapping);
Object.entries(childrenMapping).forEach(([key, childDefinition])=>{
const hasPrev = key in prevChildMapping;
const hasNext = key in nextChildMapping;
if (hasNext) {
// Case 1: item hasn't changed transition states
if (hasPrev) {
childrenMapping[key] = {
...childDefinition
};
return;
}
// Case 2: item is new (entering)
childrenMapping[key] = {
...childDefinition,
appear: true,
visible: true
};
return;
}
// Case 3: item is leaving
childrenMapping[key] = {
...childDefinition,
visible: false
};
});
return childrenMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/getNextChildMapping.ts"],"sourcesContent":["import { mergeChildMappings } from './mergeChildMappings';\nimport type { PresenceGroupChildMapping } from './types';\n\nexport function getNextChildMapping(\n prevChildMapping: PresenceGroupChildMapping,\n nextChildMapping: PresenceGroupChildMapping,\n) {\n const childrenMapping = mergeChildMappings(prevChildMapping, nextChildMapping);\n\n Object.entries(childrenMapping).forEach(([key, childDefinition]) => {\n const hasPrev = key in prevChildMapping;\n const hasNext = key in nextChildMapping;\n\n if (hasNext) {\n // Case 1: item hasn't changed transition states\n if (hasPrev) {\n childrenMapping[key] = { ...childDefinition };\n return;\n }\n\n // Case 2: item is new (entering)\n childrenMapping[key] = {\n ...childDefinition,\n appear: true,\n visible: true,\n };\n return;\n }\n\n // Case 3: item is leaving\n childrenMapping[key] = {\n ...childDefinition,\n visible: false,\n };\n });\n\n return childrenMapping;\n}\n"],"names":["mergeChildMappings","getNextChildMapping","prevChildMapping","nextChildMapping","childrenMapping","Object","entries","forEach","key","childDefinition","hasPrev","hasNext","appear","visible"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,SAASA,kBAAkB,QAAQ,uBAAuB;AAG1D,OAAO,SAASC,oBACdC,gBAA2C,EAC3CC,gBAA2C;IAE3C,MAAMC,kBAAkBJ,mBAAmBE,kBAAkBC;IAE7DE,OAAOC,OAAO,CAACF,iBAAiBG,OAAO,CAAC,CAAC,CAACC,KAAKC,gBAAgB;QAC7D,MAAMC,UAAUF,OAAON;QACvB,MAAMS,UAAUH,OAAOL;QAEvB,IAAIQ,SAAS;YACX,gDAAgD;YAChD,IAAID,SAAS;gBACXN,eAAe,CAACI,IAAI,GAAG;oBAAE,GAAGC,eAAe;gBAAC;gBAC5C;YACF;YAEA,iCAAiC;YACjCL,eAAe,CAACI,IAAI,GAAG;gBACrB,GAAGC,eAAe;gBAClBG,QAAQ;gBACRC,SAAS;YACX;YACA;QACF;QAEA,0BAA0B;QAC1BT,eAAe,CAACI,IAAI,GAAG;YACrB,GAAGC,eAAe;YAClBI,SAAS;QACX;IACF;IAEA,OAAOT;AACT"}
@@ -0,0 +1,39 @@
/**
* When you're adding or removing children some may be added or removed in the same render pass. We want to show *both*
* since we want to simultaneously animate elements in and out. This function takes a previous set of keys and a new set
* of keys and merges them with its best guess of the correct ordering.
*/ export function mergeChildMappings(prevMapping, nextMapping) {
function getValueForKey(key) {
return key in nextMapping ? nextMapping[key] : prevMapping[key];
}
// For each key of `next`, the list of keys to insert before that key in
// the combined list
const nextKeysPending = {};
let pendingKeys = [];
// eslint-disable-next-line guard-for-in
for(const prevKey in prevMapping){
if (prevKey in nextMapping) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys;
pendingKeys = [];
}
continue;
}
pendingKeys.push(prevKey);
}
const childMapping = {};
// eslint-disable-next-line guard-for-in
for(const nextKey in nextMapping){
if (nextKeysPending[nextKey]) {
for (const pendingNextKey of nextKeysPending[nextKey]){
childMapping[pendingNextKey] = getValueForKey(pendingNextKey);
}
}
childMapping[nextKey] = getValueForKey(nextKey);
}
// Finally, add the keys which didn't appear before any key in `next`
for (const pendingKey of pendingKeys){
childMapping[pendingKey] = getValueForKey(pendingKey);
}
return childMapping;
}
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/mergeChildMappings.ts"],"sourcesContent":["import type { PresenceGroupChildMapping } from './types';\n\n/**\n * When you're adding or removing children some may be added or removed in the same render pass. We want to show *both*\n * since we want to simultaneously animate elements in and out. This function takes a previous set of keys and a new set\n * of keys and merges them with its best guess of the correct ordering.\n */\nexport function mergeChildMappings(\n prevMapping: PresenceGroupChildMapping,\n nextMapping: PresenceGroupChildMapping,\n): PresenceGroupChildMapping {\n function getValueForKey(key: string) {\n return key in nextMapping ? nextMapping[key] : prevMapping[key];\n }\n\n // For each key of `next`, the list of keys to insert before that key in\n // the combined list\n const nextKeysPending: Record<string, string[]> = {};\n let pendingKeys: string[] = [];\n\n // eslint-disable-next-line guard-for-in\n for (const prevKey in prevMapping) {\n if (prevKey in nextMapping) {\n if (pendingKeys.length) {\n nextKeysPending[prevKey] = pendingKeys;\n pendingKeys = [];\n }\n\n continue;\n }\n\n pendingKeys.push(prevKey);\n }\n\n const childMapping: PresenceGroupChildMapping = {};\n\n // eslint-disable-next-line guard-for-in\n for (const nextKey in nextMapping) {\n if (nextKeysPending[nextKey]) {\n for (const pendingNextKey of nextKeysPending[nextKey]) {\n childMapping[pendingNextKey] = getValueForKey(pendingNextKey);\n }\n }\n\n childMapping[nextKey] = getValueForKey(nextKey);\n }\n\n // Finally, add the keys which didn't appear before any key in `next`\n for (const pendingKey of pendingKeys) {\n childMapping[pendingKey] = getValueForKey(pendingKey);\n }\n\n return childMapping;\n}\n"],"names":["mergeChildMappings","prevMapping","nextMapping","getValueForKey","key","nextKeysPending","pendingKeys","prevKey","length","push","childMapping","nextKey","pendingNextKey","pendingKey"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA;;;;CAIC,GACD,OAAO,SAASA,mBACdC,WAAsC,EACtCC,WAAsC;IAEtC,SAASC,eAAeC,GAAW;QACjC,OAAOA,OAAOF,cAAcA,WAAW,CAACE,IAAI,GAAGH,WAAW,CAACG,IAAI;IACjE;IAEA,wEAAwE;IACxE,oBAAoB;IACpB,MAAMC,kBAA4C,CAAC;IACnD,IAAIC,cAAwB,EAAE;IAE9B,wCAAwC;IACxC,IAAK,MAAMC,WAAWN,YAAa;QACjC,IAAIM,WAAWL,aAAa;YAC1B,IAAII,YAAYE,MAAM,EAAE;gBACtBH,eAAe,CAACE,QAAQ,GAAGD;gBAC3BA,cAAc,EAAE;YAClB;YAEA;QACF;QAEAA,YAAYG,IAAI,CAACF;IACnB;IAEA,MAAMG,eAA0C,CAAC;IAEjD,wCAAwC;IACxC,IAAK,MAAMC,WAAWT,YAAa;QACjC,IAAIG,eAAe,CAACM,QAAQ,EAAE;YAC5B,KAAK,MAAMC,kBAAkBP,eAAe,CAACM,QAAQ,CAAE;gBACrDD,YAAY,CAACE,eAAe,GAAGT,eAAeS;YAChD;QACF;QAEAF,YAAY,CAACC,QAAQ,GAAGR,eAAeQ;IACzC;IAEA,qEAAqE;IACrE,KAAK,MAAME,cAAcP,YAAa;QACpCI,YAAY,CAACG,WAAW,GAAGV,eAAeU;IAC5C;IAEA,OAAOH;AACT"}
+1
View File
@@ -0,0 +1 @@
import * as React from 'react';
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/utils/groups/types.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type PresenceGroupChild = {\n element: React.ReactElement;\n\n appear: boolean;\n visible: boolean;\n unmountOnExit: boolean;\n};\n\nexport type PresenceGroupChildMapping = Record<string, PresenceGroupChild>;\n"],"names":["React"],"rangeMappings":"","mappings":"AAAA,YAAYA,WAAW,QAAQ"}
+54
View File
@@ -0,0 +1,54 @@
{
"name": "@fluentui/react-motion",
"version": "9.6.7",
"description": "A package with utilities & motion definitions using Web Animations API",
"main": "lib-commonjs/index.js",
"module": "lib/index.js",
"typings": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"*.md",
"dist/*.d.ts",
"lib",
"lib-commonjs"
],
"repository": {
"type": "git",
"url": "https://github.com/microsoft/fluentui"
},
"license": "MIT",
"devDependencies": {
"@fluentui/eslint-plugin": "*",
"@fluentui/react-conformance": "*",
"@fluentui/react-conformance-griffel": "*",
"@fluentui/scripts-api-extractor": "*",
"@fluentui/scripts-cypress": "*"
},
"dependencies": {
"@fluentui/react-shared-contexts": "^9.21.2",
"@fluentui/react-utilities": "^9.18.20",
"@swc/helpers": "^0.5.1",
"react-is": "^17.0.2"
},
"peerDependencies": {
"@types/react": ">=16.8.0 <19.0.0",
"@types/react-dom": ">=16.8.0 <19.0.0",
"react": ">=16.14.0 <19.0.0",
"react-dom": ">=16.8.0 <19.0.0"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"node": "./lib-commonjs/index.js",
"import": "./lib/index.js",
"require": "./lib-commonjs/index.js"
},
"./package.json": "./package.json"
},
"beachball": {
"disallowedChangeTypes": [
"major",
"prerelease"
]
}
}