@slimr/styled 2.0.3 → 2.0.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/README.md +5 -5
- package/{src → cjs}/core.d.ts +6 -8
- package/cjs/core.js +159 -0
- package/cjs/core.js.map +1 -0
- package/cjs/core.ts +229 -0
- package/cjs/index.d.ts +186 -0
- package/cjs/index.js +205 -0
- package/cjs/index.js.map +1 -0
- package/cjs/index.ts +200 -0
- package/esm/core.d.ts +53 -0
- package/esm/core.js +155 -0
- package/esm/core.js.map +1 -0
- package/esm/core.ts +229 -0
- package/esm/index.d.ts +186 -0
- package/esm/index.js +188 -0
- package/esm/index.js.map +1 -0
- package/esm/index.ts +200 -0
- package/package.json +12 -22
- package/src/core.cjs +0 -35
- package/src/core.cjs.map +0 -1
- package/src/core.js +0 -35
- package/src/core.js.map +0 -1
- package/src/index.cjs +0 -35
- package/src/index.cjs.map +0 -1
- package/src/index.d.ts +0 -189
- package/src/index.js +0 -35
- package/src/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -109,9 +109,9 @@ export function App() {
|
|
|
109
109
|
}
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
## Comparisons
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
### [Chakra-UI](https://chakra-ui.com/)
|
|
115
115
|
|
|
116
116
|
- A popular css-in-js lib that inspired this lib
|
|
117
117
|
|
|
@@ -124,7 +124,7 @@ Cons
|
|
|
124
124
|
|
|
125
125
|
- Is crazy large bundle impact (80+kb)
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
### [Styled-Components](https://github.com/styled-components/styled-components)
|
|
128
128
|
|
|
129
129
|
- A popular css-in-js lib that inspired this lib
|
|
130
130
|
|
|
@@ -137,7 +137,7 @@ Cons
|
|
|
137
137
|
- Is massive (~12kb), plus has dependency on emotion (~11kb)
|
|
138
138
|
- Does not support zx prop or css shorthand props
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
### [Emotion](https://emotion.sh/docs/introduction)
|
|
141
141
|
|
|
142
142
|
- A popular css-in-js lib similar to styled-components
|
|
143
143
|
|
|
@@ -151,7 +151,7 @@ Cons
|
|
|
151
151
|
- Many features require addons, which make bundle even larger
|
|
152
152
|
- Does not support zx prop or css shorthand props
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
### [Goober](https://github.com/cristianbote/goober)
|
|
155
155
|
|
|
156
156
|
- another tiny 1kb styled-components like css-in-js
|
|
157
157
|
|
package/{src → cjs}/core.d.ts
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { ShorthandProps } from '@slimr/css';
|
|
2
|
-
import { CSSProperties,
|
|
3
|
-
|
|
2
|
+
import { CSSProperties, FC, HTMLAttributes } from 'react';
|
|
4
3
|
type allowableAny = any;
|
|
5
4
|
/** A type that represents all the css properties + shorthand props */
|
|
6
|
-
interface ZxProps extends CSSProperties, ShorthandProps {
|
|
5
|
+
export interface ZxProps extends CSSProperties, ShorthandProps {
|
|
7
6
|
}
|
|
8
7
|
type ZxP = ZxProps;
|
|
9
8
|
type Zx = {
|
|
@@ -12,7 +11,7 @@ type Zx = {
|
|
|
12
11
|
type _Props = {
|
|
13
12
|
[k in keyof Zx as `_${k}`]?: Zx[k];
|
|
14
13
|
};
|
|
15
|
-
interface SCProps extends _Props {
|
|
14
|
+
export interface SCProps extends _Props {
|
|
16
15
|
/** Like zx prop, but applies only on :active */
|
|
17
16
|
_active?: Zx;
|
|
18
17
|
className?: string;
|
|
@@ -42,7 +41,7 @@ interface SCProps extends _Props {
|
|
|
42
41
|
_zx?: Zx;
|
|
43
42
|
}
|
|
44
43
|
/** Styled Component: Like FunctionalComponent but adds SCProps */
|
|
45
|
-
type SC<T extends {
|
|
44
|
+
export type SC<T extends {
|
|
46
45
|
className?: HTMLAttributes<allowableAny>['className'];
|
|
47
46
|
}> = FC<T & SCProps>;
|
|
48
47
|
/**
|
|
@@ -50,6 +49,5 @@ type SC<T extends {
|
|
|
50
49
|
* @param function - a functional component to be styled; must accept a className prop
|
|
51
50
|
* @returns a function that accepts a template string of css returns a decorated functional component
|
|
52
51
|
*/
|
|
53
|
-
declare function styledBase<C extends FC<allowableAny>>(Component: C): (strings: string | TemplateStringsArray, ...placeHolders: string[]) => SC<Parameters<C>[0]>;
|
|
54
|
-
|
|
55
|
-
export { SC, SCProps, ZxProps, styledBase };
|
|
52
|
+
export declare function styledBase<C extends FC<allowableAny>>(Component: C): (strings: string | TemplateStringsArray, ...placeHolders: string[]) => SC<Parameters<C>[0]>;
|
|
53
|
+
export {};
|
package/cjs/core.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.styledBase = void 0;
|
|
4
|
+
/* eslint-disable prefer-const */
|
|
5
|
+
const css_1 = require("@slimr/css");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
/** Converts a string to kebab case */
|
|
8
|
+
function toKebabCase(str) {
|
|
9
|
+
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
/** Converts a string to camel case */
|
|
12
|
+
function toCamelCase(str) {
|
|
13
|
+
return str.replace(/-./g, x => x[1].toUpperCase());
|
|
14
|
+
}
|
|
15
|
+
/** Expands the shorthand props of a zx prop into css full */
|
|
16
|
+
function expandShorthandProps(zx) {
|
|
17
|
+
return Object.entries(zx).reduce((acc, [k, v]) => {
|
|
18
|
+
if (k === 'mx') {
|
|
19
|
+
acc.marginLeft = v;
|
|
20
|
+
acc.marginRight = v;
|
|
21
|
+
}
|
|
22
|
+
else if (k === 'my') {
|
|
23
|
+
acc.marginTop = v;
|
|
24
|
+
acc.marginBottom = v;
|
|
25
|
+
}
|
|
26
|
+
else if (k === 'px') {
|
|
27
|
+
acc.paddingLeft = v;
|
|
28
|
+
acc.paddingRight = v;
|
|
29
|
+
}
|
|
30
|
+
else if (k === 'py') {
|
|
31
|
+
acc.paddingTop = v;
|
|
32
|
+
acc.paddingBottom = v;
|
|
33
|
+
}
|
|
34
|
+
else if (k in css_1.shorthandPropsMap) {
|
|
35
|
+
acc[toCamelCase(css_1.shorthandPropsMap[k])] = v;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
acc[k] = v;
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, {});
|
|
42
|
+
}
|
|
43
|
+
/** Converts a zx prop into css string */
|
|
44
|
+
function zxToCss(zx) {
|
|
45
|
+
return Object.entries(zx)
|
|
46
|
+
.map(([k, v]) => {
|
|
47
|
+
if (!v)
|
|
48
|
+
return '';
|
|
49
|
+
k = toKebabCase(k);
|
|
50
|
+
if (typeof v === 'number')
|
|
51
|
+
v = v + 'px';
|
|
52
|
+
if (Array.isArray(v)) {
|
|
53
|
+
// @ts-expect-error - TS gets confused by the complexity
|
|
54
|
+
v = '[' + v.map(v => (typeof v === 'number' ? v + 'px' : v)).join(',') + ']';
|
|
55
|
+
}
|
|
56
|
+
return k + ':' + v + ';';
|
|
57
|
+
})
|
|
58
|
+
.join('\n');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A lightweight alternative to styled-components
|
|
62
|
+
* @param function - a functional component to be styled; must accept a className prop
|
|
63
|
+
* @returns a function that accepts a template string of css returns a decorated functional component
|
|
64
|
+
*/
|
|
65
|
+
function styledBase(Component) {
|
|
66
|
+
return (...cssProps) => {
|
|
67
|
+
const className = (0, css_1.css)(...cssProps);
|
|
68
|
+
/**
|
|
69
|
+
* A functional component that accepts Styled Props
|
|
70
|
+
*/
|
|
71
|
+
const CStyled = (0, react_1.forwardRef)(function CStyled(props, ref) {
|
|
72
|
+
let { _active, _css, _dark, _focus, _focusVisible, _focusWithin, _hover, _target, _visited, _zx = {}, ...rest } = props;
|
|
73
|
+
// Pluck out $ prefixed props
|
|
74
|
+
Object.entries(props).forEach(([k, v]) => {
|
|
75
|
+
if (k.startsWith('_')) {
|
|
76
|
+
// @ts-expect-error - We know the key exists but ts doesn't
|
|
77
|
+
_zx[k.slice(1)] = v;
|
|
78
|
+
// @ts-expect-error - We know the key exists but ts doesn't
|
|
79
|
+
delete rest[k];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
let cssStr = '';
|
|
83
|
+
if (_active) {
|
|
84
|
+
cssStr += `
|
|
85
|
+
&:active {
|
|
86
|
+
${zxToCss(_active)}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
if (_dark) {
|
|
91
|
+
cssStr += `
|
|
92
|
+
@media (prefers-color-scheme: dark) {
|
|
93
|
+
${zxToCss(_dark)}
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
if (_focus) {
|
|
98
|
+
cssStr += `
|
|
99
|
+
&:focus {
|
|
100
|
+
${zxToCss(_focus)}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
if (_focusVisible) {
|
|
105
|
+
cssStr += `
|
|
106
|
+
&:focus-visible {
|
|
107
|
+
${zxToCss(_focusVisible)}
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
if (_focusWithin) {
|
|
112
|
+
cssStr += `
|
|
113
|
+
&:focus-within {
|
|
114
|
+
${zxToCss(_focusWithin)}
|
|
115
|
+
}
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
if (_hover) {
|
|
119
|
+
cssStr += `
|
|
120
|
+
&:hover {
|
|
121
|
+
${zxToCss(_hover)}
|
|
122
|
+
}
|
|
123
|
+
`;
|
|
124
|
+
}
|
|
125
|
+
if (_target) {
|
|
126
|
+
cssStr += `
|
|
127
|
+
&:target {
|
|
128
|
+
${zxToCss(_target)}
|
|
129
|
+
}
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
if (_visited) {
|
|
133
|
+
cssStr += `
|
|
134
|
+
&:visited {
|
|
135
|
+
${zxToCss(_visited)}
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
const hasMediaQuery = Object.values(_zx).some(v => Array.isArray(v));
|
|
140
|
+
// If has media query styles, use css class. Otherwise favor inline styles
|
|
141
|
+
if (hasMediaQuery || cssStr) {
|
|
142
|
+
cssStr = zxToCss(_zx) + cssStr;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
_zx = expandShorthandProps(_zx);
|
|
146
|
+
rest.style = { ...rest.style, ..._zx };
|
|
147
|
+
}
|
|
148
|
+
return (0, react_1.createElement)(Component, {
|
|
149
|
+
ref,
|
|
150
|
+
...rest,
|
|
151
|
+
className: (0, css_1.classJoin)(className, _css ? (_css.includes(':') ? (0, css_1.css)(_css) : _css) : undefined, cssStr ? (0, css_1.css)(cssStr) : undefined, props.className),
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
CStyled.toString = () => '.' + className;
|
|
155
|
+
return CStyled;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
exports.styledBase = styledBase;
|
|
159
|
+
//# sourceMappingURL=core.js.map
|
package/cjs/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/cjs/core.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/* eslint-disable prefer-const */
|
|
2
|
+
import {ShorthandProps, TemplateStringProps, classJoin, css, shorthandPropsMap} from '@slimr/css'
|
|
3
|
+
|
|
4
|
+
import {CSSProperties, FC, HTMLAttributes, createElement, forwardRef} from 'react'
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
type allowableAny = any
|
|
8
|
+
|
|
9
|
+
/** A type that represents all the css properties + shorthand props */
|
|
10
|
+
export interface ZxProps extends CSSProperties, ShorthandProps {}
|
|
11
|
+
type ZxP = ZxProps
|
|
12
|
+
|
|
13
|
+
type Zx = {
|
|
14
|
+
[k in keyof ZxP]:
|
|
15
|
+
| ZxP[k]
|
|
16
|
+
| [ZxP[k] | null, ZxP[k]]
|
|
17
|
+
| [ZxP[k] | null, ZxP[k] | null, ZxP[k]]
|
|
18
|
+
| [ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]]
|
|
19
|
+
| [ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]]
|
|
20
|
+
| [ZxP[k], ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]]
|
|
21
|
+
| [ZxP[k], ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type _Props = {
|
|
25
|
+
[k in keyof Zx as `_${k}`]?: Zx[k]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SCProps extends _Props {
|
|
29
|
+
/** Like zx prop, but applies only on :active */
|
|
30
|
+
_active?: Zx
|
|
31
|
+
className?: string
|
|
32
|
+
/** A string of css or classname to be added to the component */
|
|
33
|
+
_css?: string
|
|
34
|
+
/** Like zx prop, but applies only when user prefers dark theme */
|
|
35
|
+
_dark?: Zx
|
|
36
|
+
/** Like zx prop, but applies only on :focus */
|
|
37
|
+
_focus?: Zx
|
|
38
|
+
/** Like zx prop, but applies only on :focus-visible */
|
|
39
|
+
_focusVisible?: Zx
|
|
40
|
+
/** Like zx prop, but applies only on :focus-within */
|
|
41
|
+
_focusWithin?: Zx
|
|
42
|
+
/** Like zx prop, but applies only on :hover */
|
|
43
|
+
_hover?: Zx
|
|
44
|
+
style?: CSSProperties
|
|
45
|
+
/** Like zx prop, but applies only on :target */
|
|
46
|
+
_target?: Zx
|
|
47
|
+
/** Like zx prop, but applies only on :visited */
|
|
48
|
+
_visited?: Zx
|
|
49
|
+
/**
|
|
50
|
+
* Like style prop, but enhanced with features like chakra
|
|
51
|
+
* - Array values are converted to media query breakpoints
|
|
52
|
+
* - Numbers are converted to px
|
|
53
|
+
* - Shorthand props are supported
|
|
54
|
+
*/
|
|
55
|
+
_zx?: Zx
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Styled Component: Like FunctionalComponent but adds SCProps */
|
|
59
|
+
export type SC<T extends {className?: HTMLAttributes<allowableAny>['className']}> = FC<T & SCProps>
|
|
60
|
+
|
|
61
|
+
/** Converts a string to kebab case */
|
|
62
|
+
function toKebabCase(str: string) {
|
|
63
|
+
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Converts a string to camel case */
|
|
67
|
+
function toCamelCase(str: string) {
|
|
68
|
+
return str.replace(/-./g, x => x[1].toUpperCase())
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Expands the shorthand props of a zx prop into css full */
|
|
72
|
+
function expandShorthandProps(zx: Zx) {
|
|
73
|
+
return Object.entries(zx).reduce((acc, [k, v]) => {
|
|
74
|
+
if (k === 'mx') {
|
|
75
|
+
acc.marginLeft = v
|
|
76
|
+
acc.marginRight = v
|
|
77
|
+
} else if (k === 'my') {
|
|
78
|
+
acc.marginTop = v
|
|
79
|
+
acc.marginBottom = v
|
|
80
|
+
} else if (k === 'px') {
|
|
81
|
+
acc.paddingLeft = v
|
|
82
|
+
acc.paddingRight = v
|
|
83
|
+
} else if (k === 'py') {
|
|
84
|
+
acc.paddingTop = v
|
|
85
|
+
acc.paddingBottom = v
|
|
86
|
+
} else if (k in shorthandPropsMap) {
|
|
87
|
+
acc[toCamelCase(shorthandPropsMap[k as keyof typeof shorthandPropsMap])] = v
|
|
88
|
+
} else {
|
|
89
|
+
acc[k] = v
|
|
90
|
+
}
|
|
91
|
+
return acc
|
|
92
|
+
}, {} as Record<string, allowableAny>)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Converts a zx prop into css string */
|
|
96
|
+
function zxToCss(zx: Zx): string {
|
|
97
|
+
return Object.entries(zx)
|
|
98
|
+
.map(([k, v]) => {
|
|
99
|
+
if (!v) return ''
|
|
100
|
+
k = toKebabCase(k)
|
|
101
|
+
if (typeof v === 'number') v = v + 'px'
|
|
102
|
+
if (Array.isArray(v)) {
|
|
103
|
+
// @ts-expect-error - TS gets confused by the complexity
|
|
104
|
+
v = '[' + v.map(v => (typeof v === 'number' ? v + 'px' : v)).join(',') + ']'
|
|
105
|
+
}
|
|
106
|
+
return k + ':' + v + ';'
|
|
107
|
+
})
|
|
108
|
+
.join('\n')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* A lightweight alternative to styled-components
|
|
113
|
+
* @param function - a functional component to be styled; must accept a className prop
|
|
114
|
+
* @returns a function that accepts a template string of css returns a decorated functional component
|
|
115
|
+
*/
|
|
116
|
+
export function styledBase<C extends FC<allowableAny>>(Component: C) {
|
|
117
|
+
return (...cssProps: TemplateStringProps) => {
|
|
118
|
+
const className = css(...cssProps)
|
|
119
|
+
/**
|
|
120
|
+
* A functional component that accepts Styled Props
|
|
121
|
+
*/
|
|
122
|
+
const CStyled = forwardRef(function CStyled(props: SCProps, ref) {
|
|
123
|
+
let {
|
|
124
|
+
_active,
|
|
125
|
+
_css,
|
|
126
|
+
_dark,
|
|
127
|
+
_focus,
|
|
128
|
+
_focusVisible,
|
|
129
|
+
_focusWithin,
|
|
130
|
+
_hover,
|
|
131
|
+
_target,
|
|
132
|
+
_visited,
|
|
133
|
+
_zx = {},
|
|
134
|
+
...rest
|
|
135
|
+
} = props
|
|
136
|
+
|
|
137
|
+
// Pluck out $ prefixed props
|
|
138
|
+
Object.entries(props).forEach(([k, v]) => {
|
|
139
|
+
if (k.startsWith('_')) {
|
|
140
|
+
// @ts-expect-error - We know the key exists but ts doesn't
|
|
141
|
+
_zx[k.slice(1)] = v
|
|
142
|
+
// @ts-expect-error - We know the key exists but ts doesn't
|
|
143
|
+
delete rest[k]
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
let cssStr = ''
|
|
148
|
+
|
|
149
|
+
if (_active) {
|
|
150
|
+
cssStr += `
|
|
151
|
+
&:active {
|
|
152
|
+
${zxToCss(_active)}
|
|
153
|
+
}
|
|
154
|
+
`
|
|
155
|
+
}
|
|
156
|
+
if (_dark) {
|
|
157
|
+
cssStr += `
|
|
158
|
+
@media (prefers-color-scheme: dark) {
|
|
159
|
+
${zxToCss(_dark)}
|
|
160
|
+
}
|
|
161
|
+
`
|
|
162
|
+
}
|
|
163
|
+
if (_focus) {
|
|
164
|
+
cssStr += `
|
|
165
|
+
&:focus {
|
|
166
|
+
${zxToCss(_focus)}
|
|
167
|
+
}
|
|
168
|
+
`
|
|
169
|
+
}
|
|
170
|
+
if (_focusVisible) {
|
|
171
|
+
cssStr += `
|
|
172
|
+
&:focus-visible {
|
|
173
|
+
${zxToCss(_focusVisible)}
|
|
174
|
+
}
|
|
175
|
+
`
|
|
176
|
+
}
|
|
177
|
+
if (_focusWithin) {
|
|
178
|
+
cssStr += `
|
|
179
|
+
&:focus-within {
|
|
180
|
+
${zxToCss(_focusWithin)}
|
|
181
|
+
}
|
|
182
|
+
`
|
|
183
|
+
}
|
|
184
|
+
if (_hover) {
|
|
185
|
+
cssStr += `
|
|
186
|
+
&:hover {
|
|
187
|
+
${zxToCss(_hover)}
|
|
188
|
+
}
|
|
189
|
+
`
|
|
190
|
+
}
|
|
191
|
+
if (_target) {
|
|
192
|
+
cssStr += `
|
|
193
|
+
&:target {
|
|
194
|
+
${zxToCss(_target)}
|
|
195
|
+
}
|
|
196
|
+
`
|
|
197
|
+
}
|
|
198
|
+
if (_visited) {
|
|
199
|
+
cssStr += `
|
|
200
|
+
&:visited {
|
|
201
|
+
${zxToCss(_visited)}
|
|
202
|
+
}
|
|
203
|
+
`
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const hasMediaQuery = Object.values(_zx).some(v => Array.isArray(v))
|
|
207
|
+
// If has media query styles, use css class. Otherwise favor inline styles
|
|
208
|
+
if (hasMediaQuery || cssStr) {
|
|
209
|
+
cssStr = zxToCss(_zx) + cssStr
|
|
210
|
+
} else {
|
|
211
|
+
_zx = expandShorthandProps(_zx)
|
|
212
|
+
rest.style = {...rest.style, ..._zx} as CSSProperties
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return createElement(Component, {
|
|
216
|
+
ref,
|
|
217
|
+
...rest,
|
|
218
|
+
className: classJoin(
|
|
219
|
+
className,
|
|
220
|
+
_css ? (_css.includes(':') ? css(_css) : _css) : undefined,
|
|
221
|
+
cssStr ? css(cssStr) : undefined,
|
|
222
|
+
props.className
|
|
223
|
+
),
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
CStyled.toString = () => '.' + className
|
|
227
|
+
return CStyled as unknown as SC<Parameters<C>[0]>
|
|
228
|
+
}
|
|
229
|
+
}
|