@tenphi/glaze 0.1.1 → 0.3.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 +165 -73
- package/dist/index.cjs +129 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -13
- package/dist/index.d.mts +45 -13
- package/dist/index.mjs +129 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Finds the closest OKHSL lightness that satisfies a WCAG 2 contrast target
|
|
6
6
|
* against a base color. Used by glaze when resolving dependent colors
|
|
7
|
-
* with `
|
|
7
|
+
* with `contrast`.
|
|
8
8
|
*/
|
|
9
9
|
type ContrastPreset = 'AA' | 'AAA' | 'AA-large' | 'AAA-large';
|
|
10
10
|
type MinContrast$1 = number | ContrastPreset;
|
|
@@ -17,8 +17,8 @@ interface FindLightnessForContrastOptions {
|
|
|
17
17
|
preferredLightness: number;
|
|
18
18
|
/** Base/reference color as linear sRGB (channels may be outside 0–1 before clamp). */
|
|
19
19
|
baseLinearRgb: [number, number, number];
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/** WCAG contrast ratio target floor. */
|
|
21
|
+
contrast: MinContrast$1;
|
|
22
22
|
/** Search bounds for lightness. Default: [0, 1]. */
|
|
23
23
|
lightnessRange?: [number, number];
|
|
24
24
|
/** Convergence threshold. Default: 1e-4. */
|
|
@@ -48,6 +48,8 @@ declare function findLightnessForContrast(options: FindLightnessForContrastOptio
|
|
|
48
48
|
type HCPair<T> = T | [T, T];
|
|
49
49
|
type MinContrast = number | ContrastPreset;
|
|
50
50
|
type AdaptationMode = 'auto' | 'fixed' | 'static';
|
|
51
|
+
/** A signed relative offset string, e.g. '+20' or '-15.5'. */
|
|
52
|
+
type RelativeValue = `+${number}` | `-${number}`;
|
|
51
53
|
/** Color format for output. */
|
|
52
54
|
type GlazeColorFormat = 'okhsl' | 'rgb' | 'hsl' | 'oklch';
|
|
53
55
|
/**
|
|
@@ -61,16 +63,24 @@ interface GlazeOutputModes {
|
|
|
61
63
|
highContrast?: boolean;
|
|
62
64
|
}
|
|
63
65
|
interface ColorDef {
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Lightness value (0–100).
|
|
68
|
+
* - Number: absolute lightness.
|
|
69
|
+
* - String ('+N' / '-N'): relative to base color's lightness (requires `base`).
|
|
70
|
+
*/
|
|
71
|
+
lightness?: HCPair<number | RelativeValue>;
|
|
66
72
|
/** Saturation factor applied to the seed saturation (0–1, default: 1). */
|
|
67
|
-
|
|
73
|
+
saturation?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Hue override for this color.
|
|
76
|
+
* - Number: absolute hue (0–360).
|
|
77
|
+
* - String ('+N' / '-N'): relative to the theme seed hue.
|
|
78
|
+
*/
|
|
79
|
+
hue?: number | RelativeValue;
|
|
68
80
|
/** Name of another color in the same theme (dependent color). */
|
|
69
81
|
base?: string;
|
|
70
|
-
/**
|
|
71
|
-
contrast?: HCPair<
|
|
72
|
-
/** Ensures the WCAG contrast ratio meets a target floor against the base. */
|
|
73
|
-
ensureContrast?: HCPair<MinContrast>;
|
|
82
|
+
/** WCAG contrast ratio floor against the base color. */
|
|
83
|
+
contrast?: HCPair<MinContrast>;
|
|
74
84
|
/** Adaptation mode. Default: 'auto'. */
|
|
75
85
|
mode?: AdaptationMode;
|
|
76
86
|
}
|
|
@@ -125,8 +135,8 @@ interface GlazeThemeExport {
|
|
|
125
135
|
interface GlazeColorInput {
|
|
126
136
|
hue: number;
|
|
127
137
|
saturation: number;
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
lightness: HCPair<number>;
|
|
139
|
+
saturationFactor?: number;
|
|
130
140
|
mode?: AdaptationMode;
|
|
131
141
|
}
|
|
132
142
|
/** Return type for `glaze.color()`. */
|
|
@@ -167,6 +177,8 @@ interface GlazeTheme {
|
|
|
167
177
|
tokens(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
|
|
168
178
|
/** Export as plain JSON. */
|
|
169
179
|
json(options?: GlazeJsonOptions): Record<string, Record<string, string>>;
|
|
180
|
+
/** Export as CSS custom property declarations. */
|
|
181
|
+
css(options?: GlazeCssOptions): GlazeCssResult;
|
|
170
182
|
}
|
|
171
183
|
interface GlazeExtendOptions {
|
|
172
184
|
hue?: number;
|
|
@@ -192,6 +204,19 @@ interface GlazeJsonOptions {
|
|
|
192
204
|
/** Output color format. Default: 'okhsl'. */
|
|
193
205
|
format?: GlazeColorFormat;
|
|
194
206
|
}
|
|
207
|
+
interface GlazeCssOptions {
|
|
208
|
+
/** Output color format. Default: 'rgb'. */
|
|
209
|
+
format?: GlazeColorFormat;
|
|
210
|
+
/** Suffix appended to each CSS custom property name. Default: '-color'. */
|
|
211
|
+
suffix?: string;
|
|
212
|
+
}
|
|
213
|
+
/** CSS custom property declarations grouped by scheme variant. */
|
|
214
|
+
interface GlazeCssResult {
|
|
215
|
+
light: string;
|
|
216
|
+
dark: string;
|
|
217
|
+
lightContrast: string;
|
|
218
|
+
darkContrast: string;
|
|
219
|
+
}
|
|
195
220
|
interface GlazePalette {
|
|
196
221
|
/** Export all themes as a combined token map. */
|
|
197
222
|
tokens(options?: GlazeTokenOptions): Record<string, Record<string, string>>;
|
|
@@ -199,6 +224,10 @@ interface GlazePalette {
|
|
|
199
224
|
json(options?: GlazeJsonOptions & {
|
|
200
225
|
prefix?: boolean | Record<string, string>;
|
|
201
226
|
}): Record<string, Record<string, Record<string, string>>>;
|
|
227
|
+
/** Export all themes as CSS custom property declarations. */
|
|
228
|
+
css(options?: GlazeCssOptions & {
|
|
229
|
+
prefix?: boolean | Record<string, string>;
|
|
230
|
+
}): GlazeCssResult;
|
|
202
231
|
}
|
|
203
232
|
//#endregion
|
|
204
233
|
//#region src/glaze.d.ts
|
|
@@ -224,6 +253,9 @@ declare namespace glaze {
|
|
|
224
253
|
json(options?: GlazeJsonOptions & {
|
|
225
254
|
prefix?: boolean | Record<string, string>;
|
|
226
255
|
}): Record<string, Record<string, Record<string, string>>>;
|
|
256
|
+
css(options?: GlazeCssOptions & {
|
|
257
|
+
prefix?: boolean | Record<string, string>;
|
|
258
|
+
}): GlazeCssResult;
|
|
227
259
|
};
|
|
228
260
|
var from: (data: GlazeThemeExport) => GlazeTheme;
|
|
229
261
|
var color: (input: GlazeColorInput) => GlazeColorToken;
|
|
@@ -294,5 +326,5 @@ declare function formatHsl(h: number, s: number, l: number): string;
|
|
|
294
326
|
*/
|
|
295
327
|
declare function formatOklch(h: number, s: number, l: number): string;
|
|
296
328
|
//#endregion
|
|
297
|
-
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type MinContrast, type ResolvedColor, type ResolvedColorVariant, contrastRatioFromLuminance, findLightnessForContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
329
|
+
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorToken, type GlazeConfig, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type MinContrast, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, contrastRatioFromLuminance, findLightnessForContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, glaze, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, parseHex, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
|
|
298
330
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -493,7 +493,7 @@ function formatOklch(h, s, l) {
|
|
|
493
493
|
*
|
|
494
494
|
* Finds the closest OKHSL lightness that satisfies a WCAG 2 contrast target
|
|
495
495
|
* against a base color. Used by glaze when resolving dependent colors
|
|
496
|
-
* with `
|
|
496
|
+
* with `contrast`.
|
|
497
497
|
*/
|
|
498
498
|
const CONTRAST_PRESETS = {
|
|
499
499
|
AA: 4.5,
|
|
@@ -631,8 +631,8 @@ function coarseScan(h, s, lo, hi, yBase, target, epsilon, maxIter) {
|
|
|
631
631
|
* against a base color, staying as close to `preferredLightness` as possible.
|
|
632
632
|
*/
|
|
633
633
|
function findLightnessForContrast(options) {
|
|
634
|
-
const { hue, saturation, preferredLightness, baseLinearRgb,
|
|
635
|
-
const target = resolveMinContrast(
|
|
634
|
+
const { hue, saturation, preferredLightness, baseLinearRgb, contrast: contrastInput, lightnessRange = [0, 1], epsilon = 1e-4, maxIterations = 14 } = options;
|
|
635
|
+
const target = resolveMinContrast(contrastInput);
|
|
636
636
|
const yBase = relativeLuminanceFromLinearRgb(baseLinearRgb);
|
|
637
637
|
const crPref = contrastRatioFromLuminance(cachedLuminance(hue, saturation, preferredLightness), yBase);
|
|
638
638
|
if (crPref >= target) return {
|
|
@@ -713,9 +713,10 @@ function validateColorDefs(defs) {
|
|
|
713
713
|
const names = new Set(Object.keys(defs));
|
|
714
714
|
for (const [name, def] of Object.entries(defs)) {
|
|
715
715
|
if (def.contrast !== void 0 && !def.base) throw new Error(`glaze: color "${name}" has "contrast" without "base".`);
|
|
716
|
-
if (def.
|
|
716
|
+
if (def.lightness !== void 0 && !isAbsoluteLightness(def.lightness) && !def.base) throw new Error(`glaze: color "${name}" has relative "lightness" without "base".`);
|
|
717
|
+
if (isAbsoluteLightness(def.lightness) && def.base !== void 0) console.warn(`glaze: color "${name}" has absolute "lightness" and "base". Absolute lightness takes precedence.`);
|
|
717
718
|
if (def.base && !names.has(def.base)) throw new Error(`glaze: color "${name}" references non-existent base "${def.base}".`);
|
|
718
|
-
if (def.
|
|
719
|
+
if (!isAbsoluteLightness(def.lightness) && def.base === void 0) throw new Error(`glaze: color "${name}" must have either absolute "lightness" (root) or "base" (dependent).`);
|
|
719
720
|
}
|
|
720
721
|
const visited = /* @__PURE__ */ new Set();
|
|
721
722
|
const inStack = /* @__PURE__ */ new Set();
|
|
@@ -724,7 +725,7 @@ function validateColorDefs(defs) {
|
|
|
724
725
|
if (visited.has(name)) return;
|
|
725
726
|
inStack.add(name);
|
|
726
727
|
const def = defs[name];
|
|
727
|
-
if (def.base && def.
|
|
728
|
+
if (def.base && !isAbsoluteLightness(def.lightness)) dfs(def.base);
|
|
728
729
|
inStack.delete(name);
|
|
729
730
|
visited.add(name);
|
|
730
731
|
}
|
|
@@ -737,7 +738,7 @@ function topoSort(defs) {
|
|
|
737
738
|
if (visited.has(name)) return;
|
|
738
739
|
visited.add(name);
|
|
739
740
|
const def = defs[name];
|
|
740
|
-
if (def.base && def.
|
|
741
|
+
if (def.base && !isAbsoluteLightness(def.lightness)) visit(def.base);
|
|
741
742
|
result.push(name);
|
|
742
743
|
}
|
|
743
744
|
for (const name of Object.keys(defs)) visit(name);
|
|
@@ -753,44 +754,75 @@ function mapSaturationDark(s, mode) {
|
|
|
753
754
|
if (mode === "static") return s;
|
|
754
755
|
return s * (1 - globalConfig.darkDesaturation);
|
|
755
756
|
}
|
|
757
|
+
function clamp(v, min, max) {
|
|
758
|
+
return Math.max(min, Math.min(max, v));
|
|
759
|
+
}
|
|
756
760
|
/**
|
|
757
|
-
*
|
|
761
|
+
* Parse a value that can be absolute (number) or relative (signed string).
|
|
762
|
+
* Returns the numeric value and whether it's relative.
|
|
758
763
|
*/
|
|
759
|
-
function
|
|
760
|
-
if (
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
+
function parseRelativeOrAbsolute(value) {
|
|
765
|
+
if (typeof value === "number") return {
|
|
766
|
+
value,
|
|
767
|
+
relative: false
|
|
768
|
+
};
|
|
769
|
+
return {
|
|
770
|
+
value: parseFloat(value),
|
|
771
|
+
relative: true
|
|
772
|
+
};
|
|
764
773
|
}
|
|
765
|
-
|
|
766
|
-
|
|
774
|
+
/**
|
|
775
|
+
* Compute the effective hue for a color, given the theme seed hue
|
|
776
|
+
* and an optional per-color hue override.
|
|
777
|
+
*/
|
|
778
|
+
function resolveEffectiveHue(seedHue, defHue) {
|
|
779
|
+
if (defHue === void 0) return seedHue;
|
|
780
|
+
const parsed = parseRelativeOrAbsolute(defHue);
|
|
781
|
+
if (parsed.relative) return ((seedHue + parsed.value) % 360 + 360) % 360;
|
|
782
|
+
return (parsed.value % 360 + 360) % 360;
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Check whether a lightness value represents an absolute root definition
|
|
786
|
+
* (i.e. a number, not a relative string).
|
|
787
|
+
*/
|
|
788
|
+
function isAbsoluteLightness(lightness) {
|
|
789
|
+
if (lightness === void 0) return false;
|
|
790
|
+
return typeof (Array.isArray(lightness) ? lightness[0] : lightness) === "number";
|
|
767
791
|
}
|
|
768
792
|
function resolveRootColor(_name, def, _ctx, isHighContrast) {
|
|
769
|
-
const rawL = def.
|
|
793
|
+
const rawL = def.lightness;
|
|
770
794
|
return {
|
|
771
|
-
lightL: clamp(isHighContrast ? pairHC(rawL) : pairNormal(rawL), 0, 100),
|
|
772
|
-
|
|
795
|
+
lightL: clamp(parseRelativeOrAbsolute(isHighContrast ? pairHC(rawL) : pairNormal(rawL)).value, 0, 100),
|
|
796
|
+
satFactor: clamp(def.saturation ?? 1, 0, 1)
|
|
773
797
|
};
|
|
774
798
|
}
|
|
775
|
-
function resolveDependentColor(name, def, ctx, isHighContrast, isDark) {
|
|
799
|
+
function resolveDependentColor(name, def, ctx, isHighContrast, isDark, effectiveHue) {
|
|
776
800
|
const baseName = def.base;
|
|
777
801
|
const baseResolved = ctx.resolved.get(baseName);
|
|
778
802
|
if (!baseResolved) throw new Error(`glaze: base "${baseName}" not yet resolved for "${name}".`);
|
|
779
803
|
const mode = def.mode ?? "auto";
|
|
780
|
-
const
|
|
804
|
+
const satFactor = clamp(def.saturation ?? 1, 0, 1);
|
|
781
805
|
let baseL;
|
|
782
806
|
if (isDark && isHighContrast) baseL = baseResolved.darkContrast.l * 100;
|
|
783
807
|
else if (isDark) baseL = baseResolved.dark.l * 100;
|
|
784
808
|
else if (isHighContrast) baseL = baseResolved.lightContrast.l * 100;
|
|
785
809
|
else baseL = baseResolved.light.l * 100;
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
if (
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
810
|
+
let preferredL;
|
|
811
|
+
const rawLightness = def.lightness;
|
|
812
|
+
if (rawLightness === void 0) preferredL = baseL;
|
|
813
|
+
else {
|
|
814
|
+
const parsed = parseRelativeOrAbsolute(isHighContrast ? pairHC(rawLightness) : pairNormal(rawLightness));
|
|
815
|
+
if (parsed.relative) {
|
|
816
|
+
let delta = parsed.value;
|
|
817
|
+
if (isDark && mode === "auto") delta = -delta;
|
|
818
|
+
preferredL = clamp(baseL + delta, 0, 100);
|
|
819
|
+
} else if (isDark) preferredL = mapLightnessDark(parsed.value, mode);
|
|
820
|
+
else preferredL = clamp(parsed.value, 0, 100);
|
|
821
|
+
}
|
|
822
|
+
const rawContrast = def.contrast;
|
|
823
|
+
if (rawContrast !== void 0) {
|
|
824
|
+
const minCr = isHighContrast ? pairHC(rawContrast) : pairNormal(rawContrast);
|
|
825
|
+
const effectiveSat = isDark ? mapSaturationDark(satFactor * ctx.saturation / 100, mode) : satFactor * ctx.saturation / 100;
|
|
794
826
|
let baseH;
|
|
795
827
|
let baseS;
|
|
796
828
|
let baseLNorm;
|
|
@@ -814,48 +846,49 @@ function resolveDependentColor(name, def, ctx, isHighContrast, isDark) {
|
|
|
814
846
|
const baseLinearRgb = okhslToLinearSrgb(baseH, baseS, baseLNorm);
|
|
815
847
|
return {
|
|
816
848
|
l: findLightnessForContrast({
|
|
817
|
-
hue:
|
|
849
|
+
hue: effectiveHue,
|
|
818
850
|
saturation: effectiveSat,
|
|
819
851
|
preferredLightness: preferredL / 100,
|
|
820
852
|
baseLinearRgb,
|
|
821
|
-
|
|
853
|
+
contrast: minCr
|
|
822
854
|
}).lightness * 100,
|
|
823
|
-
|
|
855
|
+
satFactor
|
|
824
856
|
};
|
|
825
857
|
}
|
|
826
858
|
return {
|
|
827
859
|
l: clamp(preferredL, 0, 100),
|
|
828
|
-
|
|
860
|
+
satFactor
|
|
829
861
|
};
|
|
830
862
|
}
|
|
831
863
|
function resolveColorForScheme(name, def, ctx, isDark, isHighContrast) {
|
|
832
864
|
const mode = def.mode ?? "auto";
|
|
833
|
-
const isRoot = def.
|
|
865
|
+
const isRoot = isAbsoluteLightness(def.lightness) && !def.base;
|
|
866
|
+
const effectiveHue = resolveEffectiveHue(ctx.hue, def.hue);
|
|
834
867
|
let lightL;
|
|
835
|
-
let
|
|
868
|
+
let satFactor;
|
|
836
869
|
if (isRoot) {
|
|
837
870
|
const root = resolveRootColor(name, def, ctx, isHighContrast);
|
|
838
871
|
lightL = root.lightL;
|
|
839
|
-
|
|
872
|
+
satFactor = root.satFactor;
|
|
840
873
|
} else {
|
|
841
|
-
const dep = resolveDependentColor(name, def, ctx, isHighContrast, isDark);
|
|
874
|
+
const dep = resolveDependentColor(name, def, ctx, isHighContrast, isDark, effectiveHue);
|
|
842
875
|
lightL = dep.l;
|
|
843
|
-
|
|
876
|
+
satFactor = dep.satFactor;
|
|
844
877
|
}
|
|
845
878
|
let finalL;
|
|
846
879
|
let finalSat;
|
|
847
880
|
if (isDark && isRoot) {
|
|
848
881
|
finalL = mapLightnessDark(lightL, mode);
|
|
849
|
-
finalSat = mapSaturationDark(
|
|
882
|
+
finalSat = mapSaturationDark(satFactor * ctx.saturation / 100, mode);
|
|
850
883
|
} else if (isDark && !isRoot) {
|
|
851
884
|
finalL = lightL;
|
|
852
|
-
finalSat = mapSaturationDark(
|
|
885
|
+
finalSat = mapSaturationDark(satFactor * ctx.saturation / 100, mode);
|
|
853
886
|
} else {
|
|
854
887
|
finalL = lightL;
|
|
855
|
-
finalSat =
|
|
888
|
+
finalSat = satFactor * ctx.saturation / 100;
|
|
856
889
|
}
|
|
857
890
|
return {
|
|
858
|
-
h:
|
|
891
|
+
h: effectiveHue,
|
|
859
892
|
s: clamp(finalSat, 0, 1),
|
|
860
893
|
l: clamp(finalL / 100, 0, 1)
|
|
861
894
|
};
|
|
@@ -974,6 +1007,27 @@ function buildJsonMap(resolved, modes, format = "okhsl") {
|
|
|
974
1007
|
}
|
|
975
1008
|
return result;
|
|
976
1009
|
}
|
|
1010
|
+
function buildCssMap(resolved, prefix, suffix, format) {
|
|
1011
|
+
const lines = {
|
|
1012
|
+
light: [],
|
|
1013
|
+
dark: [],
|
|
1014
|
+
lightContrast: [],
|
|
1015
|
+
darkContrast: []
|
|
1016
|
+
};
|
|
1017
|
+
for (const [name, color] of resolved) {
|
|
1018
|
+
const prop = `--${prefix}${name}${suffix}`;
|
|
1019
|
+
lines.light.push(`${prop}: ${formatVariant(color.light, format)};`);
|
|
1020
|
+
lines.dark.push(`${prop}: ${formatVariant(color.dark, format)};`);
|
|
1021
|
+
lines.lightContrast.push(`${prop}: ${formatVariant(color.lightContrast, format)};`);
|
|
1022
|
+
lines.darkContrast.push(`${prop}: ${formatVariant(color.darkContrast, format)};`);
|
|
1023
|
+
}
|
|
1024
|
+
return {
|
|
1025
|
+
light: lines.light.join("\n"),
|
|
1026
|
+
dark: lines.dark.join("\n"),
|
|
1027
|
+
lightContrast: lines.lightContrast.join("\n"),
|
|
1028
|
+
darkContrast: lines.darkContrast.join("\n")
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
977
1031
|
function createTheme(hue, saturation, initialColors) {
|
|
978
1032
|
let colorDefs = initialColors ? { ...initialColors } : {};
|
|
979
1033
|
return {
|
|
@@ -1030,6 +1084,9 @@ function createTheme(hue, saturation, initialColors) {
|
|
|
1030
1084
|
},
|
|
1031
1085
|
json(options) {
|
|
1032
1086
|
return buildJsonMap(resolveAllColors(hue, saturation, colorDefs), resolveModes(options?.modes), options?.format);
|
|
1087
|
+
},
|
|
1088
|
+
css(options) {
|
|
1089
|
+
return buildCssMap(resolveAllColors(hue, saturation, colorDefs), "", options?.suffix ?? "-color", options?.format ?? "rgb");
|
|
1033
1090
|
}
|
|
1034
1091
|
};
|
|
1035
1092
|
}
|
|
@@ -1057,13 +1114,42 @@ function createPalette(themes) {
|
|
|
1057
1114
|
const result = {};
|
|
1058
1115
|
for (const [themeName, theme] of Object.entries(themes)) result[themeName] = buildJsonMap(theme.resolve(), modes, options?.format);
|
|
1059
1116
|
return result;
|
|
1117
|
+
},
|
|
1118
|
+
css(options) {
|
|
1119
|
+
const suffix = options?.suffix ?? "-color";
|
|
1120
|
+
const format = options?.format ?? "rgb";
|
|
1121
|
+
const allLines = {
|
|
1122
|
+
light: [],
|
|
1123
|
+
dark: [],
|
|
1124
|
+
lightContrast: [],
|
|
1125
|
+
darkContrast: []
|
|
1126
|
+
};
|
|
1127
|
+
for (const [themeName, theme] of Object.entries(themes)) {
|
|
1128
|
+
const resolved = theme.resolve();
|
|
1129
|
+
let prefix = "";
|
|
1130
|
+
if (options?.prefix === true) prefix = `${themeName}-`;
|
|
1131
|
+
else if (typeof options?.prefix === "object" && options.prefix !== null) prefix = options.prefix[themeName] ?? `${themeName}-`;
|
|
1132
|
+
const css = buildCssMap(resolved, prefix, suffix, format);
|
|
1133
|
+
for (const key of [
|
|
1134
|
+
"light",
|
|
1135
|
+
"dark",
|
|
1136
|
+
"lightContrast",
|
|
1137
|
+
"darkContrast"
|
|
1138
|
+
]) if (css[key]) allLines[key].push(css[key]);
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
light: allLines.light.join("\n"),
|
|
1142
|
+
dark: allLines.dark.join("\n"),
|
|
1143
|
+
lightContrast: allLines.lightContrast.join("\n"),
|
|
1144
|
+
darkContrast: allLines.darkContrast.join("\n")
|
|
1145
|
+
};
|
|
1060
1146
|
}
|
|
1061
1147
|
};
|
|
1062
1148
|
}
|
|
1063
1149
|
function createColorToken(input) {
|
|
1064
1150
|
const defs = { __color__: {
|
|
1065
|
-
|
|
1066
|
-
|
|
1151
|
+
lightness: input.lightness,
|
|
1152
|
+
saturation: input.saturationFactor,
|
|
1067
1153
|
mode: input.mode
|
|
1068
1154
|
} };
|
|
1069
1155
|
return {
|