@symbo.ls/scratch 0.3.16 → 0.3.19

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@symbo.ls/scratch",
3
3
  "description": "Φ / CSS framework and methodology.",
4
4
  "author": "Symbols",
5
- "version": "0.3.16",
5
+ "version": "0.3.19",
6
6
  "files": [
7
7
  "src"
8
8
  ],
@@ -0,0 +1,3 @@
1
+ 'use strict'
2
+
3
+ export const CASES = {}
@@ -2,18 +2,14 @@
2
2
 
3
3
  export * from './sequence'
4
4
  export * from './unit'
5
-
6
5
  export * from './typography'
7
6
  export * from './font'
8
7
  export * from './font-family'
9
-
8
+ export * from './media'
10
9
  export * from './spacing'
11
-
12
10
  export * from './color'
13
11
  export * from './theme'
14
-
15
12
  export * from './icons'
16
-
17
- export * from './media'
18
-
13
+ export * from './timing'
19
14
  export * from './document'
15
+ export * from './cases'
@@ -11,5 +11,6 @@ export const MEDIA = {
11
11
  mobileM: '(max-width: 560px)',
12
12
  mobileS: '(max-width: 480px)',
13
13
 
14
- light: '(prefers-color-scheme: light)'
14
+ light: '(prefers-color-scheme: light)',
15
+ dark: '(prefers-color-scheme: dark)'
15
16
  }
@@ -1,5 +1,28 @@
1
1
  'use strict'
2
2
 
3
- export const TIMING = {
4
- base: 16
3
+ import { SEQUENCE } from '.'
4
+ import { fallBack, generateSequence } from '../utils'
5
+
6
+ const defaultProps = {
7
+ default: 150,
8
+ base: 150,
9
+ type: 'timing',
10
+ ratio: SEQUENCE['minor-third'],
11
+ range: [-3, +12],
12
+ sequence: {},
13
+ scales: {}
14
+ }
15
+
16
+ export const applyTimingSequence = () => {
17
+ generateSequence(defaultProps)
5
18
  }
19
+
20
+ export const mapTiming = val => fallBack({
21
+ type: defaultProps.sequence,
22
+ prop: 'timing',
23
+ val,
24
+ unit: 'ms',
25
+ prefix: '--duration-'
26
+ })
27
+
28
+ export const TIMING = defaultProps
package/src/index.js CHANGED
@@ -4,7 +4,7 @@ import CONFIG from './factory'
4
4
 
5
5
  export * from './factory'
6
6
  export * from './utils'
7
- export * from './methods'
7
+ export * from './set'
8
8
  export * from './config'
9
9
  export * from './reset'
10
10
 
package/src/reset.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  import * as CONFIG from './config'
4
+ import { getTheme } from './set'
4
5
  import { deepMerge, merge } from './utils'
5
6
 
6
7
  export const RESET = {}
@@ -27,7 +28,9 @@ export const applyReset = (reset = {}) => deepMerge(merge(RESET, reset), {
27
28
  body: {
28
29
  boxSizing: 'border-box',
29
30
  height: '100%',
30
- margin: 0
31
+ margin: 0,
32
+
33
+ ...getTheme('document')
31
34
  },
32
35
 
33
36
  ...CONFIG.TYPOGRAPHY.styles,
@@ -1,7 +1,8 @@
1
1
  'use strict'
2
2
 
3
- import { applyDocument, applySpacingSequence, applyTypographySequence } from '../config'
4
- import CONFIG, { CSS_VARS } from '../factory'
3
+ import { applyDocument, applySpacingSequence, applyTimingSequence, applyTypographySequence } from './config'
4
+ import CONFIG, { CSS_VARS } from './factory'
5
+ import { applyReset } from './reset'
5
6
  import {
6
7
  isArray,
7
8
  colorStringToRgbaArray,
@@ -14,8 +15,9 @@ import {
14
15
  getDefaultOrFirstKey,
15
16
  getFontFaceEach,
16
17
  hslToRgb,
17
- getColorShade
18
- } from '../utils'
18
+ getColorShade,
19
+ setVariables
20
+ } from './utils'
19
21
 
20
22
  const ENV = process.env.NODE_ENV
21
23
 
@@ -45,7 +47,7 @@ export const getColor = value => {
45
47
  if (tone.slice(0, 1) === '-' || tone.slice(0, 1) === '+') {
46
48
  rgb = hexToRgbArray(getColorShade(toHex, parseFloat(tone))).join(', ')
47
49
  } else {
48
- const [r, g, b] = [...rgb.split(', ').map(v => parseFloat(v))]
50
+ const [r, g, b] = [...rgb.split(', ').map(v => parseInt(v))]
49
51
  const hsl = rgbToHSL(r, g, b)
50
52
  const [h, s, l] = hsl // eslint-disable-line
51
53
  const newRgb = hslToRgb(h, s, parseFloat(tone) / 100 * 255)
@@ -104,26 +106,29 @@ const getThemeValue = theme => {
104
106
 
105
107
  export const getTheme = value => {
106
108
  const { THEME } = CONFIG
107
- // console.log('theme', THEME, CONFIG)
109
+
110
+ if (isString(value)) {
111
+ const [theme, subtheme] = value.split(' ')
112
+ const isOurTheme = THEME[theme]
113
+ if (isOurTheme) {
114
+ if (!subtheme) return getThemeValue(isOurTheme)
115
+ value = [theme, subtheme]
116
+ }
117
+ }
118
+
108
119
  if (isObjectLike(value) && value[1]) {
109
120
  const themeName = value[0]
110
121
  const subThemeName = value[1]
111
122
  const { helpers, variants, state } = THEME[themeName]
123
+
112
124
  if (variants && variants[subThemeName]) return getThemeValue(variants[subThemeName])
113
125
  if (helpers && helpers[subThemeName]) return getThemeValue(helpers[subThemeName])
114
126
  if (state && state[subThemeName]) return getThemeValue(state[subThemeName])
115
127
  } else if (isObject(value)) return setThemeValue(value)
116
- else if (isString(value) && THEME[value]) return getThemeValue(THEME[value])
117
128
 
118
129
  if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose) console.warn('Can\'t find theme', value)
119
130
  }
120
131
 
121
- const setPrefersScheme = (theme, key, variant, themeValue) => {
122
- const result = getTheme(variant)
123
- themeValue[`@media (prefers-color-scheme: ${key})`] = result
124
- if (isObject(variant) && !variant.value) variant.value = result
125
- }
126
-
127
132
  const setInverseTheme = (theme, variant, value) => {
128
133
  if (isObject(variant)) {
129
134
  theme.variants.inverse.value = setThemeValue(variant)
@@ -138,25 +143,39 @@ const setInverseTheme = (theme, variant, value) => {
138
143
  }
139
144
  }
140
145
 
141
- const goThroughHelpers = (theme, value) => {
142
- const { helpers } = theme
143
- if (!helpers) return
144
- const keys = Object.keys(helpers)
146
+ const setPseudo = (theme, key, variant, themeValue) => {
147
+ const result = getTheme(variant)
148
+ themeValue[`&:${key}`] = result
149
+ if (isObject(variant) && !variant.value) variant.value = result
150
+ }
151
+
152
+ const goThroughInteractiveStates = (theme, value) => {
153
+ const { state } = theme
154
+ if (!state) return
155
+ const keys = Object.keys(state)
145
156
  keys.map(key => {
146
- const helper = helpers[key]
147
- if (isString(helper)) helpers[key] = CONFIG.THEME[helper]
148
- else getThemeValue(helpers[key])
157
+ const variant = state[key]
158
+ setPseudo(theme, key, variant, value)
149
159
  return theme
150
160
  })
151
161
  return theme
152
162
  }
153
163
 
164
+ const setPrefersScheme = (theme, key, variant, themeValue) => {
165
+ const result = getTheme(variant)
166
+ // console.log(variant)
167
+ themeValue[`@media (prefers-color-scheme: ${key})`] = result
168
+ if (isObject(variant) && !variant.value) variant.value = result
169
+ }
170
+
154
171
  const goThroughVariants = (theme, value) => {
155
172
  const { variants } = theme
156
173
  if (!variants) return
157
174
  const keys = Object.keys(variants)
158
175
  keys.map(key => {
159
176
  const variant = variants[key]
177
+ // console.log('=========')
178
+ // console.log(theme, key, variant, value)
160
179
  if (key === 'dark' || key === 'light') setPrefersScheme(theme, key, variant, value)
161
180
  if (key === 'inverse') setInverseTheme(theme, variant, value)
162
181
  return theme
@@ -164,19 +183,14 @@ const goThroughVariants = (theme, value) => {
164
183
  return theme
165
184
  }
166
185
 
167
- const setPseudo = (theme, key, variant, themeValue) => {
168
- const result = getTheme(variant)
169
- themeValue[`&:${key}`] = result
170
- if (isObject(variant) && !variant.value) variant.value = result
171
- }
172
-
173
- const goThroughInteractiveStates = (theme, value) => {
174
- const { state } = theme
175
- if (!state) return
176
- const keys = Object.keys(state)
186
+ const goThroughHelpers = (theme, value) => {
187
+ const { helpers } = theme
188
+ if (!helpers) return
189
+ const keys = Object.keys(helpers)
177
190
  keys.map(key => {
178
- const variant = state[key]
179
- setPseudo(theme, key, variant, value)
191
+ const helper = helpers[key]
192
+ if (isString(helper)) helpers[key] = CONFIG.THEME[helper]
193
+ else getThemeValue(helpers[key])
180
194
  return theme
181
195
  })
182
196
  return theme
@@ -214,6 +228,10 @@ const setFontFamily = (val, key) => {
214
228
  return { var: CSSvar, value: str, arr: value, type }
215
229
  }
216
230
 
231
+ const setCases = (val, key) => {
232
+ return val()
233
+ }
234
+
217
235
  const setSameValue = (val, key) => val
218
236
 
219
237
  export const SETTERS = {
@@ -223,9 +241,12 @@ export const SETTERS = {
223
241
  font_family: setFontFamily,
224
242
  theme: setTheme,
225
243
  typography: setSameValue,
244
+ cases: setCases,
226
245
  spacing: setSameValue,
227
246
  media: setSameValue,
228
- icons: setSameValue
247
+ timing: setSameValue,
248
+ icons: setSameValue,
249
+ reset: setSameValue
229
250
  }
230
251
 
231
252
  /**
@@ -239,8 +260,15 @@ export const setValue = (FACTORY_NAME, value, key) => {
239
260
  const factoryName = FACTORY_NAME.toLowerCase()
240
261
  const FACTORY = CONFIG[FACTORY_NAME]
241
262
  const result = SETTERS[factoryName](value, key)
263
+
264
+ // console.log(CONFIG.verbose)
265
+ if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose && FACTORY[key]) {
266
+ // console.warn('Replacing ', key, ' as ', FACTORY[key], ' in ', factoryName)
267
+ }
268
+
242
269
  FACTORY[key] = result
243
- CSS_VARS[result.var] = result.value
270
+ setVariables(result, key)
271
+
244
272
  return FACTORY
245
273
  }
246
274
 
@@ -253,7 +281,15 @@ export const setEach = (factoryName, props) => {
253
281
  }
254
282
 
255
283
  export const set = recivedConfig => {
256
- const { version, verbose, ...config } = recivedConfig
284
+ const { version, verbose, useVariable, ...config } = recivedConfig
285
+
286
+ // console.log('=========')
287
+ // console.log(verbose)
288
+ CONFIG.verbose = verbose
289
+ CONFIG.useVariable = useVariable
290
+ // console.log(recivedConfig)
291
+ if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose) console.log(CONFIG)
292
+
257
293
  const keys = Object.keys(config)
258
294
  keys.map(key => setEach(key, config[key]))
259
295
 
@@ -261,11 +297,9 @@ export const set = recivedConfig => {
261
297
  applyTypographySequence()
262
298
  applySpacingSequence()
263
299
  applyDocument()
300
+ applyTimingSequence()
301
+ applyReset()
264
302
 
265
- CONFIG.verbose = verbose
266
- if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose) console.log(CONFIG)
267
-
303
+ CONFIG.VARS = CSS_VARS
268
304
  return CONFIG
269
305
  }
270
-
271
- export default set
@@ -0,0 +1,148 @@
1
+ 'use strict'
2
+
3
+ const ENV = process.env.NODE_ENV
4
+
5
+ export const colorStringToRgbaArray = color => {
6
+ if (color === '') return
7
+ if (color.toLowerCase() === 'transparent') return [0, 0, 0, 0]
8
+
9
+ // convert #RGB and #RGBA to #RRGGBB and #RRGGBBAA
10
+ if (color[0] === '#') {
11
+ if (color.length < 7) {
12
+ color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3] + (color.length > 4 ? color[4] + color[4] : '')
13
+ } return [parseInt(color.substr(1, 2), 16),
14
+ parseInt(color.substr(3, 2), 16),
15
+ parseInt(color.substr(5, 2), 16),
16
+ color.length > 7 ? parseInt(color.substr(7, 2), 16) / 255 : 1]
17
+ }
18
+
19
+ // convert named colors
20
+ if (color.indexOf('rgb') === -1) {
21
+ // intentionally use unknown tag to lower chances of css rule override with !important
22
+ const elem = document.body.appendChild(document.createElement('fictum'))
23
+ // this flag tested on chrome 59, ff 53, ie9, ie10, ie11, edge 14
24
+ const flag = 'rgb(1, 2, 3)'
25
+ elem.style.color = flag
26
+ // color set failed - some monstrous css rule is probably taking over the color of our object
27
+ if (elem.style.color !== flag) return
28
+ elem.style.color = color
29
+ if (elem.style.color === flag || elem.style.color === '') return // color parse failed
30
+ color = window.getComputedStyle(elem).color
31
+ document.body.removeChild(elem)
32
+ }
33
+
34
+ // convert 'rgb(R,G,B)' to 'rgb(R,G,B,A)' which looks awful but will pass the regxep below
35
+ if (color.indexOf('rgb') === 0) {
36
+ if (color.indexOf('rgba') === -1) color = `${color}, 1`
37
+ return color.match(/[\.\d]+/g).map(a => +a) // eslint-disable-line
38
+ }
39
+ }
40
+
41
+ export const mixTwoColors = (colorA, colorB, range = 0.5) => {
42
+ colorA = colorStringToRgbaArray(colorA)
43
+ colorB = colorStringToRgbaArray(colorB)
44
+ return mixTwoRgba(colorA, colorB, range)
45
+ }
46
+
47
+ export const hexToRgb = (hex, alpha = 1) => {
48
+ const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
49
+ return `rgb(${r},${g},${b})`
50
+ }
51
+
52
+ export const hexToRgbArray = (hex, alpha = 1) => {
53
+ const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
54
+ return [r, g, b]
55
+ }
56
+
57
+ export const rgbToHex = (r, g, b) => {
58
+ return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
59
+ }
60
+
61
+ export const rgbArrayToHex = ([r, g, b]) => {
62
+ return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
63
+ }
64
+
65
+ export const hexToRgba = (hex, alpha = 1) => {
66
+ const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
67
+ return `rgba(${r},${g},${b},${alpha})`
68
+ }
69
+
70
+ export const mixTwoRgb = (colorA, colorB, range = 0.5) => {
71
+ const arr = []
72
+ for (let i = 0; i < 3; i++) {
73
+ arr[i] = Math.round(
74
+ colorA[i] + (
75
+ (colorB[i] - colorA[i]) * range
76
+ )
77
+ )
78
+ }
79
+ return `rgb(${arr})`
80
+ }
81
+
82
+ export const changeLightness = (delta, hsl) => {
83
+ const [hue, saturation, lightness] = hsl
84
+
85
+ const newLightness = Math.max(
86
+ 0,
87
+ Math.min(100, lightness + parseFloat(delta))
88
+ )
89
+
90
+ return [hue, saturation, newLightness]
91
+ }
92
+
93
+ export const rgbToHSL = (r, g, b) => {
94
+ const a = Math.max(r, g, b); const n = a - Math.min(r, g, b); const f = (1 - Math.abs(a + a - n - 1))
95
+ const h = n && ((a == r) ? (g - b) / n : ((a == g) ? 2 + (b - r) / n : 4 + (r - g) / n)) //eslint-disable-line
96
+ return [60 * (h < 0 ? h + 6 : h), f ? n / f : 0, (a + a - n) / 2]
97
+ }
98
+
99
+ export const hslToRgb = (h, s, l,
100
+ a = s * Math.min(l, 1 - l),
101
+ f = (n, k = (n + h / 30) % 12) => l - a * Math.max(
102
+ Math.min(k - 3, 9 - k, 1), -1
103
+ )
104
+ ) => [f(0), f(8), f(4)]
105
+
106
+ export const getColorShade = (col, amt) => {
107
+ const num = parseInt(col, 16)
108
+
109
+ let r = (num >> 16) + amt
110
+
111
+ if (r > 255) r = 255
112
+ else if (r < 0) r = 0
113
+
114
+ let b = ((num >> 8) & 0x00FF) + amt
115
+
116
+ if (b > 255) b = 255
117
+ else if (b < 0) b = 0
118
+
119
+ let g = (num & 0x0000FF) + amt
120
+
121
+ if (g > 255) g = 255
122
+ else if (g < 0) g = 0
123
+
124
+ return (g | (b << 8) | (r << 16)).toString(16)
125
+ }
126
+
127
+ export const mixTwoRgba = (colorA, colorB, range = 0.5) => {
128
+ const arr = []
129
+ for (let i = 0; i < 4; i++) {
130
+ const round = (i === 3) ? x => x : Math.round
131
+ arr[i] = round(
132
+ (colorA[i] + (
133
+ (colorB[i] - colorA[i]) * range
134
+ ))
135
+ )
136
+ }
137
+ return `rgba(${arr})`
138
+ }
139
+
140
+ export const opacify = (color, opacity) => {
141
+ const arr = colorStringToRgbaArray(color)
142
+ if (!arr) {
143
+ if (ENV === 'test' || ENV === 'development') console.warn(color + 'color is not rgba')
144
+ return
145
+ }
146
+ arr[3] = opacity
147
+ return `rgba(${arr})`
148
+ }
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ export const getDefaultOrFirstKey = (LIBRARY, key) => {
4
+ if (LIBRARY[key]) return LIBRARY[key].value
5
+ if (LIBRARY.default) return LIBRARY[LIBRARY.default].value
6
+ return LIBRARY[Object.keys(LIBRARY)[0]].value
7
+ }
8
+
9
+ export const getFontFormat = url => url.split(/[#?]/)[0].split('.').pop().trim()
10
+
11
+ export const setCustomFont = (name, weight, url) => `@font-face {
12
+ font-family: '${name}';
13
+ font-style: normal;
14
+ font-weight: ${weight};
15
+ src: url('${url}') format('${getFontFormat(url)}');
16
+ }`
17
+ // src: url('${url}') format('${getFontFormat(url)}');
18
+
19
+ export const getFontFaceEach = (name, weightsObject) => {
20
+ const keys = Object.keys(weightsObject)
21
+ const weightsJoint = keys.map(key => {
22
+ const { fontWeight, url } = weightsObject[key]
23
+ return setCustomFont(name, fontWeight, url)
24
+ })
25
+ return weightsJoint.join('\n')
26
+ }
27
+
28
+ export const getFontFace = LIBRARY => {
29
+ const keys = Object.keys(LIBRARY)
30
+ const fontsJoint = keys.map(key => getFontFaceEach(key, LIBRARY[key].value))
31
+ return fontsJoint.join('\n')
32
+ }
@@ -1,365 +1,7 @@
1
1
  'use strict'
2
2
 
3
- import { UNIT } from '../config'
4
-
5
- const ENV = process.env.NODE_ENV
6
-
7
- export const isString = arg => typeof arg === 'string'
8
-
9
- export const isArray = arg => Array.isArray(arg)
10
-
11
- export const isObject = arg => {
12
- if (arg === null) return false
13
- return (typeof arg === 'object') && (arg.constructor === Object)
14
- }
15
-
16
- export const isObjectLike = arg => {
17
- if (arg === null) return false
18
- return (typeof arg === 'object')
19
- }
20
-
21
- export const merge = (obj, original) => {
22
- for (const e in original) {
23
- const objProp = obj[e]
24
- const originalProp = original[e]
25
- if (objProp === undefined) {
26
- obj[e] = originalProp
27
- }
28
- }
29
- return obj
30
- }
31
-
32
- export const deepMerge = (obj, obj2) => {
33
- for (const e in obj2) {
34
- const objProp = obj[e]
35
- const obj2Prop = obj2[e]
36
- if (objProp === undefined) {
37
- obj[e] = obj2Prop
38
- } else if (isObjectLike(objProp) && isObject(obj2Prop)) {
39
- deepMerge(objProp, obj2Prop)
40
- }
41
- }
42
- return obj
43
- }
44
-
45
- export const colorStringToRgbaArray = color => {
46
- if (color === '') return
47
- if (color.toLowerCase() === 'transparent') return [0, 0, 0, 0]
48
-
49
- // convert #RGB and #RGBA to #RRGGBB and #RRGGBBAA
50
- if (color[0] === '#') {
51
- if (color.length < 7) {
52
- color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3] + (color.length > 4 ? color[4] + color[4] : '')
53
- } return [parseInt(color.substr(1, 2), 16),
54
- parseInt(color.substr(3, 2), 16),
55
- parseInt(color.substr(5, 2), 16),
56
- color.length > 7 ? parseInt(color.substr(7, 2), 16) / 255 : 1]
57
- }
58
-
59
- // convert named colors
60
- if (color.indexOf('rgb') === -1) {
61
- // intentionally use unknown tag to lower chances of css rule override with !important
62
- const elem = document.body.appendChild(document.createElement('fictum'))
63
- // this flag tested on chrome 59, ff 53, ie9, ie10, ie11, edge 14
64
- const flag = 'rgb(1, 2, 3)'
65
- elem.style.color = flag
66
- // color set failed - some monstrous css rule is probably taking over the color of our object
67
- if (elem.style.color !== flag) return
68
- elem.style.color = color
69
- if (elem.style.color === flag || elem.style.color === '') return // color parse failed
70
- color = window.getComputedStyle(elem).color
71
- document.body.removeChild(elem)
72
- }
73
-
74
- // convert 'rgb(R,G,B)' to 'rgb(R,G,B,A)' which looks awful but will pass the regxep below
75
- if (color.indexOf('rgb') === 0) {
76
- if (color.indexOf('rgba') === -1) color = `${color}, 1`
77
- return color.match(/[\.\d]+/g).map(a => +a) // eslint-disable-line
78
- }
79
- }
80
-
81
- export const mixTwoColors = (colorA, colorB, range = 0.5) => {
82
- colorA = colorStringToRgbaArray(colorA)
83
- colorB = colorStringToRgbaArray(colorB)
84
- return mixTwoRgba(colorA, colorB, range)
85
- }
86
-
87
- export const hexToRgb = (hex, alpha = 1) => {
88
- const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
89
- return `rgb(${r},${g},${b})`
90
- }
91
-
92
- export const hexToRgbArray = (hex, alpha = 1) => {
93
- const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
94
- return [r, g, b]
95
- }
96
-
97
- export const rgbToHex = (r, g, b) => {
98
- return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
99
- }
100
-
101
- export const rgbArrayToHex = ([r, g, b]) => {
102
- return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
103
- }
104
-
105
- export const hexToRgba = (hex, alpha = 1) => {
106
- const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
107
- return `rgba(${r},${g},${b},${alpha})`
108
- }
109
-
110
- export const mixTwoRgb = (colorA, colorB, range = 0.5) => {
111
- const arr = []
112
- for (let i = 0; i < 3; i++) {
113
- arr[i] = Math.round(
114
- colorA[i] + (
115
- (colorB[i] - colorA[i]) * range
116
- )
117
- )
118
- }
119
- return `rgb(${arr})`
120
- }
121
-
122
- // export const rgbToHSL = (r, g, b) => {
123
- // console.log(r, g, b)
124
- // r /= 255
125
- // g /= 255
126
- // b /= 255
127
- // const l = Math.max(r, g, b)
128
- // const s = l - Math.min(r, g, b)
129
- // const h = s
130
- // ? l === r
131
- // ? (g - b) / s
132
- // : l === g
133
- // ? 2 + (b - r) / s
134
- // : 4 + (r - g) / s
135
- // : 0
136
- // return [
137
- // 60 * h < 0 ? 60 * h + 360 : 60 * h,
138
- // 100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),
139
- // (100 * (2 * l - s)) / 2
140
- // ]
141
- // }
142
-
143
- // export const hslToRgb = (h, s, l) => {
144
- // console.log(h, s, l)
145
- // const a = s * Math.min(l, 1 - l)
146
- // const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)
147
- // return [f(0), f(8), f(4)].map(v => v * 1000)
148
- // }
149
-
150
- export const changeLightness = (delta, hsl) => {
151
- const [hue, saturation, lightness] = hsl
152
-
153
- const newLightness = Math.max(
154
- 0,
155
- Math.min(100, lightness + parseFloat(delta))
156
- )
157
-
158
- return [hue, saturation, newLightness]
159
- }
160
-
161
- export const rgbToHSL = (r, g, b) => {
162
- const a = Math.max(r, g, b); const n = a - Math.min(r, g, b); const f = (1 - Math.abs(a + a - n - 1))
163
- const h = n && ((a == r) ? (g - b) / n : ((a == g) ? 2 + (b - r) / n : 4 + (r - g) / n)) //eslint-disable-line
164
- return [60 * (h < 0 ? h + 6 : h), f ? n / f : 0, (a + a - n) / 2]
165
- }
166
-
167
- export const hslToRgb = (h, s, l,
168
- a = s * Math.min(l, 1 - l),
169
- f = (n, k = (n + h / 30) % 12) => l - a * Math.max(
170
- Math.min(k - 3, 9 - k, 1), -1
171
- )
172
- ) => [f(0), f(8), f(4)]
173
-
174
- export const getColorShade = (col, amt) => {
175
- const num = parseInt(col, 16)
176
-
177
- let r = (num >> 16) + amt
178
-
179
- if (r > 255) r = 255
180
- else if (r < 0) r = 0
181
-
182
- let b = ((num >> 8) & 0x00FF) + amt
183
-
184
- if (b > 255) b = 255
185
- else if (b < 0) b = 0
186
-
187
- let g = (num & 0x0000FF) + amt
188
-
189
- if (g > 255) g = 255
190
- else if (g < 0) g = 0
191
-
192
- return (g | (b << 8) | (r << 16)).toString(16)
193
- }
194
-
195
- export const mixTwoRgba = (colorA, colorB, range = 0.5) => {
196
- const arr = []
197
- for (let i = 0; i < 4; i++) {
198
- const round = (i === 3) ? x => x : Math.round
199
- arr[i] = round(
200
- (colorA[i] + (
201
- (colorB[i] - colorA[i]) * range
202
- ))
203
- )
204
- }
205
- return `rgba(${arr})`
206
- }
207
-
208
- export const opacify = (color, opacity) => {
209
- const arr = colorStringToRgbaArray(color)
210
- if (!arr) {
211
- if (ENV === 'test' || ENV === 'development') console.warn(color + 'color is not rgba')
212
- return
213
- }
214
- arr[3] = opacity
215
- return `rgba(${arr})`
216
- }
217
-
218
- export const getDefaultOrFirstKey = (LIBRARY, key) => {
219
- if (LIBRARY[key]) return LIBRARY[key].value
220
- if (LIBRARY.default) return LIBRARY[LIBRARY.default].value
221
- return LIBRARY[Object.keys(LIBRARY)[0]].value
222
- }
223
-
224
- export const getFontFormat = url => url.split(/[#?]/)[0].split('.').pop().trim()
225
-
226
- export const setCustomFont = (name, weight, url) => `@font-face {
227
- font-family: '${name}';
228
- font-style: normal;
229
- font-weight: ${weight};
230
- src: url('${url}') format('${getFontFormat(url)}');
231
- }`
232
- // src: url('${url}') format('${getFontFormat(url)}');
233
-
234
- export const getFontFaceEach = (name, weightsObject) => {
235
- const keys = Object.keys(weightsObject)
236
- const weightsJoint = keys.map(key => {
237
- const { fontWeight, url } = weightsObject[key]
238
- return setCustomFont(name, fontWeight, url)
239
- })
240
- return weightsJoint.join('\n')
241
- }
242
-
243
- export const getFontFace = LIBRARY => {
244
- const keys = Object.keys(LIBRARY)
245
- const fontsJoint = keys.map(key => getFontFaceEach(key, LIBRARY[key].value))
246
- return fontsJoint.join('\n')
247
- }
248
-
249
- export const numToLetterMap = {
250
- '-6': 'U',
251
- '-5': 'V',
252
- '-4': 'W',
253
- '-3': 'X',
254
- '-2': 'Y',
255
- '-1': 'Z',
256
- 0: 'A',
257
- 1: 'B',
258
- 2: 'C',
259
- 3: 'D',
260
- 4: 'E',
261
- 5: 'F',
262
- 6: 'G',
263
- 7: 'H',
264
- 8: 'I',
265
- 9: 'J',
266
- 10: 'K',
267
- 11: 'L',
268
- 12: 'M',
269
- 13: 'N',
270
- 14: 'O',
271
- 15: 'P'
272
- }
273
-
274
- const setSequenceValue = ({ key, variable, value, scaling, state, index }) => {
275
- state.sequence[variable] = {
276
- key,
277
- decimal: Math.round(value * 100) / 100,
278
- val: Math.round(value),
279
- scaling,
280
- index
281
- }
282
- state.scales[variable] = scaling
283
- }
284
-
285
- export const generateSubSequence = ({ key, base, value, ratio, variable, state, index }) => {
286
- const next = value * ratio
287
- const smallscale = (next - value) / ratio
288
-
289
- const valueRounded = Math.round(value)
290
- const nextRounded = Math.round(next)
291
- const diffRounded = nextRounded - valueRounded
292
-
293
- let arr = []
294
- const first = next - smallscale
295
- const second = value + smallscale
296
- const middle = (first + second) / 2
297
- if (diffRounded > 100) arr = [first, middle, second]
298
- else arr = [first, second]
299
- // else if (diffRounded > 2) arr = [first, second]
300
- // else if (diffRounded > 1) arr = [middle]
301
-
302
- arr.map((v, k) => {
303
- const scaling = Math.round(v / base * 1000) / 1000
304
- const newVar = variable + (k + 1)
305
-
306
- return setSequenceValue({ key: key + (k + 1), variable: newVar, value: v, scaling, state, index: index + (k + 1) / 10 })
307
- })
308
- }
309
-
310
- export const generateSequence = ({ type, base, ratio, range, subSequence, ...state }) => {
311
- const n = Math.abs(range[0]) + Math.abs(range[1])
312
- const prefix = '--' + type + '-'
313
- for (let i = 0; i <= n; i++) {
314
- const key = range[1] - i
315
- const letterKey = numToLetterMap[key]
316
- const value = base * Math.pow(ratio, key)
317
- const scaling = Math.round(value / base * 1000) / 1000
318
- const variable = prefix + letterKey
319
-
320
- setSequenceValue({ key: letterKey, variable, value, scaling, state, index: key })
321
-
322
- if (subSequence) generateSubSequence({ key: letterKey, base, value, ratio, variable, state, index: key })
323
- }
324
- return state
325
- }
326
-
327
- export const fallBack = ({ type, prop, val = 'A', prefix = '--font-size-', unit = UNIT.default }) => {
328
- if (typeof val !== 'string') console.warn(prop, val, 'is not a string')
329
-
330
- if (val === '-' || val === '') return ({ })
331
- if (val === 'none' || val === 'auto' || val === 'fit-content' || val === 'min-content' || val === 'max-content') return ({ [prop]: val })
332
-
333
- // const startsWithLetterRegex = /^[a-zA-Z]/i
334
- const startsWithLetterRegex = /^-?[a-zA-Z]/i
335
- // const hasLetter = /[A-Za-z]+/.test(val)
336
- const startsWithLetter = startsWithLetterRegex.test(val)
337
- if (!startsWithLetter) return ({ [prop]: val })
338
-
339
- const letterVal = val.toUpperCase()
340
- const isNegative = letterVal.slice(0, 1) === '-' ? '-' : ''
341
- const simplyLetterVal = isNegative ? letterVal.slice(1) : letterVal
342
-
343
- const value = type ? type[prefix + simplyLetterVal] : null
344
- if (!value) return console.warn('can\'t find', type, prefix + simplyLetterVal, simplyLetterVal)
345
-
346
- return ({
347
- [prop]: isNegative + value.val + value.unit,
348
- [prop]: isNegative + value.scaling + 'em'
349
- })
350
- }
351
-
352
- export const Arrayize = val => {
353
- const isString = typeof val === 'string'
354
- if (isString) return val.split(' ')
355
- if (isObject(val)) return Object.keys(val).map(v => val[v])
356
- if (isArray(val)) return val
357
- }
358
-
359
- export const findHeadings = (TYPOGRAPHY) => {
360
- const { h1Matches, type, sequence } = TYPOGRAPHY
361
- return new Array(6).fill(null).map((_, i) => {
362
- const findLetter = numToLetterMap[h1Matches - i]
363
- return sequence[`--${type}-${findLetter}`]
364
- })
365
- }
3
+ export * from './object'
4
+ export * from './color'
5
+ export * from './font'
6
+ export * from './sequence'
7
+ export * from './setVariables'
@@ -0,0 +1,46 @@
1
+ 'use strict'
2
+
3
+ export const isString = arg => typeof arg === 'string'
4
+
5
+ export const isArray = arg => Array.isArray(arg)
6
+
7
+ export const isObject = arg => {
8
+ if (arg === null) return false
9
+ return (typeof arg === 'object') && (arg.constructor === Object)
10
+ }
11
+
12
+ export const isObjectLike = arg => {
13
+ if (arg === null) return false
14
+ return (typeof arg === 'object')
15
+ }
16
+
17
+ export const merge = (obj, original) => {
18
+ for (const e in original) {
19
+ const objProp = obj[e]
20
+ const originalProp = original[e]
21
+ if (objProp === undefined) {
22
+ obj[e] = originalProp
23
+ }
24
+ }
25
+ return obj
26
+ }
27
+
28
+ export const deepMerge = (obj, obj2) => {
29
+ for (const e in obj2) {
30
+ const objProp = obj[e]
31
+ const obj2Prop = obj2[e]
32
+ if (objProp === undefined) {
33
+ obj[e] = obj2Prop
34
+ } else if (isObjectLike(objProp) && isObject(obj2Prop)) {
35
+ deepMerge(objProp, obj2Prop)
36
+ }
37
+ }
38
+ return obj
39
+ }
40
+
41
+ export const Arrayize = val => {
42
+ const isString = typeof val === 'string'
43
+ if (isString) return val.split(' ')
44
+ if (isObject(val)) return Object.keys(val).map(v => val[v])
45
+ if (isArray(val)) return val
46
+ }
@@ -0,0 +1,117 @@
1
+ 'use strict'
2
+
3
+ import { UNIT } from '../config'
4
+
5
+ export const numToLetterMap = {
6
+ '-6': 'U',
7
+ '-5': 'V',
8
+ '-4': 'W',
9
+ '-3': 'X',
10
+ '-2': 'Y',
11
+ '-1': 'Z',
12
+ 0: 'A',
13
+ 1: 'B',
14
+ 2: 'C',
15
+ 3: 'D',
16
+ 4: 'E',
17
+ 5: 'F',
18
+ 6: 'G',
19
+ 7: 'H',
20
+ 8: 'I',
21
+ 9: 'J',
22
+ 10: 'K',
23
+ 11: 'L',
24
+ 12: 'M',
25
+ 13: 'N',
26
+ 14: 'O',
27
+ 15: 'P'
28
+ }
29
+
30
+ const setSequenceValue = ({ key, variable, value, scaling, state, index }) => {
31
+ state.sequence[variable] = {
32
+ key,
33
+ decimal: Math.round(value * 100) / 100,
34
+ val: Math.round(value),
35
+ scaling,
36
+ index
37
+ }
38
+ state.scales[variable] = scaling
39
+ }
40
+
41
+ export const generateSubSequence = ({ key, base, value, ratio, variable, state, index }) => {
42
+ const next = value * ratio
43
+ const smallscale = (next - value) / ratio
44
+
45
+ const valueRounded = Math.round(value)
46
+ const nextRounded = Math.round(next)
47
+ const diffRounded = nextRounded - valueRounded
48
+
49
+ let arr = []
50
+ const first = next - smallscale
51
+ const second = value + smallscale
52
+ const middle = (first + second) / 2
53
+ if (diffRounded > 100) arr = [first, middle, second]
54
+ else arr = [first, second]
55
+ // else if (diffRounded > 2) arr = [first, second]
56
+ // else if (diffRounded > 1) arr = [middle]
57
+
58
+ arr.map((v, k) => {
59
+ const scaling = Math.round(v / base * 1000) / 1000
60
+ const newVar = variable + (k + 1)
61
+
62
+ return setSequenceValue({ key: key + (k + 1), variable: newVar, value: v, scaling, state, index: index + (k + 1) / 10 })
63
+ })
64
+ }
65
+
66
+ export const generateSequence = ({ type, base, ratio, range, subSequence, ...state }) => {
67
+ const n = Math.abs(range[0]) + Math.abs(range[1])
68
+ const prefix = '--' + type + '-'
69
+ for (let i = 0; i <= n; i++) {
70
+ const key = range[1] - i
71
+ const letterKey = numToLetterMap[key]
72
+ const value = base * Math.pow(ratio, key)
73
+ const scaling = Math.round(value / base * 1000) / 1000
74
+ const variable = prefix + letterKey
75
+
76
+ setSequenceValue({ key: letterKey, variable, value, scaling, state, index: key })
77
+
78
+ if (subSequence) generateSubSequence({ key: letterKey, base, value, ratio, variable, state, index: key })
79
+ }
80
+ return state
81
+ }
82
+
83
+ export const fallBack = ({ type, prop, val = 'A', prefix = '--font-size-', unit = UNIT.default }) => {
84
+ if (typeof val !== 'string') console.warn(prop, val, 'is not a string')
85
+
86
+ if (val === '-' || val === '') return ({ })
87
+ if (val === 'none' || val === 'auto' || val === 'fit-content' || val === 'min-content' || val === 'max-content') return ({ [prop]: val })
88
+
89
+ // const startsWithLetterRegex = /^[a-zA-Z]/i
90
+ const startsWithLetterRegex = /^-?[a-zA-Z]/i
91
+ // const hasLetter = /[A-Za-z]+/.test(val)
92
+ const startsWithLetter = startsWithLetterRegex.test(val)
93
+ if (!startsWithLetter) return ({ [prop]: val })
94
+
95
+ const letterVal = val.toUpperCase()
96
+ const isNegative = letterVal.slice(0, 1) === '-' ? '-' : ''
97
+ const simplyLetterVal = isNegative ? letterVal.slice(1) : letterVal
98
+
99
+ const value = type ? type[prefix + simplyLetterVal] : null
100
+ if (!value) return console.warn('can\'t find', type, prefix + simplyLetterVal, simplyLetterVal)
101
+
102
+ if (unit === 'ms' || unit === 's') {
103
+ return ({ [prop]: isNegative + value.val + value.unit })
104
+ }
105
+ return ({
106
+ [prop]: isNegative + value.val + value.unit,
107
+ [prop]: isNegative + value.scaling + 'em'
108
+ })
109
+ }
110
+
111
+ export const findHeadings = (TYPOGRAPHY) => {
112
+ const { h1Matches, type, sequence } = TYPOGRAPHY
113
+ return new Array(6).fill(null).map((_, i) => {
114
+ const findLetter = numToLetterMap[h1Matches - i]
115
+ return sequence[`--${type}-${findLetter}`]
116
+ })
117
+ }
@@ -0,0 +1,18 @@
1
+ 'use strict'
2
+
3
+ import { CSS_VARS } from '../factory'
4
+ import { isObjectLike } from './object'
5
+
6
+ export const setVariables = (result, key) => {
7
+ // CSS_VARS[result.var] =
8
+ if (isObjectLike(result.value)) {
9
+ // console.group(key)
10
+ // for (const key in result.value) {
11
+ // console.log(key, result.value[key])
12
+ // }
13
+ // console.log(result)
14
+ // console.groupEnd(key)
15
+ } else {
16
+ CSS_VARS[result.var] = result.value
17
+ }
18
+ }
@@ -1,9 +0,0 @@
1
- 'use strict'
2
-
3
- import base from '../base'
4
-
5
- const create = (what, params, preset) => {
6
- base[what] = preset(params)
7
- }
8
-
9
- export default { create }
@@ -1,40 +0,0 @@
1
- 'use strict'
2
-
3
- import { themeMap } from '../config/theme'
4
-
5
- // var pairAsInvert = (scheme, referenced) => cx(scheme, referenced)
6
-
7
- const mapThemeCSS = scheme => {
8
- let str = ''
9
- for (const prop in scheme) {
10
- const mappedProp = themeMap[prop]
11
- const value = scheme[prop]
12
- if (mappedProp && value) {
13
- str += `${mappedProp}: ${value}`
14
- }
15
- }
16
- return str
17
- }
18
-
19
- const generateTheme = scheme => {
20
- const { helpers, inverse } = scheme
21
-
22
- let rule = `
23
- ${mapThemeCSS(scheme)}
24
- `
25
-
26
- if (inverse) {
27
- rule += `&.inverse { ${inverse} }`
28
- }
29
-
30
- if (helpers) {
31
- for (const prop in helpers) {
32
- const value = helpers[prop]
33
- rule += `.${prop} { ${value} }`
34
- }
35
- }
36
-
37
- return rule
38
- }
39
-
40
- export default { generateTheme }
@@ -1,3 +0,0 @@
1
- 'use strict'
2
-
3
- export * from './set'
@@ -1,5 +0,0 @@
1
- 'use strict'
2
-
3
- const global = ''
4
-
5
- export default global