@animus-ui/core 0.1.1-beta.9 → 0.1.1-e4cdacd2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/Animus.d.ts +2 -2
- package/dist/compatTheme.d.ts +7 -0
- package/dist/index.js +1229 -0
- package/dist/legacy/config.d.ts +2 -1
- package/dist/legacy/createParser.d.ts +0 -7
- package/dist/properties/styledOptions.d.ts +2 -2
- package/dist/styles/createParser.d.ts +0 -7
- package/dist/styles/createPropertyStyle.d.ts +2 -1
- package/dist/types/config.d.ts +9 -3
- package/dist/types/props.d.ts +0 -9
- package/package.json +4 -4
- package/dist/index.cjs.js +0 -1
- package/dist/index.esm.js +0 -1
package/dist/index.js
ADDED
|
@@ -0,0 +1,1229 @@
|
|
|
1
|
+
import { isNumber, get, isArray, isObject, isString, isUndefined, identity, mapValues, omit, intersection, merge, pick, isEmpty, set, keys } from 'lodash';
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
|
|
4
|
+
const createScale = () => [];
|
|
5
|
+
|
|
6
|
+
const percentageOrAbsolute = (coordinate) => {
|
|
7
|
+
if (coordinate === 0) {
|
|
8
|
+
return coordinate;
|
|
9
|
+
}
|
|
10
|
+
if (coordinate <= 1 && coordinate >= -1) {
|
|
11
|
+
return `${coordinate * 100}%`;
|
|
12
|
+
}
|
|
13
|
+
return `${coordinate}px`;
|
|
14
|
+
};
|
|
15
|
+
const valueWithUnit = /(-?\d*\.?\d+)(%|\w*)/;
|
|
16
|
+
const size = (value) => {
|
|
17
|
+
if (isNumber(value)) {
|
|
18
|
+
return percentageOrAbsolute(value);
|
|
19
|
+
}
|
|
20
|
+
if (value.includes('calc')) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
const [match, number, unit] = valueWithUnit.exec(value) || [];
|
|
24
|
+
if (match === undefined) {
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
const numericValue = parseFloat(number);
|
|
28
|
+
return !unit ? percentageOrAbsolute(numericValue) : `${numericValue}${unit}`;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const gridItemMap = {
|
|
32
|
+
max: 'max-content',
|
|
33
|
+
min: 'min-content',
|
|
34
|
+
};
|
|
35
|
+
const unitlessNumber = new RegExp(/^[0-9]*$/);
|
|
36
|
+
const isUnitlessNumber = (val) => unitlessNumber.test(val);
|
|
37
|
+
const gridItem = (item) => {
|
|
38
|
+
const template = isUnitlessNumber(item)
|
|
39
|
+
? `${item}fr`
|
|
40
|
+
: get(gridItemMap, item, item);
|
|
41
|
+
return `minmax(0, ${template})`;
|
|
42
|
+
};
|
|
43
|
+
const repeatGridItem = (item, count) => {
|
|
44
|
+
const template = gridItem(item);
|
|
45
|
+
return count > 1 ? `repeat(${count}, ${template})` : template;
|
|
46
|
+
};
|
|
47
|
+
const parseGridRatio = (val) => {
|
|
48
|
+
const items = val.split(':');
|
|
49
|
+
let repeated = ['', 0];
|
|
50
|
+
let gridStyle = '';
|
|
51
|
+
for (let i = 0; i < items.length + 1; i += 1) {
|
|
52
|
+
const delimiter = gridStyle.length > 0 ? ' ' : '';
|
|
53
|
+
const curr = items[i];
|
|
54
|
+
if (repeated?.[0] !== curr) {
|
|
55
|
+
if (repeated[0].length)
|
|
56
|
+
gridStyle += delimiter + repeatGridItem(...repeated);
|
|
57
|
+
if (curr)
|
|
58
|
+
repeated = [curr, 1];
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
repeated[1] += 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return gridStyle;
|
|
65
|
+
};
|
|
66
|
+
const gridItemRatio = (val) => {
|
|
67
|
+
return isNumber(val) ? repeatGridItem('1', val) : parseGridRatio(val);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const numberToTemplate = (val, template) => (typeof val === 'number' ? template(val) : val);
|
|
71
|
+
const numberToPx = (val) => {
|
|
72
|
+
return numberToTemplate(val, (pixels) => `${pixels}px`);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const borderShorthand = (val) => {
|
|
76
|
+
return numberToTemplate(val, (width) => `${width}px solid currentColor`);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const compatTheme = {
|
|
80
|
+
breakpoints: {
|
|
81
|
+
xs: 480,
|
|
82
|
+
sm: 768,
|
|
83
|
+
md: 1024,
|
|
84
|
+
lg: 1200,
|
|
85
|
+
xl: 1440,
|
|
86
|
+
},
|
|
87
|
+
spacing: [0, 4, 8, 12, 16, 24, 32, 40, 48, 64, 96],
|
|
88
|
+
fontSize: [64, 44, 34, 26, 22, 20, 18, 16, 14],
|
|
89
|
+
lineHeight: {
|
|
90
|
+
body: 1.5,
|
|
91
|
+
heading: 1,
|
|
92
|
+
},
|
|
93
|
+
fontWeight: [400, 600, 700],
|
|
94
|
+
fontFamily: {
|
|
95
|
+
body: 'Verdana, sans-serif',
|
|
96
|
+
heading: 'Verdana, Lato, sans-serif',
|
|
97
|
+
monospace: 'monospace',
|
|
98
|
+
},
|
|
99
|
+
radii: [2, 4, 6, 8],
|
|
100
|
+
borders: [1, 2, 3],
|
|
101
|
+
colors: {},
|
|
102
|
+
modes: {},
|
|
103
|
+
mode: undefined,
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const lookupScaleValue = (val, scale, theme) => {
|
|
107
|
+
if (isArray(scale)) {
|
|
108
|
+
return val;
|
|
109
|
+
}
|
|
110
|
+
if (isObject(scale)) {
|
|
111
|
+
return get(scale, val);
|
|
112
|
+
}
|
|
113
|
+
if (isString(scale)) {
|
|
114
|
+
const usedScale = get(theme, scale, get(compatTheme, scale));
|
|
115
|
+
if (!usedScale)
|
|
116
|
+
return undefined;
|
|
117
|
+
return isArray(usedScale) ? val : get(usedScale, val);
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const createPropertyStyle = (value, props, config) => {
|
|
123
|
+
const styles = {};
|
|
124
|
+
const { transform = identity, property, properties = [property], scale, variable, } = config;
|
|
125
|
+
const alwaysTransform = scale === undefined || isArray(scale);
|
|
126
|
+
if (isUndefined(value)) {
|
|
127
|
+
return styles;
|
|
128
|
+
}
|
|
129
|
+
let useTransform = false;
|
|
130
|
+
let intermediateValue;
|
|
131
|
+
let scaleValue;
|
|
132
|
+
switch (typeof value) {
|
|
133
|
+
case 'number':
|
|
134
|
+
case 'string':
|
|
135
|
+
scaleValue = lookupScaleValue(value, scale, props?.theme);
|
|
136
|
+
useTransform = scaleValue !== undefined || alwaysTransform;
|
|
137
|
+
intermediateValue = scaleValue ?? value;
|
|
138
|
+
break;
|
|
139
|
+
case 'function':
|
|
140
|
+
if (props.theme) {
|
|
141
|
+
intermediateValue = value(props.theme);
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
default:
|
|
145
|
+
return styles;
|
|
146
|
+
}
|
|
147
|
+
// for each property look up the scale value from theme if passed and apply any
|
|
148
|
+
// final transforms to the value
|
|
149
|
+
properties.forEach((property) => {
|
|
150
|
+
let styleValue = intermediateValue;
|
|
151
|
+
if (useTransform && !isUndefined(styleValue)) {
|
|
152
|
+
styleValue = transform(styleValue, property, props);
|
|
153
|
+
}
|
|
154
|
+
switch (typeof styleValue) {
|
|
155
|
+
case 'number':
|
|
156
|
+
case 'string':
|
|
157
|
+
return (styles[property] = styleValue);
|
|
158
|
+
case 'object':
|
|
159
|
+
return Object.assign(styles, styleValue);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
if (variable) {
|
|
163
|
+
let styleValue = intermediateValue;
|
|
164
|
+
if (useTransform && !isUndefined(styleValue)) {
|
|
165
|
+
styleValue = transform(styleValue, property, props);
|
|
166
|
+
}
|
|
167
|
+
if (styleValue && typeof styleValue !== 'object') {
|
|
168
|
+
styles[variable] = styleValue;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// return the resulting styles object
|
|
172
|
+
return styles;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const SHORTHAND_PROPERTIES = [
|
|
176
|
+
'border',
|
|
177
|
+
'borderTop',
|
|
178
|
+
'borderBottom',
|
|
179
|
+
'borderLeft',
|
|
180
|
+
'borderRight',
|
|
181
|
+
'borderWidth',
|
|
182
|
+
'borderStyle',
|
|
183
|
+
'borderColor',
|
|
184
|
+
'background',
|
|
185
|
+
'flex',
|
|
186
|
+
'margin',
|
|
187
|
+
'padding',
|
|
188
|
+
'transition',
|
|
189
|
+
'gap',
|
|
190
|
+
'grid',
|
|
191
|
+
'gridArea',
|
|
192
|
+
'gridColumn',
|
|
193
|
+
'gridRow',
|
|
194
|
+
'gridTemplate',
|
|
195
|
+
'overflow',
|
|
196
|
+
'transition',
|
|
197
|
+
];
|
|
198
|
+
const SORT = {
|
|
199
|
+
A_BEFORE_B: -1,
|
|
200
|
+
B_BEFORE_A: 1,
|
|
201
|
+
EQUAL: 1,
|
|
202
|
+
};
|
|
203
|
+
const compare = (a, b) => {
|
|
204
|
+
if (a < b)
|
|
205
|
+
return SORT.A_BEFORE_B;
|
|
206
|
+
if (b < a)
|
|
207
|
+
return SORT.B_BEFORE_A;
|
|
208
|
+
return SORT.EQUAL;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Orders all properties by the most dependent props
|
|
212
|
+
* @param config
|
|
213
|
+
*/
|
|
214
|
+
const orderPropNames = (config) => Object.keys(config).sort((a, b) => {
|
|
215
|
+
const { [a]: aConf, [b]: bConf } = config;
|
|
216
|
+
const { property: aProp, properties: aProperties = [] } = aConf;
|
|
217
|
+
const { property: bProp, properties: bProperties = [] } = bConf;
|
|
218
|
+
const aIsShorthand = SHORTHAND_PROPERTIES.includes(aProp);
|
|
219
|
+
const bIsShorthand = SHORTHAND_PROPERTIES.includes(bProp);
|
|
220
|
+
if (aIsShorthand && bIsShorthand) {
|
|
221
|
+
const aNum = aProperties.length;
|
|
222
|
+
const bNum = bProperties.length;
|
|
223
|
+
if (aProp !== bProp) {
|
|
224
|
+
return compare(SHORTHAND_PROPERTIES.indexOf(aProp), SHORTHAND_PROPERTIES.indexOf(bProp));
|
|
225
|
+
}
|
|
226
|
+
if (aProp === bProp) {
|
|
227
|
+
if (aNum === 0)
|
|
228
|
+
return SORT.A_BEFORE_B;
|
|
229
|
+
if (bNum === 0)
|
|
230
|
+
return SORT.B_BEFORE_A;
|
|
231
|
+
}
|
|
232
|
+
return compare(bNum, aNum);
|
|
233
|
+
}
|
|
234
|
+
if (aIsShorthand)
|
|
235
|
+
return SORT.A_BEFORE_B;
|
|
236
|
+
if (bIsShorthand)
|
|
237
|
+
return SORT.B_BEFORE_A;
|
|
238
|
+
return SORT.EQUAL;
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const BREAKPOINT_KEYS$1 = ['_', 'xs', 'sm', 'md', 'lg', 'xl'];
|
|
242
|
+
/**
|
|
243
|
+
* Destructures the themes breakpoints into an ordered structure to traverse
|
|
244
|
+
*/
|
|
245
|
+
const templateMediaQuery$1 = (breakpoint) => `@media screen and (min-width: ${breakpoint}px)`;
|
|
246
|
+
const createMediaQueries$1 = (breakpoints) => {
|
|
247
|
+
if (breakpoints === undefined)
|
|
248
|
+
return null;
|
|
249
|
+
const { xs, sm, md, lg, xl } = breakpoints ?? {};
|
|
250
|
+
// Ensure order for mapping
|
|
251
|
+
return {
|
|
252
|
+
map: mapValues(breakpoints, templateMediaQuery$1),
|
|
253
|
+
array: [xs, sm, md, lg, xl].map(templateMediaQuery$1),
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
const isMediaArray$1 = (val) => Array.isArray(val);
|
|
257
|
+
const isMediaMap$1 = (val) => intersection(Object.keys(val), BREAKPOINT_KEYS$1).length > 0;
|
|
258
|
+
const objectParser$1 = (value, props, config, breakpoints) => {
|
|
259
|
+
const styles = {};
|
|
260
|
+
const { _, ...rest } = value;
|
|
261
|
+
// the keyof 'base' is base styles
|
|
262
|
+
if (_)
|
|
263
|
+
Object.assign(styles, createPropertyStyle(_, props, config));
|
|
264
|
+
// Map over remaining keys and merge the corresponding breakpoint styles
|
|
265
|
+
// for that property.
|
|
266
|
+
Object.keys(breakpoints).forEach((breakpointKey) => {
|
|
267
|
+
const bpStyles = rest[breakpointKey];
|
|
268
|
+
if (typeof bpStyles === 'undefined')
|
|
269
|
+
return;
|
|
270
|
+
Object.assign(styles, {
|
|
271
|
+
[breakpoints[breakpointKey]]: createPropertyStyle(bpStyles, props, config),
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
return styles;
|
|
275
|
+
};
|
|
276
|
+
const arrayParser$1 = (value, props, config, breakpoints) => {
|
|
277
|
+
const styles = {};
|
|
278
|
+
const [_, ...rest] = value;
|
|
279
|
+
// the first index is base styles
|
|
280
|
+
if (_)
|
|
281
|
+
Object.assign(styles, createPropertyStyle(_, props, config));
|
|
282
|
+
// Map over each value in the array and merge the corresponding breakpoint styles
|
|
283
|
+
// for that property.
|
|
284
|
+
rest.forEach((val, i) => {
|
|
285
|
+
const breakpointKey = breakpoints[i];
|
|
286
|
+
if (!breakpointKey || typeof val === 'undefined')
|
|
287
|
+
return;
|
|
288
|
+
Object.assign(styles, {
|
|
289
|
+
[breakpointKey]: createPropertyStyle(val, props, config),
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
return styles;
|
|
293
|
+
};
|
|
294
|
+
const orderBreakpoints$1 = (styles, breakpoints) => {
|
|
295
|
+
const orderedStyles = omit(styles, breakpoints);
|
|
296
|
+
breakpoints.forEach((bp) => {
|
|
297
|
+
if (styles[bp]) {
|
|
298
|
+
orderedStyles[bp] = styles[bp];
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
return orderedStyles;
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const renderPropValue$1 = (styles, prop, props, property, ctx) => {
|
|
305
|
+
const value = get(props, prop);
|
|
306
|
+
switch (typeof value) {
|
|
307
|
+
case 'string':
|
|
308
|
+
case 'number':
|
|
309
|
+
case 'function':
|
|
310
|
+
return Object.assign(styles, createPropertyStyle(value, props, property));
|
|
311
|
+
// handle any props configured with the responsive notation
|
|
312
|
+
case 'object':
|
|
313
|
+
if (!ctx.mediaQueries) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// If it is an array the order of values is smallest to largest: [_, xs, ...]
|
|
317
|
+
if (isMediaArray$1(value)) {
|
|
318
|
+
return merge(styles, arrayParser$1(value, props, property, ctx.mediaQueries.array));
|
|
319
|
+
}
|
|
320
|
+
// Check to see if value is an object matching the responsive syntax and generate the styles.
|
|
321
|
+
if (value && isMediaMap$1(value)) {
|
|
322
|
+
return merge(styles, objectParser$1(value, props, property, ctx.mediaQueries.map));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
function createParser$1(config) {
|
|
327
|
+
const propNames = orderPropNames(config);
|
|
328
|
+
const ctx = {
|
|
329
|
+
mediaQueries: null,
|
|
330
|
+
};
|
|
331
|
+
const parser = (props, isCss = false) => {
|
|
332
|
+
const styles = {};
|
|
333
|
+
const { theme } = props;
|
|
334
|
+
// Attempt to cache the breakpoints if we have not yet or if theme has become available.
|
|
335
|
+
if (ctx.mediaQueries === null) {
|
|
336
|
+
// Save the breakpoints if we can
|
|
337
|
+
ctx.mediaQueries = createMediaQueries$1(theme?.breakpoints ?? compatTheme.breakpoints);
|
|
338
|
+
}
|
|
339
|
+
if (!isCss) {
|
|
340
|
+
// Loops over all prop names on the configured config to check for configured styles
|
|
341
|
+
propNames.forEach((prop) => {
|
|
342
|
+
const property = config[prop];
|
|
343
|
+
renderPropValue$1(styles, prop, props, property, ctx);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// Loops over all prop names on the configured config to check for configured styles
|
|
348
|
+
Object.keys(props).forEach((prop) => {
|
|
349
|
+
const property = config[prop];
|
|
350
|
+
if (property) {
|
|
351
|
+
renderPropValue$1(styles, prop, props, property, ctx);
|
|
352
|
+
}
|
|
353
|
+
else if (prop !== 'theme') {
|
|
354
|
+
Object.assign(styles, { [prop]: get(props, prop) });
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
if (ctx.mediaQueries !== null)
|
|
359
|
+
return orderBreakpoints$1(styles, ctx.mediaQueries.array);
|
|
360
|
+
return styles;
|
|
361
|
+
};
|
|
362
|
+
// return the parser function with the resulting meta information for further composition
|
|
363
|
+
return Object.assign(parser, { propNames, config });
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* eslint-disable guard-for-in */
|
|
367
|
+
const getSelectors = (base = {}, variants = {}, states = {}, filters) => {
|
|
368
|
+
const rules = {};
|
|
369
|
+
Object.entries(base).forEach(([key, styles]) => {
|
|
370
|
+
if (!filters.includes(key) && isObject(styles)) {
|
|
371
|
+
set(rules, [key, 'base'], styles);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
set(rules, ['primary', 'base', key], styles);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
Object.entries(variants).forEach(([key, { variants: variantConfig }]) => {
|
|
378
|
+
Object.entries(variantConfig).forEach(([option, optionStyles]) => {
|
|
379
|
+
const optionId = `${key}-${option}`;
|
|
380
|
+
Object.entries(optionStyles).forEach(([key, styles]) => {
|
|
381
|
+
if (!filters.includes(key) && isObject(styles)) {
|
|
382
|
+
set(rules, [key, optionId], styles);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
set(rules, ['primary', optionId, key], styles);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
Object.entries(states).forEach(([optionId, optionStyles]) => {
|
|
391
|
+
Object.entries(optionStyles).forEach(([key, styles]) => {
|
|
392
|
+
if (!filters.includes(key) && isObject(styles)) {
|
|
393
|
+
set(rules, [key, optionId], styles);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
set(rules, ['primary', optionId, key], styles);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
return rules;
|
|
401
|
+
};
|
|
402
|
+
const createGetActiveStyleIds = (variants, states) => {
|
|
403
|
+
const vIds = Object.keys(variants);
|
|
404
|
+
const sIds = Object.keys(states);
|
|
405
|
+
return (props) => {
|
|
406
|
+
const activeIds = [];
|
|
407
|
+
vIds.forEach((id) => {
|
|
408
|
+
if (props[id]) {
|
|
409
|
+
activeIds.push(`${id}-${props[id]}`);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
sIds.forEach((id) => {
|
|
413
|
+
if (props[id]) {
|
|
414
|
+
activeIds.push(id);
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
return activeIds;
|
|
418
|
+
};
|
|
419
|
+
};
|
|
420
|
+
const extractBreakpointStyles = (styles, medias) => {
|
|
421
|
+
const unscoped = {};
|
|
422
|
+
const breakpoint = {};
|
|
423
|
+
Object.entries(styles).forEach(([rule, value]) => {
|
|
424
|
+
const target = medias.includes(rule) ? breakpoint : unscoped;
|
|
425
|
+
target[rule] = value;
|
|
426
|
+
});
|
|
427
|
+
return [unscoped, breakpoint];
|
|
428
|
+
};
|
|
429
|
+
const applyOverride = (override = {}, baseResult, breakpointResult, parser, theme, media) => {
|
|
430
|
+
const [overrideStyles, overrideBreakpointStyles] = extractBreakpointStyles(parser({ ...override, theme }, true), media);
|
|
431
|
+
for (const rule in overrideStyles) {
|
|
432
|
+
baseResult[rule] = overrideStyles[rule];
|
|
433
|
+
}
|
|
434
|
+
media.forEach((mq) => {
|
|
435
|
+
const mqOverride = overrideBreakpointStyles[mq];
|
|
436
|
+
if (!mqOverride || isEmpty(mqOverride))
|
|
437
|
+
return;
|
|
438
|
+
if (!breakpointResult[mq]) {
|
|
439
|
+
breakpointResult[mq] = {};
|
|
440
|
+
}
|
|
441
|
+
const mqStyle = breakpointResult[mq];
|
|
442
|
+
for (const rule in mqOverride) {
|
|
443
|
+
mqStyle[rule] = mqOverride[rule];
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
};
|
|
447
|
+
const applyStyle = (resultStyles, config, props, ctx) => {
|
|
448
|
+
const { base } = config;
|
|
449
|
+
const { parser, getMediaSelectors, getActiveOverrides } = ctx;
|
|
450
|
+
const { theme } = props;
|
|
451
|
+
const overrides = Object.values(pick(config, getActiveOverrides(props)));
|
|
452
|
+
const media = getMediaSelectors(props);
|
|
453
|
+
const [styles, breakpointStyles] = extractBreakpointStyles(parser({ ...base, theme }, true), media);
|
|
454
|
+
for (const rule in styles) {
|
|
455
|
+
resultStyles[rule] = styles[rule];
|
|
456
|
+
}
|
|
457
|
+
overrides.forEach((override) => {
|
|
458
|
+
applyOverride(override, resultStyles, breakpointStyles, parser, theme, media);
|
|
459
|
+
});
|
|
460
|
+
media.forEach((media) => {
|
|
461
|
+
const bp = breakpointStyles[media];
|
|
462
|
+
if (!isEmpty(bp)) {
|
|
463
|
+
resultStyles[media] = bp;
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
};
|
|
467
|
+
const createStylist = (parser, base = {}, variants = {}, states = {}) => {
|
|
468
|
+
const selectorGroups = getSelectors(base, variants, states, parser.propNames);
|
|
469
|
+
const context = {
|
|
470
|
+
parser,
|
|
471
|
+
getMediaSelectors: ({ theme }) => {
|
|
472
|
+
const breakpoints = theme?.breakpoints ?? compatTheme.breakpoints;
|
|
473
|
+
return ['xs', 'sm', 'md', 'lg', 'xl'].map((key) => breakpoints[key]);
|
|
474
|
+
},
|
|
475
|
+
getActiveOverrides: createGetActiveStyleIds(variants, states),
|
|
476
|
+
};
|
|
477
|
+
return (props) => {
|
|
478
|
+
const { vars } = props;
|
|
479
|
+
const result = { ...vars };
|
|
480
|
+
Object.entries(selectorGroups).forEach(([selectorId, config = {}]) => {
|
|
481
|
+
if (selectorId === 'primary') {
|
|
482
|
+
applyStyle(result, config, props, context);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
result[selectorId] = {};
|
|
486
|
+
applyStyle(result[selectorId], config, props, context);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
applyStyle(result, { base: parser(props) }, props, context);
|
|
490
|
+
return result;
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
class AnimusWithAll {
|
|
495
|
+
propRegistry = {};
|
|
496
|
+
groupRegistry = {};
|
|
497
|
+
parser = {};
|
|
498
|
+
baseStyles = {};
|
|
499
|
+
statesConfig = {};
|
|
500
|
+
variants = {};
|
|
501
|
+
activeGroups = {};
|
|
502
|
+
custom = {};
|
|
503
|
+
constructor(props, groups, parser, base, variants, states, activeGroups, custom) {
|
|
504
|
+
this.propRegistry = props;
|
|
505
|
+
this.groupRegistry = groups;
|
|
506
|
+
this.parser = parser;
|
|
507
|
+
this.baseStyles = base;
|
|
508
|
+
this.variants = variants;
|
|
509
|
+
this.statesConfig = states;
|
|
510
|
+
this.activeGroups = activeGroups;
|
|
511
|
+
this.custom = custom;
|
|
512
|
+
}
|
|
513
|
+
asComponent(component) {
|
|
514
|
+
const handler = createStylist(createParser$1({ ...this.parser.config, ...this.custom }), this.baseStyles, this.variants, this.statesConfig);
|
|
515
|
+
return styled(component)(handler);
|
|
516
|
+
}
|
|
517
|
+
build() {
|
|
518
|
+
const handler = createStylist(createParser$1({ ...this.parser.config, ...this.custom }), this.baseStyles, this.variants, this.statesConfig);
|
|
519
|
+
return handler;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
class AnimusWithSystem extends AnimusWithAll {
|
|
523
|
+
constructor(props, groups, parser, base, variants, states, activeGroups) {
|
|
524
|
+
super(props, groups, parser, base, variants, states, activeGroups, {});
|
|
525
|
+
}
|
|
526
|
+
props(config) {
|
|
527
|
+
return new AnimusWithAll(this.propRegistry, this.groupRegistry, this.parser, this.baseStyles, this.variants, this.statesConfig, this.activeGroups, config);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
class AnimusWithStates extends AnimusWithSystem {
|
|
531
|
+
constructor(props, groups, parser, base, variants, states) {
|
|
532
|
+
super(props, groups, parser, base, variants, states, {});
|
|
533
|
+
}
|
|
534
|
+
groups(config) {
|
|
535
|
+
return new AnimusWithSystem(this.propRegistry, this.groupRegistry, this.parser, this.baseStyles, this.variants, this.statesConfig, config);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
class AnimusWithVariants extends AnimusWithStates {
|
|
539
|
+
constructor(props, groups, parser, base, variants) {
|
|
540
|
+
super(props, groups, parser, base, variants, {});
|
|
541
|
+
}
|
|
542
|
+
states(config) {
|
|
543
|
+
return new AnimusWithStates(this.propRegistry, this.groupRegistry, this.parser, this.baseStyles, this.variants, config);
|
|
544
|
+
}
|
|
545
|
+
variant(options) {
|
|
546
|
+
const prop = options.prop || 'variant';
|
|
547
|
+
return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.parser, this.baseStyles, merge(this.variants, { [prop]: options }));
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
class AnimusWithBase extends AnimusWithVariants {
|
|
551
|
+
constructor(props, groups, parser, base) {
|
|
552
|
+
super(props, groups, parser, base, {});
|
|
553
|
+
}
|
|
554
|
+
variant(options) {
|
|
555
|
+
const prop = options.prop || 'variant';
|
|
556
|
+
return new AnimusWithVariants(this.propRegistry, this.groupRegistry, this.parser, this.baseStyles, merge(this.variants, { [prop]: options }));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
class Animus extends AnimusWithBase {
|
|
560
|
+
constructor(props, groups) {
|
|
561
|
+
super(props, groups, createParser$1(props), {});
|
|
562
|
+
}
|
|
563
|
+
styles(config) {
|
|
564
|
+
return new AnimusWithBase(this.propRegistry, this.groupRegistry, this.parser, config);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
class AnimusConfig {
|
|
569
|
+
#props = {};
|
|
570
|
+
#groups = {};
|
|
571
|
+
constructor(config, groups) {
|
|
572
|
+
this.#props = config || {};
|
|
573
|
+
this.#groups = groups || {};
|
|
574
|
+
}
|
|
575
|
+
addGroup(name, config) {
|
|
576
|
+
const newGroup = {
|
|
577
|
+
[name]: Object.keys(config),
|
|
578
|
+
};
|
|
579
|
+
return new AnimusConfig({ ...this.#props, ...config }, { ...this.#groups, ...newGroup });
|
|
580
|
+
}
|
|
581
|
+
build() {
|
|
582
|
+
const props = this.#props;
|
|
583
|
+
const groups = this.#groups;
|
|
584
|
+
return new Animus(props, groups);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const createAnimus = () => new AnimusConfig();
|
|
589
|
+
|
|
590
|
+
const color = {
|
|
591
|
+
color: { property: 'color', scale: 'colors' },
|
|
592
|
+
textColor: { property: 'color', scale: 'colors' },
|
|
593
|
+
bg: { property: 'backgroundColor', scale: 'colors' },
|
|
594
|
+
borderColor: { property: 'borderColor', scale: 'colors' },
|
|
595
|
+
borderColorX: {
|
|
596
|
+
property: 'borderColor',
|
|
597
|
+
properties: ['borderLeftColor', 'borderRightColor'],
|
|
598
|
+
scale: 'colors',
|
|
599
|
+
},
|
|
600
|
+
borderColorY: {
|
|
601
|
+
property: 'borderColor',
|
|
602
|
+
properties: ['borderTopColor', 'borderBottomColor'],
|
|
603
|
+
scale: 'colors',
|
|
604
|
+
},
|
|
605
|
+
borderColorLeft: { property: 'borderLeftColor', scale: 'colors' },
|
|
606
|
+
borderColorRight: { property: 'borderRightColor', scale: 'colors' },
|
|
607
|
+
borderColorTop: { property: 'borderTopColor', scale: 'colors' },
|
|
608
|
+
borderColorBottom: { property: 'borderBottomColor', scale: 'colors' },
|
|
609
|
+
};
|
|
610
|
+
const border = {
|
|
611
|
+
border: {
|
|
612
|
+
property: 'border',
|
|
613
|
+
scale: 'borders',
|
|
614
|
+
transform: borderShorthand,
|
|
615
|
+
},
|
|
616
|
+
borderX: {
|
|
617
|
+
property: 'border',
|
|
618
|
+
properties: ['borderLeft', 'borderRight'],
|
|
619
|
+
scale: 'borders',
|
|
620
|
+
transform: borderShorthand,
|
|
621
|
+
},
|
|
622
|
+
borderY: {
|
|
623
|
+
property: 'border',
|
|
624
|
+
properties: ['borderTop', 'borderBottom'],
|
|
625
|
+
scale: 'borders',
|
|
626
|
+
transform: borderShorthand,
|
|
627
|
+
},
|
|
628
|
+
borderTop: {
|
|
629
|
+
property: 'borderTop',
|
|
630
|
+
scale: 'borders',
|
|
631
|
+
transform: borderShorthand,
|
|
632
|
+
},
|
|
633
|
+
borderRight: {
|
|
634
|
+
property: 'borderRight',
|
|
635
|
+
scale: 'borders',
|
|
636
|
+
transform: borderShorthand,
|
|
637
|
+
},
|
|
638
|
+
borderBottom: {
|
|
639
|
+
property: 'borderBottom',
|
|
640
|
+
scale: 'borders',
|
|
641
|
+
transform: borderShorthand,
|
|
642
|
+
},
|
|
643
|
+
borderLeft: {
|
|
644
|
+
property: 'borderLeft',
|
|
645
|
+
scale: 'borders',
|
|
646
|
+
transform: borderShorthand,
|
|
647
|
+
},
|
|
648
|
+
// Width
|
|
649
|
+
borderWidth: { property: 'borderWidth' },
|
|
650
|
+
borderWidthX: {
|
|
651
|
+
property: 'borderWidth',
|
|
652
|
+
properties: ['borderLeftWidth', 'borderRightWidth'],
|
|
653
|
+
},
|
|
654
|
+
borderWidthY: {
|
|
655
|
+
property: 'borderWidth',
|
|
656
|
+
properties: ['borderTopWidth', 'borderBottomWidth'],
|
|
657
|
+
},
|
|
658
|
+
borderWidthLeft: { property: 'borderLeftWidth' },
|
|
659
|
+
borderWidthRight: { property: 'borderRightWidth' },
|
|
660
|
+
borderWidthTop: { property: 'borderTopWidth' },
|
|
661
|
+
borderWidthBottom: { property: 'borderBottomWidth' },
|
|
662
|
+
// Radius
|
|
663
|
+
borderRadius: {
|
|
664
|
+
property: 'borderRadius',
|
|
665
|
+
scale: 'radii',
|
|
666
|
+
transform: numberToPx,
|
|
667
|
+
},
|
|
668
|
+
borderRadiusLeft: {
|
|
669
|
+
property: 'borderRadius',
|
|
670
|
+
properties: ['borderTopLeftRadius', 'borderBottomLeftRadius'],
|
|
671
|
+
scale: 'radii',
|
|
672
|
+
transform: numberToPx,
|
|
673
|
+
},
|
|
674
|
+
borderRadiusTop: {
|
|
675
|
+
property: 'borderRadius',
|
|
676
|
+
properties: ['borderTopLeftRadius', 'borderTopRightRadius'],
|
|
677
|
+
scale: 'radii',
|
|
678
|
+
transform: numberToPx,
|
|
679
|
+
},
|
|
680
|
+
borderRadiusBottom: {
|
|
681
|
+
property: 'borderRadius',
|
|
682
|
+
properties: ['borderBottomLeftRadius', 'borderBottomRightRadius'],
|
|
683
|
+
scale: 'radii',
|
|
684
|
+
transform: numberToPx,
|
|
685
|
+
},
|
|
686
|
+
borderRadiusRight: {
|
|
687
|
+
property: 'borderRadius',
|
|
688
|
+
properties: ['borderTopRightRadius', 'borderBottomRightRadius'],
|
|
689
|
+
scale: 'radii',
|
|
690
|
+
transform: numberToPx,
|
|
691
|
+
},
|
|
692
|
+
borderRadiusTopLeft: {
|
|
693
|
+
property: 'borderTopLeftRadius',
|
|
694
|
+
scale: 'radii',
|
|
695
|
+
transform: numberToPx,
|
|
696
|
+
},
|
|
697
|
+
borderRadiusTopRight: {
|
|
698
|
+
property: 'borderTopRightRadius',
|
|
699
|
+
scale: 'radii',
|
|
700
|
+
transform: numberToPx,
|
|
701
|
+
},
|
|
702
|
+
borderRadiusBottomRight: {
|
|
703
|
+
property: 'borderBottomRightRadius',
|
|
704
|
+
scale: 'radii',
|
|
705
|
+
transform: numberToPx,
|
|
706
|
+
},
|
|
707
|
+
borderRadiusBottomLeft: {
|
|
708
|
+
property: 'borderBottomLeftRadius',
|
|
709
|
+
scale: 'radii',
|
|
710
|
+
transform: numberToPx,
|
|
711
|
+
},
|
|
712
|
+
// Style
|
|
713
|
+
borderStyle: { property: 'borderStyle' },
|
|
714
|
+
borderStyleX: {
|
|
715
|
+
property: 'borderStyle',
|
|
716
|
+
properties: ['borderLeftStyle', 'borderRightStyle'],
|
|
717
|
+
},
|
|
718
|
+
borderStyleY: {
|
|
719
|
+
property: 'borderStyle',
|
|
720
|
+
properties: ['borderTopStyle', 'borderBottomStyle'],
|
|
721
|
+
},
|
|
722
|
+
borderStyleLeft: { property: 'borderLeftStyle' },
|
|
723
|
+
borderStyleRight: { property: 'borderRightStyle' },
|
|
724
|
+
borderStyleTop: { property: 'borderTopStyle' },
|
|
725
|
+
borderStyleBottom: { property: 'borderBottomStyle' },
|
|
726
|
+
};
|
|
727
|
+
const gaps = {
|
|
728
|
+
gap: { property: 'gap', scale: 'spacing' },
|
|
729
|
+
rowGap: { property: 'rowGap', scale: 'spacing' },
|
|
730
|
+
columnGap: { property: 'columnGap', scale: 'spacing' },
|
|
731
|
+
};
|
|
732
|
+
const selfAlignments = {
|
|
733
|
+
justifySelf: { property: 'justifySelf' },
|
|
734
|
+
alignSelf: { property: 'alignSelf' },
|
|
735
|
+
gridArea: { property: 'gridArea' },
|
|
736
|
+
area: { property: 'gridArea' },
|
|
737
|
+
};
|
|
738
|
+
const alignments = {
|
|
739
|
+
justifyContent: { property: 'justifyContent' },
|
|
740
|
+
justifyItems: { property: 'justifyItems' },
|
|
741
|
+
alignItems: { property: 'alignItems' },
|
|
742
|
+
alignContent: { property: 'alignContent' },
|
|
743
|
+
...selfAlignments,
|
|
744
|
+
};
|
|
745
|
+
const flexItems = {
|
|
746
|
+
flexBasis: { property: 'flexBasis' },
|
|
747
|
+
flexShrink: { property: 'flexShrink' },
|
|
748
|
+
flexGrow: { property: 'flexGrow' },
|
|
749
|
+
order: { property: 'order' },
|
|
750
|
+
};
|
|
751
|
+
const flex = {
|
|
752
|
+
flexDirection: { property: 'flexDirection' },
|
|
753
|
+
flexWrap: { property: 'flexWrap' },
|
|
754
|
+
flex: { property: 'flex' },
|
|
755
|
+
...alignments,
|
|
756
|
+
...flexItems,
|
|
757
|
+
...gaps,
|
|
758
|
+
};
|
|
759
|
+
const gridItems = {
|
|
760
|
+
gridColumn: { property: 'gridColumn' },
|
|
761
|
+
gridRow: { property: 'gridRow' },
|
|
762
|
+
gridColumnStart: { property: 'gridColumnStart' },
|
|
763
|
+
gridRowStart: { property: 'gridRowStart' },
|
|
764
|
+
gridColumnEnd: { property: 'gridColumnEnd' },
|
|
765
|
+
gridRowEnd: { property: 'gridRowEnd' },
|
|
766
|
+
};
|
|
767
|
+
const grid = {
|
|
768
|
+
gridAutoColumns: { property: 'gridAutoColumns' },
|
|
769
|
+
gridAutoRows: { property: 'gridAutoRows' },
|
|
770
|
+
gridTemplateColumns: { property: 'gridTemplateColumns' },
|
|
771
|
+
gridTemplateRows: { property: 'gridTemplateRows' },
|
|
772
|
+
gridTemplateAreas: { property: 'gridTemplateAreas' },
|
|
773
|
+
gridAutoFlow: { property: 'gridAutoFlow' },
|
|
774
|
+
flow: {
|
|
775
|
+
property: 'gridAutoFlow',
|
|
776
|
+
scale: createScale(),
|
|
777
|
+
},
|
|
778
|
+
cols: {
|
|
779
|
+
property: 'gridTemplateColumns',
|
|
780
|
+
transform: gridItemRatio,
|
|
781
|
+
scale: createScale(),
|
|
782
|
+
},
|
|
783
|
+
rows: {
|
|
784
|
+
property: 'gridTemplateRows',
|
|
785
|
+
transform: gridItemRatio,
|
|
786
|
+
scale: createScale(),
|
|
787
|
+
},
|
|
788
|
+
autoRows: {
|
|
789
|
+
property: 'gridAutoRows',
|
|
790
|
+
transform: gridItem,
|
|
791
|
+
},
|
|
792
|
+
autoCols: {
|
|
793
|
+
property: 'gridAutoColumns',
|
|
794
|
+
transform: gridItem,
|
|
795
|
+
},
|
|
796
|
+
alignAll: {
|
|
797
|
+
property: 'justifyContent',
|
|
798
|
+
properties: ['justifyContent', 'alignItems'],
|
|
799
|
+
},
|
|
800
|
+
...alignments,
|
|
801
|
+
...gridItems,
|
|
802
|
+
...gaps,
|
|
803
|
+
};
|
|
804
|
+
const background = {
|
|
805
|
+
background: { property: 'background' },
|
|
806
|
+
backgroundImage: { property: 'backgroundImage' },
|
|
807
|
+
backgroundSize: { property: 'backgroundSize' },
|
|
808
|
+
backgroundRepeat: { property: 'backgroundRepeat' },
|
|
809
|
+
backgroundPosition: { property: 'backgroundPosition' },
|
|
810
|
+
};
|
|
811
|
+
const positioning = {
|
|
812
|
+
position: { property: 'position' },
|
|
813
|
+
inset: {
|
|
814
|
+
property: 'inset',
|
|
815
|
+
properties: ['top', 'right', 'bottom', 'left'],
|
|
816
|
+
transform: size,
|
|
817
|
+
},
|
|
818
|
+
top: { property: 'top', transform: size },
|
|
819
|
+
right: { property: 'right', transform: size },
|
|
820
|
+
bottom: { property: 'bottom', transform: size },
|
|
821
|
+
left: { property: 'left', transform: size },
|
|
822
|
+
zIndex: { property: 'zIndex' },
|
|
823
|
+
opacity: { property: 'opacity' },
|
|
824
|
+
};
|
|
825
|
+
const shadows = {
|
|
826
|
+
boxShadow: { property: 'boxShadow' },
|
|
827
|
+
textShadow: { property: 'textShadow' },
|
|
828
|
+
};
|
|
829
|
+
const layout = {
|
|
830
|
+
display: { property: 'display' },
|
|
831
|
+
overflow: { property: 'overflow' },
|
|
832
|
+
overflowX: { property: 'overflowX' },
|
|
833
|
+
overflowY: { property: 'overflowY' },
|
|
834
|
+
size: {
|
|
835
|
+
property: 'width',
|
|
836
|
+
properties: ['width', 'height'],
|
|
837
|
+
transform: size,
|
|
838
|
+
},
|
|
839
|
+
width: {
|
|
840
|
+
property: 'width',
|
|
841
|
+
transform: size,
|
|
842
|
+
},
|
|
843
|
+
minWidth: { property: 'minWidth', transform: size },
|
|
844
|
+
maxWidth: { property: 'maxWidth', transform: size },
|
|
845
|
+
height: { property: 'height', transform: size },
|
|
846
|
+
minHeight: {
|
|
847
|
+
property: 'minHeight',
|
|
848
|
+
transform: size,
|
|
849
|
+
},
|
|
850
|
+
maxHeight: {
|
|
851
|
+
property: 'maxHeight',
|
|
852
|
+
transform: size,
|
|
853
|
+
},
|
|
854
|
+
verticalAlign: { property: 'verticalAlign' },
|
|
855
|
+
...selfAlignments,
|
|
856
|
+
...gridItems,
|
|
857
|
+
...flexItems,
|
|
858
|
+
};
|
|
859
|
+
const typography = {
|
|
860
|
+
fontFamily: { property: 'fontFamily', scale: 'fontFamily' },
|
|
861
|
+
fontWeight: {
|
|
862
|
+
property: 'fontWeight',
|
|
863
|
+
scale: 'fontWeight',
|
|
864
|
+
},
|
|
865
|
+
lineHeight: {
|
|
866
|
+
property: 'lineHeight',
|
|
867
|
+
scale: 'lineHeight',
|
|
868
|
+
lineHeight: 'lineHeight',
|
|
869
|
+
},
|
|
870
|
+
fontSize: {
|
|
871
|
+
property: 'fontSize',
|
|
872
|
+
scale: 'fontSize',
|
|
873
|
+
},
|
|
874
|
+
letterSpacing: { property: 'letterSpacing' },
|
|
875
|
+
textAlign: { property: 'textAlign' },
|
|
876
|
+
fontStyle: { property: 'fontStyle' },
|
|
877
|
+
textDecoration: { property: 'textDecoration' },
|
|
878
|
+
textTransform: { property: 'textTransform' },
|
|
879
|
+
whiteSpace: { property: 'whiteSpace' },
|
|
880
|
+
};
|
|
881
|
+
const margin = {
|
|
882
|
+
m: { property: 'margin', scale: 'spacing' },
|
|
883
|
+
mx: {
|
|
884
|
+
property: 'margin',
|
|
885
|
+
properties: ['marginLeft', 'marginRight'],
|
|
886
|
+
scale: 'spacing',
|
|
887
|
+
},
|
|
888
|
+
my: {
|
|
889
|
+
property: 'margin',
|
|
890
|
+
properties: ['marginTop', 'marginBottom'],
|
|
891
|
+
scale: 'spacing',
|
|
892
|
+
},
|
|
893
|
+
mt: { property: 'marginTop', scale: 'spacing' },
|
|
894
|
+
mb: { property: 'marginBottom', scale: 'spacing' },
|
|
895
|
+
mr: { property: 'marginRight', scale: 'spacing' },
|
|
896
|
+
ml: { property: 'marginLeft', scale: 'spacing' },
|
|
897
|
+
};
|
|
898
|
+
const padding = {
|
|
899
|
+
p: { property: 'padding', scale: 'spacing' },
|
|
900
|
+
px: {
|
|
901
|
+
property: 'padding',
|
|
902
|
+
properties: ['paddingLeft', 'paddingRight'],
|
|
903
|
+
scale: 'spacing',
|
|
904
|
+
},
|
|
905
|
+
py: {
|
|
906
|
+
property: 'padding',
|
|
907
|
+
properties: ['paddingTop', 'paddingBottom'],
|
|
908
|
+
scale: 'spacing',
|
|
909
|
+
},
|
|
910
|
+
pt: { property: 'paddingTop', scale: 'spacing' },
|
|
911
|
+
pb: { property: 'paddingBottom', scale: 'spacing' },
|
|
912
|
+
pr: { property: 'paddingRight', scale: 'spacing' },
|
|
913
|
+
pl: { property: 'paddingLeft', scale: 'spacing' },
|
|
914
|
+
};
|
|
915
|
+
const space = {
|
|
916
|
+
...margin,
|
|
917
|
+
...padding,
|
|
918
|
+
};
|
|
919
|
+
const mode = {
|
|
920
|
+
mode: { property: 'none', scale: 'mode' },
|
|
921
|
+
};
|
|
922
|
+
const vars = {
|
|
923
|
+
vars: { property: 'variables' },
|
|
924
|
+
};
|
|
925
|
+
const config = createAnimus()
|
|
926
|
+
.addGroup('flex', flex)
|
|
927
|
+
.addGroup('grid', grid)
|
|
928
|
+
.addGroup('mode', mode)
|
|
929
|
+
.addGroup('vars', vars)
|
|
930
|
+
.addGroup('space', space)
|
|
931
|
+
.addGroup('color', color)
|
|
932
|
+
.addGroup('layout', layout)
|
|
933
|
+
.addGroup('borders', border)
|
|
934
|
+
.addGroup('shadows', shadows)
|
|
935
|
+
.addGroup('background', background)
|
|
936
|
+
.addGroup('typography', typography)
|
|
937
|
+
.addGroup('positioning', positioning);
|
|
938
|
+
config.build();
|
|
939
|
+
|
|
940
|
+
const getStylePropNames = (props, filteredKeys) => pick(props, keys(props).filter((key) => !filteredKeys.includes(key)));
|
|
941
|
+
|
|
942
|
+
const BREAKPOINT_KEYS = ['_', 'xs', 'sm', 'md', 'lg', 'xl'];
|
|
943
|
+
/**
|
|
944
|
+
* Destructures the themes breakpoints into an ordered structure to traverse
|
|
945
|
+
*/
|
|
946
|
+
const templateMediaQuery = (breakpoint) => `@media screen and (min-width: ${breakpoint}px)`;
|
|
947
|
+
const createMediaQueries = (breakpoints) => {
|
|
948
|
+
if (breakpoints === undefined)
|
|
949
|
+
return null;
|
|
950
|
+
const { xs, sm, md, lg, xl } = breakpoints ?? {};
|
|
951
|
+
// Ensure order for mapping
|
|
952
|
+
return {
|
|
953
|
+
map: mapValues(breakpoints, templateMediaQuery),
|
|
954
|
+
array: [xs, sm, md, lg, xl].map(templateMediaQuery),
|
|
955
|
+
};
|
|
956
|
+
};
|
|
957
|
+
const isMediaArray = (val) => Array.isArray(val);
|
|
958
|
+
const isMediaMap = (val) => intersection(Object.keys(val), BREAKPOINT_KEYS).length > 0;
|
|
959
|
+
const objectParser = (value, props, config, breakpoints) => {
|
|
960
|
+
const styles = {};
|
|
961
|
+
const { styleFn, prop } = config;
|
|
962
|
+
const { _, ...rest } = value;
|
|
963
|
+
// the keyof 'base' is base styles
|
|
964
|
+
if (_)
|
|
965
|
+
Object.assign(styles, styleFn(_, prop, props));
|
|
966
|
+
// Map over remaining keys and merge the corresponding breakpoint styles
|
|
967
|
+
// for that property.
|
|
968
|
+
Object.keys(breakpoints).forEach((breakpointKey) => {
|
|
969
|
+
const bpStyles = rest[breakpointKey];
|
|
970
|
+
if (typeof bpStyles === 'undefined')
|
|
971
|
+
return;
|
|
972
|
+
Object.assign(styles, {
|
|
973
|
+
[breakpoints[breakpointKey]]: styleFn(bpStyles, prop, props),
|
|
974
|
+
});
|
|
975
|
+
});
|
|
976
|
+
return styles;
|
|
977
|
+
};
|
|
978
|
+
const arrayParser = (value, props, config, breakpoints) => {
|
|
979
|
+
const styles = {};
|
|
980
|
+
const { styleFn, prop } = config;
|
|
981
|
+
const [_, ...rest] = value;
|
|
982
|
+
// the first index is base styles
|
|
983
|
+
if (_)
|
|
984
|
+
Object.assign(styles, styleFn(_, prop, props));
|
|
985
|
+
// Map over each value in the array and merge the corresponding breakpoint styles
|
|
986
|
+
// for that property.
|
|
987
|
+
rest.forEach((val, i) => {
|
|
988
|
+
const breakpointKey = breakpoints[i];
|
|
989
|
+
if (!breakpointKey || typeof val === 'undefined')
|
|
990
|
+
return;
|
|
991
|
+
Object.assign(styles, {
|
|
992
|
+
[breakpointKey]: styleFn(val, prop, props),
|
|
993
|
+
});
|
|
994
|
+
});
|
|
995
|
+
return styles;
|
|
996
|
+
};
|
|
997
|
+
const orderBreakpoints = (styles, breakpoints) => {
|
|
998
|
+
const orderedStyles = omit(styles, breakpoints);
|
|
999
|
+
breakpoints.forEach((bp) => {
|
|
1000
|
+
if (styles[bp]) {
|
|
1001
|
+
orderedStyles[bp] = styles[bp];
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
return orderedStyles;
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
const renderPropValue = (styles, prop, props, property, ctx) => {
|
|
1008
|
+
const value = get(props, prop);
|
|
1009
|
+
switch (typeof value) {
|
|
1010
|
+
case 'string':
|
|
1011
|
+
case 'number':
|
|
1012
|
+
case 'function':
|
|
1013
|
+
return Object.assign(styles, property.styleFn(value, prop, props));
|
|
1014
|
+
// handle any props configured with the responsive notation
|
|
1015
|
+
case 'object':
|
|
1016
|
+
if (!ctx.mediaQueries) {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
// If it is an array the order of values is smallest to largest: [_, xs, ...]
|
|
1020
|
+
if (isMediaArray(value)) {
|
|
1021
|
+
return merge(styles, arrayParser(value, props, property, ctx.mediaQueries.array));
|
|
1022
|
+
}
|
|
1023
|
+
// Check to see if value is an object matching the responsive syntax and generate the styles.
|
|
1024
|
+
if (value && isMediaMap(value)) {
|
|
1025
|
+
return merge(styles, objectParser(value, props, property, ctx.mediaQueries.map));
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
function createParser(config) {
|
|
1030
|
+
const propNames = orderPropNames(config);
|
|
1031
|
+
const ctx = {
|
|
1032
|
+
mediaQueries: null,
|
|
1033
|
+
};
|
|
1034
|
+
const parser = (props, isCss = false) => {
|
|
1035
|
+
const styles = {};
|
|
1036
|
+
const { theme } = props;
|
|
1037
|
+
// Attempt to cache the breakpoints if we have not yet or if theme has become available.
|
|
1038
|
+
if (ctx.mediaQueries === null) {
|
|
1039
|
+
// Save the breakpoints if we can
|
|
1040
|
+
ctx.mediaQueries = createMediaQueries(theme?.breakpoints ?? compatTheme.breakpoints);
|
|
1041
|
+
}
|
|
1042
|
+
if (!isCss) {
|
|
1043
|
+
// Loops over all prop names on the configured config to check for configured styles
|
|
1044
|
+
propNames.forEach((prop) => {
|
|
1045
|
+
const property = config[prop];
|
|
1046
|
+
renderPropValue(styles, prop, props, property, ctx);
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
// Loops over all prop names on the configured config to check for configured styles
|
|
1051
|
+
Object.keys(props).forEach((prop) => {
|
|
1052
|
+
const property = config[prop];
|
|
1053
|
+
if (property) {
|
|
1054
|
+
renderPropValue(styles, prop, props, property, ctx);
|
|
1055
|
+
}
|
|
1056
|
+
else if (prop !== 'theme') {
|
|
1057
|
+
Object.assign(styles, { [prop]: get(props, prop) });
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
if (ctx.mediaQueries !== null)
|
|
1062
|
+
return orderBreakpoints(styles, ctx.mediaQueries.array);
|
|
1063
|
+
return styles;
|
|
1064
|
+
};
|
|
1065
|
+
// return the parser function with the resulting meta information for further composition
|
|
1066
|
+
return Object.assign(parser, { propNames, config });
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
function createTransform(prop, config) {
|
|
1070
|
+
const { transform = identity, property, properties = [property], scale, variable, } = config;
|
|
1071
|
+
const alwaysTransform = scale === undefined || isArray(scale);
|
|
1072
|
+
return {
|
|
1073
|
+
...config,
|
|
1074
|
+
prop,
|
|
1075
|
+
styleFn: (value, prop, props) => {
|
|
1076
|
+
const styles = {};
|
|
1077
|
+
if (isUndefined(value)) {
|
|
1078
|
+
return styles;
|
|
1079
|
+
}
|
|
1080
|
+
let useTransform = false;
|
|
1081
|
+
let intermediateValue;
|
|
1082
|
+
let scaleValue;
|
|
1083
|
+
switch (typeof value) {
|
|
1084
|
+
case 'number':
|
|
1085
|
+
case 'string':
|
|
1086
|
+
scaleValue = lookupScaleValue(value, scale, props.theme);
|
|
1087
|
+
useTransform = scaleValue !== undefined || alwaysTransform;
|
|
1088
|
+
intermediateValue = scaleValue ?? value;
|
|
1089
|
+
break;
|
|
1090
|
+
case 'function':
|
|
1091
|
+
if (props.theme) {
|
|
1092
|
+
intermediateValue = value(props.theme);
|
|
1093
|
+
}
|
|
1094
|
+
break;
|
|
1095
|
+
default:
|
|
1096
|
+
return styles;
|
|
1097
|
+
}
|
|
1098
|
+
// for each property look up the scale value from theme if passed and apply any
|
|
1099
|
+
// final transforms to the value
|
|
1100
|
+
properties.forEach((property) => {
|
|
1101
|
+
let styleValue = intermediateValue;
|
|
1102
|
+
if (useTransform && !isUndefined(styleValue)) {
|
|
1103
|
+
styleValue = transform(styleValue, property, props);
|
|
1104
|
+
}
|
|
1105
|
+
switch (typeof styleValue) {
|
|
1106
|
+
case 'number':
|
|
1107
|
+
case 'string':
|
|
1108
|
+
return (styles[property] = styleValue);
|
|
1109
|
+
case 'object':
|
|
1110
|
+
return Object.assign(styles, styleValue);
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
if (variable) {
|
|
1114
|
+
let styleValue = intermediateValue;
|
|
1115
|
+
if (useTransform && !isUndefined(styleValue)) {
|
|
1116
|
+
styleValue = transform(styleValue, property, props);
|
|
1117
|
+
}
|
|
1118
|
+
if (styleValue && typeof styleValue !== 'object') {
|
|
1119
|
+
styles[variable] = styleValue;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
// return the resulting styles object
|
|
1123
|
+
return styles;
|
|
1124
|
+
},
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
function create(config) {
|
|
1129
|
+
// Create a transform function for each of the props
|
|
1130
|
+
const transforms = {};
|
|
1131
|
+
for (const prop in config) {
|
|
1132
|
+
if (typeof prop === 'string') {
|
|
1133
|
+
transforms[prop] = createTransform(prop, config[prop]);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
// Create a parser that handles all the props within the config
|
|
1137
|
+
return createParser(transforms);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
function createCss(config) {
|
|
1141
|
+
const parser = create(config);
|
|
1142
|
+
const filteredProps = parser.propNames;
|
|
1143
|
+
return (cssProps) => {
|
|
1144
|
+
let cache;
|
|
1145
|
+
const allKeys = Object.keys(cssProps);
|
|
1146
|
+
/** Any key of the CSSProps that is not a System Prop or a Static CSS Property is treated as a nested selector */
|
|
1147
|
+
const selectors = allKeys.filter((key) => !filteredProps.includes(key) && isObject(cssProps[key]));
|
|
1148
|
+
/** Static CSS Properties get extracted if they match neither syntax */
|
|
1149
|
+
const staticCss = getStylePropNames(cssProps, [
|
|
1150
|
+
'theme',
|
|
1151
|
+
...selectors,
|
|
1152
|
+
...filteredProps,
|
|
1153
|
+
]);
|
|
1154
|
+
return ({ theme }) => {
|
|
1155
|
+
if (cache)
|
|
1156
|
+
return cache;
|
|
1157
|
+
const css = parser({ ...cssProps, theme });
|
|
1158
|
+
selectors.forEach((selector) => {
|
|
1159
|
+
const selectorConfig = cssProps[selector] ?? {};
|
|
1160
|
+
css[selector] = {
|
|
1161
|
+
...getStylePropNames(selectorConfig, filteredProps),
|
|
1162
|
+
...parser({ ...selectorConfig, theme }),
|
|
1163
|
+
};
|
|
1164
|
+
});
|
|
1165
|
+
/** Merge the static and generated css and save it to the cache */
|
|
1166
|
+
cache = {
|
|
1167
|
+
...staticCss,
|
|
1168
|
+
...css,
|
|
1169
|
+
};
|
|
1170
|
+
return cache;
|
|
1171
|
+
};
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
function createVariant(config) {
|
|
1176
|
+
const css = createCss(config);
|
|
1177
|
+
return ({ prop = 'variant', defaultVariant, base = {}, variants }) => {
|
|
1178
|
+
const baseFn = css(base);
|
|
1179
|
+
const variantFns = {};
|
|
1180
|
+
Object.keys(variants).forEach((key) => {
|
|
1181
|
+
const variantKey = key;
|
|
1182
|
+
const cssProps = variants[variantKey];
|
|
1183
|
+
variantFns[variantKey] = css(cssProps);
|
|
1184
|
+
});
|
|
1185
|
+
return (props) => {
|
|
1186
|
+
const { [prop]: selected = defaultVariant } = props;
|
|
1187
|
+
const styles = {};
|
|
1188
|
+
if (!selected)
|
|
1189
|
+
return styles;
|
|
1190
|
+
return merge(styles, baseFn(props), variantFns?.[selected]?.(props));
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
function compose(...parsers) {
|
|
1196
|
+
return createParser(parsers.reduce((carry, parser) => ({ ...carry, ...parser.config }), {}));
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
function createStates(config) {
|
|
1200
|
+
const css = createCss(config);
|
|
1201
|
+
return (states) => {
|
|
1202
|
+
const orderedStates = Object.keys(states);
|
|
1203
|
+
const stateFns = {};
|
|
1204
|
+
orderedStates.forEach((key) => {
|
|
1205
|
+
const stateKey = key;
|
|
1206
|
+
const cssProps = states[stateKey];
|
|
1207
|
+
stateFns[stateKey] = css(cssProps);
|
|
1208
|
+
});
|
|
1209
|
+
return (props) => {
|
|
1210
|
+
const styles = {};
|
|
1211
|
+
orderedStates.forEach((state) => {
|
|
1212
|
+
merge(styles, props[state] && stateFns[state](props));
|
|
1213
|
+
});
|
|
1214
|
+
return styles;
|
|
1215
|
+
};
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
const animusProps = {
|
|
1220
|
+
compose,
|
|
1221
|
+
create,
|
|
1222
|
+
createCss,
|
|
1223
|
+
createVariant,
|
|
1224
|
+
createStates,
|
|
1225
|
+
};
|
|
1226
|
+
|
|
1227
|
+
const animus = config.build();
|
|
1228
|
+
|
|
1229
|
+
export { AnimusConfig, animus, animusProps, borderShorthand, compatTheme, config, createAnimus, createScale, gridItem, gridItemRatio, numberToPx, numberToTemplate, parseGridRatio, percentageOrAbsolute, repeatGridItem, size };
|