css-in-props 0.8.29 → 0.9.0

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 CHANGED
@@ -1,25 +1,24 @@
1
- # Symbols
1
+ # css-in-props
2
2
 
3
3
  UI Library in composition of [Scratch](https://github.com/smbo-ls/scratch) and [DOMQL](https://github.com/domql/domql)
4
4
 
5
- [![npm version](https://badge.fury.io/js/smbls.svg)](https://badge.fury.io/js/smbls)
5
+ [![npm version](https://badge.fury.io/js/css-in-props.svg)](https://badge.fury.io/js/css-in-props)
6
6
 
7
7
  ### Setup
8
8
 
9
9
  1. Installation
10
10
  ```
11
- yarn add smbls
11
+ yarn add css-in-props
12
12
  ```
13
13
 
14
14
  2. Import the component from Symbols
15
15
  ```
16
- import { Box } from 'smbls'
16
+ import { transformClassname, transformEmotion } from 'css-in-props'
17
17
  ```
18
18
 
19
19
  3. Use it inside your DOMQL code
20
20
  ```
21
- const Header = {
22
- proto: Box,
23
- // ...Other Properties
24
- }
21
+ const Box = ({ children, ...props }) => <div className={
22
+ transformEmotion(transformClassname(props))
23
+ }>{children}</div>
25
24
  ```
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Utilize props as CSS methods",
4
4
  "private": false,
5
5
  "author": "symbo.ls",
6
- "version": "0.8.29",
6
+ "version": "0.9.0",
7
7
  "repository": "https://github.com/symbo-ls/smbls",
8
8
  "main": "src/index.js",
9
9
  "files": [
@@ -13,6 +13,7 @@
13
13
  "registry": "https://registry.npmjs.org"
14
14
  },
15
15
  "scripts": {
16
+ "prestart": "rm -rf dist .cache",
16
17
  "start": "parcel index.html",
17
18
  "build": "parcel build index.html --public-url .",
18
19
  "deploy": "yarn build && gh-pages -d dist",
@@ -22,6 +23,7 @@
22
23
  },
23
24
  "dependencies": {
24
25
  "@domql/utils": "^2.2.1",
26
+ "@emotion/css": "^11.10.0",
25
27
  "@symbo.ls/scratch": "^0.3.19"
26
28
  },
27
29
  "devDependencies": {
package/src/index.js CHANGED
@@ -1,19 +1,4 @@
1
1
  'use strict'
2
2
 
3
- import { classNames } from './classNames'
4
- import { keySetters } from './subprops'
5
-
6
- export * from '@symbo.ls/scratch'
7
-
8
- export const transformClassname = props => {
9
- const CLASS_NAMES = {}
10
-
11
- for (const key in props) {
12
- const setter = keySetters[key.slice(0, 1)]
13
- const hasCSS = classNames[key]
14
- if (setter) setter(key, props[key], CLASS_NAMES)
15
- else if (hasCSS) CLASS_NAMES[key] = hasCSS
16
- }
17
-
18
- return CLASS_NAMES
19
- }
3
+ export { set } from '@symbo.ls/scratch'
4
+ export * from './transform'
@@ -0,0 +1,216 @@
1
+ 'use strict'
2
+
3
+ import { isArray, isObject } from '@domql/utils'
4
+ import { getColor, mapSpacing, getTheme, SPACING, mapFontSize, getFontFamily, FONT_FAMILY } from '@symbo.ls/scratch'
5
+
6
+ export const mapBasedOnRatio = (props, prop, unit) => {
7
+ const { spacingRatio } = props
8
+ const val = props[prop]
9
+ // TODO: move this to mapSpacing
10
+ if (spacingRatio) {
11
+ const params = SPACING[spacingRatio]
12
+
13
+ if (!params) {
14
+ SPACING[spacingRatio] = {
15
+ base: SPACING.base,
16
+ type: 'spacing',
17
+ ratio: spacingRatio,
18
+ range: [-5, +7],
19
+ subSequence: true,
20
+ sequence: {},
21
+ scales: {}
22
+ }
23
+ }
24
+
25
+ return mapSpacing(val, prop, params, unit)
26
+ }
27
+ return mapSpacing(val, prop, null, unit)
28
+ }
29
+
30
+ const isBorderStyle = str =>
31
+ ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'initial'].some(v => str.includes(v))
32
+
33
+ const diffBorder = (border, key = 'border') => {
34
+ const obj = {}
35
+ const arr = isObject(border) ? Object.values(border) : isArray(border) ? border : border.split(', ')
36
+ arr.map(v => {
37
+ if (v.includes('px')) obj[`${key}Width`] = v // TODO: add map spacing
38
+ else if (isBorderStyle(v)) obj[`${key}Style`] = v || 'solid'
39
+ else if (getColor(v)) obj[`${key}Color`] = getColor(v)
40
+ })
41
+ return obj
42
+ }
43
+
44
+ const diffStroke = stroke => {
45
+ const WebkitTextStroke = stroke.split(', ').map(v => {
46
+ if (v.includes('px')) return v
47
+ else if (getColor(v)) return getColor(v)
48
+ }).join(' ')
49
+ return { WebkitTextStroke }
50
+ }
51
+
52
+ export const grid = {
53
+ columns: props => props.columns ? ({ gridTemplateColumns: props.columns }) : null,
54
+ rows: props => props.rows ? ({ gridTemplateRows: props.rows }) : null,
55
+ area: props => props.area ? ({ gridArea: props.area }) : null,
56
+ template: props => props.template ? ({ gridTemplate: props.template }) : null,
57
+ templateAreas: props => props.templateAreas ? ({ gridTemplateAreas: props.templateAreas }) : null,
58
+ gap: props => props.gap ? mapBasedOnRatio(props, 'gap') : null,
59
+ columnGap: props => props.template ? mapBasedOnRatio(props, 'columnGap') : null,
60
+ rowGap: props => props.template ? mapBasedOnRatio(props, 'rowGap') : null
61
+ }
62
+
63
+ export const theme = {
64
+ theme: props => props.theme ? getTheme(props.theme) : null,
65
+
66
+ color: props => props.color ? ({ color: getColor(props.color) }) : null,
67
+ background: props => props.background ? ({ backgroundColor: getColor(props.background) }) : null,
68
+
69
+ textStroke: props => props.textStroke ? diffStroke(props.textStroke) : null,
70
+
71
+ border: props => props.border ? diffBorder(props.border) : null,
72
+ borderColor: props => props.borderColor ? ({ borderColor: getColor(props.borderColor) }) : null,
73
+ borderStyle: props => props.borderStyle && ({ borderStyle: props.borderStyle }),
74
+
75
+ borderLeft: props => props.borderLeft ? diffBorder(props.borderLeft, 'borderLeft') : null,
76
+ borderTop: props => props.borderTop ? diffBorder(props.borderTop, 'borderTop') : null,
77
+ borderRight: props => props.borderRight ? diffBorder(props.borderRight, 'borderRight') : null,
78
+ borderBottom: props => props.borderBottom ? diffBorder(props.borderBottom, 'borderBottom') : null,
79
+
80
+ opacity: props => props.opacity && ({ opacity: props.opacity }),
81
+ visibility: props => ({ visibility: props.visibility })
82
+ }
83
+
84
+ export const block = {
85
+ round: ({ props, key }) => props.round ? (mapSpacing(props.round, 'borderRadius') || ({ borderRadius: props.round })) : null,
86
+ borderRadius: ({ props, key }) => props.borderRadius ? (mapSpacing(props.borderRadius, 'borderRadius') || ({ borderRadius: props.borderRadius })) : null,
87
+
88
+ transition: props => props.transition && ({ transition: props.transition }),
89
+ transitionProperty: props => props.transitionProperty && ({
90
+ transitionProperty: props.transitionProperty,
91
+ willChange: props.transitionProperty
92
+ }),
93
+
94
+ boxSizing: props => props.boxSizing ? ({ display: props.boxSizing }) : {
95
+ boxSizing: 'border-box'
96
+ },
97
+
98
+ display: props => props.display && ({ display: props.display }),
99
+
100
+ hide: props => props.hide && ({ display: 'none' }),
101
+
102
+ width: props => props.width && mapBasedOnRatio(props, 'width'),
103
+ height: props => props.height && mapBasedOnRatio(props, 'height'),
104
+ boxSize: props => {
105
+ if (typeof props.boxSize !== 'string') return
106
+ const [height, width] = props.boxSize.split(' ')
107
+ return {
108
+ ...mapSpacing(height, 'height'),
109
+ ...mapSpacing(width, 'width')
110
+ }
111
+ },
112
+
113
+ maxWidth: props => props.maxWidth && mapBasedOnRatio(props, 'maxWidth'),
114
+ minWidth: props => props.minWidth && mapBasedOnRatio(props, 'minWidth'),
115
+ widthRange: props => {
116
+ if (typeof props.widthRange !== 'string') return
117
+ const [minWidth, maxWidth] = props.widthRange.split(' ')
118
+ return {
119
+ ...mapSpacing(minWidth, 'minWidth'),
120
+ ...mapSpacing(maxWidth, 'maxWidth')
121
+ }
122
+ },
123
+
124
+ maxHeight: props => props.maxHeight && mapBasedOnRatio(props, 'maxHeight'),
125
+ minHeight: props => props.minHeight && mapBasedOnRatio(props, 'minHeight'),
126
+ heightRange: props => {
127
+ if (typeof props.heightRange !== 'string') return
128
+ const [minHeight, maxHeight] = props.heightRange.split(' ')
129
+ return {
130
+ ...mapSpacing(minHeight, 'minHeight'),
131
+ ...mapSpacing(maxHeight, 'maxHeight')
132
+ }
133
+ },
134
+
135
+ aspectRatio: props => props.aspectRatio && ({ aspectRatio: props.aspectRatio }),
136
+
137
+ borderWidth: props => props.borderWidth ? mapBasedOnRatio(props, 'borderWidth') : null,
138
+
139
+ padding: props => props.padding ? mapBasedOnRatio(props, 'padding') : null,
140
+ margin: props => props.margin ? mapBasedOnRatio(props, 'margin') : null,
141
+
142
+ gap: props => props.gap ? mapBasedOnRatio(props, 'gap') : null,
143
+ gridArea: props => props.gridArea && ({ gridArea: props.gridArea })
144
+ }
145
+
146
+ export const flex = {
147
+ flexFlow: props => props.flexFlow && ({
148
+ display: 'flex',
149
+ flexFlow: props.flexFlow
150
+ }),
151
+ flexAlign: props => {
152
+ if (typeof props.flexAlign !== 'string') return
153
+ const [alignItems, justifyContent] = props.flexAlign.split(' ')
154
+ return {
155
+ display: 'flex',
156
+ alignItems: alignItems,
157
+ justifyContent: justifyContent
158
+ }
159
+ },
160
+
161
+ flex: props => props.flex && ({ flex: props.flex }),
162
+ alignItems: props => props.alignItems && ({ alignItems: props.alignItems }),
163
+ alignContent: props => props.alignContent && ({ alignContent: props.alignContent }),
164
+ justifyContent: props => props.justifyContent && ({ justifyContent: props.justifyContent })
165
+ }
166
+
167
+ export const position = {
168
+ position: props => props.position && ({ position: props.position }),
169
+ inset: props => {
170
+ const { inset } = props
171
+ if (typeof inset !== 'string') return
172
+ return { inset: inset.split(' ').map(v => mapSpacing(v, 'k').k).join(' ') }
173
+ },
174
+
175
+ left: props => mapSpacing(props.left, 'left'),
176
+ top: props => mapSpacing(props.top, 'top'),
177
+ right: props => mapSpacing(props.right, 'right'),
178
+ bottom: props => mapSpacing(props.bottom, 'bottom')
179
+ }
180
+
181
+ export const text = {
182
+ fontSize: props => props.fontSize ? mapFontSize(props.fontSize) : null,
183
+ fontFamily: props => props.fontFamily && ({ fontFamily: getFontFamily(FONT_FAMILY, props.fontFamily) || props.fontFamily }),
184
+ lineHeight: props => props.lineHeight && ({ lineHeight: props.lineHeight }),
185
+ // lineHeight: props => props.lineHeight && mapBasedOnRatio(props, 'lineHeight', null, ''),
186
+ textDecoration: props => props.textDecoration && ({ textDecoration: props.textDecoration }),
187
+ textTransform: props => props.textTransform && ({ textTransform: props.textTransform }),
188
+ textAlign: props => props.textAlign && ({ textAlign: props.textAlign }),
189
+ fontWeight: props => props.fontWeight && ({ fontWeight: props.fontWeight })
190
+ }
191
+
192
+ export const registry = {
193
+ style: props => props.style,
194
+
195
+ ...theme,
196
+ ...block,
197
+ ...flex,
198
+ ...position,
199
+ ...text,
200
+
201
+ gridColumn: props => props.gridColumn && ({ gridColumn: props.gridColumn }),
202
+ gridRow: props => props.gridRow && ({ gridRow: props.gridRow }),
203
+
204
+ size: props => {
205
+ if (typeof props.heightRange !== 'string') return
206
+ const [minHeight, maxHeight] = props.heightRange.split(' ')
207
+ return {
208
+ ...mapSpacing(minHeight, 'minHeight'),
209
+ ...mapSpacing(maxHeight, 'maxHeight')
210
+ }
211
+ },
212
+
213
+ overflow: props => props.overflow && ({ overflow: props.overflow }),
214
+
215
+ transform: props => props.transform && ({ transform: props.transform })
216
+ }
@@ -0,0 +1,21 @@
1
+ 'use strict'
2
+
3
+ import { merge, isFunction } from '@domql/utils'
4
+ import { keySetters } from './subProps'
5
+
6
+ import { registry } from '../registry'
7
+
8
+ export const transformClassname = props => {
9
+ const CLASS_NAMES = {}
10
+
11
+ for (const key in props) {
12
+ const setter = keySetters[key.slice(0, 1)]
13
+ const hasCSS = registry[key]
14
+
15
+ if (setter) setter(key, props[key], CLASS_NAMES)
16
+ else if (isFunction(hasCSS)) merge(CLASS_NAMES, hasCSS(props))
17
+ }
18
+
19
+
20
+ return CLASS_NAMES
21
+ }
@@ -0,0 +1,20 @@
1
+ 'use strict'
2
+
3
+ import createEmotion from '@emotion/css/create-instance'
4
+ // const ENV = process.env.NODE_ENV
5
+
6
+ export const {
7
+ flush,
8
+ hydrate,
9
+ cx,
10
+ getRegisteredStyles,
11
+ injectGlobal,
12
+ keyframes,
13
+ css,
14
+ sheet,
15
+ cache
16
+ } = createEmotion({
17
+ key: 'smbls'
18
+ })
19
+
20
+ export const transformEmotion = props => css(props)
@@ -0,0 +1,5 @@
1
+ 'use strict'
2
+
3
+ export * from './emotion'
4
+ export * from './classname'
5
+ export * from './subProps'
@@ -0,0 +1,68 @@
1
+
2
+ import { isArray, merge } from '@domql/utils'
3
+ import { CASES as CONFIG_CASES, MEDIA as CONFIG_MEDIA } from '@symbo.ls/scratch'
4
+ import { registry } from '../registry'
5
+
6
+ const execClass = (key, props, result, rootProps) => {
7
+ const className = registry[key]
8
+
9
+ if (typeof className !== 'function') return
10
+
11
+ let classExec = className(props)
12
+ if (isArray(classExec)) {
13
+ classExec = classExec.reduce((a, c) => merge(a, c), {})
14
+ }
15
+
16
+ for (const finalProp in classExec) {
17
+ result[finalProp] = classExec[finalProp]
18
+ }
19
+ }
20
+
21
+ export const transformProps = (props, result, rootProps) => {
22
+ const propsClassObj = {}
23
+
24
+ for (const key in props) {
25
+ const setter = keySetters[key.slice(0, 1)]
26
+ if (setter) {
27
+ setter(key, props[key], propsClassObj, rootProps)
28
+ continue
29
+ } else {
30
+ execClass(key, props, propsClassObj, rootProps)
31
+ }
32
+ }
33
+
34
+ return propsClassObj
35
+ }
36
+
37
+ export const transformMedia = (key, props, result, rootProps) => {
38
+ const mediaName = CONFIG_MEDIA[key.slice(1)]
39
+ const mediaKey = `@media screen and ${mediaName}`
40
+ // result[mediaKey] = transformProps(props, result, rootProps)
41
+ const obj = { [mediaKey]: transformProps(props, result, rootProps) }
42
+ merge(result, obj)
43
+ }
44
+
45
+ export const transformSelector = (key, props, result, rootProps) => {
46
+ const selectorKey = `&${key}`
47
+ const obj = { [selectorKey]: transformProps(props, result, rootProps) }
48
+ merge(result, obj)
49
+ }
50
+
51
+ export const transformCases = (key, props, result, rootProps) => {
52
+ const caseKey = key.slice(1)
53
+ if (!CONFIG_CASES[caseKey]) return
54
+ merge(result, transformProps(props, result, rootProps))
55
+ }
56
+
57
+ export const transformConditionalCases = (key, props, result, rootProps) => {
58
+ const caseKey = key.slice(1)
59
+ if (!rootProps[caseKey]) return // remove classname if not here
60
+ merge(result, transformProps(props, result, rootProps))
61
+ }
62
+
63
+ export const keySetters = {
64
+ '@': transformMedia,
65
+ ':': transformSelector,
66
+ $: transformCases,
67
+ '.': transformConditionalCases
68
+ }
package/src/classNames.js DELETED
@@ -1,50 +0,0 @@
1
- 'use strict'
2
-
3
- import { isArray, isObject } from '@domql/utils'
4
- import { getColor, mapSpacing, getTheme } from '@symbo.ls/scratch'
5
-
6
- const isBorderStyle = str =>
7
- ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset', 'initial'].some(v => str.includes(v))
8
-
9
- const diffBorder = (border, key = 'border') => {
10
- const obj = {}
11
- const arr = isObject(border) ? Object.values(border) : isArray(border) ? border : border.split(', ')
12
- arr.map(v => {
13
- if (v.includes('px')) obj[`${key}Width`] = v // TODO: add map spacing
14
- else if (isBorderStyle(v)) obj[`${key}Style`] = v || 'solid'
15
- else if (getColor(v)) obj[`${key}Color`] = getColor(v)
16
- })
17
- return obj
18
- }
19
-
20
- const diffStroke = stroke => {
21
- const WebkitTextStroke = stroke.split(', ').map(v => {
22
- if (v.includes('px')) return v
23
- else if (getColor(v)) return getColor(v)
24
- }).join(' ')
25
- return { WebkitTextStroke }
26
- }
27
-
28
- export const classNames = {
29
- round: ({ props, key }) => props.round ? (mapSpacing(props.round, 'borderRadius') || ({ borderRadius: props.round })) : null,
30
- borderRadius: ({ props, key }) => props.borderRadius ? (mapSpacing(props.borderRadius, 'borderRadius') || ({ borderRadius: props.borderRadius })) : null,
31
-
32
- theme: ({ props }) => props.theme ? getTheme(props.theme) : null,
33
-
34
- color: ({ props }) => props.color ? ({ color: getColor(props.color) }) : null,
35
- background: ({ props }) => props.background ? ({ backgroundColor: getColor(props.background) }) : null,
36
-
37
- textStroke: ({ props }) => props.textStroke ? diffStroke(props.textStroke) : null,
38
-
39
- border: ({ props }) => props.border ? diffBorder(props.border) : null,
40
- borderColor: ({ props }) => props.borderColor ? ({ borderColor: getColor(props.borderColor) }) : null,
41
- borderStyle: ({ props }) => props.borderStyle && ({ borderStyle: props.borderStyle }),
42
-
43
- borderLeft: ({ props }) => props.borderLeft ? diffBorder(props.borderLeft, 'borderLeft') : null,
44
- borderTop: ({ props }) => props.borderTop ? diffBorder(props.borderTop, 'borderTop') : null,
45
- borderRight: ({ props }) => props.borderRight ? diffBorder(props.borderRight, 'borderRight') : null,
46
- borderBottom: ({ props }) => props.borderBottom ? diffBorder(props.borderBottom, 'borderBottom') : null,
47
-
48
- opacity: ({ props }) => props.opacity && ({ opacity: props.opacity }),
49
- visibility: ({ props }) => ({ visibility: props.visibility })
50
- }
package/src/subprops.js DELETED
@@ -1,67 +0,0 @@
1
-
2
- import { isArray, merge } from '@domql/utils'
3
- import { CASES as CONFIG_CASES, MEDIA as CONFIG_MEDIA } from '@symbo.ls/scratch'
4
- import { classNames } from './classNames'
5
-
6
- export const keySetters = {
7
- '@': (key, props, result, rootProps) => applyMediaProps(key, props, result, rootProps),
8
- ':': (key, props, result, rootProps) => applySelectorProps(key, props, result, rootProps),
9
- $: (key, props, result, rootProps) => applyCaseProps(key, props, result, rootProps),
10
- '.': (key, props, result, rootProps) => applyConditionalCaseProps(key, props, result, rootProps)
11
- }
12
-
13
- const execClass = (key, props, result, rootProps) => {
14
- const className = classNames[key]
15
-
16
- if (typeof className !== 'function') return
17
-
18
- let classExec = className({ props })
19
- if (isArray(classExec)) {
20
- classExec = classExec.reduce((a, c) => merge(a, c), {})
21
- }
22
-
23
- for (const finalProp in classExec) {
24
- result[finalProp] = classExec[finalProp]
25
- }
26
- }
27
-
28
- const convertPropsToClass = (props, result, rootProps) => {
29
- const propsClassObj = {}
30
-
31
- for (const key in props) {
32
- const setter = keySetters[key.slice(0, 1)]
33
- if (setter) {
34
- setter(key, props[key], propsClassObj, rootProps)
35
- continue
36
- } else {
37
- execClass(key, props, propsClassObj, rootProps)
38
- }
39
- }
40
-
41
- return propsClassObj
42
- }
43
-
44
- const applyMediaProps = (key, props, result, rootProps) => {
45
- const mediaName = CONFIG_MEDIA[key.slice(1)]
46
- const mediaKey = `@media screen and ${mediaName}`
47
- // result[mediaKey] = convertPropsToClass(props, result, rootProps)
48
- merge(result, convertPropsToClass(props, result, rootProps))
49
- }
50
-
51
- const applySelectorProps = (key, props, result, rootProps) => {
52
- const selectorKey = `&${key}`
53
- result[selectorKey] = convertPropsToClass(props, result, rootProps)
54
- merge(result, convertPropsToClass(props, result, rootProps))
55
- }
56
-
57
- const applyCaseProps = (key, props, result, rootProps) => {
58
- const caseKey = key.slice(1)
59
- if (!CONFIG_CASES[caseKey]) return
60
- merge(result, convertPropsToClass(props, result, rootProps))
61
- }
62
-
63
- const applyConditionalCaseProps = (key, props, result, rootProps) => {
64
- const caseKey = key.slice(1)
65
- if (!rootProps[caseKey]) return // remove classname if not here
66
- merge(result, convertPropsToClass(props, result, rootProps))
67
- }