Files
piratepoet/packages/js/email-editor/src/engine/hooks/use-email-styles.ts
Oluwaseun Olorunsola 912282f57c Move all items to src folder
MAILPOET-6215
2024-11-11 11:53:49 +02:00

111 lines
2.9 KiB
TypeScript

import deepmerge from 'deepmerge';
import { useSelect } from '@wordpress/data';
import { useCallback } from '@wordpress/element';
import { storeName, TypographyProperties } from '../store';
import { useEmailTheme } from './use-email-theme';
interface ElementProperties {
typography: TypographyProperties;
}
export interface StyleProperties {
spacing?: {
padding: {
top: string;
right: string;
bottom: string;
left: string;
};
blockGap: string;
};
typography?: TypographyProperties;
color?: {
background: string;
text: string;
};
elements?: Record<string, ElementProperties>;
}
interface EmailStylesData {
styles: StyleProperties;
defaultStyles: StyleProperties;
updateStyleProp: (path, newValue) => void;
updateStyles: (newStyles: StyleProperties) => void;
}
/**
* Immutably sets a value inside an object. Like `lodash#set`, but returning a
* new object. Treats nullish initial values as empty objects. Clones any
* nested objects. Supports arrays, too.
*
* @param {Object} object Object to set a value in.
* @param {number|string|Array} setPath Path in the object to modify.
* @param {*} value New value to set.
* @return {Object} Cloned object with the new value set.
*/
export function setImmutably(setObject, setPath, value): typeof setObject {
// Normalize path
const path = Array.isArray(setPath) ? [...setPath] : [setPath];
// Shallowly clone the base of the object
const object = Array.isArray(setObject) ? [...setObject] : { ...setObject };
const leaf = path.pop();
// Traverse object from root to leaf, shallowly cloning at each level
let prev = object;
path.forEach((key) => {
const lvl = prev[key];
prev[key] = Array.isArray(lvl) ? [...lvl] : { ...lvl };
prev = prev[key];
});
prev[leaf] = value;
return object;
}
export const useEmailStyles = (): EmailStylesData => {
const { templateTheme, updateTemplateTheme } = useEmailTheme();
// This is email level styling stored in post meta.
const styles = templateTheme?.styles;
// Default styles from theme.json.
const { styles: defaultStyles } = useSelect((select) => ({
styles: select(storeName).getStyles(),
}));
// Update email styles.
const updateStyles = useCallback(
(newStyles) => {
const newTheme = {
...templateTheme,
styles: newStyles,
};
updateTemplateTheme(newTheme);
},
[updateTemplateTheme, templateTheme],
);
// Update an email style prop.
const updateStyleProp = useCallback(
(path, newValue) => {
const newTheme = setImmutably(
templateTheme,
['styles', ...path],
newValue,
);
updateTemplateTheme(newTheme);
},
[updateTemplateTheme, templateTheme],
);
return {
styles: deepmerge.all([defaultStyles || {}, styles || {}]),
defaultStyles,
updateStyleProp,
updateStyles,
};
};