@nxds/core 0.12.0 → 0.13.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.
@@ -1889,6 +1889,321 @@ function apcaLc(foreground, background) {
1889
1889
  );
1890
1890
  }
1891
1891
 
1892
+ // src/lib/contrast.ts
1893
+ import { APCAcontrast as APCAcontrast3, sRGBtoY as sRGBtoY3 } from "apca-w3";
1894
+ import { clampChroma as clampChroma5 } from "culori";
1895
+
1896
+ // src/lib/semantic-palette-references.ts
1897
+ var STATUS_PALETTE_FAMILIES = {
1898
+ success: "green",
1899
+ warning: "orange",
1900
+ error: "red",
1901
+ information: "blue"
1902
+ };
1903
+ var CHART_PALETTE_REFERENCES = [
1904
+ { palette: "teal", light: "700", dark: "200" },
1905
+ { palette: "lime", light: "700", dark: "200" },
1906
+ { palette: "orange", light: "600", dark: "200" },
1907
+ { palette: "rose", light: "600", dark: "200" },
1908
+ { palette: "indigo", light: "600", dark: "200" }
1909
+ ];
1910
+ var SYNTAX_PALETTE_REFERENCES = {
1911
+ keyword: CHART_PALETTE_REFERENCES[3],
1912
+ string: CHART_PALETTE_REFERENCES[1],
1913
+ function: CHART_PALETTE_REFERENCES[4],
1914
+ type: CHART_PALETTE_REFERENCES[0],
1915
+ constant: CHART_PALETTE_REFERENCES[2]
1916
+ };
1917
+
1918
+ // src/lib/apca-pairs.ts
1919
+ var COLOR_FAMILIES = [
1920
+ "primary",
1921
+ "secondary",
1922
+ "success",
1923
+ "warning",
1924
+ "error",
1925
+ "information"
1926
+ ];
1927
+ var CATEGORICAL_INDICES = CHART_PALETTE_REFERENCES.map(
1928
+ (_, index) => index + 1
1929
+ );
1930
+ var CHART_STAGGER_LC = 4.5;
1931
+ var DIFF_SURFACES = ["success-subtle", "error-subtle"];
1932
+ var CODE_SURFACES = ["container", "container-hover", ...DIFF_SURFACES];
1933
+ var FOCUS_SURFACES = [
1934
+ "background",
1935
+ "container",
1936
+ "popover",
1937
+ "nav-background",
1938
+ "nav-item-hover",
1939
+ "nav-item-active",
1940
+ "nav-border"
1941
+ ];
1942
+ var text = (fg, bg, tier) => ({
1943
+ fg,
1944
+ bg,
1945
+ tier,
1946
+ kind: "text"
1947
+ });
1948
+ var label = (fg, bg, tier) => ({
1949
+ fg,
1950
+ bg,
1951
+ tier,
1952
+ kind: "label"
1953
+ });
1954
+ var ink = (fg, bg, tier) => ({
1955
+ fg,
1956
+ bg,
1957
+ tier,
1958
+ kind: "ink"
1959
+ });
1960
+ var APCA_PAIRS = [
1961
+ text("foreground", "background", "body"),
1962
+ text("foreground", "background-hover", "ui"),
1963
+ text("foreground", "muted", "ui"),
1964
+ text("muted-foreground", "muted", "ui"),
1965
+ text("muted-foreground-subtle", "muted", "incidental"),
1966
+ text("muted-foreground", "container", "ui"),
1967
+ text("muted-foreground-subtle", "container", "incidental"),
1968
+ text("foreground", "muted-extralight", "ui"),
1969
+ text("muted-foreground", "muted-extralight", "ui"),
1970
+ text("disabled-foreground", "disabled", "incidental"),
1971
+ text("container-foreground", "container", "body"),
1972
+ text("foreground", "container", "body"),
1973
+ text("popover-foreground", "popover", "body"),
1974
+ text("popover-foreground", "popover-hover", "ui"),
1975
+ text("foreground", "control-background", "ui"),
1976
+ text("foreground", "control-background-hover", "ui"),
1977
+ text("nav-foreground", "nav-background", "ui"),
1978
+ text("nav-muted-foreground", "nav-background", "incidental"),
1979
+ text("nav-foreground", "nav-item-hover", "ui"),
1980
+ text("nav-foreground", "nav-item-active", "ui"),
1981
+ ink("error-subtle-foreground", "background", "ui"),
1982
+ ink("error-subtle-foreground", "container", "ui"),
1983
+ ...COLOR_FAMILIES.flatMap((family) => [
1984
+ label(`${family}-foreground`, `${family}-background`, "ui"),
1985
+ label(`${family}-foreground`, `${family}-background-hover`, "ui"),
1986
+ label(`${family}-foreground`, `${family}-background-active`, "ui"),
1987
+ ink(`${family}-subtle-foreground`, `${family}-subtle`, "ui"),
1988
+ ink(`${family}-subtle-foreground`, `${family}-subtle-hover`, "ui"),
1989
+ ink(`${family}-subtle-foreground`, `${family}-subtle-active`, "ui")
1990
+ ]),
1991
+ ...CATEGORICAL_INDICES.flatMap(
1992
+ (index) => ["container", "container-hover", "background"].map((bg) => ({
1993
+ ...ink(`chart-categorical-${index}`, bg, "ui"),
1994
+ offset: (index - 1) * CHART_STAGGER_LC
1995
+ }))
1996
+ ),
1997
+ ...CODE_SURFACES.flatMap(
1998
+ (bg) => Object.keys(SYNTAX_PALETTE_REFERENCES).map(
1999
+ (role) => ink(`syntax-${role}`, bg, "ui")
2000
+ )
2001
+ ),
2002
+ // codeBlockTheme also colours code with the text tokens, which already read
2003
+ // on container and container-hover.
2004
+ ...DIFF_SURFACES.flatMap((bg) => [
2005
+ text("foreground", bg, "ui"),
2006
+ text("muted-foreground", bg, "ui"),
2007
+ text("muted-foreground-subtle", bg, "incidental")
2008
+ ]),
2009
+ // Focus is the primary accent (components.md § Focus States), so it shares
2010
+ // one solved color with primary-subtle-foreground.
2011
+ ...FOCUS_SURFACES.flatMap((surface) => [
2012
+ {
2013
+ ...ink("focus-default", surface, "incidental"),
2014
+ solveAs: "primary-subtle-foreground"
2015
+ },
2016
+ ink("focus-error", surface, "incidental")
2017
+ ]),
2018
+ ...[
2019
+ "background-active",
2020
+ "container-hover",
2021
+ "container-active",
2022
+ "popover",
2023
+ "popover-hover",
2024
+ "popover-active",
2025
+ "nav-background"
2026
+ ].flatMap((surface) => [
2027
+ text("foreground", surface, "ui"),
2028
+ text("muted-foreground", surface, "ui"),
2029
+ text("muted-foreground-subtle", surface, "incidental")
2030
+ ]),
2031
+ text("muted-foreground", "background", "ui"),
2032
+ text("muted-foreground-subtle", "background", "incidental"),
2033
+ text("container-foreground", "container-hover", "ui"),
2034
+ text("container-foreground", "container-active", "ui"),
2035
+ text("popover-foreground", "popover-active", "ui"),
2036
+ ...["background", "container", "popover"].flatMap((backdrop) => [
2037
+ { ...text("popover-foreground", "popover-alpha", "body"), backdrop },
2038
+ { ...text("foreground", "background-hover-alpha", "ui"), backdrop }
2039
+ ]),
2040
+ ...["#000000", "#ffffff"].map((backdrop) => ({
2041
+ ...text("popover-foreground", "popover-alpha", "body"),
2042
+ backdrop
2043
+ }))
2044
+ ];
2045
+
2046
+ // src/lib/perceptual-ramp.ts
2047
+ import { clampChroma as clampChroma4, oklch as oklch5, parse as parse5 } from "culori";
2048
+ var EMIT_GAMUT2 = "p3";
2049
+ var CUSP_FRACTION2 = 0.95;
2050
+ function isColor(value) {
2051
+ return parse5(value) !== void 0;
2052
+ }
2053
+ function seedOklch(input) {
2054
+ const parsed = parse5(input);
2055
+ if (!parsed)
2056
+ throw new Error(`perceptual-ramp: cannot parse color '${input}'`);
2057
+ const converted = oklch5(parsed);
2058
+ if (!converted)
2059
+ throw new Error(`perceptual-ramp: cannot convert '${input}' to OKLCH`);
2060
+ return converted;
2061
+ }
2062
+ function pinnedOklch(seedHex, shade, options = {}) {
2063
+ const { capAtSeedChroma = true } = options;
2064
+ const seed = seedOklch(seedHex);
2065
+ const l = PERCEPTUAL_L_GRID[shade];
2066
+ const hue = seed.h ?? 0;
2067
+ const seedC = seed.c ?? 0;
2068
+ const cuspC = clampChroma4({ mode: "oklch", l, c: 0.5, h: hue }, "oklch", EMIT_GAMUT2).c ?? 0;
2069
+ let chroma = cuspC * CUSP_FRACTION2;
2070
+ if (capAtSeedChroma) chroma = Math.min(chroma, seedC);
2071
+ const target = { mode: "oklch", l, c: chroma, h: hue };
2072
+ return formatOklch(clampChroma4(target, "oklch", EMIT_GAMUT2));
2073
+ }
2074
+ function rampFromSeed(seedHex, options = {}) {
2075
+ const ramp = {};
2076
+ for (const shade of SHADES)
2077
+ ramp[shade] = pinnedOklch(seedHex, shade, options);
2078
+ return ramp;
2079
+ }
2080
+
2081
+ // src/lib/contrast.ts
2082
+ var CONTRAST_MIN = 0;
2083
+ var CONTRAST_MAX = 100;
2084
+ function normalizeContrast(value, fallback = 50) {
2085
+ return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(CONTRAST_MIN, Math.min(CONTRAST_MAX, value))) : fallback;
2086
+ }
2087
+ function contrastTarget(tier, contrast) {
2088
+ return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
2089
+ }
2090
+ var BISECT_STEPS = 12;
2091
+ function bisect(fail, pass, passes) {
2092
+ for (let i = 0; i < BISECT_STEPS; i++) {
2093
+ const middle = (fail + pass) / 2;
2094
+ if (passes(middle)) pass = middle;
2095
+ else fail = middle;
2096
+ }
2097
+ return pass;
2098
+ }
2099
+ var token = (map, name) => {
2100
+ const value = map[`--nx-color-${name}`];
2101
+ if (value === void 0) throw new Error(`contrast: missing ${name}`);
2102
+ return value;
2103
+ };
2104
+ function pairBackground(map, pair) {
2105
+ const backdrop = pair.backdrop ? resolveToSrgbInts(
2106
+ pair.backdrop.startsWith("#") ? pair.backdrop : token(map, pair.backdrop)
2107
+ ) : void 0;
2108
+ return resolveToSrgbInts(token(map, pair.bg), backdrop);
2109
+ }
2110
+ function contrastForPair(map, pair) {
2111
+ const background = pairBackground(map, pair);
2112
+ return Math.abs(
2113
+ APCAcontrast3(
2114
+ sRGBtoY3(resolveToSrgbInts(token(map, pair.fg), background)),
2115
+ sRGBtoY3(background)
2116
+ )
2117
+ );
2118
+ }
2119
+ var luminance = (color) => sRGBtoY3(resolveToSrgbInts(color));
2120
+ var score = (foregroundY, backgroundY) => Math.abs(APCAcontrast3(foregroundY, backgroundY));
2121
+ function constraintsFor(map, pairs, contrast, endpointY) {
2122
+ const constraints = [];
2123
+ for (const pair of pairs) {
2124
+ const backgroundY = sRGBtoY3(pairBackground(map, pair));
2125
+ const reachable = score(endpointY, backgroundY);
2126
+ if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
2127
+ const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
2128
+ constraints.push({ backgroundY, target: Math.min(target, reachable) });
2129
+ }
2130
+ return constraints;
2131
+ }
2132
+ var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
2133
+ function solveForeground(seed, constraints, endpoint, keepSeed) {
2134
+ const passes = (color) => {
2135
+ const y = luminance(color);
2136
+ return constraints.every((c) => score(y, c.backgroundY) >= c.target);
2137
+ };
2138
+ if (keepSeed && passes(seed)) return seed;
2139
+ const parsed = seedOklch(seed);
2140
+ const at = (l) => formatOklch(clampChroma5({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
2141
+ return at(
2142
+ bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
2143
+ );
2144
+ }
2145
+ var SOLVE_GROUPS = /* @__PURE__ */ new Map();
2146
+ for (const pair of APCA_PAIRS) {
2147
+ const key = pair.solveAs ?? pair.fg;
2148
+ const group = SOLVE_GROUPS.get(key);
2149
+ if (!group) {
2150
+ SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
2151
+ continue;
2152
+ }
2153
+ if (group.kind !== pair.kind)
2154
+ throw new Error(
2155
+ `contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
2156
+ );
2157
+ group.pairs.push(pair);
2158
+ }
2159
+ function constrainFamilyFills(map, name, pairs) {
2160
+ const basePair = pairs[0];
2161
+ if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
2162
+ const baseY = luminance(token(map, basePair.bg));
2163
+ const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
2164
+ map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
2165
+ for (const pair of pairs) {
2166
+ const floor = TIER_THRESHOLDS[pair.tier];
2167
+ const value = token(map, pair.bg);
2168
+ if (score(endpoint, luminance(value)) >= floor) continue;
2169
+ const fill = seedOklch(value);
2170
+ const at = (l) => formatOklch(clampChroma5({ ...fill, l }, "oklch", "p3"));
2171
+ const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
2172
+ map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
2173
+ }
2174
+ }
2175
+ function constrainColors(map, mode, contrast) {
2176
+ for (const [name, { kind, pairs }] of SOLVE_GROUPS)
2177
+ if (kind === "label") constrainFamilyFills(map, name, pairs);
2178
+ const endpoint = mode === "dark" ? 1 : 0;
2179
+ const endpointY = luminance(`oklch(${endpoint} 0 0)`);
2180
+ for (const [name, { kind, pairs }] of SOLVE_GROUPS) {
2181
+ if (kind === "label") continue;
2182
+ const constraints = constraintsFor(map, pairs, contrast, endpointY);
2183
+ if (constraints === void 0)
2184
+ throw new Error(`contrast: no readable ${name} in ${mode}`);
2185
+ const solved = solveForeground(
2186
+ token(map, name),
2187
+ constraints,
2188
+ endpoint,
2189
+ keepsTextSeed(mode, kind)
2190
+ );
2191
+ for (const fg of new Set(pairs.map((pair) => pair.fg).concat(name)))
2192
+ map[`--nx-color-${fg}`] = solved;
2193
+ }
2194
+ return map;
2195
+ }
2196
+
2197
+ // src/lib/runtime-layer.ts
2198
+ var RUNTIME_LAYER_ORDER = "@layer properties, theme, base, components, utilities, nx-runtime;";
2199
+ function inRuntimeLayer(css) {
2200
+ return `${RUNTIME_LAYER_ORDER}
2201
+ @layer nx-runtime {
2202
+ ${css}
2203
+ }
2204
+ `;
2205
+ }
2206
+
1892
2207
  // tokens/primitives/typography/typography-default.json
1893
2208
  var typography_default_default = {
1894
2209
  family: {
@@ -2027,6 +2342,13 @@ var typography_default_default = {
2027
2342
  unit: "px"
2028
2343
  },
2029
2344
  $type: "dimension"
2345
+ },
2346
+ code: {
2347
+ $value: {
2348
+ value: 12,
2349
+ unit: "px"
2350
+ },
2351
+ $type: "dimension"
2030
2352
  }
2031
2353
  },
2032
2354
  weight: {
@@ -2148,384 +2470,93 @@ var typography_default_default = {
2148
2470
  "7xl": {
2149
2471
  $value: {
2150
2472
  value: 72,
2151
- unit: "px"
2152
- },
2153
- $type: "dimension"
2154
- },
2155
- "8xl": {
2156
- $value: {
2157
- value: 96,
2158
- unit: "px"
2159
- },
2160
- $type: "dimension"
2161
- },
2162
- "9xl": {
2163
- $value: {
2164
- value: 128,
2165
- unit: "px"
2166
- },
2167
- $type: "dimension"
2168
- }
2169
- },
2170
- letterspacing: {
2171
- tighter: {
2172
- $value: {
2173
- value: -0.800000011920929,
2174
- unit: "px"
2175
- },
2176
- $type: "dimension"
2177
- },
2178
- tight: {
2179
- $value: {
2180
- value: -0.4000000059604645,
2181
- unit: "px"
2182
- },
2183
- $type: "dimension"
2184
- },
2185
- normal: {
2186
- $value: {
2187
- value: 0,
2188
- unit: "px"
2189
- },
2190
- $type: "dimension"
2191
- },
2192
- wide: {
2193
- $value: {
2194
- value: 0.4000000059604645,
2195
- unit: "px"
2196
- },
2197
- $type: "dimension"
2198
- },
2199
- wider: {
2200
- $value: {
2201
- value: 0.800000011920929,
2202
- unit: "px"
2203
- },
2204
- $type: "dimension"
2205
- },
2206
- widest: {
2207
- $value: {
2208
- value: 1.600000023841858,
2209
- unit: "px"
2210
- },
2211
- $type: "dimension"
2212
- }
2213
- }
2214
- };
2215
-
2216
- // src/lib/contrast.ts
2217
- import { APCAcontrast as APCAcontrast3, sRGBtoY as sRGBtoY3 } from "apca-w3";
2218
- import { clampChroma as clampChroma5 } from "culori";
2219
-
2220
- // src/lib/semantic-palette-references.ts
2221
- var STATUS_PALETTE_FAMILIES = {
2222
- success: "green",
2223
- warning: "orange",
2224
- error: "red",
2225
- information: "blue"
2226
- };
2227
- var CHART_PALETTE_REFERENCES = [
2228
- { palette: "teal", light: "700", dark: "200" },
2229
- { palette: "lime", light: "700", dark: "200" },
2230
- { palette: "orange", light: "600", dark: "200" },
2231
- { palette: "rose", light: "600", dark: "200" },
2232
- { palette: "indigo", light: "600", dark: "200" }
2233
- ];
2234
- var SYNTAX_PALETTE_REFERENCES = {
2235
- keyword: CHART_PALETTE_REFERENCES[3],
2236
- string: CHART_PALETTE_REFERENCES[1],
2237
- function: CHART_PALETTE_REFERENCES[4],
2238
- type: CHART_PALETTE_REFERENCES[0],
2239
- constant: CHART_PALETTE_REFERENCES[2]
2240
- };
2241
-
2242
- // src/lib/apca-pairs.ts
2243
- var COLOR_FAMILIES = [
2244
- "primary",
2245
- "secondary",
2246
- "success",
2247
- "warning",
2248
- "error",
2249
- "information"
2250
- ];
2251
- var CATEGORICAL_INDICES = CHART_PALETTE_REFERENCES.map(
2252
- (_, index) => index + 1
2253
- );
2254
- var CHART_STAGGER_LC = 4.5;
2255
- var DIFF_SURFACES = ["success-subtle", "error-subtle"];
2256
- var CODE_SURFACES = ["container", "container-hover", ...DIFF_SURFACES];
2257
- var FOCUS_SURFACES = [
2258
- "background",
2259
- "container",
2260
- "popover",
2261
- "nav-background",
2262
- "nav-item-hover",
2263
- "nav-item-active",
2264
- "nav-border"
2265
- ];
2266
- var text = (fg, bg, tier) => ({
2267
- fg,
2268
- bg,
2269
- tier,
2270
- kind: "text"
2271
- });
2272
- var label = (fg, bg, tier) => ({
2273
- fg,
2274
- bg,
2275
- tier,
2276
- kind: "label"
2277
- });
2278
- var ink = (fg, bg, tier) => ({
2279
- fg,
2280
- bg,
2281
- tier,
2282
- kind: "ink"
2283
- });
2284
- var APCA_PAIRS = [
2285
- text("foreground", "background", "body"),
2286
- text("foreground", "background-hover", "ui"),
2287
- text("foreground", "muted", "ui"),
2288
- text("muted-foreground", "muted", "ui"),
2289
- text("muted-foreground-subtle", "muted", "incidental"),
2290
- text("muted-foreground", "container", "ui"),
2291
- text("muted-foreground-subtle", "container", "incidental"),
2292
- text("foreground", "muted-extralight", "ui"),
2293
- text("muted-foreground", "muted-extralight", "ui"),
2294
- text("disabled-foreground", "disabled", "incidental"),
2295
- text("container-foreground", "container", "body"),
2296
- text("foreground", "container", "body"),
2297
- text("popover-foreground", "popover", "body"),
2298
- text("popover-foreground", "popover-hover", "ui"),
2299
- text("foreground", "control-background", "ui"),
2300
- text("foreground", "control-background-hover", "ui"),
2301
- text("nav-foreground", "nav-background", "ui"),
2302
- text("nav-muted-foreground", "nav-background", "incidental"),
2303
- text("nav-foreground", "nav-item-hover", "ui"),
2304
- text("nav-foreground", "nav-item-active", "ui"),
2305
- ink("error-subtle-foreground", "background", "ui"),
2306
- ink("error-subtle-foreground", "container", "ui"),
2307
- ...COLOR_FAMILIES.flatMap((family) => [
2308
- label(`${family}-foreground`, `${family}-background`, "ui"),
2309
- label(`${family}-foreground`, `${family}-background-hover`, "ui"),
2310
- label(`${family}-foreground`, `${family}-background-active`, "ui"),
2311
- ink(`${family}-subtle-foreground`, `${family}-subtle`, "ui"),
2312
- ink(`${family}-subtle-foreground`, `${family}-subtle-hover`, "ui"),
2313
- ink(`${family}-subtle-foreground`, `${family}-subtle-active`, "ui")
2314
- ]),
2315
- ...CATEGORICAL_INDICES.flatMap(
2316
- (index) => ["container", "container-hover", "background"].map((bg) => ({
2317
- ...ink(`chart-categorical-${index}`, bg, "ui"),
2318
- offset: (index - 1) * CHART_STAGGER_LC
2319
- }))
2320
- ),
2321
- ...CODE_SURFACES.flatMap(
2322
- (bg) => Object.keys(SYNTAX_PALETTE_REFERENCES).map(
2323
- (role) => ink(`syntax-${role}`, bg, "ui")
2324
- )
2325
- ),
2326
- // codeBlockTheme also colours code with the text tokens, which already read
2327
- // on container and container-hover.
2328
- ...DIFF_SURFACES.flatMap((bg) => [
2329
- text("foreground", bg, "ui"),
2330
- text("muted-foreground", bg, "ui"),
2331
- text("muted-foreground-subtle", bg, "incidental")
2332
- ]),
2333
- // Focus is the primary accent (components.md § Focus States), so it shares
2334
- // one solved color with primary-subtle-foreground.
2335
- ...FOCUS_SURFACES.flatMap((surface) => [
2336
- {
2337
- ...ink("focus-default", surface, "incidental"),
2338
- solveAs: "primary-subtle-foreground"
2473
+ unit: "px"
2474
+ },
2475
+ $type: "dimension"
2339
2476
  },
2340
- ink("focus-error", surface, "incidental")
2341
- ]),
2342
- ...[
2343
- "background-active",
2344
- "container-hover",
2345
- "container-active",
2346
- "popover",
2347
- "popover-hover",
2348
- "popover-active",
2349
- "nav-background"
2350
- ].flatMap((surface) => [
2351
- text("foreground", surface, "ui"),
2352
- text("muted-foreground", surface, "ui"),
2353
- text("muted-foreground-subtle", surface, "incidental")
2354
- ]),
2355
- text("muted-foreground", "background", "ui"),
2356
- text("muted-foreground-subtle", "background", "incidental"),
2357
- text("container-foreground", "container-hover", "ui"),
2358
- text("container-foreground", "container-active", "ui"),
2359
- text("popover-foreground", "popover-active", "ui"),
2360
- ...["background", "container", "popover"].flatMap((backdrop) => [
2361
- { ...text("popover-foreground", "popover-alpha", "body"), backdrop },
2362
- { ...text("foreground", "background-hover-alpha", "ui"), backdrop }
2363
- ]),
2364
- ...["#000000", "#ffffff"].map((backdrop) => ({
2365
- ...text("popover-foreground", "popover-alpha", "body"),
2366
- backdrop
2367
- }))
2368
- ];
2369
-
2370
- // src/lib/perceptual-ramp.ts
2371
- import { clampChroma as clampChroma4, oklch as oklch5, parse as parse5 } from "culori";
2372
- var EMIT_GAMUT2 = "p3";
2373
- var CUSP_FRACTION2 = 0.95;
2374
- function isColor(value) {
2375
- return parse5(value) !== void 0;
2376
- }
2377
- function seedOklch(input) {
2378
- const parsed = parse5(input);
2379
- if (!parsed)
2380
- throw new Error(`perceptual-ramp: cannot parse color '${input}'`);
2381
- const converted = oklch5(parsed);
2382
- if (!converted)
2383
- throw new Error(`perceptual-ramp: cannot convert '${input}' to OKLCH`);
2384
- return converted;
2385
- }
2386
- function pinnedOklch(seedHex, shade, options = {}) {
2387
- const { capAtSeedChroma = true } = options;
2388
- const seed = seedOklch(seedHex);
2389
- const l = PERCEPTUAL_L_GRID[shade];
2390
- const hue = seed.h ?? 0;
2391
- const seedC = seed.c ?? 0;
2392
- const cuspC = clampChroma4({ mode: "oklch", l, c: 0.5, h: hue }, "oklch", EMIT_GAMUT2).c ?? 0;
2393
- let chroma = cuspC * CUSP_FRACTION2;
2394
- if (capAtSeedChroma) chroma = Math.min(chroma, seedC);
2395
- const target = { mode: "oklch", l, c: chroma, h: hue };
2396
- return formatOklch(clampChroma4(target, "oklch", EMIT_GAMUT2));
2397
- }
2398
- function rampFromSeed(seedHex, options = {}) {
2399
- const ramp = {};
2400
- for (const shade of SHADES)
2401
- ramp[shade] = pinnedOklch(seedHex, shade, options);
2402
- return ramp;
2403
- }
2404
-
2405
- // src/lib/contrast.ts
2406
- var CONTRAST_MIN = 0;
2407
- var CONTRAST_MAX = 100;
2408
- function normalizeContrast(value, fallback = 50) {
2409
- return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(CONTRAST_MIN, Math.min(CONTRAST_MAX, value))) : fallback;
2410
- }
2411
- function contrastTarget(tier, contrast) {
2412
- return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
2413
- }
2414
- var BISECT_STEPS = 12;
2415
- function bisect(fail, pass, passes) {
2416
- for (let i = 0; i < BISECT_STEPS; i++) {
2417
- const middle = (fail + pass) / 2;
2418
- if (passes(middle)) pass = middle;
2419
- else fail = middle;
2477
+ "8xl": {
2478
+ $value: {
2479
+ value: 96,
2480
+ unit: "px"
2481
+ },
2482
+ $type: "dimension"
2483
+ },
2484
+ "9xl": {
2485
+ $value: {
2486
+ value: 128,
2487
+ unit: "px"
2488
+ },
2489
+ $type: "dimension"
2490
+ }
2491
+ },
2492
+ letterspacing: {
2493
+ tighter: {
2494
+ $value: {
2495
+ value: -0.800000011920929,
2496
+ unit: "px"
2497
+ },
2498
+ $type: "dimension"
2499
+ },
2500
+ tight: {
2501
+ $value: {
2502
+ value: -0.4000000059604645,
2503
+ unit: "px"
2504
+ },
2505
+ $type: "dimension"
2506
+ },
2507
+ normal: {
2508
+ $value: {
2509
+ value: 0,
2510
+ unit: "px"
2511
+ },
2512
+ $type: "dimension"
2513
+ },
2514
+ wide: {
2515
+ $value: {
2516
+ value: 0.4000000059604645,
2517
+ unit: "px"
2518
+ },
2519
+ $type: "dimension"
2520
+ },
2521
+ wider: {
2522
+ $value: {
2523
+ value: 0.800000011920929,
2524
+ unit: "px"
2525
+ },
2526
+ $type: "dimension"
2527
+ },
2528
+ widest: {
2529
+ $value: {
2530
+ value: 1.600000023841858,
2531
+ unit: "px"
2532
+ },
2533
+ $type: "dimension"
2534
+ }
2420
2535
  }
2421
- return pass;
2422
- }
2423
- var token = (map, name) => {
2424
- const value = map[`--nx-color-${name}`];
2425
- if (value === void 0) throw new Error(`contrast: missing ${name}`);
2426
- return value;
2427
2536
  };
2428
- function pairBackground(map, pair) {
2429
- const backdrop = pair.backdrop ? resolveToSrgbInts(
2430
- pair.backdrop.startsWith("#") ? pair.backdrop : token(map, pair.backdrop)
2431
- ) : void 0;
2432
- return resolveToSrgbInts(token(map, pair.bg), backdrop);
2433
- }
2434
- function contrastForPair(map, pair) {
2435
- const background = pairBackground(map, pair);
2436
- return Math.abs(
2437
- APCAcontrast3(
2438
- sRGBtoY3(resolveToSrgbInts(token(map, pair.fg), background)),
2439
- sRGBtoY3(background)
2440
- )
2441
- );
2442
- }
2443
- var luminance = (color) => sRGBtoY3(resolveToSrgbInts(color));
2444
- var score = (foregroundY, backgroundY) => Math.abs(APCAcontrast3(foregroundY, backgroundY));
2445
- function constraintsFor(map, pairs, contrast, endpointY) {
2446
- const constraints = [];
2447
- for (const pair of pairs) {
2448
- const backgroundY = sRGBtoY3(pairBackground(map, pair));
2449
- const reachable = score(endpointY, backgroundY);
2450
- if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
2451
- const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
2452
- constraints.push({ backgroundY, target: Math.min(target, reachable) });
2453
- }
2454
- return constraints;
2455
- }
2456
- var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
2457
- function solveForeground(seed, constraints, endpoint, keepSeed) {
2458
- const passes = (color) => {
2459
- const y = luminance(color);
2460
- return constraints.every((c) => score(y, c.backgroundY) >= c.target);
2461
- };
2462
- if (keepSeed && passes(seed)) return seed;
2463
- const parsed = seedOklch(seed);
2464
- const at = (l) => formatOklch(clampChroma5({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
2465
- return at(
2466
- bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
2467
- );
2468
- }
2469
- var SOLVE_GROUPS = /* @__PURE__ */ new Map();
2470
- for (const pair of APCA_PAIRS) {
2471
- const key = pair.solveAs ?? pair.fg;
2472
- const group = SOLVE_GROUPS.get(key);
2473
- if (!group) {
2474
- SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
2475
- continue;
2476
- }
2477
- if (group.kind !== pair.kind)
2478
- throw new Error(
2479
- `contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
2480
- );
2481
- group.pairs.push(pair);
2482
- }
2483
- function constrainFamilyFills(map, name, pairs) {
2484
- const basePair = pairs[0];
2485
- if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
2486
- const baseY = luminance(token(map, basePair.bg));
2487
- const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
2488
- map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
2489
- for (const pair of pairs) {
2490
- const floor = TIER_THRESHOLDS[pair.tier];
2491
- const value = token(map, pair.bg);
2492
- if (score(endpoint, luminance(value)) >= floor) continue;
2493
- const fill = seedOklch(value);
2494
- const at = (l) => formatOklch(clampChroma5({ ...fill, l }, "oklch", "p3"));
2495
- const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
2496
- map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
2497
- }
2498
- }
2499
- function constrainColors(map, mode, contrast) {
2500
- for (const [name, { kind, pairs }] of SOLVE_GROUPS)
2501
- if (kind === "label") constrainFamilyFills(map, name, pairs);
2502
- const endpoint = mode === "dark" ? 1 : 0;
2503
- const endpointY = luminance(`oklch(${endpoint} 0 0)`);
2504
- for (const [name, { kind, pairs }] of SOLVE_GROUPS) {
2505
- if (kind === "label") continue;
2506
- const constraints = constraintsFor(map, pairs, contrast, endpointY);
2507
- if (constraints === void 0)
2508
- throw new Error(`contrast: no readable ${name} in ${mode}`);
2509
- const solved = solveForeground(
2510
- token(map, name),
2511
- constraints,
2512
- endpoint,
2513
- keepsTextSeed(mode, kind)
2514
- );
2515
- for (const fg of new Set(pairs.map((pair) => pair.fg).concat(name)))
2516
- map[`--nx-color-${fg}`] = solved;
2517
- }
2518
- return map;
2519
- }
2520
2537
 
2521
- // src/lib/runtime-layer.ts
2522
- var RUNTIME_LAYER_ORDER = "@layer properties, theme, base, components, utilities, nx-runtime;";
2523
- function inRuntimeLayer(css) {
2524
- return `${RUNTIME_LAYER_ORDER}
2525
- @layer nx-runtime {
2526
- ${css}
2538
+ // src/lib/typography-scale.ts
2539
+ var TYPOGRAPHY_BASE_PX = 14;
2540
+ function formatPx(value) {
2541
+ return `${Number(value.toFixed(4))}px`;
2527
2542
  }
2528
- `;
2543
+ var CODE_SIZE = "code";
2544
+ function typographyScale(uiPx, codePx) {
2545
+ const scale = uiPx / TYPOGRAPHY_BASE_PX;
2546
+ return new Map([
2547
+ ...Object.entries(typography_default_default.size).map(
2548
+ ([name, token2]) => [
2549
+ `--nx-typography-size-${name}`,
2550
+ formatPx(name === CODE_SIZE ? codePx : token2.$value.value * scale)
2551
+ ]
2552
+ ),
2553
+ ...Object.entries(typography_default_default["line-height"]).map(
2554
+ ([name, token2]) => [
2555
+ `--nx-typography-line-height-${name}`,
2556
+ formatPx(token2.$value.value * scale)
2557
+ ]
2558
+ )
2559
+ ]);
2529
2560
  }
2530
2561
 
2531
2562
  // src/lib/appearance-model.ts
@@ -2600,7 +2631,7 @@ var DEFAULT_NXDS_APPEARANCE = {
2600
2631
  uiFont: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
2601
2632
  headingFont: null,
2602
2633
  codeFont: 'ui-monospace, "SF Mono", Menlo, monospace',
2603
- uiFontSize: 14,
2634
+ uiFontSize: TYPOGRAPHY_BASE_PX,
2604
2635
  codeFontSize: 12,
2605
2636
  reduceMotion: false,
2606
2637
  pointerCursors: false,
@@ -2635,18 +2666,8 @@ var fontFamilyOr = (value, fallback) => typeof value === "string" && value.lengt
2635
2666
  var boolOr = (value, fallback) => typeof value === "boolean" ? value : fallback;
2636
2667
  var enumOr = (value, values, fallback) => typeof value === "string" && values.has(value) ? value : fallback;
2637
2668
  var clampFontSize = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(FONT_SIZE_PX_MAX, Math.max(FONT_SIZE_PX_MIN, value)) : fallback;
2638
- function formatPx(value) {
2639
- return `${Number(value.toFixed(4))}px`;
2640
- }
2641
- function typographyScaleVariables(uiPx) {
2642
- const scale = uiPx / DEFAULT_NXDS_APPEARANCE.prefs.uiFontSize;
2643
- const sizeVars = Object.entries(typography_default_default.size).map(
2644
- ([name, token2]) => ` --nx-typography-size-${name}: ${formatPx(token2.$value.value * scale)};`
2645
- );
2646
- const lineHeightVars = Object.entries(typography_default_default["line-height"]).map(
2647
- ([name, token2]) => ` --nx-typography-line-height-${name}: ${formatPx(token2.$value.value * scale)};`
2648
- );
2649
- return [...sizeVars, ...lineHeightVars].join("\n");
2669
+ function typographyScaleVariables(uiPx, codePx) {
2670
+ return [...typographyScale(uiPx, codePx)].map(([name, value]) => ` ${name}: ${value};`).join("\n");
2650
2671
  }
2651
2672
  var PUBLIC_MODE_RENAME = {
2652
2673
  density: {
@@ -2734,9 +2755,8 @@ function appearancePrefsToCss(prefs) {
2734
2755
  --nx-typography-family-font-sans: ${prefs.uiFont};
2735
2756
  --nx-typography-family-font-heading: ${prefs.headingFont ?? "var(--nx-typography-family-font-sans)"};
2736
2757
  --nx-typography-family-font-mono: ${prefs.codeFont};
2737
- ${typographyScaleVariables(uiPx)}
2738
- }`),
2739
- `.nx\\:font-mono, .nx\\:typography-code-block, .nx\\:typography-code-inline { font-size: ${codePx}px; }`
2758
+ ${typographyScaleVariables(uiPx, codePx)}
2759
+ }`)
2740
2760
  ];
2741
2761
  if (prefs.fontSmoothing) {
2742
2762
  blocks.push(