@ethlete/core 5.0.0-next.17 → 5.0.0-next.19

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.
@@ -5,6 +5,10 @@ export default async function generate(tree, schema) {
5
5
  const themesPath = schema.themesPath || 'src/themes.ts';
6
6
  const outputPath = schema.outputPath || 'src/styles/generated-tailwind-themes.css';
7
7
  const prefix = schema.prefix || 'et';
8
+ // The runtime prefix drives the theme-swap CSS variables (--<runtimePrefix>-color-primary)
9
+ // and selectors (.<runtimePrefix>-color--<name>). It defaults to `prefix` so existing
10
+ // consumers who only ever passed one prefix see no change in output.
11
+ const runtimePrefix = schema.runtimePrefix || prefix;
8
12
  // Step 1: Check if themes file exists
9
13
  if (!tree.exists(themesPath)) {
10
14
  logger.error(`āŒ Themes file not found at: ${themesPath}`);
@@ -43,7 +47,7 @@ export default async function generate(tree, schema) {
43
47
  }
44
48
  // Step 5: Generate Tailwind CSS
45
49
  logger.log('\nšŸŽØ Generating Tailwind theme CSS...');
46
- const css = generateTailwindThemeCss(themes, prefix, schema);
50
+ const css = generateTailwindThemeCss(themes, prefix, runtimePrefix, schema);
47
51
  // Step 6: Write the generated CSS file
48
52
  const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'));
49
53
  if (outputDir && !tree.exists(outputDir)) {
@@ -298,18 +302,18 @@ function createCssThemeName(name) {
298
302
  .replace(/\s+/g, '-')
299
303
  .replace(/[^a-z0-9-]/g, '');
300
304
  }
301
- function generateTailwindThemeCss(themes, prefix, schema) {
305
+ function generateTailwindThemeCss(themes, utilityPrefix, runtimePrefix, schema) {
302
306
  const tailwindVars = [];
303
307
  const themeVars = [];
304
308
  const themesPath = schema.themesPath || 'src/themes.ts';
305
309
  const outputPath = schema.outputPath || 'src/styles/generated-tailwind-themes.css';
306
- const header = `/*
310
+ const header = `/*
307
311
  * Auto-generated Tailwind 4 theme colors from @ethlete/core
308
312
  * DO NOT EDIT THIS FILE MANUALLY
309
- *
313
+ *
310
314
  * Generated from your theme definitions
311
315
  * This file can be regenerated by running:
312
- * nx g @ethlete/core:tailwind-4-color-theme --themesPath=${themesPath}${schema.outputPath ? ` --outputPath=${outputPath}` : ''}${schema.prefix && schema.prefix !== 'et' ? ` --prefix=${schema.prefix}` : ''}
316
+ * nx g @ethlete/core:tailwind-4-color-theme --themesPath=${themesPath}${schema.outputPath ? ` --outputPath=${outputPath}` : ''}${schema.prefix && schema.prefix !== 'et' ? ` --prefix=${schema.prefix}` : ''}${schema.runtimePrefix && schema.runtimePrefix !== utilityPrefix ? ` --runtimePrefix=${schema.runtimePrefix}` : ''}
313
317
  */
314
318
 
315
319
  `;
@@ -322,26 +326,26 @@ function generateTailwindThemeCss(themes, prefix, schema) {
322
326
  // Add comment for theme section
323
327
  tailwindVars.push(` /* ${theme.name} theme */`);
324
328
  // Primary colors for Tailwind utilities
325
- addTailwindColorVariants(tailwindVars, `${prefix}-${name}`, theme.primary.color);
329
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}`, theme.primary.color);
326
330
  tailwindVars.push('');
327
331
  // On colors for Tailwind utilities
328
- addTailwindColorVariants(tailwindVars, `${prefix}-on-${name}`, theme.primary.onColor);
332
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}`, theme.primary.onColor);
329
333
  tailwindVars.push('');
330
334
  // Ink colors for standalone foreground usage
331
- addTailwindColorVariants(tailwindVars, `${prefix}-${name}-ink`, theme.primary.inkColor || theme.primary.color);
335
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-ink`, theme.primary.inkColor || theme.primary.color);
332
336
  tailwindVars.push('');
333
337
  // Secondary colors if present
334
338
  if (theme.secondary) {
335
- addTailwindColorVariants(tailwindVars, `${prefix}-${name}-secondary`, theme.secondary.color);
339
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-secondary`, theme.secondary.color);
336
340
  tailwindVars.push('');
337
- addTailwindColorVariants(tailwindVars, `${prefix}-on-${name}-secondary`, theme.secondary.onColor);
341
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-secondary`, theme.secondary.onColor);
338
342
  tailwindVars.push('');
339
343
  }
340
344
  // Tertiary colors if present
341
345
  if (theme.tertiary) {
342
- addTailwindColorVariants(tailwindVars, `${prefix}-${name}-tertiary`, theme.tertiary.color);
346
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-tertiary`, theme.tertiary.color);
343
347
  tailwindVars.push('');
344
- addTailwindColorVariants(tailwindVars, `${prefix}-on-${name}-tertiary`, theme.tertiary.onColor);
348
+ addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-tertiary`, theme.tertiary.onColor);
345
349
  tailwindVars.push('');
346
350
  }
347
351
  }
@@ -351,50 +355,50 @@ function generateTailwindThemeCss(themes, prefix, schema) {
351
355
  const hasSecondary = mainThemes.some((t) => t.secondary);
352
356
  const hasTertiary = mainThemes.some((t) => t.tertiary);
353
357
  tailwindVars.push(' /* Dynamic theme colors (references runtime CSS variables) */');
354
- addDynamicThemeColors(tailwindVars, prefix, 'theme', 'primary', true);
355
- addDynamicInkColors(tailwindVars, prefix, 'theme-ink', 'primary-ink');
358
+ addDynamicThemeColors(tailwindVars, utilityPrefix, runtimePrefix, 'theme', 'primary', true);
359
+ addDynamicInkColors(tailwindVars, utilityPrefix, runtimePrefix, 'theme-ink', 'primary-ink');
356
360
  if (hasSecondary) {
357
- addDynamicThemeColors(tailwindVars, prefix, 'theme-secondary', 'secondary', false);
361
+ addDynamicThemeColors(tailwindVars, utilityPrefix, runtimePrefix, 'theme-secondary', 'secondary', false);
358
362
  }
359
363
  if (hasTertiary) {
360
- addDynamicThemeColors(tailwindVars, prefix, 'theme-tertiary', 'tertiary', false);
364
+ addDynamicThemeColors(tailwindVars, utilityPrefix, runtimePrefix, 'theme-tertiary', 'tertiary', false);
361
365
  }
362
366
  // Generate runtime CSS for all themes
363
367
  themes.forEach((theme) => {
364
368
  const name = createCssThemeName(theme.name);
365
369
  // Determine if this is the default theme
366
370
  const isDefault = theme.isDefault;
367
- // Generate color variant (.et-color--{name})
371
+ // Generate color variant (.<runtimePrefix>-color--{name})
368
372
  if (isDefault) {
369
- // Default color gets :root and .et-color--default selectors
370
- const selectors = [':root', `.${prefix}-color--default`, `.${prefix}-color--${name}`];
373
+ // Default color gets :root and .<runtimePrefix>-color--default selectors
374
+ const selectors = [':root', `.${runtimePrefix}-color--default`, `.${runtimePrefix}-color--${name}`];
371
375
  themeVars.push(`${selectors.join(', ')} {`);
372
376
  }
373
377
  else {
374
378
  // Regular colors just get their own class
375
- themeVars.push(`.${prefix}-color--${name} {`);
379
+ themeVars.push(`.${runtimePrefix}-color--${name} {`);
376
380
  }
377
- addThemeColorVariants(themeVars, prefix, '', theme);
381
+ addThemeColorVariants(themeVars, runtimePrefix, '', theme);
378
382
  themeVars.push('}\n');
379
383
  });
380
384
  // Convenience var aliases — available on any element with a color class (or root for default)
381
385
  const aliasBlock = `/* Convenience aliases (rgb + solid + opacity variants) */
382
386
  @layer base {
383
- :root, :where([class*="${prefix}-color--"]) {
384
- --${prefix}-theme-color-primary-rgb: var(--${prefix}-color-primary);
385
- --${prefix}-theme-color-primary-opacity: 1;
386
- --${prefix}-theme-color-primary-solid: rgb(var(--${prefix}-theme-color-primary-rgb));
387
- --${prefix}-theme-color-primary: rgb(var(--${prefix}-theme-color-primary-rgb) / var(--${prefix}-theme-color-primary-opacity));
387
+ :root, :where([class*="${runtimePrefix}-color--"]) {
388
+ --${runtimePrefix}-theme-color-primary-rgb: var(--${runtimePrefix}-color-primary);
389
+ --${runtimePrefix}-theme-color-primary-opacity: 1;
390
+ --${runtimePrefix}-theme-color-primary-solid: rgb(var(--${runtimePrefix}-theme-color-primary-rgb));
391
+ --${runtimePrefix}-theme-color-primary: rgb(var(--${runtimePrefix}-theme-color-primary-rgb) / var(--${runtimePrefix}-theme-color-primary-opacity));
388
392
 
389
- --${prefix}-theme-color-on-primary-rgb: var(--${prefix}-color-on-primary);
390
- --${prefix}-theme-color-on-primary-opacity: 1;
391
- --${prefix}-theme-color-on-primary-solid: rgb(var(--${prefix}-theme-color-on-primary-rgb) / var(--${prefix}-theme-color-on-primary-opacity));
392
- --${prefix}-theme-color-on-primary: rgb(var(--${prefix}-theme-color-on-primary-rgb) / var(--${prefix}-theme-color-on-primary-opacity));
393
+ --${runtimePrefix}-theme-color-on-primary-rgb: var(--${runtimePrefix}-color-on-primary);
394
+ --${runtimePrefix}-theme-color-on-primary-opacity: 1;
395
+ --${runtimePrefix}-theme-color-on-primary-solid: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
396
+ --${runtimePrefix}-theme-color-on-primary: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
393
397
 
394
- --${prefix}-theme-color-ink-rgb: var(--${prefix}-color-primary-ink, var(--${prefix}-color-primary));
395
- --${prefix}-theme-color-ink-opacity: 1;
396
- --${prefix}-theme-color-ink-solid: rgb(var(--${prefix}-theme-color-ink-rgb) / var(--${prefix}-theme-color-ink-opacity));
397
- --${prefix}-theme-color-ink: rgb(var(--${prefix}-theme-color-ink-rgb) / var(--${prefix}-theme-color-ink-opacity));
398
+ --${runtimePrefix}-theme-color-ink-rgb: var(--${runtimePrefix}-color-primary-ink, var(--${runtimePrefix}-color-primary));
399
+ --${runtimePrefix}-theme-color-ink-opacity: 1;
400
+ --${runtimePrefix}-theme-color-ink-solid: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
401
+ --${runtimePrefix}-theme-color-ink: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
398
402
  }
399
403
  }
400
404
  `;
@@ -408,31 +412,31 @@ ${themeVars.join('\n')}
408
412
 
409
413
  ${aliasBlock}`;
410
414
  }
411
- function addDynamicThemeColors(vars, prefix, tailwindName, cssVarName, addSpacingBefore) {
415
+ function addDynamicThemeColors(vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName, addSpacingBefore) {
412
416
  if (addSpacingBefore && vars.length > 0 && vars[vars.length - 1] !== '') {
413
417
  vars.push('');
414
418
  }
415
419
  // Color variants
416
- vars.push(` --color-${prefix}-${tailwindName}: rgb(var(--${prefix}-color-${cssVarName}));`);
417
- vars.push(` --color-${prefix}-${tailwindName}-hover: rgb(var(--${prefix}-color-${cssVarName}-hover));`);
418
- vars.push(` --color-${prefix}-${tailwindName}-focus: rgb(var(--${prefix}-color-${cssVarName}-focus));`);
419
- vars.push(` --color-${prefix}-${tailwindName}-active: rgb(var(--${prefix}-color-${cssVarName}-active));`);
420
- vars.push(` --color-${prefix}-${tailwindName}-disabled: rgb(var(--${prefix}-color-${cssVarName}-disabled));`);
420
+ vars.push(` --color-${utilityPrefix}-${tailwindName}: rgb(var(--${runtimePrefix}-color-${cssVarName}));`);
421
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-${cssVarName}-hover));`);
422
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-${cssVarName}-focus));`);
423
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-${cssVarName}-active));`);
424
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-${cssVarName}-disabled));`);
421
425
  vars.push('');
422
426
  // On-color variants
423
- vars.push(` --color-${prefix}-on-${tailwindName}: rgb(var(--${prefix}-color-on-${cssVarName}));`);
424
- vars.push(` --color-${prefix}-on-${tailwindName}-hover: rgb(var(--${prefix}-color-on-${cssVarName}-hover));`);
425
- vars.push(` --color-${prefix}-on-${tailwindName}-focus: rgb(var(--${prefix}-color-on-${cssVarName}-focus));`);
426
- vars.push(` --color-${prefix}-on-${tailwindName}-active: rgb(var(--${prefix}-color-on-${cssVarName}-active));`);
427
- vars.push(` --color-${prefix}-on-${tailwindName}-disabled: rgb(var(--${prefix}-color-on-${cssVarName}-disabled));`);
427
+ vars.push(` --color-${utilityPrefix}-on-${tailwindName}: rgb(var(--${runtimePrefix}-color-on-${cssVarName}));`);
428
+ vars.push(` --color-${utilityPrefix}-on-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-hover));`);
429
+ vars.push(` --color-${utilityPrefix}-on-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-focus));`);
430
+ vars.push(` --color-${utilityPrefix}-on-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-active));`);
431
+ vars.push(` --color-${utilityPrefix}-on-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-on-${cssVarName}-disabled));`);
428
432
  vars.push('');
429
433
  }
430
- function addDynamicInkColors(vars, prefix, tailwindName, cssVarName) {
431
- vars.push(` --color-${prefix}-${tailwindName}: rgb(var(--${prefix}-color-${cssVarName}));`);
432
- vars.push(` --color-${prefix}-${tailwindName}-hover: rgb(var(--${prefix}-color-${cssVarName}-hover));`);
433
- vars.push(` --color-${prefix}-${tailwindName}-focus: rgb(var(--${prefix}-color-${cssVarName}-focus));`);
434
- vars.push(` --color-${prefix}-${tailwindName}-active: rgb(var(--${prefix}-color-${cssVarName}-active));`);
435
- vars.push(` --color-${prefix}-${tailwindName}-disabled: rgb(var(--${prefix}-color-${cssVarName}-disabled));`);
434
+ function addDynamicInkColors(vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName) {
435
+ vars.push(` --color-${utilityPrefix}-${tailwindName}: rgb(var(--${runtimePrefix}-color-${cssVarName}));`);
436
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-hover: rgb(var(--${runtimePrefix}-color-${cssVarName}-hover));`);
437
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-focus: rgb(var(--${runtimePrefix}-color-${cssVarName}-focus));`);
438
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-active: rgb(var(--${runtimePrefix}-color-${cssVarName}-active));`);
439
+ vars.push(` --color-${utilityPrefix}-${tailwindName}-disabled: rgb(var(--${runtimePrefix}-color-${cssVarName}-disabled));`);
436
440
  vars.push('');
437
441
  }
438
442
  function addTailwindColorVariants(vars, colorName, colorSet) {
@@ -19,9 +19,13 @@
19
19
  },
20
20
  "prefix": {
21
21
  "type": "string",
22
- "description": "Prefix for color variable names (e.g., 'et' creates --color-et-primary)",
22
+ "description": "Prefix for Tailwind utility color variable names (e.g., 'et' creates --color-et-primary, usable as bg-et-primary)",
23
23
  "default": "et"
24
24
  },
25
+ "runtimePrefix": {
26
+ "type": "string",
27
+ "description": "Prefix for the runtime theme-swap mechanism: the CSS custom properties (--<runtimePrefix>-color-primary) and selectors (.<runtimePrefix>-color--<name>) that ProvideColorDirective (etProvideColor) toggles between. Defaults to the same value as 'prefix'. Set this separately when your Tailwind utility prefix needs to differ from your runtime theme-switching prefix (e.g. because '--color-primary' is already a documented public API elsewhere in your app)."
28
+ },
25
29
  "skipFormat": {
26
30
  "type": "boolean",
27
31
  "description": "Skip formatting files after generation",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethlete/core",
3
- "version": "5.0.0-next.17",
3
+ "version": "5.0.0-next.19",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {