Web related enhancements to merge and simplified tokens (#50)
* Make token types easier to use * fix bug with null token arrays after typing change * ensure styles merge selectors and merge handles className * Change files * switch flatten to use array mapping
This commit is contained in:
Родитель
b7349c6471
Коммит
6a408c2ade
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"comment": "ensure styles merge selectors and merge handles className",
|
||||
"packageName": "@uifabricshared/foundation-settings",
|
||||
"email": "jasonmo360@gmail.com",
|
||||
"commit": "30d9a31ad57f098ab1b6074fd975dc157e64fdc8",
|
||||
"date": "2019-10-30T07:05:21.836Z"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"comment": "Make token types easier to use",
|
||||
"packageName": "@uifabricshared/foundation-tokens",
|
||||
"email": "jasonmo360@gmail.com",
|
||||
"commit": "30d9a31ad57f098ab1b6074fd975dc157e64fdc8",
|
||||
"date": "2019-10-30T07:05:33.247Z"
|
||||
}
|
|
@ -5,6 +5,7 @@ import { IStyleProp } from './Styles.types';
|
|||
interface IProps {
|
||||
root: {
|
||||
prop1: string;
|
||||
className?: string;
|
||||
style: IStyleProp<{
|
||||
fontFamily?: string;
|
||||
fontWeight?: 'light' | 'normal' | 'bold';
|
||||
|
@ -19,6 +20,7 @@ interface IProps {
|
|||
|
||||
const settingsDefault: IComponentSettings<IProps> = {
|
||||
root: {
|
||||
className: 'foo bar',
|
||||
style: {
|
||||
fontFamily: 'Calibri',
|
||||
fontWeight: 'normal',
|
||||
|
@ -30,6 +32,7 @@ const settingsDefault: IComponentSettings<IProps> = {
|
|||
|
||||
const settingsBase: IComponentSettings<IProps> = {
|
||||
root: {
|
||||
className: 'baz',
|
||||
style: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
|
@ -105,6 +108,7 @@ describe('Merge settings tests', () => {
|
|||
const merged = mergeSettings(settingsDefault, settingsBase);
|
||||
expect(merged).toEqual({
|
||||
root: {
|
||||
className: 'foo bar baz',
|
||||
style: {
|
||||
fontFamily: 'Calibri',
|
||||
fontWeight: 'bold',
|
||||
|
@ -137,6 +141,7 @@ describe('Merge settings tests', () => {
|
|||
const merged = mergeSettings(settingsBase, settingsNormal);
|
||||
expect(merged).toEqual({
|
||||
root: {
|
||||
className: 'baz',
|
||||
style: {
|
||||
fontFamily: 'Calibri Body',
|
||||
fontWeight: 'bold',
|
||||
|
@ -161,6 +166,7 @@ describe('Merge settings tests', () => {
|
|||
const merged = mergeSettings(settingsDefault, settingsBase, settingsNormal);
|
||||
expect(merged).toEqual({
|
||||
root: {
|
||||
className: 'foo bar baz',
|
||||
style: {
|
||||
fontFamily: 'Calibri Body',
|
||||
fontWeight: 'bold',
|
||||
|
|
|
@ -15,6 +15,10 @@ function _mergeStyles(_options: IMergeOptions, ...objs: (IStyleProp<object>)[]):
|
|||
return mergeAndFlattenStyles(undefined, undefined, ...objs);
|
||||
}
|
||||
|
||||
function _mergeClassName(_options: IMergeOptions, ...names: any[]): string | undefined {
|
||||
return names.filter(v => v && typeof v === 'string').join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* styles should be flattened and merged
|
||||
* tokens should be merged one level
|
||||
|
@ -23,6 +27,7 @@ function _mergeStyles(_options: IMergeOptions, ...objs: (IStyleProp<object>)[]):
|
|||
const _recurseOptions = {
|
||||
style: _mergeStyles,
|
||||
tokens: true,
|
||||
className: _mergeClassName,
|
||||
_overrides: _mergeCollection
|
||||
};
|
||||
|
||||
|
@ -43,7 +48,11 @@ const _mergeCollectionOptions: IMergeOptions = {
|
|||
};
|
||||
|
||||
const _mergePropsOptions: IMergeOptions = {
|
||||
recurse: { style: _mergeStyles, tokens: true }
|
||||
recurse: {
|
||||
style: _mergeStyles,
|
||||
tokens: true,
|
||||
className: _mergeClassName
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ interface IFakeStyle {
|
|||
color?: string;
|
||||
fontFamily?: string;
|
||||
borderWidth?: number;
|
||||
':hover'?: IFakeStyle;
|
||||
}
|
||||
|
||||
const styleFinalizer: IFinalizeStyle = (target: IFakeStyle) => {
|
||||
|
@ -96,6 +97,36 @@ const sMergedFinal: IFakeStyleProp = {
|
|||
...s2Final
|
||||
};
|
||||
|
||||
const sSelector: IFakeStyleProp = {
|
||||
borderWidth: 1,
|
||||
':hover': {
|
||||
borderWidth: 2,
|
||||
fontFamily: 'primary'
|
||||
}
|
||||
};
|
||||
|
||||
const sSelector2: IFakeStyleProp = {
|
||||
backgroundColor: 'white',
|
||||
':hover': {
|
||||
backgroundColor: 'black',
|
||||
borderWidth: 3
|
||||
}
|
||||
};
|
||||
|
||||
const sArraySelector: IFakeStyleProp = [[sSelector]];
|
||||
|
||||
const sArraySelector2: IFakeStyleProp = [sSelector2];
|
||||
|
||||
const sMergedSelectors: IFakeStyleProp = {
|
||||
borderWidth: 1,
|
||||
backgroundColor: 'white',
|
||||
':hover': {
|
||||
borderWidth: 3,
|
||||
fontFamily: 'primary',
|
||||
backgroundColor: 'black'
|
||||
}
|
||||
};
|
||||
|
||||
describe('Style flatten and merge tests', () => {
|
||||
test('flatten recursive arrays', () => {
|
||||
const flattened = flattenStyle(s1);
|
||||
|
@ -113,6 +144,16 @@ describe('Style flatten and merge tests', () => {
|
|||
expect(merged).toEqual(sMerged);
|
||||
});
|
||||
|
||||
test('merge with sub objects', () => {
|
||||
const merged = mergeAndFlattenStyles(undefined, undefined, sSelector, sSelector2);
|
||||
expect(merged).toEqual(sMergedSelectors);
|
||||
});
|
||||
|
||||
test('merge sub objects in arrays', () => {
|
||||
const merged = mergeAndFlattenStyles(undefined, undefined, sArraySelector, sArraySelector2);
|
||||
expect(merged).toEqual(sMergedSelectors);
|
||||
});
|
||||
|
||||
test('finalize single style', () => {
|
||||
const final = mergeAndFlattenStyles(styleFinalizer, s1);
|
||||
expect(final).toEqual(s1flattenFinal);
|
||||
|
|
|
@ -15,12 +15,7 @@ export function flattenStyle(style: IStyleProp<object>): object {
|
|||
if (!Array.isArray(style)) {
|
||||
return style;
|
||||
}
|
||||
|
||||
const result = {};
|
||||
for (let i = 0, styleLength = style.length; i < styleLength; ++i) {
|
||||
Object.assign(result, flattenStyle(style[i]));
|
||||
}
|
||||
return result;
|
||||
return immutableMerge(...style.map(v => flattenStyle(v)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -141,16 +141,23 @@ export function buildComponentTokens<TProps extends object, TTheme>(
|
|||
// iterate through each factory and generate a handler for it. Note that even if no styleFactories
|
||||
// are provided within it will still generate the handler to do style caching and finalization
|
||||
Object.getOwnPropertyNames(factories).forEach(slot => {
|
||||
const factorySet = factories[slot].styleFactories;
|
||||
const factoriesBase = factories[slot].styleFactories;
|
||||
const mappings: ITokensForSlot<TProps, TTheme> = { toStyle: [], toTokens: [], functions: [] };
|
||||
const { toStyle, toTokens, functions } = mappings;
|
||||
const slotKeys = {};
|
||||
|
||||
// if there are style factories provided split them into ones that target tokens and ones that target styles
|
||||
if (factorySet) {
|
||||
if (factoriesBase) {
|
||||
const factorySet = Array.isArray(factoriesBase) ? factoriesBase : [factoriesBase];
|
||||
for (const set of factorySet) {
|
||||
if (Array.isArray(set)) {
|
||||
for (const operation of set) {
|
||||
if (typeof set === 'function') {
|
||||
functions.push(set);
|
||||
set._keys.forEach(key => {
|
||||
slotKeys[key as string] = undefined;
|
||||
});
|
||||
} else {
|
||||
const setArray = Array.isArray(set) ? set : [set as IStyleFactoryOperation<TProps, TTheme>];
|
||||
for (const operation of setArray) {
|
||||
slotKeys[operation.source as string] = undefined;
|
||||
const target = operation.target || operation.source;
|
||||
if (hasToken && hasToken(slot, target as string)) {
|
||||
|
@ -159,11 +166,6 @@ export function buildComponentTokens<TProps extends object, TTheme>(
|
|||
toStyle.push(operation);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
functions.push(set);
|
||||
set._keys.forEach(key => {
|
||||
slotKeys[key as string] = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,11 +50,19 @@ export type IOperationSet<TProps, TTheme> = IStyleFactoryOperation<TProps, TThem
|
|||
export type IStyleFactoryFunctionRaw<TProps, TTheme> = (tokenProps: TProps, theme: TTheme) => TProps;
|
||||
export type IStyleFactoryFunction<TProps, TTheme> = IStyleFactoryFunctionRaw<TProps, TTheme> & { _keys: (keyof TProps)[] };
|
||||
|
||||
/**
|
||||
* An entry can be an individual operation, an array of operations, or a token function
|
||||
*/
|
||||
export type IStyleFactoryEntry<TProps, TTheme> =
|
||||
| IStyleFactoryOperation<TProps, TTheme>
|
||||
| IOperationSet<TProps, TTheme>
|
||||
| IStyleFactoryFunction<TProps, TTheme>;
|
||||
|
||||
/**
|
||||
* For a given slot a component author specifies an array of operations and functions to execute to produce props and styles
|
||||
*/
|
||||
export interface ISlotStyleFactories<TProps, TTheme> {
|
||||
styleFactories?: (IOperationSet<TProps, TTheme> | IStyleFactoryFunction<TProps, TTheme>)[];
|
||||
styleFactories?: IStyleFactoryEntry<TProps, TTheme> | IStyleFactoryEntry<TProps, TTheme>[];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче