ngx-theme-stack 2.0.0 → 2.1.1
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/README.md +133 -12
- package/fesm2022/ngx-theme-stack.mjs +50 -32
- package/fesm2022/ngx-theme-stack.mjs.map +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/anti-flash.d.ts +2 -0
- package/schematics/ng-add/anti-flash.js +53 -31
- package/schematics/ng-add/anti-flash.js.map +1 -1
- package/schematics/ng-add/app-config.js +5 -3
- package/schematics/ng-add/app-config.js.map +1 -1
- package/schematics/ng-add/constants.d.ts +1 -0
- package/schematics/ng-add/constants.js +1 -0
- package/schematics/ng-add/constants.js.map +1 -1
- package/schematics/ng-add/index.js +89 -12
- package/schematics/ng-add/index.js.map +1 -1
- package/schematics/ng-add/schema.d.ts +2 -0
- package/schematics/ng-add/schema.json +7 -2
- package/schematics/ng-add/utils.d.ts +1 -6
- package/schematics/ng-add/utils.js +11 -27
- package/schematics/ng-add/utils.js.map +1 -1
- package/schematics/sync/index.d.ts +0 -9
- package/schematics/sync/index.js +208 -42
- package/schematics/sync/index.js.map +1 -1
- package/schematics/sync/schema.d.ts +2 -0
- package/schematics/sync/schema.json +5 -0
- package/types/ngx-theme-stack.d.ts +70 -31
package/schematics/sync/index.js
CHANGED
|
@@ -5,36 +5,36 @@ const constants_1 = require("../ng-add/constants");
|
|
|
5
5
|
// ── Regex patterns ────────────────────────────────────────────────────────────
|
|
6
6
|
/**
|
|
7
7
|
* Matches the provideThemeStack() call in app.config.ts.
|
|
8
|
-
* Captures the full options object string (may be empty).
|
|
8
|
+
* Captures the full options object string (may be empty or span multiple lines).
|
|
9
9
|
*
|
|
10
10
|
* Examples matched:
|
|
11
11
|
* provideThemeStack()
|
|
12
12
|
* provideThemeStack({ mode: 'attribute', themes: ['dark', 'light'] })
|
|
13
|
+
* provideThemeStack({ ← multi-line call (new explicit format)
|
|
14
|
+
* themes: ['light', 'dark'],
|
|
15
|
+
* defaultTheme: 'system',
|
|
16
|
+
* })
|
|
13
17
|
*/
|
|
14
|
-
const PROVIDE_CALL_RE = /provideThemeStack\s*\(([
|
|
15
|
-
/**
|
|
16
|
-
* Extracts "mode" value from the captured options string.
|
|
17
|
-
* e.g. { mode: 'attribute', ... } → 'attribute'
|
|
18
|
-
*/
|
|
18
|
+
const PROVIDE_CALL_RE = /provideThemeStack\s*\(([\s\S]*?)\)/;
|
|
19
|
+
/** Extracts "mode" value from the captured options string. */
|
|
19
20
|
const OPTION_MODE_RE = /mode\s*:\s*['"]([^'"]+)['"]/;
|
|
20
|
-
/**
|
|
21
|
-
* Extracts "storageKey" value from the captured options string.
|
|
22
|
-
*/
|
|
21
|
+
/** Extracts "storageKey" value from the captured options string. */
|
|
23
22
|
const OPTION_KEY_RE = /storageKey\s*:\s*['"]([^'"]+)['"]/;
|
|
24
|
-
/**
|
|
25
|
-
* Extracts "defaultTheme" value from the captured options string.
|
|
26
|
-
*/
|
|
23
|
+
/** Extracts "defaultTheme" value from the captured options string. */
|
|
27
24
|
const OPTION_DEFAULT_THEME_RE = /defaultTheme\s*:\s*['"]([^'"]+)['"]/;
|
|
25
|
+
const OPTION_STRATEGY_RE = /strategy\s*:\s*['"]([^'"]+)['"]/;
|
|
28
26
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* Extracts the themes array from the options string.
|
|
28
|
+
* Matches: themes: ['light', 'dark', 'sunset']
|
|
31
29
|
*/
|
|
32
|
-
const
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
const OPTION_THEMES_RE = /themes\s*:\s*\[([^\]]*)\]/;
|
|
31
|
+
/** Matches the complete <script> anti-flash block (identified by its marker comment). */
|
|
32
|
+
const SCRIPT_BLOCK_RE = /<!--\s*ngx-theme-stack\s*anti-flash\s*-->\s*<script[^>]*>[\s\S]*?<\/script>/;
|
|
33
|
+
/** Marker injected by ng-add that delimits the Critters Trick zone in <body>. */
|
|
34
|
+
const CRITTERS_MARKER = '<!-- ngx-theme-stack critters-trick -->';
|
|
35
|
+
/** Regex that matches the entire Critters Trick block (marker + divs). */
|
|
36
|
+
const CRITTERS_BLOCK_RE = /<!-- ngx-theme-stack critters-trick -->[\s\S]*?<!-- \/ngx-theme-stack critters-trick -->/;
|
|
37
|
+
// ── Config extraction ─────────────────────────────────────────────────────────
|
|
38
38
|
/**
|
|
39
39
|
* Reads `app.config.ts` (or `main.ts`) and extracts the current
|
|
40
40
|
* `provideThemeStack()` configuration using regex.
|
|
@@ -42,7 +42,7 @@ const SCRIPT_BLOCK_RE = /<!-- ngx-theme-stack anti-flash -->\s*<script>[\s\S]*?<
|
|
|
42
42
|
* Falls back to library defaults for any option that is not found.
|
|
43
43
|
*/
|
|
44
44
|
function extractConfig(tree, sourceRoot, context) {
|
|
45
|
-
var _a, _b, _c, _d, _e, _f;
|
|
45
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
46
46
|
const candidates = [
|
|
47
47
|
`${sourceRoot}/app/app.config.ts`,
|
|
48
48
|
`${sourceRoot}/main.ts`,
|
|
@@ -53,29 +53,37 @@ function extractConfig(tree, sourceRoot, context) {
|
|
|
53
53
|
const content = tree.readText(filePath);
|
|
54
54
|
const provideMatch = PROVIDE_CALL_RE.exec(content);
|
|
55
55
|
if (!provideMatch) {
|
|
56
|
-
context.logger.warn(`⚠ provideThemeStack() not found in ${filePath}. Using library defaults
|
|
56
|
+
context.logger.warn(`⚠ provideThemeStack() not found in ${filePath}. Using library defaults.\n` +
|
|
57
|
+
` Tip: Add provideThemeStack({...}) to your providers for explicit control.`);
|
|
57
58
|
break;
|
|
58
59
|
}
|
|
59
60
|
const opts = provideMatch[1]; // everything inside provideThemeStack(...)
|
|
60
61
|
const mode = (_b = (_a = OPTION_MODE_RE.exec(opts)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : constants_1.DEFAULTS.mode;
|
|
61
62
|
const storageKey = (_d = (_c = OPTION_KEY_RE.exec(opts)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : constants_1.DEFAULTS.storageKey;
|
|
62
63
|
const defaultTheme = (_f = (_e = OPTION_DEFAULT_THEME_RE.exec(opts)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : constants_1.DEFAULTS.defaultTheme;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const strategy = (_h = (_g = OPTION_STRATEGY_RE.exec(opts)) === null || _g === void 0 ? void 0 : _g[1]) !== null && _h !== void 0 ? _h : undefined;
|
|
65
|
+
// Extract themes array: ['light', 'dark', 'sunset'] → ['light', 'dark', 'sunset']
|
|
66
|
+
const themesRaw = (_k = (_j = OPTION_THEMES_RE.exec(opts)) === null || _j === void 0 ? void 0 : _j[1]) !== null && _k !== void 0 ? _k : '';
|
|
67
|
+
const themes = themesRaw
|
|
68
|
+
? themesRaw
|
|
69
|
+
.split(',')
|
|
70
|
+
.map((t) => t.trim().replace(/^['"]|['"]$/g, ''))
|
|
71
|
+
.filter(Boolean)
|
|
72
|
+
: [...constants_1.DEFAULTS.themes];
|
|
73
|
+
return { mode, strategy, storageKey, defaultTheme, themes };
|
|
67
74
|
}
|
|
68
75
|
// Fallback to defaults if no config file found
|
|
69
76
|
return {
|
|
70
77
|
mode: constants_1.DEFAULTS.mode,
|
|
71
78
|
storageKey: constants_1.DEFAULTS.storageKey,
|
|
72
79
|
defaultTheme: constants_1.DEFAULTS.defaultTheme,
|
|
80
|
+
themes: [...constants_1.DEFAULTS.themes],
|
|
73
81
|
};
|
|
74
82
|
}
|
|
75
|
-
// ──
|
|
83
|
+
// ── Anti-flash script generation ──────────────────────────────────────────────
|
|
76
84
|
/**
|
|
77
85
|
* Builds the minimal blocking inline script — identical logic to anti-flash.ts
|
|
78
|
-
* but
|
|
86
|
+
* but kept here to avoid cross-directory dependencies in the schematic build.
|
|
79
87
|
*/
|
|
80
88
|
function buildScript(config) {
|
|
81
89
|
const { storageKey, defaultTheme, mode } = config;
|
|
@@ -92,40 +100,188 @@ function buildScript(config) {
|
|
|
92
100
|
`if(t==='dark'||t==='light')e.style.setProperty('color-scheme',t);` +
|
|
93
101
|
`}catch(x){}})();`);
|
|
94
102
|
}
|
|
103
|
+
// ── Critters Trick div generation ─────────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Generates the hidden divs for the Critters Trick based on the mode.
|
|
106
|
+
*
|
|
107
|
+
* When Angular builds for production, Critters inlines "critical" CSS.
|
|
108
|
+
* It determines "critical" by checking which selectors match elements in the HTML.
|
|
109
|
+
* By placing hidden divs with the theme class/attribute, we trick Critters into
|
|
110
|
+
* inlining ALL theme token blocks — achieving zero-network-request CSS for themes.
|
|
111
|
+
*
|
|
112
|
+
* @param themes - The list of themes to generate divs for (excludes 'system').
|
|
113
|
+
* @param mode - 'class' | 'attribute' | 'both'
|
|
114
|
+
*/
|
|
115
|
+
function buildCrittersDivs(themes, mode) {
|
|
116
|
+
// 'system' is a meta-theme that resolves to 'light' or 'dark'; no CSS selector needed.
|
|
117
|
+
const renderableThemes = themes.filter((t) => t !== 'system');
|
|
118
|
+
const divs = renderableThemes
|
|
119
|
+
.map((theme) => {
|
|
120
|
+
if (mode === 'class') {
|
|
121
|
+
return ` <div class="${theme}"></div>`;
|
|
122
|
+
}
|
|
123
|
+
else if (mode === 'attribute') {
|
|
124
|
+
return ` <div data-theme="${theme}"></div>`;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// 'both'
|
|
128
|
+
return ` <div class="${theme}" data-theme="${theme}"></div>`;
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
.join('\n');
|
|
132
|
+
return (`<!-- ngx-theme-stack critters-trick -->\n` +
|
|
133
|
+
` <div id="ngx-theme-stack-critters-trick" hidden>\n${divs}\n </div>\n` +
|
|
134
|
+
` <!-- /ngx-theme-stack critters-trick -->`);
|
|
135
|
+
}
|
|
95
136
|
// ── index.html patching ───────────────────────────────────────────────────────
|
|
96
|
-
function syncIndexHtml(tree, context, sourceRoot, config) {
|
|
137
|
+
function syncIndexHtml(tree, context, sourceRoot, config, strategy) {
|
|
97
138
|
const candidates = [`${sourceRoot}/index.html`, 'public/index.html'].map((p) => p.startsWith('/') ? p.slice(1) : p);
|
|
98
139
|
for (const path of candidates) {
|
|
99
140
|
if (!tree.exists(path))
|
|
100
141
|
continue;
|
|
101
|
-
|
|
102
|
-
if (!content.includes(
|
|
142
|
+
let content = tree.readText(path);
|
|
143
|
+
if (!content.includes('ngx-theme-stack anti-flash')) {
|
|
103
144
|
context.logger.warn(`⚠ Anti-flash script marker not found in ${path}.\n` +
|
|
104
145
|
` Run 'ng add ngx-theme-stack' first, or add the script manually.`);
|
|
105
146
|
return;
|
|
106
147
|
}
|
|
148
|
+
// ── 1. Sync the anti-flash JS script ───────────────────────────────────
|
|
107
149
|
const newScriptBlock = `<!-- ngx-theme-stack anti-flash -->\n <script>${buildScript(config)}</script>`;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
context.logger.warn(`⚠ Could not replace script block in ${path}. The format may have changed.`);
|
|
150
|
+
if (!SCRIPT_BLOCK_RE.test(content)) {
|
|
151
|
+
context.logger.warn(`⚠ Could not find a valid <script> block after the anti-flash marker in ${path}. The format may have changed.`);
|
|
111
152
|
return;
|
|
112
153
|
}
|
|
113
|
-
|
|
114
|
-
|
|
154
|
+
const updatedScript = content.replace(SCRIPT_BLOCK_RE, newScriptBlock);
|
|
155
|
+
if (updatedScript === content) {
|
|
156
|
+
context.logger.info(`ℹ Anti-flash script in ${path} is already up to date.`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
content = updatedScript;
|
|
160
|
+
context.logger.info(`✔ Anti-flash script synced in ${path}`);
|
|
161
|
+
}
|
|
162
|
+
// ── 2. Sync the Critters Trick divs (only for 'critters' strategy) ─────
|
|
163
|
+
if (strategy === 'critters') {
|
|
164
|
+
const crittersBlock = buildCrittersDivs(config.themes, config.mode);
|
|
165
|
+
const CRITTERS_ID_RE = /<div id="ngx-theme-stack-critters-trick"[\s\S]*?<\/div>/;
|
|
166
|
+
if (CRITTERS_BLOCK_RE.test(content)) {
|
|
167
|
+
content = content.replace(CRITTERS_BLOCK_RE, crittersBlock);
|
|
168
|
+
context.logger.info(`✔ Critters Trick block updated in ${path}`);
|
|
169
|
+
}
|
|
170
|
+
else if (CRITTERS_ID_RE.test(content)) {
|
|
171
|
+
content = content.replace(CRITTERS_ID_RE, crittersBlock);
|
|
172
|
+
context.logger.info(`✔ Critters Trick div wrapped in ${path}`);
|
|
173
|
+
}
|
|
174
|
+
else if (content.includes(CRITTERS_MARKER)) {
|
|
175
|
+
content = content.replace(CRITTERS_MARKER, crittersBlock);
|
|
176
|
+
context.logger.info(`✔ Critters Trick divs injected in ${path}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
content = content.replace('</body>', ` ${crittersBlock}\n </body>`);
|
|
180
|
+
context.logger.info(`✔ Critters Trick block added before </body> in ${path}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// blocking strategy: remove any existing Critters divs if present
|
|
185
|
+
if (CRITTERS_BLOCK_RE.test(content)) {
|
|
186
|
+
content = content.replace(CRITTERS_BLOCK_RE, '');
|
|
187
|
+
context.logger.info(`✔ Critters Trick divs removed (blocking strategy) in ${path}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
tree.overwrite(path, content);
|
|
115
191
|
return;
|
|
116
192
|
}
|
|
117
193
|
context.logger.warn(`⚠ Could not find index.html (tried: ${candidates.join(', ')}).`);
|
|
118
194
|
}
|
|
195
|
+
// ── angular.json patching ───────────────────────────────────────────────────
|
|
196
|
+
function syncAngularJson(tree, context, projectName, strategy) {
|
|
197
|
+
var _a, _b;
|
|
198
|
+
const content = tree.read('/angular.json');
|
|
199
|
+
if (!content)
|
|
200
|
+
return;
|
|
201
|
+
const workspace = JSON.parse(content.toString());
|
|
202
|
+
const project = workspace.projects[projectName];
|
|
203
|
+
if (!project)
|
|
204
|
+
return;
|
|
205
|
+
const buildTarget = (_a = project.architect) === null || _a === void 0 ? void 0 : _a.build;
|
|
206
|
+
if (!buildTarget)
|
|
207
|
+
return;
|
|
208
|
+
const prodConfig = (_b = buildTarget.configurations) === null || _b === void 0 ? void 0 : _b.production;
|
|
209
|
+
if (!prodConfig)
|
|
210
|
+
return;
|
|
211
|
+
if (strategy === 'blocking') {
|
|
212
|
+
// Disable inlineCritical for blocking strategy
|
|
213
|
+
if (typeof prodConfig.optimization === 'object') {
|
|
214
|
+
prodConfig.optimization.styles = prodConfig.optimization.styles || {};
|
|
215
|
+
if (prodConfig.optimization.styles.inlineCritical !== false) {
|
|
216
|
+
prodConfig.optimization.styles.inlineCritical = false;
|
|
217
|
+
context.logger.info(`✔ Disabled inlineCritical in angular.json projects/${projectName} (production).`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// It's either boolean or undefined
|
|
222
|
+
prodConfig.optimization = {
|
|
223
|
+
styles: { inlineCritical: false },
|
|
224
|
+
};
|
|
225
|
+
context.logger.info(`✔ Disabled inlineCritical in angular.json projects/${projectName} (production).`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// Enable inlineCritical (or revert to default) for critters strategy
|
|
230
|
+
if (typeof prodConfig.optimization === 'object' && prodConfig.optimization.styles) {
|
|
231
|
+
if (prodConfig.optimization.styles.inlineCritical === false) {
|
|
232
|
+
prodConfig.optimization.styles.inlineCritical = true;
|
|
233
|
+
context.logger.info(`✔ Re-enabled inlineCritical in angular.json projects/${projectName} (production).`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
tree.overwrite('/angular.json', JSON.stringify(workspace, null, 2));
|
|
238
|
+
}
|
|
119
239
|
// ── Schematic factory ─────────────────────────────────────────────────────────
|
|
120
240
|
/**
|
|
121
241
|
* `ng generate ngx-theme-stack:sync`
|
|
122
242
|
*
|
|
123
243
|
* Reads the current `provideThemeStack()` configuration from `app.config.ts`
|
|
124
|
-
* and regenerates
|
|
244
|
+
* and regenerates:
|
|
245
|
+
*
|
|
246
|
+
* 1. **The anti-flash inline script** in `index.html` — keeping `storageKey`,
|
|
247
|
+
* `defaultTheme`, and `mode` in sync with the Angular provider.
|
|
248
|
+
*
|
|
249
|
+
* 2. **The Critters Trick divs** (if `strategy: 'critters'`) — hidden `<div>`
|
|
250
|
+
* elements that trick Angular's built-in CSS inliner (Critters) into treating
|
|
251
|
+
* all theme token blocks as "critical CSS", inlining them in the `<head>`
|
|
252
|
+
* at build time. This achieves zero-flash without any extra network requests.
|
|
125
253
|
*
|
|
126
|
-
* Run this whenever you change `mode`, `storageKey`, or `
|
|
127
|
-
* inside `provideThemeStack()
|
|
254
|
+
* Run this whenever you change `mode`, `storageKey`, `defaultTheme`, or `themes`
|
|
255
|
+
* inside `provideThemeStack()`. Tip: add it as a `prebuild` script in package.json
|
|
256
|
+
* so it runs automatically before every build.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* // One-off sync
|
|
260
|
+
* ng generate ngx-theme-stack:sync
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* // Automatic sync (recommended — add to package.json)
|
|
264
|
+
* "prebuild": "ng generate ngx-theme-stack:sync"
|
|
128
265
|
*/
|
|
266
|
+
/**
|
|
267
|
+
* Auto-detects the strategy by checking if a Critters marker exists in index.html.
|
|
268
|
+
* This allows the prebuild command to run with zero extra flags.
|
|
269
|
+
*/
|
|
270
|
+
function detectStrategy(tree, sourceRoot, explicitStrategy) {
|
|
271
|
+
if (explicitStrategy)
|
|
272
|
+
return explicitStrategy;
|
|
273
|
+
const candidates = [`${sourceRoot}/index.html`, 'public/index.html'].map((p) => p.startsWith('/') ? p.slice(1) : p);
|
|
274
|
+
for (const path of candidates) {
|
|
275
|
+
if (!tree.exists(path))
|
|
276
|
+
continue;
|
|
277
|
+
const content = tree.readText(path);
|
|
278
|
+
// If either the full block OR the bare marker comment exist → critters
|
|
279
|
+
if (content.includes('ngx-theme-stack critters-trick'))
|
|
280
|
+
return 'critters';
|
|
281
|
+
return 'blocking';
|
|
282
|
+
}
|
|
283
|
+
return 'critters'; // safe default
|
|
284
|
+
}
|
|
129
285
|
function sync(options) {
|
|
130
286
|
return (tree, context) => {
|
|
131
287
|
var _a, _b;
|
|
@@ -140,13 +296,23 @@ function sync(options) {
|
|
|
140
296
|
throw new Error(`Project "${projectName}" not found in angular.json.`);
|
|
141
297
|
}
|
|
142
298
|
const sourceRoot = project.sourceRoot || `${(_b = project.root) !== null && _b !== void 0 ? _b : ''}/src`;
|
|
299
|
+
const config = extractConfig(tree, sourceRoot, context);
|
|
300
|
+
const strategy = (options.strategy || config.strategy || detectStrategy(tree, sourceRoot));
|
|
301
|
+
context.logger.info(` Detected mode : ${config.mode}`);
|
|
302
|
+
context.logger.info(` Detected strategy : ${strategy} ${config.strategy ? '(from code)' : '(auto-detected)'}`);
|
|
303
|
+
context.logger.info(` Detected storageKey : ${config.storageKey}`);
|
|
304
|
+
context.logger.info(` Detected defaultTheme : ${config.defaultTheme}`);
|
|
305
|
+
context.logger.info(` Detected themes : [${config.themes.join(', ')}]`);
|
|
143
306
|
context.logger.info('');
|
|
144
307
|
context.logger.info(`🔄 ngx-theme-stack sync [project: ${projectName}]`);
|
|
145
308
|
context.logger.info('');
|
|
146
|
-
|
|
147
|
-
|
|
309
|
+
syncIndexHtml(tree, context, sourceRoot, config, strategy);
|
|
310
|
+
syncAngularJson(tree, context, projectName, strategy);
|
|
148
311
|
context.logger.info('');
|
|
149
|
-
context.logger.info('✅ Done! The anti-flash
|
|
312
|
+
context.logger.info('✅ Done! The anti-flash setup is now in sync with your provider config.');
|
|
313
|
+
if (strategy === 'critters') {
|
|
314
|
+
context.logger.info(' Critters Trick: theme CSS will be automatically inlined at build time.');
|
|
315
|
+
}
|
|
150
316
|
context.logger.info('');
|
|
151
317
|
};
|
|
152
318
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/sync/index.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/sync/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"$default": {
|
|
11
11
|
"$source": "projectName"
|
|
12
12
|
}
|
|
13
|
+
},
|
|
14
|
+
"strategy": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The strategy to use (critters or blocking). Auto-detected if not provided.",
|
|
17
|
+
"enum": ["blocking", "critters"]
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"required": ["project"]
|
|
@@ -36,7 +36,19 @@ type NgTheme<T extends string = string & {}> = DefaultNgTheme | T;
|
|
|
36
36
|
* Represents the value that comes from `matchMedia`, not user selection.
|
|
37
37
|
*/
|
|
38
38
|
type NgSystemTheme = Exclude<DefaultNgTheme, 'system'>;
|
|
39
|
+
/**
|
|
40
|
+
* Theme application mode.
|
|
41
|
+
* - `'attribute'`: sets `data-theme` attribute on `<html>`
|
|
42
|
+
* - `'class'`: adds theme class to `<html>`
|
|
43
|
+
* - `'both'`: uses both attribute and class
|
|
44
|
+
*/
|
|
39
45
|
type NgMode = 'attribute' | 'class' | 'both';
|
|
46
|
+
/**
|
|
47
|
+
* Theme application strategy.
|
|
48
|
+
* - `'blocking'`: theme CSS is loaded synchronously before rendering
|
|
49
|
+
* - `'critters'`: theme CSS is inlined using Critters for SSR/SSG
|
|
50
|
+
*/
|
|
51
|
+
type NgStrategy = 'blocking' | 'critters';
|
|
40
52
|
/**
|
|
41
53
|
* Library configuration.
|
|
42
54
|
*
|
|
@@ -45,9 +57,22 @@ type NgMode = 'attribute' | 'class' | 'both';
|
|
|
45
57
|
* via {@link provideThemeStack} to get a closed, type-safe theme union.
|
|
46
58
|
*/
|
|
47
59
|
interface NgConfig<T extends string = string & {}> {
|
|
60
|
+
/** The theme to use on first visit or when no preference is saved. Default: 'system'. */
|
|
48
61
|
defaultTheme: NgTheme<T>;
|
|
62
|
+
/** Key used to persist theme preference in localStorage. Default: 'ngx-theme-stack-theme'. */
|
|
49
63
|
storageKey: string;
|
|
64
|
+
/**
|
|
65
|
+
* How the theme should be applied to the document (via class, attribute or both).
|
|
66
|
+
* Default: 'class'.
|
|
67
|
+
*/
|
|
50
68
|
mode: NgMode;
|
|
69
|
+
/**
|
|
70
|
+
* Performance strategy for anti-flash.
|
|
71
|
+
* Use 'critters' for SSG/SSR builds with inlined CSS, 'blocking' for standard CSS files.
|
|
72
|
+
* Default: 'critters'.
|
|
73
|
+
*/
|
|
74
|
+
strategy: NgStrategy;
|
|
75
|
+
/** List of supported theme identifiers. Default: ['light', 'dark', 'system']. */
|
|
51
76
|
themes: NgTheme<T>[];
|
|
52
77
|
}
|
|
53
78
|
|
|
@@ -74,18 +99,17 @@ declare class CoreThemeService {
|
|
|
74
99
|
/**
|
|
75
100
|
* Whether the service has completed client-side initialization.
|
|
76
101
|
*
|
|
77
|
-
* `false` during SSR and on the very first render pass
|
|
78
|
-
*
|
|
79
|
-
*
|
|
102
|
+
* `false` during SSR and on the very first render pass before the initial theme
|
|
103
|
+
* is resolved from `localStorage`. Becomes `true` immediately after the
|
|
104
|
+
* first browser render pass.
|
|
80
105
|
*
|
|
81
|
-
*
|
|
82
|
-
* `resolvedTheme`
|
|
83
|
-
* renders the default
|
|
84
|
-
* value stored.
|
|
106
|
+
* **Important:** Guard template elements that display `selectedTheme()` or
|
|
107
|
+
* `resolvedTheme()` behind this signal to prevent hydration-mismatch flashes
|
|
108
|
+
* (e.g. if the server renders the default 'system' but the user has 'dark' stored).
|
|
85
109
|
*
|
|
86
110
|
* @example
|
|
87
111
|
* ```html
|
|
88
|
-
* {{
|
|
112
|
+
* {{ theme.isHydrated() ? theme.selectedTheme() : '...' }}
|
|
89
113
|
* ```
|
|
90
114
|
*/
|
|
91
115
|
readonly isHydrated: _angular_core.WritableSignal<boolean>;
|
|
@@ -132,6 +156,7 @@ declare const DEFAULT_NG_CONFIG: {
|
|
|
132
156
|
defaultTheme: "system";
|
|
133
157
|
storageKey: string;
|
|
134
158
|
mode: "class";
|
|
159
|
+
strategy: "critters";
|
|
135
160
|
themes: ("system" | "light" | "dark")[];
|
|
136
161
|
};
|
|
137
162
|
declare const NGX_THEME_STACK_CONFIG: InjectionToken<NgConfig<string>>;
|
|
@@ -140,6 +165,14 @@ declare const NGX_THEME_STACK_CONFIG: InjectionToken<NgConfig<string>>;
|
|
|
140
165
|
*
|
|
141
166
|
* Custom `themes` are **merged** with the built-in defaults
|
|
142
167
|
* (`'light'`, `'dark'`, `'system'`), so you never lose the base themes.
|
|
168
|
+
*
|
|
169
|
+
* **Defaults:**
|
|
170
|
+
* - `themes`: `['light', 'dark', 'system']`
|
|
171
|
+
* - `defaultTheme`: `'system'`
|
|
172
|
+
* - `storageKey`: `'ngx-theme-stack-theme'`
|
|
173
|
+
* - `mode`: `'class'`
|
|
174
|
+
* - `strategy`: `'critters'`
|
|
175
|
+
|
|
143
176
|
*
|
|
144
177
|
* The type parameter `T` is **inferred automatically** from the `themes` array
|
|
145
178
|
* when passed as a `const` — no need to specify it manually.
|
|
@@ -159,6 +192,13 @@ declare const NGX_THEME_STACK_CONFIG: InjectionToken<NgConfig<string>>;
|
|
|
159
192
|
* provideThemeStack()
|
|
160
193
|
*
|
|
161
194
|
* @example
|
|
195
|
+
* // SSR/SSG Optimization — uses Critters inlining strategy
|
|
196
|
+
* provideThemeStack({
|
|
197
|
+
* strategy: 'critters',
|
|
198
|
+
* mode: 'class',
|
|
199
|
+
* })
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
162
202
|
* // Closed union: TypeScript infers 'sepia' | 'ocean' from the array
|
|
163
203
|
* provideThemeStack({
|
|
164
204
|
* themes: ['sepia', 'ocean'] as const,
|
|
@@ -170,7 +210,7 @@ declare const NGX_THEME_STACK_CONFIG: InjectionToken<NgConfig<string>>;
|
|
|
170
210
|
* // Custom storage key and mode
|
|
171
211
|
* provideThemeStack({
|
|
172
212
|
* storageKey: 'my-app-theme',
|
|
173
|
-
* mode: '
|
|
213
|
+
* mode: 'attribute',
|
|
174
214
|
* })
|
|
175
215
|
*/
|
|
176
216
|
declare function provideThemeStack<const T extends string = DefaultNgTheme>(config?: Partial<NgConfig<T>>): {
|
|
@@ -190,17 +230,17 @@ declare class ThemeCycleService {
|
|
|
190
230
|
#private;
|
|
191
231
|
/** The theme explicitly selected by the user. May be `'system'`. */
|
|
192
232
|
readonly selectedTheme: _angular_core.Signal<ngx_theme_stack.NgTheme>;
|
|
193
|
-
/** Resolved theme applied to the DOM. Always concrete — never `'system'`. */
|
|
233
|
+
/** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */
|
|
194
234
|
readonly resolvedTheme: _angular_core.Signal<(string & {}) | ngx_theme_stack.NgSystemTheme>;
|
|
195
|
-
/** Whether the currently applied theme is dark
|
|
235
|
+
/** Whether the currently applied theme is `'dark'`. */
|
|
196
236
|
readonly isDark: _angular_core.Signal<boolean>;
|
|
197
|
-
/** Whether the currently applied theme is light
|
|
237
|
+
/** Whether the currently applied theme is `'light'`. */
|
|
198
238
|
readonly isLight: _angular_core.Signal<boolean>;
|
|
199
|
-
/** Whether the
|
|
239
|
+
/** Whether the user has explicitly selected `'system'` preference. */
|
|
200
240
|
readonly isSystem: _angular_core.Signal<boolean>;
|
|
201
241
|
/**
|
|
202
|
-
* Whether the service has completed client-side initialization
|
|
203
|
-
*
|
|
242
|
+
* Whether the service has completed client-side initialization and
|
|
243
|
+
* resolved the real persisted theme. Use to prevent hydration flashes.
|
|
204
244
|
*/
|
|
205
245
|
readonly isHydrated: _angular_core.Signal<boolean>;
|
|
206
246
|
/**
|
|
@@ -224,21 +264,21 @@ declare class ThemeCycleService {
|
|
|
224
264
|
*/
|
|
225
265
|
declare class ThemeSelectService {
|
|
226
266
|
#private;
|
|
227
|
-
/** List of all configured themes. Defaults to ['light', 'dark', 'system']
|
|
267
|
+
/** List of all configured themes. Defaults to `['light', 'dark', 'system']`. */
|
|
228
268
|
readonly availableThemes: string[];
|
|
229
269
|
/** The theme explicitly selected by the user. May be `'system'`. */
|
|
230
270
|
readonly selectedTheme: _angular_core.Signal<NgTheme>;
|
|
231
|
-
/** Resolved theme applied to the DOM. Always concrete — never `'system'`. */
|
|
271
|
+
/** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */
|
|
232
272
|
readonly resolvedTheme: _angular_core.Signal<(string & {}) | ngx_theme_stack.NgSystemTheme>;
|
|
233
|
-
/** Whether the currently applied theme is dark
|
|
273
|
+
/** Whether the currently applied theme is `'dark'`. */
|
|
234
274
|
readonly isDark: _angular_core.Signal<boolean>;
|
|
235
|
-
/** Whether the currently applied theme is light
|
|
275
|
+
/** Whether the currently applied theme is `'light'`. */
|
|
236
276
|
readonly isLight: _angular_core.Signal<boolean>;
|
|
237
|
-
/** Whether the
|
|
277
|
+
/** Whether the user has explicitly selected `'system'` preference. */
|
|
238
278
|
readonly isSystem: _angular_core.Signal<boolean>;
|
|
239
279
|
/**
|
|
240
|
-
* Whether the service has completed client-side initialization
|
|
241
|
-
*
|
|
280
|
+
* Whether the service has completed client-side initialization and
|
|
281
|
+
* resolved the real persisted theme. Use to prevent hydration flashes.
|
|
242
282
|
*/
|
|
243
283
|
readonly isHydrated: _angular_core.Signal<boolean>;
|
|
244
284
|
/**
|
|
@@ -260,20 +300,19 @@ declare class ThemeSelectService {
|
|
|
260
300
|
*/
|
|
261
301
|
declare class ThemeToggleService {
|
|
262
302
|
#private;
|
|
263
|
-
/** Resolved theme applied to the DOM. Always concrete — never `'system'`. */
|
|
303
|
+
/** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */
|
|
264
304
|
readonly resolvedTheme: _angular_core.Signal<(string & {}) | ngx_theme_stack.NgSystemTheme>;
|
|
305
|
+
/** The theme explicitly selected by the user. May be `'system'`. */
|
|
265
306
|
readonly selectedTheme: _angular_core.Signal<ngx_theme_stack.NgTheme>;
|
|
266
|
-
/** Whether the currently applied theme is dark
|
|
307
|
+
/** Whether the currently applied theme is `'dark'`. */
|
|
267
308
|
readonly isDark: _angular_core.Signal<boolean>;
|
|
268
|
-
/** Whether the currently applied theme is light
|
|
309
|
+
/** Whether the currently applied theme is `'light'`. */
|
|
269
310
|
readonly isLight: _angular_core.Signal<boolean>;
|
|
270
|
-
/** Whether the
|
|
311
|
+
/** Whether the user has explicitly selected `'system'` preference. */
|
|
271
312
|
readonly isSystem: _angular_core.Signal<boolean>;
|
|
272
313
|
/**
|
|
273
|
-
* Whether the service has completed client-side initialization
|
|
274
|
-
*
|
|
275
|
-
* Guard any template logic that shows `selectedTheme` or `resolvedTheme`
|
|
276
|
-
* behind this signal to avoid a hydration-mismatch flash.
|
|
314
|
+
* Whether the service has completed client-side initialization and
|
|
315
|
+
* resolved the real persisted theme. Use to prevent hydration flashes.
|
|
277
316
|
*/
|
|
278
317
|
readonly isHydrated: _angular_core.Signal<boolean>;
|
|
279
318
|
/**
|
|
@@ -309,4 +348,4 @@ declare class NgxThemeStackError extends Error {
|
|
|
309
348
|
}
|
|
310
349
|
|
|
311
350
|
export { CoreThemeService, DEFAULT_NG_CONFIG, DEFAULT_THEMES, NGX_THEME_STACK_CONFIG, NgxThemeStackError, ThemeCycleService, ThemeSelectService, ThemeToggleService, provideThemeStack };
|
|
312
|
-
export type { DefaultNgTheme, NgConfig, NgMode, NgSystemTheme, NgTheme };
|
|
351
|
+
export type { DefaultNgTheme, NgConfig, NgMode, NgStrategy, NgSystemTheme, NgTheme };
|