@tenphi/glaze 0.8.0 → 0.9.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/README.md +61 -21
- package/dist/index.cjs +66 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -25
- package/dist/index.d.mts +34 -25
- package/dist/index.mjs +66 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -243,11 +243,12 @@ interface GlazeConfig {
|
|
|
243
243
|
/** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */
|
|
244
244
|
darkDesaturation?: number;
|
|
245
245
|
/**
|
|
246
|
-
*
|
|
246
|
+
* Möbius beta for dark auto-inversion (0–1).
|
|
247
247
|
* Lower values expand subtle near-white distinctions in dark mode.
|
|
248
248
|
* Set to 1 for linear (legacy) behavior. Default: 0.5.
|
|
249
|
+
* Accepts [normal, highContrast] pair for separate HC tuning.
|
|
249
250
|
*/
|
|
250
|
-
darkCurve?: number
|
|
251
|
+
darkCurve?: HCPair<number>;
|
|
251
252
|
/** State alias names for token export. */
|
|
252
253
|
states?: {
|
|
253
254
|
dark?: string;
|
|
@@ -262,7 +263,7 @@ interface GlazeConfigResolved {
|
|
|
262
263
|
lightLightness: [number, number];
|
|
263
264
|
darkLightness: [number, number];
|
|
264
265
|
darkDesaturation: number;
|
|
265
|
-
darkCurve: number
|
|
266
|
+
darkCurve: HCPair<number>;
|
|
266
267
|
states: {
|
|
267
268
|
dark: string;
|
|
268
269
|
highContrast: string;
|
|
@@ -392,35 +393,47 @@ interface GlazeCssResult {
|
|
|
392
393
|
lightContrast: string;
|
|
393
394
|
darkContrast: string;
|
|
394
395
|
}
|
|
395
|
-
/** Options
|
|
396
|
-
interface
|
|
397
|
-
/**
|
|
398
|
-
* Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
|
|
399
|
-
* Defaults to `true` for palette export methods.
|
|
400
|
-
* Set to `false` explicitly to disable prefixing (last-write-wins on collisions).
|
|
401
|
-
*/
|
|
402
|
-
prefix?: boolean | Record<string, string>;
|
|
396
|
+
/** Options for `glaze.palette()` creation. */
|
|
397
|
+
interface GlazePaletteOptions {
|
|
403
398
|
/**
|
|
404
399
|
* Name of the primary theme. The primary theme's tokens are duplicated
|
|
405
|
-
* without prefix, providing convenient short aliases
|
|
406
|
-
* prefixed versions.
|
|
400
|
+
* without prefix in all exports, providing convenient short aliases
|
|
401
|
+
* alongside the prefixed versions. Can be overridden per-export.
|
|
407
402
|
*
|
|
408
403
|
* @example
|
|
409
404
|
* ```ts
|
|
410
|
-
* palette.
|
|
405
|
+
* const palette = glaze.palette({ brand, accent }, { primary: 'brand' });
|
|
406
|
+
* palette.tokens()
|
|
411
407
|
* // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
|
|
412
408
|
* ```
|
|
413
409
|
*/
|
|
414
410
|
primary?: string;
|
|
415
411
|
}
|
|
412
|
+
/** Options shared by palette `tokens()`, `tasty()`, and `css()` exports. */
|
|
413
|
+
interface GlazePaletteExportOptions {
|
|
414
|
+
/**
|
|
415
|
+
* Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
|
|
416
|
+
* Defaults to `true` for palette export methods.
|
|
417
|
+
* Set to `false` explicitly to disable prefixing. Colliding keys
|
|
418
|
+
* produce a console.warn and the first-written value wins.
|
|
419
|
+
*/
|
|
420
|
+
prefix?: boolean | Record<string, string>;
|
|
421
|
+
/**
|
|
422
|
+
* Override the palette-level primary theme for this export.
|
|
423
|
+
* Pass a theme name to set/change the primary, or `false` to disable it.
|
|
424
|
+
* When omitted, inherits the palette-level `primary`.
|
|
425
|
+
*/
|
|
426
|
+
primary?: string | false;
|
|
427
|
+
}
|
|
416
428
|
interface GlazePalette {
|
|
417
429
|
/**
|
|
418
430
|
* Export all themes as a flat token map grouped by scheme variant.
|
|
419
431
|
* Prefix defaults to `true` — all tokens are prefixed with the theme name.
|
|
420
|
-
*
|
|
432
|
+
* Inherits the palette-level `primary`; override per-call or pass `false` to disable.
|
|
421
433
|
*
|
|
422
434
|
* ```ts
|
|
423
|
-
* palette.
|
|
435
|
+
* const palette = glaze.palette({ brand, accent }, { primary: 'brand' });
|
|
436
|
+
* palette.tokens()
|
|
424
437
|
* // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
|
|
425
438
|
* ```
|
|
426
439
|
*/
|
|
@@ -428,12 +441,10 @@ interface GlazePalette {
|
|
|
428
441
|
/**
|
|
429
442
|
* Export all themes as tasty style-to-state bindings.
|
|
430
443
|
* Uses `#name` color token keys and state aliases (`''`, `@dark`, etc.).
|
|
431
|
-
* Prefix defaults to `true`.
|
|
444
|
+
* Prefix defaults to `true`. Inherits the palette-level `primary`.
|
|
432
445
|
* @see https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs
|
|
433
446
|
*/
|
|
434
|
-
tasty(options?: GlazeTokenOptions &
|
|
435
|
-
primary?: string;
|
|
436
|
-
}): Record<string, Record<string, string>>;
|
|
447
|
+
tasty(options?: GlazeTokenOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
437
448
|
/** Export all themes as plain JSON grouped by theme name. */
|
|
438
449
|
json(options?: GlazeJsonOptions & {
|
|
439
450
|
prefix?: boolean | Record<string, string>;
|
|
@@ -460,11 +471,9 @@ declare function glaze(hueOrOptions: number | {
|
|
|
460
471
|
}, saturation?: number): GlazeTheme;
|
|
461
472
|
declare namespace glaze {
|
|
462
473
|
var configure: (config: GlazeConfig) => void;
|
|
463
|
-
var palette: (themes: PaletteInput) => {
|
|
474
|
+
var palette: (themes: PaletteInput, options?: GlazePaletteOptions) => {
|
|
464
475
|
tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
465
|
-
tasty(options?: GlazeTokenOptions &
|
|
466
|
-
primary?: string;
|
|
467
|
-
}): Record<string, Record<string, string>>;
|
|
476
|
+
tasty(options?: GlazeTokenOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
468
477
|
json(options?: GlazeJsonOptions & {
|
|
469
478
|
prefix?: boolean | Record<string, string>;
|
|
470
479
|
}): Record<string, Record<string, Record<string, string>>>;
|
|
@@ -548,5 +557,5 @@ declare function formatHsl(h: number, s: number, l: number): string;
|
|
|
548
557
|
*/
|
|
549
558
|
declare function formatOklch(h: number, s: number, l: number): string;
|
|
550
559
|
//#endregion
|
|
551
|
-
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type MinContrast, type MixColorDef, type OkhslColor, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ShadowColorDef, type ShadowTuning, contrastRatioFromLuminance, findLightnessForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, gamutClampedLuminance, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
560
|
+
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type MinContrast, type MixColorDef, type OkhslColor, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ShadowColorDef, type ShadowTuning, contrastRatioFromLuminance, findLightnessForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, gamutClampedLuminance, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
552
561
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.mts
CHANGED
|
@@ -243,11 +243,12 @@ interface GlazeConfig {
|
|
|
243
243
|
/** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */
|
|
244
244
|
darkDesaturation?: number;
|
|
245
245
|
/**
|
|
246
|
-
*
|
|
246
|
+
* Möbius beta for dark auto-inversion (0–1).
|
|
247
247
|
* Lower values expand subtle near-white distinctions in dark mode.
|
|
248
248
|
* Set to 1 for linear (legacy) behavior. Default: 0.5.
|
|
249
|
+
* Accepts [normal, highContrast] pair for separate HC tuning.
|
|
249
250
|
*/
|
|
250
|
-
darkCurve?: number
|
|
251
|
+
darkCurve?: HCPair<number>;
|
|
251
252
|
/** State alias names for token export. */
|
|
252
253
|
states?: {
|
|
253
254
|
dark?: string;
|
|
@@ -262,7 +263,7 @@ interface GlazeConfigResolved {
|
|
|
262
263
|
lightLightness: [number, number];
|
|
263
264
|
darkLightness: [number, number];
|
|
264
265
|
darkDesaturation: number;
|
|
265
|
-
darkCurve: number
|
|
266
|
+
darkCurve: HCPair<number>;
|
|
266
267
|
states: {
|
|
267
268
|
dark: string;
|
|
268
269
|
highContrast: string;
|
|
@@ -392,35 +393,47 @@ interface GlazeCssResult {
|
|
|
392
393
|
lightContrast: string;
|
|
393
394
|
darkContrast: string;
|
|
394
395
|
}
|
|
395
|
-
/** Options
|
|
396
|
-
interface
|
|
397
|
-
/**
|
|
398
|
-
* Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
|
|
399
|
-
* Defaults to `true` for palette export methods.
|
|
400
|
-
* Set to `false` explicitly to disable prefixing (last-write-wins on collisions).
|
|
401
|
-
*/
|
|
402
|
-
prefix?: boolean | Record<string, string>;
|
|
396
|
+
/** Options for `glaze.palette()` creation. */
|
|
397
|
+
interface GlazePaletteOptions {
|
|
403
398
|
/**
|
|
404
399
|
* Name of the primary theme. The primary theme's tokens are duplicated
|
|
405
|
-
* without prefix, providing convenient short aliases
|
|
406
|
-
* prefixed versions.
|
|
400
|
+
* without prefix in all exports, providing convenient short aliases
|
|
401
|
+
* alongside the prefixed versions. Can be overridden per-export.
|
|
407
402
|
*
|
|
408
403
|
* @example
|
|
409
404
|
* ```ts
|
|
410
|
-
* palette.
|
|
405
|
+
* const palette = glaze.palette({ brand, accent }, { primary: 'brand' });
|
|
406
|
+
* palette.tokens()
|
|
411
407
|
* // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
|
|
412
408
|
* ```
|
|
413
409
|
*/
|
|
414
410
|
primary?: string;
|
|
415
411
|
}
|
|
412
|
+
/** Options shared by palette `tokens()`, `tasty()`, and `css()` exports. */
|
|
413
|
+
interface GlazePaletteExportOptions {
|
|
414
|
+
/**
|
|
415
|
+
* Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
|
|
416
|
+
* Defaults to `true` for palette export methods.
|
|
417
|
+
* Set to `false` explicitly to disable prefixing. Colliding keys
|
|
418
|
+
* produce a console.warn and the first-written value wins.
|
|
419
|
+
*/
|
|
420
|
+
prefix?: boolean | Record<string, string>;
|
|
421
|
+
/**
|
|
422
|
+
* Override the palette-level primary theme for this export.
|
|
423
|
+
* Pass a theme name to set/change the primary, or `false` to disable it.
|
|
424
|
+
* When omitted, inherits the palette-level `primary`.
|
|
425
|
+
*/
|
|
426
|
+
primary?: string | false;
|
|
427
|
+
}
|
|
416
428
|
interface GlazePalette {
|
|
417
429
|
/**
|
|
418
430
|
* Export all themes as a flat token map grouped by scheme variant.
|
|
419
431
|
* Prefix defaults to `true` — all tokens are prefixed with the theme name.
|
|
420
|
-
*
|
|
432
|
+
* Inherits the palette-level `primary`; override per-call or pass `false` to disable.
|
|
421
433
|
*
|
|
422
434
|
* ```ts
|
|
423
|
-
* palette.
|
|
435
|
+
* const palette = glaze.palette({ brand, accent }, { primary: 'brand' });
|
|
436
|
+
* palette.tokens()
|
|
424
437
|
* // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
|
|
425
438
|
* ```
|
|
426
439
|
*/
|
|
@@ -428,12 +441,10 @@ interface GlazePalette {
|
|
|
428
441
|
/**
|
|
429
442
|
* Export all themes as tasty style-to-state bindings.
|
|
430
443
|
* Uses `#name` color token keys and state aliases (`''`, `@dark`, etc.).
|
|
431
|
-
* Prefix defaults to `true`.
|
|
444
|
+
* Prefix defaults to `true`. Inherits the palette-level `primary`.
|
|
432
445
|
* @see https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs
|
|
433
446
|
*/
|
|
434
|
-
tasty(options?: GlazeTokenOptions &
|
|
435
|
-
primary?: string;
|
|
436
|
-
}): Record<string, Record<string, string>>;
|
|
447
|
+
tasty(options?: GlazeTokenOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
437
448
|
/** Export all themes as plain JSON grouped by theme name. */
|
|
438
449
|
json(options?: GlazeJsonOptions & {
|
|
439
450
|
prefix?: boolean | Record<string, string>;
|
|
@@ -460,11 +471,9 @@ declare function glaze(hueOrOptions: number | {
|
|
|
460
471
|
}, saturation?: number): GlazeTheme;
|
|
461
472
|
declare namespace glaze {
|
|
462
473
|
var configure: (config: GlazeConfig) => void;
|
|
463
|
-
var palette: (themes: PaletteInput) => {
|
|
474
|
+
var palette: (themes: PaletteInput, options?: GlazePaletteOptions) => {
|
|
464
475
|
tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
465
|
-
tasty(options?: GlazeTokenOptions &
|
|
466
|
-
primary?: string;
|
|
467
|
-
}): Record<string, Record<string, string>>;
|
|
476
|
+
tasty(options?: GlazeTokenOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
468
477
|
json(options?: GlazeJsonOptions & {
|
|
469
478
|
prefix?: boolean | Record<string, string>;
|
|
470
479
|
}): Record<string, Record<string, Record<string, string>>>;
|
|
@@ -548,5 +557,5 @@ declare function formatHsl(h: number, s: number, l: number): string;
|
|
|
548
557
|
*/
|
|
549
558
|
declare function formatOklch(h: number, s: number, l: number): string;
|
|
550
559
|
//#endregion
|
|
551
|
-
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type MinContrast, type MixColorDef, type OkhslColor, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ShadowColorDef, type ShadowTuning, contrastRatioFromLuminance, findLightnessForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, gamutClampedLuminance, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
560
|
+
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type MinContrast, type MixColorDef, type OkhslColor, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ShadowColorDef, type ShadowTuning, contrastRatioFromLuminance, findLightnessForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, gamutClampedLuminance, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
552
561
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -960,9 +960,13 @@ function topoSort(defs) {
|
|
|
960
960
|
for (const name of Object.keys(defs)) visit(name);
|
|
961
961
|
return result;
|
|
962
962
|
}
|
|
963
|
+
function lightnessWindow(isHighContrast, kind) {
|
|
964
|
+
if (isHighContrast) return [0, 100];
|
|
965
|
+
return kind === "dark" ? globalConfig.darkLightness : globalConfig.lightLightness;
|
|
966
|
+
}
|
|
963
967
|
function mapLightnessLight(l, mode, isHighContrast) {
|
|
964
|
-
if (mode === "static"
|
|
965
|
-
const [lo, hi] =
|
|
968
|
+
if (mode === "static") return l;
|
|
969
|
+
const [lo, hi] = lightnessWindow(isHighContrast, "light");
|
|
966
970
|
return l * (hi - lo) / 100 + lo;
|
|
967
971
|
}
|
|
968
972
|
function mobiusCurve(t, beta) {
|
|
@@ -971,22 +975,17 @@ function mobiusCurve(t, beta) {
|
|
|
971
975
|
}
|
|
972
976
|
function mapLightnessDark(l, mode, isHighContrast) {
|
|
973
977
|
if (mode === "static") return l;
|
|
974
|
-
const beta = globalConfig.darkCurve;
|
|
975
|
-
|
|
976
|
-
if (mode === "fixed") return l;
|
|
977
|
-
return 100 * mobiusCurve((100 - l) / 100, beta);
|
|
978
|
-
}
|
|
979
|
-
const [darkLo, darkHi] = globalConfig.darkLightness;
|
|
978
|
+
const beta = isHighContrast ? pairHC(globalConfig.darkCurve) : pairNormal(globalConfig.darkCurve);
|
|
979
|
+
const [darkLo, darkHi] = lightnessWindow(isHighContrast, "dark");
|
|
980
980
|
if (mode === "fixed") return l * (darkHi - darkLo) / 100 + darkLo;
|
|
981
|
-
const [lightLo, lightHi] =
|
|
981
|
+
const [lightLo, lightHi] = lightnessWindow(isHighContrast, "light");
|
|
982
982
|
const t = (lightHi - (l * (lightHi - lightLo) / 100 + lightLo)) / (lightHi - lightLo);
|
|
983
983
|
return darkLo + (darkHi - darkLo) * mobiusCurve(t, beta);
|
|
984
984
|
}
|
|
985
985
|
function lightMappedToDark(lightL, isHighContrast) {
|
|
986
|
-
const beta = globalConfig.darkCurve;
|
|
987
|
-
|
|
988
|
-
const [
|
|
989
|
-
const [darkLo, darkHi] = globalConfig.darkLightness;
|
|
986
|
+
const beta = isHighContrast ? pairHC(globalConfig.darkCurve) : pairNormal(globalConfig.darkCurve);
|
|
987
|
+
const [lightLo, lightHi] = lightnessWindow(isHighContrast, "light");
|
|
988
|
+
const [darkLo, darkHi] = lightnessWindow(isHighContrast, "dark");
|
|
990
989
|
const t = (lightHi - clamp(lightL, lightLo, lightHi)) / (lightHi - lightLo);
|
|
991
990
|
return darkLo + (darkHi - darkLo) * mobiusCurve(t, beta);
|
|
992
991
|
}
|
|
@@ -995,8 +994,8 @@ function mapSaturationDark(s, mode) {
|
|
|
995
994
|
return s * (1 - globalConfig.darkDesaturation);
|
|
996
995
|
}
|
|
997
996
|
function schemeLightnessRange(isDark, mode, isHighContrast) {
|
|
998
|
-
if (mode === "static"
|
|
999
|
-
const [lo, hi] = isDark ?
|
|
997
|
+
if (mode === "static") return [0, 1];
|
|
998
|
+
const [lo, hi] = lightnessWindow(isHighContrast, isDark ? "dark" : "light");
|
|
1000
999
|
return [lo / 100, hi / 100];
|
|
1001
1000
|
}
|
|
1002
1001
|
function clamp(v, min, max) {
|
|
@@ -1451,40 +1450,74 @@ function validatePrimaryTheme(primary, themes) {
|
|
|
1451
1450
|
throw new Error(`glaze: primary theme "${primary}" not found in palette. Available: ${available}.`);
|
|
1452
1451
|
}
|
|
1453
1452
|
}
|
|
1454
|
-
|
|
1453
|
+
/**
|
|
1454
|
+
* Resolve the effective primary for an export call.
|
|
1455
|
+
* `false` disables, a string overrides, `undefined` inherits from palette.
|
|
1456
|
+
*/
|
|
1457
|
+
function resolveEffectivePrimary(exportPrimary, palettePrimary) {
|
|
1458
|
+
if (exportPrimary === false) return void 0;
|
|
1459
|
+
return exportPrimary ?? palettePrimary;
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Filter a resolved color map, skipping keys already in `seen`.
|
|
1463
|
+
* Warns on collision and keeps the first-written value (first-write-wins).
|
|
1464
|
+
* Returns a new map containing only non-colliding entries.
|
|
1465
|
+
*/
|
|
1466
|
+
function filterCollisions(resolved, prefix, seen, themeName, isPrimary) {
|
|
1467
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
1468
|
+
const label = isPrimary ? `${themeName} (primary)` : themeName;
|
|
1469
|
+
for (const [name, color] of resolved) {
|
|
1470
|
+
const key = `${prefix}${name}`;
|
|
1471
|
+
if (seen.has(key)) {
|
|
1472
|
+
console.warn(`glaze: token "${key}" from theme "${label}" collides with theme "${seen.get(key)}" — skipping.`);
|
|
1473
|
+
continue;
|
|
1474
|
+
}
|
|
1475
|
+
seen.set(key, label);
|
|
1476
|
+
filtered.set(name, color);
|
|
1477
|
+
}
|
|
1478
|
+
return filtered;
|
|
1479
|
+
}
|
|
1480
|
+
function createPalette(themes, paletteOptions) {
|
|
1481
|
+
validatePrimaryTheme(paletteOptions?.primary, themes);
|
|
1455
1482
|
return {
|
|
1456
1483
|
tokens(options) {
|
|
1457
|
-
|
|
1484
|
+
const effectivePrimary = resolveEffectivePrimary(options?.primary, paletteOptions?.primary);
|
|
1485
|
+
if (options?.primary !== void 0) validatePrimaryTheme(effectivePrimary, themes);
|
|
1458
1486
|
const modes = resolveModes(options?.modes);
|
|
1459
1487
|
const allTokens = {};
|
|
1488
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1460
1489
|
for (const [themeName, theme] of Object.entries(themes)) {
|
|
1461
1490
|
const resolved = theme.resolve();
|
|
1462
|
-
const
|
|
1491
|
+
const prefix = resolvePrefix(options, themeName, true);
|
|
1492
|
+
const tokens = buildFlatTokenMap(filterCollisions(resolved, prefix, seen, themeName), prefix, modes, options?.format);
|
|
1463
1493
|
for (const variant of Object.keys(tokens)) {
|
|
1464
1494
|
if (!allTokens[variant]) allTokens[variant] = {};
|
|
1465
1495
|
Object.assign(allTokens[variant], tokens[variant]);
|
|
1466
1496
|
}
|
|
1467
|
-
if (themeName ===
|
|
1468
|
-
const unprefixed = buildFlatTokenMap(resolved, "", modes, options?.format);
|
|
1497
|
+
if (themeName === effectivePrimary) {
|
|
1498
|
+
const unprefixed = buildFlatTokenMap(filterCollisions(resolved, "", seen, themeName, true), "", modes, options?.format);
|
|
1469
1499
|
for (const variant of Object.keys(unprefixed)) Object.assign(allTokens[variant], unprefixed[variant]);
|
|
1470
1500
|
}
|
|
1471
1501
|
}
|
|
1472
1502
|
return allTokens;
|
|
1473
1503
|
},
|
|
1474
1504
|
tasty(options) {
|
|
1475
|
-
|
|
1505
|
+
const effectivePrimary = resolveEffectivePrimary(options?.primary, paletteOptions?.primary);
|
|
1506
|
+
if (options?.primary !== void 0) validatePrimaryTheme(effectivePrimary, themes);
|
|
1476
1507
|
const states = {
|
|
1477
1508
|
dark: options?.states?.dark ?? globalConfig.states.dark,
|
|
1478
1509
|
highContrast: options?.states?.highContrast ?? globalConfig.states.highContrast
|
|
1479
1510
|
};
|
|
1480
1511
|
const modes = resolveModes(options?.modes);
|
|
1481
1512
|
const allTokens = {};
|
|
1513
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1482
1514
|
for (const [themeName, theme] of Object.entries(themes)) {
|
|
1483
1515
|
const resolved = theme.resolve();
|
|
1484
|
-
const
|
|
1516
|
+
const prefix = resolvePrefix(options, themeName, true);
|
|
1517
|
+
const tokens = buildTokenMap(filterCollisions(resolved, prefix, seen, themeName), prefix, states, modes, options?.format);
|
|
1485
1518
|
Object.assign(allTokens, tokens);
|
|
1486
|
-
if (themeName ===
|
|
1487
|
-
const unprefixed = buildTokenMap(resolved, "", states, modes, options?.format);
|
|
1519
|
+
if (themeName === effectivePrimary) {
|
|
1520
|
+
const unprefixed = buildTokenMap(filterCollisions(resolved, "", seen, themeName, true), "", states, modes, options?.format);
|
|
1488
1521
|
Object.assign(allTokens, unprefixed);
|
|
1489
1522
|
}
|
|
1490
1523
|
}
|
|
@@ -1497,7 +1530,8 @@ function createPalette(themes) {
|
|
|
1497
1530
|
return result;
|
|
1498
1531
|
},
|
|
1499
1532
|
css(options) {
|
|
1500
|
-
|
|
1533
|
+
const effectivePrimary = resolveEffectivePrimary(options?.primary, paletteOptions?.primary);
|
|
1534
|
+
if (options?.primary !== void 0) validatePrimaryTheme(effectivePrimary, themes);
|
|
1501
1535
|
const suffix = options?.suffix ?? "-color";
|
|
1502
1536
|
const format = options?.format ?? "rgb";
|
|
1503
1537
|
const allLines = {
|
|
@@ -1506,17 +1540,19 @@ function createPalette(themes) {
|
|
|
1506
1540
|
lightContrast: [],
|
|
1507
1541
|
darkContrast: []
|
|
1508
1542
|
};
|
|
1543
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1509
1544
|
for (const [themeName, theme] of Object.entries(themes)) {
|
|
1510
1545
|
const resolved = theme.resolve();
|
|
1511
|
-
const
|
|
1546
|
+
const prefix = resolvePrefix(options, themeName, true);
|
|
1547
|
+
const css = buildCssMap(filterCollisions(resolved, prefix, seen, themeName), prefix, suffix, format);
|
|
1512
1548
|
for (const key of [
|
|
1513
1549
|
"light",
|
|
1514
1550
|
"dark",
|
|
1515
1551
|
"lightContrast",
|
|
1516
1552
|
"darkContrast"
|
|
1517
1553
|
]) if (css[key]) allLines[key].push(css[key]);
|
|
1518
|
-
if (themeName ===
|
|
1519
|
-
const unprefixed = buildCssMap(resolved, "", suffix, format);
|
|
1554
|
+
if (themeName === effectivePrimary) {
|
|
1555
|
+
const unprefixed = buildCssMap(filterCollisions(resolved, "", seen, themeName, true), "", suffix, format);
|
|
1520
1556
|
for (const key of [
|
|
1521
1557
|
"light",
|
|
1522
1558
|
"dark",
|
|
@@ -1598,8 +1634,8 @@ glaze.configure = function configure(config) {
|
|
|
1598
1634
|
/**
|
|
1599
1635
|
* Compose multiple themes into a palette.
|
|
1600
1636
|
*/
|
|
1601
|
-
glaze.palette = function palette(themes) {
|
|
1602
|
-
return createPalette(themes);
|
|
1637
|
+
glaze.palette = function palette(themes, options) {
|
|
1638
|
+
return createPalette(themes, options);
|
|
1603
1639
|
};
|
|
1604
1640
|
/**
|
|
1605
1641
|
* Create a theme from a serialized export.
|