Skip to content

Commit

Permalink
Merge pull request #1607 from gluestack/release/@gluestack-style/reac…
Browse files Browse the repository at this point in the history
  • Loading branch information
ankit-tailor authored Jan 11, 2024
2 parents 07f174a + 27d8f8c commit 21d1d34
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs';
argsType: {
name: {
control: 'select',
options: ['2000s', '2010s', '2020s'],
default: '2000s',
options: ['classic', 'modern', 'latest'],
default: 'classic',
},
},
}}
Expand Down Expand Up @@ -162,14 +162,14 @@ export const config = createConfig({
themes: {
classic: {
colors: {
$primary: '$colors.$brown400',
$secondary: '$colors.$brown100',
primary: '$colors$brown400',
secondary: '$colors$brown100',
},
},
modern: {
colors: {
$primary: '$colors.$red400',
$secondary: '$colors.$red100',
primary: '$colors$red400',
secondary: '$colors$red100',
},
},
},
Expand Down Expand Up @@ -211,4 +211,43 @@ export const App = () => {
};
```

> Note: Theme name should always be a string.
### Theme specific style

You can apply theme-specific styling by using the . prefix with the theme name. This API is supported in both `styled()` and the `sx` prop.

```tsx
import { styled, StyledProvider, Theme } from '@gluestack-style/react';
import { Pressable } from 'react-native';
import { config } from './config';

const Button = styled(Pressable, {
backgroundColor: '$primary',
padding: '$3',
'.classic': {
backgroundColor: '$secondary'
}
});

const ButtonText = styled(Pressable, {
color: '$secondary',
'.classic': {
color: '$primary'
}
});

export const App = () => {
return (
<StyledProvider config={config}>
<Theme theme="classic">
<Button>
<ButtonText>Classic Button</ButtonText>
</Button>
</Theme>
</StyledProvider>
);
};
```

> **Note**: Components must be wrapped inside the `Theme` component to use the theme. Else default tokens from config will be used.
7 changes: 7 additions & 0 deletions packages/styled/react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @gluestack-style/react

## 1.0.34

### Patch Changes

- Fixed inline theme performance [PR](https://github.com/gluestack/gluestack-ui/pull/1606)
- Fixed multiple provider color mode issue [PR](https://github.com/gluestack/gluestack-ui/pull/1602)

## 1.0.33

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/styled/react/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@gluestack-style/react",
"description": "A universal & performant styling library for React Native, Next.js & React",
"version": "1.0.33",
"version": "1.0.34",
"keywords": [
"React Native",
"Next.js",
Expand Down
20 changes: 17 additions & 3 deletions packages/styled/react/src/StyledProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { propertyTokenMap } from './propertyTokenMap';
import type { COLORMODES } from './types';
import {
convertTokensToCssVariables,
generateMergedThemeTokens,
platformSpecificSpaceUnits,
} from './utils';
import { createGlobalStylesWeb } from './createGlobalStylesWeb';
Expand Down Expand Up @@ -45,6 +46,7 @@ const setCurrentColorMode = (inputColorMode: string | undefined) => {
// colorModeSet = true;
// }
};

export const StyledProvider: React.FC<{
config: Config;
colorMode?: COLORMODES;
Expand All @@ -63,6 +65,8 @@ export const StyledProvider: React.FC<{
});

const { themes } = useTheme();
const styledContext = useStyled();
const isParentProviderExist = styledContext?.config ? true : false;

const themeContextValue = React.useMemo(() => {
if (colorMode) {
Expand Down Expand Up @@ -96,6 +100,10 @@ export const StyledProvider: React.FC<{
);
}

configWithPlatformSpecificUnits = generateMergedThemeTokens(
configWithPlatformSpecificUnits
);

return configWithPlatformSpecificUnits;
}, [config]);

Expand Down Expand Up @@ -130,7 +138,9 @@ export const StyledProvider: React.FC<{
documentElement.classList.add(`gs`);

if (currentColorMode) {
document.body.setAttribute('data-theme-id', currentColorMode);
if (!isParentProviderExist) {
document.body.setAttribute('data-theme-id', currentColorMode);
}
documentElement.classList.add(`gs-${currentColorMode}`);
} else {
documentElement.classList.add(`gs-light`);
Expand All @@ -145,10 +155,14 @@ export const StyledProvider: React.FC<{
if (Platform.OS === 'web') {
if (currentColor) {
if (currentColor === 'dark') {
document.body.setAttribute('data-theme-id', 'dark');
if (!isParentProviderExist) {
document.body.setAttribute('data-theme-id', 'dark');
}
documentElement.classList.remove(`gs-light`);
} else {
document.body.setAttribute('data-theme-id', 'light');
if (!isParentProviderExist) {
document.body.setAttribute('data-theme-id', 'light');
}
documentElement.classList.remove(`gs-dark`);
}
documentElement.classList.add(`gs-${currentColor}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/styled/react/src/createConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { stableHash } from './stableHash';
import { propertyTokenMap } from './propertyTokenMap';
import { updateOrderUnResolvedMap } from './updateOrderUnResolvedMap';
import { GluestackStyleSheet } from './style-sheet';
import { resolvePlatformTheme } from './styled';
import { resolvePlatformTheme } from './utils';
import { Platform } from 'react-native';

/********************* PLUGINS *****************************/
Expand Down
2 changes: 1 addition & 1 deletion packages/styled/react/src/createGlobalStyles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { convertStyledToStyledVerbosed } from './convertSxToSxVerbosed';
import { stableHash } from './stableHash';
import { resolvePlatformTheme } from './styled';
import { resolvePlatformTheme } from './utils';
import { updateOrderUnResolvedMap } from './updateOrderUnResolvedMap';

export const createGlobalStyles = (globalStyle: object, Platform: any) => {
Expand Down
52 changes: 27 additions & 25 deletions packages/styled/react/src/resolver/StyledValueToCSSObject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { CSSObject, StyledValue } from '../types';
import { deepMerge, resolvedTokenization } from '../utils';
import { deepClone } from '../utils/cssify/utils/common';
import { resolvedTokenization } from '../utils';

export function StyledValueToCSSObject(
input: StyledValue | undefined,
Expand All @@ -11,6 +10,7 @@ export function StyledValueToCSSObject(
if (!input) {
return {};
}

return resolvedTokenization(input, CONFIG, ignoreKeys, deleteIfTokenNotExist);
}
export function themeStyledValueToCSSObject(
Expand All @@ -20,34 +20,36 @@ export function themeStyledValueToCSSObject(
) {
let themeResolved1: any = {};
if (CONFIG?.themes) {
const tokens = deepClone(CONFIG.tokens);
Object.keys(CONFIG?.themes).forEach((key: any) => {
const themeTokens = CONFIG?.themes[key];
Object.keys(themeTokens).forEach((tokenKey1: any) => {
Object.keys(themeTokens[tokenKey1]).forEach((tokenKey: any) => {
delete tokens[tokenKey1][tokenKey];
});
});
});
// const tokens = deepClone(CONFIG.tokens);
// Object.keys(CONFIG?.themes).forEach((key: any) => {
// const themeTokens = CONFIG?.themes[key];
// Object.keys(themeTokens).forEach((tokenKey1: any) => {
// Object.keys(themeTokens[tokenKey1]).forEach((tokenKey: any) => {
// delete tokens[tokenKey1][tokenKey];
// });
// });
// });

// debugger;

Object.keys(CONFIG?.themes).forEach((key: any) => {
const themeResolved = StyledValueToCSSObject(
input,
{
...CONFIG,
tokens: deepMerge(deepClone(tokens), CONFIG.themes[key]),
},
ignoreKeys,
true
);
Object.keys(CONFIG?.themes).forEach((themeName: any) => {
if (themeName !== 'tokens') {
const themeResolved = StyledValueToCSSObject(
input,
{
...CONFIG,
tokens: CONFIG?.themes?.tokens[themeName],
},
ignoreKeys,
true
);

Object.keys(themeResolved).forEach((key) =>
themeResolved[key] === undefined ? delete themeResolved[key] : {}
);
Object.keys(themeResolved).forEach((key: any) =>
themeResolved[key] === undefined ? delete themeResolved[key] : {}
);

themeResolved1[key] = themeResolved;
themeResolved1[themeName] = themeResolved;
}
});
}

Expand Down
2 changes: 1 addition & 1 deletion packages/styled/react/src/style-sheet/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
StyledValueToCSSObject,
themeStyledValueToCSSObject,
} from '../resolver';
} from '../resolver/StyledValueToCSSObject';
import type { OrderedSXResolved } from '../types';
import { getCSSIdAndRuleset } from '../updateCSSStyleInOrderedResolved.web';
import {
Expand Down
27 changes: 1 addition & 26 deletions packages/styled/react/src/styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { styledResolvedToOrderedSXResolved } from './resolver/orderedResolved';
import { styledToStyledResolved } from './resolver/styledResolved';
import { getStyleIds } from './resolver/getStyleIds';
import { injectComponentAndDescendantStyles } from './resolver/injectComponentAndDescendantStyles';
import { resolvePlatformTheme } from './utils';

import {
convertStyledToStyledVerbosed,
Expand Down Expand Up @@ -692,32 +693,6 @@ function mergeArraysInObjects(...objects: any) {
return merged;
}

export function resolvePlatformTheme(theme: any, platform: any) {
if (typeof theme === 'object') {
Object.keys(theme).forEach((themeKey) => {
if (themeKey !== 'style' && themeKey !== 'defaultProps') {
if (theme[themeKey].platform) {
let temp = { ...theme[themeKey] };
theme[themeKey] = deepMerge(temp, theme[themeKey].platform[platform]);
delete theme[themeKey].platform;
resolvePlatformTheme(theme[themeKey], platform);
} else if (themeKey === 'queries') {
theme[themeKey].forEach((query: any) => {
if (query.value.platform) {
let temp = { ...query.value };
query.value = deepMerge(temp, query.value.platform[platform]);
delete query.value.platform;
}
resolvePlatformTheme(query.value, platform);
});
} else {
resolvePlatformTheme(theme[themeKey], platform);
}
}
});
}
}

export function getVariantProps(
props: any,
theme: any,
Expand Down
49 changes: 49 additions & 0 deletions packages/styled/react/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
import type { Config } from './types';
import { deepClone } from './utils/cssify/utils/common';

const propsNotToConvertToCSSVariables = ['shadowColor', 'textShadowColor'];

export function generateMergedThemeTokens(CONFIG: any) {
const mergedTokens: any = CONFIG;
const tokens = deepClone(CONFIG.tokens);
const themeTokens: any = {};

if (CONFIG?.themes) {
Object.keys(CONFIG.themes).forEach((key) => {
// tokens is a reserved key to merge theme tokens
if (key !== 'tokens') {
themeTokens[key] = deepMerge(tokens, CONFIG.themes[key]);
}
});

if (themeTokens) {
mergedTokens.themes.tokens = {};
Object.assign(mergedTokens.themes.tokens, themeTokens);
}
}

return mergedTokens;
}

export function convertToUnicodeString(inputString: any) {
let result = '';
if (!inputString) {
Expand Down Expand Up @@ -600,3 +623,29 @@ export function addThemeConditionInMeta(originalThemeObject: any, CONFIG: any) {
});
return themeObject;
}

export function resolvePlatformTheme(theme: any, platform: any) {
if (typeof theme === 'object') {
Object.keys(theme).forEach((themeKey) => {
if (themeKey !== 'style' && themeKey !== 'defaultProps') {
if (theme[themeKey].platform) {
let temp = { ...theme[themeKey] };
theme[themeKey] = deepMerge(temp, theme[themeKey].platform[platform]);
delete theme[themeKey].platform;
resolvePlatformTheme(theme[themeKey], platform);
} else if (themeKey === 'queries') {
theme[themeKey].forEach((query: any) => {
if (query.value.platform) {
let temp = { ...query.value };
query.value = deepMerge(temp, query.value.platform[platform]);
delete query.value.platform;
}
resolvePlatformTheme(query.value, platform);
});
} else {
resolvePlatformTheme(theme[themeKey], platform);
}
}
});
}
}

0 comments on commit 21d1d34

Please sign in to comment.