Skip to content

Commit

Permalink
TypeScript conversion of animation package (#12702)
Browse files Browse the repository at this point in the history
* WIP

* WIP: Partial refactor and conversion to TypeScript

Note that the main story editor does not compile at this stage, but the animation package works in isolation and can be seen in action through Storybook: `npm run storybook`.

* Forgot to simplify the animation creation in this file

* Converted tests to TS and added to tsconfig

* Fixed test for `sanitizeTimings`

* Updated story editor to use new animation state enum

* Fixed a bunch of references to anim enum

A bunch of anim constants have been converted from object to enums and thus had their casing updating from `SCREAMING_SNAKE_CASE` to `PascalCase`.

* Fixed constant

* Excluded stories from TS

* Excluded stories from TS

* Fixed some bugs found in test failures

* Fixed last ts errors

Thís required creating a union type for all the animations. However, it works a little weird, so had to do a bunch of `as const` stuff in tests, so worry about typing the implementation of this in other packages, but for now this is good.

* Restructured animation parts

* Fixed a missing export

* Adjusted comment to clarify

* Fixed bug, that I feel must have been there before too?

* Fixed bug due to misspelled field name

Yes, `panDirection` would be better, but it is already referenced a ton of places, so it is a lot of unnecessary work to change it.

* Fixed pulse keyframe generator test

* Fixed types and test for `getGlobalSpace`

* Trying to fix errors in d.ts. files

Dunno why eslint complains, but maybe it is the missing header?

* Fixed test with bad animation ids

* (Re)fixed test with bad animation ids

* Fix config for text-sets package

* Update lock file

* Fix types for amp components

* Update tsconfig

* Try to adjust web-animations-js types

* Removed irrelevant polyfill

* Moved element offset functions once more

* Added clarifying comment

* Fixed some types

* Fix case

* Typo

* Fixed import after reorg

Co-authored-by: Pascal Birchler <pascalb@google.com>
  • Loading branch information
Morten Barklund and swissspidy authored Nov 29, 2022
1 parent 3f30fe7 commit 7e8f703
Show file tree
Hide file tree
Showing 190 changed files with 3,795 additions and 4,164 deletions.
1 change: 1 addition & 0 deletions .storybook/main.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module.exports = {
'../packages/wp-story-editor/src/**/stories/*.@(js|mdx)',
'../packages/activation-notice/src/**/stories/*.@(js|mdx)',
'../packages/design-system/src/**/stories/*.@(js|mdx)',
'../packages/animation/src/**/stories/*.@(js|mdx)',
],
addons: [
'@storybook/addon-a11y/register',
Expand Down
42 changes: 31 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 8 additions & 6 deletions packages/animation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,30 @@
},
"customExports": {
".": {
"default": "./src/index.js"
"default": "./src/index.ts"
}
},
"main": "dist/index.js",
"module": "dist-module/index.js",
"source": "src/index.js",
"types": "dist-types/index.d.ts",
"source": "src/index.ts",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@googleforcreators/elements": "*",
"@googleforcreators/i18n": "*",
"@googleforcreators/media": "*",
"@googleforcreators/react": "*",
"@googleforcreators/units": "*",
"flagged": "^2.0.6",
"prop-types": "^15.8.1",
"styled-components": "^5.3.6",
"uuid": "^9.0.0",
"web-animations-js": "^2.3.2"
"uuid": "^9.0.0"
},
"devDependencies": {
"@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1"
"@testing-library/react-hooks": "^8.0.1",
"@types/styled-components": "^5.1.26",
"@types/web-animations-js": "^2.2.12"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ function AMPAnimations() {
actions: { getAnimationParts },
} = useStoryAnimationContext();

return animationTargets.reduce(
(animators, target) => [
...animators,
...getAnimationParts(target).map(({ id, AMPAnimation }) => (
<AMPAnimation key={id} prefixId={providerId} />
)),
],
[]
return (
<>
{animationTargets
.map((target) => [
getAnimationParts(target).map(({ id, AMPAnimation }) => (
<AMPAnimation key={id} prefixId={providerId} />
)),
])
.flat(2)}
</>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
* External dependencies
*/
import { useMemo } from '@googleforcreators/react';
import PropTypes from 'prop-types';
import type { FunctionComponent, PropsWithChildren } from 'react';

/**
* Internal dependencies
*/
import type { AnimationPart } from '../parts';
import type { WrapperProps } from './types';
import useStoryAnimationContext from './useStoryAnimationContext';

const fullSizeAbsoluteStyles = {
Expand All @@ -32,15 +34,26 @@ const fullSizeAbsoluteStyles = {
position: 'absolute',
top: 0,
left: 0,
};
} as const;

function ComposableWrapper({ animationParts, children }) {
type ComposableWrapperProps = PropsWithChildren<{
animationParts: AnimationPart[];
}>;

type Composed = PropsWithChildren<unknown>;

function ComposableWrapper({
animationParts,
children,
}: ComposableWrapperProps) {
const root: FunctionComponent = (props: Composed) =>
props.children as React.ReactElement;
const ComposedWrapper = useMemo(
() =>
animationParts.reduce(
(Composable, animationPart) => {
animationParts.reduce<FunctionComponent>(
(Composable: FunctionComponent, animationPart: AnimationPart) => {
const { AMPTarget } = animationPart;
const Composed = function (props) {
const Composed = (props: Composed) => {
return (
<Composable>
<AMPTarget style={fullSizeAbsoluteStyles}>
Expand All @@ -49,23 +62,16 @@ function ComposableWrapper({ animationParts, children }) {
</Composable>
);
};
Composed.propTypes = { children: PropTypes.node };
return Composed;
},
(props) => props.children
root
),
[animationParts]
);

return <ComposedWrapper>{children}</ComposedWrapper>;
}

ComposableWrapper.propTypes = {
animationParts: PropTypes.arrayOf(PropTypes.object),
children: PropTypes.node.isRequired,
};

function AMPWrapper({ target, children }) {
function AMPWrapper({ target, children }: WrapperProps) {
const {
actions: { getAnimationParts },
} = useStoryAnimationContext();
Expand All @@ -77,9 +83,4 @@ function AMPWrapper({ target, children }) {
);
}

AMPWrapper.propTypes = {
target: PropTypes.string,
children: PropTypes.node,
};

export default AMPWrapper;
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,36 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';
import { useCallback, useRef, useEffect } from '@googleforcreators/react';

/**
* Internal dependencies
*/
import createKeyframeEffect from '../utils/createKeyframeEffect';
import FullSizeAbsolute from './fullSizeAbsolute';
import { WAAPIAnimationProps } from './types';
import type { WAAPIAnimationWrapperProps, WrapperProps } from './types';
import useStoryAnimationContext from './useStoryAnimationContext';

function WAAPIAnimationWrapper({
children,
hoistAnimation,
keyframes,
timings,
targetLeafElement,
}) {
const target = useRef(null);
targetLeafElement = false,
}: WAAPIAnimationWrapperProps) {
const target = useRef<HTMLDivElement | null>(null);

useEffect(() => {
if (!keyframes) {
return () => {};
return () => undefined;
}

const targetEl = targetLeafElement
? target.current?.querySelector('[data-leaf-element="true"]')
: target.current;

if (!targetEl) {
return () => {};
return () => undefined;
}
const effect = createKeyframeEffect(targetEl, keyframes, timings);
return hoistAnimation(new Animation(effect, document.timeline));
Expand All @@ -55,21 +54,20 @@ function WAAPIAnimationWrapper({
return <FullSizeAbsolute ref={target}>{children}</FullSizeAbsolute>;
}

WAAPIAnimationWrapper.propTypes = WAAPIAnimationProps;

function WAAPIWrapper({ children, target }) {
const { hoistWAAPIAnimation, AnimationParts } = useStoryAnimationContext(
function WAAPIWrapper({ children, target }: WrapperProps) {
const { hoistWAAPIAnimation, animationParts } = useStoryAnimationContext(
({ actions }) => ({
hoistWAAPIAnimation: actions.hoistWAAPIAnimation,
AnimationParts: actions.getAnimationParts(target),
animationParts: actions.getAnimationParts(target),
})
);
const WAAPIAnimationParts = AnimationParts?.map(
const WAAPIAnimationParts = animationParts?.map(
(anim) => anim.WAAPIAnimation
);

const hoistAnimation = useCallback(
(animation) => hoistWAAPIAnimation({ animation, elementId: target }),
(animation: Animation) =>
hoistWAAPIAnimation({ animation, elementId: target }),
[target, hoistWAAPIAnimation]
);

Expand Down Expand Up @@ -101,9 +99,4 @@ function WAAPIWrapper({ children, target }) {
);
}

WAAPIWrapper.propTypes = {
children: PropTypes.node,
target: PropTypes.string,
};

export default WAAPIWrapper;
Loading

0 comments on commit 7e8f703

Please sign in to comment.