@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.
Files changed (63) hide show
  1. package/dist/browser/create-strict-api/index.d.ts +19 -22
  2. package/dist/browser/create-strict-api/index.js +6 -4
  3. package/dist/browser/create-strict-api/index.js.map +1 -1
  4. package/dist/browser/create-strict-api/types.d.ts +28 -0
  5. package/dist/browser/create-strict-api/types.js +2 -0
  6. package/dist/browser/create-strict-api/types.js.map +1 -0
  7. package/dist/browser/css/index.d.ts +2 -0
  8. package/dist/browser/css/index.js.map +1 -1
  9. package/dist/browser/css-map/index.d.ts +15 -2
  10. package/dist/browser/css-map/index.js.map +1 -1
  11. package/dist/browser/index.d.ts +3 -2
  12. package/dist/browser/index.js +1 -1
  13. package/dist/browser/index.js.map +1 -1
  14. package/dist/browser/types.d.ts +4 -2
  15. package/dist/browser/xcss-prop/index.d.ts +17 -14
  16. package/dist/browser/xcss-prop/index.js.map +1 -1
  17. package/dist/cjs/create-strict-api/index.d.ts +19 -22
  18. package/dist/cjs/create-strict-api/index.js +6 -4
  19. package/dist/cjs/create-strict-api/index.js.map +1 -1
  20. package/dist/cjs/create-strict-api/types.d.ts +28 -0
  21. package/dist/cjs/create-strict-api/types.js +3 -0
  22. package/dist/cjs/create-strict-api/types.js.map +1 -0
  23. package/dist/cjs/css/index.d.ts +2 -0
  24. package/dist/cjs/css/index.js.map +1 -1
  25. package/dist/cjs/css-map/index.d.ts +15 -2
  26. package/dist/cjs/css-map/index.js.map +1 -1
  27. package/dist/cjs/index.d.ts +3 -2
  28. package/dist/cjs/index.js.map +1 -1
  29. package/dist/cjs/types.d.ts +4 -2
  30. package/dist/cjs/xcss-prop/index.d.ts +17 -14
  31. package/dist/cjs/xcss-prop/index.js.map +1 -1
  32. package/dist/esm/create-strict-api/index.d.ts +19 -22
  33. package/dist/esm/create-strict-api/index.js +6 -4
  34. package/dist/esm/create-strict-api/index.js.map +1 -1
  35. package/dist/esm/create-strict-api/types.d.ts +28 -0
  36. package/dist/esm/create-strict-api/types.js +2 -0
  37. package/dist/esm/create-strict-api/types.js.map +1 -0
  38. package/dist/esm/css/index.d.ts +2 -0
  39. package/dist/esm/css/index.js.map +1 -1
  40. package/dist/esm/css-map/index.d.ts +15 -2
  41. package/dist/esm/css-map/index.js.map +1 -1
  42. package/dist/esm/index.d.ts +3 -2
  43. package/dist/esm/index.js +1 -1
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/types.d.ts +4 -2
  46. package/dist/esm/xcss-prop/index.d.ts +17 -14
  47. package/dist/esm/xcss-prop/index.js.map +1 -1
  48. package/package.json +1 -1
  49. package/src/create-strict-api/__tests__/__fixtures__/strict-api-recursive.ts +6 -6
  50. package/src/create-strict-api/__tests__/__fixtures__/strict-api.ts +14 -3
  51. package/src/create-strict-api/__tests__/css-func.test.tsx +49 -0
  52. package/src/create-strict-api/__tests__/generics.test.tsx +26 -5
  53. package/src/create-strict-api/__tests__/index.test.tsx +198 -32
  54. package/src/create-strict-api/index.ts +41 -34
  55. package/src/create-strict-api/types.ts +69 -0
  56. package/src/css/index.ts +2 -0
  57. package/src/css-map/index.ts +20 -2
  58. package/src/index.ts +16 -2
  59. package/src/types.ts +14 -10
  60. package/src/xcss-prop/__tests__/media-query-strict.test.tsx +179 -0
  61. package/src/xcss-prop/__tests__/media-query.test.tsx +53 -0
  62. package/src/xcss-prop/__tests__/xcss-prop.test.tsx +3 -34
  63. 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: 's',
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 styles = css({
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={styles} data-testid="div" />);
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: 'orange' },
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: 'orange' },
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="button" className={xcss} />;
439
+ return <button data-testid={testId} className={xcss} />;
348
440
  }
349
441
 
350
- const styles = cssMap({
442
+ const stylesOne = cssMapLoose({
351
443
  primary: {
352
- // @ts-expect-error -- This is not in the `createStrictAPI` schema—this should be a css variable.
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
- <Button
361
- // @ts-expect-error -- Errors because `color` conflicts with the `XCSSProp` schema–`color` should be a css variable.
362
- xcss={styles.primary}
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 -- Errors because `background` + `&:hover` are not in the `XCSSProp` schema.
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 -- Fails because `foo` is not assignable to our CSSProperties whatsoever.
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
- // This does not fail, but would if the above was removed; this should be tested in raw `cssMap` fully.
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={styles.primary} />);
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="button" className={xcss} />;
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
- <Button
554
- // @ts-expect-error — Type '{}' is not assignable to type 'Internal$XCSSProp<"background", never, EnforceSchema<{ background: "var(--ds-surface)" | "var(--ds-surface-sunken"; }>, object, { requiredProperties: "background"; requiredPseudos: never; }>'.ts(2322)
555
- xcss={{}}
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')).not.toHaveCompiledCss('color', 'red');
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 PseudosDeclarations = {
6
- [Q in CSSPseudos]?: StrictCSSProperties;
7
- };
5
+ import type { AllowedStyles, ApplySchema, ApplySchemaMap, CompiledSchemaShape } from './types';
8
6
 
9
- type EnforceSchema<TSchema> = {
10
- [P in keyof TSchema]?: P extends keyof CompiledSchema
11
- ? TSchema[P] extends Record<string, any>
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<TSchema extends CompiledSchema> {
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(styles: CSSStyles<TSchema>): StrictCSSProperties;
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<TStylesMap extends CSSMapStyles<TSchema>>(
57
- // We intersection type the generic both with the concrete type and the generic to ensure the output has the generic applied.
58
- // Without both it would either have the input arg not have excess property check kick in allowing unexpected values or
59
- // have all values set as the output making usage with XCSSProp have type violations unexpectedly.
60
- styles: CSSMapStyles<TSchema> & TStylesMap
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', requiredPseudos: never }
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<TAllowedProperties, TAllowedPseudos, TSchema, TRequiredProperties>;
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
- * const { css } = createStrictAPI<{
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<TSchema extends CompiledSchema>(): CompiledAPI<TSchema> {
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