@symbo.ls/scratch 3.2.3 → 3.2.8

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.
Files changed (66) hide show
  1. package/dist/cjs/factory.js +23 -494
  2. package/dist/cjs/index.js +11 -2742
  3. package/dist/cjs/set.js +66 -2060
  4. package/dist/esm/factory.js +43 -0
  5. package/dist/esm/index.js +12 -0
  6. package/dist/esm/set.js +148 -0
  7. package/dist/iife/index.js +2580 -0
  8. package/package.json +25 -15
  9. package/src/set.js +22 -7
  10. package/src/system/color.js +48 -11
  11. package/src/system/font.js +19 -5
  12. package/src/system/reset.js +12 -3
  13. package/src/system/shadow.js +20 -13
  14. package/src/system/spacing.js +63 -56
  15. package/src/system/theme.js +4 -3
  16. package/src/system/timing.js +1 -1
  17. package/src/transforms/index.js +212 -95
  18. package/src/utils/color.js +79 -0
  19. package/src/utils/font.js +54 -14
  20. package/src/utils/sequence.js +94 -39
  21. package/src/utils/sprite.js +2 -2
  22. package/src/utils/unit.js +69 -2
  23. package/src/utils/var.js +1 -2
  24. package/dist/cjs/defaultConfig/animation.js +0 -26
  25. package/dist/cjs/defaultConfig/cases.js +0 -26
  26. package/dist/cjs/defaultConfig/class.js +0 -27
  27. package/dist/cjs/defaultConfig/color.js +0 -28
  28. package/dist/cjs/defaultConfig/document.js +0 -26
  29. package/dist/cjs/defaultConfig/font-family.js +0 -34
  30. package/dist/cjs/defaultConfig/font.js +0 -26
  31. package/dist/cjs/defaultConfig/grid.js +0 -27
  32. package/dist/cjs/defaultConfig/icons.js +0 -28
  33. package/dist/cjs/defaultConfig/index.js +0 -222
  34. package/dist/cjs/defaultConfig/media.js +0 -31
  35. package/dist/cjs/defaultConfig/responsive.js +0 -52
  36. package/dist/cjs/defaultConfig/sequence.js +0 -51
  37. package/dist/cjs/defaultConfig/shadow.js +0 -26
  38. package/dist/cjs/defaultConfig/spacing.js +0 -87
  39. package/dist/cjs/defaultConfig/svg.js +0 -28
  40. package/dist/cjs/defaultConfig/templates.js +0 -26
  41. package/dist/cjs/defaultConfig/theme.js +0 -26
  42. package/dist/cjs/defaultConfig/timing.js +0 -68
  43. package/dist/cjs/defaultConfig/typography.js +0 -72
  44. package/dist/cjs/defaultConfig/unit.js +0 -28
  45. package/dist/cjs/package.json +0 -4
  46. package/dist/cjs/system/color.js +0 -1175
  47. package/dist/cjs/system/document.js +0 -987
  48. package/dist/cjs/system/font.js +0 -1009
  49. package/dist/cjs/system/index.js +0 -2227
  50. package/dist/cjs/system/reset.js +0 -1099
  51. package/dist/cjs/system/shadow.js +0 -1384
  52. package/dist/cjs/system/spacing.js +0 -1338
  53. package/dist/cjs/system/svg.js +0 -1086
  54. package/dist/cjs/system/theme.js +0 -1276
  55. package/dist/cjs/system/timing.js +0 -1213
  56. package/dist/cjs/system/typography.js +0 -1311
  57. package/dist/cjs/tests/index.js +0 -30
  58. package/dist/cjs/transforms/index.js +0 -1613
  59. package/dist/cjs/utils/color.js +0 -333
  60. package/dist/cjs/utils/font.js +0 -69
  61. package/dist/cjs/utils/index.js +0 -1548
  62. package/dist/cjs/utils/sequence.js +0 -1198
  63. package/dist/cjs/utils/sprite.js +0 -579
  64. package/dist/cjs/utils/theme.js +0 -31
  65. package/dist/cjs/utils/unit.js +0 -28
  66. package/dist/cjs/utils/var.js +0 -1040
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- import { isNull, isString, isObject, isUndefined } from '@domql/utils'
3
+ import { isString, isObject, exec } from '@domql/utils'
4
4
  import { getActiveConfig } from '../factory'
5
5
  import {
6
6
  getSpacingByKey,
@@ -9,134 +9,251 @@ import {
9
9
  getMediaColor,
10
10
  getTimingByKey,
11
11
  getTimingFunction,
12
- getSpacingBasedOnRatio
12
+ getSpacingBasedOnRatio,
13
+ checkIfBoxSize,
14
+ splitSpacedValue
13
15
  } from '../system'
16
+ import {
17
+ getFnPrefixAndValue,
18
+ isResolvedColor,
19
+ isCSSVar,
20
+ CSS_NATIVE_COLOR_REGEX,
21
+ splitTopLevelCommas,
22
+ parseColorToken
23
+ } from '../utils'
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
14
46
 
15
- const isBorderStyle = str => [
16
- 'none',
17
- 'hidden',
18
- 'dotted',
19
- 'dashed',
20
- 'solid',
21
- 'double',
22
- 'groove',
23
- 'ridge',
24
- 'inset',
25
- 'outset',
26
- 'initial'
27
- ].some(v => str.includes(v))
28
-
29
- export const transformBorder = border => {
30
- const arr = border.split(', ')
31
- return arr.map(v => {
32
- v = v.trim()
33
- if (v.slice(0, 2) === '--') return `var(${v})`
34
- else if (isBorderStyle(v)) return v || 'solid'
35
- else if (v.slice(-2) === 'px' || v.slice(-2) === 'em') return v // TODO: add map spacing
36
- else if (getColor(v).length > 2) return getColor(v)
37
- return getSpacingByKey(v, 'border').border
38
- }).join(' ')
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(' ')
39
66
  }
40
67
 
41
- export const transformTextStroke = stroke => {
42
- return stroke.split(', ').map(v => {
43
- if (v.slice(0, 2) === '--') return `var(${v})`
44
- if (v.includes('px')) return v
45
- else if (getColor(v)) return getColor(v)
46
- return v
47
- }).join(' ')
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(' ')
48
84
  }
49
85
 
50
86
  export const transformShadow = (sh, globalTheme) => getShadow(sh, globalTheme)
51
87
 
52
- export const transformBoxShadow = (shadows, globalTheme) => shadows.split('|').map(shadow => {
53
- return shadow.split(',').map(v => {
54
- v = v.trim()
55
- if (v.slice(0, 2) === '--') return `var(${v})`
56
- if (getColor(v).length > 2) {
57
- const color = getMediaColor(v, globalTheme)
58
- if (isObject(color)) return Object.values(color).filter(v => v.includes(': ' + globalTheme))[0]
59
- return color
60
- }
61
- if (v.includes('px') || v.slice(-2) === 'em') return v
62
- const arr = v.split(' ')
63
- if (!arr.length) return v
64
- return arr.map(v => getSpacingByKey(v, 'shadow').shadow).join(' ')
65
- }).join(' ')
66
- }).join(',')
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
+ }
67
171
 
68
172
  export const transformBackgroundImage = (backgroundImage, globalTheme) => {
69
173
  const CONFIG = getActiveConfig()
70
- return backgroundImage.split(', ').map(v => {
71
- if (v.slice(0, 2) === '--') return `var(${v})`
72
- if (v.includes('url') || v.includes('gradient')) return v
73
- else if (CONFIG.GRADIENT[backgroundImage]) {
74
- return {
75
- backgroundImage: getMediaColor(backgroundImage, globalTheme || CONFIG.globalTheme)
76
- }
77
- } else if (v.includes('/') || v.startsWith('http') || v.includes('.')) return `url(${v})`
78
- return v
79
- }).join(' ')
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(' ')
80
192
  }
81
193
 
82
- export const transfromGap = gap => isString(gap) && (
83
- gap.split(' ').map(v => getSpacingByKey(v, 'gap').gap).join(' ')
84
- )
194
+ export const transfromGap = (gap) =>
195
+ isString(gap) &&
196
+ gap
197
+ .split(' ')
198
+ .map((v) => getSpacingByKey(v, 'gap').gap)
199
+ .join(' ')
85
200
 
86
- export const transformTransition = transition => {
201
+ export const transformTransition = (transition) => {
87
202
  const arr = transition.split(' ')
88
203
 
89
204
  if (!arr.length) return transition
90
205
 
91
- return arr.map(v => {
92
- if (v.slice(0, 2) === '--') return `var(${v})`
93
- if (v.length < 3 || v.includes('ms')) {
94
- const mapWithSequence = getTimingByKey(v)
95
- return mapWithSequence.timing || v
96
- }
97
- if (getTimingFunction(v)) return getTimingFunction(v)
98
- return v
99
- }).join(' ')
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(' ')
100
217
  }
101
218
 
102
219
  export const transformDuration = (duration, props, propertyName) => {
103
220
  if (!isString(duration)) return
104
- return duration.split(',').map(v => getTimingByKey(v).timing || v).join(',')
221
+ return duration
222
+ .split(',')
223
+ .map((v) => getTimingByKey(v).timing || v)
224
+ .join(',')
105
225
  }
106
226
 
107
- export const splitTransition = transition => {
227
+ export const splitTransition = (transition) => {
108
228
  const arr = transition.split(',')
109
229
  if (!arr.length) return
110
230
  return arr.map(transformTransition).join(',')
111
231
  }
112
232
 
113
- export const checkIfBoxSize = propertyName => {
114
- const prop = propertyName.toLowerCase()
115
- return (prop.includes('width') || prop.includes('height')) && !prop.includes('border')
116
- }
117
-
118
- export const transformSize = (propertyName, val, props = {}, opts = {}) => {
119
- let value = val || props[propertyName]
233
+ export function transformSize(propertyName, val, props = {}, opts = {}) {
234
+ let value = exec.call(this, val || props[propertyName])
120
235
 
121
- if (isUndefined(value) && isNull(value)) return
236
+ if (value === undefined || value === null) return
122
237
 
123
- const shouldScaleBoxSize = props.scaleBoxSize
124
- const isBoxSize = checkIfBoxSize(propertyName)
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
+ }
125
246
 
126
- if (!shouldScaleBoxSize && isBoxSize && isString(value)) {
127
- value = value.split(' ').map(v => {
128
- const isSingleLetter = v.length < 3 && /[A-Z]/.test(v)
129
- const hasUnits = ['%', 'vw', 'vh', 'ch'].some(unit => value.includes(unit))
130
- if (isSingleLetter && !hasUnits) return v + '_default'
131
- return v
132
- }).join(' ')
247
+ const shouldScaleBoxSize = props.scaleBoxSize
248
+ const isBoxSize = checkIfBoxSize(propertyName)
249
+ if (!shouldScaleBoxSize && isBoxSize) {
250
+ value = splitSpacedValue(value)
251
+ }
133
252
  }
134
253
 
135
- if (opts.ratio) {
136
- return getSpacingBasedOnRatio(props, propertyName, value)
137
- } else {
138
- return getSpacingByKey(value, propertyName)
139
- }
254
+ return opts.ratio
255
+ ? getSpacingBasedOnRatio(props, propertyName, value, fnPrefix)
256
+ : getSpacingByKey(value, propertyName, undefined, fnPrefix)
140
257
  }
141
258
 
142
259
  export const transformSizeRatio = (propertyName, val = null, props) => {
@@ -168,6 +168,85 @@ export const opacify = (color, opacity) => {
168
168
  return `rgba(${arr})`
169
169
  }
170
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
+ // +N or -N = relative shade, =N = absolute lightness percentage
179
+ const COLOR_TOKEN_REGEX = /^([a-zA-Z]\w*)(?:\.(\d+))?(?:([+-]\d+|=\d+))?$/
180
+
181
+ /**
182
+ * Parse a color token string into its components.
183
+ * Returns { name, alpha, tone } for valid tokens,
184
+ * { passthrough: value } for CSS native values,
185
+ * or null for non-color tokens (e.g. '10px', '0')
186
+ *
187
+ * Tone prefixes:
188
+ * +N relative shade (add N to RGB)
189
+ * -N relative shade (subtract N from RGB)
190
+ * =N absolute lightness (set HSL lightness to N%)
191
+ */
192
+ export const parseColorToken = (value) => {
193
+ if (!isString(value)) return null
194
+
195
+ // CSS native color passthrough
196
+ if (CSS_NATIVE_COLOR_REGEX.test(value)) return { passthrough: value }
197
+
198
+ // CSS var passthrough
199
+ if (isCSSVar(value)) return { cssVar: value }
200
+
201
+ const match = value.match(COLOR_TOKEN_REGEX)
202
+ if (!match) return null
203
+
204
+ const [, name, alphaDigits, rawTone] = match
205
+ const alpha = alphaDigits !== undefined ? `0.${alphaDigits}` : undefined
206
+ // Strip '=' prefix for absolute tones — getRgbTone handles unsigned values as absolute
207
+ const tone = rawTone && rawTone[0] === '=' ? rawTone.slice(1) : rawTone
208
+
209
+ return { name, alpha, tone }
210
+ }
211
+
212
+ /**
213
+ * Check if a getColor() result is a resolved CSS color
214
+ * (as opposed to the original unresolved value being returned)
215
+ */
216
+ export const isResolvedColor = (result) => {
217
+ return isString(result) && (
218
+ result.includes('rgb') ||
219
+ result.includes('var(') ||
220
+ result.includes('#')
221
+ )
222
+ }
223
+
224
+ /**
225
+ * Split a string by commas, respecting parenthesized groups.
226
+ * e.g. 'rgba(0,0,0,0.1), white.5 0 A' → ['rgba(0,0,0,0.1)', ' white.5 0 A']
227
+ */
228
+ export const splitTopLevelCommas = (value) => {
229
+ const result = []
230
+ let current = ''
231
+ let depth = 0
232
+
233
+ for (const char of value) {
234
+ if (char === '(') depth += 1
235
+ else if (char === ')' && depth > 0) depth -= 1
236
+
237
+ if (char === ',' && depth === 0) {
238
+ result.push(current)
239
+ current = ''
240
+ continue
241
+ }
242
+
243
+ current += char
244
+ }
245
+
246
+ if (current.length || !result.length) result.push(current)
247
+ return result
248
+ }
249
+
171
250
  export const getRgbTone = (rgb, tone) => {
172
251
  if (isString(rgb) && rgb.includes('rgb'))
173
252
  rgb = colorStringToRgbaArray(rgb).join(', ')
package/src/utils/font.js CHANGED
@@ -7,41 +7,81 @@ export const getDefaultOrFirstKey = (LIBRARY, key) => {
7
7
  return hasValue && LIBRARY[hasValue] && LIBRARY[hasValue].value
8
8
  }
9
9
 
10
- export const getFontFormat = url => url.split(/[#?]/)[0].split('.').pop().trim()
10
+ export const getFontFormat = (url) => {
11
+ const ext = url.split(/[#?]/)[0].split('.').pop().trim()
12
+ if (['woff2', 'woff', 'ttf', 'otf', 'eot'].includes(ext)) return ext
13
+ return null
14
+ }
15
+
16
+ export const isGoogleFontsUrl = (url) =>
17
+ url &&
18
+ (url.includes('fonts.googleapis.com') || url.includes('fonts.gstatic.com'))
11
19
 
12
- export const setInCustomFontMedia = str => `@font-face { ${str} }`
20
+ export const setFontImport = (url) => `@import url('${url}');`
13
21
 
14
- export const setCustomFont = (name, url, weight) => `
22
+ export const setInCustomFontMedia = (str) => `@font-face { ${str} }`
23
+
24
+ export const setCustomFont = (name, url, weight, options = {}) => {
25
+ const format = getFontFormat(url)
26
+ const formatStr = format ? ` format('${format}')` : ''
27
+ return `
15
28
  font-family: '${name}';
16
- font-style: normal;
17
- ${weight && `font-weight: ${weight};`}
18
- src: url('${url}') format('${getFontFormat(url)}');`
29
+ font-style: normal;${
30
+ weight
31
+ ? `
32
+ font-weight: ${weight};`
33
+ : ''
34
+ }${
35
+ options.fontStretch
36
+ ? `
37
+ font-stretch: ${options.fontStretch};`
38
+ : ''
39
+ }${
40
+ options.fontDisplay
41
+ ? `
42
+ font-display: ${options.fontDisplay};`
43
+ : ''
44
+ }
45
+ src: url('${url}')${formatStr};`
46
+ }
19
47
 
20
- export const setCustomFontMedia = (name, url, weight) => `@font-face {
21
- ${setCustomFont(name, url, weight)}
48
+ export const setCustomFontMedia = (
49
+ name,
50
+ url,
51
+ weight,
52
+ options
53
+ ) => `@font-face {${setCustomFont(name, url, weight, options)}
22
54
  }`
23
- // src: url('${url}') format('${getFontFormat(url)}');
24
55
 
25
56
  export const getFontFaceEach = (name, weights) => {
26
57
  const keys = Object.keys(weights)
27
- return keys.map(key => {
58
+ return keys.map((key) => {
28
59
  const { url, fontWeight } = weights[key]
29
60
  return setCustomFont(name, url, fontWeight)
30
61
  })
31
62
  }
32
63
 
33
- export const getFontFace = LIBRARY => {
64
+ export const getFontFace = (LIBRARY) => {
34
65
  const keys = Object.keys(LIBRARY)
35
- return keys.map(key => getFontFaceEach(key, LIBRARY[key].value))
66
+ return keys.map((key) => getFontFaceEach(key, LIBRARY[key].value))
36
67
  }
37
68
 
38
69
  export const getFontFaceEachString = (name, weights) => {
70
+ if (weights && weights.isVariable) {
71
+ if (isGoogleFontsUrl(weights.url)) {
72
+ return setFontImport(weights.url)
73
+ }
74
+ return setCustomFontMedia(name, weights.url, weights.fontWeight, {
75
+ fontStretch: weights.fontStretch,
76
+ fontDisplay: weights.fontDisplay || 'swap'
77
+ })
78
+ }
39
79
  const isArr = weights[0]
40
80
  if (isArr) return getFontFaceEach(name, weights).map(setInCustomFontMedia)
41
81
  return setCustomFontMedia(name, weights.url)
42
82
  }
43
83
 
44
- export const getFontFaceString = LIBRARY => {
84
+ export const getFontFaceString = (LIBRARY) => {
45
85
  const keys = Object.keys(LIBRARY)
46
- return keys.map(key => getFontFaceEachString(key, LIBRARY[key].value))
86
+ return keys.map((key) => getFontFaceEachString(key, LIBRARY[key].value))
47
87
  }