react-native-terra-ui 0.7.2 → 0.8.0
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 +28 -0
- package/README.md +1 -1
- package/lib/module/components/avatar/Avatar.js +20 -20
- package/lib/module/components/avatar/Avatar.js.map +1 -1
- package/lib/module/components/button/Button.js +11 -11
- package/lib/module/components/button/Button.js.map +1 -1
- package/lib/module/components/chip/Chip.js +32 -32
- package/lib/module/components/chip/Chip.js.map +1 -1
- package/lib/module/components/empty-state/EmptyState.js +3 -3
- package/lib/module/components/empty-state/EmptyState.js.map +1 -1
- package/lib/module/components/header/variants/LargeTitleHeader/index.js +30 -32
- package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -1
- package/lib/module/components/header/variants/TitleHeader/index.js +26 -18
- package/lib/module/components/header/variants/TitleHeader/index.js.map +1 -1
- package/lib/module/components/icon/Icon.js +3 -3
- package/lib/module/components/page-indicator/hooks/use-page-indicator-colors.js +2 -2
- package/lib/module/components/screen/Screen.js +63 -34
- package/lib/module/components/screen/Screen.js.map +1 -1
- package/lib/module/components/screen/ScreenContext.js +28 -9
- package/lib/module/components/screen/ScreenContext.js.map +1 -1
- package/lib/module/components/screen/ScreenFlatList.js +4 -162
- package/lib/module/components/screen/ScreenFlatList.js.map +1 -1
- package/lib/module/components/screen/ScreenList.js +81 -97
- package/lib/module/components/screen/ScreenList.js.map +1 -1
- package/lib/module/components/screen/ScreenScrollView.js +64 -115
- package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
- package/lib/module/components/screen/hooks/use-screen-ref.js +18 -0
- package/lib/module/components/screen/hooks/use-screen-ref.js.map +1 -0
- package/lib/module/components/screen/hooks/use-screen-scroll-handler.js +19 -0
- package/lib/module/components/screen/hooks/use-screen-scroll-handler.js.map +1 -0
- package/lib/module/components/screen/index.js.map +1 -1
- package/lib/module/components/screen/parts/ScreenFrame.js +47 -0
- package/lib/module/components/screen/parts/ScreenFrame.js.map +1 -0
- package/lib/module/components/screen/parts/ScreenHeaderAppearance.js +43 -0
- package/lib/module/components/screen/parts/ScreenHeaderAppearance.js.map +1 -0
- package/lib/module/components/screen/parts/ScreenPlaceholder.js +11 -13
- package/lib/module/components/screen/parts/ScreenPlaceholder.js.map +1 -1
- package/lib/module/components/screen/parts/ScreenSafeArea.android.js +27 -0
- package/lib/module/components/screen/parts/ScreenSafeArea.android.js.map +1 -0
- package/lib/module/components/screen/parts/ScreenSafeArea.js +26 -0
- package/lib/module/components/screen/parts/ScreenSafeArea.js.map +1 -0
- package/lib/module/components/screen/utils.js +18 -9
- package/lib/module/components/screen/utils.js.map +1 -1
- package/lib/module/components/spinner/Spinner.js +2 -2
- package/lib/module/components/text/Text.js +1 -1
- package/lib/module/components/toast/Toast.js +13 -13
- package/lib/module/components/toast/Toast.js.map +1 -1
- package/lib/module/components/toolbar/Toolbar.js +2 -2
- package/lib/module/context/ThemeProvider.js +22 -39
- package/lib/module/context/ThemeProvider.js.map +1 -1
- package/lib/module/context/index.js +1 -1
- package/lib/module/context/index.js.map +1 -1
- package/lib/module/theme/breakpoints.js +1 -1
- package/lib/module/theme/define-config.js +21 -0
- package/lib/module/theme/define-config.js.map +1 -0
- package/lib/module/theme/diagnostics.js +13 -0
- package/lib/module/theme/diagnostics.js.map +1 -0
- package/lib/module/theme/errors.js +15 -0
- package/lib/module/theme/errors.js.map +1 -0
- package/lib/module/theme/index.js +7 -1
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/legacy-tokens.js +119 -0
- package/lib/module/theme/legacy-tokens.js.map +1 -0
- package/lib/module/theme/registry.js +122 -130
- package/lib/module/theme/registry.js.map +1 -1
- package/lib/module/theme/resolve-config.js +346 -0
- package/lib/module/theme/resolve-config.js.map +1 -0
- package/lib/module/theme/runtime.js +57 -12
- package/lib/module/theme/runtime.js.map +1 -1
- package/lib/module/theme/screen-margin.js +6 -14
- package/lib/module/theme/screen-margin.js.map +1 -1
- package/lib/module/theme/screen-padding.js +17 -0
- package/lib/module/theme/screen-padding.js.map +1 -0
- package/lib/module/theme/selection-store.js +75 -0
- package/lib/module/theme/selection-store.js.map +1 -0
- package/lib/module/theme/theme.js +81 -36
- package/lib/module/theme/theme.js.map +1 -1
- package/lib/module/theme/tokens/canonical-color-keys.js +102 -0
- package/lib/module/theme/tokens/canonical-color-keys.js.map +1 -0
- package/lib/module/theme/tokens/dark.js +72 -88
- package/lib/module/theme/tokens/dark.js.map +1 -1
- package/lib/module/theme/tokens/light.js +69 -83
- package/lib/module/theme/tokens/light.js.map +1 -1
- package/lib/module/theme/tokens/primitives.js +14 -14
- package/lib/module/theme/tokens/primitives.js.map +1 -1
- package/lib/module/theme/tokens/validate.js +238 -0
- package/lib/module/theme/tokens/validate.js.map +1 -0
- package/lib/module/theme/unistyles-adapter.js +77 -0
- package/lib/module/theme/unistyles-adapter.js.map +1 -0
- package/lib/module/utils/accent-generator.js +476 -0
- package/lib/module/utils/accent-generator.js.map +1 -0
- package/lib/module/utils/accent-utils.js +52 -35
- package/lib/module/utils/accent-utils.js.map +1 -1
- package/lib/module/utils/color-utils.js +224 -7
- package/lib/module/utils/color-utils.js.map +1 -1
- package/lib/module/utils/deep-merge.js +1 -1
- package/lib/module/utils/deep-merge.js.map +1 -1
- package/lib/module/utils/resolve-theme-color.js +2 -2
- package/lib/typescript/src/components/chip/types.d.ts +1 -1
- package/lib/typescript/src/components/empty-state/EmptyState.d.ts +1 -1
- package/lib/typescript/src/components/empty-state/EmptyState.d.ts.map +1 -1
- package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts +6 -5
- package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -1
- package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts +11 -5
- package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts.map +1 -1
- package/lib/typescript/src/components/icon/Icon.d.ts +2 -2
- package/lib/typescript/src/components/screen/Screen.d.ts +45 -16
- package/lib/typescript/src/components/screen/Screen.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenContext.d.ts +42 -26
- package/lib/typescript/src/components/screen/ScreenContext.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenFlatList.d.ts +5 -46
- package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenList.d.ts +62 -50
- package/lib/typescript/src/components/screen/ScreenList.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/ScreenScrollView.d.ts +18 -58
- package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts +5 -0
- package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts +53 -0
- package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/index.d.ts +2 -2
- package/lib/typescript/src/components/screen/index.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts +6 -0
- package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts +21 -0
- package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts +6 -8
- package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts +7 -0
- package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts +6 -0
- package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts.map +1 -0
- package/lib/typescript/src/components/screen/types.d.ts +27 -32
- package/lib/typescript/src/components/screen/types.d.ts.map +1 -1
- package/lib/typescript/src/components/screen/utils.d.ts +9 -8
- package/lib/typescript/src/components/screen/utils.d.ts.map +1 -1
- package/lib/typescript/src/components/text/Text.d.ts +1 -1
- package/lib/typescript/src/components/text/Text.d.ts.map +1 -1
- package/lib/typescript/src/components/toolbar/Toolbar.d.ts +2 -2
- package/lib/typescript/src/context/ThemeProvider.d.ts +29 -12
- package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
- package/lib/typescript/src/context/index.d.ts +1 -1
- package/lib/typescript/src/context/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/breakpoints.d.ts +1 -1
- package/lib/typescript/src/theme/define-config.d.ts +23 -0
- package/lib/typescript/src/theme/define-config.d.ts.map +1 -0
- package/lib/typescript/src/theme/diagnostics.d.ts +4 -0
- package/lib/typescript/src/theme/diagnostics.d.ts.map +1 -0
- package/lib/typescript/src/theme/errors.d.ts +10 -0
- package/lib/typescript/src/theme/errors.d.ts.map +1 -0
- package/lib/typescript/src/theme/index.d.ts +10 -2
- package/lib/typescript/src/theme/index.d.ts.map +1 -1
- package/lib/typescript/src/theme/legacy-tokens.d.ts +187 -0
- package/lib/typescript/src/theme/legacy-tokens.d.ts.map +1 -0
- package/lib/typescript/src/theme/registry.d.ts +12 -17
- package/lib/typescript/src/theme/registry.d.ts.map +1 -1
- package/lib/typescript/src/theme/resolve-config.d.ts +99 -0
- package/lib/typescript/src/theme/resolve-config.d.ts.map +1 -0
- package/lib/typescript/src/theme/runtime.d.ts +25 -4
- package/lib/typescript/src/theme/runtime.d.ts.map +1 -1
- package/lib/typescript/src/theme/screen-margin.d.ts +6 -14
- package/lib/typescript/src/theme/screen-margin.d.ts.map +1 -1
- package/lib/typescript/src/theme/screen-padding.d.ts +15 -0
- package/lib/typescript/src/theme/screen-padding.d.ts.map +1 -0
- package/lib/typescript/src/theme/selection-store.d.ts +41 -0
- package/lib/typescript/src/theme/selection-store.d.ts.map +1 -0
- package/lib/typescript/src/theme/theme.d.ts +54 -1
- package/lib/typescript/src/theme/theme.d.ts.map +1 -1
- package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts +95 -0
- package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts.map +1 -0
- package/lib/typescript/src/theme/tokens/dark.d.ts +56 -63
- package/lib/typescript/src/theme/tokens/dark.d.ts.map +1 -1
- package/lib/typescript/src/theme/tokens/light.d.ts +56 -71
- package/lib/typescript/src/theme/tokens/light.d.ts.map +1 -1
- package/lib/typescript/src/theme/tokens/primitives.d.ts +11 -10
- package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -1
- package/lib/typescript/src/theme/tokens/validate.d.ts +34 -0
- package/lib/typescript/src/theme/tokens/validate.d.ts.map +1 -0
- package/lib/typescript/src/theme/types.d.ts +166 -86
- package/lib/typescript/src/theme/types.d.ts.map +1 -1
- package/lib/typescript/src/theme/unistyles-adapter.d.ts +33 -0
- package/lib/typescript/src/theme/unistyles-adapter.d.ts.map +1 -0
- package/lib/typescript/src/utils/accent-generator.d.ts +103 -0
- package/lib/typescript/src/utils/accent-generator.d.ts.map +1 -0
- package/lib/typescript/src/utils/accent-utils.d.ts +15 -2
- package/lib/typescript/src/utils/accent-utils.d.ts.map +1 -1
- package/lib/typescript/src/utils/color-utils.d.ts +59 -2
- package/lib/typescript/src/utils/color-utils.d.ts.map +1 -1
- package/lib/typescript/src/utils/deep-merge.d.ts +1 -0
- package/lib/typescript/src/utils/deep-merge.d.ts.map +1 -1
- package/lib/typescript/src/utils/resolve-theme-color.d.ts +2 -2
- package/package.json +1 -1
- package/src/components/avatar/Avatar.tsx +20 -20
- package/src/components/button/Button.tsx +11 -11
- package/src/components/chip/Chip.tsx +32 -32
- package/src/components/chip/types.ts +1 -1
- package/src/components/empty-state/EmptyState.tsx +4 -4
- package/src/components/header/variants/LargeTitleHeader/index.tsx +31 -30
- package/src/components/header/variants/TitleHeader/index.tsx +33 -22
- package/src/components/icon/Icon.tsx +4 -4
- package/src/components/page-indicator/hooks/use-page-indicator-colors.ts +2 -2
- package/src/components/screen/Screen.tsx +89 -43
- package/src/components/screen/ScreenContext.tsx +48 -28
- package/src/components/screen/ScreenFlatList.tsx +5 -191
- package/src/components/screen/ScreenList.tsx +197 -175
- package/src/components/screen/ScreenScrollView.tsx +92 -167
- package/src/components/screen/hooks/use-screen-ref.ts +24 -0
- package/src/components/screen/hooks/use-screen-scroll-handler.ts +31 -0
- package/src/components/screen/index.ts +8 -2
- package/src/components/screen/parts/ScreenFrame.tsx +49 -0
- package/src/components/screen/parts/ScreenHeaderAppearance.tsx +52 -0
- package/src/components/screen/parts/ScreenPlaceholder.tsx +16 -16
- package/src/components/screen/parts/ScreenSafeArea.android.tsx +22 -0
- package/src/components/screen/parts/ScreenSafeArea.tsx +20 -0
- package/src/components/screen/types.ts +29 -32
- package/src/components/screen/utils.ts +24 -11
- package/src/components/spinner/Spinner.tsx +2 -2
- package/src/components/text/Text.tsx +2 -2
- package/src/components/toast/Toast.tsx +13 -13
- package/src/components/toolbar/Toolbar.tsx +4 -4
- package/src/context/ThemeProvider.tsx +47 -51
- package/src/context/index.ts +1 -1
- package/src/theme/breakpoints.ts +1 -1
- package/src/theme/define-config.ts +27 -0
- package/src/theme/diagnostics.ts +11 -0
- package/src/theme/errors.ts +14 -0
- package/src/theme/index.ts +40 -1
- package/src/theme/legacy-tokens.ts +227 -0
- package/src/theme/registry.ts +119 -137
- package/src/theme/resolve-config.ts +406 -0
- package/src/theme/runtime.ts +52 -14
- package/src/theme/screen-margin.ts +6 -25
- package/src/theme/screen-padding.ts +26 -0
- package/src/theme/selection-store.ts +76 -0
- package/src/theme/theme.ts +104 -39
- package/src/theme/tokens/canonical-color-keys.ts +107 -0
- package/src/theme/tokens/dark.ts +91 -98
- package/src/theme/tokens/light.ts +88 -93
- package/src/theme/tokens/primitives.ts +14 -14
- package/src/theme/tokens/validate.ts +271 -0
- package/src/theme/types.ts +184 -95
- package/src/theme/unistyles-adapter.ts +75 -0
- package/src/utils/accent-generator.ts +530 -0
- package/src/utils/accent-utils.ts +66 -39
- package/src/utils/color-utils.ts +225 -8
- package/src/utils/deep-merge.ts +1 -1
- package/src/utils/resolve-theme-color.ts +2 -2
- package/lib/module/components/screen/parts/BottomSafeArea.js +0 -62
- package/lib/module/components/screen/parts/BottomSafeArea.js.map +0 -1
- package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts +0 -30
- package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts.map +0 -1
- package/src/components/screen/parts/BottomSafeArea.tsx +0 -59
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure theme resolution — normalization, layer processing, derived values and
|
|
5
|
+
* theme creation. Shared by startup configuration, runtime accent changes and
|
|
6
|
+
* previews so every consumer sees the same colors for the same input.
|
|
7
|
+
*
|
|
8
|
+
* Precedence, identical for both schemes:
|
|
9
|
+
*
|
|
10
|
+
* default tokens → shared → schemes[scheme]
|
|
11
|
+
* → generated selected accent → selected accent explicit overrides
|
|
12
|
+
*
|
|
13
|
+
* This module must stay free of registry, provider, Unistyles and renderer
|
|
14
|
+
* imports so `createTerraThemes` works without any native configuration.
|
|
15
|
+
*/
|
|
16
|
+
import { checkAccentContrast, GENERATED_ACCENT_ROLES, generateAccentColors, isSupportedAccentSeed } from "../utils/accent-generator.js";
|
|
17
|
+
import { deepMerge, isPlainObject } from "../utils/deep-merge.js";
|
|
18
|
+
import { warnContrastDiagnostics } from "./diagnostics.js";
|
|
19
|
+
import { TerraConfigError } from "./errors.js";
|
|
20
|
+
import { normalizeTokenOverride } from "./legacy-tokens.js";
|
|
21
|
+
import { buildRadiusScale, buildSpacingScale, createDefaultThemeSource, finalizeThemeSource } from "./theme.js";
|
|
22
|
+
const SCHEMES = ["light", "dark"];
|
|
23
|
+
const SURFACE_ROLES = ["surface.canvas", "surface.default", "surface.raised", "surface.sunken"];
|
|
24
|
+
|
|
25
|
+
// ─── Layer state ─────────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A theme mid-resolution: its source form plus provenance for every elevation
|
|
29
|
+
* level whose `shadowColor` a layer pinned explicitly. Default shadow colors are
|
|
30
|
+
* derived, never pinned, so a later `color.shadow` override still moves them.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Deep-copies an override, dropping `undefined` and `null` leaves (neither is
|
|
35
|
+
* an override; `null` is not a deletion mechanism). The copy means later
|
|
36
|
+
* mutation of caller data can never reach a normalized config or a theme.
|
|
37
|
+
*/
|
|
38
|
+
function sanitizeOverride(value) {
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
return value.map(item => sanitizeOverride(item));
|
|
41
|
+
}
|
|
42
|
+
if (isPlainObject(value)) {
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const [key, item] of Object.entries(value)) {
|
|
45
|
+
if (item === undefined || item === null) continue;
|
|
46
|
+
out[key] = sanitizeOverride(item);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Applies one override layer onto `state` and returns the next state. Every
|
|
55
|
+
* layer — shared, scheme, generated accent, accent overrides, or a full accent
|
|
56
|
+
* patch — goes through here, so they all follow the same rules:
|
|
57
|
+
* - deprecated names are normalized within the layer (canonical wins);
|
|
58
|
+
* - `undefined`/`null` leaves are no override; arrays replace; objects merge;
|
|
59
|
+
* - `spacing.base` / `radius.base` regenerate their scale, then that layer's
|
|
60
|
+
* explicit steps win over the regenerated values;
|
|
61
|
+
* - `elevation.<level>.shadowColor` pins that level (a later pin replaces an
|
|
62
|
+
* earlier one); other elevation fields merge normally.
|
|
63
|
+
* Inputs are never mutated.
|
|
64
|
+
*/
|
|
65
|
+
export function applyThemeLayer(state, override) {
|
|
66
|
+
if (!override) return state;
|
|
67
|
+
const normalized = normalizeTokenOverride(sanitizeOverride(override));
|
|
68
|
+
if (!normalized) return state;
|
|
69
|
+
const {
|
|
70
|
+
radius,
|
|
71
|
+
spacing,
|
|
72
|
+
elevation,
|
|
73
|
+
...rest
|
|
74
|
+
} = normalized;
|
|
75
|
+
let source = deepMerge(state.source, rest);
|
|
76
|
+
const pinnedShadowColors = {
|
|
77
|
+
...state.pinnedShadowColors
|
|
78
|
+
};
|
|
79
|
+
if (radius) {
|
|
80
|
+
const {
|
|
81
|
+
base,
|
|
82
|
+
...steps
|
|
83
|
+
} = radius;
|
|
84
|
+
if (base !== undefined) {
|
|
85
|
+
source = {
|
|
86
|
+
...source,
|
|
87
|
+
radius: buildRadiusScale(base)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
source = deepMerge(source, {
|
|
91
|
+
radius: steps
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (spacing) {
|
|
95
|
+
const {
|
|
96
|
+
base,
|
|
97
|
+
...steps
|
|
98
|
+
} = spacing;
|
|
99
|
+
if (base !== undefined) {
|
|
100
|
+
source = {
|
|
101
|
+
...source,
|
|
102
|
+
spacing: buildSpacingScale(base)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
source = deepMerge(source, {
|
|
106
|
+
spacing: steps
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (elevation) {
|
|
110
|
+
const levels = {};
|
|
111
|
+
for (const [key, level] of Object.entries(elevation)) {
|
|
112
|
+
if (!level) continue;
|
|
113
|
+
const {
|
|
114
|
+
shadowColor,
|
|
115
|
+
...fields
|
|
116
|
+
} = level;
|
|
117
|
+
if (shadowColor !== undefined) {
|
|
118
|
+
pinnedShadowColors[key] = shadowColor;
|
|
119
|
+
}
|
|
120
|
+
levels[key] = fields;
|
|
121
|
+
}
|
|
122
|
+
source = deepMerge(source, {
|
|
123
|
+
elevation: levels
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
source,
|
|
128
|
+
pinnedShadowColors
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ─── Normalized configuration ────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* A validated, immutable theme configuration. `base` is the fully layered
|
|
136
|
+
* `defaults → shared → scheme` state per scheme; every accent selection is
|
|
137
|
+
* re-resolved from it rather than from a previously resolved accent.
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
export function normalizeAccentScheme(input, path) {
|
|
141
|
+
if (input === undefined || input === null) return {
|
|
142
|
+
kind: "none"
|
|
143
|
+
};
|
|
144
|
+
if (typeof input === "string") {
|
|
145
|
+
if (!isSupportedAccentSeed(input)) {
|
|
146
|
+
throw new TerraConfigError(`${path}.seed`, `Unsupported accent seed ${JSON.stringify(input)}; expected an opaque six-digit hex color (#rrggbb).`);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
kind: "seed",
|
|
150
|
+
seed: input.trim()
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (!isPlainObject(input)) {
|
|
154
|
+
throw new TerraConfigError(path, "Expected a color string, `{ seed, overrides }`, or a theme override object.");
|
|
155
|
+
}
|
|
156
|
+
if (!("seed" in input)) {
|
|
157
|
+
return {
|
|
158
|
+
kind: "patch",
|
|
159
|
+
patch: sanitizeOverride(input)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const extra = Object.keys(input).filter(key => key !== "seed" && key !== "overrides");
|
|
163
|
+
if (extra.length > 0) {
|
|
164
|
+
throw new TerraConfigError(path, `A seeded accent accepts only \`seed\` and \`overrides\`; found ${extra.map(key => `\`${key}\``).join(", ")}. Use \`{ seed, overrides: { ... } }\` for color exceptions, or drop \`seed\` for a full theme override.`);
|
|
165
|
+
}
|
|
166
|
+
const {
|
|
167
|
+
seed,
|
|
168
|
+
overrides
|
|
169
|
+
} = input;
|
|
170
|
+
if (!isSupportedAccentSeed(seed)) {
|
|
171
|
+
throw new TerraConfigError(`${path}.seed`, `Unsupported accent seed ${JSON.stringify(seed)}; expected an opaque six-digit hex color (#rrggbb).`);
|
|
172
|
+
}
|
|
173
|
+
if (overrides !== undefined && !isPlainObject(overrides)) {
|
|
174
|
+
throw new TerraConfigError(`${path}.overrides`, "Expected a flat semantic color patch object.");
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
kind: "seed",
|
|
178
|
+
seed: seed.trim(),
|
|
179
|
+
...(overrides ? {
|
|
180
|
+
overrides: sanitizeOverride(overrides)
|
|
181
|
+
} : {})
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function normalizeAccentEntry(name, accent) {
|
|
185
|
+
const path = `accents.${name}`;
|
|
186
|
+
if (!isPlainObject(accent)) {
|
|
187
|
+
throw new TerraConfigError(path, "Expected an object with `light` and/or `dark` scheme inputs.");
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
light: normalizeAccentScheme(accent.light, `${path}.light`),
|
|
191
|
+
dark: normalizeAccentScheme(accent.dark, `${path}.dark`)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function assertOverrideObject(value, path) {
|
|
195
|
+
if (value !== undefined && !isPlainObject(value)) {
|
|
196
|
+
throw new TerraConfigError(path, "Expected a theme override object.");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Validates a theme input and pre-computes the immutable per-scheme base
|
|
202
|
+
* (`defaults → shared → scheme`). Throws {@link TerraConfigError} for invalid
|
|
203
|
+
* input — before any state exists to mutate. Never mutates `input` or the
|
|
204
|
+
* exported defaults.
|
|
205
|
+
*/
|
|
206
|
+
export function normalizeThemeInput(input = {}) {
|
|
207
|
+
if (!isPlainObject(input)) {
|
|
208
|
+
throw new TerraConfigError("", "Expected a configuration object.");
|
|
209
|
+
}
|
|
210
|
+
assertOverrideObject(input.shared, "shared");
|
|
211
|
+
assertOverrideObject(input.schemes, "schemes");
|
|
212
|
+
assertOverrideObject(input.schemes?.light, "schemes.light");
|
|
213
|
+
assertOverrideObject(input.schemes?.dark, "schemes.dark");
|
|
214
|
+
if (input.accents !== undefined && !isPlainObject(input.accents)) {
|
|
215
|
+
throw new TerraConfigError("accents", "Expected a record of named accents.");
|
|
216
|
+
}
|
|
217
|
+
const accents = {};
|
|
218
|
+
for (const [name, accent] of Object.entries(input.accents ?? {})) {
|
|
219
|
+
accents[name] = normalizeAccentEntry(name, accent);
|
|
220
|
+
}
|
|
221
|
+
const accentNames = Object.keys(accents);
|
|
222
|
+
let defaultAccent = null;
|
|
223
|
+
if (input.defaultAccent !== undefined && input.defaultAccent !== null) {
|
|
224
|
+
if (typeof input.defaultAccent !== "string" || !Object.hasOwn(accents, input.defaultAccent)) {
|
|
225
|
+
throw new TerraConfigError("defaultAccent", `Unknown accent ${JSON.stringify(input.defaultAccent)}; declared accents: ${accentNames.length > 0 ? accentNames.map(n => `"${n}"`).join(", ") : "(none)"}.`);
|
|
226
|
+
}
|
|
227
|
+
defaultAccent = input.defaultAccent;
|
|
228
|
+
}
|
|
229
|
+
const base = {};
|
|
230
|
+
for (const scheme of SCHEMES) {
|
|
231
|
+
let state = {
|
|
232
|
+
source: createDefaultThemeSource(scheme),
|
|
233
|
+
pinnedShadowColors: {}
|
|
234
|
+
};
|
|
235
|
+
state = applyThemeLayer(state, input.shared);
|
|
236
|
+
state = applyThemeLayer(state, input.schemes?.[scheme]);
|
|
237
|
+
base[scheme] = state;
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
accentNames,
|
|
241
|
+
defaultAccent,
|
|
242
|
+
base,
|
|
243
|
+
accents
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ─── Resolution ──────────────────────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
function getAccentEntry(config, accent) {
|
|
250
|
+
if (accent === null) return undefined;
|
|
251
|
+
const entry = config.accents[accent];
|
|
252
|
+
if (entry) return entry;
|
|
253
|
+
throw new TerraConfigError("accent", `Unknown accent ${JSON.stringify(accent)}; declared accents: ${config.accentNames.length > 0 ? config.accentNames.map(name => `"${name}"`).join(", ") : "(none)"}.`);
|
|
254
|
+
}
|
|
255
|
+
function accentContext(scheme, source) {
|
|
256
|
+
const surfaces = {};
|
|
257
|
+
for (const role of SURFACE_ROLES) {
|
|
258
|
+
surfaces[role] = source.color[role];
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
scheme,
|
|
262
|
+
surfaces,
|
|
263
|
+
pressedOpacity: source.opacity.pressed
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function pickGeneratedRoles(color) {
|
|
267
|
+
const out = {};
|
|
268
|
+
for (const role of GENERATED_ACCENT_ROLES) {
|
|
269
|
+
out[role] = color[role];
|
|
270
|
+
}
|
|
271
|
+
return out;
|
|
272
|
+
}
|
|
273
|
+
function resolveScheme(scheme, base, accent) {
|
|
274
|
+
let state = base;
|
|
275
|
+
let diagnostics = [];
|
|
276
|
+
if (accent.kind === "patch") {
|
|
277
|
+
state = applyThemeLayer(state, accent.patch);
|
|
278
|
+
} else if (accent.kind === "seed") {
|
|
279
|
+
const context = accentContext(scheme, state.source);
|
|
280
|
+
const generated = generateAccentColors(accent.seed, context);
|
|
281
|
+
state = applyThemeLayer(state, {
|
|
282
|
+
color: generated.colors
|
|
283
|
+
});
|
|
284
|
+
if (accent.overrides) {
|
|
285
|
+
state = applyThemeLayer(state, {
|
|
286
|
+
color: accent.overrides
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// The post-override check is authoritative: it evaluates the colours that
|
|
290
|
+
// actually ship, so an override that fixes a pair leaves no stale report.
|
|
291
|
+
diagnostics = checkAccentContrast(pickGeneratedRoles(state.source.color), accentContext(scheme, state.source));
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
theme: finalizeThemeSource(state.source, state.pinnedShadowColors),
|
|
295
|
+
diagnostics
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Resolves both schemes for `accent` from the config's immutable base. `null`
|
|
301
|
+
* selects the base themes; an unknown name throws {@link TerraConfigError}.
|
|
302
|
+
* Returned themes are freshly built and independently owned.
|
|
303
|
+
*/
|
|
304
|
+
export function resolveThemes(config, accent) {
|
|
305
|
+
const entry = getAccentEntry(config, accent);
|
|
306
|
+
const themes = {};
|
|
307
|
+
const diagnostics = [];
|
|
308
|
+
for (const scheme of SCHEMES) {
|
|
309
|
+
const resolved = resolveScheme(scheme, config.base[scheme], entry?.[scheme] ?? {
|
|
310
|
+
kind: "none"
|
|
311
|
+
});
|
|
312
|
+
themes[scheme] = resolved.theme;
|
|
313
|
+
diagnostics.push(resolved.diagnostics);
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
themes,
|
|
317
|
+
diagnostics: diagnostics.flat()
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Resolves one scheme without generating and finalizing the other. */
|
|
322
|
+
export function resolveThemeScheme(config, scheme, accent) {
|
|
323
|
+
const entry = getAccentEntry(config, accent);
|
|
324
|
+
return resolveScheme(scheme, config.base[scheme], entry?.[scheme] ?? {
|
|
325
|
+
kind: "none"
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Pure theme creation — no Unistyles configuration or registry involved.
|
|
331
|
+
* `options.accent` omitted → the input's `defaultAccent`; `null` → the base
|
|
332
|
+
* themes. Invalid input and unknown accents throw {@link TerraConfigError}.
|
|
333
|
+
* In development, contrast diagnostics are reported once each via
|
|
334
|
+
* `console.warn`; requested colors are never altered.
|
|
335
|
+
*/
|
|
336
|
+
export function createTerraThemes(input, options) {
|
|
337
|
+
const config = normalizeThemeInput(input);
|
|
338
|
+
const accent = options?.accent === undefined ? config.defaultAccent : options.accent;
|
|
339
|
+
const {
|
|
340
|
+
themes,
|
|
341
|
+
diagnostics
|
|
342
|
+
} = resolveThemes(config, accent);
|
|
343
|
+
warnContrastDiagnostics(diagnostics);
|
|
344
|
+
return themes;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=resolve-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["checkAccentContrast","GENERATED_ACCENT_ROLES","generateAccentColors","isSupportedAccentSeed","deepMerge","isPlainObject","warnContrastDiagnostics","TerraConfigError","normalizeTokenOverride","buildRadiusScale","buildSpacingScale","createDefaultThemeSource","finalizeThemeSource","SCHEMES","SURFACE_ROLES","sanitizeOverride","value","Array","isArray","map","item","out","key","Object","entries","undefined","applyThemeLayer","state","override","normalized","radius","spacing","elevation","rest","source","pinnedShadowColors","base","steps","levels","level","shadowColor","fields","normalizeAccentScheme","input","path","kind","JSON","stringify","seed","trim","patch","extra","keys","filter","length","join","overrides","normalizeAccentEntry","name","accent","light","dark","assertOverrideObject","normalizeThemeInput","shared","schemes","accents","accentNames","defaultAccent","hasOwn","n","scheme","getAccentEntry","config","entry","accentContext","surfaces","role","color","pressedOpacity","opacity","pressed","pickGeneratedRoles","resolveScheme","diagnostics","context","generated","colors","theme","resolveThemes","themes","resolved","push","flat","resolveThemeScheme","createTerraThemes","options"],"sourceRoot":"../../../src","sources":["theme/resolve-config.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,25 +1,70 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Runtime selection commands — accent and theme mode — plus the subscribed
|
|
5
|
+
* selection snapshot consumed by `useTheme()`.
|
|
6
|
+
*
|
|
7
|
+
* Every accent change re-resolves both schemes from the installed, immutable
|
|
8
|
+
* configuration (never from the previously resolved accent), hands them to
|
|
9
|
+
* Unistyles, and only then publishes the new selection. A rejected or failed
|
|
10
|
+
* change leaves both the native themes and the published selection untouched.
|
|
11
|
+
*/
|
|
12
|
+
import { warnContrastDiagnostics } from "./diagnostics.js";
|
|
13
|
+
import { resolveThemes } from "./resolve-config.js";
|
|
14
|
+
import { getInstalledConfig, getThemeSelection, publishThemeSelection } from "./selection-store.js";
|
|
15
|
+
import { applyMode, updateThemes } from "./unistyles-adapter.js";
|
|
16
|
+
export { getThemeSelection, subscribeThemeSelection } from "./selection-store.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Apply a registered accent (`null` restores the base themes) by updating both
|
|
20
|
+
* registered themes. An unknown name warns in development and changes nothing.
|
|
21
|
+
*
|
|
22
|
+
* If the native update fails part-way (see `updateThemes` in the adapter), the
|
|
23
|
+
* error propagates and the previous selection stays published; calling
|
|
24
|
+
* `applyAccent(getCurrentAccent() ?? null)` rewrites both themes.
|
|
25
|
+
*/
|
|
6
26
|
export function applyAccent(name) {
|
|
7
|
-
const
|
|
8
|
-
if (!
|
|
27
|
+
const config = getInstalledConfig();
|
|
28
|
+
if (name !== null && !config.accentNames.includes(name)) {
|
|
9
29
|
if (__DEV__) {
|
|
10
30
|
console.warn(`[react-native-terra-ui] Unknown accent "${name}".`);
|
|
11
31
|
}
|
|
12
32
|
return;
|
|
13
33
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
34
|
+
const {
|
|
35
|
+
themes,
|
|
36
|
+
diagnostics
|
|
37
|
+
} = resolveThemes(config, name);
|
|
38
|
+
updateThemes(themes);
|
|
39
|
+
publishThemeSelection({
|
|
40
|
+
accent: name ?? undefined
|
|
41
|
+
});
|
|
42
|
+
warnContrastDiagnostics(diagnostics);
|
|
17
43
|
}
|
|
18
|
-
export const getCurrentAccent = () => getRegistry().currentAccent;
|
|
19
44
|
|
|
20
|
-
/**
|
|
45
|
+
/** The applied accent name, or `undefined` for the base themes. */
|
|
46
|
+
export const getCurrentAccent = () => getThemeSelection().accent;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Choose how the active scheme is selected: `system` follows the OS appearance;
|
|
50
|
+
* `light` / `dark` pin a scheme until the next call.
|
|
51
|
+
*/
|
|
52
|
+
export function setThemeMode(mode) {
|
|
53
|
+
applyMode(mode);
|
|
54
|
+
publishThemeSelection({
|
|
55
|
+
mode
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The current theme mode. A system appearance change does not change it. */
|
|
60
|
+
export const getThemeMode = () => getThemeSelection().mode;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Pin the active color scheme, disabling adaptive (system) theming.
|
|
64
|
+
* Compatibility wrapper for `setThemeMode(scheme)`; use `setThemeMode("system")`
|
|
65
|
+
* to return to the OS preference.
|
|
66
|
+
*/
|
|
21
67
|
export function applyScheme(scheme) {
|
|
22
|
-
|
|
23
|
-
UnistylesRuntime.setTheme(scheme);
|
|
68
|
+
setThemeMode(scheme);
|
|
24
69
|
}
|
|
25
70
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["warnContrastDiagnostics","resolveThemes","getInstalledConfig","getThemeSelection","publishThemeSelection","applyMode","updateThemes","subscribeThemeSelection","applyAccent","name","config","accentNames","includes","__DEV__","console","warn","themes","diagnostics","accent","undefined","getCurrentAccent","setThemeMode","mode","getThemeMode","applyScheme","scheme"],"sourceRoot":"../../../src","sources":["theme/runtime.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,uBAAuB;AAChC,SAASC,aAAa;AACtB,SAASC,kBAAkB,EAAEC,iBAAiB,EAAEC,qBAAqB;AAErE,SAASC,SAAS,EAAEC,YAAY;AAGhC,SAASH,iBAAiB,EAAEI,uBAAuB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CAACC,IAAmB,EAAQ;EACrD,MAAMC,MAAM,GAAGR,kBAAkB,CAAC,CAAC;EACnC,IAAIO,IAAI,KAAK,IAAI,IAAI,CAACC,MAAM,CAACC,WAAW,CAACC,QAAQ,CAACH,IAAI,CAAC,EAAE;IACvD,IAAII,OAAO,EAAE;MACXC,OAAO,CAACC,IAAI,CAAC,2CAA2CN,IAAI,IAAI,CAAC;IACnE;IACA;EACF;EAEA,MAAM;IAAEO,MAAM;IAAEC;EAAY,CAAC,GAAGhB,aAAa,CAACS,MAAM,EAAED,IAAI,CAAC;EAC3DH,YAAY,CAACU,MAAM,CAAC;EACpBZ,qBAAqB,CAAC;IAAEc,MAAM,EAAET,IAAI,IAAIU;EAAU,CAAC,CAAC;EACpDnB,uBAAuB,CAACiB,WAAW,CAAC;AACtC;;AAEA;AACA,OAAO,MAAMG,gBAAgB,GAAGA,CAAA,KAA0BjB,iBAAiB,CAAC,CAAC,CAACe,MAAM;;AAEpF;AACA;AACA;AACA;AACA,OAAO,SAASG,YAAYA,CAACC,IAAe,EAAQ;EAClDjB,SAAS,CAACiB,IAAI,CAAC;EACflB,qBAAqB,CAAC;IAAEkB;EAAK,CAAC,CAAC;AACjC;;AAEA;AACA,OAAO,MAAMC,YAAY,GAAGA,CAAA,KAAiBpB,iBAAiB,CAAC,CAAC,CAACmB,IAAI;;AAErE;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,WAAWA,CAACC,MAAc,EAAQ;EAChDJ,YAAY,CAACI,MAAM,CAAC;AACtB","ignoreList":[]}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* reactive to breakpoint changes; outside one, use {@link useScreenMargin}.
|
|
10
|
-
*/
|
|
11
|
-
export function resolveScreenMargin(theme, breakpoint) {
|
|
12
|
-
return {
|
|
13
|
-
x: resolveBreakpointValue(theme.layout.screen.margin.x, breakpoint),
|
|
14
|
-
y: resolveBreakpointValue(theme.layout.screen.margin.y, breakpoint)
|
|
15
|
-
};
|
|
16
|
-
}
|
|
3
|
+
import { resolveScreenPadding } from "./screen-padding.js";
|
|
4
|
+
|
|
5
|
+
/** @deprecated Use ResolvedScreenPadding. */
|
|
6
|
+
|
|
7
|
+
/** @deprecated Use resolveScreenPadding. */
|
|
8
|
+
export const resolveScreenMargin = resolveScreenPadding;
|
|
17
9
|
//# sourceMappingURL=screen-margin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["resolveScreenPadding","resolveScreenMargin"],"sourceRoot":"../../../src","sources":["theme/screen-margin.ts"],"mappings":";;AACA,SAASA,oBAAoB;;AAE7B;;AAEA;AACA,OAAO,MAAMC,mBAAmB,GAAGD,oBAAoB","ignoreList":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { resolveBreakpointValue } from "./breakpoints.js";
|
|
4
|
+
/**
|
|
5
|
+
* Resolves both axes of `theme.layout.screen.padding` for the current runtime
|
|
6
|
+
* breakpoint in one call — nearly every consumer needs both axes, so this
|
|
7
|
+
* saves calling `resolveBreakpointValue` twice. Call inside a
|
|
8
|
+
* `StyleSheet.create` factory (passing `rt.breakpoint`) so the result stays
|
|
9
|
+
* reactive to breakpoint changes; outside one, use {@link useScreenPadding}.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveScreenPadding(theme, breakpoint) {
|
|
12
|
+
return {
|
|
13
|
+
x: resolveBreakpointValue(theme.layout.screen.padding.x, breakpoint),
|
|
14
|
+
y: resolveBreakpointValue(theme.layout.screen.padding.y, breakpoint)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=screen-padding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["resolveBreakpointValue","resolveScreenPadding","theme","breakpoint","x","layout","screen","padding","y"],"sourceRoot":"../../../src","sources":["theme/screen-padding.ts"],"mappings":";;AAEA,SAASA,sBAAsB;AAQ/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAClCC,KAAiB,EACjBC,UAAkD,EAC3B;EACvB,OAAO;IACLC,CAAC,EAAEJ,sBAAsB,CAACE,KAAK,CAACG,MAAM,CAACC,MAAM,CAACC,OAAO,CAACH,CAAC,EAAED,UAAU,CAAC;IACpEK,CAAC,EAAER,sBAAsB,CAACE,KAAK,CAACG,MAAM,CAACC,MAAM,CAACC,OAAO,CAACC,CAAC,EAAEL,UAAU;EACrE,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Internal runtime state shared by `registry.ts` (installation) and
|
|
5
|
+
* `runtime.ts` (selection commands). Lives in its own module so neither of
|
|
6
|
+
* those has to import the other.
|
|
7
|
+
*
|
|
8
|
+
* Holds two things, both private to `theme/`:
|
|
9
|
+
* - the installed {@link NormalizedThemeConfig} — immutable; every accent
|
|
10
|
+
* selection is re-resolved from it, never layered on a previous result;
|
|
11
|
+
* - the selection snapshot (`accent`, `mode`) behind a `useSyncExternalStore`
|
|
12
|
+
* compatible subscribe/get pair. The snapshot object keeps its identity until
|
|
13
|
+
* a value actually changes, so subscribers only re-render on real changes.
|
|
14
|
+
*
|
|
15
|
+
* Nothing here touches Unistyles. Callers publish *after* native work succeeds.
|
|
16
|
+
*/
|
|
17
|
+
import { normalizeThemeInput } from "./resolve-config.js";
|
|
18
|
+
// ─── Installed configuration ─────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Before any configure call the built-in defaults are "installed", matching
|
|
22
|
+
* the previous behaviour where `resolveTheme` worked pre-configuration.
|
|
23
|
+
*/
|
|
24
|
+
let installedConfig = normalizeThemeInput({});
|
|
25
|
+
|
|
26
|
+
/** @internal Read-only handle on the installed config. */
|
|
27
|
+
export const getInstalledConfig = () => installedConfig;
|
|
28
|
+
|
|
29
|
+
/** @internal Replaces the installed config; only `registry.ts` should call this. */
|
|
30
|
+
export function setInstalledConfig(config) {
|
|
31
|
+
installedConfig = config;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ─── Selection snapshot ──────────────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
/** The current runtime selection: which accent is applied and how the scheme is chosen. */
|
|
37
|
+
|
|
38
|
+
let selection = Object.freeze({
|
|
39
|
+
accent: undefined,
|
|
40
|
+
mode: "system"
|
|
41
|
+
});
|
|
42
|
+
const listeners = new Set();
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Current selection snapshot. Stable identity: the same object is returned
|
|
46
|
+
* until {@link publishThemeSelection} commits a real change, which makes it a
|
|
47
|
+
* valid `getSnapshot` for `useSyncExternalStore`.
|
|
48
|
+
*/
|
|
49
|
+
export const getThemeSelection = () => selection;
|
|
50
|
+
|
|
51
|
+
/** Subscribe to selection changes. Returns the unsubscribe function. */
|
|
52
|
+
export function subscribeThemeSelection(listener) {
|
|
53
|
+
listeners.add(listener);
|
|
54
|
+
return () => {
|
|
55
|
+
listeners.delete(listener);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @internal Commits a (partial) selection change and notifies subscribers.
|
|
61
|
+
* A no-op — same snapshot identity, no notification — when nothing changed.
|
|
62
|
+
*/
|
|
63
|
+
export function publishThemeSelection(next) {
|
|
64
|
+
const accent = "accent" in next ? next.accent : selection.accent;
|
|
65
|
+
const mode = next.mode ?? selection.mode;
|
|
66
|
+
if (accent === selection.accent && mode === selection.mode) return;
|
|
67
|
+
selection = Object.freeze({
|
|
68
|
+
accent,
|
|
69
|
+
mode
|
|
70
|
+
});
|
|
71
|
+
for (const listener of listeners) {
|
|
72
|
+
listener();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=selection-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["normalizeThemeInput","installedConfig","getInstalledConfig","setInstalledConfig","config","selection","Object","freeze","accent","undefined","mode","listeners","Set","getThemeSelection","subscribeThemeSelection","listener","add","delete","publishThemeSelection","next"],"sourceRoot":"../../../src","sources":["theme/selection-store.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAqCA,mBAAmB;AAGxD;;AAEA;AACA;AACA;AACA;AACA,IAAIC,eAAsC,GAAGD,mBAAmB,CAAC,CAAC,CAAC,CAAC;;AAEpE;AACA,OAAO,MAAME,kBAAkB,GAAGA,CAAA,KAA6BD,eAAe;;AAE9E;AACA,OAAO,SAASE,kBAAkBA,CAACC,MAA6B,EAAQ;EACtEH,eAAe,GAAGG,MAAM;AAC1B;;AAEA;;AAEA;;AAQA,IAAIC,SAAyB,GAAGC,MAAM,CAACC,MAAM,CAAC;EAAEC,MAAM,EAAEC,SAAS;EAAEC,IAAI,EAAE;AAAsB,CAAC,CAAC;AAEjG,MAAMC,SAAS,GAAG,IAAIC,GAAG,CAAa,CAAC;;AAEvC;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,GAAGA,CAAA,KAAsBR,SAAS;;AAEhE;AACA,OAAO,SAASS,uBAAuBA,CAACC,QAAoB,EAAc;EACxEJ,SAAS,CAACK,GAAG,CAACD,QAAQ,CAAC;EACvB,OAAO,MAAM;IACXJ,SAAS,CAACM,MAAM,CAACF,QAAQ,CAAC;EAC5B,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASG,qBAAqBA,CAACC,IAA6B,EAAQ;EACzE,MAAMX,MAAM,GAAG,QAAQ,IAAIW,IAAI,GAAGA,IAAI,CAACX,MAAM,GAAGH,SAAS,CAACG,MAAM;EAChE,MAAME,IAAI,GAAGS,IAAI,CAACT,IAAI,IAAIL,SAAS,CAACK,IAAI;EACxC,IAAIF,MAAM,KAAKH,SAAS,CAACG,MAAM,IAAIE,IAAI,KAAKL,SAAS,CAACK,IAAI,EAAE;EAE5DL,SAAS,GAAGC,MAAM,CAACC,MAAM,CAAC;IAAEC,MAAM;IAAEE;EAAK,CAAC,CAAC;EAC3C,KAAK,MAAMK,QAAQ,IAAIJ,SAAS,EAAE;IAChCI,QAAQ,CAAC,CAAC;EACZ;AACF","ignoreList":[]}
|