diff --git a/.changeset/config.json b/.changeset/config.json index 53769b98b..9aa735316 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,11 +7,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": [ - "expo-app", - "babel-gluestack-style-resolver-example", - "example-storybook", - "next-example-styled", - "benchmark-next" - ] + "ignore": ["benchmark-next", "@gluestack/ui-storybook"] } diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml_old similarity index 100% rename from .github/workflows/testing.yml rename to .github/workflows/testing.yml_old diff --git a/.vscode/settings.json b/.vscode/settings.json index 7cdc87cfe..292fbfa5f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ // Path to a .prettierignore or similar file "prettier.ignorePath": ".prettierignore", // If true, puts the `>` of a multi-line jsx element at the end of the last line instead of being alone on the next line - "editor.wordWrap": "on" + "editor.wordWrap": "on", + "cSpell.words": ["gluestack", "Pressable", "themeable"] } diff --git a/README.md b/README.md index 9b58f4cbe..22914096a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@
-## A library that allows you to use CSS in your React and React Native projects with a modern, powerful and flexible way. `gluestack-style` allows you to write CSS using JavaScript, which enables you to take advantage of the power and expressiveness of both languages. With its simple and intuitive API, you can easily create dynamic styles, responsive design, and handle themes for your applications. +**A library that allows you to use CSS in your React and React Native projects with a modern, powerful and flexible way. `gluestack-style` allows you to write CSS using JavaScript, which enables you to take advantage of the power and expressiveness of both languages. With its simple and intuitive API, you can easily create dynamic styles, responsive design, and handle themes for your applications.** ## Documentation @@ -88,7 +88,7 @@ export const App = () => { ``` More guides on how to get started are available -[here](https://gluestack.io/style). +[here](https://gluestack.io/style/docs). ## Contributing @@ -96,4 +96,4 @@ We welcome contributions to the `gluestack-style`! If you have an idea for a new ## License -Licensed under the MIT License, Copyright © 2021 GeekyAnts. See [LICENSE](https://github.com/gluestack/gluestack-style/blob/master/LICENSE) for more information. +Licensed under the MIT License, Copyright © 2021 GeekyAnts. See [LICENSE](https://github.com/gluestack/gluestack-style/blob/main/LICENSE) for more information. diff --git a/example/storybook/package.json b/example/storybook/package.json index 04fb7dd3a..56f78c943 100644 --- a/example/storybook/package.json +++ b/example/storybook/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "@expo/html-elements": "^0.4.2", - "@gluestack-style/react": "^0.2.11-alpha.0", + "@gluestack-style/react": "1.0.8", "@gluestack-ui/actionsheet": "^0.2.16", "@gluestack-ui/alert-dialog": "^0.1.14", "@gluestack-ui/button": "^0.1.23", diff --git a/example/storybook/src/advanced/BabelPlugins/index.stories.mdx b/example/storybook/src/advanced/BabelPlugins/index.stories.mdx index 71707a3e4..f9f733adf 100644 --- a/example/storybook/src/advanced/BabelPlugins/index.stories.mdx +++ b/example/storybook/src/advanced/BabelPlugins/index.stories.mdx @@ -1,6 +1,6 @@ --- title: Babel Plugins | gluestack-style -description: All the Babel plugins gluestack-style provides for its ecosystem. It transpiles your styled function calls and resolves the component styling in build time. +description: All the Babel plugins gluestack-style provides for its ecosystem. It transpile your styled function calls and resolves the component styling in build time. --- import { Canvas, Meta, Story } from '@storybook/addon-docs'; @@ -12,7 +12,7 @@ import { Box, AppProvider } from '@gluestack/design-system'; ### @gluestack-style/babel-plugin-styled-resolver -@gluestack-style/babel-plugin-styled-resolver transpiles your `styled` function calls and resolves the `component styling` in build time. It also generates all the `CSS rules` and style ids based on which these CSS styles are applied on the component. Doing this saves tons of time on runtime because all your style calculation is already done and all your app has to do is to inject this style into a style tag and viola! All your styles appear instantaneously. This helps us to improve the performance of the apps 5-6 times. If you provide the `components` option then it also resolves the inline styles of the components created using `@gluestack-style/react`. +@gluestack-style/babel-plugin-styled-resolver transpile your `styled` function calls and resolves the `component styling` in build time. It also generates all the `CSS rules` and style ids based on which these CSS styles are applied on the component. Doing this saves tons of time on runtime because all your style calculation is already done and all your app has to do is to inject this style into a style tag and viola! All your styles appear instantaneously. This helps us to improve the performance of the apps 5-6 times. If you provide the `components` option then it also resolves the inline styles of the components created using `@gluestack-style/react`. ## Installation Steps: @@ -40,7 +40,7 @@ import { Box, AppProvider } from '@gluestack/design-system'; 3. Just make sure your `babel.config.js` and `gluestack-style.config.js/ts` are in the same directory. We suggest you keep both of them at the root of your app codebase. -### **Let us see how this Babel plugin works.** +### Let us see how this Babel plugin works. - First, it traverses your files and tries to find `styled` imported from `@gluestack-style/react`. - Once it finds a declaration of `styled` it then looks for its function call. @@ -196,7 +196,7 @@ module.exports = function (api) { - `components`: The `components` option allows you to specify the library/import_path name & file path of components created using `@gluestack-style/react`. This option is useful in scenarios where you are creating a custom component with the styled function and using it with inline styles. If you want to resolve those inline styles on build time just define this option with the library name and file path of the components folder or library. -> **Note**: Even using this option if you have extended your config, added aliases, tokens or propertyResolver to a StyledComponent then it will not be resolved on build time. It will be resolved on runtime. +> Note: Even using this option if you have extended your config, added aliases, tokens or propertyResolver to a StyledComponent then it will not be resolved on build time. It will be resolved on runtime. ```js // babel.config.js diff --git a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx index 03351aa26..ed6a9271a 100644 --- a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx +++ b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx @@ -116,8 +116,12 @@ const Text1 = styled( } ); -const MyLink = styled(Link, {}); +const Box = styled(View, { + bg: '$blue500', + p: '$10', +}); export function ContextBasedStyles() { + console.log('>>>>> component'); return ( {/* */} @@ -129,14 +133,12 @@ export function ContextBasedStyles() { > vdkbkdfbv */} - - next link - + > ); } diff --git a/example/storybook/src/api/PropertyResolver/index.stories.mdx b/example/storybook/src/api/PropertyResolver/index.stories.mdx index abf7ab65d..7a682ad41 100644 --- a/example/storybook/src/api/PropertyResolver/index.stories.mdx +++ b/example/storybook/src/api/PropertyResolver/index.stories.mdx @@ -187,4 +187,4 @@ export const config = createConfig({ } as const); ``` -> Warning: We strongly advise against using this feature" as this can impact your performance since this needs to be resolved on the fly and can not be optimised at build time. +> Warning: We strongly advise against using this feature" as this can impact your performance since this needs to be resolved on the fly and can not be optimized at build time. diff --git a/example/storybook/src/api/PropsPassing/index.stories.mdx b/example/storybook/src/api/PropsPassing/index.stories.mdx index 89dc45812..0ae57a8de 100644 --- a/example/storybook/src/api/PropsPassing/index.stories.mdx +++ b/example/storybook/src/api/PropsPassing/index.stories.mdx @@ -33,3 +33,5 @@ const StyledComponent = styled( }, ); ``` + +> Caution: Utilizing the `Passing Props` feature within `Media Queries` is not supported. diff --git a/example/storybook/src/api/ResponsiveStyles/index.stories.mdx b/example/storybook/src/api/ResponsiveStyles/index.stories.mdx index 21ca805a0..f6991f615 100644 --- a/example/storybook/src/api/ResponsiveStyles/index.stories.mdx +++ b/example/storybook/src/api/ResponsiveStyles/index.stories.mdx @@ -107,6 +107,9 @@ Once configured, you can apply different styles at different breakpoints. /> + > Note that the '@' symbol indicates a media query.The '@' symbol should be followed by the name of the desired breakpoint for the styles. > Note that the same API can be used with the sx prop to override styles inline. + +> Caution: Utilizing the `Passing Props` feature within `Media Queries` is not supported. diff --git a/example/storybook/src/api/UtilityProps/index.stories.mdx b/example/storybook/src/api/UtilityProps/index.stories.mdx index ce101f2f0..cbf41785b 100644 --- a/example/storybook/src/api/UtilityProps/index.stories.mdx +++ b/example/storybook/src/api/UtilityProps/index.stories.mdx @@ -1,6 +1,6 @@ --- title: Utility Props | gluestack-style -description: Writing inline styles with Utlity Props. We provide you the ability to pass down utility props on any Styled Component which internally converts to `sx` prop. +description: Writing inline styles with Utility Props. We provide you the ability to pass down utility props on any Styled Component which internally converts to `sx` prop. --- import { Canvas, Meta, Story } from '@storybook/addon-docs'; diff --git a/example/storybook/src/components/nb.config.ts b/example/storybook/src/components/nb.config.ts index 9f922adf5..03bb38488 100644 --- a/example/storybook/src/components/nb.config.ts +++ b/example/storybook/src/components/nb.config.ts @@ -659,6 +659,9 @@ export const config = createConfig({ 100: 1, }, } as const, + globalStyle: { + variants: {}, + }, themes: { '2000s': { colors: { diff --git a/example/storybook/src/overview/Performance/index.stories.mdx b/example/storybook/src/overview/Performance/index.stories.mdx index 89819540b..88b1de710 100644 --- a/example/storybook/src/overview/Performance/index.stories.mdx +++ b/example/storybook/src/overview/Performance/index.stories.mdx @@ -16,7 +16,7 @@ We tested the performance of our landing page, built with `gluestack-style` and Performance matrics from lighthouse report We have run the benchmark, and we are getting great results compared to other libraries. We don't want the comparison with other libraries to be the ultimate scoring system. It doesn't give the full picture of any library. There are other important metrics too. Also, we may go wrong in how we run the benchmark, we may end up with selection bias too (unintentionally). diff --git a/example/storybook/src/plugins/FontsPlugin/index.stories.mdx b/example/storybook/src/plugins/FontsPlugin/index.stories.mdx index aeb8dc30b..56628938e 100644 --- a/example/storybook/src/plugins/FontsPlugin/index.stories.mdx +++ b/example/storybook/src/plugins/FontsPlugin/index.stories.mdx @@ -21,7 +21,7 @@ The font plugin, a utility for the styled function, provides a unified way to pa Include the `FontResolver` plugin in your config. To customize font resolution, pass a mapFonts callback function to the constructor. ```js -import { FontResolver } from '@gluetsack-style/react'; +import { FontResolver } from '@gluestack-style/react'; export const config = { aliases: {}, diff --git a/package.json b/package.json index be1075f10..52f52d998 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "scripts": { "test": "bash ./scripts/test.sh", "dev": "turbo run dev", - "build": "turbo run build --filter=@gluestack-style* --no-cache", + "build": "turbo run build --filter=@gluestack-style/react --no-cache && yarn build:rest", + "build:rest": "turbo run build --filter=@gluestack-style* --no-cache --ignore=@gluestack-style/react", "clean": "turbo run clean && rm -rf node_modules", "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\" --ignore-path .gitignore", "release": "changeset publish", diff --git a/packages/animation-legend-motion-driver/package.json b/packages/animation-legend-motion-driver/package.json index 5fcec3c2c..91529a4d8 100644 --- a/packages/animation-legend-motion-driver/package.json +++ b/packages/animation-legend-motion-driver/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-style/legend-motion-animation-driver", - "version": "1.0.1", + "version": "1.0.2", "description": "A gluestack-style plugin for animation support using legendapp motion library", "keywords": [ "react", diff --git a/packages/animation-legend-motion-driver/src/index.tsx b/packages/animation-legend-motion-driver/src/index.tsx index 0a0333cc3..6ae0813b2 100644 --- a/packages/animation-legend-motion-driver/src/index.tsx +++ b/packages/animation-legend-motion-driver/src/index.tsx @@ -1,63 +1,18 @@ -import { useStyled } from '@gluestack-style/react'; import type { IAnimationDriverPlugin, IAnimationResolver, } from '@gluestack-style/react'; -import React, { useMemo } from 'react'; -import { - deepMerge, - deepMergeObjects, - setObjectKeyValue, - resolvedTokenization, -} from './utils'; +import React from 'react'; +import { deepMerge } from './utils'; import { Motion, AnimatePresence as MotionAnimatePresence, createMotionAnimatedComponent, } from '@legendapp/motion'; +import { MotionSvg } from '@legendapp/motion/svg'; import { propertyTokenMap } from './propertyTokenMap'; import { Pressable } from 'react-native'; -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) : []; @@ -91,15 +46,7 @@ function resolveVariantAnimationProps(variantProps: any, styledObject: any) { 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 ( @@ -107,49 +54,30 @@ const AnimatePresence = React.forwardRef( child?.type?.displayName.includes('Gluestack-AnimatedResolver')) || child?.type?.isStyledComponent ) { - let tokenizedAnimatedProps: any = {}; - const animationAliases = {}; - const componentStyledObject = child?.type?.getStyledData()?.config; const { variantProps, restProps } = getVariantProps( - child?.props, + { ...componentStyledObject?.props, ...child?.props }, componentStyledObject ); - const config = CONFIG; - - const variantStyledObject = resolveVariantAnimationProps( + const variantStyledObject: any = resolveVariantAnimationProps( variantProps, componentStyledObject ); - const componentStyledObjectWithVariants = deepMergeObjects( - componentStyledObject, - variantStyledObject - ); - tokenizedAnimatedProps = tokenizeAnimationPropsFromConfig( - componentStyledObjectWithVariants, - config, - animationAliases - ); - - const tokenizedSxAnimationProps: any = tokenizeAnimationPropsFromConfig( - child?.props?.sx, - config, - animationAliases - ); - - const mergedAnimatedProps = deepMergeObjects( - {}, - tokenizedSxAnimationProps, - tokenizedAnimatedProps - ); + const exit = { + ...componentStyledObject?.[':exit'], + ...variantStyledObject?.[':exit'], + ...restProps?.sx?.[':exit'], + ...restProps?.exit, + }; const clonedChild = React.cloneElement(child, { + exit, ...restProps, - exit: mergedAnimatedProps?.baseStyle?.[':exit'], }); + clonedChildren.push(clonedChild); } else { clonedChildren.push(child); @@ -167,9 +95,17 @@ const AnimatePresence = React.forwardRef( const AnimatedPressable = createMotionAnimatedComponent( Pressable ) as React.ComponentType; + +const MotionComponents = { + ...Motion, + ...MotionSvg, + Pressable: AnimatedPressable, + AnimatePresence, +}; + export class MotionAnimationDriver implements IAnimationDriverPlugin { name: 'MotionAnimationDriver'; - engine = { ...Motion, Pressable: AnimatedPressable, AnimatePresence }; + engine = MotionComponents; config = { aliases: { ':animate': 'animate', diff --git a/packages/animation-moti-driver/package.json b/packages/animation-moti-driver/package.json index ccd160a46..ca3d65f16 100644 --- a/packages/animation-moti-driver/package.json +++ b/packages/animation-moti-driver/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-style/moti-animation-driver", - "version": "1.0.1", + "version": "1.0.2", "description": "A gluestack-style driver for using moti animation with animation resolver plugin.", "keywords": [ "react", @@ -24,13 +24,13 @@ "clean": "rm -rf lib" }, "peerDependencies": { - "@gluestack-style/react": ">=0.2", + "@gluestack-style/react": ">=1.0.7", "moti": ">=0.26", "react-native-gesture-handler": ">=2.12", "react-native-reanimated": ">=3.5" }, "devDependencies": { - "@gluestack-style/react": "^0.2.49", + "@gluestack-style/react": "^1.0.7", "@types/react": "^18.0.22", "@types/react-native": "^0.69.15", "babel-plugin-transform-remove-console": "^6.9.4", diff --git a/packages/animation-moti-driver/src/index.tsx b/packages/animation-moti-driver/src/index.tsx index 86df238a5..d6c93dec7 100644 --- a/packages/animation-moti-driver/src/index.tsx +++ b/packages/animation-moti-driver/src/index.tsx @@ -13,6 +13,32 @@ import { MotiProgressBar, AnimatePresence, } from 'moti'; +import { + Svg as RNSvg, + Rect as RNRect, + Circle as RNCircle, + Ellipse as RNEllipse, + Line as RNLine, + Polyline as RNPolyline, + Path as RNPath, + TSpan as RNTSpan, + TextPath as RNTextPath, + G as RNG, + ClipPath as RNClipPath, +} from 'react-native-svg'; +import { motifySvg } from 'moti/svg'; + +const Svg = motifySvg(RNSvg); +const Rect = motifySvg(RNRect); +const Circle = motifySvg(RNCircle); +const Ellipse = motifySvg(RNEllipse); +const Line = motifySvg(RNLine); +const Polyline = motifySvg(RNPolyline); +const Path = motifySvg(RNPath); +const TSpan = motifySvg(RNTSpan); +const TextPath = motifySvg(RNTextPath); +const G = motifySvg(RNG); +const ClipPath = motifySvg(RNClipPath); let Moti = { Image: MotiImage, @@ -21,6 +47,17 @@ let Moti = { ScrollView: MotiScrollView, SafeAreaView: MotiSafeAreaView, ProgressBar: MotiProgressBar, + Svg, + Rect, + Circle, + Ellipse, + Line, + Polyline, + Path, + TSpan, + TextPath, + G, + ClipPath, AnimatePresence, }; export class MotiAnimationDriver implements IAnimationDriverPlugin { diff --git a/packages/animation-resolver/package.json b/packages/animation-resolver/package.json index 7b52fff12..c428cf9a7 100644 --- a/packages/animation-resolver/package.json +++ b/packages/animation-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-style/animation-resolver", - "version": "1.0.1", + "version": "1.0.2", "description": "A gluestack-style plugin for resolving animation properties, utilizing animation libraries.", "keywords": [ "react", @@ -22,10 +22,10 @@ "clean": "rm -rf lib" }, "peerDependencies": { - "@gluestack-style/react": ">=0.2" + "@gluestack-style/react": ">=1.0.7" }, "devDependencies": { - "@gluestack-style/react": "^0.2.49", + "@gluestack-style/react": "^1.0.7", "@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 index b472f8b45..b494c4d2f 100644 --- a/packages/animation-resolver/src/AnimatedComponents/index.tsx +++ b/packages/animation-resolver/src/AnimatedComponents/index.tsx @@ -9,10 +9,23 @@ import type { FlatListProps, SectionListProps, } from 'react-native'; +import type { + SvgProps, + GProps, + ClipPathProps, + RectProps, + PolylineProps, + CircleProps, + EllipseProps, + LineProps, + PathProps, + TSpanProps, + TextPathProps, +} from 'react-native-svg'; const getAnimationResolverPlugin: any = (plugins: any[]) => { let pluginData; - plugins.forEach((plugin) => { + plugins?.forEach((plugin) => { if (plugin.name === 'AnimationResolver') { pluginData = plugin; } @@ -94,6 +107,95 @@ const AnimatedSectionList = ( const Component = animatedComponent('SectionList', props); return ; }; + +const AnimatedSvg = ( + props: SvgProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Svg', props); + return ; +}; +const AnimatedRect = ( + props: RectProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Rect', props); + return ; +}; +const AnimatedCircle = ( + props: CircleProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Circle', props); + return ; +}; +const AnimatedEllipse = ( + props: EllipseProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Ellipse', props); + return ; +}; +const AnimatedLine = ( + props: LineProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Line', props); + return ; +}; +const AnimatedPolyline = ( + props: PolylineProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Polyline', props); + return ; +}; +const AnimatedPath = ( + props: PathProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('Path', props); + return ; +}; +const AnimatedTSpan = ( + props: TSpanProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('TSpan', props); + return ; +}; +const AnimatedTextPath = ( + props: TextPathProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('TextPath', props); + return ; +}; +const AnimatedG = ( + props: GProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('G', props); + return ; +}; +const AnimatedClipPath = ( + props: ClipPathProps & { + animationComponentGluestack: true; + } +) => { + const Component = animatedComponent('ClipPath', props); + return ; +}; const AnimatePresence = animatedComponent('AnimatePresence', {}); AnimatedText.displayName = 'Gluestack-AnimatedResolver-AnimatedText'; @@ -109,6 +211,17 @@ AnimatedSectionList.displayName = 'Gluestack-AnimatedResolver-AnimatedSectionList'; AnimatePresence.displayName = 'Gluestack-AnimatedResolver-AnimatedAnimatePresence'; +AnimatedSvg.displayName = 'Gluestack-AnimatedResolver-AnimatedSvg'; +AnimatedRect.displayName = 'Gluestack-AnimatedResolver-AnimatedRect'; +AnimatedCircle.displayName = 'Gluestack-AnimatedResolver-AnimatedCircle'; +AnimatedEllipse.displayName = 'Gluestack-AnimatedResolver-AnimatedEllipse'; +AnimatedLine.displayName = 'Gluestack-AnimatedResolver-AnimatedLine'; +AnimatedPolyline.displayName = 'Gluestack-AnimatedResolver-AnimatedPolyline'; +AnimatedPath.displayName = 'Gluestack-AnimatedResolver-AnimatedPath'; +AnimatedTSpan.displayName = 'Gluestack-AnimatedResolver-AnimatedTSpan'; +AnimatedTextPath.displayName = 'Gluestack-AnimatedResolver-AnimatedTextPath'; +AnimatedG.displayName = 'Gluestack-AnimatedResolver-AnimatedG'; +AnimatedClipPath.displayName = 'Gluestack-AnimatedResolver-AnimatedClipPath'; export { AnimatedText, @@ -120,4 +233,15 @@ export { AnimatedFlatList, AnimatedSectionList, AnimatePresence, + AnimatedSvg, + AnimatedRect, + AnimatedCircle, + AnimatedEllipse, + AnimatedLine, + AnimatedPolyline, + AnimatedPath, + AnimatedTSpan, + AnimatedTextPath, + AnimatedG, + AnimatedClipPath, }; diff --git a/packages/animation-resolver/src/index.tsx b/packages/animation-resolver/src/index.tsx index f46033641..17068cd98 100644 --- a/packages/animation-resolver/src/index.tsx +++ b/packages/animation-resolver/src/index.tsx @@ -210,24 +210,18 @@ export class AnimationResolver implements IStyledPlugin { resolvedStyledObject: any = {}, keyPath: string[] = [] ) { - const aliases = this.config?.aliases; + const aliases: any = 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 + for (const prop in styledObject) { if (aliases && aliases?.[prop]) { + let isStyleKey = false; if (shouldUpdateConfig) { // this.#childrenExitPropsMap[prop] = styledObject[prop]; + if (keyPath[keyPath.length - 1] === 'style') { + isStyleKey = true; + keyPath.pop(); + } setObjectKeyValue( this.#childrenExitPropsMap, [...keyPath, prop], @@ -236,9 +230,6 @@ export class AnimationResolver implements IStyledPlugin { } const value = styledObject[prop]; - if (keyPath[keyPath.length - 1] === 'style') { - keyPath.pop(); - } // @ts-ignore keyPath.push('props', aliases[prop]); // setObjectKeyValue(resolvedStyledObject, keyPath, value); @@ -246,9 +237,22 @@ export class AnimationResolver implements IStyledPlugin { setObjectKeyValue(resolvedStyledObject, keyPath, value); keyPath.pop(); keyPath.pop(); - // delete styledObject[prop]; + if (isStyleKey) keyPath.push('style'); + + delete styledObject[prop]; + } else if (typeof styledObject[prop] === 'object') { + keyPath.push(prop); + this.updateStyledObject( + styledObject[prop], + shouldUpdateConfig, + resolvedStyledObject, + keyPath + ); + keyPath.pop(); } + // @ts-ignore + if (animatedPropMap && animatedPropMap[prop]) { this.renameObjectKey(styledObject, prop, animatedPropMap[prop]); } @@ -334,14 +338,7 @@ export class AnimationResolver implements IStyledPlugin { resolvedAnimatedStyledWithStyledObject?.props : {}; - return ( - - ); + return ; }); if (NewComponent) { @@ -349,14 +346,19 @@ export class AnimationResolver implements IStyledPlugin { NewComponent.styled = {}; //@ts-ignore NewComponent.styled.config = {}; + //@ts-ignore - NewComponent.styled.config = styledConfig; + NewComponent.styled.config = { + ...Component?.styled?.config, + ...styledConfig, + }; //@ts-ignore NewComponent.isStyledComponent = Component?.isStyledComponent; //@ts-ignore NewComponent.isComposedComponent = Component?.isComposedComponent; NewComponent.displayName = Component?.displayName; + return NewComponent; } } else { diff --git a/packages/babel-plugin-styled-resolver/package.json b/packages/babel-plugin-styled-resolver/package.json index 2250aafd1..e34cadcd2 100644 --- a/packages/babel-plugin-styled-resolver/package.json +++ b/packages/babel-plugin-styled-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-style/babel-plugin-styled-resolver", - "version": "1.0.0-alpha.0", + "version": "1.0.0", "description": "A gluestack-style babel plugin that transpiles your styled function calls and resolves the component styling in build time.", "keywords": [ "css-in-js", diff --git a/packages/benchmark-next/package.json b/packages/benchmark-next/package.json index 02724489f..0b158dd35 100644 --- a/packages/benchmark-next/package.json +++ b/packages/benchmark-next/package.json @@ -25,8 +25,8 @@ "styled-components": "^5.3.0" }, "devDependencies": { - "@gluestack-style/babel-plugin-styled-resolver": "^0.1.6", - "@gluestack-style/react": "^0.1.33", + "@gluestack-style/babel-plugin-styled-resolver": "1.0.0", + "@gluestack-style/react": "1.0.8", "@emotion/styled": "^11.3.0", "@expo/next-adapter": "^4.0.13", "@types/react": "17.0.1", diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 78ce2539a..a6ffdc918 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,19 @@ # @gluestack-style/react +## 1.0.8 + +### Patch Changes + +- - Fixed global style platform based resolution + - Fixed useToken to return default value as fallback + - Fixed theme passing props resolution + +## 1.0.7 + +### Patch Changes + +- fix: component typings + ## 0.2.9 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index f386b944f..d04887dfd 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { "name": "@gluestack-style/react", "description": "A universal & performant styling library for React Native, Next.js & React", - "version": "1.0.1", + "version": "1.0.8", "keywords": [ "React Native", "Next.js", diff --git a/packages/react/src/StyledProvider.tsx b/packages/react/src/StyledProvider.tsx index 758a9e652..b8a50b7a4 100644 --- a/packages/react/src/StyledProvider.tsx +++ b/packages/react/src/StyledProvider.tsx @@ -1,11 +1,12 @@ import { get, onChange, set } from './core/colorMode'; import * as React from 'react'; -import { Platform } from 'react-native'; +import { Platform, View } from 'react-native'; import { propertyTokenMap } from './propertyTokenMap'; import type { COLORMODES } from './types'; import { platformSpecificSpaceUnits } from './utils'; import { createGlobalStylesWeb } from './createGlobalStylesWeb'; import { createGlobalStyles } from './createGlobalStyles'; + type Config = any; let colorModeSet = false; @@ -42,7 +43,19 @@ export const StyledProvider: React.FC<{ colorMode?: COLORMODES; children?: React.ReactNode; globalStyles?: any; -}> = ({ config, colorMode, children, globalStyles }) => { + _experimentalNestedProvider?: boolean; +}> = ({ + config, + colorMode, + children, + globalStyles, + _experimentalNestedProvider, +}) => { + const inlineStyleMap: any = React.useRef({ + initialStyleInjected: false, + }); + inlineStyleMap.current.initialStyleInjected = false; + const currentConfig: any = React.useMemo(() => { //TODO: Add this later return platformSpecificSpaceUnits(config, Platform.OS); @@ -57,11 +70,22 @@ export const StyledProvider: React.FC<{ return colorMode ?? get() ?? 'light'; }, [colorMode]); + const _experimentalNestedProviderRef = React.useRef(null); React.useEffect(() => { + let documentElement: any = null; + + if (Platform.OS === 'web') { + if (_experimentalNestedProvider) { + // write own code for nested colorMode + documentElement = _experimentalNestedProviderRef.current; + } else { + documentElement = document.documentElement; + } + } // Add gs class name if (Platform.OS === 'web') { - document.documentElement.classList.add(`gs`); - document.documentElement.classList.add(`gs-${currentColorMode}`); + documentElement.classList.add(`gs`); + documentElement.classList.add(`gs-${currentColorMode}`); } // GluestackStyleSheet.resolve({ ...config, propertyTokenMap }); @@ -69,13 +93,17 @@ export const StyledProvider: React.FC<{ onChange((currentColor: string) => { // only for web - if (Platform.OS === 'web') { - if (currentColor === 'dark') { - document.documentElement.classList.remove(`gs-light`); - } else { - document.documentElement.classList.remove(`gs-dark`); + if (Platform.OS === 'web' && !_experimentalNestedProvider) { + const documentElement = document.documentElement; + + if (Platform.OS === 'web') { + if (currentColor === 'dark') { + documentElement.classList.remove(`gs-light`); + } else { + documentElement.classList.remove(`gs-dark`); + } + documentElement.classList.add(`gs-${currentColor}`); } - document.documentElement.classList.add(`gs-${currentColor}`); } }); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -85,6 +113,38 @@ export const StyledProvider: React.FC<{ setCurrentColorMode(currentColorMode); }, [currentColorMode]); + React.useLayoutEffect(() => { + if (Platform.OS === 'web') { + const toBeInjectedStyles: any = {}; + + if (inlineStyleMap.current.initialStyleInjected) { + return; + } + + Object.keys(inlineStyleMap.current).forEach((key: any) => { + if (key !== 'initialStyleInjected') { + const styles = inlineStyleMap.current[key]; + if (!toBeInjectedStyles[key]) { + toBeInjectedStyles[key] = document.createDocumentFragment(); + } + + styles.forEach((style: any) => { + if (!document.getElementById(style.id)) { + toBeInjectedStyles[key].appendChild(style); + } + }); + } + }); + Object.keys(toBeInjectedStyles).forEach((key) => { + let wrapperElement = document.querySelector('#' + key); + if (wrapperElement) { + wrapperElement.appendChild(toBeInjectedStyles[key]); + } + // delete inlineStyleMap.current[key]; + }); + inlineStyleMap.current.initialStyleInjected = true; + } + }); // // Set colormode for the first time if (!colorModeSet) { setCurrentColorMode(currentColorMode); @@ -92,22 +152,40 @@ export const StyledProvider: React.FC<{ const [animationDriverData, setAnimationDriverData] = React.useState(); const globalStyleMap = - config?.globalStyle && createGlobalStyles(config.globalStyle); + config?.globalStyle && createGlobalStyles(config.globalStyle, Platform); const contextValue = React.useMemo(() => { - return { + const styledData = { config: currentConfig, globalStyle: globalStyleMap, animationDriverData, setAnimationDriverData, + inlineStyleMap: inlineStyleMap.current, }; + + if (_experimentalNestedProvider) { + //@ts-ignore + styledData._experimentalNestedProvider = _experimentalNestedProvider; + //@ts-ignore + styledData.colorMode = colorMode; + } + return styledData; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentConfig, globalStyleMap, animationDriverData]); - return ( + const providerComponent = ( {children} ); + + if (_experimentalNestedProvider) { + return ( + {providerComponent} + ); + } else { + return <>{providerComponent}; + } }; export const useStyled = () => React.useContext(StyledContext); diff --git a/packages/react/src/core/styled-system.ts b/packages/react/src/core/styled-system.ts index 0238c473d..b942220bf 100644 --- a/packages/react/src/core/styled-system.ts +++ b/packages/react/src/core/styled-system.ts @@ -9,6 +9,10 @@ export const CSSPropertiesMap = { borderTopWidth: '0', borderEndWidth: '0', borderStartWidth: '0', + borderEndEndRadius: '0', + borderStartStartRadius: '0', + borderStartEndRadius: '0', + borderEndStartRadius: '0', borderWidth: '0', bottom: 'auto', direction: 'ltr', @@ -65,6 +69,9 @@ export const CSSPropertiesMap = { borderBottomLeftRadius: '0', borderBottomRightRadius: '0', borderColor: 'initial', + borderBlockColor: 'initial', + borderBlockEndColor: 'initial', + borderBlockStartColor: 'initial', borderRadius: '0', borderTopLeftRadius: '0', borderTopRightRadius: '0', @@ -92,6 +99,7 @@ export const CSSPropertiesMap = { textShadowOffset: '0px 0px', textShadowRadius: '0', textAlignVertical: 'auto', + verticalAlign: 'auto', letterSpacing: 'normal', textDecorationColor: 'initial', textDecorationStyle: 'solid', @@ -101,6 +109,7 @@ export const CSSPropertiesMap = { borderStartColor: 'initial', borderTopEndRadius: '0', borderTopStartRadius: '0', + userSelect: 'auto', }; export const reservedKeys = { diff --git a/packages/react/src/createConfig.ts b/packages/react/src/createConfig.ts index 5df3a0467..bf411ad7e 100644 --- a/packages/react/src/createConfig.ts +++ b/packages/react/src/createConfig.ts @@ -11,21 +11,21 @@ import { Platform } from 'react-native'; /********************* PLUGINS *****************************/ -var globalPluginStore: never[] = []; -function setGlobalPluginStore(plugins: any) { - if (plugins) { - // @ts-ignore - globalPluginStore.push(...plugins); - } - return getGlobalPluginStore(); -} -function getGlobalPluginStore() { - return globalPluginStore; -} +// var globalPluginStore: never[] = []; +// function setGlobalPluginStore(plugins: any) { +// if (plugins) { +// // @ts-ignore +// globalPluginStore.push(...plugins); +// } +// return getGlobalPluginStore(); +// } +// function getGlobalPluginStore() { +// return globalPluginStore; +// } -export function getInstalledPlugins() { - return getGlobalPluginStore(); -} +// export function getInstalledPlugins() { +// return getGlobalPluginStore(); +// } /********************* CREATE COMPONENTS *****************************/ @@ -74,7 +74,7 @@ export const createConfig = < > ): T => { if (config.plugins) { - config.plugins = setGlobalPluginStore(config.plugins); + // config.plugins = setGlobalPluginStore(config.plugins); } // delete config.plugins; diff --git a/packages/react/src/createGlobalStyles.ts b/packages/react/src/createGlobalStyles.ts index 30294efd9..558e501c3 100644 --- a/packages/react/src/createGlobalStyles.ts +++ b/packages/react/src/createGlobalStyles.ts @@ -1,9 +1,11 @@ import { convertStyledToStyledVerbosed } from './convertSxToSxVerbosed'; import { stableHash } from './stableHash'; +import { resolvePlatformTheme } from './styled'; import { updateOrderUnResolvedMap } from './updateOrderUnResolvedMap'; -export const createGlobalStyles = (globalStyle: object) => { +export const createGlobalStyles = (globalStyle: object, Platform: any) => { const versboseComponentTheme = convertStyledToStyledVerbosed(globalStyle); + resolvePlatformTheme(versboseComponentTheme, Platform.OS); const componentHash = stableHash({ ...globalStyle, }); diff --git a/packages/react/src/hooks/useToken.ts b/packages/react/src/hooks/useToken.ts index 2bbd1b679..2ca7bce15 100644 --- a/packages/react/src/hooks/useToken.ts +++ b/packages/react/src/hooks/useToken.ts @@ -11,5 +11,5 @@ export const useToken = (tokenScale: string, token: string) => { const theme: ICustomConfig = useStyled(); // @ts-ignore const themeTokens = theme.config.tokens; - return themeTokens?.[`${tokenScale}`]?.[`${token}`]; + return themeTokens?.[`${tokenScale}`]?.[`${token}`] ?? token; }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 4359ef50f..ef0d7582f 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -92,9 +92,9 @@ export { createStyle } from './createStyle'; export { INTERNAL_updateCSSStyleInOrderedResolved } from './updateCSSStyleInOrderedResolved'; export { createConfig, - getInstalledPlugins, + // getInstalledPlugins, createComponents, - getInstalledComponents, + // getInstalledComponents, } from './createConfig'; export * from './core'; export * from './hooks'; diff --git a/packages/react/src/plugins/font-resolver.tsx b/packages/react/src/plugins/font-resolver.tsx index 8b5b19a65..7dafdaa6b 100644 --- a/packages/react/src/plugins/font-resolver.tsx +++ b/packages/react/src/plugins/font-resolver.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import type { IStyled, IStyledPlugin } from '../types'; import { useStyled } from '../StyledProvider'; import { propertyTokenMap } from '../propertyTokenMap'; -import { deepMerge, deepMergeObjects, setObjectKeyValue } from '../utils'; +import { deepMerge, setObjectKeyValue } from '../utils'; import { getVariantProps } from '../styled'; const fontWeights: any = { @@ -140,14 +140,19 @@ export class FontResolver implements IStyledPlugin, FontPlugin { this.mapFonts = mapFonts || this.mapFonts; } - inputMiddleWare(styledObj: any = {}, shouldUpdate: boolean = true): void { + inputMiddleWare( + styledObj: any = {}, + shouldUpdate: boolean = true, + _?: boolean, + Component?: React.ComponentType + ) { const modifiedStyledObject = this.fontHandler(styledObj, shouldUpdate); if (shouldUpdate) { - return styledObj; + return [styledObj, shouldUpdate, _, Component]; } - return modifiedStyledObject; + return [modifiedStyledObject, shouldUpdate, _, Component]; } #fontFamily: any = {}; @@ -204,18 +209,20 @@ export class FontResolver implements IStyledPlugin, FontPlugin { fontWeightsTokens: this.#fontWeightsTokenConfig, }); - if (styledObject[styledObjectKey]) this.mapFonts(styledObject); + if (styledObject[styledObjectKey]) { + this.mapFonts(styledObject); + } } } return styledObject; } - componentMiddleWare({ NewComp, extendedConfig }: any) { + componentMiddleWare({ Component: InputComponent, extendedConfig }: any) { const styledConfig = this.#fontFamily; this.#fontFamily = {}; - const Comp = React.forwardRef((props: any, ref: any) => { + const OutputComponent = React.forwardRef((props: any, ref: any) => { const styledContext = useStyled(); const CONFIG = useMemo( () => ({ @@ -242,12 +249,9 @@ export class FontResolver implements IStyledPlugin, FontPlugin { variantProps, styledConfig ); - let componentStyledObject = deepMergeObjects( - styledConfig, - variantStyledObject - ); + let componentStyledObject = deepMerge(styledConfig, variantStyledObject); - delete componentStyledObject.variants; + // delete componentStyledObject.variants; const { sx, fontWeight, fontFamily, fontStyle, ...rest } = restProps; @@ -268,17 +272,35 @@ export class FontResolver implements IStyledPlugin, FontPlugin { const sxPropsWithThemeProps = deepMerge(sx, componentStyledObject); - const resolvedSxProps = this.inputMiddleWare( + const [resolvedSxProps, , ,] = this.inputMiddleWare( sxPropsWithThemeProps, - false + false, + false, + () => <> ); - return ; + return ; }); //@ts-ignore - Comp.isStyledComponent = NewComp.isStyledComponent; + OutputComponent.styled = {}; + //@ts-ignore + OutputComponent.styled.config = {}; + //@ts-ignore + OutputComponent.styled.config = { + ...styledConfig?.config, + ...InputComponent?.styled?.config, + }; + + //@ts-ignore + OutputComponent.isStyledComponent = InputComponent?.isStyledComponent; + //@ts-ignore + OutputComponent.isComposedComponent = InputComponent?.isComposedComponent; + //@ts-ignore + OutputComponent.isAnimatedComponent = InputComponent?.isAnimatedComponent; + + OutputComponent.displayName = InputComponent?.displayName; - return Comp; + return OutputComponent; } } diff --git a/packages/react/src/propertyTokenMap.ts b/packages/react/src/propertyTokenMap.ts index 9ffecb11b..64f87b3a1 100644 --- a/packages/react/src/propertyTokenMap.ts +++ b/packages/react/src/propertyTokenMap.ts @@ -127,7 +127,17 @@ export const propertyTokenMap = { textDecorationColor: colors, shadowColor: colors, + borderBlockColor: colors, + borderBlockEndColor: colors, + borderBlockStartColor: colors, + + borderEndEndRadius: radii, + borderStartStartRadius: radii, + borderStartEndRadius: radii, + borderEndStartRadius: radii, + shadowOpacity: opacity, + opacity: opacity, shadow: shadows, // Media Query diff --git a/packages/react/src/resolver/injectComponentAndDescendantStyles.ts b/packages/react/src/resolver/injectComponentAndDescendantStyles.ts index 913ac2f71..b3a37804b 100644 --- a/packages/react/src/resolver/injectComponentAndDescendantStyles.ts +++ b/packages/react/src/resolver/injectComponentAndDescendantStyles.ts @@ -12,7 +12,8 @@ export function injectComponentAndDescendantStyles( styleTagId?: string, type: 'boot' | 'inline' = 'boot', _GluestackStyleSheet: StyleInjector = GluestackStyleSheet, - platform: string = '' + platform: string = '', + inlineStyleMap?: any ) { const [ componentOrderResolvedBaseStyle, @@ -84,7 +85,7 @@ export function injectComponentAndDescendantStyles( ); if (platform === 'web') { - GluestackStyleSheet.inject(toBeInjected); + GluestackStyleSheet.inject(toBeInjected, inlineStyleMap); } return styleCSSIdsArr; diff --git a/packages/react/src/style-sheet/index.ts b/packages/react/src/style-sheet/index.ts index ee7f34d14..d3d82f311 100644 --- a/packages/react/src/style-sheet/index.ts +++ b/packages/react/src/style-sheet/index.ts @@ -109,10 +109,15 @@ export class StyleInjector { return toBeInjected; } - inject(toBeInjected: any = {}) { + inject(toBeInjected: any = {}, inlineStyleMap: any) { Object.keys(toBeInjected).forEach((type) => { Object.keys(toBeInjected[type]).forEach((styleTag) => { - this.injectStyles(toBeInjected[type][styleTag], type, styleTag); + this.injectStyles( + toBeInjected[type][styleTag], + type, + styleTag, + inlineStyleMap + ); }); }); } @@ -162,9 +167,19 @@ export class StyleInjector { return this.#globalStyleMap; } - injectStyles(cssRuleset: any, _wrapperType: any, _styleTagId: any) { + injectStyles( + cssRuleset: any, + _wrapperType: any, + _styleTagId: any, + inlineStyleMap: any + ) { if (cssRuleset) { - inject(`@media screen {${cssRuleset}}`, _wrapperType as any, _styleTagId); + inject( + `@media screen {${cssRuleset}}`, + _wrapperType as any, + _styleTagId, + inlineStyleMap + ); } } } diff --git a/packages/react/src/styled.tsx b/packages/react/src/styled.tsx index 301b16911..6488369ab 100644 --- a/packages/react/src/styled.tsx +++ b/packages/react/src/styled.tsx @@ -5,12 +5,12 @@ import type { OrderedSXResolved, StyleIds, ComponentProps, - UtilityProps, IVerbosedTheme, ITheme, ExtendedConfigType, IComponentStyleConfig, StyledConfig, + UtilityProps, } from './types'; import { deepMerge, @@ -837,7 +837,8 @@ export function verboseStyled( }; toBeInjected: any; styledIds: Array; - } + }, + nonVerbosedTheme?: any ) { // const componentName = componentStyleConfig?.componentName; const componentHash = stableHash({ @@ -906,7 +907,7 @@ export function verboseStyled( styleIds = BUILD_TIME_PARAMS?.verbosedStyleIds; } - function injectSx(sx: any, type: any = 'inline') { + function injectSx(sx: any, type: any = 'inline', inlineStyleMap?: any) { const inlineSxTheme = { baseStyle: sx, }; @@ -965,7 +966,8 @@ export function verboseStyled( sxHash, type, GluestackStyleSheet, - Platform.OS + Platform.OS, + inlineStyleMap ); return orderedSXResolved; @@ -996,7 +998,7 @@ export function verboseStyled( }: Omit< Omit & Partial> & - Partial> & { + Partial> & { as?: any; children?: any; }, @@ -1030,7 +1032,9 @@ export function verboseStyled( const sxCompoundVariantFlatternStyleObject = React.useRef({}); const sxDescendantFlattenStyles: any = React.useRef({}); - const COLOR_MODE: any = get(); + const COLOR_MODE: any = styledContext._experimentalNestedProvider + ? styledContext.colorMode + : get(); if (!styleHashCreated) { CONFIG = { @@ -1049,6 +1053,8 @@ export function verboseStyled( if (EXTENDED_THEME) { // RUN Middlewares + nonVerbosedTheme = deepMerge(nonVerbosedTheme, EXTENDED_THEME.theme); + const resolvedComponentExtendedTheme = resolveComponentTheme( CONFIG, EXTENDED_THEME @@ -1057,7 +1063,6 @@ export function verboseStyled( // const resolvedComponentExtendedTheme = EXTENDED_THEME; theme = deepMerge(theme, resolvedComponentExtendedTheme.theme); - // @ts-ignore Object.assign(themeDefaultProps, theme?.baseStyle?.props); if (Object.keys(EXTENDED_THEME?.BUILD_TIME_PARAMS ?? {}).length > 0) { @@ -1068,7 +1073,8 @@ export function verboseStyled( EXTENDED_THEME_BUILD_TIME_PARAMS?.verbosedStyleIds ); GluestackStyleSheet.inject( - EXTENDED_THEME_BUILD_TIME_PARAMS?.toBeInjected + EXTENDED_THEME_BUILD_TIME_PARAMS?.toBeInjected, + styledContext.inlineStyleMap ); } else { // Merge of Extended Config Style ID's with Component Style ID's @@ -1082,7 +1088,10 @@ export function verboseStyled( CONFIG, componentExtendedConfig ); - GluestackStyleSheet.inject(extendedStylesToBeInjected); + GluestackStyleSheet.inject( + extendedStylesToBeInjected, + styledContext.inlineStyleMap + ); } } @@ -1096,13 +1105,11 @@ export function verboseStyled( if (plugins) { for (const pluginName in plugins) { // @ts-ignore - [theme, , , Component] = plugins[pluginName]?.inputMiddleWare

( - theme, - true, - true, - Component - ); + [nonVerbosedTheme, , , Component] = plugins[ + pluginName + ]?.inputMiddleWare

(nonVerbosedTheme, true, true, Component); } + nonVerbosedTheme = convertStyledToStyledVerbosed(nonVerbosedTheme); } // for extended components end @@ -1131,12 +1138,18 @@ export function verboseStyled( componentExtendedConfig ); if (Platform.OS === 'web') { - GluestackStyleSheet.inject(toBeInjected); + GluestackStyleSheet.inject( + toBeInjected, + styledContext.inlineStyleMap + ); } } else { if (Platform.OS === 'web') { //@ts-ignore - GluestackStyleSheet.inject(BUILD_TIME_PARAMS.toBeInjected); + GluestackStyleSheet.inject( + BUILD_TIME_PARAMS.toBeInjected, + styledContext.inlineStyleMap + ); } } @@ -1185,7 +1198,7 @@ export function verboseStyled( const { variantProps: defaultVariantProps, - restProps: defaultComponentPropsWithoutVariants, + restProps: defaultThemePropsWithoutVariants, } = getVariantProps(themeDefaultProps, theme); const { @@ -1227,7 +1240,10 @@ export function verboseStyled( ); if (Platform.OS === 'web') { - GluestackStyleSheet.inject(toBeInjected); + GluestackStyleSheet.inject( + toBeInjected, + styledContext.inlineStyleMap + ); } isInjected = true; } @@ -1368,7 +1384,7 @@ export function verboseStyled( const defaultResolvedInlineProps = resolveInlineProps( componentStyleConfig, componentExtendedConfig, - defaultComponentPropsWithoutVariants, + defaultThemePropsWithoutVariants, CONFIG ); @@ -1388,17 +1404,19 @@ export function verboseStyled( const { sx: filteredComponentSx, rest: filteredComponentRemainingProps } = convertUtiltiyToSXFromProps( - Object.assign( - defaultComponentPropsWithoutVariants, - inlineComponentPropsWithoutVariants - ), + // Object.assign( + // defaultThemePropsWithoutVariants, + inlineComponentPropsWithoutVariants, styledSystemProps, componentStyleConfig ); let { sx: filteredPassingSx, rest: filteredPassingRemainingProps } = convertUtiltiyToSXFromProps( - shallowMerge({ ...passingProps }, applyAncestorPassingProps), + shallowMerge( + { ...defaultThemePropsWithoutVariants, ...passingProps }, + applyAncestorPassingProps + ), styledSystemProps, componentStyleConfig ); @@ -1430,11 +1448,19 @@ export function verboseStyled( function injectAndUpdateSXProps(filteredPassingSx: any) { if (Object.keys(filteredComponentSx).length > 0) { - orderedComponentSXResolved = injectSx(filteredComponentSx, 'inline'); + orderedComponentSXResolved = injectSx( + filteredComponentSx, + 'inline', + styledContext.inlineStyleMap + ); } if (Object.keys(filteredPassingSx).length > 0) { - orderedPassingSXResolved = injectSx(filteredPassingSx, 'passing'); + orderedPassingSXResolved = injectSx( + filteredPassingSx, + 'passing', + styledContext.inlineStyleMap + ); } const orderedSXResolved = [ @@ -1886,40 +1912,50 @@ export function verboseStyled( // } - if (plugins) { - // plugins?.reverse(); - plugins.reverse(); - for (const pluginName in plugins) { - // @ts-ignore - if (plugins[pluginName]?.componentMiddleWare) { + const ComponentWithPlugin = React.useMemo(() => { + if (plugins) { + for (const pluginName in plugins) { // @ts-ignore - Component = plugins[pluginName]?.componentMiddleWare({ - Component: Component, - theme, - componentStyleConfig, - ExtendedConfig, - }); + if (plugins[pluginName]?.componentMiddleWare) { + // @ts-ignore + Component = plugins[pluginName]?.componentMiddleWare({ + Component: Component, + theme, + componentStyleConfig, + ExtendedConfig, + }); - //@ts-ignore - pluginData = Component.styled; + //@ts-ignore + pluginData = { ...pluginData, ...Component?.styled }; + } } } - } + return Component; + }, []); let component; + const propsToBePassedInToPlugin = + plugins?.length > 0 + ? { + ...variantProps, + sx: componentProps.sx, + } + : {}; + if (AsComp) { //@ts-ignore if (Component.isStyledComponent) { component = ( - {children} - + ); } else { component = ( @@ -1930,9 +1966,14 @@ export function verboseStyled( } } else { component = ( - + {children} - + ); } @@ -1981,6 +2022,7 @@ export function styled( styledIds: Array; } ) { + const nonVerbosedTheme = theme; // const DEBUG_TAG = componentStyleConfig?.DEBUG; // const DEBUG = // process.env.NODE_ENV === 'development' && DEBUG_TAG ? false : false; @@ -2032,7 +2074,8 @@ export function styled( sxConvertedObject, componentStyleConfig, ExtendedConfig, - BUILD_TIME_PARAMS + BUILD_TIME_PARAMS, + nonVerbosedTheme ); // @ts-ignore diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 47301963f..019753f30 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -65,6 +65,7 @@ export interface Tokens { breakpoints?: { [key: GenericKey]: Record & {} }; mediaQueries?: { [key: GenericKey]: Record & {} }; letterSpacings?: { [key: GenericKey]: Record & {} }; + opacity?: { [key: GenericKey]: Record & {} }; lineHeights?: { [key: GenericKey]: any }; fontWeights?: { [key: GenericKey]: any }; fonts?: { [key: GenericKey]: any }; @@ -208,17 +209,7 @@ export type ExtendedConfigType = { /*********************** GLOBAL STYLE TYPES ****************************************/ export type GlobalVariantAliasesProps = - | RemoveNever<{ - [key in keyof Aliases]?: Aliases[key] extends keyof RNStyledProps - ? Aliases[key] extends keyof PropertyTokenType - ? PropertyTokenType[Aliases[key]] extends keyof Tokens - ? - | StringifyToken - | ExtendRNStyle - : never - : any - : any; - }> + | AliasesProps | RNStyledProps; export type GlobalVariantSx = Partial< @@ -795,10 +786,14 @@ export type ComponentProps = >[Key]; }); -export type UtilityProps = TokenizedRNStyleProps< - GetRNStyles +export type UtilityProps = Omit< + TokenizedRNStyleProps>, + keyof GenericComponentProps > & - AliasesProps>; + Omit< + AliasesProps>, + keyof GenericComponentProps + >; /********************* UTILITY TYPE *****************************************/ @@ -812,21 +807,30 @@ export type RemoveNever = { [K in FilteredKeys]: T[K]; }; +type WithNegativeValue = T extends string | number ? T | `-${T}` : T; // Mapping tokens with scale value of alaises -export type AliasesProps = RemoveNever<{ +export type AliasesProps< + GenericComponentStyles = RNStyledProps, + Aliases = GSConfig['aliases'], + Tokens = GSConfig['tokens'] +> = RemoveNever<{ [key in keyof Aliases]?: Aliases[key] extends keyof GenericComponentStyles - ? PropertyTokenType[Aliases[key]] extends 'sizes' + ? //@ts-expect-error + PropertyTokenType[Aliases[key]] extends 'sizes' ? - | StringifyToken< - keyof GSConfig['tokens'][PropertyTokenType[Aliases[key]]] - > - | StringifyToken + | WithSizeNegativeValue | ExtendRNStyle - : - | StringifyToken< - keyof GSConfig['tokens'][PropertyTokenType[Aliases[key]]] + : //@ts-expect-error + PropertyTokenType[Aliases[key]] extends 'space' + ? + | WithNegativeValue< + //@ts-expect-error + StringifyToken > | ExtendRNStyle + : //@ts-expect-error + | StringifyToken + | ExtendRNStyle : never; }>; @@ -887,15 +891,32 @@ export type ExtendRNStyle = : //@ts-ignore GenericComponentStyles[key]; -export type TokenizedRNStyleProps = { +type WithSizeNegativeValue = keyof Tokens extends 'sizes' + ? //@ts-expect-error + | StringifyToken + //@ts-expect-error + | StringifyToken + : //@ts-expect-error + StringifyToken; + +export type TokenizedRNStyleProps< + GenericComponentStyles, + Tokens = GSConfig['tokens'] +> = { [key in keyof GenericComponentStyles]?: key extends keyof PropertyTokenType ? PropertyTokenType[key] extends 'sizes' ? - | StringifyToken - | StringifyToken + | WithSizeNegativeValue + | ExtendRNStyle + : PropertyTokenType[key] extends 'space' + ? + | WithNegativeValue< + //@ts-expect-error + StringifyToken + > | ExtendRNStyle : //@ts-ignore - | StringifyToken + | StringifyToken | ExtendRNStyle : GenericComponentStyles[key]; }; diff --git a/packages/react/src/utils/css-injector/utils/inject.ts b/packages/react/src/utils/css-injector/utils/inject.ts index b0f316b8b..bba2b8ed5 100644 --- a/packages/react/src/utils/css-injector/utils/inject.ts +++ b/packages/react/src/utils/css-injector/utils/inject.ts @@ -5,13 +5,16 @@ type IWrapperType = | 'boot-descendant' | 'inline-descendant'; +export const WRAPPER_BLOCK_PREFIX = 'gs-injected'; + export const hasCss = (_id: any, _text: any) => {}; export const addCss = (_id: any, _text: any) => {}; export const injectCss = ( _css: any, _wrapperType: IWrapperType, - _styleTagId: string + _styleTagId: string, + _inlineStyleMap?: any ) => {}; export const injectGlobalCss = ( _css: any, diff --git a/packages/react/src/utils/css-injector/utils/inject.web.ts b/packages/react/src/utils/css-injector/utils/inject.web.ts index 8fa26f04a..443e50719 100644 --- a/packages/react/src/utils/css-injector/utils/inject.web.ts +++ b/packages/react/src/utils/css-injector/utils/inject.web.ts @@ -117,7 +117,8 @@ const createStyle = (styleTagId: any, css: any) => { export const injectCss = ( css: any, wrapperType: IWrapperType, - styleTagId: string + styleTagId: string, + inlineStyleMap?: any ) => { // let modifiedStylesheet = {} as any; if (!toBeFlushedStyles[wrapperType]) { @@ -138,8 +139,23 @@ export const injectCss = ( if (!style) { style = createStyle(styleTagId, css); - // wrapperElement.insertBefore(style, wrapperElement.firstChild); - wrapperElement.appendChild(style); + // console.log(inlineStyleMap, 'append child here >>>>>'); + if (inlineStyleMap) { + if (!inlineStyleMap?.initialStyleInjected) { + const styleMapId = `${WRAPPER_BLOCK_PREFIX}-${wrapperType}`; + const inlineMapStyles = inlineStyleMap[styleMapId]; + + if (inlineMapStyles) { + inlineMapStyles.push(style); + } else { + inlineStyleMap[styleMapId] = [style]; + } + // console.log('hello here >>>> there'); + } else { + // console.log('hello here >>>>'); + wrapperElement.appendChild(style); + } + } } } } diff --git a/yarn.lock b/yarn.lock index 5a435166e..6344fb3de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2606,28 +2606,7 @@ "@babel/traverse" "^7.20.5" lodash.merge "^4.6.2" -"@gluestack-style/babel-plugin-styled-resolver@^0.1.6": - version "0.1.14" - resolved "https://registry.yarnpkg.com/@gluestack-style/babel-plugin-styled-resolver/-/babel-plugin-styled-resolver-0.1.14.tgz#1e3cd2dbdf91b5e9dcb8d34ab7df7aed1beea9bb" - integrity sha512-fgfuvCTngRZIbZf5prtoiZeOBaMtjEh4EJUIJygHY6iXscFuU6tnstnMnHqZdCd1dty+2E1DuwnG+JSKfYgYmA== - dependencies: - "@babel/core" "^7.20.5" - "@babel/generator" "^7.20.5" - "@babel/parser" "^7.20.5" - "@babel/plugin-transform-typescript" "^7.20.2" - "@babel/preset-typescript" "^7.18.6" - "@babel/traverse" "^7.20.5" - lodash.merge "^4.6.2" - -"@gluestack-style/react@^0.1.33": - version "0.1.33" - resolved "https://registry.yarnpkg.com/@gluestack-style/react/-/react-0.1.33.tgz#cd18f38bf359527e4f79d223bb07e9024f40ba4f" - integrity sha512-wBdoOA3i/cp0EcgJnwJgL1a8BATjbX/pCZgWm31N6sZOgCB4Phq7m0bDjfSpeJ8sKpOEDlUP5wYCo7Yww0mbqA== - dependencies: - inline-style-prefixer "^6.0.1" - normalize-css-color "^1.0.2" - -"@gluestack-style/react@^0.2.11-alpha.0", "@gluestack-style/react@^0.2.16", "@gluestack-style/react@^0.2.21", "@gluestack-style/react@^0.2.49": +"@gluestack-style/react@^0.2.16", "@gluestack-style/react@^0.2.21": version "0.2.51" resolved "https://registry.yarnpkg.com/@gluestack-style/react/-/react-0.2.51.tgz#0cfcca4f97f908ed3a352bd7e2336d436cc22415" integrity sha512-21TLr+e7KneP8N1d1iMKG6npMdYb/oPN/t5KZ/2kns2mg9NVCrfVmVuuMYKo+Xcej95BFOHuGuomskzLwdK1HQ==