@symbo.ls/scratch 0.3.17 → 0.3.20

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.17",
5
+ "version": "0.3.20",
6
6
  "files": [
7
7
  "src"
8
8
  ],
@@ -2,20 +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'
20
-
21
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,25 +106,29 @@ const getThemeValue = theme => {
104
106
 
105
107
  export const getTheme = value => {
106
108
  const { 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
+
107
119
  if (isObjectLike(value) && value[1]) {
108
120
  const themeName = value[0]
109
121
  const subThemeName = value[1]
110
122
  const { helpers, variants, state } = THEME[themeName]
123
+
111
124
  if (variants && variants[subThemeName]) return getThemeValue(variants[subThemeName])
112
125
  if (helpers && helpers[subThemeName]) return getThemeValue(helpers[subThemeName])
113
126
  if (state && state[subThemeName]) return getThemeValue(state[subThemeName])
114
127
  } else if (isObject(value)) return setThemeValue(value)
115
- else if (isString(value) && THEME[value]) return getThemeValue(THEME[value])
116
128
 
117
129
  if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose) console.warn('Can\'t find theme', value)
118
130
  }
119
131
 
120
- const setPrefersScheme = (theme, key, variant, themeValue) => {
121
- const result = getTheme(variant)
122
- themeValue[`@media (prefers-color-scheme: ${key})`] = result
123
- if (isObject(variant) && !variant.value) variant.value = result
124
- }
125
-
126
132
  const setInverseTheme = (theme, variant, value) => {
127
133
  if (isObject(variant)) {
128
134
  theme.variants.inverse.value = setThemeValue(variant)
@@ -137,25 +143,39 @@ const setInverseTheme = (theme, variant, value) => {
137
143
  }
138
144
  }
139
145
 
140
- const goThroughHelpers = (theme, value) => {
141
- const { helpers } = theme
142
- if (!helpers) return
143
- 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)
144
156
  keys.map(key => {
145
- const helper = helpers[key]
146
- if (isString(helper)) helpers[key] = CONFIG.THEME[helper]
147
- else getThemeValue(helpers[key])
157
+ const variant = state[key]
158
+ setPseudo(theme, key, variant, value)
148
159
  return theme
149
160
  })
150
161
  return theme
151
162
  }
152
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
+
153
171
  const goThroughVariants = (theme, value) => {
154
172
  const { variants } = theme
155
173
  if (!variants) return
156
174
  const keys = Object.keys(variants)
157
175
  keys.map(key => {
158
176
  const variant = variants[key]
177
+ // console.log('=========')
178
+ // console.log(theme, key, variant, value)
159
179
  if (key === 'dark' || key === 'light') setPrefersScheme(theme, key, variant, value)
160
180
  if (key === 'inverse') setInverseTheme(theme, variant, value)
161
181
  return theme
@@ -163,19 +183,14 @@ const goThroughVariants = (theme, value) => {
163
183
  return theme
164
184
  }
165
185
 
166
- const setPseudo = (theme, key, variant, themeValue) => {
167
- const result = getTheme(variant)
168
- themeValue[`&:${key}`] = result
169
- if (isObject(variant) && !variant.value) variant.value = result
170
- }
171
-
172
- const goThroughInteractiveStates = (theme, value) => {
173
- const { state } = theme
174
- if (!state) return
175
- const keys = Object.keys(state)
186
+ const goThroughHelpers = (theme, value) => {
187
+ const { helpers } = theme
188
+ if (!helpers) return
189
+ const keys = Object.keys(helpers)
176
190
  keys.map(key => {
177
- const variant = state[key]
178
- setPseudo(theme, key, variant, value)
191
+ const helper = helpers[key]
192
+ if (isString(helper)) helpers[key] = CONFIG.THEME[helper]
193
+ else getThemeValue(helpers[key])
179
194
  return theme
180
195
  })
181
196
  return theme
@@ -226,10 +241,12 @@ export const SETTERS = {
226
241
  font_family: setFontFamily,
227
242
  theme: setTheme,
228
243
  typography: setSameValue,
244
+ cases: setCases,
229
245
  spacing: setSameValue,
230
246
  media: setSameValue,
231
- cases: setCases,
232
- icons: setSameValue
247
+ timing: setSameValue,
248
+ icons: setSameValue,
249
+ reset: setSameValue
233
250
  }
234
251
 
235
252
  /**
@@ -243,8 +260,15 @@ export const setValue = (FACTORY_NAME, value, key) => {
243
260
  const factoryName = FACTORY_NAME.toLowerCase()
244
261
  const FACTORY = CONFIG[FACTORY_NAME]
245
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
+
246
269
  FACTORY[key] = result
247
- CSS_VARS[result.var] = result.value
270
+ setVariables(result, key)
271
+
248
272
  return FACTORY
249
273
  }
250
274
 
@@ -257,7 +281,15 @@ export const setEach = (factoryName, props) => {
257
281
  }
258
282
 
259
283
  export const set = recivedConfig => {
260
- 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
+
261
293
  const keys = Object.keys(config)
262
294
  keys.map(key => setEach(key, config[key]))
263
295
 
@@ -265,11 +297,9 @@ export const set = recivedConfig => {
265
297
  applyTypographySequence()
266
298
  applySpacingSequence()
267
299
  applyDocument()
300
+ applyTimingSequence()
301
+ applyReset()
268
302
 
269
- CONFIG.verbose = verbose
270
- if ((ENV === 'test' || ENV === 'development') && CONFIG.verbose) console.log(CONFIG)
271
-
303
+ CONFIG.VARS = CSS_VARS
272
304
  return CONFIG
273
305
  }
274
-
275
- 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,33 @@
1
+ 'use strict'
2
+
3
+ export const getDefaultOrFirstKey = (LIBRARY, key) => {
4
+ if (LIBRARY[key]) return LIBRARY[key].value
5
+ if (LIBRARY.isDefault) return LIBRARY[LIBRARY.isDefault].value
6
+ const hasValue = Object.keys(LIBRARY)[0]
7
+ return hasValue && LIBRARY[hasValue] && LIBRARY[hasValue].value
8
+ }
9
+
10
+ export const getFontFormat = url => url.split(/[#?]/)[0].split('.').pop().trim()
11
+
12
+ export const setCustomFont = (name, weight, url) => `@font-face {
13
+ font-family: '${name}';
14
+ font-style: normal;
15
+ font-weight: ${weight};
16
+ src: url('${url}') format('${getFontFormat(url)}');
17
+ }`
18
+ // src: url('${url}') format('${getFontFormat(url)}');
19
+
20
+ export const getFontFaceEach = (name, weightsObject) => {
21
+ const keys = Object.keys(weightsObject)
22
+ const weightsJoint = keys.map(key => {
23
+ const { fontWeight, url } = weightsObject[key]
24
+ return setCustomFont(name, fontWeight, url)
25
+ })
26
+ return weightsJoint.join('\n')
27
+ }
28
+
29
+ export const getFontFace = LIBRARY => {
30
+ const keys = Object.keys(LIBRARY)
31
+ const fontsJoint = keys.map(key => getFontFaceEach(key, LIBRARY[key].value))
32
+ return fontsJoint.join('\n')
33
+ }
@@ -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