aboutsummaryrefslogtreecommitdiff
path: root/src/services/theme_data/theme_data_3.service.js
blob: 39a9998d7d25a4d920b00a45f5d2583da138782d (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
import Underlay from 'src/components/underlay.style.js'
import Panel from 'src/components/panel.style.js'
import Button from 'src/components/button.style.js'
import Text from 'src/components/text.style.js'
import Icon from 'src/components/icon.style.js'

const root = Underlay
const components = {
  Underlay,
  Panel,
  Button,
  Text,
  Icon
}

// This gives you an array of arrays of all possible unique (i.e. order-insensitive) combinations
export const getAllPossibleCombinations = (array) => {
  const combos = [array.map(x => [x])]
  for (let comboSize = 2; comboSize <= array.length; comboSize++) {
    const previous = combos[combos.length - 1]
    const selfSet = new Set()
    const newCombos = previous.map(self => {
      self.forEach(x => selfSet.add(x))
      const nonSelf = array.filter(x => !selfSet.has(x))
      return nonSelf.map(x => [...self, x])
    })
    const flatCombos = newCombos.reduce((acc, x) => [...acc, ...x], [])
    combos.push(flatCombos)
  }
  return combos.reduce((acc, x) => [...acc, ...x], [])
}

export const ruleToSelector = (rule) => {
  const component = components[rule.component]
  const { states, variants, selector } = component

  const applicableStates = (rule.state.filter(x => x !== 'normal') || []).map(state => states[state])

  const applicableVariantName = (rule.variant || 'normal')
  let applicableVariant = ''
  if (applicableVariantName !== 'normal') {
    applicableVariant = variants[applicableVariantName]
  }

  const selectors = [selector, applicableVariant, ...applicableStates]
    .toSorted((a, b) => {
      if (a.startsWith(':')) return 1
      else return -1
    })
    .join('')

  if (rule.parent) {
    return ruleToSelector(rule.parent) + ' ' + selectors
  }
  return selectors
}

export const init = (ruleset) => {
  const rootName = root.name
  const rules = []
  const rulesByComponent = {}

  const addRule = (rule) => {
    rules.push(rule)
    rulesByComponent[rule.component] = rulesByComponent[rule.component] || []
    rulesByComponent.push(rule)
  }

  ruleset.forEach(rule => {

  })

  const processInnerComponent = (component, parent) => {
    const {
      validInnerComponents = [],
      states: originalStates = {},
      variants: originalVariants = {},
      name
    } = component

    const states = { normal: '', ...originalStates }
    const variants = { normal: '', ...originalVariants }
    const innerComponents = validInnerComponents.map(name => components[name])

    const stateCombinations = getAllPossibleCombinations(Object.keys(states))
    const stateVariantCombination = Object.keys(variants).map(variant => {
      return stateCombinations.map(state => ({ variant, state }))
    }).reduce((acc, x) => [...acc, ...x], [])

    stateVariantCombination.forEach(combination => {
      // addRule(({
      //   parent,
      //   component: component.name,
      //   state: combination.state,
      //   variant: combination.variant
      // }))

      innerComponents.forEach(innerComponent => processInnerComponent(innerComponent, { parent, component: name, ...combination }))
    })
  }

  processInnerComponent(components[rootName])
  return rules
}