aboutsummaryrefslogtreecommitdiff
path: root/src/services/theme_data/css_utils.js
blob: 8395f6a7700d95361e8acee3dd37867bbdacba1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { convert } from 'chromatism'

import { rgba2css } from '../color_convert/color_convert.js'

export const getCssColorString = (color, alpha) => rgba2css({ ...convert(color).rgb, a: alpha })

export const getCssShadow = (input, usesDropShadow) => {
  if (input.length === 0) {
    return 'none'
  }

  return input
    .filter(_ => usesDropShadow ? _.inset : _)
    .map((shad) => [
      shad.x,
      shad.y,
      shad.blur,
      shad.spread
    ].map(_ => _ + 'px ').concat([
      getCssColorString(shad.color, shad.alpha),
      shad.inset ? 'inset' : ''
    ]).join(' ')).join(', ')
}

export const getCssShadowFilter = (input) => {
  if (input.length === 0) {
    return 'none'
  }

  return input
  // drop-shadow doesn't support inset or spread
    .filter((shad) => !shad.inset && Number(shad.spread) === 0)
    .map((shad) => [
      shad.x,
      shad.y,
      // drop-shadow's blur is twice as strong compared to box-shadow
      shad.blur / 2
    ].map(_ => _ + 'px').concat([
      getCssColorString(shad.color, shad.alpha)
    ]).join(' '))
    .map(_ => `drop-shadow(${_})`)
    .join(' ')
}

export const getCssRules = (rules) => rules.map(rule => {
  let selector = rule.selector
  if (!selector) {
    selector = 'body'
  }
  const header = selector + ' {'
  const footer = '}'

  const virtualDirectives = Object.entries(rule.virtualDirectives || {}).map(([k, v]) => {
    return '  ' + k + ': ' + v
  }).join(';\n')

  let directives
  if (rule.component !== 'Root') {
    directives = Object.entries(rule.directives).map(([k, v]) => {
      switch (k) {
        case 'roundness': {
          return '  ' + [
            '--roundness: ' + v + 'px'
          ].join(';\n  ')
        }
        case 'shadow': {
          return '  ' + [
            '--shadow: ' + getCssShadow(rule.dynamicVars.shadow),
            '--shadowFilter: ' + getCssShadowFilter(rule.dynamicVars.shadow),
            '--shadowInset: ' + getCssShadow(rule.dynamicVars.shadow, true)
          ].join(';\n  ')
        }
        case 'background': {
          if (v === 'transparent') {
            return [
              rule.directives.backgroundNoCssColor !== 'yes' ? ('background-color: ' + v) : '',
              '  --background: ' + v
            ].filter(x => x).join(';\n')
          }
          const color = getCssColorString(rule.dynamicVars.background, rule.directives.opacity)
          return [
            rule.directives.backgroundNoCssColor !== 'yes' ? ('background-color: ' + color) : '',
            '  --background: ' + color
          ].filter(x => x).join(';\n')
        }
        case 'textColor': {
          if (rule.directives.textNoCssColor === 'yes') { return '' }
          return 'color: ' + v
        }
        default:
          if (k.startsWith('--')) {
            const [type] = v.split('|').map(x => x.trim()) // woah, Extreme!
            switch (type) {
              case 'color':
                return k + ': ' + rgba2css(rule.dynamicVars[k])
              default:
                return ''
            }
          }
          return ''
      }
    }).filter(x => x).map(x => '  ' + x).join(';\n')
  } else {
    directives = {}
  }

  return [
    header,
    directives + ';',
    (!rule.virtual && rule.directives.textNoCssColor !== 'yes') ? '  color: var(--text);' : '',
    '',
    virtualDirectives,
    footer
  ].join('\n')
}).filter(x => x)