@newtonedev/colors 1.1.3 → 1.1.4

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validate.test.ts"],"names":[],"mappings":""}
package/dist/config.d.ts CHANGED
@@ -17,25 +17,25 @@ export declare const DEFAULT_SCALE_STEPS = 26;
17
17
  */
18
18
  export declare const DEFAULT_HUE = 0;
19
19
  /**
20
- * Lightest step's lightness when the whites slider is at 0 (Display P3).
21
- * P3's wider gamut can reproduce near-whites that clip in sRGB.
20
+ * Maximum lightness for the lightest scale step (slider = 1).
21
+ * The brightest achievable L value.
22
22
  */
23
- export declare const MIN_LIGHTEST_L_P3 = 0.98;
23
+ export declare const MAX_LIGHT = 0.98;
24
24
  /**
25
- * Lightest step's lightness when the whites slider is at 0 (sRGB).
26
- * slider 0 L = MIN_LIGHTEST_L, slider 1 L = 1.0 (pure white).
25
+ * Minimum lightness for the lightest scale step (slider = 0).
26
+ * The scale opens from here toward MAX_LIGHT as the whites slider increases.
27
27
  */
28
- export declare const MIN_LIGHTEST_L = 0.92;
28
+ export declare const MIN_LIGHT = 0.92;
29
29
  /**
30
- * Darkest step's lightness when the darks slider is at 0 (sRGB).
31
- * slider 0 L = MAX_DARKEST_L, slider 1 L = 0.0 (pure black).
30
+ * Minimum darkness for the darkest scale step (slider = 0).
31
+ * The scale extends from here toward MAX_DARK as the darks slider increases.
32
32
  */
33
- export declare const MAX_DARKEST_L = 0.2;
33
+ export declare const MIN_DARK = 0.2;
34
34
  /**
35
- * Darkest step's lightness when the darks slider is at 0 (Display P3).
36
- * P3's wider gamut can reproduce near-blacks that clip in sRGB.
35
+ * Maximum darkness for the darkest scale step (slider = 1).
36
+ * Lower L = darker. This is the darkest achievable value.
37
37
  */
38
- export declare const MAX_DARKEST_L_P3 = 0.14;
38
+ export declare const MAX_DARK = 0.14;
39
39
  /**
40
40
  * How far global grading reaches into the scale from each end (0–1).
41
41
  * Light grading fades to zero at t = GRADING_REACH.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAI7B;;;GAGG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,aAAa,MAAO,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAIrC;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAIpC;;;;GAIG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAO7B;;;GAGG;AACH,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B;;;GAGG;AACH,eAAO,MAAM,SAAS,OAAO,CAAC;AAE9B;;;GAGG;AACH,eAAO,MAAM,QAAQ,MAAO,CAAC;AAE7B;;;GAGG;AACH,eAAO,MAAM,QAAQ,OAAO,CAAC;AAI7B;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAIpC;;;;GAIG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Srgb } from "../types.js";
2
+ /** APCA Lc magnitude threshold for large text (≥24px or ≥18.66px bold) */
3
+ export declare const APCA_THRESHOLD_LARGE_TEXT = 60;
4
+ /** APCA Lc magnitude threshold for normal/body text */
5
+ export declare const APCA_THRESHOLD_NORMAL_TEXT = 75;
6
+ /** WCAG 2.x AA contrast ratio for normal text */
7
+ export declare const WCAG_AA_NORMAL = 4.5;
8
+ /** WCAG 2.x AA contrast ratio for large text (≥18pt or ≥14pt bold) */
9
+ export declare const WCAG_AA_LARGE = 3;
10
+ export type ContrastStandard = "apca" | "wcag";
11
+ export interface ContrastCheckResult {
12
+ readonly standard: ContrastStandard;
13
+ /** Raw contrast value: APCA |Lc| magnitude or WCAG ratio */
14
+ readonly value: number;
15
+ /** Passes threshold for large text? */
16
+ readonly passesLargeText: boolean;
17
+ /** Passes threshold for normal/body text? */
18
+ readonly passesSmallText: boolean;
19
+ }
20
+ export interface ContrastValidation {
21
+ readonly apca: ContrastCheckResult;
22
+ readonly wcag: ContrastCheckResult;
23
+ /** Passes large text in BOTH standards */
24
+ readonly passesLargeText: boolean;
25
+ /** Passes normal text in BOTH standards */
26
+ readonly passesSmallText: boolean;
27
+ }
28
+ /**
29
+ * Validate APCA contrast between text and background.
30
+ * Uses |Lc| magnitude (ignores polarity) for threshold comparison.
31
+ */
32
+ export declare function validateApcaContrast(textColor: Srgb, bgColor: Srgb): ContrastCheckResult;
33
+ /**
34
+ * Validate WCAG 2.x AA contrast between two colors.
35
+ */
36
+ export declare function validateWcagContrast(textColor: Srgb, bgColor: Srgb): ContrastCheckResult;
37
+ /**
38
+ * Validate text-on-background contrast against both APCA and WCAG standards.
39
+ * Combined `passesLargeText`/`passesSmallText` are true only when BOTH standards pass.
40
+ */
41
+ export declare function validateContrast(textColor: Srgb, bgColor: Srgb): ContrastValidation;
42
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/contrast/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAMxC,0EAA0E;AAC1E,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAC5C,uDAAuD;AACvD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,iDAAiD;AACjD,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,sEAAsE;AACtE,eAAO,MAAM,aAAa,IAAI,CAAC;AAI/B,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,6CAA6C;IAC7C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,mBAAmB,CAQrB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,mBAAmB,CAQrB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,kBAAkB,CASpB"}
package/dist/index.cjs CHANGED
@@ -339,6 +339,40 @@ function apcaContrast(textColor, bgColor) {
339
339
  }
340
340
  }
341
341
 
342
+ // src/contrast/validate.ts
343
+ var APCA_THRESHOLD_LARGE_TEXT = 60;
344
+ var APCA_THRESHOLD_NORMAL_TEXT = 75;
345
+ var WCAG_AA_NORMAL = 4.5;
346
+ var WCAG_AA_LARGE = 3;
347
+ function validateApcaContrast(textColor, bgColor) {
348
+ const lc = Math.abs(apcaContrast(textColor, bgColor));
349
+ return {
350
+ standard: "apca",
351
+ value: lc,
352
+ passesLargeText: lc >= APCA_THRESHOLD_LARGE_TEXT,
353
+ passesSmallText: lc >= APCA_THRESHOLD_NORMAL_TEXT
354
+ };
355
+ }
356
+ function validateWcagContrast(textColor, bgColor) {
357
+ const ratio = wcagContrast(textColor, bgColor);
358
+ return {
359
+ standard: "wcag",
360
+ value: ratio,
361
+ passesLargeText: ratio >= WCAG_AA_LARGE,
362
+ passesSmallText: ratio >= WCAG_AA_NORMAL
363
+ };
364
+ }
365
+ function validateContrast(textColor, bgColor) {
366
+ const apca = validateApcaContrast(textColor, bgColor);
367
+ const wcag = validateWcagContrast(textColor, bgColor);
368
+ return {
369
+ apca,
370
+ wcag,
371
+ passesLargeText: apca.passesLargeText && wcag.passesLargeText,
372
+ passesSmallText: apca.passesSmallText && wcag.passesSmallText
373
+ };
374
+ }
375
+
342
376
  // src/color/interpolation.ts
343
377
  function mix(a, b, t) {
344
378
  const L = a.L + (b.L - a.L) * t;
@@ -362,10 +396,10 @@ function mix(a, b, t) {
362
396
  // src/config.ts
363
397
  var DEFAULT_SCALE_STEPS = 26;
364
398
  var DEFAULT_HUE = 0;
365
- var MIN_LIGHTEST_L_P3 = 0.98;
366
- var MIN_LIGHTEST_L = 0.92;
367
- var MAX_DARKEST_L = 0.2;
368
- var MAX_DARKEST_L_P3 = 0.14;
399
+ var MAX_LIGHT = 0.98;
400
+ var MIN_LIGHT = 0.92;
401
+ var MIN_DARK = 0.2;
402
+ var MAX_DARK = 0.14;
369
403
  var GRADING_REACH = 3 / 5;
370
404
  var MAX_GRADING_AMOUNT = 0.25;
371
405
  var GRADING_CHROMA_RATIO = 0.5;
@@ -473,12 +507,10 @@ function generateScale(options = {}) {
473
507
  const localHueGrade = shift ? buildOneSidedGrade(shift.hue, shift.amount, shift.light) : void 0;
474
508
  const ratio = Math.max(0, Math.min(1, chromaRatio));
475
509
  const peak = Math.max(0, Math.min(1, chromaPeak));
476
- const capLight = isP3 ? MIN_LIGHTEST_L_P3 : 1;
477
- const capDark = isP3 ? MAX_DARKEST_L_P3 : 0;
478
510
  const lightSlider = Math.max(0, Math.min(1, contrast?.light ?? 1));
479
511
  const darkSlider = Math.max(0, Math.min(1, contrast?.dark ?? 1));
480
- const lightestL = MIN_LIGHTEST_L + lightSlider * (capLight - MIN_LIGHTEST_L);
481
- const darkestL = MAX_DARKEST_L - darkSlider * (MAX_DARKEST_L - capDark);
512
+ const lightestL = MIN_LIGHT + lightSlider * (MAX_LIGHT - MIN_LIGHT);
513
+ const darkestL = MIN_DARK - darkSlider * (MIN_DARK - MAX_DARK);
482
514
  const hueAt = (t) => resolveGradedHue(hue, t, hueGrade, localHueGrade);
483
515
  if (peak === 0.5 || ratio === 0 || ratio >= 1) {
484
516
  const scale2 = [];
@@ -582,11 +614,11 @@ function resolveColor(input, isP3 = false) {
582
614
  // src/scale/dynamic-range.ts
583
615
  function resolveLightest(slider) {
584
616
  const s = Math.max(0, Math.min(1, slider));
585
- return MIN_LIGHTEST_L + s * (1 - MIN_LIGHTEST_L);
617
+ return MIN_LIGHT + s * (MAX_LIGHT - MIN_LIGHT);
586
618
  }
587
619
  function resolveDarkest(slider) {
588
620
  const s = Math.max(0, Math.min(1, slider));
589
- return MAX_DARKEST_L * (1 - s);
621
+ return MIN_DARK - s * (MIN_DARK - MAX_DARK);
590
622
  }
591
623
  function lightnessToScaleT(L, lightestL, darkestL) {
592
624
  const range = lightestL - darkestL;
@@ -614,18 +646,22 @@ function keyColor(color, options) {
614
646
  }
615
647
 
616
648
  exports.APCA_LC_MAX = APCA_LC_MAX;
649
+ exports.APCA_THRESHOLD_LARGE_TEXT = APCA_THRESHOLD_LARGE_TEXT;
650
+ exports.APCA_THRESHOLD_NORMAL_TEXT = APCA_THRESHOLD_NORMAL_TEXT;
617
651
  exports.DEFAULT_HUE = DEFAULT_HUE;
618
652
  exports.DEFAULT_SCALE_STEPS = DEFAULT_SCALE_STEPS;
619
653
  exports.GRADING_CHROMA_RATIO = GRADING_CHROMA_RATIO;
620
654
  exports.GRADING_REACH = GRADING_REACH;
621
- exports.MAX_DARKEST_L = MAX_DARKEST_L;
622
- exports.MAX_DARKEST_L_P3 = MAX_DARKEST_L_P3;
655
+ exports.MAX_DARK = MAX_DARK;
623
656
  exports.MAX_GRADING_AMOUNT = MAX_GRADING_AMOUNT;
657
+ exports.MAX_LIGHT = MAX_LIGHT;
624
658
  exports.MAX_SHIFT_AMOUNT = MAX_SHIFT_AMOUNT;
625
- exports.MIN_LIGHTEST_L = MIN_LIGHTEST_L;
626
- exports.MIN_LIGHTEST_L_P3 = MIN_LIGHTEST_L_P3;
659
+ exports.MIN_DARK = MIN_DARK;
660
+ exports.MIN_LIGHT = MIN_LIGHT;
627
661
  exports.PERCEPTUAL_JND = PERCEPTUAL_JND;
628
662
  exports.SHIFT_REACH = SHIFT_REACH;
663
+ exports.WCAG_AA_LARGE = WCAG_AA_LARGE;
664
+ exports.WCAG_AA_NORMAL = WCAG_AA_NORMAL;
629
665
  exports.apcaContrast = apcaContrast;
630
666
  exports.apcaToNormalized = apcaToNormalized;
631
667
  exports.buildOneSidedGrade = buildOneSidedGrade;
@@ -660,12 +696,17 @@ exports.oklchToP3 = oklchToP3;
660
696
  exports.oklchToP3Css = oklchToP3Css;
661
697
  exports.oklchToSrgb = oklchToSrgb;
662
698
  exports.p3ToOklch = p3ToOklch;
699
+ exports.resolveDarkest = resolveDarkest;
663
700
  exports.resolveGradedHue = resolveGradedHue;
701
+ exports.resolveLightest = resolveLightest;
664
702
  exports.srgbChannelToLinear = srgbChannelToLinear;
665
703
  exports.srgbToHex = srgbToHex;
666
704
  exports.srgbToLinearSrgb = srgbToLinearSrgb;
667
705
  exports.srgbToOklab = srgbToOklab;
668
706
  exports.srgbToOklch = srgbToOklch;
707
+ exports.validateApcaContrast = validateApcaContrast;
708
+ exports.validateContrast = validateContrast;
709
+ exports.validateWcagContrast = validateWcagContrast;
669
710
  exports.wcagContrast = wcagContrast;
670
711
  exports.wcagLuminance = wcagLuminance;
671
712
  //# sourceMappingURL=index.cjs.map