@startupjs-ui/core 0.1.1 → 0.1.3

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.
@@ -0,0 +1,83 @@
1
+ $UI.media = {
2
+ mobile: 480px,
3
+ tablet: 768px,
4
+ desktop: 1024px,
5
+ wide: 1280px
6
+ }
7
+
8
+ $UI.gutters = {
9
+ xs: 0.5u,
10
+ s: 1u,
11
+ m: 2u,
12
+ l: 3u,
13
+ xl: 4u,
14
+ xxl: 5u
15
+ }
16
+
17
+ $UI.defaultFontSize = 'body2'
18
+
19
+ $UI.fontFamilies = {
20
+ web: {
21
+ normal: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, 'Helvetica Neue', sans-serif",
22
+ heading: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, 'Helvetica Neue', sans-serif"
23
+ },
24
+ android: {
25
+ normal: 'System',
26
+ heading: 'System'
27
+ },
28
+ ios: {
29
+ normal: 'System',
30
+ heading: 'System'
31
+ }
32
+ }
33
+
34
+ $UI.fontWeights = {
35
+ normal: 400,
36
+ normalBold: 600,
37
+ heading: 400,
38
+ headingBold: 600
39
+ }
40
+
41
+ $UI.fontSizes = {
42
+ xs: 1.25u, // DEPRECATED
43
+ s: 1.5u, // DEPRECATED
44
+ m: 1.75u, // DEPRECATED
45
+ l: 2u, // DEPRECATED
46
+ xl: 2.5u, // DEPRECATED
47
+ xxl: 3u, // DEPRECATED
48
+ xxxl: 4.5u, // DEPRECATED
49
+ xxxxl: 6u, // DEPRECATED
50
+ xxxxxl: 9u, // DEPRECATED
51
+ h1: 9u,
52
+ h2: 6u,
53
+ h3: 4.5u,
54
+ h4: 3u,
55
+ h5: 2.5u,
56
+ h6: 2u,
57
+ description: 1.75u, // DEPRECATED
58
+ body1: 2u,
59
+ body2: 1.75u,
60
+ caption: 1.5u
61
+ }
62
+
63
+ $UI.lineHeights = {
64
+ xs: 1.75u, // DEPRECATED
65
+ s: 2u, // DEPRECATED
66
+ m: 2.5u, // DEPRECATED
67
+ l: 3u, // DEPRECATED
68
+ xl: 3.5u, // DEPRECATED
69
+ xxl: 4u, // DEPRECATED
70
+ xxxl: 6u, // DEPRECATED
71
+ xxxxl: 8u, // DEPRECATED
72
+ xxxxxl: 12u, // DEPRECATED
73
+ h1: 12u,
74
+ h2: 8u,
75
+ h3: 6u,
76
+ h4: 4u,
77
+ h5: 3.5u,
78
+ h6: 3u,
79
+ description: 2.5u, // DEPRECATED
80
+ body1: 3u,
81
+ body2: 2.5u,
82
+ caption: 2u
83
+ }
@@ -0,0 +1,109 @@
1
+ export const BaseColors = {
2
+ main: 'main',
3
+ 'bg-main': 'bg-main',
4
+ 'text-main': 'text-main',
5
+ 'border-main': 'border-main',
6
+ primary: 'primary',
7
+ secondary: 'secondary',
8
+ error: 'error',
9
+ success: 'success',
10
+ warning: 'warning',
11
+ info: 'info',
12
+ attention: 'attention'
13
+ }
14
+
15
+ export const BgColors = {
16
+ 'bg-main-subtle': 'bg-main-subtle',
17
+ 'bg-main-subtle-alt': 'bg-main-subtle-alt',
18
+ 'bg-main-strong': 'bg-main-strong',
19
+ 'bg-primary': 'bg-primary',
20
+ 'bg-secondary': 'bg-secondary',
21
+ 'bg-error': 'bg-error',
22
+ 'bg-success': 'bg-success',
23
+ 'bg-warning': 'bg-warning',
24
+ 'bg-info': 'bg-info',
25
+ 'bg-attention': 'bg-attention',
26
+ 'bg-primary-strong': 'bg-primary-strong',
27
+ 'bg-primary-subtle': 'bg-primary-subtle',
28
+ 'bg-primary-transparent': 'bg-primary-transparent',
29
+ 'bg-secondary-subtle': 'bg-secondary-subtle',
30
+ 'bg-error-transparent': 'bg-error-transparent',
31
+ 'bg-success-transparent': 'bg-success-transparent',
32
+ 'bg-warning-transparent': 'bg-warning-transparent'
33
+ }
34
+
35
+ export const TextColors = {
36
+ 'text-description': 'text-description',
37
+ 'text-placeholder': 'text-placeholder',
38
+ 'text-subtle': 'text-subtle',
39
+ 'text-primary': 'text-primary',
40
+ 'text-secondary': 'text-secondary',
41
+ 'text-error': 'text-error',
42
+ 'text-success': 'text-success',
43
+ 'text-warning': 'text-warning',
44
+ 'text-info': 'text-info',
45
+ 'text-attention': 'text-attention',
46
+ 'text-success-strong': 'text-success-strong',
47
+ 'text-info-strong': 'text-info-strong'
48
+ }
49
+
50
+ export const TextOnColors = {
51
+ 'text-on-color': 'text-on-color',
52
+ 'text-on-primary': 'text-on-primary',
53
+ 'text-on-secondary': 'text-on-secondary',
54
+ 'text-on-error': 'text-on-error',
55
+ 'text-on-success': 'text-on-success',
56
+ 'text-on-warning': 'text-on-warning',
57
+ 'text-on-info': 'text-on-info',
58
+ 'text-on-attention': 'text-on-attention'
59
+ }
60
+
61
+ export const BorderColors = {
62
+ 'border-main-strong': 'border-main-strong',
63
+ 'border-main-strong-alt': 'border-main-strong-alt',
64
+ 'border-main-subtle': 'border-main-subtle',
65
+ 'border-primary': 'border-primary',
66
+ 'border-secondary': 'border-secondary',
67
+ 'border-error': 'border-error',
68
+ 'border-success': 'border-success',
69
+ 'border-warning': 'border-warning',
70
+ 'border-info': 'border-info',
71
+ 'border-attention': 'border-attention'
72
+ }
73
+
74
+ export const ShadowColors = {
75
+ 'shadow-main': 'shadow-main',
76
+ 'shadow-main-strong': 'shadow-main-strong',
77
+ 'shadow-main-subtle': 'shadow-main-subtle'
78
+ }
79
+
80
+ export const ComponentColors = {
81
+ '--AutoSuggest-itemBg': '--AutoSuggest-itemBg',
82
+ '--Carousel-arrowWrapperBg': '--Carousel-arrowWrapperBg',
83
+ '--Checkbox-switchBg': '--Checkbox-switchBg',
84
+ '--Checkbox-switchBulletBg': '--Checkbox-switchBulletBg',
85
+ '--Checkbox-switchBulletBg-checked': '--Checkbox-switchBulletBg-checked',
86
+ '--Div-hoverBg': '--Div-hoverBg',
87
+ '--Div-activeBg': '--Div-activeBg',
88
+ '--Div-tooltipBg': '--Div-tooltipBg',
89
+ '--Div-tooltipText': '--Div-tooltipText',
90
+ '--Modal-overlayBg': '--Modal-overlayBg',
91
+ '--InputWrapper-label-color': '--InputWrapper-label-color',
92
+ '--Range-labelBg': '--Range-labelBg',
93
+ '--Range-labelText': '--Range-labelText',
94
+ '--TextInput-text-color': '--TextInput-text-color'
95
+ }
96
+
97
+ const Colors = {
98
+ ...BaseColors,
99
+ ...BgColors,
100
+ ...TextColors,
101
+ ...TextOnColors,
102
+ ...BorderColors,
103
+ ...ShadowColors,
104
+ ...ComponentColors
105
+ }
106
+
107
+ export default Colors
108
+
109
+ export const ColorValues = Object.values(Colors)
@@ -0,0 +1,59 @@
1
+ import { useMemo } from 'react'
2
+ import { $, variables as singletonVariables } from 'startupjs'
3
+ // TODO: Move CssVariables to basic startupjs and also move the singleton variables file to some generic lib
4
+ // so that it's not tightly coupled with our custom stylesheets implementation
5
+ import transformColors from './transformColors'
6
+
7
+ export default function CssVariables ({ meta, clear = true, children }) {
8
+ function setColorScheme (value = '') {
9
+ document.documentElement.style.colorScheme = value
10
+ }
11
+
12
+ useMemo(() => {
13
+ const isWeb = $.system.platform.get() === 'web'
14
+ const isDark = isWeb ? document.documentElement.style.colorScheme === 'dark' : false
15
+
16
+ if (!meta) {
17
+ // default color scheme is light so we reset it to default if there are no overrides
18
+ if (isDark) setColorScheme()
19
+ return
20
+ }
21
+
22
+ const variables = transformColors(meta)
23
+
24
+ // set new variables
25
+ for (const variableName in variables) {
26
+ if (variables[variableName] !== singletonVariables[variableName]) {
27
+ singletonVariables[variableName] = variables[variableName]
28
+ }
29
+ }
30
+
31
+ // remove old variables
32
+ for (const variableName in singletonVariables) {
33
+ if (variables[variableName] == null) {
34
+ delete singletonVariables[variableName]
35
+ }
36
+ }
37
+
38
+ if (isWeb) {
39
+ if (singletonVariables['--color-bg-main']?.isDark?.()) {
40
+ if (!isDark) setColorScheme('dark')
41
+ } else {
42
+ setColorScheme()
43
+ }
44
+ }
45
+
46
+ // clear dynamic theme when destroyed
47
+ if (clear) {
48
+ return () => {
49
+ if (isWeb) setColorScheme()
50
+
51
+ for (const variableName in singletonVariables) {
52
+ delete singletonVariables[variableName]
53
+ }
54
+ }
55
+ }
56
+ }, [JSON.stringify(meta)])
57
+
58
+ return children || null
59
+ }
@@ -0,0 +1,20 @@
1
+ import { TheColor } from './TheColor'
2
+ import { getPaletteMeta, prepareColorsObject } from './helpers'
3
+ import defaultPalette from './palette.json'
4
+
5
+ export default class Palette {
6
+ constructor (palette = defaultPalette) {
7
+ this.colors = palette
8
+
9
+ Object.assign(this, getPaletteMeta(palette))
10
+ }
11
+
12
+ generateColors = (overrides, componentOverrides) => {
13
+ const { low, high, middle } = this
14
+ return prepareColorsObject(this.colors, this.Color, { overrides, componentOverrides, low, middle, high })
15
+ }
16
+
17
+ Color = (name, level, { alpha } = {}) => {
18
+ return new TheColor(name, level, this.colors, { alpha })
19
+ }
20
+ }
@@ -0,0 +1,9 @@
1
+ import React, { useContext } from 'react'
2
+
3
+ const StyleContext = React.createContext()
4
+
5
+ export default StyleContext
6
+
7
+ export function useStyle () {
8
+ return useContext(StyleContext)
9
+ }
@@ -0,0 +1,76 @@
1
+ import { getPaletteMeta, rgba, getPaletteLength } from './helpers'
2
+
3
+ const BLACK = '#000000'
4
+ const WHITE = '#ffffff'
5
+ export class TheColor {
6
+ constructor (name, level, palette, { alpha } = {}) {
7
+ const isBlackOrWhite = this.isBlack(name, level, palette) || this.isWhite(name, level)
8
+
9
+ if (!isBlackOrWhite && !palette?.[name]?.[level]) {
10
+ throw Error(`Color ${name} level ${level} not found in palette ${JSON.stringify(palette, null, 2)}`)
11
+ }
12
+
13
+ const meta = {
14
+ name,
15
+ level,
16
+ palette,
17
+ ...getPaletteMeta(palette)
18
+ }
19
+
20
+ if (alpha != null) meta.alpha = alpha
21
+
22
+ Object.assign(this, meta)
23
+ }
24
+
25
+ clone (name, level, palette, { alpha } = {}) {
26
+ return new TheColor(
27
+ name ?? this.name,
28
+ level ?? this.level,
29
+ palette ?? this.palette,
30
+ { alpha: alpha ?? this.alpha }
31
+ )
32
+ }
33
+
34
+ toString () {
35
+ let stringColor
36
+
37
+ if (this.isBlack()) {
38
+ stringColor = BLACK
39
+ } else if (this.isWhite()) {
40
+ stringColor = WHITE
41
+ } else {
42
+ stringColor = this.palette[this.name][this.level]
43
+ }
44
+
45
+ return this.alpha != null ? rgba(stringColor, this.alpha) : stringColor
46
+ }
47
+
48
+ isEqual (other) {
49
+ return this.name === other.name && this.level === other.level && this.alpha === other.alpha
50
+ }
51
+
52
+ isBlack (name = this.name, level = this.level, palette = this.palette) {
53
+ return name === 'main' && level === getPaletteLength(palette)
54
+ }
55
+
56
+ isWhite (name = this.name, level = this.level) {
57
+ return name === 'main' && level === -1
58
+ }
59
+
60
+ setAlpha (alpha) {
61
+ const { name, level, palette, ...rest } = this
62
+ return this.clone(name, level, palette, { ...rest, alpha })
63
+ }
64
+
65
+ isDark () { return this.level > this.middle }
66
+ isLight () { return !this.isDark() }
67
+ highContrast () { return this.clone(this.name, this.isLight() ? this.high : this.low) }
68
+ stronger (offset = 1) { return this.subtler(-offset) }
69
+
70
+ subtler (offset = 1) {
71
+ if (this.isDark()) offset = -offset
72
+ let level = this.level + offset
73
+ level = Math.min(this.high + 1, Math.max(this.low - 1, level))
74
+ return this.clone(this.name, level)
75
+ }
76
+ }
@@ -0,0 +1,5 @@
1
+ import React from 'react'
2
+
3
+ const ThemeContext = React.createContext()
4
+
5
+ export default ThemeContext
@@ -0,0 +1,3 @@
1
+ import ThemeContext from './ThemeContext'
2
+
3
+ export default ThemeContext.Provider
@@ -0,0 +1,3 @@
1
+ import Palette from './Palette'
2
+
3
+ export default new Palette()
@@ -0,0 +1,9 @@
1
+ // TODO: Figure out if we would want to transition default UI colors to be dynamic
2
+ import palette from './defaultPalette'
3
+ import transformColors from './transformColors'
4
+
5
+ export default { ...getColors() }
6
+
7
+ function getColors () {
8
+ return transformColors(palette.generateColors())
9
+ }
@@ -0,0 +1,12 @@
1
+ import { prepareColorsObject, getPaletteMeta } from './helpers'
2
+ import { TheColor } from './TheColor'
3
+
4
+ // generate meaningful colors from palette
5
+ export default function generateColors (palette, overrides = {}) {
6
+ if (!palette) throw Error('palette is required')
7
+
8
+ const Color = (name, level, { alpha } = {}) => new TheColor(name, level, palette, { alpha })
9
+ const { low, middle, high } = getPaletteMeta(palette)
10
+
11
+ return prepareColorsObject(palette, Color, { overrides, low, middle, high })
12
+ }
@@ -0,0 +1,10 @@
1
+ import { variables as singletonVariables, defaultVariables } from 'startupjs'
2
+
3
+ export default function getCssVariable (cssVarName, { convertToString = true } = {}) {
4
+ if (!/^--/.test(cssVarName)) throw Error('[getCssVariable]: Incorrect name format - must begin with --')
5
+
6
+ const colorInstance = singletonVariables[cssVarName] || defaultVariables[cssVarName]
7
+ if (!colorInstance) return
8
+
9
+ return convertToString ? colorInstance.toString() : colorInstance
10
+ }
@@ -0,0 +1,265 @@
1
+ // refs:
2
+ // https://accessiblepalette.com/?lightness=98,93.3,88.6,79.9,71.2,60.5,49.8,38.4,27,15.6&e94c49=1,0&F1903C=1,-10&f3e203=1,-15&89BF1D=0,0&64c273=0,15&007DCC=0,0&808080=0,0&EAE8DE=0,0&768092=0,0
3
+ // https://www.ibm.com/design/language/color/
4
+ import Colors from './Colors'
5
+ import { TheColor } from './TheColor'
6
+ import getCssVariable from './getCssVariable'
7
+
8
+ export function getPaletteMeta (palette) {
9
+ const res = {}
10
+ const high = getPaletteLength(palette) - 1
11
+ res.low = 0 // lightest colorful color
12
+ res.high = high // darkest colorful color
13
+ res.middle = Math.floor(high / 2) // last light color
14
+ return res
15
+ }
16
+
17
+ export function rgbToHex (r, g, b) {
18
+ // Ensure that the input values are within the valid range
19
+ r = Math.max(0, Math.min(255, r))
20
+ g = Math.max(0, Math.min(255, g))
21
+ b = Math.max(0, Math.min(255, b))
22
+
23
+ // Convert the RGB values to hexadecimal
24
+ const hexR = r.toString(16).padStart(2, '0')
25
+ const hexG = g.toString(16).padStart(2, '0')
26
+ const hexB = b.toString(16).padStart(2, '0')
27
+
28
+ return `#${hexR}${hexG}${hexB}`
29
+ }
30
+
31
+ // Extract RGB values from RGB or RGBA string
32
+ export function extractRGB (str) {
33
+ const match = str.match(/(\d+\.?\d*|\.\d+)/g) // improved regex to match decimals
34
+ if (!match) return []
35
+ return match.map(Number)
36
+ }
37
+
38
+ export function rgba (color, alpha) {
39
+ if (typeof alpha !== 'number' || alpha < 0 || alpha > 1) {
40
+ throw new Error('Invalid alpha value. It should be between 0 and 1.')
41
+ }
42
+
43
+ // Convert hex to RGB
44
+ const hexToRgb = (hex) => {
45
+ if (hex.startsWith('#')) hex = hex.slice(1)
46
+ const bigint = parseInt(hex, 16)
47
+ const r = (bigint >> 16) & 255
48
+ const g = (bigint >> 8) & 255
49
+ const b = bigint & 255
50
+ return [r, g, b]
51
+ }
52
+
53
+ if (color.startsWith('#')) {
54
+ const [r, g, b] = hexToRgb(color)
55
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`
56
+ } else if (color.startsWith('rgb')) {
57
+ const values = extractRGB(color)
58
+ if (values.length === 3 || values.length === 4) {
59
+ return `rgba(${values[0]}, ${values[1]}, ${values[2]}, ${alpha})`
60
+ }
61
+ }
62
+
63
+ throw new Error('Invalid color format. Supported formats are hex, rgb, and rgba.')
64
+ }
65
+
66
+ // find color in palette by the color value itself
67
+ // (note that hex/rgb/rgba matters -- it's considered to be different colors)
68
+ export function findColorInPalette (color, palette) {
69
+ let alpha
70
+
71
+ if (color.includes('rgb')) {
72
+ const rgbValues = extractRGB(color)
73
+ const [r, g, b, a] = rgbValues
74
+ if (a != null) alpha = a
75
+ color = rgbToHex(r, g, b)
76
+ }
77
+
78
+ let foundName
79
+ let foundLevel
80
+ for (const name in palette) {
81
+ const level = palette[name].indexOf(color)
82
+ if (level !== -1) {
83
+ foundName = name
84
+ foundLevel = level
85
+ break
86
+ }
87
+ }
88
+
89
+ return [foundName, foundLevel, alpha]
90
+ }
91
+
92
+ export function getPaletteLength (palette) {
93
+ return Object.values(palette)[0].length
94
+ }
95
+
96
+ export function transformOverrides (overrides, palette, Color) {
97
+ if (!overrides) return
98
+
99
+ const res = {}
100
+
101
+ for (const colorName in overrides) {
102
+ const color = overrides[colorName]
103
+ // Set color as it is if it's the instance
104
+ if (color instanceof TheColor) {
105
+ res[colorName] = color
106
+ // Get color value from existing (needed for static overrides).
107
+ // First check already overriden colors in local 'res' variable to allow reuse of overriden variables immediately
108
+ // e.g.,
109
+ // :root
110
+ // --palette-primary-4: #000099
111
+ // --color-primary: var(--palette-primary-4)
112
+ // --color-secondary: var(--palette-error-4)
113
+ // --color-bg-main: var(--color-primary-bg)
114
+ } else if (/^var\(--/.test(color)) {
115
+ const colorVar = color.replace(/var\(\s*(--[A-Za-z0-9_-]+)\s*\)/, (match, varName) => {
116
+ return varName
117
+ })
118
+ const colorValue = res[colorVar] || getCssVariable(colorVar, { convertToString: false })
119
+ if (!colorValue) throw Error(`'${colorName}' does not exist.`)
120
+ res[colorName] = colorValue.clone()
121
+ // Find color in a palette by hex or rgb(a) string
122
+ } else {
123
+ const [paletteColorName, level, alpha] = findColorInPalette(color, palette)
124
+ if (!paletteColorName) throw Error(`'${colorName}' does not exist in palette. You can only pass a color from palette.`)
125
+ res[colorName] = Color(paletteColorName, level, { alpha })
126
+ }
127
+ }
128
+
129
+ return res
130
+ }
131
+
132
+ /* eslint-disable dot-notation, no-multi-spaces */
133
+ export function prepareColorsObject (
134
+ palette,
135
+ Color,
136
+ {
137
+ overrides = {},
138
+ componentOverrides,
139
+ high,
140
+ low,
141
+ middle
142
+ }
143
+ ) {
144
+ const C = {}
145
+ const transformedOverrides = transformOverrides(overrides, palette, Color)
146
+ if (transformedOverrides) Object.assign(C, transformedOverrides)
147
+
148
+ // base colors
149
+ // we don't want shadow to change to a light color in a dark theme, that's why we are creating it as
150
+ // a separate color
151
+ C[Colors['shadow-main']] ??= Color('main', high + 1, { alpha: 0.2 })
152
+ C[Colors.main] ??= Color('main', low)
153
+ C[Colors.primary] ??= Color('primary', middle)
154
+ C[Colors.secondary] ??= Color('secondary', high - 2)
155
+ C[Colors.error] ??= Color('error', middle)
156
+ C[Colors.success] ??= Color('success', middle)
157
+ C[Colors.warning] ??= Color('warning', middle - 2)
158
+ C[Colors.info] ??= Color('info', middle - 1)
159
+ C[Colors.attention] ??= Color('attention', middle)
160
+
161
+ // all other colors are generated from the base colors
162
+
163
+ // shadow colors
164
+ C[Colors['shadow-main-strong']] ??= C[Colors['shadow-main']].setAlpha(0.15)
165
+ C[Colors['shadow-main-subtle']] ??= C[Colors['shadow-main']].setAlpha(0.25)
166
+
167
+ // main bg colors
168
+ C[Colors['bg-main']] ??= C[Colors.main]
169
+ C[Colors['bg-primary']] ??= C[Colors.primary]
170
+ C[Colors['bg-secondary']] ??= C[Colors.secondary]
171
+ C[Colors['bg-error']] ??= C[Colors.error]
172
+ C[Colors['bg-success']] ??= C[Colors.success]
173
+ C[Colors['bg-warning']] ??= C[Colors.warning]
174
+ C[Colors['bg-info']] ??= C[Colors.info]
175
+ C[Colors['bg-attention']] ??= C[Colors.attention]
176
+
177
+ // extra bg colors
178
+ C[Colors['bg-main-subtle']] ??= C[Colors['bg-main']].subtler(1)
179
+ C[Colors['bg-main-subtle-alt']] ??= C[Colors['bg-main']].subtler(2)
180
+ C[Colors['bg-main-strong']] ??= C[Colors['bg-main']].stronger(1)
181
+ C[Colors['bg-primary-strong']] ??= C[Colors.primary].stronger(4)
182
+ C[Colors['bg-primary-subtle']] ??= C[Colors.primary].subtler(3)
183
+ C[Colors['bg-primary-transparent']] ??= C[Colors.primary].setAlpha(0.05)
184
+ C[Colors['bg-secondary-subtle']] ??= C[Colors.secondary].highContrast()
185
+ C[Colors['bg-error-transparent']] ??= C[Colors.error].setAlpha(0.05)
186
+ C[Colors['bg-success-transparent']] ??= C[Colors.success].setAlpha(0.05)
187
+ C[Colors['bg-warning-transparent']] ??= C[Colors.warning].setAlpha(0.05)
188
+
189
+ // text
190
+ C[Colors['text-main']] ??= C[Colors.main].subtler(7)
191
+ C[Colors['text-description']] ??= C[Colors['text-main']].subtler(2)
192
+ C[Colors['text-placeholder']] ??= C[Colors['text-main']].subtler(4)
193
+ C[Colors['text-subtle']] ??= C[Colors['text-main']].subtler(4)
194
+ C[Colors['text-primary']] ??= C[Colors.primary]
195
+ C[Colors['text-secondary']] ??= C[Colors.secondary]
196
+ C[Colors['text-error']] ??= C[Colors.error]
197
+ C[Colors['text-success']] ??= C[Colors.success]
198
+ C[Colors['text-warning']] ??= C[Colors.warning]
199
+ C[Colors['text-info']] ??= C[Colors.info]
200
+ C[Colors['text-attention']] ??= C[Colors.attention]
201
+
202
+ // extra text colors
203
+ C[Colors['text-success-strong']] ??= C[Colors.success].stronger(2)
204
+ C[Colors['text-info-strong']] ??= C[Colors.info].stronger(2)
205
+
206
+ // text on different backgrounds
207
+ C[Colors['text-on-color']] ??= C[Colors.main]
208
+ C[Colors['text-on-primary']] ??= C[Colors.primary].stronger(4)
209
+ C[Colors['text-on-secondary']] ??= C[Colors.secondary].highContrast()
210
+ C[Colors['text-on-error']] ??= C[Colors.error].stronger(4)
211
+ C[Colors['text-on-success']] ??= C[Colors.success].stronger(4)
212
+ C[Colors['text-on-warning']] ??= C[Colors['text-on-color']]
213
+ C[Colors['text-on-info']] ??= C[Colors.info].stronger(3)
214
+ C[Colors['text-on-attention']] ??= C[Colors.attention].stronger(4)
215
+
216
+ // border
217
+ C[Colors['border-main']] ??= C[Colors.main].subtler(2)
218
+ C[Colors['border-main-strong']] ??= C[Colors['border-main']].stronger(3)
219
+ C[Colors['border-primary']] ??= C[Colors.primary]
220
+ C[Colors['border-secondary']] ??= C[Colors.secondary]
221
+ C[Colors['border-error']] ??= C[Colors.error]
222
+ C[Colors['border-success']] ??= C[Colors.success]
223
+ C[Colors['border-warning']] ??= C[Colors.warning]
224
+ C[Colors['border-info']] ??= C[Colors.info]
225
+ C[Colors['border-attention']] ??= C[Colors.attention]
226
+
227
+ // extra border colors
228
+ C[Colors['border-main-subtle']] ??= C[Colors['border-main']].subtler(1)
229
+ C[Colors['border-main-strong-alt']] ??= C[Colors['border-main']].stronger(1)
230
+
231
+ // generate component colors
232
+ const CC = {}
233
+
234
+ if (componentOverrides) {
235
+ const transformedOverrides = transformOverrides(componentOverrides, palette, Color)
236
+ if (transformedOverrides) Object.assign(CC, transformedOverrides)
237
+ }
238
+
239
+ CC[Colors['--AutoSuggest-itemBg']] ??= C[Colors['bg-main']].highContrast().setAlpha(0.05)
240
+ CC[Colors['--Carousel-arrowWrapperBg']] ??= Color('main', high, { alpha: 0.1 })
241
+ CC[Colors['--Checkbox-switchBg']] ??= Color('main', middle)
242
+ CC[Colors['--Checkbox-switchBulletBg']] ??= Color('main', low)
243
+ CC[Colors['--Checkbox-switchBulletBg-checked']] ??= C[Colors['text-on-primary']]
244
+ CC[Colors['--Div-hoverBg']] ??= C[Colors['bg-main']].highContrast().setAlpha(0.05)
245
+ CC[Colors['--Div-activeBg']] ??= C[Colors['bg-main']].highContrast().setAlpha(0.2)
246
+ CC[Colors['--Div-tooltipBg']] ??= C[Colors['bg-main']].subtler(7)
247
+ CC[Colors['--Div-tooltipText']] ??= C[Colors['text-main']].subtler(7)
248
+ CC[Colors['--Modal-overlayBg']] ??= Color('main', high - 2, { alpha: 0.25 })
249
+ CC[Colors['--InputWrapper-label-color']] ??= C[Colors['text-secondary']]
250
+ CC[Colors['--Range-labelBg']] ??= C[Colors['bg-main']].subtler(7)
251
+ CC[Colors['--Range-labelText']] ??= C[Colors['text-main']].subtler(7)
252
+ CC[Colors['--TextInput-text-color']] ??= C[Colors['text-secondary']]
253
+
254
+ // add palette colors
255
+ const P = {}
256
+ for (const colorName in palette) {
257
+ const colors = palette[colorName]
258
+ for (let i = 0; i < colors.length; i++) {
259
+ P[`${colorName}-${i}`] = Color(colorName, i)
260
+ }
261
+ }
262
+
263
+ return { colors: C, palette: P, componentColors: CC }
264
+ }
265
+ /* eslint-enable dot-notation, no-multi-spaces */