Skip to content

Commit

Permalink
feat: gradients parsers added to @morfeo/web package
Browse files Browse the repository at this point in the history
  • Loading branch information
mauroerta committed Jun 1, 2021
1 parent 473b909 commit 9bcac4e
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 17 deletions.
34 changes: 32 additions & 2 deletions apps/web-sandbox/src/theme.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
export const gradients = {
primary: {
start: 0,
angle: 90,
end: 100,
colors: ['success', 'accent'],
kind: 'linear',
},
secondary: {
start: 0,
end: 100,
angle: 0,
colors: ['accent', 'success'],
kind: 'linear',
},
loading: {
start: 0,
end: 100,
angle: 90,
colors: ['transparent', 'grey', 'transparent'],
kind: 'linear',
},
};

export const lightTheme = {
colors: {
grey: '#bdc3c7',
primary: 'white',
danger: '#e74c3c',
secondary: 'black',
danger: 'red',
success: '#2ecc71',
accent: '#3498db',
warning: '#f39c12',
transparent: 'transparent',
},
gradients,
radii: {
m: '10px',
round: '50%',
Expand Down Expand Up @@ -48,7 +78,7 @@ export const lightTheme = {
borderStyle: 'solid',
borderColor: 'primary',
'&:hover': {
bg: 'secondary',
gradient: 'secondary',
color: 'primary',
},
},
Expand Down
6 changes: 6 additions & 0 deletions packages/spec/src/allProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
zIndicesMap,
fontSizesMap,
opacitiesMap,
gradientsMap,
fontWeightsMap,
lineHeightsMap,
transitionsMap,
Expand All @@ -23,6 +24,10 @@ export const fontProperties = createPropertiesMap(fontsMap, 'fonts');
export const spacesProperties = createPropertiesMap(spacesMap, 'space');
export const sizesProperties = createPropertiesMap(sizesMap, 'sizes');
export const colorProperties = createPropertiesMap(colorsMap, 'colors');
export const gradientProperties = createPropertiesMap(
gradientsMap,
'gradients',
);
export const shadowsProperties = createPropertiesMap(shadowsMap, 'shadows');
export const fontSizeProperties = createPropertiesMap(
fontSizesMap,
Expand Down Expand Up @@ -69,6 +74,7 @@ export const allProperties = {
...bordersProperties,
...fontSizeProperties,
...zIndicesProperties,
...gradientProperties,
...opacitiesProperties,
...fontWeightProperties,
...lineHeightProperties,
Expand Down
1 change: 1 addition & 0 deletions packages/spec/src/properties/gradients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const gradientsMap = ['gradient', 'bgGradient', 'textGradient'] as const;
1 change: 1 addition & 0 deletions packages/spec/src/properties/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './colors';
export * from './borders';
export * from './shadows';
export * from './zIndices';
export * from './gradients';
export * from './opacities';
export * from './components';
export * from './transitions';
42 changes: 42 additions & 0 deletions packages/spec/src/types/gradients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { gradientsMap } from '../properties';
import { Color } from './colors';

export type GradientCoordinate = {
x: number;
y: number;
};

export type GradientKind = 'linear' | 'radial';

export interface ReactNativeGradientConfig {
end: GradientCoordinate;
start: GradientCoordinate;
colors: Color[];
locations?: number[];
angle?: number;
useAngle?: boolean;
angleCenter?: GradientCoordinate;
}

export interface GradientConfig {
end?: number;
kind?: GradientKind;
start?: number;
angle?: number;
colors: Color[];
}

export interface Gradients {
primary: GradientConfig;
secondary: GradientConfig;
}

export type Gradient = keyof Gradients;

type BaseGradientProps = {
[K in typeof gradientsMap[number]]: Gradient;
};

export interface GradientProps extends BaseGradientProps {}

export type GradientProperty = keyof GradientProps;
1 change: 1 addition & 0 deletions packages/spec/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './borders';
export * from './shadows';
export * from './zIndices';
export * from './opacities';
export * from './gradients';
export * from './components';
export * from './properties';
export * from './transitions';
Expand Down
2 changes: 2 additions & 0 deletions packages/spec/src/types/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Borders, BorderWidths, BorderStyles } from './borders';
import { Opacities } from './opacities';
import { Transitions } from './transitions';
import { ZIndices } from './zIndices';
import { Gradients } from './gradients';
import { MediaQueries } from './mediaQueries';
import { Components } from './components';

Expand All @@ -27,6 +28,7 @@ export type BaseTheme = {
borders: Borders;
zIndices: ZIndices;
fontSizes: FontSizes;
gradients: Gradients;
opacities: Opacities;
fontWeights: FontWeights;
lineHeights: LineHeights;
Expand Down
80 changes: 66 additions & 14 deletions packages/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#### [Usage](#usage-1)

- [pseudos](#pseudos)
- [gradients](#gradients)

#### [Supported Pseudos](#supported-pseudos-1)

Expand All @@ -45,24 +46,19 @@ yarn add @morfeo/web

**@morfeo/web** re-export all the **@morfeo/core** library, check out its [documentation](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/core) before continue.

In addition to the core library, the web package adds the parsers to handle **pseudo classes** and **pseudo elements**.

:warning: Warning

> You'll probably never use *directly* `@morfeo/web` or `@morfeo/core`, instead, you'll more likely to use [@morfeo/react](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/react), [@morfeo/svelte](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/svelte), [@morfeo/jss](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/jss), or other packages that offer better integration of the morfeo eco-system in your framework of choice.
> In this particular case, it's important to know that you cannot define a style for pseudo-elements (or media queries) as inline-style, that's why you need some other tool like JSS or Styled Components to handle this behavior. Likely, we already thought about it, so feel free to check out our packages.
In addition to the core library, the web package adds the parsers to handle **pseudo classes**, **pseudo elements** and **gradients**.

### pseudos

You can pass to the `resolve` method any pseudo class with the format '&:{pseudo}', for example:
You can pass to the `resolve` method any pseudo class with the format '&:{pseudo}', for example:

```typescript
import { parsers } from "@morfeo/web";
import { parsers } from '@morfeo/web';

const style = parsers.resolve({
bg: "primary",
"&:hover": {
bg: "secondary",
bg: 'primary',
'&:hover': {
bg: 'secondary',
},
});
```
Expand All @@ -73,12 +69,33 @@ Will generate the style:
{
"backgroundColor": "black",
"&:hover": {
"backgroundColor": "grey",
},
"backgroundColor": "grey"
}
}
```

## Supported Pseudos
If you're using `@morfeo/web` to directly style a component without any other css-in-js library, you can use `getStyles` :

```typescript
import { getStyles } from '@morfeo/web';

const element = document.querySelector('#myButton');

const { classes } = getStyles({
button: {
bg: 'primary',
'&:hover': {
bg: 'secondary',
},
},
});

element.classList.add(classes.button);
```

In this case, @morfeo will generate plain css. To understand more about this topic we suggest you check our documentation about [@morfeo/jss](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/jss), in fact, the function `getStyles` is re-exported from `@morfeo/jss`.

#### Supported Pseudos

For now morfeo support this pseudos:

Expand Down Expand Up @@ -113,3 +130,38 @@ For now morfeo support this pseudos:
```

as specified [here](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/core#add-a-custom-parser) yuo can always add more parser to extends morfeo, or simply add more pseudos in this list by editing this [file](https://github.com/VLK-STUDIO/morfeo/blob/main/packages/web/src/properties.ts) and open a pull request.

### gradients

You can specify inside the theme a set of gradients to use inside your application by using the `gradients` theme slice:

```typescript
const myTheme = {
...restOfTheTheme,
gradients: {
...restOfTheTheme.gradients,
primary: {
start: 0,
angle: 90,
end: 100,
colors: ['primary', 'secondary'],
kind: 'linear',
},
},
};
```

An example of usage is:

```typescript
const buttonStyle = button.resolve({ gradient: 'primary' });
const textStyle = button.resolve({ textGradient: 'primary' });
```

with the results:

[![gradient-Button.png](https://i.postimg.cc/k5B8tNMP/gradient-Button.png)](https://postimg.cc/XZ6XRCys)

[![gradient-Text.png](https://i.postimg.cc/5NDMVbH5/gradient-Text.png)](https://postimg.cc/SJLPL0fj)

check out [@morfeo/spec](https://github.com/VLK-STUDIO/morfeo/tree/main/packages/spec) for the complete specification of the type `GradientConfig` used inside the `gradients` theme slice.
6 changes: 5 additions & 1 deletion packages/web/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { parsers, Property } from '@morfeo/core';
import { pseudosParses } from './parsers';
import { pseudosParses, gradientParsers } from './parsers';
import { pseudosProperties } from './properties';

pseudosProperties.forEach(property => {
parsers.add(property as Property, pseudosParses[property] as any);
});

Object.keys(gradientParsers).forEach(property => {
parsers.add(property as Property, gradientParsers[property] as any);
});

export * from './types';

/** re-export of @morfeo/core */
Expand Down
78 changes: 78 additions & 0 deletions packages/web/src/parsers/gradients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
theme,
Gradient,
ParserParams,
SliceParsers,
GradientConfig,
gradientProperties,
GradientProperty,
} from '@morfeo/core';

type GradientsParsers = SliceParsers<
typeof gradientProperties,
keyof typeof gradientProperties
>;

function getGradientPercentages({
start = 0,
end = 100,
colors = [],
}: GradientConfig) {
const { length } = colors;
const diff = end - start;
const part = diff / (length - 1 > 0 ? length - 1 : 1);
let percentage = 0;

return colors.reduce((prev, colorKey) => {
const color = theme.getValue('colors', colorKey) || colorKey;
const current = `${color} ${start + percentage}%`;
percentage += part;
return prev ? `${prev}, ${current}` : current;
}, '');
}

function getGradientProperty({ kind }: GradientConfig) {
if (kind === 'radial') {
return 'radial-gradient';
}

return 'linear-gradient';
}

function getGradientBackground(value: Gradient) {
const config = theme.getValue('gradients', value) || {};
const { angle = 180, kind } = config;
const property = getGradientProperty(config);
const percentages = getGradientPercentages(config);
const gradientAngle = kind === 'radial' ? 'circle' : `${angle}deg`;

if (!percentages) {
return undefined;
}

return `${property}(${gradientAngle}, ${percentages})`;
}

function gradient({ value }: ParserParams<GradientProperty>) {
const bg = getGradientBackground(value as any);
return {
background: bg,
};
}

function textGradient({ value }: ParserParams<GradientProperty>) {
const baseStyle = gradient({ value } as any);
return {
...baseStyle,
backgroundClip: 'text',
textFillColor: 'transparent',
'-webkit-background-clip': 'text',
'-webkit-text-fill-color': 'transparent',
};
}

export const gradientParsers: GradientsParsers = {
gradient: gradient,
bgGradient: gradient,
textGradient: textGradient,
};
1 change: 1 addition & 0 deletions packages/web/src/parsers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './pseudos';
export * from './gradients';
Loading

0 comments on commit 9bcac4e

Please sign in to comment.