@clhaas/palette-kit 0.1.8 → 0.4.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +80 -177
  3. package/dist/contrast/contrast.d.ts +16 -0
  4. package/dist/contrast/contrast.js +102 -0
  5. package/dist/core/intent-registry.d.ts +11 -0
  6. package/dist/core/intent-registry.js +70 -0
  7. package/dist/core/oklch.d.ts +16 -0
  8. package/dist/core/oklch.js +56 -0
  9. package/dist/create-palette-kit.d.ts +9 -0
  10. package/dist/create-palette-kit.js +67 -0
  11. package/dist/engine/context/context.d.ts +13 -0
  12. package/dist/engine/context/context.js +37 -0
  13. package/dist/engine/level/curves.d.ts +17 -0
  14. package/dist/engine/level/curves.js +49 -0
  15. package/dist/engine/level/level.d.ts +4 -0
  16. package/dist/engine/level/level.js +13 -0
  17. package/dist/engine/relation/relation.d.ts +105 -0
  18. package/dist/engine/relation/relation.js +137 -0
  19. package/dist/engine/resolve/resolve.d.ts +36 -0
  20. package/dist/engine/resolve/resolve.js +116 -0
  21. package/dist/engine/state/state.d.ts +46 -0
  22. package/dist/engine/state/state.js +68 -0
  23. package/dist/engine/usage/fill.d.ts +9 -0
  24. package/dist/engine/usage/fill.js +9 -0
  25. package/dist/engine/usage/lines.d.ts +9 -0
  26. package/dist/engine/usage/lines.js +9 -0
  27. package/dist/engine/usage/overlays.d.ts +9 -0
  28. package/dist/engine/usage/overlays.js +9 -0
  29. package/dist/engine/usage/strategy.d.ts +56 -0
  30. package/dist/engine/usage/strategy.js +30 -0
  31. package/dist/engine/usage/visualVocabulary.d.ts +9 -0
  32. package/dist/engine/usage/visualVocabulary.js +9 -0
  33. package/dist/export/serialize.d.ts +14 -0
  34. package/dist/export/serialize.js +89 -0
  35. package/dist/export/types.d.ts +37 -0
  36. package/dist/export/types.js +31 -0
  37. package/dist/index.d.ts +3 -22
  38. package/dist/index.js +2 -18
  39. package/dist/operators/convert.d.ts +32 -0
  40. package/dist/operators/convert.js +80 -0
  41. package/dist/presets/presets.d.ts +95 -0
  42. package/dist/presets/presets.js +308 -0
  43. package/dist/types/index.d.ts +111 -0
  44. package/dist/utils/errors/errors.d.ts +17 -0
  45. package/dist/utils/errors/errors.js +22 -0
  46. package/docs/API.md +167 -0
  47. package/docs/Alpha.md +14 -0
  48. package/docs/Architecture.md +56 -0
  49. package/docs/CLI.md +22 -0
  50. package/docs/Concepts.md +73 -0
  51. package/docs/Config.md +144 -0
  52. package/docs/Diagnostics.md +22 -0
  53. package/docs/Exporters.md +33 -0
  54. package/docs/FAQ.md +59 -0
  55. package/docs/Migration.md +61 -0
  56. package/docs/Overlays.md +33 -0
  57. package/docs/README.md +60 -0
  58. package/docs/Text.md +41 -0
  59. package/docs/Tokens.md +42 -0
  60. package/docs/Usage-JSON.md +39 -0
  61. package/docs/Usage-ReactNative.md +63 -0
  62. package/docs/Usage-Web.md +66 -0
  63. package/docs/Validation.md +97 -0
  64. package/docs/Why.md +37 -0
  65. package/docs/_api-surface.md +53 -0
  66. package/docs/snippets/serialize-oklch.md +9 -0
  67. package/docs/spec.md +98 -0
  68. package/package.json +74 -52
  69. package/dist/alpha/generateAlphaScale.d.ts +0 -5
  70. package/dist/alpha/generateAlphaScale.js +0 -34
  71. package/dist/cli.d.ts +0 -2
  72. package/dist/cli.js +0 -150
  73. package/dist/contrast/apca.d.ts +0 -2
  74. package/dist/contrast/apca.js +0 -5
  75. package/dist/contrast/onSolid.d.ts +0 -6
  76. package/dist/contrast/onSolid.js +0 -28
  77. package/dist/contrast/solveText.d.ts +0 -2
  78. package/dist/contrast/solveText.js +0 -31
  79. package/dist/createTheme.d.ts +0 -38
  80. package/dist/createTheme.js +0 -148
  81. package/dist/data/radixSeeds.d.ts +0 -3
  82. package/dist/data/radixSeeds.js +0 -34
  83. package/dist/diagnostics/analyzeScale.d.ts +0 -2
  84. package/dist/diagnostics/analyzeScale.js +0 -7
  85. package/dist/diagnostics/analyzeTheme.d.ts +0 -2
  86. package/dist/diagnostics/analyzeTheme.js +0 -35
  87. package/dist/diagnostics/warnings.d.ts +0 -2
  88. package/dist/diagnostics/warnings.js +0 -20
  89. package/dist/engine/curves.d.ts +0 -9
  90. package/dist/engine/curves.js +0 -48
  91. package/dist/engine/oklch.d.ts +0 -8
  92. package/dist/engine/oklch.js +0 -40
  93. package/dist/engine/templates.d.ts +0 -14
  94. package/dist/engine/templates.js +0 -45
  95. package/dist/exporters/selectColorMode.d.ts +0 -2
  96. package/dist/exporters/selectColorMode.js +0 -19
  97. package/dist/exporters/toCssVars.d.ts +0 -13
  98. package/dist/exporters/toCssVars.js +0 -108
  99. package/dist/exporters/toJson.d.ts +0 -3
  100. package/dist/exporters/toJson.js +0 -25
  101. package/dist/exporters/toReactNative.d.ts +0 -54
  102. package/dist/exporters/toReactNative.js +0 -33
  103. package/dist/exporters/toTailwind.d.ts +0 -17
  104. package/dist/exporters/toTailwind.js +0 -111
  105. package/dist/exporters/toTs.d.ts +0 -3
  106. package/dist/exporters/toTs.js +0 -43
  107. package/dist/generateScale.d.ts +0 -48
  108. package/dist/generateScale.js +0 -274
  109. package/dist/overlays/generateOverlayScale.d.ts +0 -2
  110. package/dist/overlays/generateOverlayScale.js +0 -34
  111. package/dist/text/generateTextScale.d.ts +0 -8
  112. package/dist/text/generateTextScale.js +0 -18
  113. package/dist/text/resolveOnBgText.d.ts +0 -9
  114. package/dist/text/resolveOnBgText.js +0 -28
  115. package/dist/tokens/presetRadixLikeUi.d.ts +0 -5
  116. package/dist/tokens/presetRadixLikeUi.js +0 -55
  117. package/dist/types.d.ts +0 -69
  118. /package/dist/{types.js → types/index.js} +0 -0
@@ -1,35 +0,0 @@
1
- import { apcaContrast } from "../contrast/apca.js";
2
- import { analyzeWarnings } from "./warnings.js";
3
- export function analyzeTheme(theme) {
4
- const contrast = {};
5
- const lightBg = theme.tokens.light["bg.app"];
6
- const darkBg = theme.tokens.dark["bg.app"];
7
- if (lightBg) {
8
- if (theme.tokens.light["text.primary"]) {
9
- contrast["light.text.primary"] = apcaContrast(theme.tokens.light["text.primary"], lightBg);
10
- }
11
- if (theme.tokens.light["text.secondary"]) {
12
- contrast["light.text.secondary"] = apcaContrast(theme.tokens.light["text.secondary"], lightBg);
13
- }
14
- }
15
- if (darkBg) {
16
- if (theme.tokens.dark["text.primary"]) {
17
- contrast["dark.text.primary"] = apcaContrast(theme.tokens.dark["text.primary"], darkBg);
18
- }
19
- if (theme.tokens.dark["text.secondary"]) {
20
- contrast["dark.text.secondary"] = apcaContrast(theme.tokens.dark["text.secondary"], darkBg);
21
- }
22
- }
23
- if (theme.tokens.light["onSolid.primary"] && theme.tokens.light["accent.solid"]) {
24
- contrast["light.onSolid.primary"] = apcaContrast(theme.tokens.light["onSolid.primary"], theme.tokens.light["accent.solid"]);
25
- }
26
- if (theme.tokens.dark["onSolid.primary"] && theme.tokens.dark["accent.solid"]) {
27
- contrast["dark.onSolid.primary"] = apcaContrast(theme.tokens.dark["onSolid.primary"], theme.tokens.dark["accent.solid"]);
28
- }
29
- let outOfGamutCount = 0;
30
- for (const scale of Object.values(theme.scales)) {
31
- outOfGamutCount += scale.meta?.outOfGamutCount ?? 0;
32
- }
33
- const warnings = analyzeWarnings(theme);
34
- return { contrast, outOfGamutCount, warnings };
35
- }
@@ -1,2 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- export declare function analyzeWarnings(theme: Theme): string[];
@@ -1,20 +0,0 @@
1
- import Color from "colorjs.io";
2
- export function analyzeWarnings(theme) {
3
- const warnings = [];
4
- const accent = theme.scales.accent?.light?.[9];
5
- if (accent) {
6
- const { coords } = new Color(accent).to("oklch");
7
- const l = coords[0] ?? 0;
8
- const c = coords[1] ?? 0;
9
- if (c < 0.03) {
10
- warnings.push("Accent seed has very low chroma; the palette may look gray.");
11
- }
12
- if (l < 0.2) {
13
- warnings.push("Accent seed is very dark; light mode solids may lack contrast.");
14
- }
15
- if (l > 0.9) {
16
- warnings.push("Accent seed is very light; dark mode solids may lack contrast.");
17
- }
18
- }
19
- return warnings;
20
- }
@@ -1,9 +0,0 @@
1
- import type { Step } from "../types.js";
2
- export type CurveConfig = {
3
- lightness?: Partial<Record<Step, number>>;
4
- chroma?: Partial<Record<Step, number>>;
5
- };
6
- export declare function resolveCurves(curves?: CurveConfig): {
7
- lightness: Record<Step, number>;
8
- chroma: Record<Step, number>;
9
- };
@@ -1,48 +0,0 @@
1
- const steps = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
2
- const defaultLightness = {
3
- 1: 0.3,
4
- 2: 0.3,
5
- 3: 0.6,
6
- 4: 0.6,
7
- 5: 0.6,
8
- 6: 0.85,
9
- 7: 0.85,
10
- 8: 0.85,
11
- 9: 1,
12
- 10: 1,
13
- 11: 1,
14
- 12: 1,
15
- };
16
- const defaultChroma = {
17
- 1: 0.2,
18
- 2: 0.2,
19
- 3: 0.6,
20
- 4: 0.6,
21
- 5: 0.6,
22
- 6: 0.8,
23
- 7: 0.8,
24
- 8: 0.8,
25
- 9: 1,
26
- 10: 1,
27
- 11: 0.7,
28
- 12: 0.7,
29
- };
30
- export function resolveCurves(curves) {
31
- const lightness = { ...defaultLightness };
32
- const chroma = { ...defaultChroma };
33
- if (curves?.lightness) {
34
- for (const step of steps) {
35
- if (curves.lightness[step] !== undefined) {
36
- lightness[step] = curves.lightness[step];
37
- }
38
- }
39
- }
40
- if (curves?.chroma) {
41
- for (const step of steps) {
42
- if (curves.chroma[step] !== undefined) {
43
- chroma[step] = curves.chroma[step];
44
- }
45
- }
46
- }
47
- return { lightness, chroma };
48
- }
@@ -1,8 +0,0 @@
1
- import type { ColorHex, ColorP3, OklchColor } from "../types.js";
2
- export declare function hexToOklch(hex: ColorHex): OklchColor;
3
- export declare function oklchToHex(oklch: OklchColor): ColorHex;
4
- export declare function inSrgbGamut(oklch: OklchColor): boolean;
5
- export declare function compressToSrgb(oklch: OklchColor): OklchColor;
6
- export declare function inP3Gamut(oklch: OklchColor): boolean;
7
- export declare function compressToP3(oklch: OklchColor): OklchColor;
8
- export declare function oklchToP3(oklch: OklchColor): ColorP3;
@@ -1,40 +0,0 @@
1
- import Color from "colorjs.io";
2
- export function hexToOklch(hex) {
3
- const color = new Color(hex).to("oklch");
4
- const [l, c, h] = color.coords;
5
- return { l: l ?? 0, c: c ?? 0, h: h ?? 0 };
6
- }
7
- export function oklchToHex(oklch) {
8
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
9
- return color.to("srgb").toString({ format: "hex" });
10
- }
11
- export function inSrgbGamut(oklch) {
12
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
13
- return color.inGamut("srgb");
14
- }
15
- export function compressToSrgb(oklch) {
16
- let current = { ...oklch };
17
- let iterations = 0;
18
- while (!inSrgbGamut(current) && current.c > 0 && iterations < 40) {
19
- current = { ...current, c: current.c * 0.95 };
20
- iterations += 1;
21
- }
22
- return current;
23
- }
24
- export function inP3Gamut(oklch) {
25
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
26
- return color.inGamut("p3");
27
- }
28
- export function compressToP3(oklch) {
29
- let current = { ...oklch };
30
- let iterations = 0;
31
- while (!inP3Gamut(current) && current.c > 0 && iterations < 40) {
32
- current = { ...current, c: current.c * 0.95 };
33
- iterations += 1;
34
- }
35
- return current;
36
- }
37
- export function oklchToP3(oklch) {
38
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
39
- return color.to("p3").toString({ format: "color" });
40
- }
@@ -1,14 +0,0 @@
1
- import type { OklchColor, Step, TemplateId } from "../types.js";
2
- export declare const templates: {
3
- light: {
4
- neutral: Record<Step, OklchColor>;
5
- warm: Record<Step, OklchColor>;
6
- cool: Record<Step, OklchColor>;
7
- };
8
- dark: {
9
- neutral: Record<Step, OklchColor>;
10
- warm: Record<Step, OklchColor>;
11
- cool: Record<Step, OklchColor>;
12
- };
13
- };
14
- export declare function selectTemplateId(oklch: OklchColor): TemplateId;
@@ -1,45 +0,0 @@
1
- const steps = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
2
- const lightnessLight = [0.99, 0.975, 0.95, 0.92, 0.89, 0.84, 0.77, 0.68, 0.58, 0.5, 0.4, 0.3];
3
- const lightnessDark = [0.12, 0.14, 0.18, 0.22, 0.26, 0.32, 0.4, 0.48, 0.58, 0.66, 0.76, 0.86];
4
- const chromaNeutral = [
5
- 0.01, 0.012, 0.016, 0.02, 0.024, 0.03, 0.04, 0.05, 0.055, 0.045, 0.035, 0.028,
6
- ];
7
- const chromaWarm = [0.02, 0.03, 0.05, 0.08, 0.12, 0.16, 0.18, 0.2, 0.22, 0.19, 0.12, 0.08];
8
- const chromaCool = [0.02, 0.03, 0.05, 0.075, 0.1, 0.14, 0.17, 0.19, 0.21, 0.18, 0.11, 0.08];
9
- const baseHue = {
10
- neutral: 250,
11
- warm: 40,
12
- cool: 220,
13
- };
14
- function buildTemplate(lightness, chroma, hue) {
15
- const output = {};
16
- for (let i = 0; i < steps.length; i += 1) {
17
- const step = steps[i];
18
- output[step] = {
19
- l: lightness[i],
20
- c: chroma[i],
21
- h: hue,
22
- };
23
- }
24
- return output;
25
- }
26
- export const templates = {
27
- light: {
28
- neutral: buildTemplate(lightnessLight, chromaNeutral, baseHue.neutral),
29
- warm: buildTemplate(lightnessLight, chromaWarm, baseHue.warm),
30
- cool: buildTemplate(lightnessLight, chromaCool, baseHue.cool),
31
- },
32
- dark: {
33
- neutral: buildTemplate(lightnessDark, chromaNeutral, baseHue.neutral),
34
- warm: buildTemplate(lightnessDark, chromaWarm, baseHue.warm),
35
- cool: buildTemplate(lightnessDark, chromaCool, baseHue.cool),
36
- },
37
- };
38
- export function selectTemplateId(oklch) {
39
- if (oklch.c < 0.05) {
40
- return "neutral";
41
- }
42
- const hue = ((oklch.h % 360) + 360) % 360;
43
- const isWarm = hue <= 60 || hue >= 330;
44
- return isWarm ? "warm" : "cool";
45
- }
@@ -1,2 +0,0 @@
1
- import type { Theme, ThemeColorMode } from "../types.js";
2
- export declare function selectThemeColorMode(theme: Theme, mode: "srgb" | "p3"): ThemeColorMode;
@@ -1,19 +0,0 @@
1
- export function selectThemeColorMode(theme, mode) {
2
- if (mode === "srgb") {
3
- return theme;
4
- }
5
- const scales = Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => {
6
- if (!scale.p3) {
7
- return [slot, scale];
8
- }
9
- return [
10
- slot,
11
- {
12
- ...scale,
13
- light: scale.p3.light,
14
- dark: scale.p3.dark,
15
- },
16
- ];
17
- }));
18
- return { ...theme, scales };
19
- }
@@ -1,13 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type CssVarsOptions = {
3
- prefix?: string;
4
- includeTokens?: boolean;
5
- includeScales?: boolean;
6
- includeAlpha?: boolean;
7
- includeOverlays?: boolean;
8
- includeP3?: boolean;
9
- lightSelector?: string;
10
- darkSelector?: string;
11
- };
12
- export declare function toCssVars(theme: Theme, options?: CssVarsOptions): string;
13
- export {};
@@ -1,108 +0,0 @@
1
- import Color from "colorjs.io";
2
- function tokenToCssVar(token, prefix) {
3
- const normalized = token.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
4
- const dashed = normalized.replace(/\./g, "-");
5
- return `--${prefix}-${dashed}`;
6
- }
7
- function scaleToCssVar(slot, step, prefix) {
8
- return `--${prefix}-scale-${slot}-${step}`;
9
- }
10
- function alphaToCssVar(slot, step, prefix) {
11
- return `--${prefix}-alpha-${slot}-${step}`;
12
- }
13
- function overlayToCssVar(color, step, prefix) {
14
- return `--${prefix}-overlay-${color}-${step}`;
15
- }
16
- function hexToP3(value) {
17
- return new Color(value).to("p3").toString({ format: "color" });
18
- }
19
- export function toCssVars(theme, options) {
20
- const prefix = options?.prefix ?? "pk";
21
- const includeTokens = options?.includeTokens ?? true;
22
- const includeScales = options?.includeScales ?? true;
23
- const includeAlpha = options?.includeAlpha ?? true;
24
- const includeOverlays = options?.includeOverlays ?? true;
25
- const includeP3 = options?.includeP3 ?? false;
26
- const lightSelector = options?.lightSelector ?? ":root";
27
- const darkSelector = options?.darkSelector ?? ".dark";
28
- const lines = [];
29
- const hasP3 = Object.values(theme.scales).some((scale) => scale.p3);
30
- function emitSelector(selector, mode) {
31
- lines.push(`${selector} {`);
32
- if (includeTokens) {
33
- for (const [token, value] of Object.entries(theme.tokens[mode])) {
34
- lines.push(` ${tokenToCssVar(token, prefix)}: ${value};`);
35
- }
36
- }
37
- if (includeScales) {
38
- for (const [slot, scale] of Object.entries(theme.scales)) {
39
- for (const [step, value] of Object.entries(scale[mode])) {
40
- lines.push(` ${scaleToCssVar(slot, Number(step), prefix)}: ${value};`);
41
- }
42
- }
43
- }
44
- if (includeAlpha && theme.alpha) {
45
- for (const [slot, scale] of Object.entries(theme.alpha)) {
46
- for (const [step, value] of Object.entries(scale[mode])) {
47
- lines.push(` ${alphaToCssVar(slot, Number(step), prefix)}: ${value};`);
48
- }
49
- }
50
- }
51
- if (includeOverlays) {
52
- for (const [step, value] of Object.entries(theme.overlay.black)) {
53
- lines.push(` ${overlayToCssVar("black", Number(step), prefix)}: ${value};`);
54
- }
55
- for (const [step, value] of Object.entries(theme.overlay.white)) {
56
- lines.push(` ${overlayToCssVar("white", Number(step), prefix)}: ${value};`);
57
- }
58
- }
59
- lines.push("}");
60
- }
61
- emitSelector(lightSelector, "light");
62
- lines.push("");
63
- emitSelector(darkSelector, "dark");
64
- if (includeP3 && hasP3) {
65
- lines.push("");
66
- lines.push("@supports (color: color(display-p3 1 1 1)) {");
67
- function emitP3Selector(selector, mode) {
68
- lines.push(` ${selector} {`);
69
- if (includeTokens) {
70
- for (const [token, value] of Object.entries(theme.tokens[mode])) {
71
- lines.push(` ${tokenToCssVar(token, prefix)}: ${hexToP3(value)};`);
72
- }
73
- }
74
- if (includeScales) {
75
- for (const [slot, scale] of Object.entries(theme.scales)) {
76
- const p3Scale = scale.p3?.[mode];
77
- if (!p3Scale) {
78
- continue;
79
- }
80
- for (const [step, value] of Object.entries(p3Scale)) {
81
- lines.push(` ${scaleToCssVar(slot, Number(step), prefix)}: ${value};`);
82
- }
83
- }
84
- }
85
- if (includeAlpha && theme.alpha) {
86
- for (const [slot, scale] of Object.entries(theme.alpha)) {
87
- for (const [step, value] of Object.entries(scale[mode])) {
88
- lines.push(` ${alphaToCssVar(slot, Number(step), prefix)}: ${hexToP3(value)};`);
89
- }
90
- }
91
- }
92
- if (includeOverlays) {
93
- for (const [step, value] of Object.entries(theme.overlay.black)) {
94
- lines.push(` ${overlayToCssVar("black", Number(step), prefix)}: ${hexToP3(value)};`);
95
- }
96
- for (const [step, value] of Object.entries(theme.overlay.white)) {
97
- lines.push(` ${overlayToCssVar("white", Number(step), prefix)}: ${hexToP3(value)};`);
98
- }
99
- }
100
- lines.push(" }");
101
- }
102
- emitP3Selector(lightSelector, "light");
103
- lines.push("");
104
- emitP3Selector(darkSelector, "dark");
105
- lines.push("}");
106
- }
107
- return lines.join("\n");
108
- }
@@ -1,3 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- export declare function toJson(theme: Theme): string;
3
- export declare function toJsonWithMode(theme: Theme, mode: "srgb" | "p3"): string;
@@ -1,25 +0,0 @@
1
- export function toJson(theme) {
2
- return JSON.stringify(theme, null, 2);
3
- }
4
- export function toJsonWithMode(theme, mode) {
5
- if (mode === "p3") {
6
- return JSON.stringify(toP3Theme(theme), null, 2);
7
- }
8
- return JSON.stringify(theme, null, 2);
9
- }
10
- function toP3Theme(theme) {
11
- const scales = Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => {
12
- if (!scale.p3) {
13
- return [slot, scale];
14
- }
15
- return [
16
- slot,
17
- {
18
- ...scale,
19
- light: scale.p3.light,
20
- dark: scale.p3.dark,
21
- },
22
- ];
23
- }));
24
- return { ...theme, scales };
25
- }
@@ -1,54 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type ReactNativeOptions = {
3
- includeTokens?: boolean;
4
- includeScales?: boolean;
5
- includeAlpha?: boolean;
6
- includeOverlays?: boolean;
7
- includeP3?: boolean;
8
- };
9
- type Mode = "light" | "dark";
10
- type ModeTokens<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
11
- includeTokens: false;
12
- } ? Record<string, never> : T["tokens"][M];
13
- type ModeScales<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
14
- includeScales: false;
15
- } ? Record<string, never> : {
16
- [K in keyof T["scales"]]: T["scales"][K][M];
17
- };
18
- type ThemeAlpha<T extends Theme> = T["alpha"] extends undefined ? undefined : T["alpha"];
19
- type ModeAlpha<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
20
- includeAlpha: false;
21
- } ? undefined : ThemeAlpha<T> extends undefined ? undefined : ThemeAlpha<T> extends Record<string, {
22
- light: infer L;
23
- dark: infer D;
24
- }> ? M extends "light" ? Record<string, L> : Record<string, D> : undefined;
25
- type ModeOverlays<T extends Theme, O extends ReactNativeOptions> = O extends {
26
- includeOverlays: false;
27
- } ? undefined : T["overlay"];
28
- type ModeP3<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
29
- includeP3: true;
30
- } ? Partial<{
31
- [K in keyof T["scales"]]: T["scales"][K] extends {
32
- p3?: {
33
- light: infer L;
34
- dark: infer D;
35
- };
36
- } ? M extends "light" ? L : D : never;
37
- }> : undefined;
38
- type ReactNativeTheme<T extends Theme, O extends ReactNativeOptions> = {
39
- overlay: ModeOverlays<T, O>;
40
- light: {
41
- tokens: ModeTokens<T, O, "light">;
42
- scales: ModeScales<T, O, "light">;
43
- alpha: ModeAlpha<T, O, "light">;
44
- p3: ModeP3<T, O, "light">;
45
- };
46
- dark: {
47
- tokens: ModeTokens<T, O, "dark">;
48
- scales: ModeScales<T, O, "dark">;
49
- alpha: ModeAlpha<T, O, "dark">;
50
- p3: ModeP3<T, O, "dark">;
51
- };
52
- };
53
- export declare function toReactNative<T extends Theme, O extends ReactNativeOptions = ReactNativeOptions>(theme: T, options?: O): ReactNativeTheme<T, O>;
54
- export {};
@@ -1,33 +0,0 @@
1
- export function toReactNative(theme, options) {
2
- const includeTokens = options?.includeTokens ?? true;
3
- const includeScales = options?.includeScales ?? true;
4
- const includeAlpha = options?.includeAlpha ?? true;
5
- const includeOverlays = options?.includeOverlays ?? true;
6
- const includeP3 = options?.includeP3 ?? false;
7
- function buildMode(mode) {
8
- const scales = includeScales
9
- ? Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => [slot, scale[mode]]))
10
- : {};
11
- const p3 = includeP3
12
- ? Object.fromEntries(Object.entries(theme.scales)
13
- .filter(([, scale]) => scale.p3?.[mode])
14
- .map(([slot, scale]) => [slot, scale.p3?.[mode]]))
15
- : undefined;
16
- const alpha = includeAlpha
17
- ? (theme.alpha
18
- ? Object.fromEntries(Object.entries(theme.alpha).map(([slot, scale]) => [slot, scale[mode]]))
19
- : undefined)
20
- : undefined;
21
- return {
22
- tokens: (includeTokens ? theme.tokens[mode] : {}),
23
- scales,
24
- alpha,
25
- p3,
26
- };
27
- }
28
- return {
29
- overlay: (includeOverlays ? theme.overlay : undefined),
30
- light: buildMode("light"),
31
- dark: buildMode("dark"),
32
- };
33
- }
@@ -1,17 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type TailwindOptions = {
3
- mode?: "light" | "dark" | "both";
4
- includeTokens?: boolean;
5
- includeScales?: boolean;
6
- includeAlpha?: boolean;
7
- includeOverlays?: boolean;
8
- includeP3?: boolean;
9
- };
10
- export declare function toTailwind(theme: Theme, options?: TailwindOptions): {
11
- theme: {
12
- extend: {
13
- colors: Record<string, unknown>;
14
- };
15
- };
16
- };
17
- export {};
@@ -1,111 +0,0 @@
1
- function setNested(target, path, value) {
2
- let cursor = target;
3
- for (let i = 0; i < path.length - 1; i += 1) {
4
- const key = path[i];
5
- if (!cursor[key] || typeof cursor[key] !== "object") {
6
- cursor[key] = {};
7
- }
8
- cursor = cursor[key];
9
- }
10
- cursor[path[path.length - 1]] = value;
11
- }
12
- function tokensToNested(tokens) {
13
- const output = {};
14
- for (const [token, value] of Object.entries(tokens)) {
15
- setNested(output, token.split("."), value);
16
- }
17
- return output;
18
- }
19
- function scalesToNested(scales, mode, useP3) {
20
- const output = {};
21
- for (const [slot, scale] of Object.entries(scales)) {
22
- const source = useP3 ? scale.p3?.[mode] : scale[mode];
23
- if (!source) {
24
- continue;
25
- }
26
- const stepMap = {};
27
- for (const [step, value] of Object.entries(source)) {
28
- stepMap[String(step)] = value;
29
- }
30
- output[slot] = stepMap;
31
- }
32
- return output;
33
- }
34
- function alphaToNested(alpha, mode) {
35
- if (!alpha) {
36
- return undefined;
37
- }
38
- const output = {};
39
- for (const [slot, scale] of Object.entries(alpha)) {
40
- const stepMap = {};
41
- for (const [step, value] of Object.entries(scale[mode])) {
42
- stepMap[String(step)] = value;
43
- }
44
- output[slot] = stepMap;
45
- }
46
- return output;
47
- }
48
- function overlaysToNested(overlays) {
49
- const output = {
50
- black: {},
51
- white: {},
52
- };
53
- for (const [step, value] of Object.entries(overlays.black)) {
54
- output.black[String(step)] = value;
55
- }
56
- for (const [step, value] of Object.entries(overlays.white)) {
57
- output.white[String(step)] = value;
58
- }
59
- return output;
60
- }
61
- export function toTailwind(theme, options) {
62
- const mode = options?.mode ?? "both";
63
- const includeTokens = options?.includeTokens ?? true;
64
- const includeScales = options?.includeScales ?? false;
65
- const includeAlpha = options?.includeAlpha ?? false;
66
- const includeOverlays = options?.includeOverlays ?? false;
67
- const includeP3 = options?.includeP3 ?? false;
68
- function buildModeTokens(modeKey, useP3) {
69
- const colors = {};
70
- if (includeTokens) {
71
- colors.tokens = tokensToNested(theme.tokens[modeKey]);
72
- }
73
- if (includeScales) {
74
- colors.scale = scalesToNested(theme.scales, modeKey, useP3);
75
- }
76
- if (includeAlpha && theme.alpha) {
77
- colors.alpha = alphaToNested(theme.alpha, modeKey);
78
- }
79
- if (includeOverlays) {
80
- colors.overlay = overlaysToNested(theme.overlay);
81
- }
82
- return colors;
83
- }
84
- const colors = {};
85
- if (mode === "light" || mode === "both") {
86
- colors.light = buildModeTokens("light");
87
- }
88
- if (mode === "dark" || mode === "both") {
89
- colors.dark = buildModeTokens("dark");
90
- }
91
- if (includeP3) {
92
- const hasP3 = Object.values(theme.scales).some((scale) => scale.p3);
93
- if (hasP3) {
94
- const p3 = {};
95
- if (mode === "light" || mode === "both") {
96
- p3.light = buildModeTokens("light", true);
97
- }
98
- if (mode === "dark" || mode === "both") {
99
- p3.dark = buildModeTokens("dark", true);
100
- }
101
- colors.p3 = p3;
102
- }
103
- }
104
- return {
105
- theme: {
106
- extend: {
107
- colors,
108
- },
109
- },
110
- };
111
- }
@@ -1,3 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- export declare function toTs(theme: Theme): string;
3
- export declare function toTsWithMode(theme: Theme, mode: "srgb" | "p3"): string;