@sanity/ui 3.1.12 → 3.1.13
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/dist/theme.js +70 -55
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +70 -55
- package/dist/theme.mjs.map +1 -1
- package/package.json +1 -1
- package/src/theme/build/buildColorTheme.ts +10 -5
- package/src/theme/build/lib/lazy.ts +30 -0
- package/src/theme/build/renderColorTheme.ts +23 -23
- package/src/theme/getScopedTheme.ts +21 -14
- package/src/theme/versioning/v2_v0.ts +27 -19
package/package.json
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
ThemeColorSyntax,
|
|
28
28
|
} from '../system'
|
|
29
29
|
import {ColorTokenContext, resolveColorTokenValue as _color} from './colorToken'
|
|
30
|
+
import {defineLazyProperty} from './lib/lazy'
|
|
30
31
|
import {resolveColorTokens} from './resolveColorTokens'
|
|
31
32
|
|
|
32
33
|
export function buildColorTheme(config?: ThemeConfig): ThemeColorSchemes_v2 {
|
|
@@ -35,10 +36,13 @@ export function buildColorTheme(config?: ThemeConfig): ThemeColorSchemes_v2 {
|
|
|
35
36
|
color: resolveColorTokens(config?.color),
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
39
|
+
// Lazy schemes — each scheme's token tree is only built when first accessed
|
|
40
|
+
const schemes = {} as ThemeColorSchemes_v2
|
|
41
|
+
|
|
42
|
+
defineLazyProperty(schemes, 'light', () => buildColorScheme({scheme: 'light'}, resolvedConfig))
|
|
43
|
+
defineLazyProperty(schemes, 'dark', () => buildColorScheme({scheme: 'dark'}, resolvedConfig))
|
|
44
|
+
|
|
45
|
+
return schemes
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
function buildColorScheme(
|
|
@@ -47,10 +51,11 @@ function buildColorScheme(
|
|
|
47
51
|
): ThemeColorScheme_v2 {
|
|
48
52
|
const {scheme} = options
|
|
49
53
|
|
|
54
|
+
// Lazy tones — each tone's token tree is only built when first accessed
|
|
50
55
|
const colorScheme = {} as ThemeColorScheme_v2
|
|
51
56
|
|
|
52
57
|
for (const tone of THEME_COLOR_CARD_TONES) {
|
|
53
|
-
colorScheme
|
|
58
|
+
defineLazyProperty(colorScheme, tone, () => buildCardColorTheme({scheme, tone}, config))
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
return colorScheme
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defines a lazy, self-replacing property on `obj`.
|
|
3
|
+
*
|
|
4
|
+
* On first access the `factory` is called and the getter is replaced with the
|
|
5
|
+
* computed plain value — subsequent reads have zero overhead.
|
|
6
|
+
*
|
|
7
|
+
* The property is enumerable (visible in `Object.keys` / spread) in both states.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function defineLazyProperty<T extends object, K extends keyof T>(
|
|
12
|
+
obj: T,
|
|
13
|
+
key: K,
|
|
14
|
+
factory: () => T[K],
|
|
15
|
+
): void {
|
|
16
|
+
Object.defineProperty(obj, key, {
|
|
17
|
+
get() {
|
|
18
|
+
const value = factory()
|
|
19
|
+
Object.defineProperty(obj, key, {
|
|
20
|
+
value,
|
|
21
|
+
enumerable: true,
|
|
22
|
+
writable: false,
|
|
23
|
+
configurable: false,
|
|
24
|
+
})
|
|
25
|
+
return value
|
|
26
|
+
},
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
@@ -3,6 +3,7 @@ import {COLOR_HUES} from '@sanity/color'
|
|
|
3
3
|
import {ThemeColorPalette, ThemeConfig} from '../config'
|
|
4
4
|
import {defaultColorPalette} from '../defaults/colorPalette'
|
|
5
5
|
import {
|
|
6
|
+
THEME_COLOR_CARD_TONES,
|
|
6
7
|
THEME_COLOR_STATE_TONES,
|
|
7
8
|
ThemeColorAvatar_v2,
|
|
8
9
|
ThemeColorBadge_v2,
|
|
@@ -12,7 +13,6 @@ import {
|
|
|
12
13
|
ThemeColorButtonMode_v2,
|
|
13
14
|
ThemeColorButtonTone_v2,
|
|
14
15
|
ThemeColorCard_v2,
|
|
15
|
-
ThemeColorCardToneKey,
|
|
16
16
|
ThemeColorInput_v2,
|
|
17
17
|
ThemeColorInputMode_v2,
|
|
18
18
|
ThemeColorInputState_v2,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ThemeColorState_v2,
|
|
26
26
|
ThemeColorSyntax,
|
|
27
27
|
} from '../system'
|
|
28
|
+
import {defineLazyProperty} from './lib/lazy'
|
|
28
29
|
import {renderColorValue, RenderColorValueOptions} from './renderColorValue'
|
|
29
30
|
|
|
30
31
|
export function renderThemeColorSchemes(
|
|
@@ -33,41 +34,40 @@ export function renderThemeColorSchemes(
|
|
|
33
34
|
): ThemeColorSchemes_v2 {
|
|
34
35
|
const colorPalette = config?.palette ?? defaultColorPalette
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// Lazy schemes — each scheme is only rendered when first accessed
|
|
38
|
+
const schemes = {} as ThemeColorSchemes_v2
|
|
39
|
+
defineLazyProperty(schemes, 'light', () => renderThemeColorScheme(colorPalette, value.light))
|
|
40
|
+
defineLazyProperty(schemes, 'dark', () => renderThemeColorScheme(colorPalette, value.dark))
|
|
41
|
+
|
|
42
|
+
return schemes
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
function renderThemeColorScheme(
|
|
43
46
|
colorPalette: ThemeColorPalette,
|
|
44
47
|
value: ThemeColorScheme_v2,
|
|
45
48
|
): ThemeColorScheme_v2 {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const [, transparentTone] = toneEntries.find(([k]) => k === 'transparent')!
|
|
49
|
-
const [, defaultTone] = toneEntries.find(([k]) => k === 'default')!
|
|
49
|
+
// The `default` tone must be rendered eagerly — other tones depend on its `bg`.
|
|
50
|
+
const renderedDefaultTone = renderThemeColor(value.default, {colorPalette})
|
|
50
51
|
|
|
51
|
-
// The `transparent` and `default` tones are special cases, so we render them first
|
|
52
|
-
// (rendered without a `bg` option).
|
|
53
|
-
// But the rest of the tones are rendered on top of the `default` tone's `bg`.
|
|
54
|
-
const renderedTransparentTone = renderThemeColor(transparentTone, {colorPalette})
|
|
55
|
-
const renderedDefaultTone = renderThemeColor(defaultTone, {colorPalette})
|
|
56
|
-
|
|
57
|
-
// Get the `default` tone's `bg` property
|
|
58
52
|
const bg = renderedDefaultTone.bg
|
|
59
53
|
|
|
60
54
|
if (bg === 'white') {
|
|
61
55
|
throw new Error('Cannot blend with white background')
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
// All other tones are lazy. `transparent` and `default` are rendered without
|
|
59
|
+
// a `bg` option; the rest blend on top of `default`'s `bg`.
|
|
60
|
+
// We iterate THEME_COLOR_CARD_TONES (not Object.entries) to avoid
|
|
61
|
+
// force-evaluating lazy getters from the build phase.
|
|
62
|
+
const scheme = {default: renderedDefaultTone} as ThemeColorScheme_v2
|
|
63
|
+
|
|
64
|
+
for (const tone of THEME_COLOR_CARD_TONES) {
|
|
65
|
+
if (tone === 'default') continue
|
|
66
|
+
const opts = tone === 'transparent' ? {colorPalette} : {bg, colorPalette}
|
|
67
|
+
defineLazyProperty(scheme, tone, () => renderThemeColor(value[tone], opts))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return scheme
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
function renderThemeColor(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {defineLazyProperty} from './build/lib/lazy'
|
|
1
2
|
import {defaultThemeConfig} from './defaults/config'
|
|
2
3
|
import {
|
|
3
4
|
RootTheme,
|
|
@@ -29,8 +30,6 @@ export function getScopedTheme(
|
|
|
29
30
|
const v0 = is_v2(themeProp) ? v2_v0(themeProp) : themeProp
|
|
30
31
|
const v2 = is_v2(themeProp) ? themeProp : v0_v2(themeProp)
|
|
31
32
|
|
|
32
|
-
const colorScheme_v0 = v0.color[scheme] || v0.color.light
|
|
33
|
-
const color_v0 = (colorScheme_v0 as Record<string, ThemeColor>)[tone] || colorScheme_v0.default
|
|
34
33
|
const layer_v0 = v0.layer || defaultThemeConfig.layer
|
|
35
34
|
|
|
36
35
|
const colorScheme_v2 = v2.color[scheme] || v2.color.light
|
|
@@ -38,19 +37,27 @@ export function getScopedTheme(
|
|
|
38
37
|
const color_v2_9 = themeColor_v0_v2_9(color_v2)
|
|
39
38
|
const layer_v2 = v2.layer || defaultThemeConfig.layer
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41
|
+
const {color: _v0Color, ...v0Rest} = v0
|
|
42
|
+
|
|
43
|
+
const sanity = {
|
|
44
|
+
...v0Rest,
|
|
45
|
+
layer: layer_v0,
|
|
46
|
+
v2: {
|
|
47
|
+
...v2,
|
|
48
|
+
_resolved: true,
|
|
49
|
+
color: color_v2_9,
|
|
50
|
+
layer: layer_v2,
|
|
52
51
|
},
|
|
53
|
-
}
|
|
52
|
+
} as Theme['sanity']
|
|
53
|
+
|
|
54
|
+
// Defer v0 color computation — only resolved if legacy code reads theme.sanity.color
|
|
55
|
+
defineLazyProperty(sanity, 'color', () => {
|
|
56
|
+
const colorScheme_v0 = v0.color[scheme] || v0.color.light
|
|
57
|
+
return (colorScheme_v0 as Record<string, ThemeColor>)[tone] || colorScheme_v0.default
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const theme: Theme = {sanity}
|
|
54
61
|
|
|
55
62
|
_setCachedTheme(themeProp, scheme, tone, theme)
|
|
56
63
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {defineLazyProperty} from '../build/lib/lazy'
|
|
1
2
|
import {
|
|
2
3
|
RootTheme,
|
|
3
4
|
RootTheme_v2,
|
|
@@ -7,10 +8,23 @@ import {
|
|
|
7
8
|
ThemeColorInputState,
|
|
8
9
|
ThemeColorInputState_v2,
|
|
9
10
|
ThemeColorInputStates,
|
|
11
|
+
ThemeColorScheme,
|
|
10
12
|
} from '../system'
|
|
11
13
|
|
|
12
14
|
const cache = new WeakMap<RootTheme_v2, RootTheme>()
|
|
13
15
|
|
|
16
|
+
const V0_TONES = ['transparent', 'default', 'primary', 'positive', 'caution', 'critical'] as const
|
|
17
|
+
|
|
18
|
+
function lazyV0Scheme(schemeKey: 'light' | 'dark', color: RootTheme_v2['color']): ThemeColorScheme {
|
|
19
|
+
const scheme = {} as ThemeColorScheme
|
|
20
|
+
|
|
21
|
+
for (const tone of V0_TONES) {
|
|
22
|
+
defineLazyProperty(scheme, tone, () => themeColor_v2_v0(color[schemeKey][tone]))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return scheme
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
/** @internal */
|
|
15
29
|
export function v2_v0(v2: RootTheme_v2): RootTheme {
|
|
16
30
|
const cachedTheme = cache.get(v2)
|
|
@@ -31,29 +45,19 @@ export function v2_v0(v2: RootTheme_v2): RootTheme {
|
|
|
31
45
|
style: styles,
|
|
32
46
|
} = v2
|
|
33
47
|
|
|
34
|
-
|
|
48
|
+
// Lazy v0 color — two-level lazy structure so we don't force-evaluate
|
|
49
|
+
// the v2 lazy getters until a v0 tone is actually accessed.
|
|
50
|
+
const v0Color = {} as RootTheme['color']
|
|
51
|
+
|
|
52
|
+
defineLazyProperty(v0Color, 'light', () => lazyV0Scheme('light', color))
|
|
53
|
+
defineLazyProperty(v0Color, 'dark', () => lazyV0Scheme('dark', color))
|
|
54
|
+
|
|
55
|
+
const theme: RootTheme = {
|
|
35
56
|
_version: 0,
|
|
36
57
|
avatar,
|
|
37
58
|
button,
|
|
38
59
|
container,
|
|
39
|
-
color:
|
|
40
|
-
light: {
|
|
41
|
-
transparent: themeColor_v2_v0(color.light.transparent),
|
|
42
|
-
default: themeColor_v2_v0(color.light.default),
|
|
43
|
-
primary: themeColor_v2_v0(color.light.primary),
|
|
44
|
-
positive: themeColor_v2_v0(color.light.positive),
|
|
45
|
-
caution: themeColor_v2_v0(color.light.caution),
|
|
46
|
-
critical: themeColor_v2_v0(color.light.critical),
|
|
47
|
-
},
|
|
48
|
-
dark: {
|
|
49
|
-
transparent: themeColor_v2_v0(color.dark.transparent),
|
|
50
|
-
default: themeColor_v2_v0(color.dark.default),
|
|
51
|
-
primary: themeColor_v2_v0(color.dark.primary),
|
|
52
|
-
positive: themeColor_v2_v0(color.dark.positive),
|
|
53
|
-
caution: themeColor_v2_v0(color.dark.caution),
|
|
54
|
-
critical: themeColor_v2_v0(color.dark.critical),
|
|
55
|
-
},
|
|
56
|
-
},
|
|
60
|
+
color: v0Color,
|
|
57
61
|
focusRing: input.text.focusRing,
|
|
58
62
|
fonts,
|
|
59
63
|
input,
|
|
@@ -65,6 +69,10 @@ export function v2_v0(v2: RootTheme_v2): RootTheme {
|
|
|
65
69
|
|
|
66
70
|
v2,
|
|
67
71
|
}
|
|
72
|
+
|
|
73
|
+
cache.set(v2, theme)
|
|
74
|
+
|
|
75
|
+
return theme
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
function themeColor_v2_v0(color_v2: ThemeColorCard_v2): ThemeColor {
|