diff --git a/example/storybook/.ondevice/storybook.requires.js b/example/storybook/.ondevice/storybook.requires.js index 0c8a85310..885793009 100644 --- a/example/storybook/.ondevice/storybook.requires.js +++ b/example/storybook/.ondevice/storybook.requires.js @@ -7,7 +7,8 @@ import { addArgsEnhancer, clearDecorators, } from '@storybook/react-native'; - +import { config } from '../src/components/nb.config'; +console.log(Object.keys(config)); global.STORIES = [ { titlePrefix: '', @@ -52,8 +53,8 @@ const getStories = () => { // "./src/api/AsForwarder/AsForwarder.stories.tsx": require("../src/api/AsForwarder/AsForwarder.stories.tsx"), // "./src/api/ColorModeBasedStyles/ColorMode.stories.tsx": require("../src/api/ColorModeBasedStyles/ColorMode.stories.tsx"), // "./src/api/CompoundVariants/CompoundVarinats.stories.tsx": require("../src/api/CompoundVariants/CompoundVarinats.stories.tsx"), - './src/api/createStyled/createStyled.stories.tsx': require('../src/api/createStyled/createStyled.stories.tsx'), - './src/api/DescendantsStyles/ContextBasedStyles.stories.tsx': require('../src/api/DescendantsStyles/ContextBasedStyles.stories.tsx'), + // './src/api/createStyled/createStyled.stories.tsx': require('../src/api/createStyled/createStyled.stories.tsx'), + // './src/api/DescendantsStyles/ContextBasedStyles.stories.tsx': require('../src/api/DescendantsStyles/ContextBasedStyles.stories.tsx'), // "./src/api/MultipleProvder/MultipleProvider.stories.tsx": require("../src/api/MultipleProvder/MultipleProvider.stories.tsx"), // "./src/api/PlatformBasedStyles/PlatformBasedStyles.stories.tsx": require("../src/api/PlatformBasedStyles/PlatformBasedStyles.stories.tsx"), // "./src/api/PropertyResolver/PropertyResolver.stories.tsx": require("../src/api/PropertyResolver/PropertyResolver.stories.tsx"), @@ -65,7 +66,7 @@ const getStories = () => { // "./src/api/Typescript/Typescript.stories.tsx": require("../src/api/Typescript/Typescript.stories.tsx"), // "./src/api/UtilityFunctions/UtilityFunctions.stories.tsx": require("../src/api/UtilityFunctions/UtilityFunctions.stories.tsx"), // "./src/api/Variants/BaseStyleVariantSizes.stories.tsx": require("../src/api/Variants/BaseStyleVariantSizes.stories.tsx"), - // "./src/plugins/AnimationPlugin/Animation.stories.tsx": require("../src/plugins/AnimationPlugin/Animation.stories.tsx"), + './src/plugins/AnimationPlugin/Animation.stories.tsx': require('../src/plugins/AnimationPlugin/Animation.stories.tsx'), // "./src/plugins/CSSVariables/CSSVariables.stories.tsx": require("../src/plugins/CSSVariables/CSSVariables.stories.tsx"), // "./src/plugins/FontsPlugin/FontsPlugin.stories.tsx": require("../src/plugins/FontsPlugin/FontsPlugin.stories.tsx"), }; diff --git a/example/storybook/babel.config.js b/example/storybook/babel.config.js index b27308285..0b330301d 100644 --- a/example/storybook/babel.config.js +++ b/example/storybook/babel.config.js @@ -5,6 +5,7 @@ module.exports = function (api) { return { presets: ['babel-preset-expo'], plugins: [ + 'react-native-reanimated/plugin', process.env.NODE_ENV !== 'production' ? [ 'module-resolver', @@ -15,14 +16,18 @@ module.exports = function (api) { __dirname, '../../packages/react/src' ), - ['@gluestack-style/animation-plugin']: path.join( + ['@gluestack-style/legend-motion-animation-driver']: path.join( __dirname, - '../../packages/animation-plugin/src' + '../../packages/animation-legend-motion-driver/src' + ), + ['@gluestack-style/moti-driver']: path.join( + __dirname, + '../../packages/animation-moti-animation-driver/src' + ), + ['@gluestack-style/animation-resolver']: path.join( + __dirname, + '../../packages/animation-resolver/src' ), - // ['@gluestack-style/animation-plugin']: path.join( - // __dirname, - // '../../packages/animation-plugin/src' - // ), // ['@dank-style/react']: path.join( // __dirname, // '../../packages/react/src' diff --git a/example/storybook/package.json b/example/storybook/package.json index 4fc488445..04fb7dd3a 100644 --- a/example/storybook/package.json +++ b/example/storybook/package.json @@ -23,7 +23,6 @@ }, "dependencies": { "@expo/html-elements": "^0.4.2", - "@gluestack-style/animation-plugin": "latest", "@gluestack-style/react": "^0.2.11-alpha.0", "@gluestack-ui/actionsheet": "^0.2.16", "@gluestack-ui/alert-dialog": "^0.1.14", @@ -53,8 +52,11 @@ "expo-status-bar": "~1.4.2", "fs": "^0.0.1-security", "lucide-react-native": "^0.236.0", + "moti": "^0.26.0", "prism-react-renderer": "^1.3.5", "react": "^18.2.0", + "react-native-gesture-handler": "^2.13.1", + "react-native-reanimated": "~2.12.0", "react-native-safe-area-context": "^4.4.1", "react-native-svg": "13.4.0", "react-native-web": "^0.19.7", @@ -95,6 +97,9 @@ "typescript": "^5.1.6" }, "peerDependencies": { + "@gluestack-style/legend-motion-animation-driver": "*", + "@gluestack-style/moti-animation-driver": "*", + "@gluestack-style/animation-resolver": "*", "react": "*", "react-dom": "*", "react-native": "*", diff --git a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx index 3ba5d4dea..55d3d5ec2 100644 --- a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx +++ b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx @@ -11,16 +11,14 @@ import { Pressable as RNPressable, Text as RNText, StyleSheet, - Switch, View, } from 'react-native'; import { AsForwarder, createStyled, - styled, + styled1, Theme, useBreakpointValue, - useColorMode, useStyled, useToken, } from '@gluestack-style/react'; @@ -30,7 +28,6 @@ import { AddIcon, Box, Icon } from '@gluestack/design-system'; import { AlertCircle, Circle, Sun } from 'lucide-react-native'; import { AnimationResolver } from '@gluestack-style/animation-plugin'; -import { ScrollView } from 'react-native'; const styleshet = StyleSheet.create({ style: { @@ -43,16 +40,6 @@ const Pressable = styled( { bg: '$red200', p: '$2', - props: { - variant: 'solid', - }, - variants: { - variant: { - solid: { - bg: '$red400', - }, - }, - }, }, { componentName: 'Pressable', @@ -196,53 +183,10 @@ const Text1 = styled( }, { ancestorStyle: ['_text'], componentName: 'TEXT' } ); - -const StyledSwitch = styled(ScrollView, {}); - export function ContextBasedStyles() { - const [state, setState] = useState(false); - return ( - - { - setState(!state); - }} - > - color mode: {state ? 'dark' : 'light'} - - - - - - - {/* - */} - + + {/* */} {/* @@ -357,12 +299,6 @@ export function ContextBasedStylesContent() { const renderItem = (item: any) => ( - {/* @ts-ignore */} - + - {/* @ts-ignore */} - + (prev + 1) % images.length); }} > - {'‣'} + {'‣'} (prev - 1 + images.length) % images.length); }} > - {'‣'} + {'‣'} ); diff --git a/example/storybook/tsconfig.json b/example/storybook/tsconfig.json index 8ad2be9db..6b68e3568 100644 --- a/example/storybook/tsconfig.json +++ b/example/storybook/tsconfig.json @@ -4,8 +4,14 @@ "baseUrl": ".", "paths": { "@gluestack-style/react": ["../../packages/react/src"], - "@gluestack-style/animation-plugin": [ - "../../packages/animation-plugin/src" + "@gluestack-style/legend-motion-animation-driver": [ + "../../packages/animation-legend-motion-driver/src" + ], + "@gluestack-style/moti-animation-driver": [ + "../../packages/animation-moti-driver/src" + ], + "@gluestack-style/animation-resolver": [ + "../../packages/animation-resolver/src" ], "react-native": ["./node_modules/react-native-web"] }, diff --git a/example/ui-examples-babel/App.tsx b/example/ui-examples-babel/App.tsx index 12ac30f41..d1b24831a 100644 --- a/example/ui-examples-babel/App.tsx +++ b/example/ui-examples-babel/App.tsx @@ -1,29 +1,30 @@ +// @ts-nocheck import React, { - useCallback, - useEffect, - useLayoutEffect, - useMemo, - useRef, + // useCallback, + // useEffect, + // useLayoutEffect, + // useMemo, + // useRef, useState, } from 'react'; import { - Pressable as RNPressable, - Text as RNText, - StyleSheet, + // Pressable as RNPressable, + // Text as RNText, + // StyleSheet, View, Pressable, Text, } from 'react-native'; import { - AsForwarder, + // AsForwarder, styled, - Theme, + // Theme, StyledProvider, } from '@gluestack-style/react'; import { config } from './gluestack-ui.config'; -import { createMotionAnimatedComponent, Motion } from '@legendapp/motion'; -import { AnimationResolver } from '@gluestack-style/animation-plugin'; +// import { createMotionAnimatedComponent, Motion } from '@legendapp/motion'; +// import { AnimationResolver } from '@gluestack-style/animation-plugin'; const Box = styled(View, { bg: '$yellow500', diff --git a/packages/animation-plugin/.gitignore b/packages/animation-legend-motion-driver/.gitignore similarity index 100% rename from packages/animation-plugin/.gitignore rename to packages/animation-legend-motion-driver/.gitignore diff --git a/packages/animation-plugin/.nvmrc b/packages/animation-legend-motion-driver/.nvmrc similarity index 100% rename from packages/animation-plugin/.nvmrc rename to packages/animation-legend-motion-driver/.nvmrc diff --git a/packages/animation-plugin/CHANGELOG.md b/packages/animation-legend-motion-driver/CHANGELOG.md similarity index 100% rename from packages/animation-plugin/CHANGELOG.md rename to packages/animation-legend-motion-driver/CHANGELOG.md diff --git a/packages/animation-plugin/README.md b/packages/animation-legend-motion-driver/README.md similarity index 100% rename from packages/animation-plugin/README.md rename to packages/animation-legend-motion-driver/README.md diff --git a/packages/animation-plugin/babel.config.js b/packages/animation-legend-motion-driver/babel.config.js similarity index 100% rename from packages/animation-plugin/babel.config.js rename to packages/animation-legend-motion-driver/babel.config.js diff --git a/packages/animation-legend-motion-driver/package.json b/packages/animation-legend-motion-driver/package.json new file mode 100644 index 000000000..57c8c031d --- /dev/null +++ b/packages/animation-legend-motion-driver/package.json @@ -0,0 +1,58 @@ +{ + "name": "@gluestack-style/legend-motion-animation-driver", + "version": "0.0.1", + "description": "A gluestack-style plugin for animation support using legendapp motion library", + "keywords": [ + "react", + "native", + "react-native", + "animation", + "legendapp", + "motion", + "driver", + "transition" + ], + "main": "lib/commonjs/index", + "types": "lib/typescript/index.d.ts", + "module": "lib/module/index", + "react-native": "src/index", + "source": "src/index", + "typings": "lib/typescript/index.d.ts", + "scripts": { + "prepare": "bob build", + "release": "release-it", + "build": "bob build", + "clean": "rm -rf lib" + }, + "peerDependencies": { + "@legendapp/motion": ">=2.2.0", + "@gluestack-style/react": ">=0.2.49" + }, + "devDependencies": { + "@gluestack-style/react": ">=0.2.49", + "@types/react": "^18.0.22", + "@types/react-native": "^0.69.15", + "babel-plugin-transform-remove-console": "^6.9.4", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "react-native": "^0.70.3", + "react-native-builder-bob": "^0.20.1", + "tsconfig": "*", + "typescript": "^4.7.4" + }, + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + "commonjs", + [ + "module" + ], + "typescript" + ] + }, + "files": [ + "lib/", + "src/" + ] +} diff --git a/packages/animation-legend-motion-driver/src/index.tsx b/packages/animation-legend-motion-driver/src/index.tsx new file mode 100644 index 000000000..6fa191d6c --- /dev/null +++ b/packages/animation-legend-motion-driver/src/index.tsx @@ -0,0 +1,210 @@ +import { + useStyled, + // @ts-ignore + type IAnimationDriverPlugin, + // @ts-ignore + type IAnimationResolver, +} from '@gluestack-style/react'; +import React, { useMemo } from 'react'; +import { + deepMerge, + deepMergeObjects, + setObjectKeyValue, + resolvedTokenization, +} from './utils'; +import { + Motion, + AnimatePresence as MotionAnimatePresence, +} from '@legendapp/motion'; +import { propertyTokenMap } from './propertyTokenMap'; + +function tokenizeAnimationPropsFromConfig( + props: any = {}, + config: any, + animationAliases: any, + path: any = [], + tokenizedAnimatedProps: any = {} +) { + for (const prop in props) { + if (Array.isArray(props[prop])) { + path.push(prop); + setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); + path.pop(); + } else if (animationAliases[prop]) { + path.push(prop); + const tokenizedValue = resolvedTokenization(props[prop], config); + setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); + path.pop(); + } else if (typeof props[prop] === 'object') { + path.push(prop); + const tokenizedValue = resolvedTokenization(props[prop], config); + setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); + // path.pop(); + tokenizeAnimationPropsFromConfig( + props[prop], + config, + animationAliases, + path, + tokenizedAnimatedProps + ); + path.pop(); + } else { + path.push(prop); + setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); + path.pop(); + } + } + + return tokenizedAnimatedProps; +} + +function getVariantProps(props: any, theme: any) { + const variantTypes = theme?.variants ? Object.keys(theme.variants) : []; + + const restProps = { ...props }; + + const variantProps: any = {}; + variantTypes?.forEach((variant) => { + if (props[variant]) { + variantProps[variant] = props[variant]; + // delete restProps[variant]; + } + }); + + return { + variantProps, + restProps, + }; +} + +function resolveVariantAnimationProps(variantProps: any, styledObject: any) { + let resolvedVariant = {}; + Object.keys(variantProps).forEach((variant) => { + const variantValue = variantProps[variant]; + const variantObject = styledObject?.variants?.[variant]?.[variantValue]; + + resolvedVariant = deepMerge(resolvedVariant, variantObject); + }); + + return resolvedVariant; +} + +const AnimatePresence = React.forwardRef( + ({ children, ...props }: any, ref?: any) => { + const ctx = useStyled(); + const clonedChildren: any = []; + const CONFIG = useMemo( + () => ({ + ...ctx.config, + propertyTokenMap, + }), + [ctx.config] + ); + + React.Children.toArray(children).forEach((child: any) => { + if (child?.type?.displayName === 'StyledComponent') { + let tokenizedAnimatedProps: any = {}; + const animationAliases = {}; + + const componentStyledObject = child?.type?.styled?.config; + const { variantProps, restProps } = getVariantProps( + child?.props, + componentStyledObject + ); + + const config = CONFIG; + + if (child.type.styled.resolvedProps) { + tokenizedAnimatedProps = child?.type?.styled?.resolvedProps; + } else { + const variantStyledObject = resolveVariantAnimationProps( + variantProps, + componentStyledObject + ); + const componentStyledObjectWithVariants = deepMergeObjects( + componentStyledObject, + variantStyledObject + ); + tokenizedAnimatedProps = tokenizeAnimationPropsFromConfig( + componentStyledObjectWithVariants, + config, + animationAliases + ); + + child.type.styled.resolvedProps = tokenizedAnimatedProps; + } + + const tokenizedSxAnimationProps: any = tokenizeAnimationPropsFromConfig( + child?.props?.sx, + config, + animationAliases + ); + + const mergedAnimatedProps = deepMergeObjects( + {}, + tokenizedSxAnimationProps, + tokenizedAnimatedProps + ); + + const clonedChild = React.cloneElement(child, { + exit: mergedAnimatedProps?.[':exit'], + ...restProps, + }); + clonedChildren.push(clonedChild); + } else { + clonedChildren.push(child); + } + }); + return ( + + {clonedChildren} + + ); + } +); +export class MotionAnimationDriver implements IAnimationDriverPlugin { + name: 'MotionAnimationDriver'; + engine = { ...Motion, AnimatePresence }; + config = { + aliases: { + ':animate': 'animate', + ':initial': 'initial', + ':exit': 'exit', + ':initialProps': 'initialProps', + ':animateProps': 'animateProps', + ':transition': 'transition', + ':transformOrigin': 'transformOrigin', + ':whileTap': 'whileTap', + ':whileHover': 'whileHover', + ':onAnimationComplete': 'onAnimationComplete', + } as const, + }; + + register(config: any) { + if (this.config) { + this.config.aliases = { + ...this.config?.aliases, + ...config?.aliases, + }; + + // @ts-ignore + this.config.tokens = { + // @ts-ignore + ...this.config?.tokens, + ...config?.tokens, + }; + + // @ts-ignore + this.config.ref = config?.ref; + } + } + + constructor(config?: IAnimationResolver) { + this.register(config); + this.name = 'MotionAnimationDriver'; + this.engine.AnimatePresence.defaultProps = { + ...this.engine.AnimatePresence.defaultProps, + config, + }; + } +} diff --git a/packages/animation-plugin/src/propertyTokenMap.ts b/packages/animation-legend-motion-driver/src/propertyTokenMap.ts similarity index 100% rename from packages/animation-plugin/src/propertyTokenMap.ts rename to packages/animation-legend-motion-driver/src/propertyTokenMap.ts diff --git a/packages/animation-plugin/src/utils.ts b/packages/animation-legend-motion-driver/src/utils.ts similarity index 100% rename from packages/animation-plugin/src/utils.ts rename to packages/animation-legend-motion-driver/src/utils.ts diff --git a/packages/animation-plugin/tsconfig.json b/packages/animation-legend-motion-driver/tsconfig.json similarity index 100% rename from packages/animation-plugin/tsconfig.json rename to packages/animation-legend-motion-driver/tsconfig.json diff --git a/packages/animation-moti-driver/.gitignore b/packages/animation-moti-driver/.gitignore new file mode 100644 index 000000000..3d3e2719a --- /dev/null +++ b/packages/animation-moti-driver/.gitignore @@ -0,0 +1,28 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +.pnp +.pnp.js + +# misc +.DS_Store +*.pem + +# build +dist +lib + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# turbo +.turbo diff --git a/packages/animation-moti-driver/.nvmrc b/packages/animation-moti-driver/.nvmrc new file mode 100644 index 000000000..5dbac1ed0 --- /dev/null +++ b/packages/animation-moti-driver/.nvmrc @@ -0,0 +1 @@ +v16.13.0 \ No newline at end of file diff --git a/packages/animation-moti-driver/CHANGELOG.md b/packages/animation-moti-driver/CHANGELOG.md new file mode 100644 index 000000000..41be139f9 --- /dev/null +++ b/packages/animation-moti-driver/CHANGELOG.md @@ -0,0 +1,17 @@ +# @gluestack-style/animation-plugin + +## 0.1.7 + +### Patch Changes + +- - Fixed transform array resoltion + +## 0.1.0 + +### Changes + +- Fix forward ref warning +- Fixed variant resolution +- Moved @gluestack-style/react to devDependency +- Add legend motion dependency +- Add variant support diff --git a/packages/animation-moti-driver/README.md b/packages/animation-moti-driver/README.md new file mode 100644 index 000000000..58e26e535 --- /dev/null +++ b/packages/animation-moti-driver/README.md @@ -0,0 +1,69 @@ +# @gluestack-style/animation-plugin + +## Installation + +To use `@gluestack-style/animation-plugin`, all you need to do is install the +`@gluestack-style/animation-plugin` package: + +```sh +$ yarn add @gluestack-style/animation-plugin + +# or + +$ npm i @gluestack-style/animation-plugin +``` + +## Usage + +You can initialize the Animation plugin by creating a new instance of the AnimationResolver class and providing it as an argument to the createStyled function. The `AnimationResolver` takes an optional `styledUtils` object that maps the styled utils object. Here's an example: + +```jsx +import { createStyled } from '@gluestack-style/react'; +import { AnimationResolver } from '@gluestack-style/animation-plugin'; + +const styled = createStyled([ + new AnimationResolver({ + aliases: { + ':initial': 'initial', + ':animate': 'animate', + ':exit': 'exit', + }, + }), +]); +``` + +In this example, we are creating a new instance of the AnimationResolver class, passing an object with the 'aliases' property as an argument. The aliases object maps the aliases :initial, :animate, and :exit to their corresponding animation props. + +## Example of creating a styled component: + +Once the plugin is initialized, you can use the styled function to create styled components with animation props. Here's an example: + +```jsx +const Box = styled(Motion.View, { + ':initial': { opacity: 0 }, + ':animate': { opacity: 1 }, + ':exit': { opacity: 0 }, +}); +``` + +The final internal styled object that will be resolved is: + +```jsx +styledObject = { + 'props': { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + }, + exit: { + opacity: 0, + }, + } + }, +}; +``` + +More guides on how to get started are available +[here](https://style.gluestack.io/). diff --git a/packages/animation-moti-driver/babel.config.js b/packages/animation-moti-driver/babel.config.js new file mode 100644 index 000000000..fda985a22 --- /dev/null +++ b/packages/animation-moti-driver/babel.config.js @@ -0,0 +1,22 @@ +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + process.env.NODE_ENV !== 'production' + ? [ + 'module-resolver', + { + alias: { + // For development, we want to alias the library to the source + ['@gluestack-style/react']: path.join( + __dirname, + '../react/src/index' + ), + }, + }, + ] + : ['transform-remove-console'], + ], + }; +}; diff --git a/packages/animation-moti-driver/package.json b/packages/animation-moti-driver/package.json new file mode 100644 index 000000000..db1ccca24 --- /dev/null +++ b/packages/animation-moti-driver/package.json @@ -0,0 +1,59 @@ +{ + "name": "@gluestack-style/moti-animation-driver", + "version": "0.0.1", + "description": "A gluestack-style driver for using moti animation with animation resolver plugin.", + "keywords": [ + "react", + "native", + "react-native", + "moti", + "driver", + "animation", + "transition" + ], + "main": "lib/commonjs/index", + "types": "lib/typescript/index.d.ts", + "module": "lib/module/index", + "react-native": "src/index", + "source": "src/index", + "typings": "lib/typescript/index.d.ts", + "scripts": { + "prepare": "bob build", + "release": "release-it", + "build": "bob build", + "clean": "rm -rf lib" + }, + "peerDependencies": { + "@gluestack-style/react": ">=0.2.49", + "moti": ">=0.26.0", + "react-native-gesture-handler": ">=2.12.1", + "react-native-reanimated": ">=3.5.1" + }, + "devDependencies": { + "@gluestack-style/react": "^0.2.49", + "@types/react": "^18.0.22", + "@types/react-native": "^0.69.15", + "babel-plugin-transform-remove-console": "^6.9.4", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "react-native": "^0.70.3", + "react-native-builder-bob": "^0.20.1", + "tsconfig": "*", + "typescript": "^4.7.4" + }, + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + "commonjs", + [ + "module" + ], + "typescript" + ] + }, + "files": [ + "lib/", + "src/" + ] +} diff --git a/packages/animation-moti-driver/src/index.tsx b/packages/animation-moti-driver/src/index.tsx new file mode 100644 index 000000000..4d574f316 --- /dev/null +++ b/packages/animation-moti-driver/src/index.tsx @@ -0,0 +1,73 @@ +import type { + // @ts-ignore + IAnimationDriverPlugin, + // @ts-ignore + IAnimationResolver, +} from '@gluestack-style/react'; +import 'react-native-reanimated'; +import 'react-native-gesture-handler'; +import { + MotiImage, + MotiView, + MotiText, + MotiScrollView, + MotiSafeAreaView, + MotiProgressBar, + AnimatePresence, +} from 'moti'; + +let Moti = { + Image: MotiImage, + View: MotiView, + Text: MotiText, + ScrollView: MotiScrollView, + SafeAreaView: MotiSafeAreaView, + ProgressBar: MotiProgressBar, + AnimatePresence, +}; +export class MotiAnimationDriver implements IAnimationDriverPlugin { + name: 'MotiAnimationDriver'; + engine = Moti; + config = { + aliases: { + ':animate': 'animate', + ':initial': 'from', + ':exit': 'exit', + ':initialProps': 'initialProps', + ':animateProps': 'animateProps', + ':transition': 'transition', + ':transformOrigin': 'transformOrigin', + ':whileTap': 'whileTap', + ':whileHover': 'whileHover', + ':onAnimationComplete': 'onAnimationComplete', + } as const, + animatedPropMap: { + x: 'translateX', + y: 'translateY', + } as const, + }; + + register(config: any) { + if (this.config) { + this.config.aliases = { + ...this.config?.aliases, + ...config?.aliases, + }; + + // @ts-ignore + this.config.tokens = { + // @ts-ignore + ...this.config?.tokens, + ...config?.tokens, + }; + + // @ts-ignore + this.config.ref = config?.ref; + } + } + + constructor(config?: IAnimationResolver) { + this.register(config); + this.name = 'MotiAnimationDriver'; + } +} diff --git a/packages/animation-moti-driver/tsconfig.json b/packages/animation-moti-driver/tsconfig.json new file mode 100644 index 000000000..7ebd787f0 --- /dev/null +++ b/packages/animation-moti-driver/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": ["./src"], + "exclude": ["node_modules", "example"], + "path": { + "@gluestack-style/react": ["../react/src"] + }, + "compilerOptions": { + "emitDeclarationOnly": true, + "noEmit": false, + "baseUrl": ".", + "declaration": true, + "allowUnreachableCode": false, + "allowUnusedLabels": true, + "esModuleInterop": true, + "importsNotUsedAsValues": "error", + "forceConsistentCasingInFileNames": true, + "jsx": "react", + "lib": ["esnext", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitUseStrict": false, + "noStrictGenericChecks": false, + "noUnusedLocals": false, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "esnext" + } +} diff --git a/packages/animation-plugin/src/index.tsx b/packages/animation-plugin/src/index.tsx deleted file mode 100644 index 8ef8ce5f4..000000000 --- a/packages/animation-plugin/src/index.tsx +++ /dev/null @@ -1,379 +0,0 @@ -import React, { useMemo } from 'react'; -import type { IStyled, IStyledPlugin } from '@gluestack-style/react'; -import { useStyled } from '@gluestack-style/react'; -import { - deepMerge, - deepMergeObjects, - setObjectKeyValue, - resolvedTokenization, -} from './utils'; -import { AnimatePresence } from '@legendapp/motion'; -import { propertyTokenMap } from './propertyTokenMap'; - -function tokenizeAnimationPropsFromConfig( - props: any = {}, - config: any, - animationAliases: any, - path: any = [], - tokenizedAnimatedProps: any = {} -) { - for (const prop in props) { - if (Array.isArray(props[prop])) { - path.push(prop); - setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); - path.pop(); - } else if (animationAliases[prop]) { - path.push(prop); - const tokenizedValue = resolvedTokenization(props[prop], config); - setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); - path.pop(); - } else if (typeof props[prop] === 'object') { - path.push(prop); - const tokenizedValue = resolvedTokenization(props[prop], config); - setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); - // path.pop(); - tokenizeAnimationPropsFromConfig( - props[prop], - config, - animationAliases, - path, - tokenizedAnimatedProps - ); - path.pop(); - } else { - path.push(prop); - setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); - path.pop(); - } - } - - return tokenizedAnimatedProps; -} - -function getVariantProps(props: any, theme: any) { - const variantTypes = theme?.variants ? Object.keys(theme.variants) : []; - - const restProps = { ...props }; - - const variantProps: any = {}; - variantTypes?.forEach((variant) => { - if (props[variant]) { - variantProps[variant] = props[variant]; - // delete restProps[variant]; - } - }); - - return { - variantProps, - restProps, - }; -} - -function resolveVariantAnimationProps(variantProps: any, styledObject: any) { - let resolvedVariant = {}; - Object.keys(variantProps).forEach((variant) => { - const variantValue = variantProps[variant]; - const variantObject = styledObject?.variants?.[variant]?.[variantValue]; - - resolvedVariant = deepMerge(resolvedVariant, variantObject); - }); - - return resolvedVariant; -} - -export class AnimationResolver implements IStyledPlugin { - name: 'AnimationResolver'; - styledUtils = { - aliases: { - ':animate': 'animate', - ':initial': 'initial', - ':exit': 'exit', - ':initialProps': 'initialProps', - ':animateProps': 'animateProps', - ':transition': 'transition', - ':transformOrigin': 'transformOrigin', - ':whileTap': 'whileTap', - ':whileHover': 'whileHover', - ':onAnimationComplete': 'onAnimationComplete', - } as const, - }; - - register(styledUtils: any) { - if (this.styledUtils) { - this.styledUtils.aliases = { - ...this.styledUtils?.aliases, - ...styledUtils?.aliases, - }; - - // @ts-ignore - this.styledUtils.tokens = { - // @ts-ignore - ...this.styledUtils?.tokens, - ...styledUtils?.tokens, - }; - - // @ts-ignore - this.styledUtils.ref = styledUtils?.ref; - } - } - - constructor(styledUtils?: IStyled) { - this.register(styledUtils); - this.name = 'AnimationResolver'; - } - - #childrenExitPropsMap: any = {}; - - #extendedConfig: any = {}; - - inputMiddleWare( - styledObj = {}, - shouldUpdateConfig: any = true - ): { - // @ts-ignore - [key in keyof typeof this.styledUtils.aliases]: (typeof this.styledUtils.aliases)[key]; - } { - // this.#childrenExitPropsMap = deepClone(styledObj); - const resolvedAnimatedProps = this.updateStyledObject( - styledObj, - shouldUpdateConfig - ); - const resolvedStyledObjectWithAnimatedProps = deepMerge( - styledObj, - resolvedAnimatedProps - ); - - if (shouldUpdateConfig) { - // @ts-ignore - return styledObj; - } - - return resolvedStyledObjectWithAnimatedProps; - } - - updateStyledObject( - styledObject: any = {}, - shouldUpdateConfig: boolean, - resolvedStyledObject: any = {}, - keyPath: string[] = [] - ) { - const aliases = this.styledUtils?.aliases; - for (const prop in styledObject) { - if (typeof styledObject[prop] === 'object') { - keyPath.push(prop); - this.updateStyledObject( - styledObject[prop], - shouldUpdateConfig, - resolvedStyledObject, - keyPath - ); - keyPath.pop(); - } - - // @ts-ignore - if (aliases && aliases?.[prop]) { - if (shouldUpdateConfig) { - // this.#childrenExitPropsMap[prop] = styledObject[prop]; - setObjectKeyValue( - this.#childrenExitPropsMap, - [...keyPath, prop], - styledObject[prop] - ); - } - const value = styledObject[prop]; - // @ts-ignore - keyPath.push('props', aliases[prop]); - setObjectKeyValue(resolvedStyledObject, keyPath, value); - keyPath.pop(); - keyPath.pop(); - delete styledObject[prop]; - } - } - - return resolvedStyledObject; - } - - componentMiddleWare({ Component, ExtendedConfig }: any) { - const styledConfig = this.#childrenExitPropsMap; - - this.#childrenExitPropsMap = {}; - - const NewComponent = React.forwardRef((props: any, ref?: any) => { - const { sx, ...rest } = props; - - const styledContext = useStyled(); - const CONFIG = useMemo( - () => ({ - ...styledContext.config, - propertyTokenMap, - }), - [styledContext.config] - ); - this.#extendedConfig = CONFIG; - if (ExtendedConfig) { - this.#extendedConfig = deepMerge(CONFIG, ExtendedConfig); - } - - let tokenizedAnimatedProps: any = {}; - const { variantProps, restProps } = getVariantProps(rest, styledConfig); - const variantStyledObject = resolveVariantAnimationProps( - variantProps, - styledConfig - ); - const componentStyledObject = deepMerge( - variantStyledObject, - styledConfig - ); - - const animationAliases = this.styledUtils?.aliases; - - const config = this.#extendedConfig; - - tokenizedAnimatedProps = tokenizeAnimationPropsFromConfig( - componentStyledObject, - config, - animationAliases - ); - - const tokenizedSxAnimationProps: any = tokenizeAnimationPropsFromConfig( - sx, - config, - animationAliases - ); - - const mergedAnimatedProps = deepMerge( - tokenizedAnimatedProps, - tokenizedSxAnimationProps - ); - - const resolvedAnimatedStyledWithStyledObject = this.inputMiddleWare( - mergedAnimatedProps, - false - ); - - let isState = false; - - Object.keys(restProps?.states ?? {}).forEach((state: any) => { - isState = restProps.states[state] ? true : false; - }); - const animatedProps = !isState - ? // @ts-ignore - resolvedAnimatedStyledWithStyledObject?.props - : {}; - - return ( - - ); - }); - - if (NewComponent) { - //@ts-ignore - NewComponent.styled = {}; - //@ts-ignore - NewComponent.styled.config = {}; - //@ts-ignore - NewComponent.styled.config = styledConfig; - - //@ts-ignore - NewComponent.isStyledComponent = Component?.isStyledComponent; - //@ts-ignore - NewComponent.isComposedComponent = Component?.isComposedComponent; - - NewComponent.displayName = 'StyledComponent'; - return NewComponent; - } - return null; - } - - wrapperComponentMiddleWare() { - const AnimatedPresenceComp = React.forwardRef( - ({ children, ...props }: any, ref?: any) => { - const clonedChildren: any = []; - const styledContext = useStyled(); - const CONFIG = useMemo( - () => ({ - ...styledContext.config, - propertyTokenMap, - }), - [styledContext.config] - ); - - this.#extendedConfig = CONFIG; - - React.Children.toArray(children).forEach((child: any) => { - if (child?.type?.displayName === 'StyledComponent') { - let tokenizedAnimatedProps: any = {}; - const animationAliases = this.styledUtils?.aliases; - - const componentStyledObject = child?.type?.styled?.config; - const { variantProps, restProps } = getVariantProps( - child?.props, - componentStyledObject - ); - - const config = CONFIG; - - if (child.type.styled.resolvedProps) { - tokenizedAnimatedProps = child?.type?.styled?.resolvedProps; - } else { - const variantStyledObject = resolveVariantAnimationProps( - variantProps, - componentStyledObject - ); - const componentStyledObjectWithVariants = deepMergeObjects( - componentStyledObject, - variantStyledObject - ); - tokenizedAnimatedProps = tokenizeAnimationPropsFromConfig( - componentStyledObjectWithVariants, - config, - animationAliases - ); - - child.type.styled.resolvedProps = tokenizedAnimatedProps; - } - - const tokenizedSxAnimationProps: any = - tokenizeAnimationPropsFromConfig( - child?.props?.sx, - config, - animationAliases - ); - - const mergedAnimatedProps = deepMergeObjects( - {}, - tokenizedSxAnimationProps, - tokenizedAnimatedProps - ); - - const clonedChild = React.cloneElement(child, { - exit: mergedAnimatedProps?.[':exit'], - ...restProps, - }); - clonedChildren.push(clonedChild); - } else { - clonedChildren.push(child); - } - }); - - return ( - - {clonedChildren} - - ); - } - ); - - AnimatedPresenceComp.displayName = `AnimatePresence`; - - return { - Component: AnimatedPresenceComp, - AnimatePresence: AnimatedPresenceComp, - }; - } -} diff --git a/packages/animation-resolver/.gitignore b/packages/animation-resolver/.gitignore new file mode 100644 index 000000000..3d3e2719a --- /dev/null +++ b/packages/animation-resolver/.gitignore @@ -0,0 +1,28 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +.pnp +.pnp.js + +# misc +.DS_Store +*.pem + +# build +dist +lib + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# turbo +.turbo diff --git a/packages/animation-resolver/.nvmrc b/packages/animation-resolver/.nvmrc new file mode 100644 index 000000000..5dbac1ed0 --- /dev/null +++ b/packages/animation-resolver/.nvmrc @@ -0,0 +1 @@ +v16.13.0 \ No newline at end of file diff --git a/packages/animation-resolver/CHANGELOG.md b/packages/animation-resolver/CHANGELOG.md new file mode 100644 index 000000000..41be139f9 --- /dev/null +++ b/packages/animation-resolver/CHANGELOG.md @@ -0,0 +1,17 @@ +# @gluestack-style/animation-plugin + +## 0.1.7 + +### Patch Changes + +- - Fixed transform array resoltion + +## 0.1.0 + +### Changes + +- Fix forward ref warning +- Fixed variant resolution +- Moved @gluestack-style/react to devDependency +- Add legend motion dependency +- Add variant support diff --git a/packages/animation-resolver/README.md b/packages/animation-resolver/README.md new file mode 100644 index 000000000..58e26e535 --- /dev/null +++ b/packages/animation-resolver/README.md @@ -0,0 +1,69 @@ +# @gluestack-style/animation-plugin + +## Installation + +To use `@gluestack-style/animation-plugin`, all you need to do is install the +`@gluestack-style/animation-plugin` package: + +```sh +$ yarn add @gluestack-style/animation-plugin + +# or + +$ npm i @gluestack-style/animation-plugin +``` + +## Usage + +You can initialize the Animation plugin by creating a new instance of the AnimationResolver class and providing it as an argument to the createStyled function. The `AnimationResolver` takes an optional `styledUtils` object that maps the styled utils object. Here's an example: + +```jsx +import { createStyled } from '@gluestack-style/react'; +import { AnimationResolver } from '@gluestack-style/animation-plugin'; + +const styled = createStyled([ + new AnimationResolver({ + aliases: { + ':initial': 'initial', + ':animate': 'animate', + ':exit': 'exit', + }, + }), +]); +``` + +In this example, we are creating a new instance of the AnimationResolver class, passing an object with the 'aliases' property as an argument. The aliases object maps the aliases :initial, :animate, and :exit to their corresponding animation props. + +## Example of creating a styled component: + +Once the plugin is initialized, you can use the styled function to create styled components with animation props. Here's an example: + +```jsx +const Box = styled(Motion.View, { + ':initial': { opacity: 0 }, + ':animate': { opacity: 1 }, + ':exit': { opacity: 0 }, +}); +``` + +The final internal styled object that will be resolved is: + +```jsx +styledObject = { + 'props': { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + }, + exit: { + opacity: 0, + }, + } + }, +}; +``` + +More guides on how to get started are available +[here](https://style.gluestack.io/). diff --git a/packages/animation-resolver/babel.config.js b/packages/animation-resolver/babel.config.js new file mode 100644 index 000000000..fda985a22 --- /dev/null +++ b/packages/animation-resolver/babel.config.js @@ -0,0 +1,22 @@ +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: [ + process.env.NODE_ENV !== 'production' + ? [ + 'module-resolver', + { + alias: { + // For development, we want to alias the library to the source + ['@gluestack-style/react']: path.join( + __dirname, + '../react/src/index' + ), + }, + }, + ] + : ['transform-remove-console'], + ], + }; +}; diff --git a/packages/animation-plugin/package.json b/packages/animation-resolver/package.json similarity index 77% rename from packages/animation-plugin/package.json rename to packages/animation-resolver/package.json index df7c6d2d1..f8c3f7903 100644 --- a/packages/animation-plugin/package.json +++ b/packages/animation-resolver/package.json @@ -1,7 +1,7 @@ { - "name": "@gluestack-style/animation-plugin", - "version": "0.1.12", - "description": "A gluestack-style plugin for animation properties, utilizing animation libraries.", + "name": "@gluestack-style/animation-resolver", + "version": "0.0.1", + "description": "A gluestack-style plugin for resolving animation properties, utilizing animation libraries.", "keywords": [ "react", "native", @@ -21,11 +21,11 @@ "build": "bob build", "clean": "rm -rf lib" }, - "dependencies": { - "@legendapp/motion": "^2.2.0" + "peerDependencies": { + "@gluestack-style/react": ">=0.2.49" }, "devDependencies": { - "@gluestack-style/react": "^0.1.11", + "@gluestack-style/react": "^0.2.49", "@types/react": "^18.0.22", "@types/react-native": "^0.69.15", "babel-plugin-transform-remove-console": "^6.9.4", diff --git a/packages/animation-resolver/src/AnimatedComponents/index.tsx b/packages/animation-resolver/src/AnimatedComponents/index.tsx new file mode 100644 index 000000000..729ae9703 --- /dev/null +++ b/packages/animation-resolver/src/AnimatedComponents/index.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { useStyled } from '@gluestack-style/react'; +import type { + ImageProps, + PressableProps, + ViewProps, + TextProps, + ScrollViewProps, + FlatListProps, + SectionListProps, +} from 'react-native'; +const AnimatedText = ( + props: TextProps & { + animationComponentGluestack: true; + } +) => { + return ; +}; +const AnimatedView = ( + props: ViewProps & { + animationComponentGluestack: true; + } +) => { + return ; +}; +const AnimatedPressable = ( + props: PressableProps & { + animationComponentGluestack: true; + } +) => { + // @ts-ignore + return ; +}; +const AnimatedImage = ( + props: ImageProps & { + animationComponentGluestack: true; + } +) => { + // @ts-ignore + return ; +}; +const AnimatedScrollView = ( + props: ScrollViewProps & { animationComponentGluestack: true } +) => { + return ; +}; +const AnimatedSafeAreaView = (props: React.PropsWithChildren) => { + return ; +}; +const AnimatedFlatList = ( + props: FlatListProps & { animationComponentGluestack: true } +) => { + return ; +}; +const AnimatedSectionList = ( + props: SectionListProps & { animationComponentGluestack: true } +) => { + return ; +}; +const AnimatedAnimatePresence = React.forwardRef( + ({ ...props }: any, ref: any) => { + const ctx = useStyled(); + let animationDriverData = ctx.animationDriverData; + if (animationDriverData?.engine.AnimatePresence) { + return ( + + ); + } + return ; + } +); +AnimatedText.displayName = 'Gluestack-AnimatedResolver-AnimatedText'; +AnimatedView.displayName = 'Gluestack-AnimatedResolver-AnimatedView'; +AnimatedPressable.displayName = 'Gluestack-AnimatedResolver-AnimatedPressable'; +AnimatedImage.displayName = 'Gluestack-AnimatedResolver-AnimatedImage'; +AnimatedScrollView.displayName = + 'Gluestack-AnimatedResolver-AnimatedScrollView'; +AnimatedSafeAreaView.displayName = + 'Gluestack-AnimatedResolver-AnimatedSafeAreaView'; +AnimatedFlatList.displayName = 'Gluestack-AnimatedResolver-AnimatedFlatList'; +AnimatedSectionList.displayName = + 'Gluestack-AnimatedResolver-AnimatedSectionList'; +AnimatedAnimatePresence.displayName = + 'Gluestack-AnimatedResolver-AnimatedAnimatePresence'; + +export { + AnimatedText, + AnimatedView, + AnimatedPressable, + AnimatedImage, + AnimatedScrollView, + AnimatedSafeAreaView, + AnimatedFlatList, + AnimatedSectionList, + AnimatedAnimatePresence, +}; diff --git a/packages/animation-resolver/src/index.tsx b/packages/animation-resolver/src/index.tsx new file mode 100644 index 000000000..d5fe5f3a3 --- /dev/null +++ b/packages/animation-resolver/src/index.tsx @@ -0,0 +1,361 @@ +import React, { useEffect, useMemo } from 'react'; +import type { + // @ts-ignore + IAnimationDriverPlugin, + IStyledPlugin, +} from '@gluestack-style/react'; +import { useStyled } from '@gluestack-style/react'; +import { deepMerge, setObjectKeyValue, resolvedTokenization } from './utils'; +import { propertyTokenMap } from './propertyTokenMap'; + +function tokenizeAnimationPropsFromConfig( + props: any = {}, + config: any, + animationAliases: any, + path: any = [], + tokenizedAnimatedProps: any = {} +) { + for (const prop in props) { + if (Array.isArray(props[prop])) { + path.push(prop); + setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); + path.pop(); + } else if (animationAliases[prop]) { + path.push(prop); + const tokenizedValue = resolvedTokenization(props[prop], config); + setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); + path.pop(); + } else if (typeof props[prop] === 'object') { + path.push(prop); + const tokenizedValue = resolvedTokenization(props[prop], config); + setObjectKeyValue(tokenizedAnimatedProps, path, tokenizedValue); + // path.pop(); + tokenizeAnimationPropsFromConfig( + props[prop], + config, + animationAliases, + path, + tokenizedAnimatedProps + ); + path.pop(); + } else { + path.push(prop); + setObjectKeyValue(tokenizedAnimatedProps, path, props[prop]); + path.pop(); + } + } + + return tokenizedAnimatedProps; +} + +function getVariantProps(props: any, theme: any) { + const variantTypes = theme?.variants ? Object.keys(theme.variants) : []; + + const restProps = { ...props }; + + const variantProps: any = {}; + variantTypes?.forEach((variant) => { + if (props[variant]) { + variantProps[variant] = props[variant]; + // delete restProps[variant]; + } + }); + + return { + variantProps, + restProps, + }; +} + +function resolveVariantAnimationProps(variantProps: any, styledObject: any) { + let resolvedVariant = {}; + Object.keys(variantProps).forEach((variant) => { + const variantValue = variantProps[variant]; + const variantObject = styledObject?.variants?.[variant]?.[variantValue]; + + resolvedVariant = deepMerge(resolvedVariant, variantObject); + }); + + return resolvedVariant; +} + +export class AnimationResolver implements IStyledPlugin { + name: 'AnimationResolver'; + componentDriver: IAnimationDriverPlugin; + config = { + aliases: { + ':animate': 'animate', + ':initial': 'initial', + ':exit': 'exit', + ':initialProps': 'initialProps', + ':animateProps': 'animateProps', + ':transition': 'transition', + ':transformOrigin': 'transformOrigin', + ':whileTap': 'whileTap', + ':whileHover': 'whileHover', + ':onAnimationComplete': 'onAnimationComplete', + } as const, + tokens: {} as const, + animatedPropMap: {} as any, + }; + + AnimatePresenceComp = React.Fragment; + + register(config: any) { + if (this.config) { + if (config?.aliases) { + this.config.aliases = { + ...this.config?.aliases, + ...config?.aliases, + }; + } + + if (config?.tokens) { + this.config.tokens = { + ...this.config?.tokens, + ...config?.tokens, + }; + } + if (config?.animatedPropMap) { + this.config.animatedPropMap = { + ...this.config?.animatedPropMap, + ...config?.animatedPropMap, + }; + } + // @ts-ignore + this.config.ref = config?.ref; + } + } + + constructor(ComponentDriverClass: any, config: any = {}) { + // @ts-ignore + const componentDriver = new ComponentDriverClass(config); + this.name = 'AnimationResolver'; + this.componentDriver = componentDriver; + if (componentDriver.engine.AnimatePresence) { + this.AnimatePresenceComp = componentDriver.engine.AnimatePresence; + } + this.register(componentDriver.config); + } + + #childrenExitPropsMap: any = {}; + + #extendedConfig: any = {}; + + inputMiddleWare

( + styledObj = {}, + shouldUpdateConfig: any = true, + _?: boolean, + Component?: React.ComponentType + ): { + // @ts-ignore + [key in keyof typeof this.config.aliases]: P[(typeof this.config.aliases)[key]]; + } { + if ( + Component && + (Component.displayName?.startsWith( + 'Gluestack-AnimatedResolver-Animated' + ) || + // @ts-ignore + Component.isAnimatedComponent) + ) { + let AnimatedComponent = + this.componentDriver.engine[ + // @ts-ignore + Component.displayName?.replace( + 'Gluestack-AnimatedResolver-Animated', + '' + ) + ]; + + if (AnimatedComponent) { + AnimatedComponent.isAnimatedComponent = true; + } + if (!AnimatedComponent) { + AnimatedComponent = React.Fragment; + } + + // this.#childrenExitPropsMap = deepClone(styledObj); + const resolvedAnimatedProps = this.updateStyledObject( + styledObj, + shouldUpdateConfig + ); + + const resolvedStyledObjectWithAnimatedProps = deepMerge( + styledObj, + resolvedAnimatedProps + ); + + if (shouldUpdateConfig) { + // @ts-ignore + return [styledObj, shouldUpdateConfig, _, AnimatedComponent]; + } + + // @ts-ignore + return [ + resolvedStyledObjectWithAnimatedProps, + shouldUpdateConfig, + _, + AnimatedComponent, + ]; + } + // @ts-ignore + return [styledObj, shouldUpdateConfig, _, Component]; + } + + updateStyledObject( + styledObject: any = {}, + shouldUpdateConfig: boolean, + resolvedStyledObject: any = {}, + keyPath: string[] = [] + ) { + const aliases = this.config?.aliases; + const animatedPropMap = this.config?.animatedPropMap; + for (const prop in styledObject) { + if (typeof styledObject[prop] === 'object') { + keyPath.push(prop); + this.updateStyledObject( + styledObject[prop], + shouldUpdateConfig, + resolvedStyledObject, + keyPath + ); + keyPath.pop(); + } + + // @ts-ignore + if (aliases && aliases?.[prop]) { + if (shouldUpdateConfig) { + // this.#childrenExitPropsMap[prop] = styledObject[prop]; + setObjectKeyValue( + this.#childrenExitPropsMap, + [...keyPath, prop], + styledObject[prop] + ); + } + const value = styledObject[prop]; + // @ts-ignore + keyPath.push('props', aliases[prop]); + setObjectKeyValue(resolvedStyledObject, keyPath, value); + keyPath.pop(); + keyPath.pop(); + delete styledObject[prop]; + } + + if (animatedPropMap && animatedPropMap[prop]) { + this.renameObjectKey(styledObject, prop, animatedPropMap[prop]); + } + } + return resolvedStyledObject; + } + + renameObjectKey(obj: any, from: string, to: string) { + obj[to] = obj[from]; + delete obj[from]; + return obj; + } + + componentMiddleWare({ Component, ExtendedConfig }: any) { + if (Component && Component.isAnimatedComponent) { + const styledConfig = this.#childrenExitPropsMap; + + this.#childrenExitPropsMap = {}; + + const NewComponent = React.forwardRef((props: any, ref?: any) => { + const { sx, ...rest } = props; + + const styledContext = useStyled(); + useEffect(() => { + if (!styledContext.animationDriverData) { + styledContext.setAnimationDriverData(this.componentDriver); + } + }, [styledContext]); + const CONFIG = useMemo( + () => ({ + ...styledContext.config, + propertyTokenMap, + }), + [styledContext.config] + ); + this.#extendedConfig = CONFIG; + if (ExtendedConfig) { + this.#extendedConfig = deepMerge(CONFIG, ExtendedConfig); + } + + let tokenizedAnimatedProps: any = {}; + const { variantProps, restProps } = getVariantProps(rest, styledConfig); + const variantStyledObject = resolveVariantAnimationProps( + variantProps, + styledConfig + ); + const componentStyledObject = deepMerge( + variantStyledObject, + styledConfig + ); + + const animationAliases = this.config?.aliases; + + const config = this.#extendedConfig; + + tokenizedAnimatedProps = tokenizeAnimationPropsFromConfig( + componentStyledObject, + config, + animationAliases + ); + + const tokenizedSxAnimationProps: any = tokenizeAnimationPropsFromConfig( + sx, + config, + animationAliases + ); + + const mergedAnimatedProps = deepMerge( + tokenizedAnimatedProps, + tokenizedSxAnimationProps + ); + + // @ts-ignore + const [resolvedAnimatedStyledWithStyledObject, , ,] = + this.inputMiddleWare(mergedAnimatedProps, false, false, Component); + let isState = false; + + Object.keys(restProps?.states ?? {}).forEach((state: any) => { + isState = restProps.states[state] ? true : false; + }); + const animatedProps = !isState + ? // @ts-ignore + resolvedAnimatedStyledWithStyledObject?.props + : {}; + return ( + + ); + }); + + if (NewComponent) { + //@ts-ignore + NewComponent.styled = {}; + //@ts-ignore + NewComponent.styled.config = {}; + //@ts-ignore + NewComponent.styled.config = styledConfig; + + //@ts-ignore + NewComponent.isStyledComponent = Component?.isStyledComponent; + //@ts-ignore + NewComponent.isComposedComponent = Component?.isComposedComponent; + + NewComponent.displayName = 'StyledComponent'; + return NewComponent; + } + } else { + return Component; + } + } +} + +export * from './AnimatedComponents'; diff --git a/packages/animation-resolver/src/propertyTokenMap.ts b/packages/animation-resolver/src/propertyTokenMap.ts new file mode 100644 index 000000000..0913ca47d --- /dev/null +++ b/packages/animation-resolver/src/propertyTokenMap.ts @@ -0,0 +1,183 @@ +const borderStyles = 'borderStyles'; +const borderWidths = 'borderWidths'; +const colors = 'colors'; +const mediaQueries = 'mediaQueries'; +const opacity = 'opacity'; +const fonts = 'fonts'; +const fontSizes = 'fontSizes'; +const fontWeights = 'fontWeights'; +const letterSpacings = 'letterSpacings'; +const lineHeights = 'lineHeights'; +const radii = 'radii'; +const shadows = 'shadows'; +// const sizes = 'sizes'; +const space = 'space'; +const transitions = 'transitions'; +const zIndices = 'zIndices'; +export const propertyTokenMap = { + gap: space, + gridGap: space, + columnGap: space, + gridColumnGap: space, + rowGap: space, + gridRowGap: space, + inset: space, + insetBlock: space, + insetBlockEnd: space, + insetBlockStart: space, + insetInline: space, + insetInlineEnd: space, + insetInlineStart: space, + margin: space, + marginTop: space, + marginRight: space, + marginBottom: space, + marginLeft: space, + marginBlock: space, + marginBlockEnd: space, + marginBlockStart: space, + marginInline: space, + marginInlineEnd: space, + marginInlineStart: space, + + marginHorizontal: space, + marginVertical: space, + padding: space, + paddingTop: space, + paddingRight: space, + paddingBottom: space, + paddingLeft: space, + + paddingBlock: space, + paddingBlockEnd: space, + paddingBlockStart: space, + paddingInline: space, + paddingInlineEnd: space, + paddingInlineStart: space, + + paddingHorizontal: space, + paddingVertical: space, + paddingStart: space, + paddingEnd: space, + + top: space, + right: space, + bottom: space, + left: space, + scrollMargin: space, + scrollMarginTop: space, + scrollMarginRight: space, + scrollMarginBottom: space, + scrollMarginLeft: space, + scrollMarginX: space, + scrollMarginY: space, + scrollMarginBlock: space, + scrollMarginBlockEnd: space, + scrollMarginBlockStart: space, + scrollMarginInline: space, + scrollMarginInlineEnd: space, + scrollMarginInlineStart: space, + scrollPadding: space, + scrollPaddingTop: space, + scrollPaddingRight: space, + scrollPaddingBottom: space, + scrollPaddingLeft: space, + scrollPaddingX: space, + scrollPaddingY: space, + scrollPaddingBlock: space, + scrollPaddingBlockEnd: space, + scrollPaddingBlockStart: space, + scrollPaddingInline: space, + scrollPaddingInlineEnd: space, + scrollPaddingInlineStart: space, + // shadowOffset: space, + shadowRadius: space, + elevation: space, + + fontSize: fontSizes, + + background: colors, + backgroundColor: colors, + backgroundImage: colors, + borderImage: colors, + border: colors, + borderBlock: colors, + borderBlockEnd: colors, + borderBlockStart: colors, + borderBottom: colors, + borderBottomColor: colors, + borderColor: colors, + borderInline: colors, + borderInlineEnd: colors, + borderInlineStart: colors, + borderLeft: colors, + borderLeftColor: colors, + borderRight: colors, + borderRightColor: colors, + borderTop: colors, + borderTopColor: colors, + caretColor: colors, + color: colors, + columnRuleColor: colors, + fill: colors, + outline: colors, + outlineColor: colors, + stroke: colors, + textDecorationColor: colors, + shadowColor: colors, + + shadowOpacity: opacity, + + shadow: shadows, + // Media Query + condition: mediaQueries, + + fontFamily: fonts, + + fontWeight: fontWeights, + + lineHeight: lineHeights, + + letterSpacing: letterSpacings, + + blockSize: space, + minBlockSize: space, + maxBlockSize: space, + inlineSize: space, + minInlineSize: space, + maxInlineSize: space, + width: space, + minWidth: space, + maxWidth: space, + height: space, + minHeight: space, + maxHeight: space, + flexBasis: space, + gridTemplateColumns: space, + gridTemplateRows: space, + + borderWidth: borderWidths, + borderTopWidth: borderWidths, + borderRightWidth: borderWidths, + borderBottomWidth: borderWidths, + borderLeftWidth: borderWidths, + + borderStyle: borderStyles, + borderTopStyle: borderStyles, + borderRightStyle: borderStyles, + borderBottomStyle: borderStyles, + borderLeftStyle: borderStyles, + + borderRadius: radii, + borderTopLeftRadius: radii, + borderTopRightRadius: radii, + borderBottomRightRadius: radii, + borderBottomLeftRadius: radii, + + boxShadow: colors, + textShadow: shadows, + + transition: transitions, + + zIndex: zIndices, +} as const; diff --git a/packages/animation-resolver/src/utils.ts b/packages/animation-resolver/src/utils.ts new file mode 100644 index 000000000..1c4be87d1 --- /dev/null +++ b/packages/animation-resolver/src/utils.ts @@ -0,0 +1,231 @@ +export const deepClone = (obj: any) => JSON.parse(JSON.stringify(obj)); + +export const deepMerge = (target: any = {}, source: any) => { + for (const key in source) { + if (source.hasOwnProperty(key)) { + if (typeof target[key] === 'object' && typeof source[key] === 'object') { + deepMerge(target[key], source[key]); + } else { + target[key] = source[key]; + } + } + } + return target; +}; + +export const setObjectKeyValue = (obj: any, keys: any, value: any) => { + let current = obj; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (i === keys.length - 1) { + // we've reached the desired key, so update its value + current[key] = value; + } else { + // we're still traversing the object, so create the key if it doesn't exist + if (!current[key]) { + current[key] = {}; + } + current = current[key]; + } + } + return obj; +}; + +export function deepMergeObjects(...objects: any) { + const isObject = (obj: any) => obj && typeof obj === 'object'; + + return objects.reduce((prev: any, obj: any) => { + if (isObject(prev) && isObject(obj)) { + Object.keys(obj).forEach((key) => { + if (isObject(obj[key])) { + if (!prev[key] || !isObject(prev[key])) { + prev[key] = {}; + } + prev[key] = deepMerge(prev[key], obj[key]); + } else { + prev[key] = obj[key]; + } + }); + } + return prev; + }, {}); +} + +export function resolvedTokenization(props: any, config: any) { + const aliasedResolvedProps = resolveAliasesFromConfig(config, props); + const newProps = resolveTokensFromConfig(config, aliasedResolvedProps); + return newProps; +} + +export function resolveAliasesFromConfig(config: any, props: any) { + const aliasResolvedProps: any = {}; + + Object.keys(props).map((key) => { + if (config?.aliases?.[key]) { + aliasResolvedProps[config.aliases?.[key]] = props[key]; + } else { + aliasResolvedProps[key] = props[key]; + } + }); + return aliasResolvedProps; +} + +export function resolveTokensFromConfig(config: any, props: any) { + let newProps: any = {}; + + Object.keys(props).map((prop: any) => { + const value = props[prop]; + + newProps[prop] = getResolvedTokenValueFromConfig( + config, + props, + prop, + value + ); + }); + // console.log('&&&&&', newProps); + + return newProps; +} + +export function getResolvedTokenValueFromConfig( + config: any, + _props: any, + prop: any, + value: any +) { + let resolvedTokenValue = getTokenFromConfig(config, prop, value); + + // Special case for token ends with em on mobile + // This will work for lineHeight and letterSpacing + // console.log('hello from token ends with em on mobile', resolvedTokenValue); + // if ( + // typeof resolvedTokenValue === 'string' && + // resolvedTokenValue.endsWith('em') && + // Platform.OS !== 'web' + // ) { + // const fontSize = getTokenFromConfig(config, 'fontSize', props?.fontSize); + // resolvedTokenValue = + // parseFloat(resolvedTokenValue) * parseFloat(fontSize ?? BASE_FONT_SIZE); + // } + + return resolvedTokenValue; +} + +export const getTokenFromConfig = (config: any, prop: any, value: any) => { + const aliasTokenType = config.propertyTokenMap[prop]; + + // const tokenScale = config?.tokens?.[aliasTokenType]; + let token; + + // resolveStringToken(value, config, config.propertyTokenMap); + if (typeof value === 'string' && value.includes('$')) { + if (config.propertyResolver?.[prop]) { + let transformer = config.propertyResolver?.[prop]; + token = transformer(value, (value1: any, scale = aliasTokenType) => + resolveStringToken(value1, config, config.propertyTokenMap, prop, scale) + ); + } else { + token = resolveStringToken(value, config, config.propertyTokenMap, prop); + } + } else { + if (config.propertyResolver?.[prop]) { + let transformer = config.propertyResolver?.[prop]; + token = transformer(value, (value: any, scale = aliasTokenType) => { + if (typeof value === 'string' && value.includes('$')) { + return resolveStringToken( + value, + config, + config.propertyTokenMap, + prop, + scale + ); + } else { + return value; + } + }); + } else { + token = value; + } + // console.log(token, typeof token, prop, '******'); + } + + return token; +}; + +function isNumeric(str: string) { + return typeof str === 'number' ? true : false; + // return /^[-+]?[0-9]*\.?[0-9]+$/.test(str); +} +export function resolveStringToken( + string: string, + config: any, + tokenScaleMap: any, + propName: any, + scale?: any +) { + let typeofResult = 'string'; + const token_scale = scale ?? tokenScaleMap[propName]; + + const splitTokenBySpace = string.split(' '); + + const result: any = splitTokenBySpace.map((currentToken) => { + let splitCurrentToken = currentToken.split('$'); + + if (currentToken.startsWith('$')) { + splitCurrentToken = splitCurrentToken.slice(1); + } + + if (splitCurrentToken.length > 1) { + const tokenValue = getObjectProperty(config.tokens, splitCurrentToken); + typeofResult = typeof tokenValue; + return tokenValue; + } else { + if (tokenScaleMap[propName]) { + if (!config || !config.tokens) { + throw new Error( + 'You cannot use tokens without wrapping the component with StyledProvider. Please wrap the component with a StyledProvider and pass theme config.' + ); + } + if ( + config?.tokens[token_scale] && + config?.tokens[token_scale].hasOwnProperty(splitCurrentToken[0]) + ) { + const tokenValue = config?.tokens[token_scale][splitCurrentToken[0]]; + typeofResult = typeof tokenValue; + + if (typeof tokenValue !== 'undefined' && tokenValue !== null) { + return tokenValue; + } else { + return ''; + } + } + } + return splitCurrentToken[splitCurrentToken.length - 1]; + } + }); + + let finalResult = result; + + if (finalResult === '') { + return undefined; + } else { + finalResult = result.join(' '); + + if (isNumeric(finalResult) || typeofResult === 'number') { + return parseFloat(finalResult); + } else { + return finalResult; + } + } +} + +export const getObjectProperty = (object: any, keyPath: any) => { + if (!Array.isArray(keyPath)) { + keyPath = [keyPath]; + } + return keyPath.reduce( + (baseObj: any, key: any) => baseObj && baseObj[key], + object + ); +}; diff --git a/packages/animation-resolver/tsconfig.json b/packages/animation-resolver/tsconfig.json new file mode 100644 index 000000000..7ebd787f0 --- /dev/null +++ b/packages/animation-resolver/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": ["./src"], + "exclude": ["node_modules", "example"], + "path": { + "@gluestack-style/react": ["../react/src"] + }, + "compilerOptions": { + "emitDeclarationOnly": true, + "noEmit": false, + "baseUrl": ".", + "declaration": true, + "allowUnreachableCode": false, + "allowUnusedLabels": true, + "esModuleInterop": true, + "importsNotUsedAsValues": "error", + "forceConsistentCasingInFileNames": true, + "jsx": "react", + "lib": ["esnext", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitUseStrict": false, + "noStrictGenericChecks": false, + "noUnusedLocals": false, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "esnext" + } +} diff --git a/packages/react/src/StyledProvider.tsx b/packages/react/src/StyledProvider.tsx index 91fd4d689..2a07ae42e 100644 --- a/packages/react/src/StyledProvider.tsx +++ b/packages/react/src/StyledProvider.tsx @@ -85,12 +85,17 @@ export const StyledProvider: React.FC<{ setCurrentColorMode(currentColorMode); } + const [animationDriverData, setAnimationDriverData] = React.useState(); const globalStyleMap = config?.globalStyle && createGlobalStyles(config.globalStyle); - const contextValue = React.useMemo(() => { - return { config: currentConfig, globalStyle: globalStyleMap }; - }, [currentConfig, globalStyleMap]); + return { + config: currentConfig, + globalStyle: globalStyleMap, + animationDriverData, + setAnimationDriverData, + }; + }, [currentConfig, globalStyleMap, animationDriverData]); return ( diff --git a/packages/react/src/createConfig.ts b/packages/react/src/createConfig.ts index 5aad9322b..07b66ddde 100644 --- a/packages/react/src/createConfig.ts +++ b/packages/react/src/createConfig.ts @@ -6,12 +6,14 @@ import { stableHash } from './stableHash'; import { propertyTokenMap } from './propertyTokenMap'; import { updateOrderUnResolvedMap } from './updateOrderUnResolvedMap'; -var globalPluginStore: any = []; - -function setGlobalPluginStore(plugins: Array) { - globalPluginStore.push(...plugins); +var globalPluginStore: never[] = []; +function setGlobalPluginStore(plugins: any) { + if (plugins) { + // @ts-ignore + globalPluginStore.push(...plugins); + } + return getGlobalPluginStore(); } - function getGlobalPluginStore() { return globalPluginStore; } @@ -25,7 +27,8 @@ export const createConfig = < //@ts-ignore T['tokens'], T['aliases'], - T['globalStyle'] + T['globalStyle'], + T['plugins'] > >( config: @@ -34,13 +37,14 @@ export const createConfig = < //@ts-ignore T['tokens'], T['aliases'], - T['globalStyle'] + T['globalStyle'], + T['plugins'] > ): T => { if (config.plugins) { - setGlobalPluginStore(config.plugins); + config.plugins = setGlobalPluginStore(config.plugins); } - delete config.plugins; + // delete config.plugins; if ( !config.components && diff --git a/packages/react/src/createStyled.ts b/packages/react/src/createStyled.ts index 7015d82b0..0dcd72cd3 100644 --- a/packages/react/src/createStyled.ts +++ b/packages/react/src/createStyled.ts @@ -1,19 +1,6 @@ import { styled } from './styled'; import type { IComponentStyleConfig, ITheme } from './types'; -export interface IStyledPlugin { - styledUtils?: IStyled; - register(styledUtils: IStyled): void; - inputMiddleWare(styledObj: any): void; - componentMiddleWare?(props: any): void; -} - -export class IStyled { - aliases?: any; - tokens?: any; - ref?: any; -} - export const createStyled = (plugins: any) => { let styledComponent = ( Component: React.ComponentType

, diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 38246bd3e..e1a6f4c6b 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -70,19 +70,22 @@ export type { Aliases, AliasesProps, ICustomConfig, + IStyledPlugin, + IStyled, + IAnimationDriverPlugin, GSConfig, } from './types'; export { createStyled } from './createStyled'; -export type { IStyledPlugin, IStyled } from './createStyled'; + export { createGlobalStylesWeb } from './createGlobalStylesWeb'; // export { styled }; // export { flush } from './utils/css-injector'; export { AsForwarder } from './AsForwarder'; -export { AddCssTokenVariables, FontResolver } from './plugins'; +export * from './plugins'; export { INTERNAL_updateCSSStyleInOrderedResolved } from './updateCSSStyleInOrderedResolved'; -export { createConfig } from './createConfig'; +export { createConfig, getInstalledPlugins } from './createConfig'; export * from './core'; export * from './hooks'; diff --git a/packages/react/src/plugins/css-variables.tsx b/packages/react/src/plugins/css-variables.tsx index b3a02520f..a10d5a012 100644 --- a/packages/react/src/plugins/css-variables.tsx +++ b/packages/react/src/plugins/css-variables.tsx @@ -1,4 +1,4 @@ -import type { IStyled, IStyledPlugin } from '../createStyled'; +import type { IStyled, IStyledPlugin } from '../types'; import { deepMerge } from '../utils'; import { injectGlobalCss } from '../utils/css-injector'; import React, { useMemo } from 'react'; diff --git a/packages/react/src/plugins/font-resolver.tsx b/packages/react/src/plugins/font-resolver.tsx index 8ded2b16a..8b5b19a65 100644 --- a/packages/react/src/plugins/font-resolver.tsx +++ b/packages/react/src/plugins/font-resolver.tsx @@ -1,5 +1,5 @@ import React, { useMemo } from 'react'; -import type { IStyled, IStyledPlugin } from '../createStyled'; +import type { IStyled, IStyledPlugin } from '../types'; import { useStyled } from '../StyledProvider'; import { propertyTokenMap } from '../propertyTokenMap'; import { deepMerge, deepMergeObjects, setObjectKeyValue } from '../utils'; diff --git a/packages/react/src/styled.tsx b/packages/react/src/styled.tsx index 889bd33c5..6168021a1 100644 --- a/packages/react/src/styled.tsx +++ b/packages/react/src/styled.tsx @@ -990,12 +990,15 @@ export function verboseStyled( // styledIds: BUILD_TIME_STYLE_IDS = [], // sxHash: BUILD_TIME_sxHash = '', ...componentProps - }: Omit & - Partial> & - Partial> & { - as?: any; - children?: any; - }, + }: Omit< + Omit & + Partial> & + Partial> & { + as?: any; + children?: any; + }, + 'animationComponentGluestack' + >, ref: React.ForwardedRef

) => { const isClient = React.useRef(false); @@ -1892,11 +1895,11 @@ export function verboseStyled( return StyledComp; } -export function styled( +export function styled( Component: React.ComponentType

, theme: ITheme, componentStyleConfig?: IComponentStyleConfig, - ExtendedConfig?: ExtendedConfigType, + ExtendedConfig?: ExtendedConfigType, BUILD_TIME_PARAMS?: { orderedResolved: OrderedSXResolved; verbosedStyleIds: { @@ -1912,8 +1915,8 @@ export function styled( // process.env.NODE_ENV === 'development' && DEBUG_TAG ? false : false; let styledObj = theme; - // @ts-ignore - let plugins: PluginType = [...getInstalledPlugins()]; + let plugins = [...getInstalledPlugins()]; + if (ExtendedConfig?.plugins) { // @ts-ignore plugins = [...plugins, ...ExtendedConfig?.plugins]; @@ -1921,7 +1924,12 @@ export function styled( for (const pluginName in plugins) { // @ts-ignore - styledObj = plugins[pluginName]?.inputMiddleWare

(styledObj, true, true); + [styledObj, , , Component] = plugins[pluginName]?.inputMiddleWare

( + styledObj, + true, + true, + Component + ); } theme = styledObj; const sxConvertedObject = convertStyledToStyledVerbosed(theme); @@ -1933,6 +1941,10 @@ export function styled( ExtendedConfig, BUILD_TIME_PARAMS ); + + // @ts-ignore + StyledComponent.isAnimatedComponent = Component.isAnimatedComponent; + // @ts-ignore plugins?.reverse(); for (const pluginName in plugins) { @@ -1947,22 +1959,21 @@ export function styled( }); } } - - for (const pluginName in plugins) { - const compWrapper = - // @ts-ignore - typeof plugins[pluginName].wrapperComponentMiddleWare === 'function' - ? // @ts-ignore - plugins[pluginName].wrapperComponentMiddleWare() - : null; - - if (compWrapper) { - for (const key of Object.keys(compWrapper)) { - // @ts-ignore - StyledComponent[key] = compWrapper[key]; - } - } - } + // for (const pluginName in plugins) { + // const compWrapper = + // // @ts-ignore + // typeof plugins[pluginName].wrapperComponentMiddleWare === 'function' + // ? // @ts-ignore + // plugins[pluginName].wrapperComponentMiddleWare() + // : null; + + // if (compWrapper) { + // for (const key of Object.keys(compWrapper)) { + // // @ts-ignore + // StyledComponent[key] = compWrapper[key]; + // } + // } + // } return StyledComponent; } diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 72a55e834..57ec92d03 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -33,6 +33,29 @@ export type COLORMODES = 'dark' | 'light'; /*************************** CORE TYPES *************************************************/ +export interface IStyledPlugin { + config?: IStyled; + register(styledUtils: IStyled): void; + inputMiddleWare(styledObj: any): void; + componentMiddleWare?(props: any): void; +} +export interface IAnimationDriverPlugin { + config?: IStyled; + register(styledUtils: IStyled): void; + engine: any; +} + +export class IAnimationResolver { + aliases?: any; + tokens?: any; + ref?: any; +} +export class IStyled { + aliases?: any; + tokens?: any; + ref?: any; +} + export interface Tokens { colors?: { [key: GenericKey]: Record & {} }; sizes?: { [key: GenericKey]: Record & {} }; @@ -53,6 +76,7 @@ export type AliasesType = { [key: string]: keyof RNStyledProps; }; +export type GlobalPluginType = unknown; export type GenericAliases = {}; export type GenericGlobalStyle = { // variants: {}; @@ -78,12 +102,13 @@ export type ThemeStyles = Partial<{ export type GlueStackConfig< IToken extends Tokens, IGlobalAliases, - IGlobalStyle + IGlobalStyle, + PluginType = [] > = { tokens: IToken; aliases: IGlobalAliases; globalStyle?: GlobalStyles; - plugins?: Array; + plugins?: PluginType; themes?: ThemeStyles; components?: { [key: string]: { @@ -102,35 +127,47 @@ export type ComponentsThemeType = { export type InferConfig = Conf extends GlueStackConfig< infer A, infer C, - infer D + infer D, + infer B > - ? GlueStackConfig + ? GlueStackConfig : any; export type CreateGenericConfig = GlueStackConfig< Tokens, GenericAliases, - GenericGlobalStyle + GenericGlobalStyle, + GlobalPluginType >; // All Aliases export type Aliases = GSConfig['aliases']; +export type Plugins = GSConfig['plugins']; export type Components = GSConfig['components']; export type IMediaQueries = keyof GSConfig['tokens']['mediaQueries']; export type SxStyleProps< GenericComponentStyles, Variants, - GenericComponentProps + GenericComponentProps, + PluginType > = { sx?: Partial< - SxProps & { + SxProps< + GenericComponentStyles, + Variants, + GenericComponentProps, + '', + '', + PluginType + > & { [Key in `@${IMediaQueries}`]?: SxProps< GenericComponentStyles, Variants, GenericComponentProps, '', - Key + Key, + PluginType >; } >; @@ -164,10 +201,10 @@ type PropsResolveType = { props?: Partial; }; type PropertyResolverType = PropsResolveType & ResolverType; -export type ExtendedConfigType = { +export type ExtendedConfigType = { propertyTokenMap?: PropertyTokenMapType; propertyResolver?: PropertyResolverType; - plugins?: T; + plugins?: Array; }; /*********************** GLOBAL STYLE TYPES ****************************************/ @@ -263,33 +300,45 @@ export type GlobalStyles = GlobalVariantSx< /*********************** USER THEME / SX TYPES ****************************************/ export type ITheme = Partial< - //@ts-ignore - StyledThemeProps + StyledThemeProps< + Variants, + 'style' extends keyof P ? P['style'] : {}, + P, + 'animationComponentGluestack' extends keyof P + ? P['animationComponentGluestack'] extends true + ? Plugins + : [] + : [] + > >; export type StyledThemeProps< Variants, GenericComponentStyles, - GenericComponentProps + GenericComponentProps, + PluginTypes > = SxProps< GenericComponentStyles, Variants & GlobalVariants, GenericComponentProps, '', - '' + '', + PluginTypes > & { [Key in `@${IMediaQueries}`]: SxProps< GenericComponentStyles, Variants, GenericComponentProps, '', - Key + Key, + PluginTypes >; } & { variants: VariantType< Variants, GenericComponentStyles, - GenericComponentProps + GenericComponentProps, + PluginTypes >; // sizes?: SizeTypeNew; compoundVariants?: Array< @@ -297,10 +346,20 @@ export type StyledThemeProps< >; defaultProps?: { [Key in keyof MergeNested< - VariantType, + VariantType< + Variants, + GenericComponentStyles, + GenericComponentProps, + PluginTypes + >, GlobalVariants >]?: keyof MergeNested< - VariantType, + VariantType< + Variants, + GenericComponentStyles, + GenericComponentProps, + PluginTypes + >, GlobalVariants >[Key]; } & { [key: string]: any }; @@ -315,7 +374,8 @@ type PassingPropsType< GenericComponentStyles, Variants, GenericComponentProps, - MediaQuery + MediaQuery, + PluginType > = MediaQuery extends '' ? { props?: Partial< @@ -328,7 +388,8 @@ type PassingPropsType< VariantType< Variants, GenericComponentStyles, - GenericComponentProps + GenericComponentProps, + PluginType >, GlobalVariants >]?: @@ -336,7 +397,8 @@ type PassingPropsType< VariantType< Variants, GenericComponentStyles, - GenericComponentProps + GenericComponentProps, + PluginType >, GlobalVariants >[Key]; @@ -345,13 +407,22 @@ type PassingPropsType< } : {}; -// PluginPropsType< -// PluginType, -// GenericComponentProps, -// GenericComponentStyles, -// PLATFORM -// > - +type AnimatedPropsType = { + opacity: number | string; + x: number | string | {}; + y: number | string | {}; + scale: any; + scaleX: any; + scaleY: any; + skewX: any; + skewY: any; + perspective: any; + rotate: number; + rotateY: number; + rotateZ: number; + matrix: any; +}; +// componentDriver // eslint-disable-next-line @typescript-eslint/no-unused-vars type PluginPropsType< PluginType, @@ -362,26 +433,9 @@ type PluginPropsType< [key in keyof UnionToIntersection< // @ts-ignore ReturnType - >]: Partial< - UnionToIntersection< - // @ts-ignore - ReturnType - >[key] extends keyof GenericComponentProps - ? StylePropsType & - GenericComponentProps[UnionToIntersection< - // @ts-ignore - ReturnType - >[key]] - : UnionToIntersection< - // @ts-ignore - ReturnType - >[key] extends keyof GenericComponentStyles - ? GenericComponentStyles[UnionToIntersection< - // @ts-ignore - ReturnType - >[key]] - : any - >; + >]: Partial & + Partial> & + Partial; }; export type SxProps< @@ -389,82 +443,108 @@ export type SxProps< Variants = unknown, GenericComponentProps = unknown, PLATFORM = '', - MediaQuery = '' -> = Partial< - StylePropsType & - PassingPropsType< - GenericComponentStyles, - Variants, - GenericComponentProps, - MediaQuery + MediaQuery = '', + PluginType = [] +> = + | Partial< + StylePropsType & + PassingPropsType< + GenericComponentStyles, + Variants, + GenericComponentProps, + MediaQuery, + PluginType + > > -> & { - [Key in `_${COLORMODES}`]?: SxProps< - GenericComponentStyles, - Variants, - GenericComponentProps, - PLATFORM, - MediaQuery - >; -} & { - [Key in `:${IState}`]?: SxProps< - GenericComponentStyles, - Variants, - GenericComponentProps, - PLATFORM, - MediaQuery - >; -} & { - [Key in `_${PLATFORMS}`]?: SxProps< - GenericComponentStyles, - Variants, - GenericComponentProps, - Key, - MediaQuery - > & - PassingPropsType< - GenericComponentStyles, - Variants, - GenericComponentProps, - MediaQuery - > & - Partial<{ - [key: string]: any; - }>; -} & { - [Key in `_${string}`]?: SxProps< - RNStyledProps, - {}, - GenericComponentProps, - PLATFORM, - MediaQuery - > & - PassingPropsType< - GenericComponentStyles, - {}, - GenericComponentProps, - MediaQuery - > & - Partial<{ - [key: string]: any; - }>; -}; + | (Partial< + PluginPropsType< + PluginType, + GenericComponentProps, + GenericComponentStyles, + PLATFORM + > + > & { + [Key in `_${COLORMODES}`]?: SxProps< + GenericComponentStyles, + Variants, + GenericComponentProps, + PLATFORM, + MediaQuery, + PluginType + >; + } & { + [Key in `:${IState}`]?: SxProps< + GenericComponentStyles, + Variants, + GenericComponentProps, + PLATFORM, + MediaQuery, + PluginType + >; + } & { + [Key in `_${PLATFORMS}`]?: SxProps< + GenericComponentStyles, + Variants, + GenericComponentProps, + Key, + MediaQuery, + PluginType + > & + PassingPropsType< + GenericComponentStyles, + Variants, + GenericComponentProps, + MediaQuery, + PluginType + > & + Partial<{ + [key: string]: any; + }>; + } & { + [Key in `_${string}`]?: SxProps< + RNStyledProps, + {}, + GenericComponentProps, + PLATFORM, + MediaQuery, + PluginType + > & + PassingPropsType< + GenericComponentStyles, + {}, + GenericComponentProps, + MediaQuery, + PluginType + > & + Partial<{ + [key: string]: any; + }>; + }); export type VariantType< Variants, GenericComponentStyles, - GenericComponentProps + GenericComponentProps, + PluginTypes > = | { [Key1 in keyof Variants]: { [Key in keyof Variants[Key1]]: Partial< - SxProps & { + SxProps< + GenericComponentStyles, + Variants, + GenericComponentProps, + '', + '', + PluginTypes + > & { [K in `@${IMediaQueries}`]?: SxProps< GenericComponentStyles, Variants, GenericComponentProps, '', - K + K, + PluginTypes >; } >; @@ -657,7 +737,16 @@ export interface GSConfig /********************* COMPONENT PROPS TYPE *****************************************/ export type ComponentProps = - SxStyleProps & { + SxStyleProps< + GenericComponentStyles, + Variants, + P, + 'animationComponentGluestack' extends keyof P + ? P['animationComponentGluestack'] extends true + ? Plugins + : [] + : [] + > & { states?: { [K in IState]?: boolean; }; diff --git a/yarn.lock b/yarn.lock index f186a0857..37e42ba1e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -187,6 +187,21 @@ "@babel/helper-split-export-declaration" "^7.22.6" semver "^6.3.1" +"@babel/helper-create-class-features-plugin@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz#97a61b385e57fe458496fad19f8e63b63c867de4" + integrity sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz#9d8e61a8d9366fe66198f57c40565663de0825f6" @@ -226,6 +241,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-function-name@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" @@ -241,6 +261,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-member-expression-to-functions@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz#b95a144896f6d491ca7863576f820f3628818621" + integrity sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-member-expression-to-functions@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2" @@ -255,6 +282,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9", "@babel/helper-module-transforms@^7.9.0": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129" @@ -266,6 +300,17 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.5" +"@babel/helper-module-transforms@^7.22.15": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz#da9edc14794babbe7386df438f3768067132f59e" + integrity sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -327,11 +372,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-validator-identifier@^7.22.19", "@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== + "@babel/helper-validator-option@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" @@ -879,6 +934,15 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" +"@babel/plugin-transform-modules-commonjs@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz#b11810117ed4ee7691b29bd29fd9f3f98276034f" + integrity sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg== + dependencies: + "@babel/helper-module-transforms" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + "@babel/plugin-transform-modules-systemjs@^7.22.5": version "7.22.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz#3386be5875d316493b517207e8f1931d93154bb1" @@ -928,6 +992,13 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-transform-object-assign@^7.16.7": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.22.5.tgz#290c1b9555dcea48bb2c29ad94237777600d04f9" + integrity sha512-iDhx9ARkXq4vhZ2CYOSnQXkmxkDgosLi3J8Z17mKz7LyzthtkdVchLD7WZ3aXeCuvJDOW3+1I5TpJmwIbF9MKQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-transform-object-rest-spread@^7.22.5": version "7.22.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.11.tgz#dbbb06ce783cd994a8f430d8cefa553e9b42ca62" @@ -1116,6 +1187,16 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-typescript" "^7.22.5" +"@babel/plugin-transform-typescript@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz#15adef906451d86349eb4b8764865c960eb54127" + integrity sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.22.5" + "@babel/plugin-transform-unicode-escapes@^7.22.10": version "7.22.10" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz#c723f380f40a2b2f57a62df24c9005834c8616d9" @@ -1274,6 +1355,17 @@ "@babel/plugin-transform-modules-commonjs" "^7.22.11" "@babel/plugin-transform-typescript" "^7.22.11" +"@babel/preset-typescript@^7.16.7": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz#43db30516fae1d417d748105a0bc95f637239d48" + integrity sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.22.5" + "@babel/plugin-transform-modules-commonjs" "^7.22.15" + "@babel/plugin-transform-typescript" "^7.22.15" + "@babel/register@^7.12.1", "@babel/register@^7.13.16": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.22.5.tgz#e4d8d0f615ea3233a27b5c6ada6750ee59559939" @@ -1347,6 +1439,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.22.15": + version "7.22.19" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.19.tgz#7425343253556916e440e662bb221a93ddb75684" + integrity sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.19" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" @@ -1743,6 +1844,13 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@egjs/hammerjs@^2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124" + integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A== + dependencies: + "@types/hammerjs" "^2.0.36" + "@emotion/babel-plugin@^11.11.0": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" @@ -1812,6 +1920,13 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== +"@emotion/is-prop-valid@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + "@emotion/is-prop-valid@^1.1.0", "@emotion/is-prop-valid@^1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" @@ -2464,6 +2579,13 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@gluestack-style/animation-plugin@^0.1.7": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@gluestack-style/animation-plugin/-/animation-plugin-0.1.12.tgz#887b57097397817c31fef25c8c53af381c11633e" + integrity sha512-lkj8iY5JBnhroUkP5gWE1zEpocb5GAK/G9SxL8DdWYQrsWOFpXr/mF/K67Dbxiv/n4B9BVff7sNTAddju+4UAw== + dependencies: + "@legendapp/motion" "^2.2.0" + "@gluestack-style/animation-plugin@latest": version "0.1.7" resolved "https://registry.yarnpkg.com/@gluestack-style/animation-plugin/-/animation-plugin-0.1.7.tgz#c9feae42684a48f2b5ece932681837d4b3ce7104" @@ -3423,6 +3545,59 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== +"@motionone/animation@^10.12.0": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.15.1.tgz#4a85596c31cbc5100ae8eb8b34c459fb0ccf6807" + integrity sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ== + dependencies: + "@motionone/easing" "^10.15.1" + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/dom@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.12.0.tgz#ae30827fd53219efca4e1150a5ff2165c28351ed" + integrity sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw== + dependencies: + "@motionone/animation" "^10.12.0" + "@motionone/generators" "^10.12.0" + "@motionone/types" "^10.12.0" + "@motionone/utils" "^10.12.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.15.1.tgz#95cf3adaef34da6deebb83940d8143ede3deb693" + integrity sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw== + dependencies: + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/generators@^10.12.0": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.15.1.tgz#dc6abb11139d1bafe758a41c134d4c753a9b871c" + integrity sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ== + dependencies: + "@motionone/types" "^10.15.1" + "@motionone/utils" "^10.15.1" + tslib "^2.3.1" + +"@motionone/types@^10.12.0", "@motionone/types@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.15.1.tgz#89441b54285012795cbba8612cbaa0fa420db3eb" + integrity sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA== + +"@motionone/utils@^10.12.0", "@motionone/utils@^10.15.1": + version "10.15.1" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.15.1.tgz#6b5f51bde75be88b5411e084310299050368a438" + integrity sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw== + dependencies: + "@motionone/types" "^10.15.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -6060,6 +6235,11 @@ dependencies: "@types/node" "*" +"@types/hammerjs@^2.0.36": + version "2.0.42" + resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.42.tgz#d7a53edbc51b2c13a9a759c45d7b5e61243d7dba" + integrity sha512-Xxk14BrwHnGi0xlURPRb+Y0UNn2w3cTkeFm7pKMsYOaNgH/kabbJLhcBoNIodwsbTz7Z8KcWjtDvlGH0nc0U9w== + "@types/hast@^2.0.0": version "2.3.5" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.5.tgz#08caac88b44d0fdd04dc17a19142355f43bd8a7a" @@ -6085,6 +6265,11 @@ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== +"@types/invariant@^2.2.35": + version "2.2.35" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" + integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== + "@types/is-ci@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/is-ci/-/is-ci-3.0.0.tgz#7e8910af6857601315592436f030aaa3ed9783c3" @@ -11643,6 +11828,27 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +framer-motion@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7" + integrity sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw== + dependencies: + "@motionone/dom" "10.12.0" + framesync "6.0.1" + hey-listen "^1.0.8" + popmotion "11.0.3" + style-value-types "5.0.0" + tslib "^2.1.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + +framesync@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== + dependencies: + tslib "^2.1.0" + freeport-async@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4" @@ -12427,6 +12633,11 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -15871,6 +16082,13 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moti@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/moti/-/moti-0.26.0.tgz#863e70e61c9d597f4fd701e588f41963335b927f" + integrity sha512-430HDIwhPQi/DkMvocyAZGkAX3ibmbyF3Fj23GuhbTB+RUXYTOnbsvygr89ABJjllYuxx4Xjd2Z4Qab0Su5mcg== + dependencies: + framer-motion "^6.5.1" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -17187,6 +17405,16 @@ polished@^4.2.2: dependencies: "@babel/runtime" "^7.17.8" +popmotion@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + style-value-types "5.0.0" + tslib "^2.1.0" + portfinder@^1.0.26: version "1.0.32" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" @@ -18145,6 +18373,17 @@ react-native-codegen@^0.70.6: jscodeshift "^0.13.1" nullthrows "^1.1.1" +react-native-gesture-handler@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.13.1.tgz#bad89caacd62c4560b9953b02f85f37ee42d5d4c" + integrity sha512-hW454X7sjuiBN+lobqw63pmT3boAmTl5OP6zQLq83iEe4T6PcHZ9lxzgCrebtgmutY8cJfq9rM2dOUVh9WBcww== + dependencies: + "@egjs/hammerjs" "^2.0.17" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + lodash "^4.17.21" + prop-types "^15.7.2" + react-native-gradle-plugin@^0.70.3: version "0.70.3" resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8" @@ -18164,6 +18403,19 @@ react-native-modal-selector@^2.1.1: dependencies: prop-types "^15.5.10" +react-native-reanimated@~2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.12.0.tgz#5821eecfb1769b1617a67a2d4dec12fdeedb2b6e" + integrity sha512-nrlPyw+Hx9u4iJhZk9PoTvDo/QmVAd+bo7OK9Tv3hveNEF9++5oig/g3Uv9V93shy9avTYGsUprUvAEt/xdzeQ== + dependencies: + "@babel/plugin-transform-object-assign" "^7.16.7" + "@babel/preset-typescript" "^7.16.7" + "@types/invariant" "^2.2.35" + invariant "^2.2.4" + lodash.isequal "^4.5.0" + setimmediate "^1.0.5" + string-hash-64 "^1.0.3" + react-native-safe-area-context@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.4.1.tgz#239c60b8a9a80eac70a38a822b04c0f1d15ffc01" @@ -19825,6 +20077,11 @@ string-argv@0.3.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== +string-hash-64@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322" + integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw== + string-hash@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -20062,6 +20319,14 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" +style-value-types@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== + dependencies: + hey-listen "^1.0.8" + tslib "^2.1.0" + styled-components@^5.3.0: version "5.3.11" resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.11.tgz#9fda7bf1108e39bf3f3e612fcc18170dedcd57a8" @@ -20685,7 +20950,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==