@compiled/react 0.16.10 → 0.17.1
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/dist/browser/create-strict-api/index.d.ts +19 -22
- package/dist/browser/create-strict-api/index.js +6 -4
- package/dist/browser/create-strict-api/index.js.map +1 -1
- package/dist/browser/create-strict-api/types.d.ts +28 -0
- package/dist/browser/create-strict-api/types.js +2 -0
- package/dist/browser/create-strict-api/types.js.map +1 -0
- package/dist/browser/css/index.d.ts +2 -0
- package/dist/browser/css/index.js.map +1 -1
- package/dist/browser/css-map/index.d.ts +15 -2
- package/dist/browser/css-map/index.js.map +1 -1
- package/dist/browser/index.d.ts +3 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/types.d.ts +4 -2
- package/dist/browser/xcss-prop/index.d.ts +17 -14
- package/dist/browser/xcss-prop/index.js.map +1 -1
- package/dist/cjs/create-strict-api/index.d.ts +19 -22
- package/dist/cjs/create-strict-api/index.js +6 -4
- package/dist/cjs/create-strict-api/index.js.map +1 -1
- package/dist/cjs/create-strict-api/types.d.ts +28 -0
- package/dist/cjs/create-strict-api/types.js +3 -0
- package/dist/cjs/create-strict-api/types.js.map +1 -0
- package/dist/cjs/css/index.d.ts +2 -0
- package/dist/cjs/css/index.js.map +1 -1
- package/dist/cjs/css-map/index.d.ts +15 -2
- package/dist/cjs/css-map/index.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types.d.ts +4 -2
- package/dist/cjs/xcss-prop/index.d.ts +17 -14
- package/dist/cjs/xcss-prop/index.js.map +1 -1
- package/dist/esm/create-strict-api/index.d.ts +19 -22
- package/dist/esm/create-strict-api/index.js +6 -4
- package/dist/esm/create-strict-api/index.js.map +1 -1
- package/dist/esm/create-strict-api/types.d.ts +28 -0
- package/dist/esm/create-strict-api/types.js +2 -0
- package/dist/esm/create-strict-api/types.js.map +1 -0
- package/dist/esm/css/index.d.ts +2 -0
- package/dist/esm/css/index.js.map +1 -1
- package/dist/esm/css-map/index.d.ts +15 -2
- package/dist/esm/css-map/index.js.map +1 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +4 -2
- package/dist/esm/xcss-prop/index.d.ts +17 -14
- package/dist/esm/xcss-prop/index.js.map +1 -1
- package/package.json +1 -1
- package/src/create-strict-api/__tests__/__fixtures__/strict-api-recursive.ts +6 -6
- package/src/create-strict-api/__tests__/__fixtures__/strict-api.ts +14 -3
- package/src/create-strict-api/__tests__/css-func.test.tsx +49 -0
- package/src/create-strict-api/__tests__/generics.test.tsx +26 -5
- package/src/create-strict-api/__tests__/index.test.tsx +198 -32
- package/src/create-strict-api/index.ts +41 -34
- package/src/create-strict-api/types.ts +69 -0
- package/src/css/index.ts +2 -0
- package/src/css-map/index.ts +20 -2
- package/src/index.ts +16 -2
- package/src/types.ts +14 -10
- package/src/xcss-prop/__tests__/media-query-strict.test.tsx +179 -0
- package/src/xcss-prop/__tests__/media-query.test.tsx +53 -0
- package/src/xcss-prop/__tests__/xcss-prop.test.tsx +3 -34
- package/src/xcss-prop/index.ts +47 -28
|
@@ -99,7 +99,7 @@ describe('createStrictAPI()', () => {
|
|
|
99
99
|
const styles = cssMap({
|
|
100
100
|
primary: {
|
|
101
101
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
102
|
-
color: '
|
|
102
|
+
color: '',
|
|
103
103
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
104
104
|
backgroundColor: '',
|
|
105
105
|
'&:hover': {
|
|
@@ -155,15 +155,15 @@ describe('createStrictAPI()', () => {
|
|
|
155
155
|
backgroundColor: '',
|
|
156
156
|
'&:hover': {
|
|
157
157
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
158
|
-
color: '',
|
|
158
|
+
color: 'var(--ds-text)',
|
|
159
159
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
160
|
-
backgroundColor: '',
|
|
160
|
+
backgroundColor: 'var(--ds-success)',
|
|
161
161
|
},
|
|
162
162
|
'&:active': {
|
|
163
163
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
164
|
-
color: '',
|
|
164
|
+
color: 'var(--ds-text)',
|
|
165
165
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
166
|
-
backgroundColor: '',
|
|
166
|
+
backgroundColor: 'var(--ds-success)',
|
|
167
167
|
},
|
|
168
168
|
'&::before': {
|
|
169
169
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
@@ -188,21 +188,31 @@ describe('createStrictAPI()', () => {
|
|
|
188
188
|
describe('type success', () => {
|
|
189
189
|
it('should pass type check for css()', () => {
|
|
190
190
|
const styles = css({
|
|
191
|
+
// @ts-expect-error — should be a value from the schema
|
|
192
|
+
padding: '10px',
|
|
191
193
|
color: 'var(--ds-text)',
|
|
192
194
|
backgroundColor: 'var(--ds-bold)',
|
|
193
195
|
'&:hover': {
|
|
196
|
+
// @ts-expect-error — should be a value from the schema
|
|
197
|
+
padding: '10px',
|
|
194
198
|
color: 'var(--ds-text-hovered)',
|
|
195
199
|
backgroundColor: 'var(--ds-bold-hovered)',
|
|
196
200
|
},
|
|
197
201
|
'&:active': {
|
|
202
|
+
// @ts-expect-error — should be a value from the schema
|
|
203
|
+
padding: '10px',
|
|
198
204
|
color: 'var(--ds-text-pressed)',
|
|
199
205
|
backgroundColor: 'var(--ds-bold-pressed)',
|
|
200
206
|
},
|
|
201
207
|
'&::before': {
|
|
208
|
+
// @ts-expect-error — should be a value from the schema
|
|
209
|
+
padding: '10px',
|
|
202
210
|
color: 'var(--ds-text)',
|
|
203
211
|
backgroundColor: 'var(--ds-bold)',
|
|
204
212
|
},
|
|
205
213
|
'&::after': {
|
|
214
|
+
// @ts-expect-error — should be a value from the schema
|
|
215
|
+
padding: '10px',
|
|
206
216
|
color: 'var(--ds-text)',
|
|
207
217
|
backgroundColor: 'var(--ds-bold)',
|
|
208
218
|
},
|
|
@@ -218,19 +228,30 @@ describe('createStrictAPI()', () => {
|
|
|
218
228
|
primary: {
|
|
219
229
|
color: 'var(--ds-text)',
|
|
220
230
|
backgroundColor: 'var(--ds-bold)',
|
|
231
|
+
// @ts-expect-error — should be a value from the schema
|
|
232
|
+
padding: '10px',
|
|
221
233
|
'&:hover': {
|
|
234
|
+
accentColor: 'red',
|
|
235
|
+
// @ts-expect-error — should be a value from the schema
|
|
236
|
+
padding: '10px',
|
|
222
237
|
color: 'var(--ds-text-hovered)',
|
|
223
238
|
backgroundColor: 'var(--ds-bold-hovered)',
|
|
224
239
|
},
|
|
225
240
|
'&:active': {
|
|
241
|
+
// @ts-expect-error — should be a value from the schema
|
|
242
|
+
padding: '10px',
|
|
226
243
|
color: 'var(--ds-text-pressed)',
|
|
227
244
|
backgroundColor: 'var(--ds-bold-pressed)',
|
|
228
245
|
},
|
|
229
246
|
'&::before': {
|
|
247
|
+
// @ts-expect-error — should be a value from the schema
|
|
248
|
+
padding: '10px',
|
|
230
249
|
color: 'var(--ds-text)',
|
|
231
250
|
backgroundColor: 'var(--ds-bold)',
|
|
232
251
|
},
|
|
233
252
|
'&::after': {
|
|
253
|
+
// @ts-expect-error — should be a value from the schema
|
|
254
|
+
padding: '10px',
|
|
234
255
|
color: 'var(--ds-text)',
|
|
235
256
|
backgroundColor: 'var(--ds-bold)',
|
|
236
257
|
},
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
/** @jsxImportSource @compiled/react */
|
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
3
|
+
import { cssMap as cssMapLoose } from '@compiled/react';
|
|
2
4
|
import { render } from '@testing-library/react';
|
|
3
5
|
|
|
4
|
-
import { css, cssMap, XCSSProp } from './__fixtures__/strict-api';
|
|
6
|
+
import { css, cssMap, XCSSProp, cx } from './__fixtures__/strict-api';
|
|
5
7
|
|
|
6
8
|
describe('createStrictAPI()', () => {
|
|
7
9
|
describe('css()', () => {
|
|
8
10
|
it('should type error when circumventing the excess property check', () => {
|
|
9
|
-
const
|
|
11
|
+
const stylesOne = css({
|
|
10
12
|
color: 'var(--ds-text)',
|
|
11
13
|
accentColor: 'red',
|
|
12
14
|
// @ts-expect-error — Type 'string' is not assignable to type 'undefined'.ts(2322)
|
|
13
15
|
bkgrnd: 'red',
|
|
16
|
+
'&:hover': {
|
|
17
|
+
color: 'var(--ds-text-hover)',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const stylesTwo = css({
|
|
21
|
+
color: 'var(--ds-text)',
|
|
22
|
+
accentColor: 'red',
|
|
14
23
|
'&:hover': {
|
|
15
24
|
color: 'var(--ds-text-hover)',
|
|
16
25
|
// @ts-expect-error — Type 'string' is not assignable to type 'undefined'.ts(2322)
|
|
@@ -18,7 +27,7 @@ describe('createStrictAPI()', () => {
|
|
|
18
27
|
},
|
|
19
28
|
});
|
|
20
29
|
|
|
21
|
-
const { getByTestId } = render(<div css={
|
|
30
|
+
const { getByTestId } = render(<div css={[stylesOne, stylesTwo]} data-testid="div" />);
|
|
22
31
|
|
|
23
32
|
expect(getByTestId('div')).toHaveCompiledCss('color', 'var(--ds-text)');
|
|
24
33
|
});
|
|
@@ -79,7 +88,7 @@ describe('createStrictAPI()', () => {
|
|
|
79
88
|
color: 'var(--ds-text)',
|
|
80
89
|
all: 'inherit',
|
|
81
90
|
'&:hover': { color: 'var(--ds-text-hover)' },
|
|
82
|
-
'&:invalid': { color: '
|
|
91
|
+
'&:invalid': { color: 'var(--ds-text)' },
|
|
83
92
|
});
|
|
84
93
|
|
|
85
94
|
const { getByTestId } = render(<div css={styles} data-testid="div" />);
|
|
@@ -146,7 +155,7 @@ describe('createStrictAPI()', () => {
|
|
|
146
155
|
accentColor: 'red',
|
|
147
156
|
all: 'inherit',
|
|
148
157
|
'&:hover': { color: 'var(--ds-text-hover)' },
|
|
149
|
-
'&:invalid': { color: '
|
|
158
|
+
'&:invalid': { color: 'var(--ds-text)' },
|
|
150
159
|
},
|
|
151
160
|
});
|
|
152
161
|
|
|
@@ -271,12 +280,94 @@ describe('createStrictAPI()', () => {
|
|
|
271
280
|
});
|
|
272
281
|
|
|
273
282
|
describe('XCSSProp', () => {
|
|
283
|
+
it('should error with values not in the strict `CompiledStrictSchema`', () => {
|
|
284
|
+
function Button({
|
|
285
|
+
xcss,
|
|
286
|
+
testId,
|
|
287
|
+
}: {
|
|
288
|
+
testId: string;
|
|
289
|
+
xcss: ReturnType<typeof XCSSProp<'background' | 'color', '&:hover'>>;
|
|
290
|
+
}) {
|
|
291
|
+
return <button data-testid={testId} className={xcss} />;
|
|
292
|
+
}
|
|
293
|
+
// NOTE: For some reason the "background" property is being expanded to "string" instead of
|
|
294
|
+
// staying narrowed as "var(--ds-surface-hover)" meaning it breaks when used with the strict
|
|
295
|
+
// schema loaded XCSS prop. This is a bug and unexpected.
|
|
296
|
+
const stylesValidRoot = cssMapLoose({
|
|
297
|
+
primary: {
|
|
298
|
+
color: 'var(--ds-text)',
|
|
299
|
+
'&:hover': { color: 'var(--ds-text-hover)', background: 'var(--ds-surface-hover)' },
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
const stylesInvalidRoot = cssMapLoose({
|
|
303
|
+
primary: {
|
|
304
|
+
color: 'red',
|
|
305
|
+
'&:hover': { color: 'var(--ds-text-hover)', background: 'var(--ds-surface-hover)' },
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
const stylesInvalid = cssMap({
|
|
309
|
+
primary: {
|
|
310
|
+
// @ts-expect-error -- This is not valid in the CompiledStrictSchema
|
|
311
|
+
color: 'red',
|
|
312
|
+
'&:hover': { color: 'var(--ds-text-hover)', background: 'var(--ds-surface-hover)' },
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const stylesValid = cssMap({
|
|
317
|
+
primary: {
|
|
318
|
+
color: 'var(--ds-text)',
|
|
319
|
+
'&:hover': { color: 'var(--ds-text-hover)', background: 'var(--ds-surface-hover)' },
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const { getByTestId } = render(
|
|
324
|
+
<>
|
|
325
|
+
<Button
|
|
326
|
+
testId="button-invalid-root"
|
|
327
|
+
// @ts-expect-error — This conflicts with the custom API, should be a different bg color
|
|
328
|
+
xcss={stylesInvalidRoot.primary}
|
|
329
|
+
/>
|
|
330
|
+
<Button
|
|
331
|
+
testId="button-invalid-root-cx"
|
|
332
|
+
// @ts-expect-error — This conflicts with the custom API, should be a different bg color
|
|
333
|
+
xcss={cx(stylesInvalidRoot.primary, stylesValid.primary)}
|
|
334
|
+
/>
|
|
335
|
+
<Button
|
|
336
|
+
testId="button-invalid-strict"
|
|
337
|
+
// @ts-expect-error — TODO: This should conflict, but when `cssMap` conflicts, it gets a different type (this has `ApplySchema`, not the raw object), so this doesn't error? Weird…
|
|
338
|
+
xcss={stylesInvalid.primary}
|
|
339
|
+
/>
|
|
340
|
+
<Button
|
|
341
|
+
testId="button-invalid-strict-cx"
|
|
342
|
+
// @ts-expect-error — TODO: This should conflict, but when `cssMap` conflicts, it gets a different type (this has `ApplySchema`, not the raw object), so this doesn't error? Weird…
|
|
343
|
+
xcss={cx(stylesInvalid.primary, stylesValid.primary)}
|
|
344
|
+
/>
|
|
345
|
+
<Button
|
|
346
|
+
testId="button-invalid-direct"
|
|
347
|
+
xcss={{
|
|
348
|
+
// @ts-expect-error — This is not in the `createStrictAPI` schema—this should be a css variable.
|
|
349
|
+
color: 'red',
|
|
350
|
+
}}
|
|
351
|
+
/>
|
|
352
|
+
<Button testId="button-valid" xcss={stylesValid.primary} />
|
|
353
|
+
<Button testId="button-valid-cx" xcss={cx(stylesValid.primary, stylesValid.primary)} />
|
|
354
|
+
<Button testId="button-valid-root" xcss={stylesValidRoot.primary} />
|
|
355
|
+
<Button
|
|
356
|
+
testId="button-valid-root-cx"
|
|
357
|
+
xcss={cx(stylesValidRoot.primary, stylesValid.primary)}
|
|
358
|
+
/>
|
|
359
|
+
</>
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
expect(getByTestId('button-invalid-root')).toHaveCompiledCss('color', 'red');
|
|
363
|
+
});
|
|
364
|
+
|
|
274
365
|
it('should allow valid values from cssMap', () => {
|
|
275
366
|
function Button({ xcss }: { xcss: ReturnType<typeof XCSSProp<'background', never>> }) {
|
|
276
367
|
return <button data-testid="button" className={xcss} />;
|
|
277
368
|
}
|
|
278
|
-
|
|
279
369
|
const styles = cssMap({ bg: { background: 'var(--ds-surface)' } });
|
|
370
|
+
|
|
280
371
|
const { getByTestId } = render(<Button xcss={styles.bg} />);
|
|
281
372
|
|
|
282
373
|
expect(getByTestId('button')).toHaveCompiledCss('background', 'var(--ds-surface)');
|
|
@@ -302,7 +393,6 @@ describe('createStrictAPI()', () => {
|
|
|
302
393
|
function Button({ xcss }: { xcss: ReturnType<typeof XCSSProp<'background', '&:hover'>> }) {
|
|
303
394
|
return <button data-testid="button" className={xcss} />;
|
|
304
395
|
}
|
|
305
|
-
|
|
306
396
|
const styles = cssMap({
|
|
307
397
|
primary: {
|
|
308
398
|
background: 'var(--ds-surface)',
|
|
@@ -341,15 +431,24 @@ describe('createStrictAPI()', () => {
|
|
|
341
431
|
it('should error with values not in the strict `CompiledAPI`', () => {
|
|
342
432
|
function Button({
|
|
343
433
|
xcss,
|
|
434
|
+
testId,
|
|
344
435
|
}: {
|
|
436
|
+
testId: string;
|
|
345
437
|
xcss: ReturnType<typeof XCSSProp<'background' | 'color', '&:hover'>>;
|
|
346
438
|
}) {
|
|
347
|
-
return <button data-testid=
|
|
439
|
+
return <button data-testid={testId} className={xcss} />;
|
|
348
440
|
}
|
|
349
441
|
|
|
350
|
-
const
|
|
442
|
+
const stylesOne = cssMapLoose({
|
|
351
443
|
primary: {
|
|
352
|
-
|
|
444
|
+
color: 'red',
|
|
445
|
+
background: 'var(--ds-surface)',
|
|
446
|
+
'&:hover': { background: 'var(--ds-surface-hover)' },
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
const stylesTwo = cssMap({
|
|
450
|
+
primary: {
|
|
451
|
+
// @ts-expect-error — This is not in the `createStrictAPI` schema—this should be a css variable.
|
|
353
452
|
color: 'red',
|
|
354
453
|
background: 'var(--ds-surface)',
|
|
355
454
|
'&:hover': { background: 'var(--ds-surface-hover)' },
|
|
@@ -357,13 +456,28 @@ describe('createStrictAPI()', () => {
|
|
|
357
456
|
});
|
|
358
457
|
|
|
359
458
|
const { getByTestId } = render(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
459
|
+
<>
|
|
460
|
+
<Button
|
|
461
|
+
testId="button-1"
|
|
462
|
+
// @ts-expect-error — This is not in the `createStrictAPI` schema—this should be a css variable.
|
|
463
|
+
xcss={stylesOne.primary}
|
|
464
|
+
/>
|
|
465
|
+
<Button
|
|
466
|
+
testId="button-3"
|
|
467
|
+
// @ts-expect-error — This is not in the `createStrictAPI` schema—this should be a css variable.
|
|
468
|
+
xcss={stylesTwo.stylesTwo}
|
|
469
|
+
/>
|
|
470
|
+
<Button
|
|
471
|
+
testId="button-2"
|
|
472
|
+
xcss={{
|
|
473
|
+
// @ts-expect-error — This is not in the `createStrictAPI` schema—this should be a css variable.
|
|
474
|
+
color: 'red',
|
|
475
|
+
}}
|
|
476
|
+
/>
|
|
477
|
+
</>
|
|
364
478
|
);
|
|
365
479
|
|
|
366
|
-
expect(getByTestId('button')).toHaveCompiledCss('background', 'var(--ds-surface)');
|
|
480
|
+
expect(getByTestId('button-1')).toHaveCompiledCss('background', 'var(--ds-surface)');
|
|
367
481
|
});
|
|
368
482
|
|
|
369
483
|
it('should error with properties not in the `XCSSProp`', () => {
|
|
@@ -380,7 +494,7 @@ describe('createStrictAPI()', () => {
|
|
|
380
494
|
|
|
381
495
|
const { getByTestId } = render(
|
|
382
496
|
<Button
|
|
383
|
-
// @ts-expect-error
|
|
497
|
+
// @ts-expect-error — Errors because `background` + `&:hover` are not in the `XCSSProp` schema.
|
|
384
498
|
xcss={styles.primary}
|
|
385
499
|
/>
|
|
386
500
|
);
|
|
@@ -392,21 +506,24 @@ describe('createStrictAPI()', () => {
|
|
|
392
506
|
function Button({ xcss }: { xcss: ReturnType<typeof XCSSProp<'background', '&:hover'>> }) {
|
|
393
507
|
return <button data-testid="button" className={xcss} />;
|
|
394
508
|
}
|
|
395
|
-
|
|
396
|
-
const styles = cssMap({
|
|
509
|
+
const stylesOne = cssMap({
|
|
397
510
|
primary: {
|
|
398
|
-
// @ts-expect-error
|
|
511
|
+
// @ts-expect-error — Fails because `foo` is not assignable to our CSSProperties whatsoever.
|
|
399
512
|
foo: 'bar',
|
|
400
513
|
background: 'var(--ds-surface)',
|
|
514
|
+
},
|
|
515
|
+
});
|
|
516
|
+
const stylesTwo = cssMap({
|
|
517
|
+
hover: {
|
|
401
518
|
'&:hover': {
|
|
402
|
-
//
|
|
519
|
+
// @ts-expect-error — Fails because `foo` is not assignable to our CSSProperties whatsoever.
|
|
403
520
|
foo: 'bar',
|
|
404
521
|
background: 'var(--ds-surface-hover)',
|
|
405
522
|
},
|
|
406
523
|
},
|
|
407
524
|
});
|
|
408
525
|
|
|
409
|
-
const { getByTestId } = render(<Button xcss={
|
|
526
|
+
const { getByTestId } = render(<Button xcss={cx(stylesOne.primary, stylesTwo.hover)} />);
|
|
410
527
|
|
|
411
528
|
expect(getByTestId('button')).toHaveCompiledCss('background', 'var(--ds-surface)');
|
|
412
529
|
});
|
|
@@ -536,27 +653,76 @@ describe('createStrictAPI()', () => {
|
|
|
536
653
|
|
|
537
654
|
it('should enforce required properties', () => {
|
|
538
655
|
function Button({
|
|
656
|
+
testId,
|
|
539
657
|
xcss,
|
|
540
658
|
}: {
|
|
659
|
+
testId: string;
|
|
541
660
|
xcss: ReturnType<
|
|
542
|
-
typeof XCSSProp<
|
|
543
|
-
'background',
|
|
544
|
-
never,
|
|
545
|
-
{ requiredProperties: 'background'; requiredPseudos: never }
|
|
546
|
-
>
|
|
661
|
+
typeof XCSSProp<'background' | 'color', never, { requiredProperties: 'background' }>
|
|
547
662
|
>;
|
|
548
663
|
}) {
|
|
549
|
-
return <button data-testid=
|
|
664
|
+
return <button data-testid={`button-${testId}`} className={xcss} />;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const stylesValid = cssMap({
|
|
668
|
+
primary: { background: 'var(--ds-surface)' },
|
|
669
|
+
});
|
|
670
|
+
const stylesInvalid = cssMap({
|
|
671
|
+
primary: { color: 'var(--ds-text)' },
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const { getByTestId } = render(
|
|
675
|
+
<>
|
|
676
|
+
<Button testId="valid" xcss={stylesValid.primary} />
|
|
677
|
+
<Button
|
|
678
|
+
testId="invalid"
|
|
679
|
+
// @ts-expect-error — This is not assignable as it's missing the required `background` property.
|
|
680
|
+
xcss={stylesInvalid.primary}
|
|
681
|
+
/>
|
|
682
|
+
</>
|
|
683
|
+
);
|
|
684
|
+
|
|
685
|
+
expect(getByTestId('button-valid')).toHaveCompiledCss('background', 'var(--ds-surface)');
|
|
686
|
+
expect(getByTestId('button-invalid')).toHaveCompiledCss('color', 'var(--ds-text)');
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
it('should enforce required psuedos', () => {
|
|
690
|
+
function Button({
|
|
691
|
+
testId,
|
|
692
|
+
xcss,
|
|
693
|
+
}: {
|
|
694
|
+
testId: string;
|
|
695
|
+
xcss: ReturnType<
|
|
696
|
+
typeof XCSSProp<'color', '&:hover' | '&:focus', { requiredProperties: never }>
|
|
697
|
+
>;
|
|
698
|
+
}) {
|
|
699
|
+
return <button data-testid={`button-${testId}`} className={xcss} />;
|
|
550
700
|
}
|
|
551
701
|
|
|
702
|
+
const stylesValid = cssMap({
|
|
703
|
+
primary: { '&:hover': { color: 'var(--ds-text-hover)' } },
|
|
704
|
+
});
|
|
705
|
+
const stylesInvalid = cssMap({
|
|
706
|
+
primary: { '&:focus': { background: 'var(--ds-surface)' } },
|
|
707
|
+
});
|
|
708
|
+
|
|
552
709
|
const { getByTestId } = render(
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
710
|
+
<>
|
|
711
|
+
<Button testId="valid" xcss={stylesValid.primary} />
|
|
712
|
+
<Button
|
|
713
|
+
testId="invalid"
|
|
714
|
+
// @ts-expect-error — This is not assignable as it's missing the required `background` property.
|
|
715
|
+
xcss={stylesInvalid.primary}
|
|
716
|
+
/>
|
|
717
|
+
</>
|
|
557
718
|
);
|
|
558
719
|
|
|
559
|
-
expect(getByTestId('button')).
|
|
720
|
+
expect(getByTestId('button-valid')).toHaveCompiledCss('color', 'var(--ds-text-hover)', {
|
|
721
|
+
target: ':hover',
|
|
722
|
+
});
|
|
723
|
+
expect(getByTestId('button-invalid')).toHaveCompiledCss('background', 'var(--ds-surface)', {
|
|
724
|
+
target: ':focus',
|
|
725
|
+
});
|
|
560
726
|
});
|
|
561
727
|
});
|
|
562
728
|
|
|
@@ -1,32 +1,25 @@
|
|
|
1
|
-
import type { StrictCSSProperties, CSSPseudos } from '../types';
|
|
1
|
+
import type { StrictCSSProperties, CSSPseudos, CSSProps } from '../types';
|
|
2
2
|
import { createStrictSetupError } from '../utils/error';
|
|
3
3
|
import { type CompiledStyles, cx, type Internal$XCSSProp } from '../xcss-prop';
|
|
4
4
|
|
|
5
|
-
type
|
|
6
|
-
[Q in CSSPseudos]?: StrictCSSProperties;
|
|
7
|
-
};
|
|
5
|
+
import type { AllowedStyles, ApplySchema, ApplySchemaMap, CompiledSchemaShape } from './types';
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
? EnforceSchema<TSchema[P]>
|
|
13
|
-
: TSchema[P]
|
|
14
|
-
: never;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
type CSSStyles<TSchema extends CompiledSchema> = StrictCSSProperties &
|
|
18
|
-
PseudosDeclarations &
|
|
19
|
-
EnforceSchema<TSchema>;
|
|
20
|
-
|
|
21
|
-
type CSSMapStyles<TSchema extends CompiledSchema> = Record<string, CSSStyles<TSchema>>;
|
|
7
|
+
export interface StrictOptions {
|
|
8
|
+
media: string;
|
|
9
|
+
}
|
|
22
10
|
|
|
23
|
-
interface CompiledAPI<
|
|
11
|
+
export interface CompiledAPI<
|
|
12
|
+
TSchema extends CompiledSchemaShape,
|
|
13
|
+
TAllowedMediaQueries extends string
|
|
14
|
+
> {
|
|
24
15
|
/**
|
|
25
16
|
* ## CSS
|
|
26
17
|
*
|
|
27
18
|
* Creates styles that are statically typed and useable with other Compiled APIs.
|
|
28
19
|
* For further details [read the documentation](https://compiledcssinjs.com/docs/api-css).
|
|
29
20
|
*
|
|
21
|
+
* This API does not currently work with XCSS prop.
|
|
22
|
+
*
|
|
30
23
|
* @example
|
|
31
24
|
* ```
|
|
32
25
|
* const redText = css({
|
|
@@ -36,7 +29,12 @@ interface CompiledAPI<TSchema extends CompiledSchema> {
|
|
|
36
29
|
* <div css={redText} />
|
|
37
30
|
* ```
|
|
38
31
|
*/
|
|
39
|
-
css
|
|
32
|
+
css<TStyles extends ApplySchema<TStyles, TSchema>>(
|
|
33
|
+
styles: AllowedStyles<TAllowedMediaQueries> & TStyles
|
|
34
|
+
// NOTE: This return type is deliberately not using ReadOnly<CompiledStyles<TStyles>>
|
|
35
|
+
// So it type errors when used with XCSS prop. When we update the compiler to work with
|
|
36
|
+
// it we can update the return type so it stops being a type violation.
|
|
37
|
+
): CSSProps<unknown>;
|
|
40
38
|
/**
|
|
41
39
|
* ## CSS Map
|
|
42
40
|
*
|
|
@@ -53,11 +51,11 @@ interface CompiledAPI<TSchema extends CompiledSchema> {
|
|
|
53
51
|
* <div css={styles.solid} />
|
|
54
52
|
* ```
|
|
55
53
|
*/
|
|
56
|
-
cssMap<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
styles:
|
|
54
|
+
cssMap<
|
|
55
|
+
TObject extends Record<string, AllowedStyles<TAllowedMediaQueries>>,
|
|
56
|
+
TStylesMap extends ApplySchemaMap<TObject, TSchema>
|
|
57
|
+
>(
|
|
58
|
+
styles: Record<string, AllowedStyles<TAllowedMediaQueries>> & TStylesMap
|
|
61
59
|
): {
|
|
62
60
|
readonly [P in keyof TStylesMap]: CompiledStyles<TStylesMap[P]>;
|
|
63
61
|
};
|
|
@@ -116,7 +114,7 @@ interface CompiledAPI<TSchema extends CompiledSchema> {
|
|
|
116
114
|
* typeof XCSSProp<
|
|
117
115
|
* XCSSAllProperties,
|
|
118
116
|
* '&:hover',
|
|
119
|
-
* { requiredProperties: 'color'
|
|
117
|
+
* { requiredProperties: 'color' }
|
|
120
118
|
* >
|
|
121
119
|
* >;
|
|
122
120
|
* }
|
|
@@ -144,13 +142,17 @@ interface CompiledAPI<TSchema extends CompiledSchema> {
|
|
|
144
142
|
TAllowedPseudos extends CSSPseudos,
|
|
145
143
|
TRequiredProperties extends {
|
|
146
144
|
requiredProperties: TAllowedProperties;
|
|
147
|
-
requiredPseudos: TAllowedPseudos;
|
|
148
145
|
} = never
|
|
149
|
-
>(): Internal$XCSSProp<
|
|
146
|
+
>(): Internal$XCSSProp<
|
|
147
|
+
TAllowedProperties,
|
|
148
|
+
TAllowedPseudos,
|
|
149
|
+
TAllowedMediaQueries,
|
|
150
|
+
TSchema,
|
|
151
|
+
TRequiredProperties,
|
|
152
|
+
'strict'
|
|
153
|
+
>;
|
|
150
154
|
}
|
|
151
155
|
|
|
152
|
-
type CompiledSchema = StrictCSSProperties & PseudosDeclarations;
|
|
153
|
-
|
|
154
156
|
/**
|
|
155
157
|
* ## Create Strict API
|
|
156
158
|
*
|
|
@@ -165,17 +167,19 @@ type CompiledSchema = StrictCSSProperties & PseudosDeclarations;
|
|
|
165
167
|
*
|
|
166
168
|
* To set up:
|
|
167
169
|
*
|
|
168
|
-
* 1. Declare the API in a module (either local or in a package)
|
|
170
|
+
* 1. Declare the API in a module (either local or in a package), optionally declaring accepted media queries.
|
|
169
171
|
*
|
|
170
172
|
* @example
|
|
171
173
|
* ```tsx
|
|
172
174
|
* // ./foo.ts
|
|
173
|
-
*
|
|
175
|
+
* interface Schema {
|
|
174
176
|
* color: 'var(--ds-text)',
|
|
175
177
|
* '&:hover': { color: 'var(--ds-text-hover)' }
|
|
176
|
-
* }
|
|
178
|
+
* }
|
|
179
|
+
*
|
|
180
|
+
* const { css, cssMap, XCSSProp, cx } = createStrictAPI<Schema, { media: '(min-width: 30rem)' }>();
|
|
177
181
|
*
|
|
178
|
-
* export { css };
|
|
182
|
+
* export { css, cssMap, XCSSProp, cx };
|
|
179
183
|
* ```
|
|
180
184
|
*
|
|
181
185
|
* 2. Configure Compiled to pick up this module:
|
|
@@ -199,7 +203,10 @@ type CompiledSchema = StrictCSSProperties & PseudosDeclarations;
|
|
|
199
203
|
* <div css={styles} />
|
|
200
204
|
* ```
|
|
201
205
|
*/
|
|
202
|
-
export function createStrictAPI<
|
|
206
|
+
export function createStrictAPI<
|
|
207
|
+
TSchema extends CompiledSchemaShape,
|
|
208
|
+
TCreateStrictAPIOptions extends StrictOptions = never
|
|
209
|
+
>(): CompiledAPI<TSchema, TCreateStrictAPIOptions['media']> {
|
|
203
210
|
return {
|
|
204
211
|
css() {
|
|
205
212
|
throw createStrictSetupError();
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
StrictCSSProperties,
|
|
3
|
+
CSSPseudoClasses,
|
|
4
|
+
CSSPseudoElements,
|
|
5
|
+
CSSPseudos,
|
|
6
|
+
} from '../types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This is the shape of the generic object that `createStrictAPI()` takes.
|
|
10
|
+
* It's deliberately a subset of `AllowedStyles` and does not take at rules
|
|
11
|
+
* and pseudo elements.
|
|
12
|
+
*/
|
|
13
|
+
export type CompiledSchemaShape = StrictCSSProperties & {
|
|
14
|
+
[Q in CSSPseudoClasses]?: StrictCSSProperties;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type PseudosDeclarations = { [Q in CSSPseudos]?: StrictCSSProperties };
|
|
18
|
+
|
|
19
|
+
export type MediaQueries<TMediaQuery extends string> = {
|
|
20
|
+
[Q in `@media ${TMediaQuery}`]?: StrictCSSProperties & PseudosDeclarations;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type AllowedStyles<TMediaQuery extends string> = StrictCSSProperties &
|
|
24
|
+
PseudosDeclarations &
|
|
25
|
+
MediaQueries<TMediaQuery>;
|
|
26
|
+
|
|
27
|
+
export type ApplySchemaValue<
|
|
28
|
+
TSchema,
|
|
29
|
+
TKey extends keyof StrictCSSProperties,
|
|
30
|
+
TPseudoKey extends CSSPseudoClasses | ''
|
|
31
|
+
> = TKey extends keyof TSchema
|
|
32
|
+
? // TKey is a valid property on the schema
|
|
33
|
+
TPseudoKey extends keyof TSchema
|
|
34
|
+
? TKey extends keyof TSchema[TPseudoKey]
|
|
35
|
+
? // We found a more specific value under TPseudoKey.
|
|
36
|
+
TSchema[TPseudoKey][TKey]
|
|
37
|
+
: // Did not found anything specific, use the top level TSchema value.
|
|
38
|
+
TSchema[TKey]
|
|
39
|
+
: // Did not found anything specific, use the top level TSchema value.
|
|
40
|
+
TSchema[TKey]
|
|
41
|
+
: // TKey wasn't found on the schema, fallback to the CSS property value
|
|
42
|
+
StrictCSSProperties[TKey];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Recursively maps over object properties to resolve them to either a {@link TSchema}
|
|
46
|
+
* value if present, else fallback to its value from {@link StrictCSSProperties}. If
|
|
47
|
+
* the property isn't a known property its value will be resolved to `never`.
|
|
48
|
+
*/
|
|
49
|
+
export type ApplySchema<TObject, TSchema, TPseudoKey extends CSSPseudoClasses | '' = ''> = {
|
|
50
|
+
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties
|
|
51
|
+
? // TKey is a valid CSS property, try to resolve its value.
|
|
52
|
+
ApplySchemaValue<TSchema, TKey, TPseudoKey>
|
|
53
|
+
: TKey extends CSSPseudoClasses
|
|
54
|
+
? // TKey is a valid pseudo class, recursively resolve its child properties
|
|
55
|
+
// while passing down the parent pseudo key to resolve any specific schema types.
|
|
56
|
+
ApplySchema<TObject[TKey], TSchema, TKey>
|
|
57
|
+
: TKey extends `@${string}` | CSSPseudoElements
|
|
58
|
+
? // TKey is either an at rule or a pseudo element, either way we don't care about
|
|
59
|
+
// passing down the key so we recursively resolve its child properties starting at
|
|
60
|
+
// the base schema, treating it as if it's not inside an object.
|
|
61
|
+
ApplySchema<TObject[TKey], TSchema>
|
|
62
|
+
: // Fallback case, did not find a valid CSS property, at rule, or pseudo.
|
|
63
|
+
// Resolve the value to `never` which will end up being a type violation.
|
|
64
|
+
never;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type ApplySchemaMap<TStylesMap, TSchema> = {
|
|
68
|
+
[P in keyof TStylesMap]: ApplySchema<TStylesMap[P], TSchema>;
|
|
69
|
+
};
|
package/src/css/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ import { createSetupError } from '../utils/error';
|
|
|
9
9
|
* Create styles that are statically typed and useable with other Compiled APIs.
|
|
10
10
|
* For further details [read the documentation](https://compiledcssinjs.com/docs/api-css).
|
|
11
11
|
*
|
|
12
|
+
* This API does not currently work with XCSS prop.
|
|
13
|
+
*
|
|
12
14
|
* ### Style with objects
|
|
13
15
|
*
|
|
14
16
|
* @example
|