From 5a4e6d2789ce307b3c2d48339ec636b40cb505d8 Mon Sep 17 00:00:00 2001 From: Thet Aung Date: Sat, 21 Dec 2024 13:49:07 +0300 Subject: [PATCH 1/2] improvements: improved style caching logic with lru-cache --- package.json | 1 + src/utils/normalizeStyles.ts | 95 +++++++++++++++++++----------------- yarn.lock | 8 +++ 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 703fdf54..0677d919 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "lodash.noop": "^3.0.1", "lodash.omit": "^4.5.0", "lodash.omitby": "^4.6.0", + "lru-cache": "^11.0.2", "react-native-actions-sheet": "^0.8.10", "react-native-mask-input": "^1.2.2", "react-native-super-grid": "^5.0.0", diff --git a/src/utils/normalizeStyles.ts b/src/utils/normalizeStyles.ts index d150d6dd..3f213690 100644 --- a/src/utils/normalizeStyles.ts +++ b/src/utils/normalizeStyles.ts @@ -1,70 +1,73 @@ import type { StyleProp } from 'react-native'; import type { MD3Theme, MD3Typescale } from '../core/theme/types'; -import { allArgumentResolver, createMemoizedFunction, get } from './lodash'; +import { get, allArgumentResolver } from './lodash'; // Assuming you have a `get` utility function -export const maybeIsToken = (value: any) => typeof value === 'string' && value.includes('.'); +import { LRUCache } from 'lru-cache'; -const normalizeStylesMemo = createMemoizedFunction({ - /** - * - * @param styles the style object to normalize - * @param currentTheme for switching between themes - * @param cacheKey to resolve unique values for different components - */ - resolver: ( - styles: StyleProp | StyleProp[], - { themeName }: MD3Theme, - cacheKey: string, - ) => `${cacheKey}_${themeName}_${allArgumentResolver(styles)}`, +const cache = new LRUCache({ + max: 1000, }); +export const maybeIsToken = (value: any) => typeof value === 'string' && value.includes('.'); + const flattenTypescale = (style: Partial & { typescale: MD3Typescale }>) => { if ('typescale' in style) { const { typescale = {}, ...rest } = style; style = { ...rest, ...typescale }; } - return style; }; // normalize tokens inside the styles object and the subsequent objects inside it -const normalizeStyles = normalizeStylesMemo( - /** - * - * @param styles the style object to normalize - * @param currentTheme for switching between themes - * @param cacheKey to resolve unique values for different components - */ - (styles: StyleProp | StyleProp[], currentTheme: MD3Theme, cacheKey: string) => { - // if the styles is an array, we want to normalize each entry - if (Array.isArray(styles)) { - return styles.map(styleObj => normalizeStyles(styleObj, currentTheme, cacheKey)); - } +/** + * + * @param styles the style object to normalize + * @param currentTheme for switching between themes + * @param cacheKey to resolve unique values for different components + */ +function normalizeStyles( + styles: StyleProp | StyleProp[], + currentTheme: MD3Theme, + _cacheKey: string, +): any { + // Generate a unique cache key + const cacheKey = `${_cacheKey}_${currentTheme.themeName}_${allArgumentResolver(styles)}`; - if (!styles) { - return undefined; - } + // Check if the result is cached + if (cache.has(cacheKey)) { + return cache.get(cacheKey); + } - const newStyles = Object.assign({}, styles); + // Proceed to normalize styles + let normalizedStyles; + if (Array.isArray(styles)) { + // if the styles is an array, we want to normalize each entry + normalizedStyles = styles.map(styleObj => + normalizeStyles(styleObj, currentTheme, cacheKey), + ); + } else if (!styles) { + normalizedStyles = undefined; + } else { + const newStyles = { ...styles }; - const normalizableProperties = []; - for (const key in styles) { - if (maybeIsToken(styles[key]) || typeof styles[key] === 'object') { - normalizableProperties.push(key); + for (const [key, value] of Object.entries(newStyles)) { + if (maybeIsToken(value)) { + // Replace token with actual value from theme + newStyles[key] = get(currentTheme, value as string, ''); + } else if (typeof value === 'object' && value !== null) { + // it's an object // we want to normalize everything inside it as well + newStyles[key] = normalizeStyles(value, currentTheme, cacheKey); } + // Primitive values (numbers, booleans, etc.) are left as is } - normalizableProperties.forEach(key => { - if (typeof newStyles[key] === 'string') { - newStyles[key] = get(currentTheme, newStyles[key], ''); - } else { - // it's an object // we want to normalize everything inside it as well - newStyles[key] = normalizeStyles(newStyles[key], currentTheme, cacheKey); - } - }); + normalizedStyles = flattenTypescale(newStyles); + } + + // Cache the result + cache.set(cacheKey, normalizedStyles); - return flattenTypescale(newStyles); - }, -); + return normalizedStyles; +} export default normalizeStyles; diff --git a/yarn.lock b/yarn.lock index 8fe667da..6dbd7e91 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3475,6 +3475,7 @@ __metadata: lodash.noop: ^3.0.1 lodash.omit: ^4.5.0 lodash.omitby: ^4.6.0 + lru-cache: ^11.0.2 prettier: ^2.7.1 react: ^18.2.0 react-dom: ^18.2.0 @@ -20856,6 +20857,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^11.0.2": + version: 11.0.2 + resolution: "lru-cache@npm:11.0.2" + checksum: f9c27c58919a30f42834de9444de9f75bcbbb802c459239f96dd449ad880d8f9a42f51556d13659864dc94ab2dbded9c4a4f42a3e25a45b6da01bb86111224df + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" From ebc182fc7f25a4309e9f0a2b75e963c7c8987f11 Mon Sep 17 00:00:00 2001 From: Thet Aung Date: Sat, 21 Dec 2024 13:49:11 +0300 Subject: [PATCH 2/2] 0.3.75 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0677d919..42c1b18c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bambooapp/bamboo-molecules", - "version": "0.3.74", + "version": "0.3.75", "repository": { "type": "git", "url": "git+https://github.com/webbeetechnologies/bamboo-molecules.git"