@compiled/react 0.18.4 → 0.18.5
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/types.d.ts +5 -5
- package/dist/browser/types.d.ts +3 -1
- package/dist/browser/xcss-prop/index.d.ts +3 -3
- package/dist/cjs/create-strict-api/types.d.ts +5 -5
- package/dist/cjs/types.d.ts +3 -1
- package/dist/cjs/xcss-prop/index.d.ts +3 -3
- package/dist/esm/create-strict-api/types.d.ts +5 -5
- package/dist/esm/types.d.ts +3 -1
- package/dist/esm/xcss-prop/index.d.ts +3 -3
- package/package.json +1 -1
- package/src/__tests__/browser.test.tsx +4 -3
- package/src/create-strict-api/__tests__/__fixtures__/strict-api-recursive.ts +6 -0
- package/src/create-strict-api/__tests__/generics.test.tsx +46 -4
- package/src/create-strict-api/types.ts +5 -5
- package/src/types.ts +14 -2
- package/src/xcss-prop/__tests__/xcss-prop.test.tsx +31 -0
- package/src/xcss-prop/index.ts +3 -3
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { StrictCSSProperties,
|
|
1
|
+
import type { StrictCSSProperties, CSSPseudoElements, CSSPseudos, AllCSSPseudoClasses } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* This is the shape of the generic object that `createStrictAPI()` takes.
|
|
4
4
|
* It's deliberately a subset of `AllowedStyles` and does not take at rules
|
|
5
5
|
* and pseudo elements.
|
|
6
6
|
*/
|
|
7
7
|
export type CompiledSchemaShape = StrictCSSProperties & {
|
|
8
|
-
[Q in
|
|
8
|
+
[Q in AllCSSPseudoClasses]?: StrictCSSProperties;
|
|
9
9
|
};
|
|
10
10
|
export type PseudosDeclarations = {
|
|
11
11
|
[Q in CSSPseudos]?: StrictCSSProperties;
|
|
@@ -14,14 +14,14 @@ export type MediaQueries<TMediaQuery extends string> = {
|
|
|
14
14
|
[Q in `@media ${TMediaQuery}`]?: StrictCSSProperties & PseudosDeclarations;
|
|
15
15
|
};
|
|
16
16
|
export type AllowedStyles<TMediaQuery extends string> = StrictCSSProperties & PseudosDeclarations & MediaQueries<TMediaQuery>;
|
|
17
|
-
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends
|
|
17
|
+
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends AllCSSPseudoClasses | ''> = TKey extends keyof TSchema ? TPseudoKey extends keyof TSchema ? TKey extends keyof TSchema[TPseudoKey] ? TSchema[TPseudoKey][TKey] : TSchema[TKey] : TSchema[TKey] : StrictCSSProperties[TKey];
|
|
18
18
|
/**
|
|
19
19
|
* Recursively maps over object properties to resolve them to either a {@link TSchema}
|
|
20
20
|
* value if present, else fallback to its value from {@link StrictCSSProperties}. If
|
|
21
21
|
* the property isn't a known property its value will be resolved to `never`.
|
|
22
22
|
*/
|
|
23
|
-
export type ApplySchema<TObject, TSchema, TPseudoKey extends
|
|
24
|
-
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends
|
|
23
|
+
export type ApplySchema<TObject, TSchema, TPseudoKey extends AllCSSPseudoClasses | '' = ''> = {
|
|
24
|
+
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends AllCSSPseudoClasses ? ApplySchema<TObject[TKey], TSchema, TKey> : TKey extends `@${string}` | CSSPseudoElements ? ApplySchema<TObject[TKey], TSchema> : never;
|
|
25
25
|
};
|
|
26
26
|
export type ApplySchemaMap<TStylesMap, TSchema> = {
|
|
27
27
|
[P in keyof TStylesMap]: ApplySchema<TStylesMap[P], TSchema>;
|
package/dist/browser/types.d.ts
CHANGED
|
@@ -19,8 +19,10 @@ export type CssObject<TProps> = Readonly<{
|
|
|
19
19
|
}>;
|
|
20
20
|
export type CssFunction<TProps = unknown> = CssType<TProps> | BasicTemplateInterpolations | null | boolean | undefined;
|
|
21
21
|
export type CSSPseudoElements = '&::after' | '&::backdrop' | '&::before' | '&::cue' | '&::cue-region' | '&::first-letter' | '&::first-line' | '&::grammar-error' | '&::marker' | '&::placeholder' | '&::selection' | '&::spelling-error' | '&::target-text' | '&::view-transition';
|
|
22
|
+
export type FlattenedChainedCSSPseudosClasses = '&:visited:active' | '&:visited:hover' | '&:active:visited' | '&:hover::before' | '&:hover::after' | '&:focus-visible::before' | '&:focus-visible::after' | '&:focus:not(:focus-visible)';
|
|
22
23
|
export type CSSPseudoClasses = '&:active' | '&:autofill' | '&:blank' | '&:checked' | '&:default' | '&:defined' | '&:disabled' | '&:empty' | '&:enabled' | '&:first' | '&:focus' | '&:focus-visible' | '&:focus-within' | '&:fullscreen' | '&:hover' | '&:in-range' | '&:indeterminate' | '&:invalid' | '&:left' | '&:link' | '&:local-link' | '&:optional' | '&:out-of-range' | '&:paused' | '&:picture-in-picture' | '&:placeholder-shown' | '&:playing' | '&:read-only' | '&:read-write' | '&:required' | '&:right' | '&:target' | '&:user-invalid' | '&:user-valid' | '&:valid' | '&:visited';
|
|
23
|
-
export type
|
|
24
|
+
export type AllCSSPseudoClasses = CSSPseudoClasses | FlattenedChainedCSSPseudosClasses;
|
|
25
|
+
export type CSSPseudos = CSSPseudoElements | AllCSSPseudoClasses;
|
|
24
26
|
/**
|
|
25
27
|
* The XCSSProp must be given all known available properties even
|
|
26
28
|
* if it takes a subset of them. This ensures the (lack-of an)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type * as CSS from 'csstype';
|
|
2
2
|
import type { ApplySchemaValue } from '../create-strict-api/types';
|
|
3
|
-
import type { CSSPseudos,
|
|
3
|
+
import type { CSSPseudos, CSSProperties, StrictCSSProperties, AllCSSPseudoClasses } from '../types';
|
|
4
4
|
type MarkAsRequired<T, K extends keyof T> = T & {
|
|
5
5
|
[P in K]-?: T[P];
|
|
6
6
|
};
|
|
7
|
-
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends
|
|
7
|
+
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends AllCSSPseudoClasses | ''> = {
|
|
8
8
|
[Q in keyof StrictCSSProperties]: Q extends TStyleDecl ? ApplySchemaValue<TSchema, Q, TPseudoKey> : never;
|
|
9
9
|
};
|
|
10
10
|
type XCSSPseudo<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TRequiredProperties extends {
|
|
11
11
|
requiredProperties: TAllowedProperties;
|
|
12
12
|
}, TSchema> = {
|
|
13
|
-
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends
|
|
13
|
+
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends AllCSSPseudoClasses ? Q : ''>, TRequiredProperties['requiredProperties']> : never;
|
|
14
14
|
};
|
|
15
15
|
type XCSSMediaQuery<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TAllowedMediaQueries extends string, TSchema> = {
|
|
16
16
|
[Q in `@media ${TAllowedMediaQueries}`]?: XCSSValue<TAllowedProperties, TSchema, ''> | XCSSPseudo<TAllowedProperties, TAllowedPseudos, never, TSchema>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { StrictCSSProperties,
|
|
1
|
+
import type { StrictCSSProperties, CSSPseudoElements, CSSPseudos, AllCSSPseudoClasses } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* This is the shape of the generic object that `createStrictAPI()` takes.
|
|
4
4
|
* It's deliberately a subset of `AllowedStyles` and does not take at rules
|
|
5
5
|
* and pseudo elements.
|
|
6
6
|
*/
|
|
7
7
|
export type CompiledSchemaShape = StrictCSSProperties & {
|
|
8
|
-
[Q in
|
|
8
|
+
[Q in AllCSSPseudoClasses]?: StrictCSSProperties;
|
|
9
9
|
};
|
|
10
10
|
export type PseudosDeclarations = {
|
|
11
11
|
[Q in CSSPseudos]?: StrictCSSProperties;
|
|
@@ -14,14 +14,14 @@ export type MediaQueries<TMediaQuery extends string> = {
|
|
|
14
14
|
[Q in `@media ${TMediaQuery}`]?: StrictCSSProperties & PseudosDeclarations;
|
|
15
15
|
};
|
|
16
16
|
export type AllowedStyles<TMediaQuery extends string> = StrictCSSProperties & PseudosDeclarations & MediaQueries<TMediaQuery>;
|
|
17
|
-
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends
|
|
17
|
+
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends AllCSSPseudoClasses | ''> = TKey extends keyof TSchema ? TPseudoKey extends keyof TSchema ? TKey extends keyof TSchema[TPseudoKey] ? TSchema[TPseudoKey][TKey] : TSchema[TKey] : TSchema[TKey] : StrictCSSProperties[TKey];
|
|
18
18
|
/**
|
|
19
19
|
* Recursively maps over object properties to resolve them to either a {@link TSchema}
|
|
20
20
|
* value if present, else fallback to its value from {@link StrictCSSProperties}. If
|
|
21
21
|
* the property isn't a known property its value will be resolved to `never`.
|
|
22
22
|
*/
|
|
23
|
-
export type ApplySchema<TObject, TSchema, TPseudoKey extends
|
|
24
|
-
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends
|
|
23
|
+
export type ApplySchema<TObject, TSchema, TPseudoKey extends AllCSSPseudoClasses | '' = ''> = {
|
|
24
|
+
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends AllCSSPseudoClasses ? ApplySchema<TObject[TKey], TSchema, TKey> : TKey extends `@${string}` | CSSPseudoElements ? ApplySchema<TObject[TKey], TSchema> : never;
|
|
25
25
|
};
|
|
26
26
|
export type ApplySchemaMap<TStylesMap, TSchema> = {
|
|
27
27
|
[P in keyof TStylesMap]: ApplySchema<TStylesMap[P], TSchema>;
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -19,8 +19,10 @@ export type CssObject<TProps> = Readonly<{
|
|
|
19
19
|
}>;
|
|
20
20
|
export type CssFunction<TProps = unknown> = CssType<TProps> | BasicTemplateInterpolations | null | boolean | undefined;
|
|
21
21
|
export type CSSPseudoElements = '&::after' | '&::backdrop' | '&::before' | '&::cue' | '&::cue-region' | '&::first-letter' | '&::first-line' | '&::grammar-error' | '&::marker' | '&::placeholder' | '&::selection' | '&::spelling-error' | '&::target-text' | '&::view-transition';
|
|
22
|
+
export type FlattenedChainedCSSPseudosClasses = '&:visited:active' | '&:visited:hover' | '&:active:visited' | '&:hover::before' | '&:hover::after' | '&:focus-visible::before' | '&:focus-visible::after' | '&:focus:not(:focus-visible)';
|
|
22
23
|
export type CSSPseudoClasses = '&:active' | '&:autofill' | '&:blank' | '&:checked' | '&:default' | '&:defined' | '&:disabled' | '&:empty' | '&:enabled' | '&:first' | '&:focus' | '&:focus-visible' | '&:focus-within' | '&:fullscreen' | '&:hover' | '&:in-range' | '&:indeterminate' | '&:invalid' | '&:left' | '&:link' | '&:local-link' | '&:optional' | '&:out-of-range' | '&:paused' | '&:picture-in-picture' | '&:placeholder-shown' | '&:playing' | '&:read-only' | '&:read-write' | '&:required' | '&:right' | '&:target' | '&:user-invalid' | '&:user-valid' | '&:valid' | '&:visited';
|
|
23
|
-
export type
|
|
24
|
+
export type AllCSSPseudoClasses = CSSPseudoClasses | FlattenedChainedCSSPseudosClasses;
|
|
25
|
+
export type CSSPseudos = CSSPseudoElements | AllCSSPseudoClasses;
|
|
24
26
|
/**
|
|
25
27
|
* The XCSSProp must be given all known available properties even
|
|
26
28
|
* if it takes a subset of them. This ensures the (lack-of an)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type * as CSS from 'csstype';
|
|
2
2
|
import type { ApplySchemaValue } from '../create-strict-api/types';
|
|
3
|
-
import type { CSSPseudos,
|
|
3
|
+
import type { CSSPseudos, CSSProperties, StrictCSSProperties, AllCSSPseudoClasses } from '../types';
|
|
4
4
|
type MarkAsRequired<T, K extends keyof T> = T & {
|
|
5
5
|
[P in K]-?: T[P];
|
|
6
6
|
};
|
|
7
|
-
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends
|
|
7
|
+
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends AllCSSPseudoClasses | ''> = {
|
|
8
8
|
[Q in keyof StrictCSSProperties]: Q extends TStyleDecl ? ApplySchemaValue<TSchema, Q, TPseudoKey> : never;
|
|
9
9
|
};
|
|
10
10
|
type XCSSPseudo<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TRequiredProperties extends {
|
|
11
11
|
requiredProperties: TAllowedProperties;
|
|
12
12
|
}, TSchema> = {
|
|
13
|
-
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends
|
|
13
|
+
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends AllCSSPseudoClasses ? Q : ''>, TRequiredProperties['requiredProperties']> : never;
|
|
14
14
|
};
|
|
15
15
|
type XCSSMediaQuery<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TAllowedMediaQueries extends string, TSchema> = {
|
|
16
16
|
[Q in `@media ${TAllowedMediaQueries}`]?: XCSSValue<TAllowedProperties, TSchema, ''> | XCSSPseudo<TAllowedProperties, TAllowedPseudos, never, TSchema>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { StrictCSSProperties,
|
|
1
|
+
import type { StrictCSSProperties, CSSPseudoElements, CSSPseudos, AllCSSPseudoClasses } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* This is the shape of the generic object that `createStrictAPI()` takes.
|
|
4
4
|
* It's deliberately a subset of `AllowedStyles` and does not take at rules
|
|
5
5
|
* and pseudo elements.
|
|
6
6
|
*/
|
|
7
7
|
export type CompiledSchemaShape = StrictCSSProperties & {
|
|
8
|
-
[Q in
|
|
8
|
+
[Q in AllCSSPseudoClasses]?: StrictCSSProperties;
|
|
9
9
|
};
|
|
10
10
|
export type PseudosDeclarations = {
|
|
11
11
|
[Q in CSSPseudos]?: StrictCSSProperties;
|
|
@@ -14,14 +14,14 @@ export type MediaQueries<TMediaQuery extends string> = {
|
|
|
14
14
|
[Q in `@media ${TMediaQuery}`]?: StrictCSSProperties & PseudosDeclarations;
|
|
15
15
|
};
|
|
16
16
|
export type AllowedStyles<TMediaQuery extends string> = StrictCSSProperties & PseudosDeclarations & MediaQueries<TMediaQuery>;
|
|
17
|
-
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends
|
|
17
|
+
export type ApplySchemaValue<TSchema, TKey extends keyof StrictCSSProperties, TPseudoKey extends AllCSSPseudoClasses | ''> = TKey extends keyof TSchema ? TPseudoKey extends keyof TSchema ? TKey extends keyof TSchema[TPseudoKey] ? TSchema[TPseudoKey][TKey] : TSchema[TKey] : TSchema[TKey] : StrictCSSProperties[TKey];
|
|
18
18
|
/**
|
|
19
19
|
* Recursively maps over object properties to resolve them to either a {@link TSchema}
|
|
20
20
|
* value if present, else fallback to its value from {@link StrictCSSProperties}. If
|
|
21
21
|
* the property isn't a known property its value will be resolved to `never`.
|
|
22
22
|
*/
|
|
23
|
-
export type ApplySchema<TObject, TSchema, TPseudoKey extends
|
|
24
|
-
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends
|
|
23
|
+
export type ApplySchema<TObject, TSchema, TPseudoKey extends AllCSSPseudoClasses | '' = ''> = {
|
|
24
|
+
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties ? ApplySchemaValue<TSchema, TKey, TPseudoKey> : TKey extends AllCSSPseudoClasses ? ApplySchema<TObject[TKey], TSchema, TKey> : TKey extends `@${string}` | CSSPseudoElements ? ApplySchema<TObject[TKey], TSchema> : never;
|
|
25
25
|
};
|
|
26
26
|
export type ApplySchemaMap<TStylesMap, TSchema> = {
|
|
27
27
|
[P in keyof TStylesMap]: ApplySchema<TStylesMap[P], TSchema>;
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -19,8 +19,10 @@ export type CssObject<TProps> = Readonly<{
|
|
|
19
19
|
}>;
|
|
20
20
|
export type CssFunction<TProps = unknown> = CssType<TProps> | BasicTemplateInterpolations | null | boolean | undefined;
|
|
21
21
|
export type CSSPseudoElements = '&::after' | '&::backdrop' | '&::before' | '&::cue' | '&::cue-region' | '&::first-letter' | '&::first-line' | '&::grammar-error' | '&::marker' | '&::placeholder' | '&::selection' | '&::spelling-error' | '&::target-text' | '&::view-transition';
|
|
22
|
+
export type FlattenedChainedCSSPseudosClasses = '&:visited:active' | '&:visited:hover' | '&:active:visited' | '&:hover::before' | '&:hover::after' | '&:focus-visible::before' | '&:focus-visible::after' | '&:focus:not(:focus-visible)';
|
|
22
23
|
export type CSSPseudoClasses = '&:active' | '&:autofill' | '&:blank' | '&:checked' | '&:default' | '&:defined' | '&:disabled' | '&:empty' | '&:enabled' | '&:first' | '&:focus' | '&:focus-visible' | '&:focus-within' | '&:fullscreen' | '&:hover' | '&:in-range' | '&:indeterminate' | '&:invalid' | '&:left' | '&:link' | '&:local-link' | '&:optional' | '&:out-of-range' | '&:paused' | '&:picture-in-picture' | '&:placeholder-shown' | '&:playing' | '&:read-only' | '&:read-write' | '&:required' | '&:right' | '&:target' | '&:user-invalid' | '&:user-valid' | '&:valid' | '&:visited';
|
|
23
|
-
export type
|
|
24
|
+
export type AllCSSPseudoClasses = CSSPseudoClasses | FlattenedChainedCSSPseudosClasses;
|
|
25
|
+
export type CSSPseudos = CSSPseudoElements | AllCSSPseudoClasses;
|
|
24
26
|
/**
|
|
25
27
|
* The XCSSProp must be given all known available properties even
|
|
26
28
|
* if it takes a subset of them. This ensures the (lack-of an)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type * as CSS from 'csstype';
|
|
2
2
|
import type { ApplySchemaValue } from '../create-strict-api/types';
|
|
3
|
-
import type { CSSPseudos,
|
|
3
|
+
import type { CSSPseudos, CSSProperties, StrictCSSProperties, AllCSSPseudoClasses } from '../types';
|
|
4
4
|
type MarkAsRequired<T, K extends keyof T> = T & {
|
|
5
5
|
[P in K]-?: T[P];
|
|
6
6
|
};
|
|
7
|
-
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends
|
|
7
|
+
type XCSSValue<TStyleDecl extends keyof CSSProperties, TSchema, TPseudoKey extends AllCSSPseudoClasses | ''> = {
|
|
8
8
|
[Q in keyof StrictCSSProperties]: Q extends TStyleDecl ? ApplySchemaValue<TSchema, Q, TPseudoKey> : never;
|
|
9
9
|
};
|
|
10
10
|
type XCSSPseudo<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TRequiredProperties extends {
|
|
11
11
|
requiredProperties: TAllowedProperties;
|
|
12
12
|
}, TSchema> = {
|
|
13
|
-
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends
|
|
13
|
+
[Q in CSSPseudos]?: Q extends TAllowedPseudos ? MarkAsRequired<XCSSValue<TAllowedProperties, TSchema, Q extends AllCSSPseudoClasses ? Q : ''>, TRequiredProperties['requiredProperties']> : never;
|
|
14
14
|
};
|
|
15
15
|
type XCSSMediaQuery<TAllowedProperties extends keyof StrictCSSProperties, TAllowedPseudos extends CSSPseudos, TAllowedMediaQueries extends string, TSchema> = {
|
|
16
16
|
[Q in `@media ${TAllowedMediaQueries}`]?: XCSSValue<TAllowedProperties, TSchema, ''> | XCSSPseudo<TAllowedProperties, TAllowedPseudos, never, TSchema>;
|
package/package.json
CHANGED
|
@@ -94,13 +94,14 @@ describe('browser', () => {
|
|
|
94
94
|
render(<StyledLink href="https://atlassian.design">Atlassian Design System</StyledLink>);
|
|
95
95
|
|
|
96
96
|
expect(document.head.innerHTML.split('</style>').join('</style>\n')).toMatchInlineSnapshot(`
|
|
97
|
-
"<style nonce="k0Mp1lEd">._1e0c1txw{display:flex}._1wyb12am{font-size:50px}._syaz1cnh{color:purple}
|
|
98
|
-
<style nonce="k0Mp1lEd">._ysv75scu:link{color:red}</style>
|
|
97
|
+
"<style nonce="k0Mp1lEd">._1e0c1txw{display:flex}._1wyb12am{font-size:50px}._syaz1cnh{color:purple}</style>
|
|
98
|
+
<style nonce="k0Mp1lEd">._ysv75scu:link{color:red}._ysv71x77:link{color:white}</style>
|
|
99
99
|
<style nonce="k0Mp1lEd">._105332ev:visited{color:pink}</style>
|
|
100
100
|
<style nonce="k0Mp1lEd">._f8pjbf54:focus{color:green}</style>
|
|
101
|
+
<style nonce="k0Mp1lEd">._v0vw1x77:focus-visible{color:white}</style>
|
|
101
102
|
<style nonce="k0Mp1lEd">._30l31gy6:hover{color:yellow}</style>
|
|
102
103
|
<style nonce="k0Mp1lEd">._9h8h13q2:active{color:blue}</style>
|
|
103
|
-
<style nonce="k0Mp1lEd">@media (max-width:800px){._1o8z1gy6:focus{color:yellow}._jbabtwqo:focus-visible
|
|
104
|
+
<style nonce="k0Mp1lEd">@media (max-width:800px){._1o8z1gy6:focus{color:yellow}._jbabtwqo:focus-visible{color:grey}._6146twqo:hover{color:grey}._1cld11x8:active{color:black}}@supports (display:grid){._1df61gy6:focus{color:yellow}._7okp11x8:active{color:black}}</style>
|
|
104
105
|
"
|
|
105
106
|
`);
|
|
106
107
|
});
|
|
@@ -24,9 +24,15 @@ interface PressedProperties {
|
|
|
24
24
|
backgroundColor: BackgroundPressed;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
interface ChainedProperties {
|
|
28
|
+
color: ColorPressed;
|
|
29
|
+
backgroundColor: BackgroundPressed;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
interface CSSPropertiesSchema extends Properties {
|
|
28
33
|
'&:hover': HoveredProperties;
|
|
29
34
|
'&:active': PressedProperties;
|
|
35
|
+
'&:hover::after': ChainedProperties;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
const { css, cssMap, cx, XCSSProp } = createStrictAPI<CSSPropertiesSchema>();
|
|
@@ -9,6 +9,7 @@ describe('createStrictAPI()', () => {
|
|
|
9
9
|
const styles = css({
|
|
10
10
|
'&:hover': {},
|
|
11
11
|
'&:active': {},
|
|
12
|
+
'&:hover::after': {},
|
|
12
13
|
'&::before': {},
|
|
13
14
|
'&::after': {},
|
|
14
15
|
});
|
|
@@ -23,6 +24,7 @@ describe('createStrictAPI()', () => {
|
|
|
23
24
|
nested: {
|
|
24
25
|
'&:hover': {},
|
|
25
26
|
'&:active': {},
|
|
27
|
+
'&:hover::after': {},
|
|
26
28
|
'&::before': {},
|
|
27
29
|
'&::after': {},
|
|
28
30
|
},
|
|
@@ -40,7 +42,7 @@ describe('createStrictAPI()', () => {
|
|
|
40
42
|
xcss: ReturnType<
|
|
41
43
|
typeof XCSSProp<
|
|
42
44
|
'backgroundColor' | 'color',
|
|
43
|
-
'&:hover' | '&:active' | '&::before' | '&::after'
|
|
45
|
+
'&:hover' | '&:active' | '&::before' | '&::after' | '&:hover::after'
|
|
44
46
|
>
|
|
45
47
|
>;
|
|
46
48
|
}) {
|
|
@@ -49,7 +51,13 @@ describe('createStrictAPI()', () => {
|
|
|
49
51
|
|
|
50
52
|
const { getByTestId } = render(
|
|
51
53
|
<Component
|
|
52
|
-
xcss={{
|
|
54
|
+
xcss={{
|
|
55
|
+
'&:hover': {},
|
|
56
|
+
'&:active': {},
|
|
57
|
+
'&::before': {},
|
|
58
|
+
'&::after': {},
|
|
59
|
+
'&:hover::after': {},
|
|
60
|
+
}}
|
|
53
61
|
data-testid="div"
|
|
54
62
|
/>
|
|
55
63
|
);
|
|
@@ -76,6 +84,12 @@ describe('createStrictAPI()', () => {
|
|
|
76
84
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
77
85
|
backgroundColor: '',
|
|
78
86
|
},
|
|
87
|
+
'&:hover::after': {
|
|
88
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
89
|
+
color: '',
|
|
90
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
91
|
+
backgroundColor: '',
|
|
92
|
+
},
|
|
79
93
|
'&::before': {
|
|
80
94
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
81
95
|
color: '',
|
|
@@ -114,6 +128,12 @@ describe('createStrictAPI()', () => {
|
|
|
114
128
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
115
129
|
backgroundColor: '',
|
|
116
130
|
},
|
|
131
|
+
'&:hover::after': {
|
|
132
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
133
|
+
color: '',
|
|
134
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
135
|
+
backgroundColor: '',
|
|
136
|
+
},
|
|
117
137
|
'&::before': {
|
|
118
138
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
119
139
|
color: '',
|
|
@@ -139,7 +159,7 @@ describe('createStrictAPI()', () => {
|
|
|
139
159
|
xcss: ReturnType<
|
|
140
160
|
typeof XCSSProp<
|
|
141
161
|
'backgroundColor' | 'color',
|
|
142
|
-
'&:hover' | '&:active' | '&::before' | '&::after'
|
|
162
|
+
'&:hover' | '&:active' | '&::before' | '&::after' | '&:hover::after'
|
|
143
163
|
>
|
|
144
164
|
>;
|
|
145
165
|
}) {
|
|
@@ -165,6 +185,12 @@ describe('createStrictAPI()', () => {
|
|
|
165
185
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
166
186
|
backgroundColor: 'var(--ds-success)',
|
|
167
187
|
},
|
|
188
|
+
'&:hover::after': {
|
|
189
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
190
|
+
color: 'var(--ds-text)',
|
|
191
|
+
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
192
|
+
backgroundColor: 'var(--ds-success)',
|
|
193
|
+
},
|
|
168
194
|
'&::before': {
|
|
169
195
|
// @ts-expect-error — Type '""' is not assignable to type ...
|
|
170
196
|
color: '',
|
|
@@ -198,6 +224,12 @@ describe('createStrictAPI()', () => {
|
|
|
198
224
|
color: 'var(--ds-text-hovered)',
|
|
199
225
|
backgroundColor: 'var(--ds-bold-hovered)',
|
|
200
226
|
},
|
|
227
|
+
'&:hover::after': {
|
|
228
|
+
// @ts-expect-error — should be a value from the schema
|
|
229
|
+
padding: '10px',
|
|
230
|
+
color: 'var(--ds-text-pressed)',
|
|
231
|
+
backgroundColor: 'var(--ds-bold-pressed)',
|
|
232
|
+
},
|
|
201
233
|
'&:active': {
|
|
202
234
|
// @ts-expect-error — should be a value from the schema
|
|
203
235
|
padding: '10px',
|
|
@@ -243,6 +275,12 @@ describe('createStrictAPI()', () => {
|
|
|
243
275
|
color: 'var(--ds-text-pressed)',
|
|
244
276
|
backgroundColor: 'var(--ds-bold-pressed)',
|
|
245
277
|
},
|
|
278
|
+
'&:hover::after': {
|
|
279
|
+
// @ts-expect-error — should be a value from the schema
|
|
280
|
+
padding: '10px',
|
|
281
|
+
color: 'var(--ds-text-pressed)',
|
|
282
|
+
backgroundColor: 'var(--ds-bold-pressed)',
|
|
283
|
+
},
|
|
246
284
|
'&::before': {
|
|
247
285
|
// @ts-expect-error — should be a value from the schema
|
|
248
286
|
padding: '10px',
|
|
@@ -270,7 +308,7 @@ describe('createStrictAPI()', () => {
|
|
|
270
308
|
xcss: ReturnType<
|
|
271
309
|
typeof XCSSProp<
|
|
272
310
|
'backgroundColor' | 'color',
|
|
273
|
-
'&:hover' | '&:active' | '&::before' | '&::after'
|
|
311
|
+
'&:hover' | '&:active' | '&::before' | '&::after' | '&:hover::after'
|
|
274
312
|
>
|
|
275
313
|
>;
|
|
276
314
|
}) {
|
|
@@ -290,6 +328,10 @@ describe('createStrictAPI()', () => {
|
|
|
290
328
|
color: 'var(--ds-text-pressed)',
|
|
291
329
|
backgroundColor: 'var(--ds-bold-pressed)',
|
|
292
330
|
},
|
|
331
|
+
'&:hover::after': {
|
|
332
|
+
color: 'var(--ds-text-pressed)',
|
|
333
|
+
backgroundColor: 'var(--ds-bold-pressed)',
|
|
334
|
+
},
|
|
293
335
|
'&::before': {
|
|
294
336
|
color: 'var(--ds-text)',
|
|
295
337
|
backgroundColor: 'var(--ds-bold)',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
StrictCSSProperties,
|
|
3
|
-
CSSPseudoClasses,
|
|
4
3
|
CSSPseudoElements,
|
|
5
4
|
CSSPseudos,
|
|
5
|
+
AllCSSPseudoClasses,
|
|
6
6
|
} from '../types';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
* and pseudo elements.
|
|
12
12
|
*/
|
|
13
13
|
export type CompiledSchemaShape = StrictCSSProperties & {
|
|
14
|
-
[Q in
|
|
14
|
+
[Q in AllCSSPseudoClasses]?: StrictCSSProperties;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export type PseudosDeclarations = { [Q in CSSPseudos]?: StrictCSSProperties };
|
|
@@ -27,7 +27,7 @@ export type AllowedStyles<TMediaQuery extends string> = StrictCSSProperties &
|
|
|
27
27
|
export type ApplySchemaValue<
|
|
28
28
|
TSchema,
|
|
29
29
|
TKey extends keyof StrictCSSProperties,
|
|
30
|
-
TPseudoKey extends
|
|
30
|
+
TPseudoKey extends AllCSSPseudoClasses | ''
|
|
31
31
|
> = TKey extends keyof TSchema
|
|
32
32
|
? // TKey is a valid property on the schema
|
|
33
33
|
TPseudoKey extends keyof TSchema
|
|
@@ -46,11 +46,11 @@ export type ApplySchemaValue<
|
|
|
46
46
|
* value if present, else fallback to its value from {@link StrictCSSProperties}. If
|
|
47
47
|
* the property isn't a known property its value will be resolved to `never`.
|
|
48
48
|
*/
|
|
49
|
-
export type ApplySchema<TObject, TSchema, TPseudoKey extends
|
|
49
|
+
export type ApplySchema<TObject, TSchema, TPseudoKey extends AllCSSPseudoClasses | '' = ''> = {
|
|
50
50
|
[TKey in keyof TObject]?: TKey extends keyof StrictCSSProperties
|
|
51
51
|
? // TKey is a valid CSS property, try to resolve its value.
|
|
52
52
|
ApplySchemaValue<TSchema, TKey, TPseudoKey>
|
|
53
|
-
: TKey extends
|
|
53
|
+
: TKey extends AllCSSPseudoClasses
|
|
54
54
|
? // TKey is a valid pseudo class, recursively resolve its child properties
|
|
55
55
|
// while passing down the parent pseudo key to resolve any specific schema types.
|
|
56
56
|
ApplySchema<TObject[TKey], TSchema, TKey>
|
package/src/types.ts
CHANGED
|
@@ -51,6 +51,16 @@ export type CSSPseudoElements =
|
|
|
51
51
|
| '&::target-text'
|
|
52
52
|
| '&::view-transition';
|
|
53
53
|
|
|
54
|
+
export type FlattenedChainedCSSPseudosClasses =
|
|
55
|
+
| '&:visited:active'
|
|
56
|
+
| '&:visited:hover'
|
|
57
|
+
| '&:active:visited'
|
|
58
|
+
| '&:hover::before'
|
|
59
|
+
| '&:hover::after'
|
|
60
|
+
| '&:focus-visible::before'
|
|
61
|
+
| '&:focus-visible::after'
|
|
62
|
+
| '&:focus:not(:focus-visible)';
|
|
63
|
+
|
|
54
64
|
export type CSSPseudoClasses =
|
|
55
65
|
| '&:active'
|
|
56
66
|
| '&:autofill'
|
|
@@ -89,14 +99,16 @@ export type CSSPseudoClasses =
|
|
|
89
99
|
| '&:valid'
|
|
90
100
|
| '&:visited';
|
|
91
101
|
|
|
102
|
+
export type AllCSSPseudoClasses = CSSPseudoClasses | FlattenedChainedCSSPseudosClasses;
|
|
103
|
+
|
|
92
104
|
/*
|
|
93
|
-
* This list of pseudo-classes and pseudo-elements are from csstype
|
|
105
|
+
* This list of pseudo-classes, chained pseudo-classes, and pseudo-elements are from csstype
|
|
94
106
|
* but with & added to the front. Compiled supports both &-ful
|
|
95
107
|
* and &-less forms and both will target the current element
|
|
96
108
|
* (`&:hover` <==> `:hover`), however we force the use of the
|
|
97
109
|
* &-ful form for consistency with the nested spec for new APIs.
|
|
98
110
|
*/
|
|
99
|
-
export type CSSPseudos = CSSPseudoElements |
|
|
111
|
+
export type CSSPseudos = CSSPseudoElements | AllCSSPseudoClasses;
|
|
100
112
|
|
|
101
113
|
/**
|
|
102
114
|
* The XCSSProp must be given all known available properties even
|
|
@@ -260,4 +260,35 @@ describe('xcss prop', () => {
|
|
|
260
260
|
/>
|
|
261
261
|
).toBeObject();
|
|
262
262
|
});
|
|
263
|
+
|
|
264
|
+
it('should allow chained pseudo elements', () => {
|
|
265
|
+
function CSSPropComponent({ xcss }: { xcss: XCSSProp<XCSSAllProperties, '&:hover::after'> }) {
|
|
266
|
+
return <div className={xcss}>foo</div>;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const styles = cssMap({
|
|
270
|
+
redColor: { color: 'red', '&:hover::after': { backgroundColor: 'green' } },
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const { getByText } = render(<CSSPropComponent xcss={styles.redColor} />);
|
|
274
|
+
|
|
275
|
+
expect(getByText('foo')).toHaveCompiledCss('color', 'red');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should type error when given a chained pseudo element and none are allowed', () => {
|
|
279
|
+
function CSSPropComponent({ xcss }: { xcss: XCSSProp<XCSSAllProperties, '&:hover'> }) {
|
|
280
|
+
return <div className={xcss}>foo</div>;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const styles = cssMap({
|
|
284
|
+
redColor: { color: 'red', '&:hover::after': { backgroundColor: 'green' } },
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
expectTypeOf(
|
|
288
|
+
<CSSPropComponent
|
|
289
|
+
// @ts-expect-error — Types of property '"&:hover::after"' are incompatible.
|
|
290
|
+
xcss={styles.redColor}
|
|
291
|
+
/>
|
|
292
|
+
).toBeObject();
|
|
293
|
+
});
|
|
263
294
|
});
|
package/src/xcss-prop/index.ts
CHANGED
|
@@ -2,14 +2,14 @@ import type * as CSS from 'csstype';
|
|
|
2
2
|
|
|
3
3
|
import type { ApplySchemaValue } from '../create-strict-api/types';
|
|
4
4
|
import { ax } from '../runtime';
|
|
5
|
-
import type { CSSPseudos,
|
|
5
|
+
import type { CSSPseudos, CSSProperties, StrictCSSProperties, AllCSSPseudoClasses } from '../types';
|
|
6
6
|
|
|
7
7
|
type MarkAsRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
|
8
8
|
|
|
9
9
|
type XCSSValue<
|
|
10
10
|
TStyleDecl extends keyof CSSProperties,
|
|
11
11
|
TSchema,
|
|
12
|
-
TPseudoKey extends
|
|
12
|
+
TPseudoKey extends AllCSSPseudoClasses | ''
|
|
13
13
|
> = {
|
|
14
14
|
[Q in keyof StrictCSSProperties]: Q extends TStyleDecl
|
|
15
15
|
? ApplySchemaValue<TSchema, Q, TPseudoKey>
|
|
@@ -24,7 +24,7 @@ type XCSSPseudo<
|
|
|
24
24
|
> = {
|
|
25
25
|
[Q in CSSPseudos]?: Q extends TAllowedPseudos
|
|
26
26
|
? MarkAsRequired<
|
|
27
|
-
XCSSValue<TAllowedProperties, TSchema, Q extends
|
|
27
|
+
XCSSValue<TAllowedProperties, TSchema, Q extends AllCSSPseudoClasses ? Q : ''>,
|
|
28
28
|
TRequiredProperties['requiredProperties']
|
|
29
29
|
>
|
|
30
30
|
: never;
|