From 1bf617cf6eef327b61a98982780a9f2cef37e9cb Mon Sep 17 00:00:00 2001 From: mauroerta Date: Sat, 30 Apr 2022 09:42:49 +0200 Subject: [PATCH] feat: #131 --- packages/jss/src/generateClassName.ts | 36 +++++++++++++++++ packages/jss/src/morfeoJSS.ts | 12 +++++- packages/jss/tests/generateClassName.test.ts | 17 ++++++++ packages/jss/tests/jss.test.ts | 19 +++++++++ packages/svelte/tests/morfeo.test.ts | 41 +++++++++----------- 5 files changed, 102 insertions(+), 23 deletions(-) create mode 100644 packages/jss/src/generateClassName.ts create mode 100644 packages/jss/tests/generateClassName.test.ts diff --git a/packages/jss/src/generateClassName.ts b/packages/jss/src/generateClassName.ts new file mode 100644 index 00000000..3d198443 --- /dev/null +++ b/packages/jss/src/generateClassName.ts @@ -0,0 +1,36 @@ +function getClassNameGenerator() { + const cache = new Map(); + + function escapeString(string: string) { + if (cache.has(string)) { + return cache.get(string); + } + + const escaped = string.replace(/[^\w\s]/gi, ''); + cache.set(string, escaped); + + return escaped; + } + + function makeRuleName(property: string, value: string) { + return `${escapeString(property)}-${escapeString(value)}`; + } + + function generator(style: Record = {}) { + const className = Object.keys(style).reduce((acc, curr) => { + let value = style[curr]; + if (typeof value !== 'string') { + value = generator(value); + } + const prefix = acc ? '_' : ''; + const ruleName = makeRuleName(curr, value); + return `${acc}${prefix}${ruleName}`; + }, ''); + + return className; + } + + return generator; +} + +export const generateClassName = getClassNameGenerator(); diff --git a/packages/jss/src/morfeoJSS.ts b/packages/jss/src/morfeoJSS.ts index 02d02fff..18934b46 100644 --- a/packages/jss/src/morfeoJSS.ts +++ b/packages/jss/src/morfeoJSS.ts @@ -1,6 +1,7 @@ import { parsers, Style } from '@morfeo/core'; import preset from 'jss-preset-default'; -import { JssOptions, Plugin } from 'jss'; +import { JssOptions, Plugin, Rule } from 'jss'; +import { generateClassName } from './generateClassName'; const defaultPreset = preset(); @@ -10,7 +11,16 @@ export const morfeoJSS: Plugin = { }, }; +function createGenerateId() { + return (rule: Rule) => { + // @ts-expect-error + const style = rule.style; + return generateClassName(style); + }; +} + export const morfeoJSSPreset: Partial = { ...defaultPreset, + createGenerateId, plugins: [morfeoJSS, ...defaultPreset.plugins], }; diff --git a/packages/jss/tests/generateClassName.test.ts b/packages/jss/tests/generateClassName.test.ts new file mode 100644 index 00000000..7db619df --- /dev/null +++ b/packages/jss/tests/generateClassName.test.ts @@ -0,0 +1,17 @@ +import { generateClassName } from '../src/generateClassName'; + +describe('generateClassName', () => { + it('should generate the class from the style object', () => { + const className = generateClassName({ + bg: 'primary', + }); + + expect(className).toBe('bg-primary'); + }); + + it('should return an empty string in case the style object is not provided', () => { + const className = generateClassName(); + + expect(className).toBe(''); + }); +}); diff --git a/packages/jss/tests/jss.test.ts b/packages/jss/tests/jss.test.ts index 83838c01..b2c9c117 100644 --- a/packages/jss/tests/jss.test.ts +++ b/packages/jss/tests/jss.test.ts @@ -6,6 +6,12 @@ const THEME: Theme = { primary: '#e3e3e3', secondary: '#000', }, + breakpoints: { + lg: '1920px', + md: '1366px', + sm: '768px', + xs: '375px', + }, } as any; describe('jss', () => { @@ -28,6 +34,19 @@ describe('jss', () => { ); }); + test('should generate the css also for responsive values', () => { + const sheet = getStyleSheet({ + button: { + color: 'secondary', + bg: { + sm: 'primary', + }, + }, + }); + + expect(sheet.toString()).toContain('background-color: #e3e3e3;'); + }); + test('should generate the classnames', () => { const { classes } = getStyles({ button: { diff --git a/packages/svelte/tests/morfeo.test.ts b/packages/svelte/tests/morfeo.test.ts index 88ba34a9..ece7d388 100644 --- a/packages/svelte/tests/morfeo.test.ts +++ b/packages/svelte/tests/morfeo.test.ts @@ -3,8 +3,8 @@ import { morfeoStyle } from '../src'; const THEME: Theme = { colors: { - primary: '#e3e3e3', - secondary: '#000', + primary: 'rgb(227, 227, 227)', + secondary: 'rgb(0, 0, 0)', }, components: { Box: { @@ -28,32 +28,18 @@ describe('morfeo', () => { morfeo.setTheme('default', THEME); }); - test('should add default className to the element', () => { + test('should generate the style for the element', () => { const element = document.createElement('div'); morfeoStyle(element, { bg: 'primary' }); - - expect(element.className).toContain('morfeo-element'); - }); - - test('should add custom className if componentName is specified', () => { - const element = document.createElement('div'); - morfeoStyle(element, { componentName: 'Box' }); - - expect(element.className).toContain('Box'); - }); - - test('should add custom className if componentName and variant is specified', () => { - const element = document.createElement('div'); - morfeoStyle(element, { componentName: 'Box', variant: 'primary' }); - - expect(element.className).toContain('Box-primary'); + const style = getComputedStyle(element); + expect(style.backgroundColor).toBe(THEME.colors.primary); }); test('should not crash if style is not specified', () => { const element = document.createElement('div'); morfeoStyle(element); - expect(element.className).toContain('morfeo-element'); + expect(element).toBeDefined(); }); test('should return a function that will remove the listener from the theme', () => { @@ -63,13 +49,24 @@ describe('morfeo', () => { expect(typeof destroy).toBe('function'); }); - test('should return a function that will update the style on changes', () => { + test('should return a function that will update the style', () => { const element = document.createElement('div'); const { update } = morfeoStyle(element); - update({} as any); + expect(typeof update).toBe('function'); }); + test('should update the style by using the update function', () => { + const element = document.createElement('div'); + const { update } = morfeoStyle(element, { bg: 'secondary' }); + + update({ bg: 'primary' }); + + const style = getComputedStyle(element); + + expect(style.backgroundColor).toBe(THEME.colors.primary); + }); + test('should set the default properties to the element', () => { const element = document.createElement('div'); morfeoStyle(element, {