@tenphi/glaze 0.6.3 → 0.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/dist/index.d.cts CHANGED
@@ -385,33 +385,54 @@ interface GlazeCssResult {
385
385
  lightContrast: string;
386
386
  darkContrast: string;
387
387
  }
388
+ /** Options shared by palette `tokens()`, `tasty()`, and `css()` exports. */
389
+ interface GlazePaletteExportOptions {
390
+ /**
391
+ * Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
392
+ * Defaults to `true` for palette export methods.
393
+ * Set to `false` explicitly to disable prefixing (last-write-wins on collisions).
394
+ */
395
+ prefix?: boolean | Record<string, string>;
396
+ /**
397
+ * Name of the primary theme. The primary theme's tokens are duplicated
398
+ * without prefix, providing convenient short aliases alongside the
399
+ * prefixed versions.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * palette.tokens({ primary: 'brand' })
404
+ * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
405
+ * ```
406
+ */
407
+ primary?: string;
408
+ }
388
409
  interface GlazePalette {
389
410
  /**
390
411
  * Export all themes as a flat token map grouped by scheme variant.
412
+ * Prefix defaults to `true` — all tokens are prefixed with the theme name.
413
+ * Use `primary` to duplicate one theme's tokens without prefix.
391
414
  *
392
415
  * ```ts
393
- * palette.tokens({ prefix: true })
394
- * // → { light: { 'primary-surface': 'okhsl(...)' }, dark: { 'primary-surface': 'okhsl(...)' } }
416
+ * palette.tokens({ primary: 'brand' })
417
+ * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
395
418
  * ```
396
419
  */
397
- tokens(options?: GlazeJsonOptions & {
398
- prefix?: boolean | Record<string, string>;
399
- }): Record<string, Record<string, string>>;
420
+ tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
400
421
  /**
401
422
  * Export all themes as tasty style-to-state bindings.
402
423
  * Uses `#name` color token keys and state aliases (`''`, `@dark`, etc.).
403
- * Spread into component styles or register as a recipe via `configure({ recipes })`.
424
+ * Prefix defaults to `true`. Use `primary` to duplicate one theme without prefix.
404
425
  * @see https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs
405
426
  */
406
- tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
407
- /** Export all themes as plain JSON. */
427
+ tasty(options?: GlazeTokenOptions & {
428
+ primary?: string;
429
+ }): Record<string, Record<string, string>>;
430
+ /** Export all themes as plain JSON grouped by theme name. */
408
431
  json(options?: GlazeJsonOptions & {
409
432
  prefix?: boolean | Record<string, string>;
410
433
  }): Record<string, Record<string, Record<string, string>>>;
411
434
  /** Export all themes as CSS custom property declarations. */
412
- css(options?: GlazeCssOptions & {
413
- prefix?: boolean | Record<string, string>;
414
- }): GlazeCssResult;
435
+ css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;
415
436
  }
416
437
  //#endregion
417
438
  //#region src/glaze.d.ts
@@ -433,16 +454,14 @@ declare function glaze(hueOrOptions: number | {
433
454
  declare namespace glaze {
434
455
  var configure: (config: GlazeConfig) => void;
435
456
  var palette: (themes: PaletteInput) => {
436
- tokens(options?: GlazeJsonOptions & {
437
- prefix?: boolean | Record<string, string>;
457
+ tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
458
+ tasty(options?: GlazeTokenOptions & {
459
+ primary?: string;
438
460
  }): Record<string, Record<string, string>>;
439
- tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
440
461
  json(options?: GlazeJsonOptions & {
441
462
  prefix?: boolean | Record<string, string>;
442
463
  }): Record<string, Record<string, Record<string, string>>>;
443
- css(options?: GlazeCssOptions & {
444
- prefix?: boolean | Record<string, string>;
445
- }): GlazeCssResult;
464
+ css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;
446
465
  };
447
466
  var from: (data: GlazeThemeExport) => GlazeTheme;
448
467
  var color: (input: GlazeColorInput) => GlazeColorToken;
@@ -522,5 +541,5 @@ declare function formatHsl(h: number, s: number, l: number): string;
522
541
  */
523
542
  declare function formatOklch(h: number, s: number, l: number): string;
524
543
  //#endregion
525
- 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 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 };
544
+ 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 };
526
545
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -385,33 +385,54 @@ interface GlazeCssResult {
385
385
  lightContrast: string;
386
386
  darkContrast: string;
387
387
  }
388
+ /** Options shared by palette `tokens()`, `tasty()`, and `css()` exports. */
389
+ interface GlazePaletteExportOptions {
390
+ /**
391
+ * Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
392
+ * Defaults to `true` for palette export methods.
393
+ * Set to `false` explicitly to disable prefixing (last-write-wins on collisions).
394
+ */
395
+ prefix?: boolean | Record<string, string>;
396
+ /**
397
+ * Name of the primary theme. The primary theme's tokens are duplicated
398
+ * without prefix, providing convenient short aliases alongside the
399
+ * prefixed versions.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * palette.tokens({ primary: 'brand' })
404
+ * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
405
+ * ```
406
+ */
407
+ primary?: string;
408
+ }
388
409
  interface GlazePalette {
389
410
  /**
390
411
  * Export all themes as a flat token map grouped by scheme variant.
412
+ * Prefix defaults to `true` — all tokens are prefixed with the theme name.
413
+ * Use `primary` to duplicate one theme's tokens without prefix.
391
414
  *
392
415
  * ```ts
393
- * palette.tokens({ prefix: true })
394
- * // → { light: { 'primary-surface': 'okhsl(...)' }, dark: { 'primary-surface': 'okhsl(...)' } }
416
+ * palette.tokens({ primary: 'brand' })
417
+ * // → { light: { 'brand-surface': '...', 'surface': '...', 'accent-surface': '...' } }
395
418
  * ```
396
419
  */
397
- tokens(options?: GlazeJsonOptions & {
398
- prefix?: boolean | Record<string, string>;
399
- }): Record<string, Record<string, string>>;
420
+ tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
400
421
  /**
401
422
  * Export all themes as tasty style-to-state bindings.
402
423
  * Uses `#name` color token keys and state aliases (`''`, `@dark`, etc.).
403
- * Spread into component styles or register as a recipe via `configure({ recipes })`.
424
+ * Prefix defaults to `true`. Use `primary` to duplicate one theme without prefix.
404
425
  * @see https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs
405
426
  */
406
- tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
407
- /** Export all themes as plain JSON. */
427
+ tasty(options?: GlazeTokenOptions & {
428
+ primary?: string;
429
+ }): Record<string, Record<string, string>>;
430
+ /** Export all themes as plain JSON grouped by theme name. */
408
431
  json(options?: GlazeJsonOptions & {
409
432
  prefix?: boolean | Record<string, string>;
410
433
  }): Record<string, Record<string, Record<string, string>>>;
411
434
  /** Export all themes as CSS custom property declarations. */
412
- css(options?: GlazeCssOptions & {
413
- prefix?: boolean | Record<string, string>;
414
- }): GlazeCssResult;
435
+ css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;
415
436
  }
416
437
  //#endregion
417
438
  //#region src/glaze.d.ts
@@ -433,16 +454,14 @@ declare function glaze(hueOrOptions: number | {
433
454
  declare namespace glaze {
434
455
  var configure: (config: GlazeConfig) => void;
435
456
  var palette: (themes: PaletteInput) => {
436
- tokens(options?: GlazeJsonOptions & {
437
- prefix?: boolean | Record<string, string>;
457
+ tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
458
+ tasty(options?: GlazeTokenOptions & {
459
+ primary?: string;
438
460
  }): Record<string, Record<string, string>>;
439
- tasty(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
440
461
  json(options?: GlazeJsonOptions & {
441
462
  prefix?: boolean | Record<string, string>;
442
463
  }): Record<string, Record<string, Record<string, string>>>;
443
- css(options?: GlazeCssOptions & {
444
- prefix?: boolean | Record<string, string>;
445
- }): GlazeCssResult;
464
+ css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;
446
465
  };
447
466
  var from: (data: GlazeThemeExport) => GlazeTheme;
448
467
  var color: (input: GlazeColorInput) => GlazeColorToken;
@@ -522,5 +541,5 @@ declare function formatHsl(h: number, s: number, l: number): string;
522
541
  */
523
542
  declare function formatOklch(h: number, s: number, l: number): string;
524
543
  //#endregion
525
- 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 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 };
544
+ 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 };
526
545
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -468,7 +468,7 @@ function formatOklch(h, s, l) {
468
468
  const C = Math.sqrt(a * a + b * b);
469
469
  let hh = Math.atan2(b, a) * (180 / Math.PI);
470
470
  hh = constrainAngle(hh);
471
- return `oklch(${fmt$1(L, 4)} ${fmt$1(C, 4)} ${fmt$1(hh, 1)})`;
471
+ return `oklch(${fmt$1(L, 4)} ${fmt$1(C, 4)} ${fmt$1(hh, 2)})`;
472
472
  }
473
473
 
474
474
  //#endregion
@@ -618,7 +618,7 @@ function coarseScan(h, s, lo, hi, yBase, target, epsilon, maxIter) {
618
618
  function findLightnessForContrast(options) {
619
619
  const { hue, saturation, preferredLightness, baseLinearRgb, contrast: contrastInput, lightnessRange = [0, 1], epsilon = 1e-4, maxIterations = 14 } = options;
620
620
  const target = resolveMinContrast(contrastInput);
621
- const searchTarget = target * 1.005;
621
+ const searchTarget = target * 1.007;
622
622
  const yBase = gamutClampedLuminance(baseLinearRgb);
623
623
  const crPref = contrastRatioFromLuminance(cachedLuminance(hue, saturation, preferredLightness), yBase);
624
624
  if (crPref >= searchTarget) return {
@@ -742,7 +742,7 @@ function searchMixBranch(lo, hi, yBase, target, epsilon, maxIter, preferred, lum
742
742
  function findValueForMixContrast(options) {
743
743
  const { preferredValue, baseLinearRgb, contrast: contrastInput, luminanceAtValue, epsilon = 1e-4, maxIterations = 20 } = options;
744
744
  const target = resolveMinContrast(contrastInput);
745
- const searchTarget = target * 1.005;
745
+ const searchTarget = target * 1.01;
746
746
  const yBase = gamutClampedLuminance(baseLinearRgb);
747
747
  const crPref = contrastRatioFromLuminance(luminanceAtValue(preferredValue), yBase);
748
748
  if (crPref >= searchTarget) return {
@@ -1419,26 +1419,40 @@ function createTheme(hue, saturation, initialColors) {
1419
1419
  }
1420
1420
  };
1421
1421
  }
1422
- function resolvePrefix(options, themeName) {
1423
- if (options?.prefix === true) return `${themeName}-`;
1424
- if (typeof options?.prefix === "object" && options.prefix !== null) return options.prefix[themeName] ?? `${themeName}-`;
1422
+ function resolvePrefix(options, themeName, defaultPrefix = false) {
1423
+ const prefix = options?.prefix ?? defaultPrefix;
1424
+ if (prefix === true) return `${themeName}-`;
1425
+ if (typeof prefix === "object" && prefix !== null) return prefix[themeName] ?? `${themeName}-`;
1425
1426
  return "";
1426
1427
  }
1428
+ function validatePrimaryTheme(primary, themes) {
1429
+ if (primary !== void 0 && !(primary in themes)) {
1430
+ const available = Object.keys(themes).join(", ");
1431
+ throw new Error(`glaze: primary theme "${primary}" not found in palette. Available: ${available}.`);
1432
+ }
1433
+ }
1427
1434
  function createPalette(themes) {
1428
1435
  return {
1429
1436
  tokens(options) {
1437
+ validatePrimaryTheme(options?.primary, themes);
1430
1438
  const modes = resolveModes(options?.modes);
1431
1439
  const allTokens = {};
1432
1440
  for (const [themeName, theme] of Object.entries(themes)) {
1433
- const tokens = buildFlatTokenMap(theme.resolve(), resolvePrefix(options, themeName), modes, options?.format);
1441
+ const resolved = theme.resolve();
1442
+ const tokens = buildFlatTokenMap(resolved, resolvePrefix(options, themeName, true), modes, options?.format);
1434
1443
  for (const variant of Object.keys(tokens)) {
1435
1444
  if (!allTokens[variant]) allTokens[variant] = {};
1436
1445
  Object.assign(allTokens[variant], tokens[variant]);
1437
1446
  }
1447
+ if (themeName === options?.primary) {
1448
+ const unprefixed = buildFlatTokenMap(resolved, "", modes, options?.format);
1449
+ for (const variant of Object.keys(unprefixed)) Object.assign(allTokens[variant], unprefixed[variant]);
1450
+ }
1438
1451
  }
1439
1452
  return allTokens;
1440
1453
  },
1441
1454
  tasty(options) {
1455
+ validatePrimaryTheme(options?.primary, themes);
1442
1456
  const states = {
1443
1457
  dark: options?.states?.dark ?? globalConfig.states.dark,
1444
1458
  highContrast: options?.states?.highContrast ?? globalConfig.states.highContrast
@@ -1446,8 +1460,13 @@ function createPalette(themes) {
1446
1460
  const modes = resolveModes(options?.modes);
1447
1461
  const allTokens = {};
1448
1462
  for (const [themeName, theme] of Object.entries(themes)) {
1449
- const tokens = buildTokenMap(theme.resolve(), resolvePrefix(options, themeName), states, modes, options?.format);
1463
+ const resolved = theme.resolve();
1464
+ const tokens = buildTokenMap(resolved, resolvePrefix(options, themeName, true), states, modes, options?.format);
1450
1465
  Object.assign(allTokens, tokens);
1466
+ if (themeName === options?.primary) {
1467
+ const unprefixed = buildTokenMap(resolved, "", states, modes, options?.format);
1468
+ Object.assign(allTokens, unprefixed);
1469
+ }
1451
1470
  }
1452
1471
  return allTokens;
1453
1472
  },
@@ -1458,6 +1477,7 @@ function createPalette(themes) {
1458
1477
  return result;
1459
1478
  },
1460
1479
  css(options) {
1480
+ validatePrimaryTheme(options?.primary, themes);
1461
1481
  const suffix = options?.suffix ?? "-color";
1462
1482
  const format = options?.format ?? "rgb";
1463
1483
  const allLines = {
@@ -1467,13 +1487,23 @@ function createPalette(themes) {
1467
1487
  darkContrast: []
1468
1488
  };
1469
1489
  for (const [themeName, theme] of Object.entries(themes)) {
1470
- const css = buildCssMap(theme.resolve(), resolvePrefix(options, themeName), suffix, format);
1490
+ const resolved = theme.resolve();
1491
+ const css = buildCssMap(resolved, resolvePrefix(options, themeName, true), suffix, format);
1471
1492
  for (const key of [
1472
1493
  "light",
1473
1494
  "dark",
1474
1495
  "lightContrast",
1475
1496
  "darkContrast"
1476
1497
  ]) if (css[key]) allLines[key].push(css[key]);
1498
+ if (themeName === options?.primary) {
1499
+ const unprefixed = buildCssMap(resolved, "", suffix, format);
1500
+ for (const key of [
1501
+ "light",
1502
+ "dark",
1503
+ "lightContrast",
1504
+ "darkContrast"
1505
+ ]) if (unprefixed[key]) allLines[key].push(unprefixed[key]);
1506
+ }
1477
1507
  }
1478
1508
  return {
1479
1509
  light: allLines.light.join("\n"),