@slimr/styled 2.0.3 → 2.0.4

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/cjs/index.ts ADDED
@@ -0,0 +1,200 @@
1
+ import {TemplateStringProps} from '@slimr/css'
2
+
3
+ import {FC} from 'react'
4
+
5
+ import {styledBase as s} from './core.js'
6
+
7
+ export * from '@slimr/css'
8
+ export * from './core.js'
9
+
10
+ /** Shorthand type */
11
+ type unk = unknown
12
+ /** Shorthand type */
13
+ type TSP = TemplateStringProps
14
+ /** Shorthand type */
15
+ type HTP = JSX.IntrinsicElements
16
+
17
+ export const styled = Object.assign(s, {
18
+ /** creates a 'a' component with css applied */
19
+ a: (...p: TSP) => s('a' as unk as FC<HTP['a']>)(...p),
20
+ /** creates a 'abbr' component with css applied */
21
+ abbr: (...p: TSP) => s('abbr' as unk as FC<HTP['abbr']>)(...p),
22
+ /** creates a 'address' component with css applied */
23
+ address: (...p: TSP) => s('address' as unk as FC<HTP['address']>)(...p),
24
+ /** creates a 'area' component with css applied */
25
+ area: (...p: TSP) => s('area' as unk as FC<HTP['area']>)(...p),
26
+ /** creates a 'article' component with css applied */
27
+ article: (...p: TSP) => s('article' as unk as FC<HTP['article']>)(...p),
28
+ /** creates a 'aside' component with css applied */
29
+ aside: (...p: TSP) => s('aside' as unk as FC<HTP['aside']>)(...p),
30
+ /** creates a 'audio' component with css applied */
31
+ audio: (...p: TSP) => s('audio' as unk as FC<HTP['audio']>)(...p),
32
+ /** creates a 'b' component with css applied */
33
+ b: (...p: TSP) => s('b' as unk as FC<HTP['b']>)(...p),
34
+ /** creates a 'big' component with css applied; Deprecated so left out */
35
+ // big: (...p: TSP) => styled('big' as unk as FC<HTP['big']>)(...p),
36
+ /** creates a 'blockquote' component with css applied */
37
+ blockquote: (...p: TSP) => s('blockquote' as unk as FC<HTP['blockquote']>)(...p),
38
+ /** creates a 'body' component with css applied; omitted bc doesnt seem useful */
39
+ // body: (...p: TSP) => styled('body' as unk as FC<HTP['body']>)(...p),
40
+ /** creates a 'br' component with css applied; omitted bc doesnt seem useful */
41
+ br: (...p: TSP) => s('br' as unk as FC<HTP['br']>)(...p),
42
+ /** creates a 'button' component with css applied */
43
+ button: (...p: TSP) => s('button' as unk as FC<HTP['button']>)(...p),
44
+ /** creates a 'caption' component with css applied */
45
+ caption: (...p: TSP) => s('caption' as unk as FC<HTP['caption']>)(...p),
46
+ /** creates a 'cite' component with css applied */
47
+ cite: (...p: TSP) => s('cite' as unk as FC<HTP['cite']>)(...p),
48
+ /** creates a 'code' component with css applied */
49
+ code: (...p: TSP) => s('code' as unk as FC<HTP['code']>)(...p),
50
+ /** creates a 'col' component with css applied */
51
+ col: (...p: TSP) => s('col' as unk as FC<HTP['col']>)(...p),
52
+ /** creates a 'colgroup' component with css applied */
53
+ colgroup: (...p: TSP) => s('colgroup' as unk as FC<HTP['colgroup']>)(...p),
54
+ /** creates a 'dd' component with css applied */
55
+ dd: (...p: TSP) => s('dd' as unk as FC<HTP['dd']>)(...p),
56
+ /** creates a 'del' component with css applied */
57
+ del: (...p: TSP) => s('del' as unk as FC<HTP['del']>)(...p),
58
+ /** creates a 'details' component with css applied */
59
+ details: (...p: TSP) => s('details' as unk as FC<HTP['details']>)(...p),
60
+ /** creates a 'dfn' component with css applied */
61
+ dfn: (...p: TSP) => s('dfn' as unk as FC<HTP['dfn']>)(...p),
62
+ /** creates a 'dialog' component with css applied */
63
+ dialog: (...p: TSP) => s('dialog' as unk as FC<HTP['dialog']>)(...p),
64
+ /** creates a 'div' component with css applied */
65
+ div: (...p: TSP) => s('div' as unk as FC<HTP['div']>)(...p),
66
+ /** creates a 'dl' component with css applied */
67
+ dl: (...p: TSP) => s('dl' as unk as FC<HTP['dl']>)(...p),
68
+ /** creates a 'dt' component with css applied */
69
+ dt: (...p: TSP) => s('dt' as unk as FC<HTP['dt']>)(...p),
70
+ /** creates a 'em' component with css applied */
71
+ em: (...p: TSP) => s('em' as unk as FC<HTP['em']>)(...p),
72
+ /** creates a 'embed' component with css applied */
73
+ embed: (...p: TSP) => s('embed' as unk as FC<HTP['embed']>)(...p),
74
+ /** creates a 'fieldset' component with css applied */
75
+ fieldset: (...p: TSP) => s('fieldset' as unk as FC<HTP['fieldset']>)(...p),
76
+ /** creates a 'figcaption' component with css applied */
77
+ figcaption: (...p: TSP) => s('figcaption' as unk as FC<HTP['figcaption']>)(...p),
78
+ /** creates a 'figure' component with css applied */
79
+ figure: (...p: TSP) => s('figure' as unk as FC<HTP['figure']>)(...p),
80
+ /** creates a 'footer' component with css applied */
81
+ footer: (...p: TSP) => s('footer' as unk as FC<HTP['footer']>)(...p),
82
+ /** creates a 'form' component with css applied */
83
+ form: (...p: TSP) => s('form' as unk as FC<HTP['form']>)(...p),
84
+ /** creates a 'h1' component with css applied */
85
+ h1: (...p: TSP) => s('h1' as unk as FC<HTP['h1']>)(...p),
86
+ /** creates a 'h2' component with css applied */
87
+ h2: (...p: TSP) => s('h2' as unk as FC<HTP['h2']>)(...p),
88
+ /** creates a 'h3' component with css applied */
89
+ h3: (...p: TSP) => s('h3' as unk as FC<HTP['h3']>)(...p),
90
+ /** creates a 'h4' component with css applied */
91
+ h4: (...p: TSP) => s('h4' as unk as FC<HTP['h4']>)(...p),
92
+ /** creates a 'h5' component with css applied */
93
+ h5: (...p: TSP) => s('h5' as unk as FC<HTP['h5']>)(...p),
94
+ /** creates a 'h6' component with css applied */
95
+ h6: (...p: TSP) => s('h6' as unk as FC<HTP['h6']>)(...p),
96
+ /** creates a 'header' component with css applied */
97
+ header: (...p: TSP) => s('header' as unk as FC<HTP['header']>)(...p),
98
+ /** creates a 'hgroup' component with css applied */
99
+ hgroup: (...p: TSP) => s('hgroup' as unk as FC<HTP['hgroup']>)(...p),
100
+ /** creates a 'hr' component with css applied */
101
+ hr: (...p: TSP) => s('hr' as unk as FC<HTP['hr']>)(...p),
102
+ /** creates a 'i' component with css applied */
103
+ i: (...p: TSP) => s('i' as unk as FC<HTP['i']>)(...p),
104
+ /** creates a 'iframe' component with css applied */
105
+ iframe: (...p: TSP) => s('iframe' as unk as FC<HTP['iframe']>)(...p),
106
+ /** creates a 'img' component with css applied */
107
+ img: (...p: TSP) => s('img' as unk as FC<HTP['img']>)(...p),
108
+ /** creates a 'input' component with css applied */
109
+ input: (...p: TSP) => s('input' as unk as FC<HTP['input']>)(...p),
110
+ /** creates a 'ins' component with css applied */
111
+ ins: (...p: TSP) => s('ins' as unk as FC<HTP['ins']>)(...p),
112
+ /** creates a 'kbd' component with css applied */
113
+ kbd: (...p: TSP) => s('kbd' as unk as FC<HTP['kbd']>)(...p),
114
+ /** creates a 'label' component with css applied */
115
+ label: (...p: TSP) => s('label' as unk as FC<HTP['label']>)(...p),
116
+ /** creates a 'legend' component with css applied */
117
+ legend: (...p: TSP) => s('legend' as unk as FC<HTP['legend']>)(...p),
118
+ /** creates a 'li' component with css applied */
119
+ li: (...p: TSP) => s('li' as unk as FC<HTP['li']>)(...p),
120
+ /** creates a 'main' component with css applied */
121
+ main: (...p: TSP) => s('main' as unk as FC<HTP['main']>)(...p),
122
+ /** creates a 'map' component with css applied */
123
+ map: (...p: TSP) => s('map' as unk as FC<HTP['map']>)(...p),
124
+ /** creates a 'mark' component with css applied */
125
+ mark: (...p: TSP) => s('mark' as unk as FC<HTP['mark']>)(...p),
126
+ /** creates a 'meter' component with css applied */
127
+ meter: (...p: TSP) => s('meter' as unk as FC<HTP['meter']>)(...p),
128
+ /** creates a 'nav' component with css applied */
129
+ nav: (...p: TSP) => s('nav' as unk as FC<HTP['nav']>)(...p),
130
+ /** creates a 'object' component with css applied */
131
+ object: (...p: TSP) => s('object' as unk as FC<HTP['object']>)(...p),
132
+ /** creates a 'ol' component with css applied */
133
+ ol: (...p: TSP) => s('ol' as unk as FC<HTP['ol']>)(...p),
134
+ /** creates a 'optgroup' component with css applied */
135
+ optgroup: (...p: TSP) => s('optgroup' as unk as FC<HTP['optgroup']>)(...p),
136
+ /** creates a 'option' component with css applied */
137
+ option: (...p: TSP) => s('option' as unk as FC<HTP['option']>)(...p),
138
+ /** creates a 'output' component with css applied */
139
+ output: (...p: TSP) => s('output' as unk as FC<HTP['output']>)(...p),
140
+ /** creates a 'p' component with css applied */
141
+ p: (...p: TSP) => s('p' as unk as FC<HTP['p']>)(...p),
142
+ /** creates a 'picture' component with css applied */
143
+ picture: (...p: TSP) => s('picture' as unk as FC<HTP['picture']>)(...p),
144
+ /** creates a 'pre' component with css applied */
145
+ pre: (...p: TSP) => s('pre' as unk as FC<HTP['pre']>)(...p),
146
+ /** creates a 'progress' component with css applied */
147
+ progress: (...p: TSP) => s('progress' as unk as FC<HTP['progress']>)(...p),
148
+ /** creates a 'q' component with css applied */
149
+ q: (...p: TSP) => s('q' as unk as FC<HTP['q']>)(...p),
150
+ /** creates a 'rp' component with css applied */
151
+ rp: (...p: TSP) => s('rp' as unk as FC<HTP['rp']>)(...p),
152
+ /** creates a 'rt' component with css applied */
153
+ rt: (...p: TSP) => s('rt' as unk as FC<HTP['rt']>)(...p),
154
+ /** creates a 'ruby' component with css applied */
155
+ ruby: (...p: TSP) => s('ruby' as unk as FC<HTP['ruby']>)(...p),
156
+ /** creates a 's' component with css applied */
157
+ s: (...p: TSP) => s('s' as unk as FC<HTP['s']>)(...p),
158
+ /** creates a 'samp' component with css applied */
159
+ samp: (...p: TSP) => s('samp' as unk as FC<HTP['samp']>)(...p),
160
+ /** creates a 'section' component with css applied */
161
+ section: (...p: TSP) => s('section' as unk as FC<HTP['section']>)(...p),
162
+ /** creates a 'select' component with css applied */
163
+ select: (...p: TSP) => s('select' as unk as FC<HTP['select']>)(...p),
164
+ /** creates a 'small' component with css applied */
165
+ small: (...p: TSP) => s('small' as unk as FC<HTP['small']>)(...p),
166
+ /** creates a 'span' component with css applied */
167
+ span: (...p: TSP) => s('span' as unk as FC<HTP['span']>)(...p),
168
+ /** creates a 'strong' component with css applied */
169
+ strong: (...p: TSP) => s('strong' as unk as FC<HTP['strong']>)(...p),
170
+ /** creates a 'sub' component with css applied */
171
+ sub: (...p: TSP) => s('sub' as unk as FC<HTP['sub']>)(...p),
172
+ /** creates a 'summary' component with css applied */
173
+ summary: (...p: TSP) => s('summary' as unk as FC<HTP['summary']>)(...p),
174
+ /** creates a 'sup' component with css applied */
175
+ sup: (...p: TSP) => s('sup' as unk as FC<HTP['sup']>)(...p),
176
+ /** creates a 'table' component with css applied */
177
+ table: (...p: TSP) => s('table' as unk as FC<HTP['table']>)(...p),
178
+ /** creates a 'tbody' component with css applied */
179
+ tbody: (...p: TSP) => s('tbody' as unk as FC<HTP['tbody']>)(...p),
180
+ /** creates a 'td' component with css applied */
181
+ td: (...p: TSP) => s('td' as unk as FC<HTP['td']>)(...p),
182
+ /** creates a 'textarea' component with css applied */
183
+ textarea: (...p: TSP) => s('textarea' as unk as FC<HTP['textarea']>)(...p),
184
+ /** creates a 'tfoot' component with css applied */
185
+ tfoot: (...p: TSP) => s('tfoot' as unk as FC<HTP['tfoot']>)(...p),
186
+ /** creates a 'th' component with css applied */
187
+ th: (...p: TSP) => s('th' as unk as FC<HTP['th']>)(...p),
188
+ /** creates a 'thead' component with css applied */
189
+ thead: (...p: TSP) => s('thead' as unk as FC<HTP['thead']>)(...p),
190
+ /** creates a 'time' component with css applied */
191
+ time: (...p: TSP) => s('time' as unk as FC<HTP['time']>)(...p),
192
+ /** creates a 'tr' component with css applied */
193
+ tr: (...p: TSP) => s('tr' as unk as FC<HTP['tr']>)(...p),
194
+ /** creates a 'u' component with css applied */
195
+ u: (...p: TSP) => s('u' as unk as FC<HTP['u']>)(...p),
196
+ /** creates a 'ul' component with css applied */
197
+ ul: (...p: TSP) => s('ul' as unk as FC<HTP['ul']>)(...p),
198
+ /** creates a 'video' component with css applied */
199
+ video: (...p: TSP) => s('video' as unk as FC<HTP['video']>)(...p),
200
+ })
package/esm/core.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import { ShorthandProps } from '@slimr/css';
2
+ import { CSSProperties, FC, HTMLAttributes } from 'react';
3
+ type allowableAny = any;
4
+ /** A type that represents all the css properties + shorthand props */
5
+ export interface ZxProps extends CSSProperties, ShorthandProps {
6
+ }
7
+ type ZxP = ZxProps;
8
+ type Zx = {
9
+ [k in keyof ZxP]: ZxP[k] | [ZxP[k] | null, ZxP[k]] | [ZxP[k] | null, ZxP[k] | null, ZxP[k]] | [ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]] | [ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]] | [ZxP[k], ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]] | [ZxP[k], ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k] | null, ZxP[k]];
10
+ };
11
+ type _Props = {
12
+ [k in keyof Zx as `_${k}`]?: Zx[k];
13
+ };
14
+ export interface SCProps extends _Props {
15
+ /** Like zx prop, but applies only on :active */
16
+ _active?: Zx;
17
+ className?: string;
18
+ /** A string of css or classname to be added to the component */
19
+ _css?: string;
20
+ /** Like zx prop, but applies only when user prefers dark theme */
21
+ _dark?: Zx;
22
+ /** Like zx prop, but applies only on :focus */
23
+ _focus?: Zx;
24
+ /** Like zx prop, but applies only on :focus-visible */
25
+ _focusVisible?: Zx;
26
+ /** Like zx prop, but applies only on :focus-within */
27
+ _focusWithin?: Zx;
28
+ /** Like zx prop, but applies only on :hover */
29
+ _hover?: Zx;
30
+ style?: CSSProperties;
31
+ /** Like zx prop, but applies only on :target */
32
+ _target?: Zx;
33
+ /** Like zx prop, but applies only on :visited */
34
+ _visited?: Zx;
35
+ /**
36
+ * Like style prop, but enhanced with features like chakra
37
+ * - Array values are converted to media query breakpoints
38
+ * - Numbers are converted to px
39
+ * - Shorthand props are supported
40
+ */
41
+ _zx?: Zx;
42
+ }
43
+ /** Styled Component: Like FunctionalComponent but adds SCProps */
44
+ export type SC<T extends {
45
+ className?: HTMLAttributes<allowableAny>['className'];
46
+ }> = FC<T & SCProps>;
47
+ /**
48
+ * A lightweight alternative to styled-components
49
+ * @param function - a functional component to be styled; must accept a className prop
50
+ * @returns a function that accepts a template string of css returns a decorated functional component
51
+ */
52
+ export declare function styledBase<C extends FC<allowableAny>>(Component: C): (strings: string | TemplateStringsArray, ...placeHolders: string[]) => SC<Parameters<C>[0]>;
53
+ export {};
package/esm/core.js ADDED
@@ -0,0 +1,155 @@
1
+ /* eslint-disable prefer-const */
2
+ import { classJoin, css, shorthandPropsMap } from '@slimr/css';
3
+ import { createElement, forwardRef } from 'react';
4
+ /** Converts a string to kebab case */
5
+ function toKebabCase(str) {
6
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
7
+ }
8
+ /** Converts a string to camel case */
9
+ function toCamelCase(str) {
10
+ return str.replace(/-./g, x => x[1].toUpperCase());
11
+ }
12
+ /** Expands the shorthand props of a zx prop into css full */
13
+ function expandShorthandProps(zx) {
14
+ return Object.entries(zx).reduce((acc, [k, v]) => {
15
+ if (k === 'mx') {
16
+ acc.marginLeft = v;
17
+ acc.marginRight = v;
18
+ }
19
+ else if (k === 'my') {
20
+ acc.marginTop = v;
21
+ acc.marginBottom = v;
22
+ }
23
+ else if (k === 'px') {
24
+ acc.paddingLeft = v;
25
+ acc.paddingRight = v;
26
+ }
27
+ else if (k === 'py') {
28
+ acc.paddingTop = v;
29
+ acc.paddingBottom = v;
30
+ }
31
+ else if (k in shorthandPropsMap) {
32
+ acc[toCamelCase(shorthandPropsMap[k])] = v;
33
+ }
34
+ else {
35
+ acc[k] = v;
36
+ }
37
+ return acc;
38
+ }, {});
39
+ }
40
+ /** Converts a zx prop into css string */
41
+ function zxToCss(zx) {
42
+ return Object.entries(zx)
43
+ .map(([k, v]) => {
44
+ if (!v)
45
+ return '';
46
+ k = toKebabCase(k);
47
+ if (typeof v === 'number')
48
+ v = v + 'px';
49
+ if (Array.isArray(v)) {
50
+ // @ts-expect-error - TS gets confused by the complexity
51
+ v = '[' + v.map(v => (typeof v === 'number' ? v + 'px' : v)).join(',') + ']';
52
+ }
53
+ return k + ':' + v + ';';
54
+ })
55
+ .join('\n');
56
+ }
57
+ /**
58
+ * A lightweight alternative to styled-components
59
+ * @param function - a functional component to be styled; must accept a className prop
60
+ * @returns a function that accepts a template string of css returns a decorated functional component
61
+ */
62
+ export function styledBase(Component) {
63
+ return (...cssProps) => {
64
+ const className = css(...cssProps);
65
+ /**
66
+ * A functional component that accepts Styled Props
67
+ */
68
+ const CStyled = forwardRef(function CStyled(props, ref) {
69
+ let { _active, _css, _dark, _focus, _focusVisible, _focusWithin, _hover, _target, _visited, _zx = {}, ...rest } = props;
70
+ // Pluck out $ prefixed props
71
+ Object.entries(props).forEach(([k, v]) => {
72
+ if (k.startsWith('_')) {
73
+ // @ts-expect-error - We know the key exists but ts doesn't
74
+ _zx[k.slice(1)] = v;
75
+ // @ts-expect-error - We know the key exists but ts doesn't
76
+ delete rest[k];
77
+ }
78
+ });
79
+ let cssStr = '';
80
+ if (_active) {
81
+ cssStr += `
82
+ &:active {
83
+ ${zxToCss(_active)}
84
+ }
85
+ `;
86
+ }
87
+ if (_dark) {
88
+ cssStr += `
89
+ @media (prefers-color-scheme: dark) {
90
+ ${zxToCss(_dark)}
91
+ }
92
+ `;
93
+ }
94
+ if (_focus) {
95
+ cssStr += `
96
+ &:focus {
97
+ ${zxToCss(_focus)}
98
+ }
99
+ `;
100
+ }
101
+ if (_focusVisible) {
102
+ cssStr += `
103
+ &:focus-visible {
104
+ ${zxToCss(_focusVisible)}
105
+ }
106
+ `;
107
+ }
108
+ if (_focusWithin) {
109
+ cssStr += `
110
+ &:focus-within {
111
+ ${zxToCss(_focusWithin)}
112
+ }
113
+ `;
114
+ }
115
+ if (_hover) {
116
+ cssStr += `
117
+ &:hover {
118
+ ${zxToCss(_hover)}
119
+ }
120
+ `;
121
+ }
122
+ if (_target) {
123
+ cssStr += `
124
+ &:target {
125
+ ${zxToCss(_target)}
126
+ }
127
+ `;
128
+ }
129
+ if (_visited) {
130
+ cssStr += `
131
+ &:visited {
132
+ ${zxToCss(_visited)}
133
+ }
134
+ `;
135
+ }
136
+ const hasMediaQuery = Object.values(_zx).some(v => Array.isArray(v));
137
+ // If has media query styles, use css class. Otherwise favor inline styles
138
+ if (hasMediaQuery || cssStr) {
139
+ cssStr = zxToCss(_zx) + cssStr;
140
+ }
141
+ else {
142
+ _zx = expandShorthandProps(_zx);
143
+ rest.style = { ...rest.style, ..._zx };
144
+ }
145
+ return createElement(Component, {
146
+ ref,
147
+ ...rest,
148
+ className: classJoin(className, _css ? (_css.includes(':') ? css(_css) : _css) : undefined, cssStr ? css(cssStr) : undefined, props.className),
149
+ });
150
+ });
151
+ CStyled.toString = () => '.' + className;
152
+ return CStyled;
153
+ };
154
+ }
155
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/esm/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
+ }