diff --git a/example/storybook/.storybook/preview.js b/example/storybook/.storybook/preview.js index a26271065..4282a98eb 100644 --- a/example/storybook/.storybook/preview.js +++ b/example/storybook/.storybook/preview.js @@ -50,7 +50,7 @@ export const parameters = { 'configuration', [ 'Theme Tokens', - // 'Themes', + 'Themes', 'Breakpoints', 'Global Style', 'Customizing Components', diff --git a/example/storybook/babel.config.js b/example/storybook/babel.config.js index fcaaa8d92..b27308285 100644 --- a/example/storybook/babel.config.js +++ b/example/storybook/babel.config.js @@ -39,6 +39,7 @@ module.exports = function (api) { }, ] : ['babel-plugin-react-docgen-typescript', { exclude: 'node_modules' }], + '@babel/plugin-transform-modules-commonjs', ], }; }; diff --git a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx index 000b77608..3e8c6b700 100644 --- a/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx +++ b/example/storybook/src/api/DescendantsStyles/ContextBasedStyles.tsx @@ -13,181 +13,91 @@ import { StyleSheet, View, } from 'react-native'; -import { AsForwarder, styled } from '@gluestack-style/react'; +import { AsForwarder, styled, Theme } from '@gluestack-style/react'; import { Wrapper } from '../../components/Wrapper'; // import { AddIcon } from '@gluestack/design-system'; -import { createIcon } from '@gluestack-ui/icon'; -import { Svg } from 'react-native-svg'; -import { FlatList } from 'react-native'; -import { StyledText, StyledView } from '../AsForwarder/AsForwarder'; -// const Box = styled(View, { -// bg: '$backgroundDark300', -// width: '200px', -// height: '100px', -// }); - -const Text = styled( - RNText, - { - // bg: '$amber300', - // color: '$red500', - // props: { - // color: '$pink400', - // }, - // variants: { - // variant: { - // solid: { - // color: '$green500', - // }, - // }, - // }, - }, - { - componentName: 'TEXT', - } -); -const MyPressable = styled( +const Pressable = styled( RNPressable, { - bg: '$red500', - // height: 40, - // p: 2, - // // props: { - // // color: '$purple500', - // // }, - // variants: { - // variant: { - // solid: { - // bg: '$red400', - // }, - // }, - // }, - // defaultProps: { - // variant: 'solid', - // }, + 'bg': '$red500', + // 'bg': '$red600', + 'w': 100, + 'h': 100, + '_light': { + bg: '$red600', + }, + '@base': { + bg: '$blue500', + }, + ':hover': { + bg: '$red500', + }, }, { - componentName: 'BOX', + componentName: 'Pressable', + descendantStyle: ['_text'], } ); -const Box = styled( - View, - { - variants: { - variant: {}, - }, - // bg: '$red500', - // height: 40, - // p: 2, - // // props: { - // // color: '$purple500', - // // }, - // variants: { - // variant: { - // solid: { - // bg: '$red400', - // }, - // }, - // }, - // defaultProps: { - // variant: 'solid', - // }, - }, +const Text = styled( + RNText, + {}, { - componentName: 'BOX2', - descendantStyle: ['_text'], + componentName: 'Text', } ); export function ContextBasedStyles() { return ( - + ); } -const MyFlatList = styled( - FlatList, - {}, - { - componentName: 'MyFlatList', - } -); -const styleshet = StyleSheet.create({ - style: { - backgroundColor: 'blue', - padding: 2, - height: 40, - }, -}); export function ContextBasedStylesContent() { - const timeTaken = useRef(Date.now()); - // useEffect(() => { - // console.log(Date.now() - timeTaken.current, 'hello'); - // }, []); - - const [state, setState] = useState(true); - - const handlePress = useCallback(() => { - timeTaken.current = Date.now(); - setState(!state); - }, [state]); - - // const layoutChange = () => {}; - - // useEffect(() => { - // console.log(Date.now() - timeTaken.current, 'hello'); - // }); + // return ; - // useEffect(() => { - // console.log(Date.now() - timeTaken.current, 'hello'); - // }, [state]); + const [tabName, setTabName] = useState(true); - const DATA = [ - { - id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', - title: 'First Item', - }, - { - id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', - title: 'Second Item', - }, - { - id: '58694a0f-3da1-471f-bd96-145571e29d72', - title: 'Third Item', - }, - ]; + const handleTabChange = (tabName: any) => { + setTabName(tabName); + }; + // const color = tabName ? '$red500' : '$green500'; return ( - { - return ( - - Hello - - ); - }} - keyExtractor={(item, index) => 'key' + index} - ItemSeparatorComponent={() => } - /> + <> + {/* + + + */} + + handleTabChange(tabName)} + onPress={() => { + handleTabChange(!tabName); + }} + bg="$amber400" + h="$50" + w="$50" + > + + hello world + + + ); - // return ; - return hello; - return ( <> - -import { styled, StyledProvider } from '@gluestack-style/react'; +import { styled, StyledProvider, Theme } from '@gluestack-style/react'; import { Pressable, Text as RNText, View } from 'react-native'; import { Button, AppProvider, CodePreview } from '@gluestack/design-system'; -import { config } from './config'; import { useState } from 'react'; +import { config } from './config'; +import { Canvas, Meta, Story } from '@storybook/addon-docs'; + + # Themes @@ -24,13 +23,14 @@ import { useState } from 'react'; metaData={{ scope: { styled, - Text, View, RNText, Pressable, + Theme, Provider: StyledProvider, - config: config(), + config: config, useState, + Theme, }, code: ` function App() { @@ -66,10 +66,8 @@ import { useState } from 'react'; ); const Box = styled(View, {}); const Text = styled(RNText, { color: '$textColor' }); - const [theme, setTheme] = React.useState('2000s'); - const themes = ['2000s', '2010s', '2020s']; return ( - + - Explorer from {theme} + Explorer x - - {themes.map((themeName) => ( - setTheme(themeName)} - size="sm" - bg={themeName !== theme ? '$backgroundDark300' : '$green400'} - > - {themeName} - - ))} - ); @@ -174,21 +160,20 @@ export const config = createConfig({ // ... }, // ... - themes: { - classic:{ - colors: { - $primary: '$colors.$brown400', - $secondary: '$colors.$brown100', - }, + }, + themes: { + classic: { + colors: { + $primary: '$colors.$brown400', + $secondary: '$colors.$brown100', }, - modern:{ - colors: { - $primary: '$colors.$red400', - $secondary: '$colors.$red100', - }, + }, + modern: { + colors: { + $primary: '$colors.$red400', + $secondary: '$colors.$red100', }, - } - } + }, }, }); ``` @@ -199,6 +184,8 @@ Now you have your themes defined, you can use them in your app. How to use it yo To use a theme you need to import the `Theme` component from `@gluestack-style/react` package. **Theme** component accepts a `name` prop which is the name of the theme you want to use. +> **Important**: `Theme` adds a View to the DOM tree. + ```tsx import { styled, StyledProvider, Theme } from '@gluestack-style/react'; import { Pressable } from 'react-native'; diff --git a/example/ui-examples/App.tsx b/example/ui-examples/App.tsx index 73ce4b0ac..4ce985021 100644 --- a/example/ui-examples/App.tsx +++ b/example/ui-examples/App.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { SafeAreaView, StyleSheet, - View, + // View, // View } from 'react-native'; import { GluestackUIProvider } from './gluestack-ui-components'; @@ -18,14 +18,14 @@ import { Inter_900Black, } from '@expo-google-fonts/inter'; import './styles'; -import { styled } from '@gluestack-style/react'; +// import { styled } from '@gluestack-style/react'; import HomestayPage from './kitchensink-components/HomestayPage'; -const Box = styled(View, { - bg: '$primary100', - h: '$10', - w: '$10', -}); +// const Box = styled(View, { +// bg: '$primary100', +// h: '$10', +// w: '$10', +// }); type ThemeContextType = { colorMode?: 'dark' | 'light'; diff --git a/example/ui-examples/gluestack-ui-components/core/Heading/styled-components/Root.tsx b/example/ui-examples/gluestack-ui-components/core/Heading/styled-components/Root.tsx index 9b6b65413..36ef31930 100644 --- a/example/ui-examples/gluestack-ui-components/core/Heading/styled-components/Root.tsx +++ b/example/ui-examples/gluestack-ui-components/core/Heading/styled-components/Root.tsx @@ -1,7 +1,7 @@ // import { styled } from '../../styled'; import { styled } from '@gluestack-style/react'; -import { H1, H2, H3, H4, H5, H6 } from '@expo/html-elements'; +import { H1 } from '@expo/html-elements'; export default styled(H1, { color: '$textLight900', letterSpacing: '$sm', diff --git a/packages/animation-plugin/package.json b/packages/animation-plugin/package.json index 6914a4956..28f1d811e 100644 --- a/packages/animation-plugin/package.json +++ b/packages/animation-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@gluestack-style/animation-plugin", - "version": "0.1.7", + "version": "0.1.8", "description": "A gluestack-style plugin for animation properties, utilizing animation libraries.", "keywords": [ "react", diff --git a/packages/react/package.json b/packages/react/package.json index a6d318d7b..e199c9a81 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": "0.2.22", + "version": "0.2.25", "keywords": [ "React Native", "Next.js", diff --git a/packages/react/src/createConfig.ts b/packages/react/src/createConfig.ts index c80c39bda..5aad9322b 100644 --- a/packages/react/src/createConfig.ts +++ b/packages/react/src/createConfig.ts @@ -1,10 +1,25 @@ import type { GlueStackConfig } from './types'; import { convertStyledToStyledVerbosed } from './convertSxToSxVerbosed'; -// import { resolveStringToken } from './utils'; +import { resolveStringToken } from './utils'; import { stableHash } from './stableHash'; import { propertyTokenMap } from './propertyTokenMap'; import { updateOrderUnResolvedMap } from './updateOrderUnResolvedMap'; + +var globalPluginStore: any = []; + +function setGlobalPluginStore(plugins: Array) { + globalPluginStore.push(...plugins); +} + +function getGlobalPluginStore() { + return globalPluginStore; +} + +export function getInstalledPlugins() { + return getGlobalPluginStore(); +} + export const createConfig = < T extends GlueStackConfig< //@ts-ignore @@ -22,10 +37,15 @@ export const createConfig = < T['globalStyle'] > ): T => { + if (config.plugins) { + setGlobalPluginStore(config.plugins); + } + delete config.plugins; + if ( - !config.components + !config.components && // @ts-ignore - // && !config.themes + !config.themes ) { return config as any; } @@ -33,37 +53,38 @@ export const createConfig = < if (config.components) { newConfig = resolveComponentThemes(config); } + // @ts-ignore - // if (config.themes) { - // const newConfigWithThemesResolved = resolveThemes(newConfig); - // return newConfigWithThemesResolved as any; - // } + if (config.themes) { + const newConfigWithThemesResolved = resolveThemes(newConfig); + return newConfigWithThemesResolved as any; + } return newConfig as any; }; -// const resolveThemes = (config: any) => { -// const newConfig = { ...config }; -// Object.keys(newConfig?.themes ?? {}).forEach((themeName: any) => { -// let theme = newConfig.themes[themeName]; -// Object.keys(theme).forEach((tokenScale: any) => { -// const tokenScaleValue = theme[tokenScale]; -// Object.keys(tokenScaleValue).forEach((token: any) => { -// const tokenValue = resolveStringToken( -// tokenScaleValue[token], -// newConfig, -// tokenScale, -// '' -// ); -// tokenScaleValue[token] = tokenValue; -// }); -// }); -// // const tempCONFIG = JSON.parse(JSON.stringify(newConfig)); -// // delete tempCONFIG.themes; -// // deepMerge(tempCONFIG, { tokens: { ...theme } }); -// // newConfig.themes[themeName] = tempCONFIG; -// }); -// return newConfig; -// }; +const resolveThemes = (config: any) => { + const newConfig = { ...config }; + Object.keys(newConfig?.themes ?? {}).forEach((themeName: any) => { + let theme = newConfig.themes[themeName]; + Object.keys(theme).forEach((tokenScale: any) => { + const tokenScaleValue = theme[tokenScale]; + Object.keys(tokenScaleValue).forEach((token: any) => { + const tokenValue = resolveStringToken( + tokenScaleValue[token], + newConfig, + tokenScale, + '' + ); + tokenScaleValue[token] = tokenValue; + }); + }); + // const tempCONFIG = JSON.parse(JSON.stringify(newConfig)); + // delete tempCONFIG.themes; + // deepMerge(tempCONFIG, { tokens: { ...theme } }); + // newConfig.themes[themeName] = tempCONFIG; + }); + return newConfig; +}; const resolveComponentThemes = (config: any) => { const newConfig = { ...config }; diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index ef38a43a1..44e251821 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -57,7 +57,7 @@ export { styled, verboseStyled, resolveBuildTimeSx } from './styled'; export { StyledProvider, useStyled } from './StyledProvider'; -// export { Theme, useTheme } from './Theme'; +export { Theme, useTheme } from './Theme'; export { styledToStyledResolved } from './resolver/styledResolved'; export { styledResolvedToOrderedSXResolved } from './resolver/orderedResolved'; export { flush } from './injectInStyle'; diff --git a/packages/react/src/style-sheet/index.ts b/packages/react/src/style-sheet/index.ts index 3dee85272..fea02251a 100644 --- a/packages/react/src/style-sheet/index.ts +++ b/packages/react/src/style-sheet/index.ts @@ -4,7 +4,7 @@ import { getCSSIdAndRuleset } from '../updateCSSStyleInOrderedResolved.web'; import { deepMerge, resolveTokensFromConfig, - // addThemeConditionInMeta, + addThemeConditionInMeta, } from '../utils'; import { inject } from '../utils/css-injector'; export type DeclarationType = 'boot' | 'forwarded'; @@ -130,7 +130,7 @@ export class StyleInjector { theme, componentExtendedConfig ); - // addThemeConditionInMeta(componentTheme, CONFIG); + addThemeConditionInMeta(componentTheme, CONFIG); // delete componentTheme.meta.cssRuleset; diff --git a/packages/react/src/styled.tsx b/packages/react/src/styled.tsx index 402536b04..f5e8f9f39 100644 --- a/packages/react/src/styled.tsx +++ b/packages/react/src/styled.tsx @@ -925,34 +925,34 @@ export function verboseStyled( componentExtendedConfig ); - // let componentTheme: any = - // // @ts-ignore - // sxStyledResolved.baseStyle.styledValueResolvedWithMeta; + let componentTheme: any = + // @ts-ignore + sxStyledResolved.baseStyle.styledValueResolvedWithMeta; // sxStyledResolved.baseStyle.styledValueResolvedWithMeta = - // addThemeConditionInMeta(componentTheme, CONFIG); - - // const colorModeComponentThemes: any = sxStyledResolved.baseStyle?.colorMode; - // if (colorModeComponentThemes) { - // Object.keys(colorModeComponentThemes).forEach( - // (colorModeComponentTheme: any) => { - // if ( - // !colorModeComponentThemes[colorModeComponentTheme] - // .styledValueResolvedWithMeta?.meta.themeCondition - // ) { - // colorModeComponentThemes[ - // colorModeComponentTheme - // ].styledValueResolvedWithMeta.meta.themeCondition = {}; - // } - - // let componentTheme: any = - // colorModeComponentThemes[colorModeComponentTheme] - // .styledValueResolvedWithMeta; - - // addThemeConditionInMeta(componentTheme, CONFIG); - // } - // ); - // } + addThemeConditionInMeta(componentTheme, CONFIG); + + const colorModeComponentThemes: any = sxStyledResolved.baseStyle?.colorMode; + if (colorModeComponentThemes) { + Object.keys(colorModeComponentThemes).forEach( + (colorModeComponentTheme: any) => { + if ( + !colorModeComponentThemes[colorModeComponentTheme] + .styledValueResolvedWithMeta?.meta.themeCondition + ) { + colorModeComponentThemes[ + colorModeComponentTheme + ].styledValueResolvedWithMeta.meta.themeCondition = {}; + } + + let componentTheme: any = + colorModeComponentThemes[colorModeComponentTheme] + .styledValueResolvedWithMeta; + + addThemeConditionInMeta(componentTheme, CONFIG); + } + ); + } const sxHash = stableHash(sx); @@ -1392,6 +1392,11 @@ export function verboseStyled( let mergedSxDescendantsStyle: any = {}; let mergedDescendantsStyle: any = {}; + const applySxStateBaseStyleCSSIds = useRef(mergedSXBaseStyleCSSIds); + const applySxDescendantStateStyleCSSIdsAndPropsWithKey = useRef( + mergedSxDescendantsStyle + ); + if (!isClient.current) { isClient.current = true; const { @@ -1425,14 +1430,76 @@ export function verboseStyled( mergedBaseStyleCSSIds = a; mergedVariantStyleCSSIds = b; stateProps = c; - mergedSXBaseStyleCSSIds = d; + applySxStateBaseStyleCSSIds.current = d; + mergedSXVariantStyleCSSIds = e; mergedSxStateProps = f; - mergedSxDescendantsStyle = g; + // mergedSxDescendantsStyle = g; + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current = g; // setComponentStatePassingProps(stateProps); // setSxStatePassingProps(mergedSxStateProps); mergedDescendantsStyle = h; + } else { + //TODO: start: refactor for sx state + colormode + dynamic variable + // for sx state props + + // MUST REFACTOR: setStateAndColorModeCssIdsAndProps + const { + baseStyleCSSIds: mergedSXBaseStyleCSSIds, + variantStyleCSSIds: mergedSXVariantStyleCSSIds, + passingProps: mergedSxStateProps, + }: any = getMergedStateAndColorModeCSSIdsAndProps( + sxComponentStyleIds.current, + //@ts-ignore + sxBaseStyleFlatternStyleObject, + states, + variantProps, + COLOR_MODE, + theme, + sxVariantFlatternStyleObject, + sxCompoundVariantFlatternStyleObject + ); + applySxStateBaseStyleCSSIds.current = mergedSXBaseStyleCSSIds; + + const mergedSxDescendantsStyle: any = {}; + if (sxDescendantStyleIds.current) { + Object.keys(sxDescendantStyleIds.current).forEach((key) => { + const { + baseStyleCSSIds: sxDescendantBaseStyleCSSIds, + variantStyleCSSIds: sxDescendantVariantStyleCSSIds, + passingProps: mergedPassingProps, + } = getMergedStateAndColorModeCSSIdsAndProps( + //@ts-ignore + sxDescendantStyleIds.current, + sxDescendantFlattenStyles[key]?.[ + 'componentBaseStyleFlatternStyleIdObject' + ], + states, + variantProps, + COLOR_MODE, + theme, + sxDescendantFlattenStyles[key]?.[ + 'componentVariantFlatternStyleIdObject' + ], + sxDescendantFlattenStyles[key]?.[ + 'componentCompoundVariantFlatternStyleIdObject' + ] + ); + + mergedSxDescendantsStyle[key] = { + baseStyleCSSIds: sxDescendantBaseStyleCSSIds, + variantStyleCSSIds: sxDescendantVariantStyleCSSIds, + passingProps: mergedPassingProps, + }; + }); + + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current = + mergedSxDescendantsStyle; + } + // MUST REFACTOR END: setStateAndColorModeCssIdsAndProps + + //TODO: end: refactor for sx state + colormode + dynamic variable } const [ @@ -1444,19 +1511,21 @@ export function verboseStyled( setApplyComponentStateVariantStyleIds, ] = useState(mergedVariantStyleCSSIds); - const [applySxStateBaseStyleCSSIds, setApplyStateSxBaseStyleCSSIds] = - useState(mergedSXBaseStyleCSSIds); - const [applySxStateVariantStyleCSSIds, setApplyStateSxVariantStyleCSSIds] = - useState(mergedSXVariantStyleCSSIds); + // const [applySxStateBaseStyleCSSIds, setApplyStateSxBaseStyleCSSIds] = + // useState(mergedSXBaseStyleCSSIds); + + // const [applySxStateVariantStyleCSSIds, setApplyStateSxVariantStyleCSSIds] = + // useState(mergedSXVariantStyleCSSIds); + const applySxStateVariantStyleCSSIds = useRef(mergedSXVariantStyleCSSIds); const [ applyDescendantStateStyleCSSIdsAndPropsWithKey, setApplyDescendantStateStyleCSSIdsAndPropsWithKey, ] = useState(mergedDescendantsStyle); - const [ - applySxDescendantStateStyleCSSIdsAndPropsWithKey, - setApplySxDescendantStateStyleCSSIdsAndPropsWithKey, - ] = useState(mergedSxDescendantsStyle); + // const [ + // applySxDescendantStateStyleCSSIdsAndPropsWithKey, + // setApplySxDescendantStateStyleCSSIdsAndPropsWithKey, + // ] = useState(mergedSxDescendantsStyle); // START: Unable to optimize because of useEffect overhead and stableHash to prevent rerender useEffect(() => { @@ -1493,15 +1562,19 @@ export function verboseStyled( setApplyComponentStateBaseStyleIds(mergedBaseStyleCSSIds); setApplyComponentStateVariantStyleIds(mergedVariantStyleCSSIds); setComponentStatePassingProps(stateProps); - setApplyStateSxBaseStyleCSSIds(mergedSXBaseStyleCSSIds); - setApplyStateSxVariantStyleCSSIds(mergedSXVariantStyleCSSIds); + applySxStateBaseStyleCSSIds.current = mergedSXBaseStyleCSSIds; + // setApplyStateSxBaseStyleCSSIds(); + applySxStateVariantStyleCSSIds.current = mergedSXVariantStyleCSSIds; + // setApplyStateSxVariantStyleCSSIds(mergedSXVariantStyleCSSIds); setSxStatePassingProps(mergedSxStateProps); setApplyDescendantStateStyleCSSIdsAndPropsWithKey( mergedDescendantsStyle ); - setApplySxDescendantStateStyleCSSIdsAndPropsWithKey( - mergedSxDescendantsStyle - ); + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current = + mergedSxDescendantsStyle; + // setApplySxDescendantStateStyleCSSIdsAndPropsWithKey( + // mergedSxDescendantsStyle + // ); }); // remove onchage listener on unmount () => @@ -1560,15 +1633,19 @@ export function verboseStyled( setApplyComponentStateBaseStyleIds(mergedBaseStyleCSSIds); setApplyComponentStateVariantStyleIds(mergedVariantStyleCSSIds); setComponentStatePassingProps(stateProps); - setApplyStateSxBaseStyleCSSIds(mergedSXBaseStyleCSSIds); - setApplyStateSxVariantStyleCSSIds(mergedSXVariantStyleCSSIds); + applySxStateBaseStyleCSSIds.current = mergedSXBaseStyleCSSIds; + // setApplyStateSxBaseStyleCSSIds(mergedSXBaseStyleCSSIds); + applySxStateVariantStyleCSSIds.current = mergedSXVariantStyleCSSIds; + // setApplyStateSxVariantStyleCSSIds(mergedSXVariantStyleCSSIds); setSxStatePassingProps(mergedSxStateProps); setApplyDescendantStateStyleCSSIdsAndPropsWithKey( mergedDescendantsStyle ); - setApplySxDescendantStateStyleCSSIdsAndPropsWithKey( - mergedSxDescendantsStyle - ); + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current = + mergedSxDescendantsStyle; + // setApplySxDescendantStateStyleCSSIdsAndPropsWithKey( + // mergedSxDescendantsStyle + // ); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [states]); @@ -1582,7 +1659,7 @@ export function verboseStyled( if ( applyDescendantsStyleCSSIdsAndPropsWithKey || applyDescendantStateStyleCSSIdsAndPropsWithKey || - applySxDescendantStateStyleCSSIdsAndPropsWithKey || + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current || applySxDescendantStyleCSSIdsAndPropsWithKey || ancestorStyleContext ) { @@ -1590,7 +1667,7 @@ export function verboseStyled( applyDescendantsStyleCSSIdsAndPropsWithKey, applyDescendantStateStyleCSSIdsAndPropsWithKey, applySxDescendantStyleCSSIdsAndPropsWithKey.current, - applySxDescendantStateStyleCSSIdsAndPropsWithKey, + applySxDescendantStateStyleCSSIdsAndPropsWithKey.current, ancestorStyleContext ); } else { @@ -1601,7 +1678,7 @@ export function verboseStyled( }, [ stableHash(applyDescendantsStyleCSSIdsAndPropsWithKey), stableHash(applyDescendantStateStyleCSSIdsAndPropsWithKey), - stableHash(applySxDescendantStateStyleCSSIdsAndPropsWithKey), + stableHash(applySxDescendantStateStyleCSSIdsAndPropsWithKey.current), ancestorStyleContext, ]); @@ -1617,11 +1694,10 @@ export function verboseStyled( ...applyComponentStateBaseStyleIds, ...applyComponentStateVariantStyleIds, ...applySxVariantStyleCSSIds.current, - ...applySxStateVariantStyleCSSIds, + ...applySxStateVariantStyleCSSIds.current, ...applySxBaseStyleCSSIds.current, - ...applySxStateBaseStyleCSSIds, + ...applySxStateBaseStyleCSSIds.current, ]; - Object.assign(resolvedInlineProps, applyComponentInlineProps); const resolvedStyleProps = generateStylePropsFromCSSIds( resolvedInlineProps, diff --git a/packages/react/src/types.ts b/packages/react/src/types.ts index 19888d2ee..aa10d6aeb 100644 --- a/packages/react/src/types.ts +++ b/packages/react/src/types.ts @@ -63,6 +63,11 @@ export type CreateConfig = { globalStyle?: CreateGenericConfig['globalStyle']; }; +export type ThemeStyles = { + // @ts-ignore + [key: string]: Tokens; +}; + // Generic Creator export type GlueStackConfig< IToken extends Tokens, @@ -72,6 +77,8 @@ export type GlueStackConfig< tokens: IToken; aliases: IGlobalAliases; globalStyle?: GlobalStyles; + plugins?: Array; + themes?: ThemeStyles; components?: { [key: string]: { theme: Partial>; diff --git a/packages/react/src/updateCSSStyleInOrderedResolved.web.ts b/packages/react/src/updateCSSStyleInOrderedResolved.web.ts index 365e1d6fd..229297967 100644 --- a/packages/react/src/updateCSSStyleInOrderedResolved.web.ts +++ b/packages/react/src/updateCSSStyleInOrderedResolved.web.ts @@ -28,12 +28,12 @@ export function getCSSIdAndRuleset( toBeInjectedStyle.colorMode = styleValueResolvedWithMeta.meta.colorMode; } // @ts-ignore - // if (styleValueResolvedWithMeta.meta.themeCondition) { - // // @ts-ignore - // toBeInjectedStyle.themeCondition = - // // @ts-ignore - // styleValueResolvedWithMeta.meta.themeCondition; - // } + if (styleValueResolvedWithMeta.meta.themeCondition) { + // @ts-ignore + toBeInjectedStyle.themeCondition = + // @ts-ignore + styleValueResolvedWithMeta.meta.themeCondition; + } //@ts-ignore const cssObject = Cssify.create( diff --git a/packages/react/src/utils/cssify/create-stylesheet/index.ts b/packages/react/src/utils/cssify/create-stylesheet/index.ts index b486819db..c29d03f7d 100644 --- a/packages/react/src/utils/cssify/create-stylesheet/index.ts +++ b/packages/react/src/utils/cssify/create-stylesheet/index.ts @@ -17,12 +17,7 @@ const createStyleSheet = ( Object.keys(stylesObject).map((key) => { if (!stylesObject?.[key]) return; - let { - condition, - colorMode, - style, - // themeCondition - } = stylesObject[key]; + let { condition, colorMode, style, themeCondition } = stylesObject[key]; const mediaQuery = createQuery(condition); @@ -32,13 +27,13 @@ const createStyleSheet = ( const css = createDeclarationBlock(style); - // const themeCssObj = {} as any; - // if (themeCondition) { - // Object.keys(themeCondition).forEach((themeName) => { - // const themeConditionValue = themeCondition[themeName]; - // themeCssObj[themeName] = createDeclarationBlock(themeConditionValue); - // }); - // } + const themeCssObj = {} as any; + if (themeCondition) { + Object.keys(themeCondition).forEach((themeName) => { + const themeConditionValue = themeCondition[themeName]; + themeCssObj[themeName] = createDeclarationBlock(themeConditionValue); + }); + } // console.log(css, style, 'css', mediaQuery, 'mediaQuery', colorSchemeQuery); // const stringHash = `cssinjected-${hash(`${key}${css}`)}`; @@ -52,13 +47,11 @@ const createStyleSheet = ( 'style', prefixClassName, prefixColorMode, - hasState - // themeCondition, - // themeCssObj + hasState, + themeCondition, + themeCssObj ); - // console.log('hello css object', colorSchemeQuery, css, rule); - delete cleanStyles[key]; ids = { diff --git a/packages/react/src/utils/cssify/utils/common.ts b/packages/react/src/utils/cssify/utils/common.ts index c9c20998b..975bcdab0 100644 --- a/packages/react/src/utils/cssify/utils/common.ts +++ b/packages/react/src/utils/cssify/utils/common.ts @@ -103,27 +103,43 @@ const createCssRule = ( dataType: string, prefixClassName: string, prefixColorMode: string, - hasState: boolean + hasState: boolean, + themeCondition: any, + themeCssObj: any ) => { const dataMediaSelector = `[data-${dataType}~="${stringHash}"]`; const stateRulePrefix = hasState ? '.gs' : ''; const inlineRulePrefix = prefixClassName ? `.${prefixClassName}` : ''; - const colorModeRulePrefix = prefixColorMode - ? `.${prefixColorMode}${colorMode}` - : ''; + const colorModeRulePrefix = + prefixColorMode && colorMode ? `.${prefixColorMode}${colorMode}` : ''; const mediaQueryPrefix = `.gs`; const inlineAndStatePrefix = `${inlineRulePrefix}${stateRulePrefix}`; - + let rule = ``; if (isMedia(mediaQuery) && isColorScheme(colorSchemeQuery)) { - return `${mediaQuery} {${mediaQueryPrefix}${inlineAndStatePrefix}${colorModeRulePrefix} ${dataMediaSelector} ${css}}`; + rule = `${mediaQuery} {${mediaQueryPrefix}${inlineAndStatePrefix}${colorModeRulePrefix} ${dataMediaSelector} ${css}}`; } else if (isMedia(mediaQuery)) { - return `${mediaQuery} {${mediaQueryPrefix}${inlineAndStatePrefix} ${dataMediaSelector} ${css}}`; + rule = `${mediaQuery} {${mediaQueryPrefix}${inlineAndStatePrefix} ${dataMediaSelector} ${css}}`; } else if (isColorScheme(colorSchemeQuery)) { - return `${inlineAndStatePrefix}${colorModeRulePrefix} ${dataMediaSelector} ${css}`; + rule = `${inlineAndStatePrefix}${colorModeRulePrefix} ${dataMediaSelector} ${css}`; } else { - return `${inlineAndStatePrefix} ${dataMediaSelector}${mediaQuery} ${css}`; + rule = `${inlineAndStatePrefix} ${dataMediaSelector}${mediaQuery} ${css}`; + } + + if (themeCondition) { + const themeConditionString = Object.keys(themeCondition) + .map((themeName) => { + return ` + [data-theme-id~="${themeName}"] ${dataMediaSelector} ${themeCssObj[themeName]} + ${inlineAndStatePrefix} [data-theme-id~="${themeName}"] ${dataMediaSelector} ${themeCssObj[themeName]} + ${colorModeRulePrefix}${inlineAndStatePrefix} [data-theme-id~="${themeName}"] ${dataMediaSelector} ${themeCssObj[themeName]} + `; + }) + .join('\n'); + // themeCondition is of higher specificity than the rest of the rules + rule = ` \n${themeConditionString}\n ${rule} `; } + return rule; }; function createQuery(condition: any) { diff --git a/yarn.lock b/yarn.lock index 50016b241..f186a0857 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2535,13 +2535,20 @@ resolved "https://registry.yarnpkg.com/@gluestack-ui/alert/-/alert-0.1.8.tgz#f9d6b6c7a2fcdc03d02edb02c11cc4c4a18fa894" integrity sha512-zDUdaAUgILeWBJhF/Ub6np35u8U0T79xsLKZl22CmH17bUHuIu1cXaiqJhGnofV/YwRv6xDIPaOXwuhaK5IoAg== -"@gluestack-ui/avatar@^0.1.6", "@gluestack-ui/avatar@latest": +"@gluestack-ui/avatar@^0.1.6": version "0.1.9" resolved "https://registry.yarnpkg.com/@gluestack-ui/avatar/-/avatar-0.1.9.tgz#cc47f6f431df576dfd37a815c71a64cdcc35c136" integrity sha512-05f1gy6ckAtNv31hsePCEW3/7T2thrYDuo/m62qjfPTf9VR/z+/vmvkAJc4AbPSe2eJ8Km/IcDpac+i4K+bwow== dependencies: "@gluestack-ui/utils" "^0.1.5" +"@gluestack-ui/avatar@latest": + version "0.1.10" + resolved "https://registry.yarnpkg.com/@gluestack-ui/avatar/-/avatar-0.1.10.tgz#536c92ebb9f263cbb8ac4f16289497975715143d" + integrity sha512-15Ed6itvI7bT8VCA5mLbQ0q9v1I7u/enK5BcQg3qKN6IVbWY6MIeT7/S7s2wvKbkNEjdN/iQWUweKPXRtZ7gEw== + dependencies: + "@gluestack-ui/utils" "^0.1.5" + "@gluestack-ui/button@^0.1.15", "@gluestack-ui/button@^0.1.23", "@gluestack-ui/button@latest": version "0.1.23" resolved "https://registry.yarnpkg.com/@gluestack-ui/button/-/button-0.1.23.tgz#216ed04c2d8b2bd013eff5713ca84a81ffc64140" @@ -2623,6 +2630,15 @@ "@react-native-aria/interactions" "^0.2.8" react-native-svg "13.4.0" +"@gluestack-ui/linear-gradient@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@gluestack-ui/linear-gradient/-/linear-gradient-0.0.2.tgz#7b05160412948acecb900952a47599a7f22a9c9f" + integrity sha512-d5Q8t1cIu95RqbFzKB/4Ad2XdMtkDmfj3UrUSnDE7sdWASjJQW3kTJF3oK2MEiEJijAwNSBhzqccvRnvYDTX6w== + dependencies: + "@gluestack-ui/utils" "0.1.8" + "@react-native-aria/focus" "^0.2.8" + "@react-native-aria/interactions" "^0.2.10" + "@gluestack-ui/link@^0.1.6", "@gluestack-ui/link@latest": version "0.1.10" resolved "https://registry.yarnpkg.com/@gluestack-ui/link/-/link-0.1.10.tgz#5a01ad0d2cf98c312f3eb1f2b04cf5e86a21ce64" @@ -2797,13 +2813,13 @@ react-native-svg "13.4.0" "@gluestack-ui/themed@^0.1.5": - version "0.1.10" - resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-0.1.10.tgz#44c4b67ca162a306c55ee1ecb7e6c08e63610c61" - integrity sha512-WJ8X52b+JFrO/LvnokaLqkg9URBJzqxP1Fkt9+VJSAr3Kb8mrZzPP3aXbA3lhSfYtTsFnYj5PskFS9pwedHTJA== + version "0.1.15" + resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-0.1.15.tgz#b5b991fdc4799f9387546cb57356e3c40835a946" + integrity sha512-8OxYmgR3uC24TkkbF/Q7yb2mCeJ1GPf/Oz1rINTefbTk8FXV/3Y9WtdYmSG9dMSWBMhsYumb5SYEw7i/OQU46Q== dependencies: "@expo/html-elements" latest "@gluestack-style/animation-plugin" latest - "@gluestack-style/react" "^0.2.11" + "@gluestack-style/react" "^0.2.21" "@gluestack-ui/actionsheet" latest "@gluestack-ui/alert" latest "@gluestack-ui/alert-dialog" latest @@ -2816,6 +2832,7 @@ "@gluestack-ui/hstack" latest "@gluestack-ui/icon" latest "@gluestack-ui/input" "^0.1.10" + "@gluestack-ui/linear-gradient" "^0.0.2" "@gluestack-ui/link" latest "@gluestack-ui/menu" latest "@gluestack-ui/modal" latest @@ -2835,6 +2852,7 @@ "@gluestack-ui/tooltip" "^0.1.15" "@gluestack-ui/vstack" latest "@legendapp/motion" latest + expo-linear-gradient "~12.0.1" react "^18.2.0" react-native-svg "13.4.0" @@ -2888,14 +2906,14 @@ "@gluestack-ui/utils" "^0.1.5" "@gluestack/design-system@^0.4.28": - version "0.4.70" - resolved "https://registry.yarnpkg.com/@gluestack/design-system/-/design-system-0.4.70.tgz#149947c8582d82e1753ef1ff074e7becfbfa8fc0" - integrity sha512-093fvEAZmZ6O9H80gWc97/ltuj+HWQvqn6CQBHquvhUXN570NoN/Vl2To+ydtNHckM9ogp3P151d77mkfxIlTg== + version "0.4.72" + resolved "https://registry.yarnpkg.com/@gluestack/design-system/-/design-system-0.4.72.tgz#d26f696d639d46f6590297613be29bbf14f68e19" + integrity sha512-bemigQEvkTlu2kGkvh6d7IUbQy4w5aP4s2xTpX97m/QzakPyz7QNX4HpKPPmAnw6TgZ+wbyLk/6/X0TvB0CTLA== dependencies: "@expo/html-elements" "0.3.0" "@gluestack-style/animation-plugin" "^0.1.7" "@gluestack-style/babel-plugin-styled-resolver" "^0.1.15-alpha.0" - "@gluestack-style/react" "^0.2.9" + "@gluestack-style/react" "^0.2.16" "@gluestack-ui/actionsheet" "^0.2.7" "@gluestack-ui/alert" "^0.1.4" "@gluestack-ui/alert-dialog" "^0.1.8"