simplestyle-js 3.4.0 → 3.4.2-alpha.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/LICENSE +1 -1
- package/dist/cjs/createStyles.cjs +202 -0
- package/dist/cjs/createStyles.d.ts +47 -0
- package/dist/cjs/generateClassName.cjs +62 -0
- package/dist/cjs/generateClassName.d.ts +3 -0
- package/dist/cjs/index.cjs +71 -0
- package/dist/cjs/numToAlpha.cjs +14 -0
- package/dist/cjs/numToAlpha.d.ts +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/plugins.cjs +25 -0
- package/dist/cjs/plugins.d.ts +3 -0
- package/dist/cjs/react/index.cjs +18 -0
- package/dist/cjs/react/useCreateStyles.cjs +73 -0
- package/dist/cjs/react/useCreateStyles.d.ts +3 -0
- package/dist/cjs/simpleStyleRegistry.cjs +25 -0
- package/dist/cjs/simpleStyleRegistry.d.ts +11 -0
- package/dist/cjs/types.cjs +4 -0
- package/{src/types.ts → dist/cjs/types.d.ts} +1 -3
- package/dist/cjs/util/deepEqual.cjs +27 -0
- package/dist/cjs/util/deepEqual.d.ts +1 -0
- package/dist/cjs/util/index.cjs +18 -0
- package/dist/esm/createStyles.d.ts +47 -0
- package/dist/esm/createStyles.mjs +174 -0
- package/dist/esm/generateClassName.d.ts +3 -0
- package/dist/esm/generateClassName.mjs +36 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.mjs +3 -0
- package/dist/esm/numToAlpha.d.ts +1 -0
- package/dist/esm/numToAlpha.mjs +4 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/plugins.d.ts +3 -0
- package/dist/esm/plugins.mjs +7 -0
- package/dist/esm/react/index.d.ts +1 -0
- package/dist/esm/react/index.mjs +1 -0
- package/dist/esm/react/useCreateStyles.d.ts +3 -0
- package/dist/esm/react/useCreateStyles.mjs +58 -0
- package/dist/esm/simpleStyleRegistry.d.ts +11 -0
- package/dist/esm/simpleStyleRegistry.mjs +15 -0
- package/dist/esm/types.d.ts +5 -0
- package/dist/esm/types.mjs +1 -0
- package/dist/esm/util/deepEqual.d.ts +1 -0
- package/dist/esm/util/deepEqual.mjs +17 -0
- package/dist/esm/util/index.d.ts +1 -0
- package/dist/esm/util/index.mjs +1 -0
- package/package.json +14 -1
- package/.coveralls.yml +0 -2
- package/.editorconfig +0 -7
- package/.prettierrc +0 -7
- package/.tool-versions +0 -3
- package/.travis.yml +0 -8
- package/.vscode/launch.json +0 -36
- package/.vscode/settings.json +0 -3
- package/CHANGELOG.md +0 -273
- package/eslint.config.js +0 -3
- package/setup.sh +0 -4
- package/src/createStyles.ts +0 -251
- package/src/generateClassName.ts +0 -43
- package/src/numToAlpha.ts +0 -5
- package/src/plugins.ts +0 -11
- package/src/react/useCreateStyles.ts +0 -58
- package/src/util/deepEqual.ts +0 -20
- package/test/createStyles.spec.ts +0 -330
- package/test/deepEqual.spec.ts +0 -97
- package/test/generateClassName.spec.ts +0 -48
- package/test/keyframes.spec.ts +0 -19
- package/test/plugins.spec.ts +0 -43
- package/test/react/useCreateStyles.spec.tsx +0 -65
- package/test/updateStyles.spec.ts +0 -41
- package/tsconfig.build.json +0 -8
- package/tsconfig.json +0 -37
- package/vite.config.ts +0 -9
- /package/{src/index.ts → dist/cjs/index.d.ts} +0 -0
- /package/{src/react/index.ts → dist/cjs/react/index.d.ts} +0 -0
- /package/{src/util/index.ts → dist/cjs/util/index.d.ts} +0 -0
package/src/util/deepEqual.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export function deepEqual<
|
|
2
|
-
O1 extends Record<string | number | symbol, any>,
|
|
3
|
-
O2 extends Record<string | number | symbol, any>,
|
|
4
|
-
>(o1: O1, o2: O2): boolean {
|
|
5
|
-
// We'll sort the keys, just in case the user kept things the same but the object is all wonky, order-wise
|
|
6
|
-
const o1Keys = Object.keys(o1).sort();
|
|
7
|
-
const o2Keys = Object.keys(o2).sort();
|
|
8
|
-
if (o1Keys.length !== o2Keys.length) return false;
|
|
9
|
-
if (o1Keys.some((key, i) => o2Keys[i] !== key)) return false;
|
|
10
|
-
// Okay, the keys SHOULD be the same
|
|
11
|
-
// so we need to test their values, recursively, to verify equality
|
|
12
|
-
return o1Keys.reduce<boolean>((prev, key) => {
|
|
13
|
-
if (!prev) return prev; // we've already failed equality checks here
|
|
14
|
-
if (!(key in o2)) return false;
|
|
15
|
-
if (typeof o1[key] !== 'object') {
|
|
16
|
-
return o1[key] === o2[key];
|
|
17
|
-
}
|
|
18
|
-
return deepEqual(o1[key], o2[key]);
|
|
19
|
-
}, true);
|
|
20
|
-
}
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { createStyles, rawStyles, setSeed } from '../src/index.js';
|
|
4
|
-
import { SimpleStyleRules } from '../src/types.js';
|
|
5
|
-
|
|
6
|
-
describe('createStyles tests', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
Array.from(document.querySelectorAll('style')).forEach(s => s.remove());
|
|
9
|
-
});
|
|
10
|
-
it('Should generate some basic styles', () => {
|
|
11
|
-
const rules: SimpleStyleRules = {
|
|
12
|
-
one: {
|
|
13
|
-
display: 'flex',
|
|
14
|
-
position: 'fixed',
|
|
15
|
-
},
|
|
16
|
-
two: {
|
|
17
|
-
backgroundColor: 'red',
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
21
|
-
|
|
22
|
-
Object.keys(rules).forEach(key => {
|
|
23
|
-
expect(classes[key]).toBeDefined();
|
|
24
|
-
expect(classes[key]?.length).toBeGreaterThan(0);
|
|
25
|
-
expect(classes[key]).toContain(key);
|
|
26
|
-
});
|
|
27
|
-
expect(stylesheet).toContain(`.${classes.one}{display:flex;position:fixed;}`);
|
|
28
|
-
expect(stylesheet).toContain(`.${classes.two}{background-color:red;}`);
|
|
29
|
-
});
|
|
30
|
-
it('Should generate some basic styles for a simple nested structure', () => {
|
|
31
|
-
const rules: SimpleStyleRules = {
|
|
32
|
-
nested: {
|
|
33
|
-
'& > span': {
|
|
34
|
-
fontFamily: 'Arial',
|
|
35
|
-
},
|
|
36
|
-
fontSize: '20px',
|
|
37
|
-
},
|
|
38
|
-
yarg: {
|
|
39
|
-
'&:hover': {
|
|
40
|
-
top: '-1px',
|
|
41
|
-
},
|
|
42
|
-
'&:focus': {
|
|
43
|
-
backgroundColor: 'purple',
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
48
|
-
|
|
49
|
-
expect(classes.nested).toBeDefined();
|
|
50
|
-
expect(classes.nested?.length).toBeGreaterThan(0);
|
|
51
|
-
expect(classes.nested).toContain('nested');
|
|
52
|
-
|
|
53
|
-
expect(classes.yarg).toBeDefined();
|
|
54
|
-
expect(classes.yarg?.length).toBeGreaterThan(0);
|
|
55
|
-
expect(classes.yarg).toContain('yarg');
|
|
56
|
-
|
|
57
|
-
expect(stylesheet).toContain(`.${classes.nested} > span{font-family:Arial;}`);
|
|
58
|
-
expect(stylesheet).toContain(`.${classes.nested}{font-size:20px;}`);
|
|
59
|
-
expect(stylesheet).toContain(`.${classes.yarg}:hover{top:-1px;}`);
|
|
60
|
-
expect(stylesheet).toContain(`.${classes.yarg}:focus{background-color:purple;}`);
|
|
61
|
-
});
|
|
62
|
-
it('Should allow backreferences', () => {
|
|
63
|
-
const rules: SimpleStyleRules = {
|
|
64
|
-
a: {
|
|
65
|
-
textAlign: 'center',
|
|
66
|
-
},
|
|
67
|
-
b: {
|
|
68
|
-
'& $a': {
|
|
69
|
-
'&:hover': {
|
|
70
|
-
fontSize: '99px',
|
|
71
|
-
},
|
|
72
|
-
fontSize: '30px',
|
|
73
|
-
},
|
|
74
|
-
lineHeight: '1.5',
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
78
|
-
|
|
79
|
-
expect(stylesheet).toContain(`.${classes.a}{text-align:center;}`);
|
|
80
|
-
expect(stylesheet).toContain(`.${classes.b}{line-height:1.5;}`);
|
|
81
|
-
expect(stylesheet).toContain(`.${classes.b} .${classes.a}{font-size:30px;}`);
|
|
82
|
-
expect(stylesheet).toContain(`.${classes.b} .${classes.a}:hover{font-size:99px;}`);
|
|
83
|
-
});
|
|
84
|
-
it('Should allow simple media queries', () => {
|
|
85
|
-
const rules: SimpleStyleRules = {
|
|
86
|
-
responsive: {
|
|
87
|
-
'@media (max-width: 960px)': {
|
|
88
|
-
'& button': {
|
|
89
|
-
padding: '24px',
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
'& button': {
|
|
93
|
-
padding: '8px',
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
98
|
-
|
|
99
|
-
expect(stylesheet).toBe(
|
|
100
|
-
`.${classes.responsive} button{padding:8px;}@media (max-width: 960px){.${classes.responsive} button{padding:24px;}}`,
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
it('Should allow multiple media queries, including deeply-nested selector', () => {
|
|
104
|
-
const rules: SimpleStyleRules = {
|
|
105
|
-
simple: {
|
|
106
|
-
width: '100%',
|
|
107
|
-
},
|
|
108
|
-
deep: {
|
|
109
|
-
'& > span, & > div': {
|
|
110
|
-
'& button': {
|
|
111
|
-
'@media(max-width: 600px)': {
|
|
112
|
-
padding: '0.5em',
|
|
113
|
-
},
|
|
114
|
-
padding: '1em',
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
color: 'pink',
|
|
118
|
-
gridTemplateColumns: 'repeat(4, 1fr)',
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
122
|
-
|
|
123
|
-
expect(stylesheet).toContain(`.${classes.simple}{width:100%;}`);
|
|
124
|
-
expect(stylesheet).toContain(`.${classes.deep}{color:pink;grid-template-columns:repeat(4, 1fr);}`);
|
|
125
|
-
expect(stylesheet).toContain(`.${classes.deep} > span button{padding:1em;}`);
|
|
126
|
-
expect(stylesheet).toContain(`.${classes.deep} > div button{padding:1em;}`);
|
|
127
|
-
expect(stylesheet).toContain(`@media(max-width: 600px){.${classes.deep} > div button{padding:0.5em;}}`);
|
|
128
|
-
expect(stylesheet).toContain(`@media(max-width: 600px){.${classes.deep} > span button{padding:0.5em;}}`);
|
|
129
|
-
});
|
|
130
|
-
it('Should allow a media query with multiple children', () => {
|
|
131
|
-
const rules: SimpleStyleRules = {
|
|
132
|
-
appHeaderHomeLink: {
|
|
133
|
-
'@media (max-width: 600px)': {
|
|
134
|
-
'& > b': {
|
|
135
|
-
display: 'none',
|
|
136
|
-
},
|
|
137
|
-
'& > i': {
|
|
138
|
-
marginLeft: '0 !important',
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
position: 'relative',
|
|
142
|
-
transition: 'background-color .2s ease',
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
146
|
-
|
|
147
|
-
// eslint-disable-next-line max-len
|
|
148
|
-
expect(stylesheet).toBe(
|
|
149
|
-
`.${classes.appHeaderHomeLink}{position:relative;transition:background-color .2s ease;}@media (max-width: 600px){.${classes.appHeaderHomeLink} > b{display:none;}.${classes.appHeaderHomeLink} > i{margin-left:0 !important;}}`,
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
it("Should ensure that multiple media queries of the same type aren't clobbered", () => {
|
|
153
|
-
const mediaQuery = '@media (max-width: 600px)';
|
|
154
|
-
const rules: SimpleStyleRules = {
|
|
155
|
-
appBarGrid: {
|
|
156
|
-
[mediaQuery]: {
|
|
157
|
-
gridTemplateColumns: '1fr 2fr',
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
appHeaderHomeLink: {
|
|
161
|
-
[mediaQuery]: {
|
|
162
|
-
'& > b': {
|
|
163
|
-
display: 'none',
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
169
|
-
|
|
170
|
-
expect(stylesheet).toBe(
|
|
171
|
-
`${mediaQuery}{.${classes.appBarGrid}{grid-template-columns:1fr 2fr;}}${mediaQuery}{.${classes.appHeaderHomeLink} > b{display:none;}}`,
|
|
172
|
-
);
|
|
173
|
-
});
|
|
174
|
-
it('Should allow creation of top-level "raw" styles that can generically apply globally to HTML tags', () => {
|
|
175
|
-
const rules: SimpleStyleRules = {
|
|
176
|
-
body: {
|
|
177
|
-
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
178
|
-
fontSize: '16px',
|
|
179
|
-
},
|
|
180
|
-
a: {
|
|
181
|
-
'&:hover': {
|
|
182
|
-
textDecoration: 'none',
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
const styleContents = rawStyles(rules);
|
|
187
|
-
|
|
188
|
-
expect(styleContents).toContain('body{font-family:Arial, Helvetica, sans-serif;font-size:16px;}');
|
|
189
|
-
expect(styleContents).toContain('a:hover{text-decoration:none;}');
|
|
190
|
-
});
|
|
191
|
-
it('Should allow creation of top-level "raw" styles with nested media queries', () => {
|
|
192
|
-
const rules: SimpleStyleRules = {
|
|
193
|
-
button: {
|
|
194
|
-
'@media(max-width:300px)': {
|
|
195
|
-
'& > svg': {
|
|
196
|
-
fontSize: '1em',
|
|
197
|
-
},
|
|
198
|
-
maxWidth: '100%',
|
|
199
|
-
},
|
|
200
|
-
minWidth: '300px',
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
const styleContents = rawStyles(rules);
|
|
204
|
-
expect(styleContents).toBe(
|
|
205
|
-
'button{min-width:300px;}@media(max-width:300px){button > svg{font-size:1em;}button{max-width:100%;}}',
|
|
206
|
-
);
|
|
207
|
-
});
|
|
208
|
-
it('Should generate different classnames across multiple passes', () => {
|
|
209
|
-
const rules: SimpleStyleRules = {
|
|
210
|
-
simple: {
|
|
211
|
-
width: '100%',
|
|
212
|
-
},
|
|
213
|
-
deep: {
|
|
214
|
-
'& > span, & > div': {
|
|
215
|
-
'& button': {
|
|
216
|
-
'@media(max-width: 600px)': {
|
|
217
|
-
padding: '0.5em',
|
|
218
|
-
},
|
|
219
|
-
padding: '1em',
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
color: 'pink',
|
|
223
|
-
gridTemplateColumns: 'repeat(4, 1fr)',
|
|
224
|
-
},
|
|
225
|
-
finder: {
|
|
226
|
-
backgroundColor: 'pink',
|
|
227
|
-
marginLeft: '40px',
|
|
228
|
-
padding: '1rem',
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
const { classes: s1, stylesheet: rendered1 } = createStyles(rules, { flush: false });
|
|
232
|
-
const { classes: s2, stylesheet: rendered2 } = createStyles(rules, { flush: false });
|
|
233
|
-
const { classes: s3, stylesheet: rendered3 } = createStyles(rules, { flush: false });
|
|
234
|
-
expect(s1).not.toEqual(s2);
|
|
235
|
-
expect(s1).not.toEqual(s3);
|
|
236
|
-
expect(s2).not.toEqual(s3);
|
|
237
|
-
expect(rendered1).not.toEqual(rendered2);
|
|
238
|
-
expect(rendered1).not.toEqual(rendered3);
|
|
239
|
-
expect(rendered2).not.toEqual(rendered3);
|
|
240
|
-
});
|
|
241
|
-
it('Should generate the same classnames across multiple passes if a custom seed is set', () => {
|
|
242
|
-
const rules: SimpleStyleRules = {
|
|
243
|
-
simple: {
|
|
244
|
-
width: '100%',
|
|
245
|
-
},
|
|
246
|
-
deep: {
|
|
247
|
-
'& > span, & > div': {
|
|
248
|
-
'& button': {
|
|
249
|
-
'@media(max-width: 600px)': {
|
|
250
|
-
padding: '0.5em',
|
|
251
|
-
},
|
|
252
|
-
padding: '1em',
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
color: 'pink',
|
|
256
|
-
gridTemplateColumns: 'repeat(4, 1fr)',
|
|
257
|
-
},
|
|
258
|
-
finder: {
|
|
259
|
-
backgroundColor: 'pink',
|
|
260
|
-
marginLeft: '40px',
|
|
261
|
-
padding: '1rem',
|
|
262
|
-
},
|
|
263
|
-
};
|
|
264
|
-
const seed = 1234;
|
|
265
|
-
setSeed(seed);
|
|
266
|
-
const { classes: s1, stylesheet: rendered1 } = createStyles(rules, { flush: false });
|
|
267
|
-
setSeed(seed);
|
|
268
|
-
const { classes: s2, stylesheet: rendered2 } = createStyles(rules, { flush: false });
|
|
269
|
-
setSeed(seed);
|
|
270
|
-
const { classes: s3, stylesheet: rendered3 } = createStyles(rules, { flush: false });
|
|
271
|
-
expect(s1).toEqual(s2);
|
|
272
|
-
expect(s1).toEqual(s3);
|
|
273
|
-
expect(s2).toEqual(s3);
|
|
274
|
-
expect(rendered1).toEqual(rendered2);
|
|
275
|
-
expect(rendered1).toEqual(rendered3);
|
|
276
|
-
expect(rendered2).toEqual(rendered3);
|
|
277
|
-
});
|
|
278
|
-
it('Should generate styles and allow inserting after a desired element', () => {
|
|
279
|
-
const insertAfter = document.createElement('div');
|
|
280
|
-
document.body.appendChild(insertAfter);
|
|
281
|
-
const { stylesheet: styleContents } = createStyles(
|
|
282
|
-
{
|
|
283
|
-
test: {
|
|
284
|
-
backgroundColor: 'purple',
|
|
285
|
-
fontSize: '40px',
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
{ insertAfter },
|
|
289
|
-
);
|
|
290
|
-
const foundStyle = document.body.querySelector('style');
|
|
291
|
-
expect(foundStyle?.innerHTML).toBe(styleContents);
|
|
292
|
-
const children = Array.from(document.body.children);
|
|
293
|
-
let success = false;
|
|
294
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
295
|
-
const child = children[i];
|
|
296
|
-
if (child === insertAfter) {
|
|
297
|
-
success = true;
|
|
298
|
-
expect(children[i + 1]).toBe(foundStyle);
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
expect(success).toBeTruthy();
|
|
303
|
-
});
|
|
304
|
-
it('Should generate styles and allow inserting before desired element', () => {
|
|
305
|
-
const insertBefore = document.createElement('div');
|
|
306
|
-
document.body.appendChild(insertBefore);
|
|
307
|
-
const { stylesheet: styleContents } = createStyles(
|
|
308
|
-
{
|
|
309
|
-
test: {
|
|
310
|
-
backgroundColor: 'purple',
|
|
311
|
-
fontSize: '40px',
|
|
312
|
-
},
|
|
313
|
-
},
|
|
314
|
-
{ insertBefore },
|
|
315
|
-
);
|
|
316
|
-
const foundStyle = document.body.querySelector('style');
|
|
317
|
-
expect(foundStyle?.innerHTML).toBe(styleContents);
|
|
318
|
-
const children = Array.from(document.body.children);
|
|
319
|
-
let success = false;
|
|
320
|
-
for (let i = 0; i < children.length; i += 1) {
|
|
321
|
-
const child = children[i];
|
|
322
|
-
if (child === insertBefore) {
|
|
323
|
-
success = true;
|
|
324
|
-
expect(children[i - 1]).toBe(foundStyle);
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
expect(success).toBeTruthy();
|
|
329
|
-
});
|
|
330
|
-
});
|
package/test/deepEqual.spec.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { deepEqual } from '../src/util/index.js';
|
|
4
|
-
|
|
5
|
-
describe('Deep Object Equality utility', () => {
|
|
6
|
-
it('Should veryify two simple objects are not equal', () => {
|
|
7
|
-
const o1 = {
|
|
8
|
-
one: 'uno',
|
|
9
|
-
two: 'dos',
|
|
10
|
-
};
|
|
11
|
-
const o2 = {
|
|
12
|
-
one: 'uno',
|
|
13
|
-
two: 'dos',
|
|
14
|
-
three: 'tres',
|
|
15
|
-
};
|
|
16
|
-
expect(deepEqual(o1, o2)).toBeFalsy();
|
|
17
|
-
});
|
|
18
|
-
it('Should veryify two simple objects are equal', () => {
|
|
19
|
-
const o1 = {
|
|
20
|
-
one: 'uno',
|
|
21
|
-
two: 'dos',
|
|
22
|
-
};
|
|
23
|
-
const o2 = {
|
|
24
|
-
one: 'uno',
|
|
25
|
-
two: 'dos',
|
|
26
|
-
};
|
|
27
|
-
expect(deepEqual(o1, o2)).toBeTruthy();
|
|
28
|
-
});
|
|
29
|
-
it('Should veryify two simple objects with the same keys but different values are not equal', () => {
|
|
30
|
-
const o1 = {
|
|
31
|
-
one: 'one',
|
|
32
|
-
two: 'dos',
|
|
33
|
-
};
|
|
34
|
-
const o2 = {
|
|
35
|
-
one: 'uno',
|
|
36
|
-
two: 'dos',
|
|
37
|
-
};
|
|
38
|
-
expect(deepEqual(o1, o2)).toBeFalsy();
|
|
39
|
-
});
|
|
40
|
-
it('Should verify two 1-layer deep objects are equal', () => {
|
|
41
|
-
const o1 = {
|
|
42
|
-
one: 'uno',
|
|
43
|
-
two: 'dos',
|
|
44
|
-
nested: {
|
|
45
|
-
yes: 'yes',
|
|
46
|
-
no: 'nopers',
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
const o2 = {
|
|
50
|
-
one: 'uno',
|
|
51
|
-
two: 'dos',
|
|
52
|
-
nested: {
|
|
53
|
-
yes: 'yes',
|
|
54
|
-
no: 'nopers',
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
expect(deepEqual(o1, o2)).toBeTruthy();
|
|
58
|
-
});
|
|
59
|
-
it('Should verify two 1-layer deep objects with the same keys are not equal', () => {
|
|
60
|
-
const o1 = {
|
|
61
|
-
one: 'uno',
|
|
62
|
-
two: 'dos',
|
|
63
|
-
nested: {
|
|
64
|
-
yes: 'yes',
|
|
65
|
-
no: 'nopers',
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
const o2 = {
|
|
69
|
-
one: 'uno',
|
|
70
|
-
two: 'dos',
|
|
71
|
-
nested: {
|
|
72
|
-
yes: 'absolutely',
|
|
73
|
-
no: 'nopers',
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
expect(deepEqual(o1, o2)).toBeFalsy();
|
|
77
|
-
});
|
|
78
|
-
it('Should verify two 1-layer deep objects with different keys are not equal', () => {
|
|
79
|
-
const o1 = {
|
|
80
|
-
one: 'uno',
|
|
81
|
-
two: 'dos',
|
|
82
|
-
nested: {
|
|
83
|
-
color: 'pink',
|
|
84
|
-
width: 10,
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
const o2 = {
|
|
88
|
-
one: 'uno',
|
|
89
|
-
two: 'dos',
|
|
90
|
-
nested: {
|
|
91
|
-
yes: 'absolutely',
|
|
92
|
-
no: 'nopers',
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
expect(deepEqual(o1, o2)).toBeFalsy();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { generateClassName, setSeed } from '../src/generateClassName.js';
|
|
4
|
-
|
|
5
|
-
describe('generateClassName tests', () => {
|
|
6
|
-
it('Should generate multiple unique classnames', () => {
|
|
7
|
-
const input = ['one', 'deux', 'tres', 'four'];
|
|
8
|
-
const output = input.map(generateClassName);
|
|
9
|
-
expect(output[0]).not.toBe(output[1]);
|
|
10
|
-
expect(output[0]).not.toBe(output[2]);
|
|
11
|
-
expect(output[0]).not.toBe(output[3]);
|
|
12
|
-
expect(output[0]).not.toBe(output[1]);
|
|
13
|
-
expect(output[1]).not.toBe(output[2]);
|
|
14
|
-
expect(output[1]).not.toBe(output[3]);
|
|
15
|
-
expect(output[2]).not.toBe(output[0]);
|
|
16
|
-
expect(output[2]).not.toBe(output[3]);
|
|
17
|
-
});
|
|
18
|
-
it('Should throw errors if an invalid seed is provided', () => {
|
|
19
|
-
try {
|
|
20
|
-
setSeed('bad' as any);
|
|
21
|
-
} catch (error) {
|
|
22
|
-
const e = error as Error;
|
|
23
|
-
expect(e).toBeInstanceOf(Error);
|
|
24
|
-
expect(e.message).toContain('not a valid number');
|
|
25
|
-
}
|
|
26
|
-
try {
|
|
27
|
-
setSeed(Number.MAX_SAFE_INTEGER);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
const e = error as Error;
|
|
30
|
-
expect(e).toBeInstanceOf(Error);
|
|
31
|
-
expect(e.message).toContain('maximum safe JavaScript');
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
setSeed(Number.POSITIVE_INFINITY);
|
|
35
|
-
} catch (error) {
|
|
36
|
-
const e = error as Error;
|
|
37
|
-
expect(e).toBeInstanceOf(Error);
|
|
38
|
-
expect(e.message).toContain('Positive or negative');
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
setSeed(-1);
|
|
42
|
-
} catch (error) {
|
|
43
|
-
const e = error as Error;
|
|
44
|
-
expect(e).toBeInstanceOf(Error);
|
|
45
|
-
expect(e.message).toContain('number >= 0');
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
});
|
package/test/keyframes.spec.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { keyframes } from '../src/index.js';
|
|
4
|
-
|
|
5
|
-
describe('Keyframes generation', () => {
|
|
6
|
-
it('Should generate simple animation keyframes', () => {
|
|
7
|
-
const [keyframeName, sheetContents] = keyframes({
|
|
8
|
-
'0%': {
|
|
9
|
-
width: '100px',
|
|
10
|
-
},
|
|
11
|
-
'100%': {
|
|
12
|
-
width: '200px',
|
|
13
|
-
},
|
|
14
|
-
});
|
|
15
|
-
expect(keyframeName).toBeDefined();
|
|
16
|
-
expect(keyframeName.length).toBeGreaterThan(0);
|
|
17
|
-
expect(sheetContents).toBe(`@keyframes ${keyframeName}{0%{width:100px;}100%{width:200px;}}`);
|
|
18
|
-
});
|
|
19
|
-
});
|
package/test/plugins.spec.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import autoprefixer from 'autoprefixer';
|
|
2
|
-
import postcss from 'postcss';
|
|
3
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { createStyles, PosthookPlugin, registerPosthook, SimpleStyleRules } from '../src/index.js';
|
|
6
|
-
import { getPosthooks } from '../src/plugins.js';
|
|
7
|
-
|
|
8
|
-
describe('Plugin hooks', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
Array.from(document.head.querySelectorAll('style')).forEach(s => s.remove());
|
|
11
|
-
getPosthooks().length = 0;
|
|
12
|
-
});
|
|
13
|
-
it('Should execute a posthook with the proper arguments', () => {
|
|
14
|
-
const rules: SimpleStyleRules = {
|
|
15
|
-
posthook: {
|
|
16
|
-
backgroundSize: 'contain',
|
|
17
|
-
backgroundRepeat: 'no-repeat',
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
const posthook: PosthookPlugin = vi.fn(sheetContents => {
|
|
21
|
-
expect(sheetContents.length).toBeGreaterThan(0);
|
|
22
|
-
expect(sheetContents.startsWith('.posthook')).toBeTruthy();
|
|
23
|
-
expect(sheetContents).toContain('{background-size:contain;background-repeat:no-repeat;}');
|
|
24
|
-
return sheetContents;
|
|
25
|
-
});
|
|
26
|
-
registerPosthook(posthook);
|
|
27
|
-
createStyles(rules);
|
|
28
|
-
expect(posthook).toBeCalled();
|
|
29
|
-
});
|
|
30
|
-
it('Should execute a posthook and transform the contents', () => {
|
|
31
|
-
const rules: SimpleStyleRules = {
|
|
32
|
-
posthook: {
|
|
33
|
-
userSelect: 'none',
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
// Post CSS and autoprefixer types have changed
|
|
37
|
-
// so we just brute-force the typings
|
|
38
|
-
const posthook: PosthookPlugin = sheetContents => postcss([autoprefixer() as any]).process(sheetContents).css;
|
|
39
|
-
registerPosthook(posthook);
|
|
40
|
-
const { classes, stylesheet } = createStyles(rules);
|
|
41
|
-
expect(stylesheet).toBe(`.${classes.posthook}{-webkit-user-select:none;-moz-user-select:none;user-select:none;}`);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { fireEvent, render } from '@testing-library/react';
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { useCreateStyles } from '../../src/react/useCreateStyles.js';
|
|
6
|
-
|
|
7
|
-
describe('React utilities tests', () => {
|
|
8
|
-
it('Should verify useCreateStyles hook generates classnames and inserts the stylesheet', () => {
|
|
9
|
-
const Bogus = () => {
|
|
10
|
-
const classes = useCreateStyles({
|
|
11
|
-
app: {
|
|
12
|
-
backgroundColor: 'purple',
|
|
13
|
-
fontSize: '16px',
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
return (
|
|
17
|
-
<section className={classes.app} data-testid='app'>
|
|
18
|
-
Testing
|
|
19
|
-
</section>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
const result = render(<Bogus />);
|
|
23
|
-
const section = result.getByTestId('app');
|
|
24
|
-
expect(section.classList.length).toBeGreaterThan(0);
|
|
25
|
-
expect(section.className.startsWith('app_')).toBeTruthy();
|
|
26
|
-
const sheet = document.head.querySelector('style');
|
|
27
|
-
expect(sheet).not.toBeNull();
|
|
28
|
-
expect(sheet?.innerHTML).toContain(section.className);
|
|
29
|
-
expect(sheet?.innerHTML).toContain('background-color:purple;');
|
|
30
|
-
expect(sheet?.innerHTML).toContain('font-size:16px;');
|
|
31
|
-
});
|
|
32
|
-
it('Should verify useCreateStyles hook updates the generated styles when they change', () => {
|
|
33
|
-
const Bogus = () => {
|
|
34
|
-
const [changeFont, setChangeFont] = useState(false);
|
|
35
|
-
if (changeFont) debugger;
|
|
36
|
-
const classes = useCreateStyles({
|
|
37
|
-
button: {
|
|
38
|
-
color: changeFont ? 'blue' : 'yellow',
|
|
39
|
-
},
|
|
40
|
-
app: {
|
|
41
|
-
backgroundColor: 'purple',
|
|
42
|
-
fontSize: '16px',
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
return (
|
|
46
|
-
<section className={classes.app} data-testid='app'>
|
|
47
|
-
Testing
|
|
48
|
-
<div>
|
|
49
|
-
<button data-testid='button' className={classes.button} onClick={() => setChangeFont(true)}>
|
|
50
|
-
Change Color
|
|
51
|
-
</button>
|
|
52
|
-
</div>
|
|
53
|
-
</section>
|
|
54
|
-
);
|
|
55
|
-
};
|
|
56
|
-
const result = render(<Bogus />);
|
|
57
|
-
const button = result.getByTestId('button');
|
|
58
|
-
const { className: initialButtonClassName } = button;
|
|
59
|
-
// shortcut - https://testing-library.com/docs/dom-testing-library/api-events/#fireeventeventname
|
|
60
|
-
fireEvent['click'](button);
|
|
61
|
-
|
|
62
|
-
const updatedButton = result.getByTestId('button');
|
|
63
|
-
expect(initialButtonClassName).not.toBe(updatedButton.className);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { beforeAll, describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { createStyles } from '../src/index.js';
|
|
4
|
-
|
|
5
|
-
describe('updateStyles tests', () => {
|
|
6
|
-
beforeAll(() => {
|
|
7
|
-
document.querySelectorAll('style').forEach(s => s.remove());
|
|
8
|
-
});
|
|
9
|
-
it('Should create styles, then update them without creating a new sheet', () => {
|
|
10
|
-
const {
|
|
11
|
-
classes: originalStyles,
|
|
12
|
-
stylesheet: originalContents,
|
|
13
|
-
updateSheet,
|
|
14
|
-
} = createStyles({
|
|
15
|
-
one: {
|
|
16
|
-
backgroundColor: 'grape',
|
|
17
|
-
boxSizing: 'border-box',
|
|
18
|
-
},
|
|
19
|
-
two: {
|
|
20
|
-
height: '100px',
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
expect(typeof updateSheet).toBe('function');
|
|
24
|
-
const sheet = document.head.querySelector('style');
|
|
25
|
-
expect(sheet?.innerHTML).toBe(originalContents);
|
|
26
|
-
const updates = updateSheet({
|
|
27
|
-
one: {
|
|
28
|
-
backgroundColor: 'red',
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
expect(updates).not.toBeNull();
|
|
32
|
-
const { classes: updatedStyles, stylesheet: updatedContents } = updates!;
|
|
33
|
-
expect(originalStyles).not.toBe(updatedStyles);
|
|
34
|
-
expect(originalContents).not.toBe(updatedContents);
|
|
35
|
-
expect(document.head.querySelectorAll('style').length).toBe(1);
|
|
36
|
-
expect(document.head.querySelector('style')?.innerHTML).toBe(updatedContents);
|
|
37
|
-
expect(updatedContents).toBe(
|
|
38
|
-
`.${updatedStyles.one}{background-color:red;box-sizing:border-box;}.${updatedStyles.two}{height:100px;}`,
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
});
|