@tenphi/glaze 1.0.0 → 1.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 +1 -1
- package/dist/index.cjs +398 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -36
- package/dist/index.d.mts +101 -36
- package/dist/index.mjs +395 -238
- package/dist/index.mjs.map +1 -1
- package/docs/api.md +111 -53
- package/docs/migration.md +5 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -675,6 +675,8 @@ function okhslToOklch(h, s, l, pastel = false) {
|
|
|
675
675
|
/**
|
|
676
676
|
* Build a fresh defaults object. Called from module init and from
|
|
677
677
|
* `resetConfig()` so the two paths can't drift.
|
|
678
|
+
*
|
|
679
|
+
* `pastel: false` is a fixed instance default — not globally configurable.
|
|
678
680
|
*/
|
|
679
681
|
function defaultConfig() {
|
|
680
682
|
return {
|
|
@@ -739,7 +741,7 @@ function configure(config) {
|
|
|
739
741
|
},
|
|
740
742
|
shadowTuning: config.shadowTuning ?? globalConfig.shadowTuning,
|
|
741
743
|
autoFlip: config.autoFlip ?? globalConfig.autoFlip,
|
|
742
|
-
pastel:
|
|
744
|
+
pastel: false,
|
|
743
745
|
inferRole: config.inferRole ?? globalConfig.inferRole
|
|
744
746
|
};
|
|
745
747
|
}
|
|
@@ -752,9 +754,15 @@ function resetConfig() {
|
|
|
752
754
|
* Only fields present in `override` are replaced; others fall through
|
|
753
755
|
* from `base`. `false` for tone windows passes through as-is
|
|
754
756
|
* (treated as the full range by `activeWindow()` in okhst.ts).
|
|
757
|
+
*
|
|
758
|
+
* `pastel` is instance-only: `override.pastel ?? false`, never inherited
|
|
759
|
+
* from the global base.
|
|
755
760
|
*/
|
|
756
761
|
function mergeConfig(base, override) {
|
|
757
|
-
if (!override) return base
|
|
762
|
+
if (!override) return base.pastel === false ? base : {
|
|
763
|
+
...base,
|
|
764
|
+
pastel: false
|
|
765
|
+
};
|
|
758
766
|
return {
|
|
759
767
|
lightTone: override.lightTone !== void 0 ? override.lightTone : base.lightTone,
|
|
760
768
|
darkTone: override.darkTone !== void 0 ? override.darkTone : base.darkTone,
|
|
@@ -763,10 +771,99 @@ function mergeConfig(base, override) {
|
|
|
763
771
|
modes: base.modes,
|
|
764
772
|
shadowTuning: override.shadowTuning ?? base.shadowTuning,
|
|
765
773
|
autoFlip: override.autoFlip ?? base.autoFlip,
|
|
766
|
-
pastel: override.pastel ??
|
|
774
|
+
pastel: override.pastel ?? false,
|
|
767
775
|
inferRole: override.inferRole ?? base.inferRole
|
|
768
776
|
};
|
|
769
777
|
}
|
|
778
|
+
/**
|
|
779
|
+
* Freeze `getConfig() ∪ instanceLocal ∪ exportArg` as a plain, resolve-relevant
|
|
780
|
+
* override for authoring export, so restored snapshots pin these fields. Later
|
|
781
|
+
* wins; nested objects (`shadowTuning`) replace wholesale. The final
|
|
782
|
+
* `structuredClone` detaches tone-window / shadow objects that `mergeConfig`
|
|
783
|
+
* may still share with the live global config.
|
|
784
|
+
*/
|
|
785
|
+
function freezeConfigForExport(instanceLocal, exportArg) {
|
|
786
|
+
const effective = mergeConfig(getConfig(), {
|
|
787
|
+
...instanceLocal,
|
|
788
|
+
...exportArg
|
|
789
|
+
});
|
|
790
|
+
const out = {
|
|
791
|
+
lightTone: effective.lightTone,
|
|
792
|
+
darkTone: effective.darkTone,
|
|
793
|
+
darkDesaturation: effective.darkDesaturation,
|
|
794
|
+
autoFlip: effective.autoFlip,
|
|
795
|
+
pastel: effective.pastel,
|
|
796
|
+
inferRole: effective.inferRole
|
|
797
|
+
};
|
|
798
|
+
if (effective.shadowTuning !== void 0) out.shadowTuning = effective.shadowTuning;
|
|
799
|
+
return structuredClone(out);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
//#endregion
|
|
803
|
+
//#region src/types.ts
|
|
804
|
+
/**
|
|
805
|
+
* Current authoring-export schema version. Bump when the export shape
|
|
806
|
+
* changes in a non-compatible way. Written on every `.export()` snapshot.
|
|
807
|
+
*/
|
|
808
|
+
const GLAZE_EXPORT_VERSION = 1;
|
|
809
|
+
|
|
810
|
+
//#endregion
|
|
811
|
+
//#region src/serialize.ts
|
|
812
|
+
/**
|
|
813
|
+
* Authoring-export helpers: schema version, type guards, and restore
|
|
814
|
+
* validation shared by `themeFrom` / `colorFrom` / `paletteFrom`.
|
|
815
|
+
*/
|
|
816
|
+
function isPlainObject(data) {
|
|
817
|
+
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Reject unknown / invalid schema versions. Missing `version` is allowed
|
|
821
|
+
* (legacy snapshots). Present versions must be an integer in
|
|
822
|
+
* `1..=GLAZE_EXPORT_VERSION`.
|
|
823
|
+
*/
|
|
824
|
+
function assertExportVersion(data, factory) {
|
|
825
|
+
if (data.version === void 0) return;
|
|
826
|
+
if (typeof data.version !== "number" || !Number.isInteger(data.version) || data.version < 1) throw new Error(`${factory}: invalid "version" field — expected an integer >= 1 (got ${JSON.stringify(data.version)}).`);
|
|
827
|
+
if (data.version > GLAZE_EXPORT_VERSION) throw new Error(`${factory}: unsupported export version ${data.version} (this library supports version ${GLAZE_EXPORT_VERSION}). Upgrade @tenphi/glaze to load this snapshot.`);
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* When `kind` is present, it must match the factory. Missing `kind` is
|
|
831
|
+
* allowed for legacy snapshots.
|
|
832
|
+
*/
|
|
833
|
+
function assertExportKind(data, expected, factory) {
|
|
834
|
+
if (data.kind === void 0) return;
|
|
835
|
+
if (data.kind !== expected) throw new Error(`${factory}: expected kind "${expected}", got ${JSON.stringify(data.kind)}.`);
|
|
836
|
+
}
|
|
837
|
+
function hasThemeShape(data) {
|
|
838
|
+
return typeof data.hue === "number" && typeof data.saturation === "number" && !("form" in data) && !("themes" in data);
|
|
839
|
+
}
|
|
840
|
+
function hasColorTokenShape(data) {
|
|
841
|
+
return data.form === "value" || data.form === "structured";
|
|
842
|
+
}
|
|
843
|
+
function hasPaletteShape(data) {
|
|
844
|
+
return isPlainObject(data.themes) && !("form" in data) && typeof data.hue !== "number";
|
|
845
|
+
}
|
|
846
|
+
/** Type guard for theme authoring snapshots (prefers `kind`, falls back to shape). */
|
|
847
|
+
function isThemeExport(data) {
|
|
848
|
+
if (!isPlainObject(data)) return false;
|
|
849
|
+
if (data.kind === "theme") return hasThemeShape(data);
|
|
850
|
+
if (data.kind !== void 0) return false;
|
|
851
|
+
return hasThemeShape(data);
|
|
852
|
+
}
|
|
853
|
+
/** Type guard for color-token authoring snapshots. */
|
|
854
|
+
function isColorTokenExport(data) {
|
|
855
|
+
if (!isPlainObject(data)) return false;
|
|
856
|
+
if (data.kind === "color") return hasColorTokenShape(data);
|
|
857
|
+
if (data.kind !== void 0) return false;
|
|
858
|
+
return hasColorTokenShape(data);
|
|
859
|
+
}
|
|
860
|
+
/** Type guard for palette authoring snapshots. */
|
|
861
|
+
function isPaletteExport(data) {
|
|
862
|
+
if (!isPlainObject(data)) return false;
|
|
863
|
+
if (data.kind === "palette") return hasPaletteShape(data);
|
|
864
|
+
if (data.kind !== void 0) return false;
|
|
865
|
+
return hasPaletteShape(data);
|
|
866
|
+
}
|
|
770
867
|
|
|
771
868
|
//#endregion
|
|
772
869
|
//#region src/format-guard.ts
|
|
@@ -811,7 +908,7 @@ function assertAllPastel(resolved, modes) {
|
|
|
811
908
|
}
|
|
812
909
|
}
|
|
813
910
|
if (nonPastel.length === 0) return;
|
|
814
|
-
throw new Error(`glaze: splitHue requires every color to be pastel (hue rotation is only clip-free when chroma is bounded by the hue-independent safe chroma). Non-pastel: ${nonPastel.join(", ")}. Set pastel: true (
|
|
911
|
+
throw new Error(`glaze: splitHue requires every color to be pastel (hue rotation is only clip-free when chroma is bounded by the hue-independent safe chroma). Non-pastel: ${nonPastel.join(", ")}. Set pastel: true (per-theme, per-token, or per-color) or drop splitHue.`);
|
|
815
912
|
}
|
|
816
913
|
|
|
817
914
|
//#endregion
|
|
@@ -1882,15 +1979,18 @@ function resolveContrastSpec(spec, isHighContrast, polarity) {
|
|
|
1882
1979
|
/**
|
|
1883
1980
|
* Apply the relative-tone delta against a base, honoring `flip`.
|
|
1884
1981
|
*
|
|
1885
|
-
* When `flip` is on and `base + delta` falls outside `[0, 100]`,
|
|
1886
|
-
* delta to the other side of the base
|
|
1887
|
-
*
|
|
1982
|
+
* When `flip` is on and `base + delta` falls outside `[0, 100]`, try mirroring
|
|
1983
|
+
* the delta to the other side of the base. If the mirrored target is also out
|
|
1984
|
+
* of range, keep the original delta so the caller clamps on the authored side.
|
|
1985
|
+
* When off, the caller clamps as usual.
|
|
1888
1986
|
*/
|
|
1889
1987
|
function applyToneFlip(delta, baseTone, flip) {
|
|
1890
1988
|
if (!flip) return delta;
|
|
1891
1989
|
const target = baseTone + delta;
|
|
1892
1990
|
if (target >= 0 && target <= 100) return delta;
|
|
1893
|
-
|
|
1991
|
+
const mirrored = baseTone - delta;
|
|
1992
|
+
if (mirrored >= 0 && mirrored <= 100) return -delta;
|
|
1993
|
+
return delta;
|
|
1894
1994
|
}
|
|
1895
1995
|
function resolveRootColor(def, isHighContrast) {
|
|
1896
1996
|
const rawT = def.tone;
|
|
@@ -2652,12 +2752,10 @@ function buildTailwindMap(resolved, themePrefix, cssPrefix, modes, format, darkS
|
|
|
2652
2752
|
* `{ l, c, h }`), the structured-input validator, the two factory paths
|
|
2653
2753
|
* (value vs structured), and the JSON-safe export / rehydration round-trip.
|
|
2654
2754
|
*
|
|
2655
|
-
*
|
|
2656
|
-
*
|
|
2657
|
-
*
|
|
2658
|
-
* `
|
|
2659
|
-
* The token's resolved variants are then memoized on first
|
|
2660
|
-
* `.resolve()` / `.token()` / ... call.
|
|
2755
|
+
* Tokens store a sparse local config override only. Resolve merges the
|
|
2756
|
+
* live global config with that local override (invalidated on
|
|
2757
|
+
* `configure()`). Authoring `.export(override?)` freezes
|
|
2758
|
+
* `getConfig() ∪ local ∪ override` at call time.
|
|
2661
2759
|
*/
|
|
2662
2760
|
/** Internal name of the user-facing standalone color in the synthesized def map. */
|
|
2663
2761
|
const STANDALONE_VALUE = "value";
|
|
@@ -2672,47 +2770,16 @@ const RESERVED_STANDALONE_NAMES = new Set([
|
|
|
2672
2770
|
STANDALONE_BASE
|
|
2673
2771
|
]);
|
|
2674
2772
|
/**
|
|
2675
|
-
*
|
|
2676
|
-
*
|
|
2677
|
-
* Light window defaults to `false` (preserve input tone exactly).
|
|
2678
|
-
* All other fields snapshot from global at create time. User override
|
|
2679
|
-
* fields win over all defaults.
|
|
2773
|
+
* Value-form local override: `lightTone` defaults to `false` (preserve
|
|
2774
|
+
* input tone). User override fields win.
|
|
2680
2775
|
*/
|
|
2681
|
-
function
|
|
2682
|
-
const cfg = getConfig();
|
|
2776
|
+
function sparseValueFormLocal(userOverride) {
|
|
2683
2777
|
return {
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
darkDesaturation: userOverride?.darkDesaturation ?? cfg.darkDesaturation,
|
|
2687
|
-
autoFlip: userOverride?.autoFlip ?? cfg.autoFlip,
|
|
2688
|
-
shadowTuning: userOverride?.shadowTuning ?? cfg.shadowTuning
|
|
2778
|
+
...userOverride,
|
|
2779
|
+
lightTone: userOverride?.lightTone !== void 0 ? userOverride.lightTone : false
|
|
2689
2780
|
};
|
|
2690
2781
|
}
|
|
2691
2782
|
/**
|
|
2692
|
-
* Build the per-token effective config override for a structured-form color.
|
|
2693
|
-
*
|
|
2694
|
-
* Both light and dark windows snapshot from global at create time.
|
|
2695
|
-
* User override fields win.
|
|
2696
|
-
*/
|
|
2697
|
-
function buildStructuredConfigOverride(userOverride) {
|
|
2698
|
-
const cfg = getConfig();
|
|
2699
|
-
return {
|
|
2700
|
-
lightTone: userOverride?.lightTone !== void 0 ? userOverride.lightTone : cfg.lightTone,
|
|
2701
|
-
darkTone: userOverride?.darkTone !== void 0 ? userOverride.darkTone : cfg.darkTone,
|
|
2702
|
-
darkDesaturation: userOverride?.darkDesaturation ?? cfg.darkDesaturation,
|
|
2703
|
-
autoFlip: userOverride?.autoFlip ?? cfg.autoFlip,
|
|
2704
|
-
shadowTuning: userOverride?.shadowTuning ?? cfg.shadowTuning
|
|
2705
|
-
};
|
|
2706
|
-
}
|
|
2707
|
-
/**
|
|
2708
|
-
* Build the `GlazeConfigResolved` to pass to `resolveAllColors` from a
|
|
2709
|
-
* snapshot override. Uses `defaultConfig()` as the base so all required
|
|
2710
|
-
* fields are present; the snapshot fields win.
|
|
2711
|
-
*/
|
|
2712
|
-
function resolvedConfigFromOverride(override) {
|
|
2713
|
-
return mergeConfig(defaultConfig(), override);
|
|
2714
|
-
}
|
|
2715
|
-
/**
|
|
2716
2783
|
* Matches the CSS color functions Glaze itself emits (`rgb()`, `hsl()`,
|
|
2717
2784
|
* `okhsl()`, `oklch()`) plus their legacy alpha aliases (`rgba()`, `hsla()`).
|
|
2718
2785
|
*
|
|
@@ -3002,12 +3069,30 @@ function buildStandaloneValueDefs(main, options) {
|
|
|
3002
3069
|
primary
|
|
3003
3070
|
};
|
|
3004
3071
|
}
|
|
3005
|
-
function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary,
|
|
3006
|
-
let
|
|
3072
|
+
function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, configOverride, baseToken, buildExport) {
|
|
3073
|
+
let cache = null;
|
|
3074
|
+
function getEffectiveConfig() {
|
|
3075
|
+
const version = getConfigVersion();
|
|
3076
|
+
if (cache && cache.version === version) return cache.effectiveConfig;
|
|
3077
|
+
const effectiveConfig = mergeConfig(getConfig(), configOverride);
|
|
3078
|
+
cache = {
|
|
3079
|
+
map: null,
|
|
3080
|
+
version,
|
|
3081
|
+
effectiveConfig
|
|
3082
|
+
};
|
|
3083
|
+
return effectiveConfig;
|
|
3084
|
+
}
|
|
3007
3085
|
const resolveOnce = () => {
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3086
|
+
const version = getConfigVersion();
|
|
3087
|
+
if (cache && cache.version === version && cache.map) return cache.map;
|
|
3088
|
+
const effectiveConfig = getEffectiveConfig();
|
|
3089
|
+
const map = resolveAllColors(seedHue, seedSaturation, defs, effectiveConfig, baseToken ? new Map([[STANDALONE_BASE, baseToken.resolve()]]) : void 0);
|
|
3090
|
+
cache = {
|
|
3091
|
+
map,
|
|
3092
|
+
version,
|
|
3093
|
+
effectiveConfig
|
|
3094
|
+
};
|
|
3095
|
+
return map;
|
|
3011
3096
|
};
|
|
3012
3097
|
const resolveStates = (options) => {
|
|
3013
3098
|
const cfg = getConfig();
|
|
@@ -3017,7 +3102,7 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
|
|
|
3017
3102
|
};
|
|
3018
3103
|
};
|
|
3019
3104
|
const tokenLike = (options) => {
|
|
3020
|
-
return buildTokenMap(resolveOnce(), "", resolveStates(options), resolveModes(options?.modes), options?.format ?? "oklch",
|
|
3105
|
+
return buildTokenMap(resolveOnce(), "", resolveStates(options), resolveModes(options?.modes), options?.format ?? "oklch", getEffectiveConfig().pastel)[`#${primary}`];
|
|
3021
3106
|
};
|
|
3022
3107
|
return {
|
|
3023
3108
|
resolve() {
|
|
@@ -3028,7 +3113,7 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
|
|
|
3028
3113
|
json(options) {
|
|
3029
3114
|
const format = options?.format ?? "oklch";
|
|
3030
3115
|
assertNativeFormat(format, "json");
|
|
3031
|
-
return buildJsonMap(resolveOnce(), resolveModes(options?.modes), format,
|
|
3116
|
+
return buildJsonMap(resolveOnce(), resolveModes(options?.modes), format, getEffectiveConfig().pastel)[primary];
|
|
3032
3117
|
},
|
|
3033
3118
|
css(options) {
|
|
3034
3119
|
const format = options.format ?? "oklch";
|
|
@@ -3047,11 +3132,11 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
|
|
|
3047
3132
|
resolvedHue: resolved.light.h
|
|
3048
3133
|
};
|
|
3049
3134
|
}
|
|
3050
|
-
return buildCssMap(renamed, "", options.suffix ?? "-color", format,
|
|
3135
|
+
return buildCssMap(renamed, "", options.suffix ?? "-color", format, getEffectiveConfig().pastel, channelCtx);
|
|
3051
3136
|
},
|
|
3052
3137
|
dtcg(options) {
|
|
3053
3138
|
const modes = resolveModes(options?.modes);
|
|
3054
|
-
const doc = buildDtcgMap(resolveOnce(), "", modes, options?.colorSpace ?? "srgb",
|
|
3139
|
+
const doc = buildDtcgMap(resolveOnce(), "", modes, options?.colorSpace ?? "srgb", getEffectiveConfig().pastel);
|
|
3055
3140
|
const result = { light: doc.light[primary] };
|
|
3056
3141
|
if (doc.dark) result.dark = doc.dark[primary];
|
|
3057
3142
|
if (doc.lightContrast) result.lightContrast = doc.lightContrast[primary];
|
|
@@ -3059,7 +3144,7 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
|
|
|
3059
3144
|
return result;
|
|
3060
3145
|
},
|
|
3061
3146
|
dtcgResolver(options) {
|
|
3062
|
-
const doc = buildDtcgMap(resolveOnce(), "", resolveModes(options?.modes), options?.colorSpace ?? "srgb",
|
|
3147
|
+
const doc = buildDtcgMap(resolveOnce(), "", resolveModes(options?.modes), options?.colorSpace ?? "srgb", getEffectiveConfig().pastel);
|
|
3063
3148
|
const name = options.name;
|
|
3064
3149
|
const result = { light: { [name]: doc.light[primary] } };
|
|
3065
3150
|
if (doc.dark) result.dark = { [name]: doc.dark[primary] };
|
|
@@ -3070,9 +3155,11 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
|
|
|
3070
3155
|
tailwind(options) {
|
|
3071
3156
|
const format = options.format ?? "oklch";
|
|
3072
3157
|
assertNativeFormat(format, "tailwind");
|
|
3073
|
-
return buildTailwindMap(new Map([[options.name, resolveOnce().get(primary)]]), "", options.namespace ?? "color-", resolveModes(options?.modes), format, options.darkSelector ?? ".dark", options.highContrastSelector ?? ".high-contrast",
|
|
3158
|
+
return buildTailwindMap(new Map([[options.name, resolveOnce().get(primary)]]), "", options.namespace ?? "color-", resolveModes(options?.modes), format, options.darkSelector ?? ".dark", options.highContrastSelector ?? ".high-contrast", getEffectiveConfig().pastel);
|
|
3074
3159
|
},
|
|
3075
|
-
export
|
|
3160
|
+
export(override) {
|
|
3161
|
+
return buildExport(override);
|
|
3162
|
+
}
|
|
3076
3163
|
};
|
|
3077
3164
|
}
|
|
3078
3165
|
/**
|
|
@@ -3139,35 +3226,35 @@ function createColorToken(input, configOverride) {
|
|
|
3139
3226
|
mode: "static"
|
|
3140
3227
|
};
|
|
3141
3228
|
}
|
|
3142
|
-
const
|
|
3143
|
-
|
|
3144
|
-
|
|
3229
|
+
const localOverride = configOverride;
|
|
3230
|
+
return createColorTokenFromDefs(input.hue, input.saturation, defs, primary, localOverride, baseToken, (exportArg) => ({
|
|
3231
|
+
kind: "color",
|
|
3232
|
+
version: GLAZE_EXPORT_VERSION,
|
|
3145
3233
|
form: "structured",
|
|
3146
|
-
input: buildStructuredInputExport(input),
|
|
3147
|
-
config:
|
|
3148
|
-
});
|
|
3149
|
-
return createColorTokenFromDefs(input.hue, input.saturation, defs, primary, effectiveConfig, baseToken, exportData);
|
|
3234
|
+
input: buildStructuredInputExport(input, exportArg),
|
|
3235
|
+
config: freezeConfigForExport(localOverride, exportArg)
|
|
3236
|
+
}));
|
|
3150
3237
|
}
|
|
3151
3238
|
function createColorTokenFromValue(value, options, configOverride) {
|
|
3152
3239
|
const main = extractOkhslFromValue(value);
|
|
3153
3240
|
const linkingBase = toLinkingBase(resolveBaseToken(options?.base));
|
|
3154
3241
|
const { seedHue, seedSaturation, defs, primary } = buildStandaloneValueDefs(main, options);
|
|
3155
|
-
const
|
|
3156
|
-
|
|
3157
|
-
|
|
3242
|
+
const localOverride = sparseValueFormLocal(configOverride);
|
|
3243
|
+
return createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, localOverride, linkingBase, (exportArg) => ({
|
|
3244
|
+
kind: "color",
|
|
3245
|
+
version: GLAZE_EXPORT_VERSION,
|
|
3158
3246
|
form: "value",
|
|
3159
3247
|
input: value,
|
|
3160
|
-
...options !== void 0 ? { overrides: buildOverridesExport(options) } : {},
|
|
3161
|
-
config:
|
|
3162
|
-
});
|
|
3163
|
-
return createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effectiveConfig, linkingBase, exportData);
|
|
3248
|
+
...options !== void 0 ? { overrides: buildOverridesExport(options, exportArg) } : {},
|
|
3249
|
+
config: freezeConfigForExport(localOverride, exportArg)
|
|
3250
|
+
}));
|
|
3164
3251
|
}
|
|
3165
3252
|
/**
|
|
3166
3253
|
* Build a JSON-safe snapshot of `GlazeColorOverrides`. `base` is
|
|
3167
3254
|
* recursively serialized when it was originally a token; raw values are
|
|
3168
3255
|
* preserved as-is so `glaze.colorFrom(...)` round-trips them.
|
|
3169
3256
|
*/
|
|
3170
|
-
function buildOverridesExport(options) {
|
|
3257
|
+
function buildOverridesExport(options, exportArg) {
|
|
3171
3258
|
const out = {};
|
|
3172
3259
|
if (options.hue !== void 0) out.hue = options.hue;
|
|
3173
3260
|
if (options.saturation !== void 0) out.saturation = options.saturation;
|
|
@@ -3180,10 +3267,10 @@ function buildOverridesExport(options) {
|
|
|
3180
3267
|
if (options.name !== void 0) out.name = options.name;
|
|
3181
3268
|
if (options.pastel !== void 0) out.pastel = options.pastel;
|
|
3182
3269
|
if (options.role !== void 0) out.role = options.role;
|
|
3183
|
-
if (options.base !== void 0) out.base = isGlazeColorToken(options.base) ? options.base.export() : options.base;
|
|
3270
|
+
if (options.base !== void 0) out.base = isGlazeColorToken(options.base) ? options.base.export(exportArg) : options.base;
|
|
3184
3271
|
return out;
|
|
3185
3272
|
}
|
|
3186
|
-
function buildStructuredInputExport(input) {
|
|
3273
|
+
function buildStructuredInputExport(input, exportArg) {
|
|
3187
3274
|
const out = {
|
|
3188
3275
|
hue: input.hue,
|
|
3189
3276
|
saturation: input.saturation,
|
|
@@ -3197,14 +3284,14 @@ function buildStructuredInputExport(input) {
|
|
|
3197
3284
|
if (input.name !== void 0) out.name = input.name;
|
|
3198
3285
|
if (input.pastel !== void 0) out.pastel = input.pastel;
|
|
3199
3286
|
if (input.role !== void 0) out.role = input.role;
|
|
3200
|
-
if (input.base !== void 0) out.base = isGlazeColorToken(input.base) ? input.base.export() : input.base;
|
|
3287
|
+
if (input.base !== void 0) out.base = isGlazeColorToken(input.base) ? input.base.export(exportArg) : input.base;
|
|
3201
3288
|
return out;
|
|
3202
3289
|
}
|
|
3203
3290
|
/**
|
|
3204
3291
|
* Discriminate a `GlazeColorTokenExport` from a raw `GlazeColorValue`.
|
|
3205
3292
|
*/
|
|
3206
3293
|
function isExportedToken(candidate) {
|
|
3207
|
-
return
|
|
3294
|
+
return isColorTokenExport(candidate);
|
|
3208
3295
|
}
|
|
3209
3296
|
function rehydrateOverrides(data) {
|
|
3210
3297
|
const out = {};
|
|
@@ -3243,12 +3330,14 @@ function rehydrateStructuredInput(data) {
|
|
|
3243
3330
|
* Rehydrate a token from its `.export()` snapshot. Recursively rebuilds
|
|
3244
3331
|
* any base dependency. Inverse of `GlazeColorToken.export()`.
|
|
3245
3332
|
*
|
|
3246
|
-
* The stored `config` field
|
|
3247
|
-
*
|
|
3248
|
-
*
|
|
3333
|
+
* The stored `config` field is the freeze from export time — passed as
|
|
3334
|
+
* the instance local override so the rehydrated token stays pinned
|
|
3335
|
+
* against later `glaze.configure()` calls.
|
|
3249
3336
|
*/
|
|
3250
3337
|
function colorFromExport(data) {
|
|
3251
3338
|
if (data === null || typeof data !== "object") throw new Error(`glaze.colorFrom: expected an object from token.export(), got ${data === null ? "null" : typeof data}.`);
|
|
3339
|
+
assertExportKind(data, "color", "glaze.colorFrom");
|
|
3340
|
+
assertExportVersion(data, "glaze.colorFrom");
|
|
3252
3341
|
if (data.form !== "value" && data.form !== "structured") throw new Error(`glaze.colorFrom: invalid "form" field — expected "value" or "structured" (got ${JSON.stringify(data.form)}).`);
|
|
3253
3342
|
if (data.input === void 0) throw new Error(`glaze.colorFrom: missing "input" field — expected the original ${data.form === "value" ? "GlazeColorValue" : "GlazeColorInput"}.`);
|
|
3254
3343
|
if (data.form === "value") {
|
|
@@ -3258,6 +3347,157 @@ function colorFromExport(data) {
|
|
|
3258
3347
|
return createColorToken(rehydrateStructuredInput(data.input), data.config);
|
|
3259
3348
|
}
|
|
3260
3349
|
|
|
3350
|
+
//#endregion
|
|
3351
|
+
//#region src/theme.ts
|
|
3352
|
+
function createTheme(hue, saturation, initialColors, configOverride) {
|
|
3353
|
+
let colorDefs = initialColors ? { ...initialColors } : {};
|
|
3354
|
+
let cache = null;
|
|
3355
|
+
function getEffectiveConfig() {
|
|
3356
|
+
const version = getConfigVersion();
|
|
3357
|
+
if (cache && cache.version === version) return cache.effectiveConfig;
|
|
3358
|
+
const effectiveConfig = mergeConfig(getConfig(), configOverride);
|
|
3359
|
+
cache = {
|
|
3360
|
+
map: null,
|
|
3361
|
+
version,
|
|
3362
|
+
effectiveConfig
|
|
3363
|
+
};
|
|
3364
|
+
return effectiveConfig;
|
|
3365
|
+
}
|
|
3366
|
+
function resolveCached() {
|
|
3367
|
+
const version = getConfigVersion();
|
|
3368
|
+
if (cache && cache.version === version && cache.map) return cache.map;
|
|
3369
|
+
const effectiveConfig = getEffectiveConfig();
|
|
3370
|
+
const map = resolveAllColors(hue, saturation, colorDefs, effectiveConfig);
|
|
3371
|
+
cache = {
|
|
3372
|
+
map,
|
|
3373
|
+
version,
|
|
3374
|
+
effectiveConfig
|
|
3375
|
+
};
|
|
3376
|
+
return map;
|
|
3377
|
+
}
|
|
3378
|
+
function invalidate() {
|
|
3379
|
+
cache = null;
|
|
3380
|
+
}
|
|
3381
|
+
function channelCtxFor(options, formatDefault, prefix) {
|
|
3382
|
+
const format = options?.format ?? formatDefault;
|
|
3383
|
+
if (!options?.splitHue || format !== "oklch") return void 0;
|
|
3384
|
+
assertAllPastel(resolveCached(), resolveModes(options?.modes));
|
|
3385
|
+
return {
|
|
3386
|
+
seedHue: hue,
|
|
3387
|
+
baseName: options.name ?? "theme",
|
|
3388
|
+
prefix,
|
|
3389
|
+
defs: colorDefs,
|
|
3390
|
+
mode: "theme"
|
|
3391
|
+
};
|
|
3392
|
+
}
|
|
3393
|
+
return {
|
|
3394
|
+
get hue() {
|
|
3395
|
+
return hue;
|
|
3396
|
+
},
|
|
3397
|
+
get saturation() {
|
|
3398
|
+
return saturation;
|
|
3399
|
+
},
|
|
3400
|
+
getConfig() {
|
|
3401
|
+
return getEffectiveConfig();
|
|
3402
|
+
},
|
|
3403
|
+
colors(defs) {
|
|
3404
|
+
colorDefs = {
|
|
3405
|
+
...colorDefs,
|
|
3406
|
+
...defs
|
|
3407
|
+
};
|
|
3408
|
+
invalidate();
|
|
3409
|
+
},
|
|
3410
|
+
color(name, def) {
|
|
3411
|
+
if (def === void 0) return colorDefs[name];
|
|
3412
|
+
colorDefs[name] = def;
|
|
3413
|
+
invalidate();
|
|
3414
|
+
},
|
|
3415
|
+
remove(names) {
|
|
3416
|
+
const list = Array.isArray(names) ? names : [names];
|
|
3417
|
+
for (const name of list) delete colorDefs[name];
|
|
3418
|
+
invalidate();
|
|
3419
|
+
},
|
|
3420
|
+
has(name) {
|
|
3421
|
+
return name in colorDefs;
|
|
3422
|
+
},
|
|
3423
|
+
list() {
|
|
3424
|
+
return Object.keys(colorDefs);
|
|
3425
|
+
},
|
|
3426
|
+
reset() {
|
|
3427
|
+
colorDefs = {};
|
|
3428
|
+
invalidate();
|
|
3429
|
+
},
|
|
3430
|
+
export(override) {
|
|
3431
|
+
return {
|
|
3432
|
+
kind: "theme",
|
|
3433
|
+
version: GLAZE_EXPORT_VERSION,
|
|
3434
|
+
hue,
|
|
3435
|
+
saturation,
|
|
3436
|
+
colors: structuredClone(colorDefs),
|
|
3437
|
+
config: freezeConfigForExport(configOverride, override)
|
|
3438
|
+
};
|
|
3439
|
+
},
|
|
3440
|
+
extend(options) {
|
|
3441
|
+
const newHue = options.hue ?? hue;
|
|
3442
|
+
const newSat = options.saturation ?? saturation;
|
|
3443
|
+
const inheritedColors = {};
|
|
3444
|
+
for (const [name, def] of Object.entries(colorDefs)) if (def.inherit !== false) inheritedColors[name] = def;
|
|
3445
|
+
return createTheme(newHue, newSat, options.colors ? {
|
|
3446
|
+
...inheritedColors,
|
|
3447
|
+
...options.colors
|
|
3448
|
+
} : { ...inheritedColors }, configOverride || options.config ? {
|
|
3449
|
+
...configOverride ?? {},
|
|
3450
|
+
...options.config ?? {}
|
|
3451
|
+
} : void 0);
|
|
3452
|
+
},
|
|
3453
|
+
resolve() {
|
|
3454
|
+
return new Map(resolveCached());
|
|
3455
|
+
},
|
|
3456
|
+
tokens(options) {
|
|
3457
|
+
const format = options?.format ?? "oklch";
|
|
3458
|
+
assertNativeFormat(format, "tokens");
|
|
3459
|
+
const modes = resolveModes(options?.modes);
|
|
3460
|
+
return buildFlatTokenMap(resolveCached(), "", modes, format, getEffectiveConfig().pastel);
|
|
3461
|
+
},
|
|
3462
|
+
tasty(options) {
|
|
3463
|
+
const cfg = getEffectiveConfig();
|
|
3464
|
+
const states = {
|
|
3465
|
+
dark: options?.states?.dark ?? cfg.states.dark,
|
|
3466
|
+
highContrast: options?.states?.highContrast ?? cfg.states.highContrast
|
|
3467
|
+
};
|
|
3468
|
+
const modes = resolveModes(options?.modes);
|
|
3469
|
+
const format = options?.format ?? "oklch";
|
|
3470
|
+
const channelCtx = channelCtxFor(options, "oklch", "");
|
|
3471
|
+
return buildTokenMap(resolveCached(), "", states, modes, format, cfg.pastel, channelCtx);
|
|
3472
|
+
},
|
|
3473
|
+
json(options) {
|
|
3474
|
+
const format = options?.format ?? "oklch";
|
|
3475
|
+
assertNativeFormat(format, "json");
|
|
3476
|
+
const modes = resolveModes(options?.modes);
|
|
3477
|
+
return buildJsonMap(resolveCached(), modes, format, getEffectiveConfig().pastel);
|
|
3478
|
+
},
|
|
3479
|
+
css(options) {
|
|
3480
|
+
const format = options?.format ?? "oklch";
|
|
3481
|
+
assertNativeFormat(format, "css");
|
|
3482
|
+
const channelCtx = channelCtxFor(options, "oklch", "");
|
|
3483
|
+
return buildCssMap(resolveCached(), "", options?.suffix ?? "-color", format, getEffectiveConfig().pastel, channelCtx);
|
|
3484
|
+
},
|
|
3485
|
+
dtcg(options) {
|
|
3486
|
+
const modes = resolveModes(options?.modes);
|
|
3487
|
+
return buildDtcgMap(resolveCached(), "", modes, options?.colorSpace ?? "srgb", getEffectiveConfig().pastel);
|
|
3488
|
+
},
|
|
3489
|
+
dtcgResolver(options) {
|
|
3490
|
+
return buildDtcgResolver(buildDtcgMap(resolveCached(), "", resolveModes(options?.modes), options?.colorSpace ?? "srgb", getEffectiveConfig().pastel), options);
|
|
3491
|
+
},
|
|
3492
|
+
tailwind(options) {
|
|
3493
|
+
const format = options?.format ?? "oklch";
|
|
3494
|
+
assertNativeFormat(format, "tailwind");
|
|
3495
|
+
const modes = resolveModes(options?.modes);
|
|
3496
|
+
return buildTailwindMap(resolveCached(), "", options?.namespace ?? "color-", modes, format, options?.darkSelector ?? ".dark", options?.highContrastSelector ?? ".high-contrast", getEffectiveConfig().pastel);
|
|
3497
|
+
}
|
|
3498
|
+
};
|
|
3499
|
+
}
|
|
3500
|
+
|
|
3261
3501
|
//#endregion
|
|
3262
3502
|
//#region src/palette.ts
|
|
3263
3503
|
function resolvePrefix(options, themeName, defaultPrefix = false) {
|
|
@@ -3337,6 +3577,26 @@ function buildPaletteOutput(themes, paletteOptions, options, buildOne, merge, em
|
|
|
3337
3577
|
}
|
|
3338
3578
|
return acc;
|
|
3339
3579
|
}
|
|
3580
|
+
/** Rebuild a theme from a `theme.export()` snapshot. */
|
|
3581
|
+
function createThemeFromExport(data, factory = "glaze.themeFrom") {
|
|
3582
|
+
if (data === null || typeof data !== "object") throw new Error(`${factory}: expected an object from theme.export(), got ${data === null ? "null" : typeof data}.`);
|
|
3583
|
+
assertExportKind(data, "theme", factory);
|
|
3584
|
+
assertExportVersion(data, factory);
|
|
3585
|
+
if (typeof data.hue !== "number" || typeof data.saturation !== "number") throw new Error(`${factory}: expected numeric "hue" and "saturation" fields.`);
|
|
3586
|
+
return createTheme(data.hue, data.saturation, data.colors, data.config);
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Rebuild a palette from a `palette.export()` snapshot.
|
|
3590
|
+
*/
|
|
3591
|
+
function createPaletteFromExport(data) {
|
|
3592
|
+
if (data === null || typeof data !== "object") throw new Error(`glaze.paletteFrom: expected an object from palette.export(), got ${data === null ? "null" : typeof data}.`);
|
|
3593
|
+
assertExportKind(data, "palette", "glaze.paletteFrom");
|
|
3594
|
+
assertExportVersion(data, "glaze.paletteFrom");
|
|
3595
|
+
if (data.themes === null || typeof data.themes !== "object") throw new Error(`glaze.paletteFrom: expected a "themes" object map of theme exports.`);
|
|
3596
|
+
const rebuilt = {};
|
|
3597
|
+
for (const [name, themeExport] of Object.entries(data.themes)) rebuilt[name] = createThemeFromExport(themeExport, `glaze.paletteFrom (theme "${name}")`);
|
|
3598
|
+
return createPalette(rebuilt, { primary: data.primary });
|
|
3599
|
+
}
|
|
3340
3600
|
function createPalette(themes, paletteOptions) {
|
|
3341
3601
|
validatePrimaryTheme(paletteOptions?.primary, themes);
|
|
3342
3602
|
const buildDtcgResult = (options) => {
|
|
@@ -3350,6 +3610,29 @@ function createPalette(themes, paletteOptions) {
|
|
|
3350
3610
|
}, () => ({ light: {} }));
|
|
3351
3611
|
};
|
|
3352
3612
|
return {
|
|
3613
|
+
list() {
|
|
3614
|
+
return Object.keys(themes);
|
|
3615
|
+
},
|
|
3616
|
+
get primary() {
|
|
3617
|
+
return paletteOptions?.primary;
|
|
3618
|
+
},
|
|
3619
|
+
theme(name) {
|
|
3620
|
+
return themes[name];
|
|
3621
|
+
},
|
|
3622
|
+
themes() {
|
|
3623
|
+
return { ...themes };
|
|
3624
|
+
},
|
|
3625
|
+
export(override) {
|
|
3626
|
+
const themesExport = {};
|
|
3627
|
+
for (const [name, theme] of Object.entries(themes)) themesExport[name] = theme.export(override);
|
|
3628
|
+
const out = {
|
|
3629
|
+
kind: "palette",
|
|
3630
|
+
version: GLAZE_EXPORT_VERSION,
|
|
3631
|
+
themes: themesExport
|
|
3632
|
+
};
|
|
3633
|
+
if (paletteOptions?.primary !== void 0) out.primary = paletteOptions.primary;
|
|
3634
|
+
return out;
|
|
3635
|
+
},
|
|
3353
3636
|
tokens(options) {
|
|
3354
3637
|
const format = options?.format ?? "oklch";
|
|
3355
3638
|
assertNativeFormat(format, "tokens");
|
|
@@ -3438,150 +3721,6 @@ function createPalette(themes, paletteOptions) {
|
|
|
3438
3721
|
};
|
|
3439
3722
|
}
|
|
3440
3723
|
|
|
3441
|
-
//#endregion
|
|
3442
|
-
//#region src/theme.ts
|
|
3443
|
-
function createTheme(hue, saturation, initialColors, configOverride) {
|
|
3444
|
-
let colorDefs = initialColors ? { ...initialColors } : {};
|
|
3445
|
-
let cache = null;
|
|
3446
|
-
function getEffectiveConfig() {
|
|
3447
|
-
const version = getConfigVersion();
|
|
3448
|
-
if (cache && cache.version === version) return cache.effectiveConfig;
|
|
3449
|
-
return mergeConfig(getConfig(), configOverride);
|
|
3450
|
-
}
|
|
3451
|
-
function resolveCached() {
|
|
3452
|
-
const version = getConfigVersion();
|
|
3453
|
-
if (cache && cache.version === version) return cache.map;
|
|
3454
|
-
const effectiveConfig = mergeConfig(getConfig(), configOverride);
|
|
3455
|
-
const map = resolveAllColors(hue, saturation, colorDefs, effectiveConfig);
|
|
3456
|
-
cache = {
|
|
3457
|
-
map,
|
|
3458
|
-
version,
|
|
3459
|
-
effectiveConfig
|
|
3460
|
-
};
|
|
3461
|
-
return map;
|
|
3462
|
-
}
|
|
3463
|
-
function invalidate() {
|
|
3464
|
-
cache = null;
|
|
3465
|
-
}
|
|
3466
|
-
function channelCtxFor(options, formatDefault, prefix) {
|
|
3467
|
-
const format = options?.format ?? formatDefault;
|
|
3468
|
-
if (!options?.splitHue || format !== "oklch") return void 0;
|
|
3469
|
-
assertAllPastel(resolveCached(), resolveModes(options?.modes));
|
|
3470
|
-
return {
|
|
3471
|
-
seedHue: hue,
|
|
3472
|
-
baseName: options.name ?? "theme",
|
|
3473
|
-
prefix,
|
|
3474
|
-
defs: colorDefs,
|
|
3475
|
-
mode: "theme"
|
|
3476
|
-
};
|
|
3477
|
-
}
|
|
3478
|
-
return {
|
|
3479
|
-
get hue() {
|
|
3480
|
-
return hue;
|
|
3481
|
-
},
|
|
3482
|
-
get saturation() {
|
|
3483
|
-
return saturation;
|
|
3484
|
-
},
|
|
3485
|
-
getConfig() {
|
|
3486
|
-
return getEffectiveConfig();
|
|
3487
|
-
},
|
|
3488
|
-
colors(defs) {
|
|
3489
|
-
colorDefs = {
|
|
3490
|
-
...colorDefs,
|
|
3491
|
-
...defs
|
|
3492
|
-
};
|
|
3493
|
-
invalidate();
|
|
3494
|
-
},
|
|
3495
|
-
color(name, def) {
|
|
3496
|
-
if (def === void 0) return colorDefs[name];
|
|
3497
|
-
colorDefs[name] = def;
|
|
3498
|
-
invalidate();
|
|
3499
|
-
},
|
|
3500
|
-
remove(names) {
|
|
3501
|
-
const list = Array.isArray(names) ? names : [names];
|
|
3502
|
-
for (const name of list) delete colorDefs[name];
|
|
3503
|
-
invalidate();
|
|
3504
|
-
},
|
|
3505
|
-
has(name) {
|
|
3506
|
-
return name in colorDefs;
|
|
3507
|
-
},
|
|
3508
|
-
list() {
|
|
3509
|
-
return Object.keys(colorDefs);
|
|
3510
|
-
},
|
|
3511
|
-
reset() {
|
|
3512
|
-
colorDefs = {};
|
|
3513
|
-
invalidate();
|
|
3514
|
-
},
|
|
3515
|
-
export() {
|
|
3516
|
-
const out = {
|
|
3517
|
-
hue,
|
|
3518
|
-
saturation,
|
|
3519
|
-
colors: { ...colorDefs }
|
|
3520
|
-
};
|
|
3521
|
-
if (configOverride !== void 0) out.config = configOverride;
|
|
3522
|
-
return out;
|
|
3523
|
-
},
|
|
3524
|
-
extend(options) {
|
|
3525
|
-
const newHue = options.hue ?? hue;
|
|
3526
|
-
const newSat = options.saturation ?? saturation;
|
|
3527
|
-
const inheritedColors = {};
|
|
3528
|
-
for (const [name, def] of Object.entries(colorDefs)) if (def.inherit !== false) inheritedColors[name] = def;
|
|
3529
|
-
return createTheme(newHue, newSat, options.colors ? {
|
|
3530
|
-
...inheritedColors,
|
|
3531
|
-
...options.colors
|
|
3532
|
-
} : { ...inheritedColors }, configOverride || options.config ? {
|
|
3533
|
-
...configOverride ?? {},
|
|
3534
|
-
...options.config ?? {}
|
|
3535
|
-
} : void 0);
|
|
3536
|
-
},
|
|
3537
|
-
resolve() {
|
|
3538
|
-
return new Map(resolveCached());
|
|
3539
|
-
},
|
|
3540
|
-
tokens(options) {
|
|
3541
|
-
const format = options?.format ?? "oklch";
|
|
3542
|
-
assertNativeFormat(format, "tokens");
|
|
3543
|
-
const modes = resolveModes(options?.modes);
|
|
3544
|
-
return buildFlatTokenMap(resolveCached(), "", modes, format, getEffectiveConfig().pastel);
|
|
3545
|
-
},
|
|
3546
|
-
tasty(options) {
|
|
3547
|
-
const cfg = getEffectiveConfig();
|
|
3548
|
-
const states = {
|
|
3549
|
-
dark: options?.states?.dark ?? cfg.states.dark,
|
|
3550
|
-
highContrast: options?.states?.highContrast ?? cfg.states.highContrast
|
|
3551
|
-
};
|
|
3552
|
-
const modes = resolveModes(options?.modes);
|
|
3553
|
-
const format = options?.format ?? "oklch";
|
|
3554
|
-
const channelCtx = channelCtxFor(options, "oklch", "");
|
|
3555
|
-
return buildTokenMap(resolveCached(), "", states, modes, format, cfg.pastel, channelCtx);
|
|
3556
|
-
},
|
|
3557
|
-
json(options) {
|
|
3558
|
-
const format = options?.format ?? "oklch";
|
|
3559
|
-
assertNativeFormat(format, "json");
|
|
3560
|
-
const modes = resolveModes(options?.modes);
|
|
3561
|
-
return buildJsonMap(resolveCached(), modes, format, getEffectiveConfig().pastel);
|
|
3562
|
-
},
|
|
3563
|
-
css(options) {
|
|
3564
|
-
const format = options?.format ?? "oklch";
|
|
3565
|
-
assertNativeFormat(format, "css");
|
|
3566
|
-
const channelCtx = channelCtxFor(options, "oklch", "");
|
|
3567
|
-
return buildCssMap(resolveCached(), "", options?.suffix ?? "-color", format, getEffectiveConfig().pastel, channelCtx);
|
|
3568
|
-
},
|
|
3569
|
-
dtcg(options) {
|
|
3570
|
-
const modes = resolveModes(options?.modes);
|
|
3571
|
-
return buildDtcgMap(resolveCached(), "", modes, options?.colorSpace ?? "srgb", getEffectiveConfig().pastel);
|
|
3572
|
-
},
|
|
3573
|
-
dtcgResolver(options) {
|
|
3574
|
-
return buildDtcgResolver(buildDtcgMap(resolveCached(), "", resolveModes(options?.modes), options?.colorSpace ?? "srgb", getEffectiveConfig().pastel), options);
|
|
3575
|
-
},
|
|
3576
|
-
tailwind(options) {
|
|
3577
|
-
const format = options?.format ?? "oklch";
|
|
3578
|
-
assertNativeFormat(format, "tailwind");
|
|
3579
|
-
const modes = resolveModes(options?.modes);
|
|
3580
|
-
return buildTailwindMap(resolveCached(), "", options?.namespace ?? "color-", modes, format, options?.darkSelector ?? ".dark", options?.highContrastSelector ?? ".high-contrast", getEffectiveConfig().pastel);
|
|
3581
|
-
}
|
|
3582
|
-
};
|
|
3583
|
-
}
|
|
3584
|
-
|
|
3585
3724
|
//#endregion
|
|
3586
3725
|
//#region src/glaze.ts
|
|
3587
3726
|
/**
|
|
@@ -3595,6 +3734,7 @@ function createTheme(hue, saturation, initialColors, configOverride) {
|
|
|
3595
3734
|
* - `shadow.ts` — standalone shadow factory (`glaze.shadow`)
|
|
3596
3735
|
* - `formatters.ts` — variant → string (`glaze.format`)
|
|
3597
3736
|
* - `config.ts` — global config singleton
|
|
3737
|
+
* - `serialize.ts` — authoring export type guards / version checks
|
|
3598
3738
|
*/
|
|
3599
3739
|
/**
|
|
3600
3740
|
* Create a single-hue glaze theme.
|
|
@@ -3626,10 +3766,15 @@ glaze.configure = function configure$1(config) {
|
|
|
3626
3766
|
glaze.palette = function palette(themes, options) {
|
|
3627
3767
|
return createPalette(themes, options);
|
|
3628
3768
|
};
|
|
3629
|
-
/**
|
|
3630
|
-
|
|
3631
|
-
|
|
3769
|
+
/**
|
|
3770
|
+
* Create a theme from a serialized `theme.export()` snapshot.
|
|
3771
|
+
* Prefer this over the legacy `glaze.from` alias.
|
|
3772
|
+
*/
|
|
3773
|
+
glaze.themeFrom = function themeFrom(data) {
|
|
3774
|
+
return createThemeFromExport(data);
|
|
3632
3775
|
};
|
|
3776
|
+
/** Compat alias for `glaze.themeFrom`. */
|
|
3777
|
+
glaze.from = glaze.themeFrom;
|
|
3633
3778
|
/**
|
|
3634
3779
|
* Create a standalone single-color token.
|
|
3635
3780
|
*
|
|
@@ -3645,8 +3790,8 @@ glaze.from = function from(data) {
|
|
|
3645
3790
|
* **arg2 — config override** (optional, all shapes):
|
|
3646
3791
|
* Overrides the resolve-relevant global config fields for this token.
|
|
3647
3792
|
* Fields that are omitted fall through to the live global config at
|
|
3648
|
-
*
|
|
3649
|
-
*
|
|
3793
|
+
* resolve time. Pass `false` for a tone window to disable clamping
|
|
3794
|
+
* entirely. `pastel` is instance-only (not set via `configure()`).
|
|
3650
3795
|
*
|
|
3651
3796
|
* ```ts
|
|
3652
3797
|
* // Bare string — no overrides
|
|
@@ -3665,8 +3810,8 @@ glaze.from = function from(data) {
|
|
|
3665
3810
|
*
|
|
3666
3811
|
* Defaults: every form defaults to `mode: 'auto'`. Value-shorthand forms
|
|
3667
3812
|
* (bare strings and value objects) preserve light tone exactly
|
|
3668
|
-
* (`lightTone: false`
|
|
3669
|
-
* tone windows
|
|
3813
|
+
* (`lightTone: false` locally). Structured form falls through to the live
|
|
3814
|
+
* global tone windows for omitted fields.
|
|
3670
3815
|
*
|
|
3671
3816
|
* Relative `tone: '+N'` and `contrast` anchor to the literal seed by
|
|
3672
3817
|
* default; when `base` is set they anchor to the base's resolved variant
|
|
@@ -3744,8 +3889,8 @@ glaze.fromRgb = function fromRgb(r, g, b) {
|
|
|
3744
3889
|
*
|
|
3745
3890
|
* The snapshot is a plain JSON-safe object containing the original
|
|
3746
3891
|
* input value, overrides (with any `base` token recursively serialized),
|
|
3747
|
-
* and the effective config
|
|
3748
|
-
*
|
|
3892
|
+
* and the effective config freeze from export time. The reconstructed
|
|
3893
|
+
* token pins that freeze as its local override.
|
|
3749
3894
|
*
|
|
3750
3895
|
* @example
|
|
3751
3896
|
* ```ts
|
|
@@ -3759,6 +3904,18 @@ glaze.fromRgb = function fromRgb(r, g, b) {
|
|
|
3759
3904
|
glaze.colorFrom = function colorFrom(data) {
|
|
3760
3905
|
return colorFromExport(data);
|
|
3761
3906
|
};
|
|
3907
|
+
/**
|
|
3908
|
+
* Rehydrate a palette from a `palette.export()` snapshot.
|
|
3909
|
+
*/
|
|
3910
|
+
glaze.paletteFrom = function paletteFrom(data) {
|
|
3911
|
+
return createPaletteFromExport(data);
|
|
3912
|
+
};
|
|
3913
|
+
/** Type guard for theme authoring snapshots. */
|
|
3914
|
+
glaze.isThemeExport = isThemeExport;
|
|
3915
|
+
/** Type guard for color-token authoring snapshots. */
|
|
3916
|
+
glaze.isColorTokenExport = isColorTokenExport;
|
|
3917
|
+
/** Type guard for palette authoring snapshots. */
|
|
3918
|
+
glaze.isPaletteExport = isPaletteExport;
|
|
3762
3919
|
/** Get the current global configuration (for testing/debugging). */
|
|
3763
3920
|
glaze.getConfig = function getConfig() {
|
|
3764
3921
|
return snapshotConfig();
|
|
@@ -3772,6 +3929,7 @@ glaze.resetConfig = function resetConfig$1() {
|
|
|
3772
3929
|
exports.APCA_HC_ENHANCEMENT = APCA_HC_ENHANCEMENT;
|
|
3773
3930
|
exports.APCA_MAX_LC = APCA_MAX_LC;
|
|
3774
3931
|
exports.APCA_PRESETS = APCA_PRESETS;
|
|
3932
|
+
exports.GLAZE_EXPORT_VERSION = GLAZE_EXPORT_VERSION;
|
|
3775
3933
|
exports.REF_EPS = REF_EPS;
|
|
3776
3934
|
exports.apcaContrast = apcaContrast;
|
|
3777
3935
|
exports.assertAllPastel = assertAllPastel;
|
|
@@ -3790,6 +3948,9 @@ exports.gamutClampedLuminance = gamutClampedLuminance;
|
|
|
3790
3948
|
exports.glaze = glaze;
|
|
3791
3949
|
exports.hslToSrgb = hslToSrgb;
|
|
3792
3950
|
exports.inferRoleFromName = inferRoleFromName;
|
|
3951
|
+
exports.isColorTokenExport = isColorTokenExport;
|
|
3952
|
+
exports.isPaletteExport = isPaletteExport;
|
|
3953
|
+
exports.isThemeExport = isThemeExport;
|
|
3793
3954
|
exports.normalizeRole = normalizeRole;
|
|
3794
3955
|
exports.okhslToLinearSrgb = okhslToLinearSrgb;
|
|
3795
3956
|
exports.okhslToOkhst = okhslToOkhst;
|