@reopt-ai/opt-ui 1.5.0 → 1.7.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/COMPONENT_CATALOG.md +178 -50
- package/README.md +28 -7
- package/dist/app.css +170 -0
- package/dist/core/index.cjs +164 -324
- package/dist/core/index.d.cts +3 -6
- package/dist/core/index.d.ts +3 -6
- package/dist/core/index.js +3 -323
- package/dist/docs/01-getting-started.md +25 -5
- package/dist/docs/02-components/01-core.md +36 -28
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +144 -23
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +4 -4
- package/dist/docs/03-recipes/03-layouts.md +16 -12
- package/dist/docs/05-migration/01-breaking-changes.md +46 -1
- package/dist/field-sidebar-BTZCBviA.d.cts +1031 -0
- package/dist/field-sidebar-BTZCBviA.d.cts.map +1 -0
- package/dist/field-sidebar-CB8vjvUM.d.ts +1031 -0
- package/dist/field-sidebar-CB8vjvUM.d.ts.map +1 -0
- package/dist/field-sidebar-Cs-J-5VE.js +4233 -0
- package/dist/field-sidebar-Cs-J-5VE.js.map +1 -0
- package/dist/field-sidebar-CzIQX70-.cjs +4561 -0
- package/dist/id-registry.cjs +1939 -1872
- package/dist/id-registry.d.cts +14 -11
- package/dist/id-registry.d.cts.map +1 -0
- package/dist/id-registry.d.ts +14 -11
- package/dist/id-registry.d.ts.map +1 -0
- package/dist/id-registry.js +1937 -1871
- package/dist/id-registry.js.map +1 -0
- package/dist/id-registry.json +113 -28
- package/dist/index.cjs +8380 -9790
- package/dist/index.d.cts +1555 -1442
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +1555 -1442
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7996 -9778
- package/dist/index.js.map +1 -0
- package/dist/meta.cjs +7753 -6875
- package/dist/meta.d.cts.map +1 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +7752 -6846
- package/dist/meta.js.map +1 -0
- package/dist/pagination-DWbvACuN.js +3850 -0
- package/dist/pagination-DWbvACuN.js.map +1 -0
- package/dist/pagination-DjfxBcjX.cjs +4739 -0
- package/dist/query.cjs +386 -0
- package/dist/query.d.cts +141 -0
- package/dist/query.d.cts.map +1 -0
- package/dist/query.d.ts +141 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +371 -0
- package/dist/query.js.map +1 -0
- package/dist/shader-surface-BUPZ0P-n.js +3654 -0
- package/dist/shader-surface-BUPZ0P-n.js.map +1 -0
- package/dist/shader-surface-BfTP9c1Q.d.ts +1788 -0
- package/dist/shader-surface-BfTP9c1Q.d.ts.map +1 -0
- package/dist/shader-surface-DRrcLrWf.d.cts +1788 -0
- package/dist/shader-surface-DRrcLrWf.d.cts.map +1 -0
- package/dist/shader-surface-Fav5K9UC.cjs +4041 -0
- package/dist/shells/index.cjs +58 -65
- package/dist/shells/index.d.cts +4 -5
- package/dist/shells/index.d.ts +4 -5
- package/dist/shells/index.js +4 -64
- package/dist/tailwind.css +49 -0
- package/dist/theme/presets/default.css +2 -2
- package/dist/theme/presets/minimal.css +2 -2
- package/dist/theme/presets/mono-dark.css +2 -2
- package/dist/theme/presets/natural.css +1 -1
- package/dist/theme/presets/pro.css +2 -2
- package/dist/theme/server.cjs +257 -228
- package/dist/theme/server.d.cts +48 -60
- package/dist/theme/server.d.cts.map +1 -0
- package/dist/theme/server.d.ts +48 -60
- package/dist/theme/server.d.ts.map +1 -0
- package/dist/theme/server.js +234 -189
- package/dist/theme/server.js.map +1 -0
- package/dist/types-D0FlcYnM.d.cts +301 -0
- package/dist/types-D0FlcYnM.d.cts.map +1 -0
- package/dist/types-D0FlcYnM.d.ts +301 -0
- package/dist/types-D0FlcYnM.d.ts.map +1 -0
- package/dist/visuals/index.cjs +10 -4
- package/dist/visuals/index.d.cts +2 -1
- package/dist/visuals/index.d.ts +2 -1
- package/dist/visuals/index.js +1 -2
- package/package.json +27 -11
- package/dist/chunk-3GWWZKX7.js +0 -38
- package/dist/chunk-3QFYBBL6.cjs +0 -4759
- package/dist/chunk-3XD4HIFL.js +0 -3241
- package/dist/chunk-AFF2HPE5.cjs +0 -5008
- package/dist/chunk-NXZJIHEZ.cjs +0 -3241
- package/dist/chunk-ONE3C5RV.cjs +0 -38
- package/dist/chunk-RBM2RNC2.js +0 -5008
- package/dist/chunk-VBGPEW45.js +0 -4759
- package/dist/index-BZ_lBlO1.d.ts +0 -474
- package/dist/index-BuvxoWHf.d.cts +0 -474
- package/dist/index-DWyqDIkH.d.cts +0 -1689
- package/dist/index-Uyijm14M.d.ts +0 -1689
- package/dist/types-D4-0lwaE.d.cts +0 -298
- package/dist/types-D4-0lwaE.d.ts +0 -298
package/dist/theme/server.cjs
CHANGED
|
@@ -1,232 +1,264 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("@reopt-ai/opt-palette");
|
|
3
|
+
const THEME_REGISTRY = {
|
|
4
|
+
default: {
|
|
5
|
+
id: "default",
|
|
6
|
+
label: "Default",
|
|
7
|
+
description: "Blue accent, balanced radius & shadow",
|
|
8
|
+
palette: {
|
|
9
|
+
seed: "#2563eb",
|
|
10
|
+
harmony: "split-complementary",
|
|
11
|
+
radiusScale: "medium",
|
|
12
|
+
shadowIntensity: "subtle",
|
|
13
|
+
neutralTemperature: "cool"
|
|
14
|
+
},
|
|
15
|
+
switcherSwatches: [
|
|
16
|
+
"hsl(221 83% 53%)",
|
|
17
|
+
"hsl(142 71% 45%)",
|
|
18
|
+
"hsl(38 92% 50%)"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
minimal: {
|
|
22
|
+
id: "minimal",
|
|
23
|
+
label: "Minimal",
|
|
24
|
+
description: "Monochrome, no shadow, sharp edges",
|
|
25
|
+
palette: {
|
|
26
|
+
seed: "#333333",
|
|
27
|
+
harmony: "analogous",
|
|
28
|
+
radiusScale: "sharp",
|
|
29
|
+
shadowIntensity: "none",
|
|
30
|
+
neutralTemperature: "cool"
|
|
31
|
+
},
|
|
32
|
+
switcherSwatches: [
|
|
33
|
+
"hsl(0 0% 20%)",
|
|
34
|
+
"hsl(0 0% 45%)",
|
|
35
|
+
"hsl(0 0% 70%)"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
natural: {
|
|
39
|
+
id: "natural",
|
|
40
|
+
label: "Natural",
|
|
41
|
+
description: "Always light — sage accent, warm cream",
|
|
42
|
+
forceLightOnly: true,
|
|
43
|
+
palette: {
|
|
44
|
+
seed: "#5a9376",
|
|
45
|
+
harmony: "complementary",
|
|
46
|
+
radiusScale: "medium",
|
|
47
|
+
shadowIntensity: "subtle",
|
|
48
|
+
neutralTemperature: "warm"
|
|
49
|
+
},
|
|
50
|
+
switcherSwatches: [
|
|
51
|
+
"hsl(155 38% 45%)",
|
|
52
|
+
"hsl(25 65% 55%)",
|
|
53
|
+
"hsl(45 75% 50%)"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
pro: {
|
|
57
|
+
id: "pro",
|
|
58
|
+
label: "Pro",
|
|
59
|
+
description: "Neon blue accent, mono headings, ultra-dense",
|
|
60
|
+
palette: {
|
|
61
|
+
seed: "#0080ff",
|
|
62
|
+
harmony: "tetradic",
|
|
63
|
+
radiusScale: "sharp",
|
|
64
|
+
shadowIntensity: "subtle",
|
|
65
|
+
neutralTemperature: "cool"
|
|
66
|
+
},
|
|
67
|
+
switcherSwatches: [
|
|
68
|
+
"hsl(210 100% 55%)",
|
|
69
|
+
"hsl(170 90% 48%)",
|
|
70
|
+
"hsl(290 85% 60%)"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
"mono-dark": {
|
|
74
|
+
id: "mono-dark",
|
|
75
|
+
label: "Mono Dark",
|
|
76
|
+
description: "OLED-friendly black, neon cyan accent, mono headings",
|
|
77
|
+
palette: {
|
|
78
|
+
seed: "#00d4ff",
|
|
79
|
+
harmony: "tetradic",
|
|
80
|
+
radiusScale: "sharp",
|
|
81
|
+
shadowIntensity: "subtle",
|
|
82
|
+
neutralTemperature: "cool"
|
|
83
|
+
},
|
|
84
|
+
switcherSwatches: [
|
|
85
|
+
"hsl(190 100% 50%)",
|
|
86
|
+
"hsl(0 0% 8%)",
|
|
87
|
+
"hsl(280 90% 65%)"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
9
90
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/theme-server.ts
|
|
21
|
-
var theme_server_exports = {};
|
|
22
|
-
__export(theme_server_exports, {
|
|
23
|
-
ALL_COMPOUND_THEMES: () => ALL_COMPOUND_THEMES,
|
|
24
|
-
DARK_MQ: () => DARK_MQ,
|
|
25
|
-
FORCE_LIGHT_PRESETS: () => FORCE_LIGHT_PRESETS,
|
|
26
|
-
LEGACY_THEME_STORAGE_KEY: () => LEGACY_THEME_STORAGE_KEY,
|
|
27
|
-
THEME_MODE_STORAGE_KEY: () => THEME_MODE_STORAGE_KEY,
|
|
28
|
-
THEME_MODE_VALUES: () => THEME_MODE_VALUES,
|
|
29
|
-
THEME_PRESET_STORAGE_KEY: () => THEME_PRESET_STORAGE_KEY,
|
|
30
|
-
THEME_PRESET_VALUES: () => THEME_PRESET_VALUES,
|
|
31
|
-
coerceThemeMode: () => coerceThemeMode,
|
|
32
|
-
createThemeBootScript: () => createThemeBootScript,
|
|
33
|
-
getCompoundTheme: () => getCompoundTheme,
|
|
34
|
-
isThemeMode: () => isThemeMode,
|
|
35
|
-
isThemePreset: () => isThemePreset,
|
|
36
|
-
readStoredTheme: () => readStoredTheme,
|
|
37
|
-
resolveThemeMode: () => resolveThemeMode
|
|
38
|
-
});
|
|
39
|
-
module.exports = __toCommonJS(theme_server_exports);
|
|
40
|
-
|
|
41
|
-
// src/lib/theme/presets/index.ts
|
|
42
|
-
var DEFAULT_DESCRIPTOR = {
|
|
43
|
-
id: "default",
|
|
44
|
-
label: "Default",
|
|
45
|
-
description: "Blue accent, balanced radius & shadow",
|
|
46
|
-
palette: {
|
|
47
|
-
seed: "#2563eb",
|
|
48
|
-
harmony: "split-complementary",
|
|
49
|
-
radiusScale: "medium",
|
|
50
|
-
shadowIntensity: "subtle",
|
|
51
|
-
neutralTemperature: "cool"
|
|
52
|
-
},
|
|
53
|
-
switcherSwatches: ["hsl(221 83% 53%)", "hsl(142 71% 45%)", "hsl(38 92% 50%)"]
|
|
54
|
-
};
|
|
55
|
-
var MINIMAL_DESCRIPTOR = {
|
|
56
|
-
id: "minimal",
|
|
57
|
-
label: "Minimal",
|
|
58
|
-
description: "Monochrome, no shadow, sharp edges",
|
|
59
|
-
palette: {
|
|
60
|
-
seed: "#333333",
|
|
61
|
-
harmony: "analogous",
|
|
62
|
-
radiusScale: "sharp",
|
|
63
|
-
shadowIntensity: "none",
|
|
64
|
-
neutralTemperature: "cool"
|
|
65
|
-
},
|
|
66
|
-
switcherSwatches: ["hsl(0 0% 20%)", "hsl(0 0% 45%)", "hsl(0 0% 70%)"]
|
|
67
|
-
};
|
|
68
|
-
var NATURAL_DESCRIPTOR = {
|
|
69
|
-
id: "natural",
|
|
70
|
-
label: "Natural",
|
|
71
|
-
description: "Always light \u2014 sage accent, warm cream",
|
|
72
|
-
forceLightOnly: true,
|
|
73
|
-
palette: {
|
|
74
|
-
seed: "#5a9376",
|
|
75
|
-
harmony: "complementary",
|
|
76
|
-
radiusScale: "medium",
|
|
77
|
-
shadowIntensity: "subtle",
|
|
78
|
-
neutralTemperature: "warm"
|
|
79
|
-
},
|
|
80
|
-
switcherSwatches: ["hsl(155 38% 45%)", "hsl(25 65% 55%)", "hsl(45 75% 50%)"]
|
|
81
|
-
};
|
|
82
|
-
var PRO_DESCRIPTOR = {
|
|
83
|
-
id: "pro",
|
|
84
|
-
label: "Pro",
|
|
85
|
-
description: "Neon blue accent, mono headings, ultra-dense",
|
|
86
|
-
palette: {
|
|
87
|
-
seed: "#0080ff",
|
|
88
|
-
harmony: "tetradic",
|
|
89
|
-
radiusScale: "sharp",
|
|
90
|
-
shadowIntensity: "subtle",
|
|
91
|
-
neutralTemperature: "cool"
|
|
92
|
-
},
|
|
93
|
-
switcherSwatches: [
|
|
94
|
-
"hsl(210 100% 55%)",
|
|
95
|
-
"hsl(170 90% 48%)",
|
|
96
|
-
"hsl(290 85% 60%)"
|
|
97
|
-
]
|
|
98
|
-
};
|
|
99
|
-
var MONO_DARK_DESCRIPTOR = {
|
|
100
|
-
id: "mono-dark",
|
|
101
|
-
label: "Mono Dark",
|
|
102
|
-
description: "OLED-friendly black, neon cyan accent, mono headings",
|
|
103
|
-
palette: {
|
|
104
|
-
seed: "#00d4ff",
|
|
105
|
-
harmony: "tetradic",
|
|
106
|
-
radiusScale: "sharp",
|
|
107
|
-
shadowIntensity: "subtle",
|
|
108
|
-
neutralTemperature: "cool"
|
|
109
|
-
},
|
|
110
|
-
switcherSwatches: ["hsl(190 100% 50%)", "hsl(0 0% 8%)", "hsl(280 90% 65%)"]
|
|
111
|
-
};
|
|
112
|
-
var THEME_REGISTRY = {
|
|
113
|
-
default: DEFAULT_DESCRIPTOR,
|
|
114
|
-
minimal: MINIMAL_DESCRIPTOR,
|
|
115
|
-
natural: NATURAL_DESCRIPTOR,
|
|
116
|
-
pro: PRO_DESCRIPTOR,
|
|
117
|
-
"mono-dark": MONO_DARK_DESCRIPTOR
|
|
118
|
-
};
|
|
119
|
-
var THEME_PRESET_IDS = Object.keys(THEME_REGISTRY);
|
|
91
|
+
/** All registered preset ids in declaration order. */
|
|
92
|
+
const THEME_PRESET_IDS = Object.keys(THEME_REGISTRY);
|
|
93
|
+
/** Type guard for a known preset id. */
|
|
120
94
|
function isThemePresetId(id) {
|
|
121
|
-
|
|
95
|
+
return id in THEME_REGISTRY;
|
|
122
96
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
97
|
+
/** Preset ids that suppress dark mode generation. */
|
|
98
|
+
const FORCE_LIGHT_PRESET_IDS = new Set(THEME_PRESET_IDS.filter((id) => THEME_REGISTRY[id].forceLightOnly));
|
|
99
|
+
/**
|
|
100
|
+
* Map from removed preset ids to the closest surviving preset. Boot script and
|
|
101
|
+
* `readStoredTheme` consult this so users with persisted `corporate`/`playful`
|
|
102
|
+
* values silently land on a working preset on next page load instead of
|
|
103
|
+
* showing the global default fallback for an unknown id.
|
|
104
|
+
*
|
|
105
|
+
* Keep this around indefinitely — localStorage values are forever and the
|
|
106
|
+
* cost of two extra entries is negligible.
|
|
107
|
+
*/
|
|
108
|
+
const DEPRECATED_PRESET_MIGRATIONS = Object.freeze({
|
|
109
|
+
corporate: "default",
|
|
110
|
+
playful: "default"
|
|
129
111
|
});
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a possibly-deprecated preset id to a registered one. Returns the
|
|
114
|
+
* input unchanged when it is already valid; returns the migration target when
|
|
115
|
+
* it is a known deprecated id; returns `null` when the id is unknown
|
|
116
|
+
* altogether (caller should fall back to its default).
|
|
117
|
+
*/
|
|
130
118
|
function migrateDeprecatedPresetId(id) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return null;
|
|
119
|
+
if (!id) return null;
|
|
120
|
+
if (isThemePresetId(id)) return id;
|
|
121
|
+
if (id in DEPRECATED_PRESET_MIGRATIONS) return DEPRECATED_PRESET_MIGRATIONS[id];
|
|
122
|
+
return null;
|
|
137
123
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/lib/theme/theme-serialize.ts
|
|
126
|
+
/**
|
|
127
|
+
* theme-serialize.ts
|
|
128
|
+
*
|
|
129
|
+
* Pure helpers that turn a `ThemeSpec` into the artifacts the runtime needs:
|
|
130
|
+
* resolved descriptor + mode, computed token maps for generated palettes, and
|
|
131
|
+
* `<style>` CSS strings ready to be injected into `<head>`.
|
|
132
|
+
*
|
|
133
|
+
* Kept side-effect free so the boot script and the provider can share the
|
|
134
|
+
* same logic without dragging React into the client bundle's critical path.
|
|
135
|
+
*/
|
|
136
|
+
/** Element id used for the global generated theme style tag. */
|
|
137
|
+
const GLOBAL_THEME_STYLE_ID = "opt-global-theme";
|
|
138
|
+
/** localStorage key for the persisted ThemeSpec (generated mode). */
|
|
139
|
+
const THEME_SPEC_STORAGE_KEY = "opt-theme-spec";
|
|
140
|
+
/**
|
|
141
|
+
* localStorage key for the cached, pre-serialized token maps that match the
|
|
142
|
+
* spec under `THEME_SPEC_STORAGE_KEY`. The boot script reads this directly so
|
|
143
|
+
* it can inline tokens without invoking opt-palette at startup.
|
|
144
|
+
*/
|
|
145
|
+
const THEME_TOKENS_STORAGE_KEY = "opt-theme-tokens";
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/lib/theme/theme-resolution.ts
|
|
148
|
+
/**
|
|
149
|
+
* Registered preset id list. Preferred for runtime iteration.
|
|
150
|
+
* @deprecated Prefer `THEME_PRESET_IDS` from `./presets`.
|
|
151
|
+
*/
|
|
152
|
+
const THEME_PRESET_VALUES = THEME_PRESET_IDS;
|
|
153
|
+
const THEME_MODE_VALUES = [
|
|
154
|
+
"light",
|
|
155
|
+
"dark",
|
|
156
|
+
"system"
|
|
157
|
+
];
|
|
158
|
+
const LEGACY_THEME_STORAGE_KEY = "opt-theme";
|
|
159
|
+
const THEME_PRESET_STORAGE_KEY = "opt-preset";
|
|
160
|
+
const THEME_MODE_STORAGE_KEY = "opt-mode";
|
|
161
|
+
const DARK_MQ = "(prefers-color-scheme: dark)";
|
|
162
|
+
/**
|
|
163
|
+
* Presets that force light mode regardless of system dark/light preference.
|
|
164
|
+
* Mirrors `FORCE_LIGHT_PRESET_IDS` from `./presets` — kept as alias for
|
|
165
|
+
* existing imports.
|
|
166
|
+
*/
|
|
167
|
+
const FORCE_LIGHT_PRESETS = FORCE_LIGHT_PRESET_IDS;
|
|
168
|
+
/** All valid compound theme names. Useful for static enumeration. */
|
|
169
|
+
const ALL_COMPOUND_THEMES = THEME_PRESET_IDS.flatMap((id) => FORCE_LIGHT_PRESET_IDS.has(id) ? [id] : [id, `${id}-dark`]);
|
|
156
170
|
function hasStorageMutation(storage) {
|
|
157
|
-
|
|
171
|
+
return typeof storage.setItem === "function" && typeof storage.removeItem === "function";
|
|
158
172
|
}
|
|
173
|
+
/** Handles is theme preset. */
|
|
159
174
|
function isThemePreset(value) {
|
|
160
|
-
|
|
175
|
+
return typeof value === "string" && THEME_PRESET_VALUES.includes(value);
|
|
161
176
|
}
|
|
177
|
+
/** Handles is theme mode. */
|
|
162
178
|
function isThemeMode(value) {
|
|
163
|
-
|
|
179
|
+
return typeof value === "string" && THEME_MODE_VALUES.includes(value);
|
|
164
180
|
}
|
|
181
|
+
/** Compute compound theme name from preset + resolved mode. */
|
|
165
182
|
function getCompoundTheme(preset, resolvedMode) {
|
|
166
|
-
|
|
167
|
-
|
|
183
|
+
if (FORCE_LIGHT_PRESETS.has(preset)) return preset;
|
|
184
|
+
return resolvedMode === "dark" ? `${preset}-dark` : preset;
|
|
168
185
|
}
|
|
186
|
+
/** Handles resolve theme mode. */
|
|
169
187
|
function resolveThemeMode(preset, mode, systemDark) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
188
|
+
if (FORCE_LIGHT_PRESETS.has(preset)) return "light";
|
|
189
|
+
if (mode === "system") return systemDark ? "dark" : "light";
|
|
190
|
+
return mode;
|
|
173
191
|
}
|
|
192
|
+
/** Handles read stored theme. */
|
|
174
193
|
function readStoredTheme(storage, defaultPreset, defaultMode, options = {}) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
const legacy = storage.getItem(LEGACY_THEME_STORAGE_KEY);
|
|
195
|
+
const storedPreset = storage.getItem(THEME_PRESET_STORAGE_KEY);
|
|
196
|
+
const storedMode = storage.getItem(THEME_MODE_STORAGE_KEY);
|
|
197
|
+
let preset = defaultPreset;
|
|
198
|
+
if (typeof legacy === "string") {
|
|
199
|
+
const migratedLegacy = migrateDeprecatedPresetId(legacy);
|
|
200
|
+
if (migratedLegacy) {
|
|
201
|
+
if (options.migrateLegacy && hasStorageMutation(storage)) {
|
|
202
|
+
storage.setItem(THEME_PRESET_STORAGE_KEY, migratedLegacy);
|
|
203
|
+
storage.removeItem(LEGACY_THEME_STORAGE_KEY);
|
|
204
|
+
}
|
|
205
|
+
preset = migratedLegacy;
|
|
206
|
+
}
|
|
207
|
+
} else if (typeof storedPreset === "string") {
|
|
208
|
+
const migrated = migrateDeprecatedPresetId(storedPreset);
|
|
209
|
+
if (migrated) {
|
|
210
|
+
preset = migrated;
|
|
211
|
+
if (hasStorageMutation(storage) && migrated !== storedPreset && storedPreset in DEPRECATED_PRESET_MIGRATIONS) storage.setItem(THEME_PRESET_STORAGE_KEY, migrated);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const mode = isThemeMode(storedMode) ? storedMode : defaultMode;
|
|
215
|
+
return {
|
|
216
|
+
preset,
|
|
217
|
+
mode
|
|
218
|
+
};
|
|
199
219
|
}
|
|
220
|
+
/** Normalize a mode against an optional allowed-mode list. */
|
|
200
221
|
function coerceThemeMode(mode, allowedModes, fallback = "system") {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
222
|
+
var _allowedModes$;
|
|
223
|
+
if (!allowedModes || allowedModes.length === 0) return mode;
|
|
224
|
+
if (allowedModes.includes(mode)) return mode;
|
|
225
|
+
if (allowedModes.includes(fallback)) return fallback;
|
|
226
|
+
return (_allowedModes$ = allowedModes[0]) !== null && _allowedModes$ !== void 0 ? _allowedModes$ : fallback;
|
|
206
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Build the inline `<head>` boot script that paints the correct theme before
|
|
230
|
+
* React mounts. Two paths:
|
|
231
|
+
*
|
|
232
|
+
* 1. **Generated** — when both `opt-theme-spec` (kind: "generated") and
|
|
233
|
+
* `opt-theme-tokens` are present and well-formed, a `<style id="…">` tag
|
|
234
|
+
* is inserted with the cached tokens and `<html data-theme>` is set to the
|
|
235
|
+
* generated id (with optional `-dark` suffix). This bypasses opt-palette
|
|
236
|
+
* at startup so first paint is instant.
|
|
237
|
+
* 2. **Preset (legacy)** — falls through to the existing preset selector,
|
|
238
|
+
* including legacy `opt-theme` → `opt-preset` migration.
|
|
239
|
+
*
|
|
240
|
+
* Returned as a single minified line; intended for `dangerouslySetInnerHTML`.
|
|
241
|
+
*/
|
|
207
242
|
function createThemeBootScript(defaultPreset = "default", defaultMode = "system", options = {}) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const legacyKey = JSON.stringify(LEGACY_THEME_STORAGE_KEY);
|
|
228
|
-
const darkMq = JSON.stringify(DARK_MQ);
|
|
229
|
-
const source = `
|
|
243
|
+
var _options$allowedModes, _allowedModes$2;
|
|
244
|
+
const presetValues = JSON.stringify(THEME_PRESET_VALUES);
|
|
245
|
+
const modeValues = JSON.stringify(THEME_MODE_VALUES);
|
|
246
|
+
const allowedModes = ((_options$allowedModes = options.allowedModes) === null || _options$allowedModes === void 0 ? void 0 : _options$allowedModes.length) ? options.allowedModes : THEME_MODE_VALUES;
|
|
247
|
+
const allowedModeValues = JSON.stringify(allowedModes);
|
|
248
|
+
const forceLightPresets = JSON.stringify(Array.from(FORCE_LIGHT_PRESETS));
|
|
249
|
+
const deprecatedMap = JSON.stringify(DEPRECATED_PRESET_MIGRATIONS);
|
|
250
|
+
const lockedPreset = options.lockedPreset;
|
|
251
|
+
const defaultPresetLiteral = JSON.stringify(lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : defaultPreset);
|
|
252
|
+
const defaultModeLiteral = JSON.stringify(coerceThemeMode(defaultMode, allowedModes, (_allowedModes$2 = allowedModes[0]) !== null && _allowedModes$2 !== void 0 ? _allowedModes$2 : "system"));
|
|
253
|
+
const lockedPresetLiteral = JSON.stringify(lockedPreset !== null && lockedPreset !== void 0 ? lockedPreset : null);
|
|
254
|
+
const styleId = JSON.stringify(GLOBAL_THEME_STYLE_ID);
|
|
255
|
+
const specKey = JSON.stringify(THEME_SPEC_STORAGE_KEY);
|
|
256
|
+
const tokensKey = JSON.stringify(THEME_TOKENS_STORAGE_KEY);
|
|
257
|
+
const presetKey = JSON.stringify(THEME_PRESET_STORAGE_KEY);
|
|
258
|
+
const modeKey = JSON.stringify(THEME_MODE_STORAGE_KEY);
|
|
259
|
+
const legacyKey = JSON.stringify(LEGACY_THEME_STORAGE_KEY);
|
|
260
|
+
const darkMq = JSON.stringify(DARK_MQ);
|
|
261
|
+
return `
|
|
230
262
|
try {
|
|
231
263
|
var pv=${presetValues},mv=${modeValues},am=${allowedModeValues},fp=${forceLightPresets},dm=${deprecatedMap},lk=${lockedPresetLiteral};
|
|
232
264
|
function mp(v){if(typeof v!=="string")return null;if(pv.indexOf(v)>=0)return v;return Object.prototype.hasOwnProperty.call(dm,v)?dm[v]:null;}
|
|
@@ -258,24 +290,21 @@ try {
|
|
|
258
290
|
var d=fp.indexOf(p)<0&&(m==="dark"||(m==="system"&&matchMedia(${darkMq}).matches));
|
|
259
291
|
document.documentElement.setAttribute("data-theme",d?p+"-dark":p);
|
|
260
292
|
}
|
|
261
|
-
} catch(e){}
|
|
262
|
-
return source.replace(/\n\s*/g, "");
|
|
293
|
+
} catch(e){}`.replace(/\n\s*/g, "");
|
|
263
294
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
resolveThemeMode
|
|
281
|
-
});
|
|
295
|
+
//#endregion
|
|
296
|
+
exports.ALL_COMPOUND_THEMES = ALL_COMPOUND_THEMES;
|
|
297
|
+
exports.DARK_MQ = DARK_MQ;
|
|
298
|
+
exports.FORCE_LIGHT_PRESETS = FORCE_LIGHT_PRESETS;
|
|
299
|
+
exports.LEGACY_THEME_STORAGE_KEY = LEGACY_THEME_STORAGE_KEY;
|
|
300
|
+
exports.THEME_MODE_STORAGE_KEY = THEME_MODE_STORAGE_KEY;
|
|
301
|
+
exports.THEME_MODE_VALUES = THEME_MODE_VALUES;
|
|
302
|
+
exports.THEME_PRESET_STORAGE_KEY = THEME_PRESET_STORAGE_KEY;
|
|
303
|
+
exports.THEME_PRESET_VALUES = THEME_PRESET_VALUES;
|
|
304
|
+
exports.coerceThemeMode = coerceThemeMode;
|
|
305
|
+
exports.createThemeBootScript = createThemeBootScript;
|
|
306
|
+
exports.getCompoundTheme = getCompoundTheme;
|
|
307
|
+
exports.isThemeMode = isThemeMode;
|
|
308
|
+
exports.isThemePreset = isThemePreset;
|
|
309
|
+
exports.readStoredTheme = readStoredTheme;
|
|
310
|
+
exports.resolveThemeMode = resolveThemeMode;
|
package/dist/theme/server.d.cts
CHANGED
|
@@ -1,53 +1,40 @@
|
|
|
1
|
-
import { PaletteConfig } from
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* presets/index.ts
|
|
5
|
-
*
|
|
6
|
-
* Single registry of theme preset metadata. Each entry pairs a stable id
|
|
7
|
-
* (used in `<html data-theme>` and localStorage) with display metadata and an
|
|
8
|
-
* optional `PaletteConfig` that approximates the preset's seed for the
|
|
9
|
-
* ThemeSwitcher swatch row and "clone to custom" workflow.
|
|
10
|
-
*
|
|
11
|
-
* Token values themselves currently live in the sibling `*.css` files. A
|
|
12
|
-
* follow-up sub-phase will migrate the full token tables into this file and
|
|
13
|
-
* have a codegen step emit the CSS, but the metadata layer is enough to
|
|
14
|
-
* unblock dynamic ThemeSwitcher rendering and type-safe preset id unions.
|
|
15
|
-
*/
|
|
16
|
-
|
|
1
|
+
import { PaletteConfig } from "@reopt-ai/opt-palette";
|
|
2
|
+
//#region src/lib/theme/presets/index.d.ts
|
|
17
3
|
interface ThemeDescriptor {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
4
|
+
/** Stable id used in `<html data-theme="...">` and localStorage. */
|
|
5
|
+
readonly id: string;
|
|
6
|
+
/** Human-readable label shown in ThemeSwitcher. */
|
|
7
|
+
readonly label: string;
|
|
8
|
+
/** Short description shown under the label. */
|
|
9
|
+
readonly description: string;
|
|
10
|
+
/**
|
|
11
|
+
* Optional engine input that approximates this preset. Used by
|
|
12
|
+
* ThemeSwitcher to derive swatches when `switcherSwatches` is omitted, and
|
|
13
|
+
* as the starting point when a user clones a preset into a custom palette.
|
|
14
|
+
* Codegen does NOT consume this in the current phase — the static `*.css`
|
|
15
|
+
* file remains the source of token values.
|
|
16
|
+
*/
|
|
17
|
+
readonly palette?: PaletteConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Three CSS color strings for the ThemeSwitcher swatch row. Falls back to
|
|
20
|
+
* the live `--opt-accent` / `--opt-surface` / `--opt-text` tokens when
|
|
21
|
+
* omitted.
|
|
22
|
+
*/
|
|
23
|
+
readonly switcherSwatches?: readonly [string, string, string];
|
|
24
|
+
/** Disable dark variant generation entirely. */
|
|
25
|
+
readonly forceLightOnly?: boolean;
|
|
40
26
|
}
|
|
41
27
|
declare const THEME_REGISTRY: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
28
|
+
readonly default: ThemeDescriptor;
|
|
29
|
+
readonly minimal: ThemeDescriptor;
|
|
30
|
+
readonly natural: ThemeDescriptor;
|
|
31
|
+
readonly pro: ThemeDescriptor;
|
|
32
|
+
readonly "mono-dark": ThemeDescriptor;
|
|
47
33
|
};
|
|
48
34
|
/** Compile-time-derived union of registered preset ids. */
|
|
49
35
|
type ThemePresetId = keyof typeof THEME_REGISTRY;
|
|
50
|
-
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/lib/theme/theme-resolution.d.ts
|
|
51
38
|
/**
|
|
52
39
|
* Registered preset id list. Preferred for runtime iteration.
|
|
53
40
|
* @deprecated Prefer `THEME_PRESET_IDS` from `./presets`.
|
|
@@ -60,17 +47,17 @@ declare const THEME_MODE_VALUES: readonly ["light", "dark", "system"];
|
|
|
60
47
|
type ThemeMode = (typeof THEME_MODE_VALUES)[number];
|
|
61
48
|
/** Runtime constraints for apps that expose only a subset of opt-ui theming. */
|
|
62
49
|
interface ThemeRuntimeOptions {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Force the root theme to one preset regardless of stored preset/generated
|
|
52
|
+
* theme state. Mode is still resolved normally unless constrained.
|
|
53
|
+
*/
|
|
54
|
+
lockedPreset?: ThemePreset;
|
|
55
|
+
/**
|
|
56
|
+
* Restrict mode reads/writes to a smaller set, e.g. `["light", "dark"]`.
|
|
57
|
+
* The first value becomes the fallback when the stored/default mode is not
|
|
58
|
+
* allowed.
|
|
59
|
+
*/
|
|
60
|
+
allowedModes?: readonly ThemeMode[];
|
|
74
61
|
}
|
|
75
62
|
/**
|
|
76
63
|
* Compound theme value applied to `<html data-theme>`. Derived from the
|
|
@@ -91,7 +78,7 @@ declare const FORCE_LIGHT_PRESETS: ReadonlySet<ThemePreset>;
|
|
|
91
78
|
/** All valid compound theme names. Useful for static enumeration. */
|
|
92
79
|
declare const ALL_COMPOUND_THEMES: CompoundTheme[];
|
|
93
80
|
interface ThemeStorageReader {
|
|
94
|
-
|
|
81
|
+
getItem(key: string): string | null;
|
|
95
82
|
}
|
|
96
83
|
/** Handles is theme preset. */
|
|
97
84
|
declare function isThemePreset(value: string | null): value is ThemePreset;
|
|
@@ -103,10 +90,10 @@ declare function getCompoundTheme(preset: ThemePreset, resolvedMode: "light" | "
|
|
|
103
90
|
declare function resolveThemeMode(preset: ThemePreset, mode: ThemeMode, systemDark: boolean): "light" | "dark";
|
|
104
91
|
/** Handles read stored theme. */
|
|
105
92
|
declare function readStoredTheme(storage: ThemeStorageReader, defaultPreset: ThemePreset, defaultMode: ThemeMode, options?: {
|
|
106
|
-
|
|
93
|
+
migrateLegacy?: boolean;
|
|
107
94
|
}): {
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
preset: ThemePreset;
|
|
96
|
+
mode: ThemeMode;
|
|
110
97
|
};
|
|
111
98
|
/** Normalize a mode against an optional allowed-mode list. */
|
|
112
99
|
declare function coerceThemeMode(mode: ThemeMode, allowedModes: readonly ThemeMode[] | undefined, fallback?: ThemeMode): ThemeMode;
|
|
@@ -125,5 +112,6 @@ declare function coerceThemeMode(mode: ThemeMode, allowedModes: readonly ThemeMo
|
|
|
125
112
|
* Returned as a single minified line; intended for `dangerouslySetInnerHTML`.
|
|
126
113
|
*/
|
|
127
114
|
declare function createThemeBootScript(defaultPreset?: ThemePreset, defaultMode?: ThemeMode, options?: ThemeRuntimeOptions): string;
|
|
128
|
-
|
|
115
|
+
//#endregion
|
|
129
116
|
export { ALL_COMPOUND_THEMES, type CompoundTheme, DARK_MQ, FORCE_LIGHT_PRESETS, LEGACY_THEME_STORAGE_KEY, THEME_MODE_STORAGE_KEY, THEME_MODE_VALUES, THEME_PRESET_STORAGE_KEY, THEME_PRESET_VALUES, type ThemeMode, type ThemePreset, type ThemeRuntimeOptions, coerceThemeMode, createThemeBootScript, getCompoundTheme, isThemeMode, isThemePreset, readStoredTheme, resolveThemeMode };
|
|
117
|
+
//# sourceMappingURL=server.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.cts","names":[],"sources":["../../src/lib/theme/presets/index.ts","../../src/lib/theme/theme-resolution.ts"],"mappings":";;UAgBiB;;WAEN;;WAEA;;WAEA;;;;;;;;WAQA,UAAU;;;;;;WAMV;;WAEA;;cA8EE;;;;;;;;KASD,6BAA6B;;;;;;;cC5G5B,8BAA8B;;KAG/B,cAAc;cAEb;;KAED,oBAAoB;;UAGf;;;;;EAKf,eAAe;;;;;;EAMf,wBAAwB;;;;;;;KAQd,mBAAmB,mBAAmB;cAErC;cACA;cACA;cACA;;;;;;cAOA,qBAAqB,YAAY;;cAIjC,qBAAqB;UAOxB;EACR,QAAQ;;;iBAkBM,cAAc,uBAAuB,SAAS;;iBAQ9C,YAAY,uBAAuB,SAAS;;iBAO5C,iBACd,QAAQ,aACR,iCACC;;iBAMa,iBACd,QAAQ,aACR,MAAM,WACN;;iBAQc,gBACd,SAAS,oBACT,eAAe,aACf,aAAa,WACb;EAAW;;EACR,QAAQ;EAAa,MAAM;;;iBAqChB,gBACd,MAAM,WACN,uBAAuB,yBACvB,WAAU,YACT;;;;;;;;;;;;;;;iBAqBa,sBACd,gBAAe,aACf,cAAa,WACb,UAAS"}
|