@symbo.ls/scratch 3.14.2 → 3.14.4
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/CHANGELOG.md +19 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/defaultConfig/animation.js +1 -0
- package/dist/cjs/src/defaultConfig/cases.js +1 -0
- package/dist/cjs/src/defaultConfig/class.js +1 -0
- package/dist/cjs/src/defaultConfig/color.js +1 -0
- package/dist/cjs/src/defaultConfig/document.js +1 -0
- package/dist/cjs/src/defaultConfig/font-family.js +1 -0
- package/dist/cjs/src/defaultConfig/font.js +1 -0
- package/dist/cjs/src/defaultConfig/grid.js +1 -0
- package/dist/cjs/src/defaultConfig/icons.js +1 -0
- package/dist/cjs/src/defaultConfig/index.js +1 -0
- package/dist/cjs/src/defaultConfig/media.js +1 -0
- package/dist/cjs/src/defaultConfig/responsive.js +1 -0
- package/dist/cjs/src/defaultConfig/sequence.js +1 -0
- package/dist/cjs/src/defaultConfig/shadow.js +1 -0
- package/dist/cjs/src/defaultConfig/spacing.js +1 -0
- package/dist/cjs/src/defaultConfig/svg.js +1 -0
- package/dist/cjs/src/defaultConfig/templates.js +1 -0
- package/dist/cjs/src/defaultConfig/theme.js +1 -0
- package/dist/cjs/src/defaultConfig/timing.js +1 -0
- package/dist/cjs/src/defaultConfig/typography.js +1 -0
- package/dist/cjs/src/defaultConfig/unit.js +1 -0
- package/dist/cjs/src/factory.js +1 -0
- package/dist/cjs/src/index.js +1 -0
- package/dist/cjs/src/set.js +1 -0
- package/dist/cjs/src/system/color.js +1 -0
- package/dist/cjs/src/system/document.js +1 -0
- package/dist/cjs/src/system/font.js +1 -0
- package/dist/cjs/src/system/index.js +1 -0
- package/dist/cjs/src/system/reset.js +1 -0
- package/dist/cjs/src/system/shadow.js +1 -0
- package/dist/cjs/src/system/spacing.js +1 -0
- package/dist/cjs/src/system/svg.js +1 -0
- package/dist/cjs/src/system/theme.js +1 -0
- package/dist/cjs/src/system/timing.js +1 -0
- package/dist/cjs/src/system/typography.js +1 -0
- package/dist/cjs/src/tests/index.js +1 -0
- package/dist/cjs/src/transforms/index.js +1 -0
- package/dist/cjs/src/utils/color.js +1 -0
- package/dist/cjs/src/utils/font.js +9 -0
- package/dist/cjs/src/utils/index.js +1 -0
- package/dist/cjs/src/utils/sequence.js +1 -0
- package/dist/cjs/src/utils/sprite.js +1 -0
- package/dist/cjs/src/utils/theme.js +1 -0
- package/dist/cjs/src/utils/unit.js +1 -0
- package/dist/cjs/src/utils/var.js +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/src/defaultConfig/animation.js +1 -0
- package/dist/esm/src/defaultConfig/cases.js +1 -0
- package/dist/esm/src/defaultConfig/class.js +1 -0
- package/dist/esm/src/defaultConfig/color.js +1 -0
- package/dist/esm/src/defaultConfig/document.js +1 -0
- package/dist/esm/src/defaultConfig/font-family.js +1 -0
- package/dist/esm/src/defaultConfig/font.js +1 -0
- package/dist/esm/src/defaultConfig/grid.js +1 -0
- package/dist/esm/src/defaultConfig/icons.js +1 -0
- package/dist/esm/src/defaultConfig/index.js +1 -0
- package/dist/esm/src/defaultConfig/media.js +1 -0
- package/dist/esm/src/defaultConfig/responsive.js +1 -0
- package/dist/esm/src/defaultConfig/sequence.js +1 -0
- package/dist/esm/src/defaultConfig/shadow.js +1 -0
- package/dist/esm/src/defaultConfig/spacing.js +1 -0
- package/dist/esm/src/defaultConfig/svg.js +1 -0
- package/dist/esm/src/defaultConfig/templates.js +1 -0
- package/dist/esm/src/defaultConfig/theme.js +1 -0
- package/dist/esm/src/defaultConfig/timing.js +1 -0
- package/dist/esm/src/defaultConfig/typography.js +1 -0
- package/dist/esm/src/defaultConfig/unit.js +1 -0
- package/dist/esm/src/factory.js +1 -0
- package/dist/esm/src/index.js +1 -0
- package/dist/esm/src/set.js +1 -0
- package/dist/esm/src/system/color.js +1 -0
- package/dist/esm/src/system/document.js +1 -0
- package/dist/esm/src/system/font.js +1 -0
- package/dist/esm/src/system/index.js +1 -0
- package/dist/esm/src/system/reset.js +1 -0
- package/dist/esm/src/system/shadow.js +1 -0
- package/dist/esm/src/system/spacing.js +1 -0
- package/dist/esm/src/system/svg.js +1 -0
- package/dist/esm/src/system/theme.js +1 -0
- package/dist/esm/src/system/timing.js +1 -0
- package/dist/esm/src/system/typography.js +1 -0
- package/dist/esm/src/tests/index.js +1 -0
- package/dist/esm/src/transforms/index.js +1 -0
- package/dist/esm/src/utils/color.js +1 -0
- package/dist/esm/src/utils/font.js +9 -0
- package/dist/esm/src/utils/index.js +1 -0
- package/dist/esm/src/utils/sequence.js +1 -0
- package/dist/esm/src/utils/sprite.js +1 -0
- package/dist/esm/src/utils/theme.js +1 -0
- package/dist/esm/src/utils/unit.js +1 -0
- package/dist/esm/src/utils/var.js +1 -0
- package/package.json +18 -17
- package/index.js +0 -1
- package/src/defaultConfig/animation.js +0 -3
- package/src/defaultConfig/cases.js +0 -3
- package/src/defaultConfig/class.js +0 -6
- package/src/defaultConfig/color.js +0 -9
- package/src/defaultConfig/document.js +0 -3
- package/src/defaultConfig/font-family.js +0 -15
- package/src/defaultConfig/font.js +0 -12
- package/src/defaultConfig/grid.js +0 -5
- package/src/defaultConfig/icons.js +0 -4
- package/src/defaultConfig/index.js +0 -24
- package/src/defaultConfig/media.js +0 -10
- package/src/defaultConfig/responsive.js +0 -29
- package/src/defaultConfig/sequence.js +0 -24
- package/src/defaultConfig/shadow.js +0 -3
- package/src/defaultConfig/spacing.js +0 -19
- package/src/defaultConfig/svg.js +0 -4
- package/src/defaultConfig/templates.js +0 -3
- package/src/defaultConfig/theme.js +0 -13
- package/src/defaultConfig/timing.js +0 -18
- package/src/defaultConfig/typography.js +0 -22
- package/src/defaultConfig/unit.js +0 -5
- package/src/factory.js +0 -135
- package/src/index.js +0 -24
- package/src/set.js +0 -353
- package/src/system/color.js +0 -327
- package/src/system/document.js +0 -16
- package/src/system/font.js +0 -66
- package/src/system/index.js +0 -12
- package/src/system/reset.js +0 -119
- package/src/system/shadow.js +0 -107
- package/src/system/spacing.js +0 -152
- package/src/system/svg.js +0 -132
- package/src/system/theme.js +0 -454
- package/src/system/timing.js +0 -32
- package/src/system/typography.js +0 -110
- package/src/tests/index.js +0 -4
- package/src/transforms/index.js +0 -270
- package/src/utils/color.js +0 -269
- package/src/utils/font.js +0 -116
- package/src/utils/index.js +0 -9
- package/src/utils/sequence.js +0 -386
- package/src/utils/sprite.js +0 -107
- package/src/utils/theme.js +0 -8
- package/src/utils/unit.js +0 -72
- package/src/utils/var.js +0 -129
package/src/transforms/index.js
DELETED
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { isString, isObject, exec } from '@symbo.ls/utils'
|
|
4
|
-
import { getActiveConfig } from '../factory.js'
|
|
5
|
-
import {
|
|
6
|
-
getSpacingByKey,
|
|
7
|
-
getColor,
|
|
8
|
-
getShadow,
|
|
9
|
-
getMediaColor,
|
|
10
|
-
getTimingByKey,
|
|
11
|
-
getTimingFunction,
|
|
12
|
-
getSpacingBasedOnRatio,
|
|
13
|
-
checkIfBoxSize,
|
|
14
|
-
splitSpacedValue
|
|
15
|
-
} from '../system/index.js'
|
|
16
|
-
import {
|
|
17
|
-
getFnPrefixAndValue,
|
|
18
|
-
isResolvedColor,
|
|
19
|
-
isCSSVar,
|
|
20
|
-
CSS_NATIVE_COLOR_REGEX,
|
|
21
|
-
splitTopLevelCommas,
|
|
22
|
-
parseColorToken
|
|
23
|
-
} from '../utils/index.js'
|
|
24
|
-
|
|
25
|
-
const BORDER_STYLES = new Set([
|
|
26
|
-
'none', 'hidden', 'dotted', 'dashed', 'solid', 'double',
|
|
27
|
-
'groove', 'ridge', 'inset', 'outset', 'initial'
|
|
28
|
-
])
|
|
29
|
-
|
|
30
|
-
const GRADIENT_KEYWORDS = new Set([
|
|
31
|
-
'to', 'top', 'bottom', 'left', 'right', 'center', 'at',
|
|
32
|
-
'circle', 'ellipse', 'closest-side', 'farthest-side',
|
|
33
|
-
'closest-corner', 'farthest-corner'
|
|
34
|
-
])
|
|
35
|
-
const isBorderStyle = (str) => BORDER_STYLES.has(str)
|
|
36
|
-
|
|
37
|
-
export const transformBorder = (border) => {
|
|
38
|
-
const str = border + ''
|
|
39
|
-
|
|
40
|
-
// CSS passthrough: native CSS color syntax
|
|
41
|
-
if (CSS_NATIVE_COLOR_REGEX.test(str)) return str
|
|
42
|
-
|
|
43
|
-
// Simple CSS keywords
|
|
44
|
-
const trimmed = str.trim()
|
|
45
|
-
if (trimmed === 'none' || trimmed === '0' || trimmed === 'initial' || trimmed === 'inherit' || trimmed === 'unset') return str
|
|
46
|
-
|
|
47
|
-
// Space-separated tokens (CSS-like syntax)
|
|
48
|
-
const tokens = str.split(/\s+/)
|
|
49
|
-
|
|
50
|
-
return tokens
|
|
51
|
-
.map((v) => {
|
|
52
|
-
v = v.trim()
|
|
53
|
-
if (!v) return ''
|
|
54
|
-
if (isCSSVar(v)) return `var(${v})`
|
|
55
|
-
if (isBorderStyle(v)) return v
|
|
56
|
-
if (/^\d/.test(v) || v === '0') return v
|
|
57
|
-
// Try color resolution
|
|
58
|
-
const color = getColor(v)
|
|
59
|
-
if (isResolvedColor(color)) return color
|
|
60
|
-
// Try spacing key
|
|
61
|
-
const spacing = getSpacingByKey(v, 'border')
|
|
62
|
-
if (spacing && spacing.border) return spacing.border
|
|
63
|
-
return v
|
|
64
|
-
})
|
|
65
|
-
.join(' ')
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const transformTextStroke = (stroke) => {
|
|
69
|
-
// CSS passthrough
|
|
70
|
-
if (CSS_NATIVE_COLOR_REGEX.test(stroke)) return stroke
|
|
71
|
-
|
|
72
|
-
return stroke
|
|
73
|
-
.split(/\s+/)
|
|
74
|
-
.map((v) => {
|
|
75
|
-
v = v.trim()
|
|
76
|
-
if (!v) return ''
|
|
77
|
-
if (isCSSVar(v)) return `var(${v})`
|
|
78
|
-
if (/^\d/.test(v) || v.includes('px') || v === '0') return v
|
|
79
|
-
const color = getColor(v)
|
|
80
|
-
if (isResolvedColor(color)) return color
|
|
81
|
-
return v
|
|
82
|
-
})
|
|
83
|
-
.join(' ')
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export const transformShadow = (sh, globalTheme) => getShadow(sh, globalTheme)
|
|
87
|
-
|
|
88
|
-
export const transformBoxShadow = (shadows, globalTheme) => {
|
|
89
|
-
// CSS passthrough: native CSS color syntax
|
|
90
|
-
if (CSS_NATIVE_COLOR_REGEX.test(shadows)) return shadows
|
|
91
|
-
|
|
92
|
-
// Split multiple shadows by commas (CSS standard), respecting parentheses
|
|
93
|
-
return splitTopLevelCommas(shadows)
|
|
94
|
-
.map((shadow) => {
|
|
95
|
-
shadow = shadow.trim()
|
|
96
|
-
if (!shadow) return ''
|
|
97
|
-
|
|
98
|
-
// Each shadow: space-separated tokens
|
|
99
|
-
return shadow.split(/\s+/)
|
|
100
|
-
.map((v) => {
|
|
101
|
-
v = v.trim()
|
|
102
|
-
if (!v) return ''
|
|
103
|
-
if (isCSSVar(v)) return `var(${v})`
|
|
104
|
-
if (v === 'inset' || v === 'none') return v
|
|
105
|
-
|
|
106
|
-
// Try color resolution
|
|
107
|
-
const color = getColor(v)
|
|
108
|
-
if (isResolvedColor(color)) {
|
|
109
|
-
const mediaColor = getMediaColor(v, globalTheme)
|
|
110
|
-
if (isObject(mediaColor))
|
|
111
|
-
return Object.values(mediaColor).filter((c) =>
|
|
112
|
-
c.includes(': ' + globalTheme)
|
|
113
|
-
)[0]
|
|
114
|
-
return mediaColor
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// CSS unit values
|
|
118
|
-
if (/^\d/.test(v) || v === '0' || v.includes('px') || v.slice(-2) === 'em') return v
|
|
119
|
-
|
|
120
|
-
// Spacing key
|
|
121
|
-
const spacing = getSpacingByKey(v, 'shadow')
|
|
122
|
-
if (spacing && spacing.shadow) return spacing.shadow
|
|
123
|
-
|
|
124
|
-
return v
|
|
125
|
-
})
|
|
126
|
-
.join(' ')
|
|
127
|
-
})
|
|
128
|
-
.join(', ')
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Resolve Symbols color tokens inside a CSS gradient string.
|
|
133
|
-
* e.g. 'linear-gradient(to bottom, white.97 65%, white.0 100%)'
|
|
134
|
-
* → 'linear-gradient(to bottom, rgba(255, 255, 255, 0.97) 65%, rgba(255, 255, 255, 0.0) 100%)'
|
|
135
|
-
*/
|
|
136
|
-
export const resolveColorsInGradient = (gradient, globalTheme) => {
|
|
137
|
-
// Find the opening paren after the gradient type
|
|
138
|
-
const parenStart = gradient.indexOf('(')
|
|
139
|
-
if (parenStart === -1) return gradient
|
|
140
|
-
|
|
141
|
-
const prefix = gradient.slice(0, parenStart + 1)
|
|
142
|
-
const inner = gradient.slice(parenStart + 1, gradient.lastIndexOf(')'))
|
|
143
|
-
const suffix = ')'
|
|
144
|
-
|
|
145
|
-
// Split by top-level commas (respects nested rgba() etc.)
|
|
146
|
-
const segments = splitTopLevelCommas(inner)
|
|
147
|
-
|
|
148
|
-
const resolved = segments.map((segment) => {
|
|
149
|
-
segment = segment.trim()
|
|
150
|
-
// Split segment into space-separated tokens
|
|
151
|
-
const tokens = segment.split(/\s+/)
|
|
152
|
-
|
|
153
|
-
return tokens.map((token) => {
|
|
154
|
-
if (!token) return token
|
|
155
|
-
// Skip CSS values: percentages, degrees, direction keywords, native colors
|
|
156
|
-
if (/^\d/.test(token) || token === '0') return token
|
|
157
|
-
if (GRADIENT_KEYWORDS.has(token)) return token
|
|
158
|
-
if (token === 'transparent') return token
|
|
159
|
-
if (CSS_NATIVE_COLOR_REGEX.test(token)) return token
|
|
160
|
-
|
|
161
|
-
// Try to resolve as a Symbols color token
|
|
162
|
-
const color = getColor(token)
|
|
163
|
-
if (isResolvedColor(color)) return color
|
|
164
|
-
|
|
165
|
-
return token
|
|
166
|
-
}).join(' ')
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
return prefix + resolved.join(', ') + suffix
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export const transformBackgroundImage = (backgroundImage, globalTheme) => {
|
|
173
|
-
const CONFIG = getActiveConfig()
|
|
174
|
-
return backgroundImage
|
|
175
|
-
.split(', ')
|
|
176
|
-
.map((v) => {
|
|
177
|
-
if (isCSSVar(v)) return `var(${v})`
|
|
178
|
-
if (v.includes('url')) return v
|
|
179
|
-
if (v.includes('gradient')) return resolveColorsInGradient(v, globalTheme)
|
|
180
|
-
else if (CONFIG.gradient[backgroundImage]) {
|
|
181
|
-
return {
|
|
182
|
-
backgroundImage: getMediaColor(
|
|
183
|
-
backgroundImage,
|
|
184
|
-
globalTheme || CONFIG.globalTheme
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
} else if (v.includes('/') || v.startsWith('http') || (v.includes('.') && !parseColorToken(v)))
|
|
188
|
-
return `url(${v})`
|
|
189
|
-
return v
|
|
190
|
-
})
|
|
191
|
-
.join(' ')
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export const transfromGap = (gap) =>
|
|
195
|
-
isString(gap) &&
|
|
196
|
-
gap
|
|
197
|
-
.split(' ')
|
|
198
|
-
.map((v) => getSpacingByKey(v, 'gap').gap)
|
|
199
|
-
.join(' ')
|
|
200
|
-
|
|
201
|
-
export const transformTransition = (transition) => {
|
|
202
|
-
const arr = transition.split(' ')
|
|
203
|
-
|
|
204
|
-
if (!arr.length) return transition
|
|
205
|
-
|
|
206
|
-
return arr
|
|
207
|
-
.map((v) => {
|
|
208
|
-
if (isCSSVar(v)) return `var(${v})`
|
|
209
|
-
if (v.length < 3 || v.includes('ms')) {
|
|
210
|
-
const mapWithSequence = getTimingByKey(v)
|
|
211
|
-
return mapWithSequence.timing || v
|
|
212
|
-
}
|
|
213
|
-
if (getTimingFunction(v)) return getTimingFunction(v)
|
|
214
|
-
return v
|
|
215
|
-
})
|
|
216
|
-
.join(' ')
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export const transformDuration = (duration, props, propertyName) => {
|
|
220
|
-
if (!isString(duration)) return
|
|
221
|
-
return duration
|
|
222
|
-
.split(',')
|
|
223
|
-
.map((v) => getTimingByKey(v).timing || v)
|
|
224
|
-
.join(',')
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export const splitTransition = (transition) => {
|
|
228
|
-
const arr = transition.split(',')
|
|
229
|
-
if (!arr.length) return
|
|
230
|
-
return arr.map(transformTransition).join(',')
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function transformSize(propertyName, val, props = {}, opts = {}) {
|
|
234
|
-
let value = exec.call(this, val || props[propertyName])
|
|
235
|
-
|
|
236
|
-
if (value === undefined || value === null) return
|
|
237
|
-
|
|
238
|
-
let fnPrefix
|
|
239
|
-
if (isString(value)) {
|
|
240
|
-
// has function prefix
|
|
241
|
-
if (value.includes('(')) {
|
|
242
|
-
const fnArr = getFnPrefixAndValue(value)
|
|
243
|
-
fnPrefix = fnArr[0]
|
|
244
|
-
value = fnArr[1]
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const shouldScaleBoxSize = props.scaleBoxSize
|
|
248
|
-
const isBoxSize = checkIfBoxSize(propertyName)
|
|
249
|
-
if (!shouldScaleBoxSize && isBoxSize && !opts.ratio) {
|
|
250
|
-
value = splitSpacedValue(value)
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return opts.ratio
|
|
255
|
-
? getSpacingBasedOnRatio(props, propertyName, value, fnPrefix)
|
|
256
|
-
: getSpacingByKey(value, propertyName, undefined, fnPrefix)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export const transformSizeRatio = (propertyName, val = null, props) => {
|
|
260
|
-
return transformSize(propertyName, val, props, {
|
|
261
|
-
ratio: true
|
|
262
|
-
})
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
export const transformBorderRadius = (radius, props, propertyName) => {
|
|
266
|
-
if (!isString(radius)) return
|
|
267
|
-
return {
|
|
268
|
-
borderRadius: radius.split(' ').map((v, k) => getSpacingBasedOnRatio(props, propertyName, v)[propertyName]).join(' ')
|
|
269
|
-
}
|
|
270
|
-
}
|
package/src/utils/color.js
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
document,
|
|
5
|
-
window,
|
|
6
|
-
isString,
|
|
7
|
-
isNumber,
|
|
8
|
-
isNotProduction
|
|
9
|
-
} from '@symbo.ls/utils'
|
|
10
|
-
|
|
11
|
-
export const colorStringToRgbaArray = color => {
|
|
12
|
-
if (color === '') return [0, 0, 0, 0]
|
|
13
|
-
if (color.toLowerCase() === 'transparent') return [0, 0, 0, 0]
|
|
14
|
-
|
|
15
|
-
// convert #RGB and #RGBA to #RRGGBB and #RRGGBBAA
|
|
16
|
-
if (color[0] === '#') {
|
|
17
|
-
if (color.length < 7) {
|
|
18
|
-
color =
|
|
19
|
-
'#' +
|
|
20
|
-
color[1] +
|
|
21
|
-
color[1] +
|
|
22
|
-
color[2] +
|
|
23
|
-
color[2] +
|
|
24
|
-
color[3] +
|
|
25
|
-
color[3] +
|
|
26
|
-
(color.length > 4 ? color[4] + color[4] : '')
|
|
27
|
-
}
|
|
28
|
-
return [
|
|
29
|
-
parseInt(color.substr(1, 2), 16),
|
|
30
|
-
parseInt(color.substr(3, 2), 16),
|
|
31
|
-
parseInt(color.substr(5, 2), 16),
|
|
32
|
-
color.length > 7 ? parseInt(color.substr(7, 2), 16) / 255 : 1
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// convert named colors
|
|
37
|
-
if (color.indexOf('rgb') === -1) {
|
|
38
|
-
if (document && window) {
|
|
39
|
-
// intentionally use unknown tag to lower chances of css rule override with !important
|
|
40
|
-
const elem = document.body.appendChild(document.createElement('fictum'))
|
|
41
|
-
// this flag tested on chrome 59, ff 53, ie9, ie10, ie11, edge 14
|
|
42
|
-
const flag = 'rgb(1, 2, 3)'
|
|
43
|
-
elem.style.color = flag
|
|
44
|
-
// color set failed - some monstrous css rule is probably taking over the color of our object
|
|
45
|
-
if (elem.style.color !== flag) {
|
|
46
|
-
document.body.removeChild(elem)
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
elem.style.color = color
|
|
50
|
-
if (elem.style.color === flag || elem.style.color === '') {
|
|
51
|
-
document.body.removeChild(elem)
|
|
52
|
-
return [0, 0, 0, 0] // color parse failed
|
|
53
|
-
}
|
|
54
|
-
color = window.getComputedStyle(elem).color
|
|
55
|
-
document.body.removeChild(elem)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// convert 'rgb(R,G,B)' to 'rgb(R,G,B,A)' which looks awful but will pass the regxep below
|
|
60
|
-
if (color.indexOf('rgb') === 0) {
|
|
61
|
-
if (color.indexOf('rgba') === -1) color = `${color}, 1`
|
|
62
|
-
return color.match(/[\.\d]+/g).map(a => +a) // eslint-disable-line
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return [0, 0, 0, 0]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const mixTwoColors = (colorA, colorB, range = 0.5) => {
|
|
69
|
-
colorA = colorStringToRgbaArray(colorA)
|
|
70
|
-
colorB = colorStringToRgbaArray(colorB)
|
|
71
|
-
return mixTwoRgba(colorA, colorB, range)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export const hexToRgb = (hex, alpha = 1) => {
|
|
75
|
-
const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
|
|
76
|
-
return `rgb(${r},${g},${b})`
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const hexToRgbArray = (hex, alpha = 1) => {
|
|
80
|
-
const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
|
|
81
|
-
return [r, g, b]
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export const rgbToHex = (r, g, b) => {
|
|
85
|
-
return '#' + ((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export const rgbArrayToHex = ([r, g, b]) => {
|
|
89
|
-
return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export const hexToRgba = (hex, alpha = 1) => {
|
|
93
|
-
const [r, g, b] = hex.match(/\w\w/g).map(x => parseInt(x, 16))
|
|
94
|
-
return `rgba(${r},${g},${b},${alpha})`
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export const mixTwoRgb = (colorA, colorB, range = 0.5) => {
|
|
98
|
-
const arr = []
|
|
99
|
-
for (let i = 0; i < 3; i++) {
|
|
100
|
-
arr[i] = ~~(colorA[i] + (colorB[i] - colorA[i]) * range)
|
|
101
|
-
}
|
|
102
|
-
return `rgb(${arr})`
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export const changeLightness = (delta, hsl) => {
|
|
106
|
-
const [hue, saturation, lightness] = hsl
|
|
107
|
-
|
|
108
|
-
const newLightness = Math.max(0, Math.min(100, lightness + parseFloat(delta)))
|
|
109
|
-
|
|
110
|
-
return [hue, saturation, newLightness]
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export const rgbToHSL = (r, g, b) => {
|
|
114
|
-
const a = Math.max(r, g, b)
|
|
115
|
-
const n = a - Math.min(r, g, b)
|
|
116
|
-
const f = 1 - Math.abs(a + a - n - 1)
|
|
117
|
-
const h =
|
|
118
|
-
n && (a == r ? (g - b) / n : a == g ? 2 + (b - r) / n : 4 + (r - g) / n) //eslint-disable-line
|
|
119
|
-
return [60 * (h < 0 ? h + 6 : h), f ? n / f : 0, (a + a - n) / 2]
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export const hslToRgb = (
|
|
123
|
-
h,
|
|
124
|
-
s,
|
|
125
|
-
l,
|
|
126
|
-
a = s * Math.min(l, 1 - l),
|
|
127
|
-
f = (n, k = (n + h / 30) % 12) =>
|
|
128
|
-
l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)
|
|
129
|
-
) => [f(0), f(8), f(4)]
|
|
130
|
-
|
|
131
|
-
export const getColorShade = (col, amt) => {
|
|
132
|
-
const num = parseInt(col, 16)
|
|
133
|
-
|
|
134
|
-
let r = (num >> 16) + amt
|
|
135
|
-
|
|
136
|
-
if (r > 255) r = 255
|
|
137
|
-
else if (r < 0) r = 0
|
|
138
|
-
|
|
139
|
-
let b = ((num >> 8) & 0x00ff) + amt
|
|
140
|
-
|
|
141
|
-
if (b > 255) b = 255
|
|
142
|
-
else if (b < 0) b = 0
|
|
143
|
-
|
|
144
|
-
let g = (num & 0x0000ff) + amt
|
|
145
|
-
|
|
146
|
-
if (g > 255) g = 255
|
|
147
|
-
else if (g < 0) g = 0
|
|
148
|
-
|
|
149
|
-
return ((g | (b << 8) | (r << 16)) + 0x1000000).toString(16).slice(1)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export const mixTwoRgba = (colorA, colorB, range = 0.5) => {
|
|
153
|
-
const arr = []
|
|
154
|
-
for (let i = 0; i < 4; i++) {
|
|
155
|
-
const round = i === 3 ? x => x : Math.round
|
|
156
|
-
arr[i] = round(colorA[i] + (colorB[i] - colorA[i]) * range)
|
|
157
|
-
}
|
|
158
|
-
return `rgba(${arr})`
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export const opacify = (color, opacity) => {
|
|
162
|
-
const arr = colorStringToRgbaArray(color)
|
|
163
|
-
if (!arr) {
|
|
164
|
-
if (isNotProduction()) console.warn(color + ' color is not rgba')
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
arr[3] = opacity
|
|
168
|
-
return `rgba(${arr})`
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Check if value is a CSS custom property reference (starts with --)
|
|
172
|
-
export const isCSSVar = (v) => v.charCodeAt(0) === 45 && v.charCodeAt(1) === 45
|
|
173
|
-
|
|
174
|
-
// Regex for CSS native color values - signals passthrough
|
|
175
|
-
export const CSS_NATIVE_COLOR_REGEX = /(?:rgba?\(|hsla?\(|#[0-9a-fA-F]{3,8}\b)/
|
|
176
|
-
|
|
177
|
-
// Regex for Symbols color token: colorName[.opacity][+/-/=tone]
|
|
178
|
-
// Supports hyphenated names like 'highlight-reversed', 'canvas-card', 'line-highlight'
|
|
179
|
-
// +N or -N = relative shade, =N = absolute lightness percentage
|
|
180
|
-
const COLOR_TOKEN_REGEX = /^([a-zA-Z]\w*)(?:\.(\d+))?(?:([+-]\d+|=\d+))?$/
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Parse a color token string into its components.
|
|
184
|
-
* Returns { name, alpha, tone } for valid tokens,
|
|
185
|
-
* { passthrough: value } for CSS native values,
|
|
186
|
-
* or null for non-color tokens (e.g. '10px', '0')
|
|
187
|
-
*
|
|
188
|
-
* Tone prefixes:
|
|
189
|
-
* +N relative shade (add N to RGB)
|
|
190
|
-
* -N relative shade (subtract N from RGB)
|
|
191
|
-
* =N absolute lightness (set HSL lightness to N%)
|
|
192
|
-
*/
|
|
193
|
-
export const parseColorToken = (value) => {
|
|
194
|
-
if (!isString(value)) return null
|
|
195
|
-
|
|
196
|
-
// CSS native color passthrough
|
|
197
|
-
if (CSS_NATIVE_COLOR_REGEX.test(value)) return { passthrough: value }
|
|
198
|
-
|
|
199
|
-
// CSS var passthrough
|
|
200
|
-
if (isCSSVar(value)) return { cssVar: value }
|
|
201
|
-
|
|
202
|
-
const match = value.match(COLOR_TOKEN_REGEX)
|
|
203
|
-
if (!match) return null
|
|
204
|
-
|
|
205
|
-
const [, name, alphaDigits, rawTone] = match
|
|
206
|
-
const alpha = alphaDigits !== undefined ? `0.${alphaDigits}` : undefined
|
|
207
|
-
// Strip '=' prefix for absolute tones — getRgbTone handles unsigned values as absolute
|
|
208
|
-
const tone = rawTone && rawTone[0] === '=' ? rawTone.slice(1) : rawTone
|
|
209
|
-
|
|
210
|
-
return { name, alpha, tone }
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Check if a getColor() result is a resolved CSS color
|
|
215
|
-
* (as opposed to the original unresolved value being returned)
|
|
216
|
-
*/
|
|
217
|
-
export const isResolvedColor = (result) => {
|
|
218
|
-
return isString(result) && (
|
|
219
|
-
result.includes('rgb') ||
|
|
220
|
-
result.includes('var(') ||
|
|
221
|
-
result.includes('#')
|
|
222
|
-
)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Split a string by commas, respecting parenthesized groups.
|
|
227
|
-
* e.g. 'rgba(0,0,0,0.1), white.5 0 A' → ['rgba(0,0,0,0.1)', ' white.5 0 A']
|
|
228
|
-
*/
|
|
229
|
-
export const splitTopLevelCommas = (value) => {
|
|
230
|
-
const result = []
|
|
231
|
-
let current = ''
|
|
232
|
-
let depth = 0
|
|
233
|
-
|
|
234
|
-
for (const char of value) {
|
|
235
|
-
if (char === '(') depth += 1
|
|
236
|
-
else if (char === ')' && depth > 0) depth -= 1
|
|
237
|
-
|
|
238
|
-
if (char === ',' && depth === 0) {
|
|
239
|
-
result.push(current)
|
|
240
|
-
current = ''
|
|
241
|
-
continue
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
current += char
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (current.length || !result.length) result.push(current)
|
|
248
|
-
return result
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export const getRgbTone = (rgb, tone) => {
|
|
252
|
-
if (isString(rgb) && rgb.includes('rgb'))
|
|
253
|
-
rgb = colorStringToRgbaArray(rgb).join(', ')
|
|
254
|
-
if (isString(rgb)) rgb = rgb.split(',').map(v => parseFloat(v.trim()))
|
|
255
|
-
if (isNumber(tone)) tone += ''
|
|
256
|
-
const toHex = rgbArrayToHex(rgb)
|
|
257
|
-
const abs = tone.slice(0, 1)
|
|
258
|
-
|
|
259
|
-
if (abs === '-' || abs === '+') {
|
|
260
|
-
const colorShade = getColorShade(toHex, parseFloat(tone))
|
|
261
|
-
return hexToRgbArray(colorShade).join(', ')
|
|
262
|
-
} else {
|
|
263
|
-
const [r, g, b] = rgb
|
|
264
|
-
const hsl = rgbToHSL(r, g, b)
|
|
265
|
-
const [h, s, l] = hsl // eslint-disable-line
|
|
266
|
-
const newRgb = hslToRgb(h, s, (parseFloat(tone) / 100) * 255)
|
|
267
|
-
return newRgb
|
|
268
|
-
}
|
|
269
|
-
}
|
package/src/utils/font.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
export const resolveFileUrl = (url, files) => {
|
|
4
|
-
if (!url || !files) return null
|
|
5
|
-
try { new URL(url); return null } catch (e) { } // expected: src is not an absolute URL, treating as relative path
|
|
6
|
-
const file = files[url]
|
|
7
|
-
if (file) return file.content && file.content.src
|
|
8
|
-
return null
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getDefaultOrFirstKey = (LIBRARY, key) => {
|
|
12
|
-
if (LIBRARY[key]) return LIBRARY[key].value
|
|
13
|
-
if (LIBRARY.default) return LIBRARY[LIBRARY.default].value
|
|
14
|
-
const hasValue = Object.keys(LIBRARY)[0]
|
|
15
|
-
return hasValue && LIBRARY[hasValue] && LIBRARY[hasValue].value
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const getFontFormat = (url) => {
|
|
19
|
-
// Tolerate missing urls — a font weight entry without a `url` should produce
|
|
20
|
-
// no `format(...)` hint rather than crashing the entire CSS pipeline.
|
|
21
|
-
if (typeof url !== 'string' || !url) return null
|
|
22
|
-
const ext = url.split(/[#?]/)[0].split('.').pop().trim()
|
|
23
|
-
if (['woff2', 'woff', 'ttf', 'otf', 'eot'].includes(ext)) return ext
|
|
24
|
-
return null
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const isGoogleFontsUrl = (url) =>
|
|
28
|
-
url &&
|
|
29
|
-
(url.includes('fonts.googleapis.com') || url.includes('fonts.gstatic.com'))
|
|
30
|
-
|
|
31
|
-
export const setFontImport = (url) => `@import url('${url}');`
|
|
32
|
-
|
|
33
|
-
export const setInCustomFontMedia = (str) => `@font-face { ${str} }`
|
|
34
|
-
|
|
35
|
-
export const setCustomFont = (name, url, weight, options = {}) => {
|
|
36
|
-
// Filter out undefined / empty entries so a missing weight URL doesn't
|
|
37
|
-
// emit a broken `url('undefined')` rule or crash on .split downstream.
|
|
38
|
-
const rawUrls = Array.isArray(url) ? url : [url]
|
|
39
|
-
const urls = rawUrls.filter((u) => typeof u === 'string' && u)
|
|
40
|
-
const srcList = urls.map((u) => {
|
|
41
|
-
const format = getFontFormat(u)
|
|
42
|
-
const formatStr = format ? ` format('${format}')` : ''
|
|
43
|
-
return `url('${u}')${formatStr}`
|
|
44
|
-
}).join(',\n ')
|
|
45
|
-
return `
|
|
46
|
-
font-family: '${name}';
|
|
47
|
-
font-style: ${options.fontStyle || 'normal'};${
|
|
48
|
-
weight
|
|
49
|
-
? `
|
|
50
|
-
font-weight: ${weight};`
|
|
51
|
-
: ''
|
|
52
|
-
}${
|
|
53
|
-
options.fontStretch
|
|
54
|
-
? `
|
|
55
|
-
font-stretch: ${options.fontStretch};`
|
|
56
|
-
: ''
|
|
57
|
-
}${
|
|
58
|
-
options.fontDisplay
|
|
59
|
-
? `
|
|
60
|
-
font-display: ${options.fontDisplay};`
|
|
61
|
-
: ''
|
|
62
|
-
}
|
|
63
|
-
src: ${srcList};`
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export const setCustomFontMedia = (
|
|
67
|
-
name,
|
|
68
|
-
url,
|
|
69
|
-
weight,
|
|
70
|
-
options
|
|
71
|
-
) => `@font-face {${setCustomFont(name, url, weight, options)}
|
|
72
|
-
}`
|
|
73
|
-
|
|
74
|
-
export const getFontFaceEach = (name, weights, files) => {
|
|
75
|
-
const keys = Object.keys(weights)
|
|
76
|
-
return keys.map((key) => {
|
|
77
|
-
const { url, fontWeight, fontStyle, fontDisplay, fontStretch } = weights[key]
|
|
78
|
-
const resolvedUrl = Array.isArray(url)
|
|
79
|
-
? url.map((u) => resolveFileUrl(u, files) || u)
|
|
80
|
-
: resolveFileUrl(url, files) || url
|
|
81
|
-
return setCustomFont(name, resolvedUrl, fontWeight, { fontStyle, fontDisplay, fontStretch })
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const getFontFace = (LIBRARY) => {
|
|
86
|
-
const keys = Object.keys(LIBRARY)
|
|
87
|
-
return keys.map((key) => getFontFaceEach(key, LIBRARY[key].value))
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export const getFontFaceEachString = (name, weights, files) => {
|
|
91
|
-
if (weights && weights.isVariable) {
|
|
92
|
-
const url = resolveFileUrl(weights.url, files) || weights.url
|
|
93
|
-
if (isGoogleFontsUrl(url)) {
|
|
94
|
-
return setFontImport(url)
|
|
95
|
-
}
|
|
96
|
-
return setCustomFontMedia(name, url, weights.fontWeight, {
|
|
97
|
-
fontStretch: weights.fontStretch,
|
|
98
|
-
fontDisplay: weights.fontDisplay || 'swap'
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
const isArr = weights[0]
|
|
102
|
-
if (isArr) return getFontFaceEach(name, weights, files).map(setInCustomFontMedia)
|
|
103
|
-
const url = Array.isArray(weights.url)
|
|
104
|
-
? weights.url.map((u) => resolveFileUrl(u, files) || u)
|
|
105
|
-
: resolveFileUrl(weights.url, files) || weights.url
|
|
106
|
-
return setCustomFontMedia(name, url, weights.fontWeight, {
|
|
107
|
-
fontStyle: weights.fontStyle,
|
|
108
|
-
fontDisplay: weights.fontDisplay,
|
|
109
|
-
fontStretch: weights.fontStretch
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export const getFontFaceString = (LIBRARY, files) => {
|
|
114
|
-
const keys = Object.keys(LIBRARY)
|
|
115
|
-
return keys.map((key) => getFontFaceEachString(key, LIBRARY[key].value, files))
|
|
116
|
-
}
|