@likec4/core 1.10.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  const types_index = require('./shared/core.Db3ntVII.cjs');
4
4
 
5
+ const { min: min$4, max: max$4 } = Math;
6
+
5
7
  const limit = (x, low = 0, high = 1) => {
6
- return min$3(max$3(low, x), high);
8
+ return min$4(max$4(low, x), high);
7
9
  };
8
10
 
9
11
  const clip_rgb = (rgb) => {
@@ -124,7 +126,7 @@ class Color {
124
126
  }
125
127
 
126
128
  // this gets updated automatically
127
- const version = '3.0.0';
129
+ const version = '3.1.1';
128
130
 
129
131
  const chroma = (...args) => {
130
132
  return new Color(...args);
@@ -2605,6 +2607,72 @@ const contrast = (a, b) => {
2605
2607
  return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
2606
2608
  };
2607
2609
 
2610
+ /**
2611
+ * @license
2612
+ *
2613
+ * The APCA contrast prediction algorithm is based of the formulas published
2614
+ * in the APCA-1.0.98G specification by Myndex. The specification is available at:
2615
+ * https://raw.githubusercontent.com/Myndex/apca-w3/master/images/APCAw3_0.1.17_APCA0.0.98G.svg
2616
+ *
2617
+ * Note that the APCA implementation is still beta, so please update to
2618
+ * future versions of chroma.js when they become available.
2619
+ *
2620
+ * You can read more about the APCA Readability Criterion at
2621
+ * https://readtech.org/ARC/
2622
+ */
2623
+
2624
+ // constants
2625
+ const W_offset = 0.027;
2626
+ const P_in = 0.0005;
2627
+ const P_out = 0.1;
2628
+ const R_scale = 1.14;
2629
+ const B_threshold = 0.022;
2630
+ const B_exp = 1.414;
2631
+
2632
+ const contrastAPCA = (text, bg) => {
2633
+ // parse input colors
2634
+ text = new Color(text);
2635
+ bg = new Color(bg);
2636
+ // if text color has alpha, blend against background
2637
+ if (text.alpha() < 1) {
2638
+ text = mix(bg, text, text.alpha(), 'rgb');
2639
+ }
2640
+ const l_text = lum(...text.rgb());
2641
+ const l_bg = lum(...bg.rgb());
2642
+
2643
+ // soft clamp black levels
2644
+ const Y_text =
2645
+ l_text >= B_threshold
2646
+ ? l_text
2647
+ : l_text + Math.pow(B_threshold - l_text, B_exp);
2648
+ const Y_bg =
2649
+ l_bg >= B_threshold ? l_bg : l_bg + Math.pow(B_threshold - l_bg, B_exp);
2650
+
2651
+ // normal polarity (dark text on light background)
2652
+ const S_norm = Math.pow(Y_bg, 0.56) - Math.pow(Y_text, 0.57);
2653
+ // reverse polarity (light text on dark background)
2654
+ const S_rev = Math.pow(Y_bg, 0.65) - Math.pow(Y_text, 0.62);
2655
+ // clamp noise then scale
2656
+ const C =
2657
+ Math.abs(Y_bg - Y_text) < P_in
2658
+ ? 0
2659
+ : Y_text < Y_bg
2660
+ ? S_norm * R_scale
2661
+ : S_rev * R_scale;
2662
+ // clamp minimum contrast then offset
2663
+ const S_apc = Math.abs(C) < P_out ? 0 : C > 0 ? C - W_offset : C + W_offset;
2664
+ // scale to 100
2665
+ return S_apc * 100;
2666
+ };
2667
+
2668
+ function lum(r, g, b) {
2669
+ return (
2670
+ 0.2126729 * Math.pow(r / 255, 2.4) +
2671
+ 0.7151522 * Math.pow(g / 255, 2.4) +
2672
+ 0.072175 * Math.pow(b / 255, 2.4)
2673
+ );
2674
+ }
2675
+
2608
2676
  const { sqrt, pow, min, max: max$1, atan2, abs, cos, sin, exp, PI } = Math;
2609
2677
 
2610
2678
  function deltaE (a, b, Kl = 1, Kc = 1, Kh = 1) {
@@ -2767,10 +2835,24 @@ const colorbrewer = {
2767
2835
  Pastel1: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2']
2768
2836
  };
2769
2837
 
2770
- // add lowercase aliases for case-insensitive matches
2771
- for (let key of Object.keys(colorbrewer)) {
2772
- colorbrewer[key.toLowerCase()] = colorbrewer[key];
2773
- }
2838
+ const colorbrewerTypes = Object.keys(colorbrewer);
2839
+ const typeMap = new Map(colorbrewerTypes.map((key) => [key.toLowerCase(), key]));
2840
+
2841
+ // use Proxy to allow case-insensitive access to palettes
2842
+ const colorbrewerProxy =
2843
+ typeof Proxy === 'function'
2844
+ ? new Proxy(colorbrewer, {
2845
+ get(target, prop) {
2846
+ const lower = prop.toLowerCase();
2847
+ if (typeMap.has(lower)) {
2848
+ return target[typeMap.get(lower)];
2849
+ }
2850
+ },
2851
+ getOwnPropertyNames() {
2852
+ return Object.getOwnPropertyNames(colorbrewerTypes);
2853
+ }
2854
+ })
2855
+ : colorbrewer;
2774
2856
 
2775
2857
  const cmyk2rgb = (...args) => {
2776
2858
  args = unpack(args, 'cmyk');
@@ -2875,7 +2957,7 @@ const lch2css = (...args) => {
2875
2957
  let mode = last(args) || 'lab';
2876
2958
  lcha[0] = rnd2(lcha[0]) + '%';
2877
2959
  lcha[1] = rnd2(lcha[1]);
2878
- lcha[2] = rnd2(lcha[2]) + 'deg'; // add deg unit to hue
2960
+ lcha[2] = isNaN(lcha[2]) ? 'none' : rnd2(lcha[2]) + 'deg'; // add deg unit to hue
2879
2961
  if (mode === 'lcha' || (lcha.length > 3 && lcha[3] < 1)) {
2880
2962
  lcha[3] = '/ ' + (lcha.length > 3 ? lcha[3] : 1);
2881
2963
  } else {
@@ -2884,7 +2966,7 @@ const lch2css = (...args) => {
2884
2966
  return `lch(${lcha.join(' ')})`;
2885
2967
  };
2886
2968
 
2887
- const oklab2css$1 = (...args) => {
2969
+ const oklab2css = (...args) => {
2888
2970
  const laba = unpack(args, 'lab');
2889
2971
  laba[0] = rnd2(laba[0] * 100) + '%';
2890
2972
  laba[1] = rnd3(laba[1]);
@@ -2904,17 +2986,17 @@ const rgb2oklch = (...args) => {
2904
2986
  return [L, c, h, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
2905
2987
  };
2906
2988
 
2907
- const oklab2css = (...args) => {
2908
- const laba = unpack(args, 'lab');
2909
- laba[0] = rnd2(laba[0] * 100) + '%';
2910
- laba[1] = rnd3(laba[1]);
2911
- laba[2] = rnd2(laba[2]) + 'deg';
2912
- if (laba.length > 3 && laba[3] < 1) {
2913
- laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1);
2989
+ const oklch2css = (...args) => {
2990
+ const lcha = unpack(args, 'lch');
2991
+ lcha[0] = rnd2(lcha[0] * 100) + '%';
2992
+ lcha[1] = rnd3(lcha[1]);
2993
+ lcha[2] = isNaN(lcha[2]) ? 'none' : rnd2(lcha[2]) + 'deg'; // add deg unit to hue
2994
+ if (lcha.length > 3 && lcha[3] < 1) {
2995
+ lcha[3] = '/ ' + (lcha.length > 3 ? lcha[3] : 1);
2914
2996
  } else {
2915
- laba.length = 3;
2997
+ lcha.length = 3;
2916
2998
  }
2917
- return `oklch(${laba.join(' ')})`;
2999
+ return `oklch(${lcha.join(' ')})`;
2918
3000
  };
2919
3001
 
2920
3002
  const { round: round$2 } = Math;
@@ -2950,10 +3032,10 @@ const rgb2css = (...args) => {
2950
3032
  return cssColor;
2951
3033
  }
2952
3034
  if (mode.substr(0, 5) === 'oklab') {
2953
- return oklab2css$1(rgb2oklab(rgba));
3035
+ return oklab2css(rgb2oklab(rgba));
2954
3036
  }
2955
3037
  if (mode.substr(0, 5) === 'oklch') {
2956
- return oklab2css(rgb2oklch(rgba));
3038
+ return oklch2css(rgb2oklch(rgba));
2957
3039
  }
2958
3040
  rgba[0] = round$2(rgba[0]);
2959
3041
  rgba[1] = round$2(rgba[1]);
@@ -2973,42 +3055,75 @@ const oklch2rgb = (...args) => {
2973
3055
  return [r, g, b, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
2974
3056
  };
2975
3057
 
2976
- const RE_RGB = /^rgb\(\s*(-?\d+) \s*(-?\d+)\s* \s*(-?\d+)\s*\)$/;
2977
- const RE_RGB_LEGACY = /^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/;
2978
-
2979
- const RE_RGBA =
2980
- /^rgba?\(\s*(-?\d+) \s*(-?\d+)\s* \s*(-?\d+)\s*\/\s*([01]|[01]?\.\d+)\)$/;
2981
- const RE_RGBA_LEGACY =
2982
- /^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/;
2983
-
2984
- const RE_RGB_PCT =
2985
- /^rgb\(\s*(-?\d+(?:\.\d+)?)% \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2986
- const RE_RGB_PCT_LEGACY =
2987
- /^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2988
-
2989
- const RE_RGBA_PCT =
2990
- /^rgba?\(\s*(-?\d+(?:\.\d+)?)% \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\/\s*([01]|[01]?\.\d+)\)$/;
2991
- const RE_RGBA_PCT_LEGACY =
2992
- /^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/;
2993
-
2994
- const RE_HSL =
2995
- /^hsl\(\s*(-?\d+(?:\.\d+)?)deg \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2996
- const RE_HSL_LEGACY =
2997
- /^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/;
3058
+ const INT_OR_PCT = /((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source;
3059
+ const FLOAT_OR_PCT = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source;
3060
+ const PCT = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source;
3061
+ const RE_S = /\s*/.source;
3062
+ const SEP = /\s+/.source;
3063
+ const COMMA = /\s*,\s*/.source;
3064
+ const ANLGE = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source;
3065
+ const ALPHA = /\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source;
3066
+
3067
+ // e.g. rgb(250 20 0), rgb(100% 50% 20%), rgb(100% 50% 20% / 0.5)
3068
+ const RE_RGB = new RegExp(
3069
+ '^rgba?\\(' +
3070
+ RE_S +
3071
+ [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT].join(SEP) +
3072
+ ALPHA +
3073
+ '\\)$'
3074
+ );
3075
+ const RE_RGB_LEGACY = new RegExp(
3076
+ '^rgb\\(' +
3077
+ RE_S +
3078
+ [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT].join(COMMA) +
3079
+ RE_S +
3080
+ '\\)$'
3081
+ );
3082
+ const RE_RGBA_LEGACY = new RegExp(
3083
+ '^rgba\\(' +
3084
+ RE_S +
3085
+ [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT, FLOAT_OR_PCT].join(COMMA) +
3086
+ RE_S +
3087
+ '\\)$'
3088
+ );
2998
3089
 
2999
- const RE_HSLA =
3000
- /^hsla?\(\s*(-?\d+(?:\.\d+)?)deg \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\/\s*([01]|[01]?\.\d+)\)$/;
3090
+ const RE_HSL = new RegExp(
3091
+ '^hsla?\\(' + RE_S + [ANLGE, PCT, PCT].join(SEP) + ALPHA + '\\)$'
3092
+ );
3093
+ const RE_HSL_LEGACY = new RegExp(
3094
+ '^hsl?\\(' + RE_S + [ANLGE, PCT, PCT].join(COMMA) + RE_S + '\\)$'
3095
+ );
3001
3096
  const RE_HSLA_LEGACY =
3002
3097
  /^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/;
3003
3098
 
3004
- const RE_LAB =
3005
- /^lab\(\s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3006
- const RE_LCH =
3007
- /^lch\(\s*(-?\d+(?:\.\d+)?%?) \s*((?:-?\d+(?:\.\d+)?%?)|none) \s*(-?\d+(?:\.\d+)?(?:deg)?|none)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3008
- const RE_OKLAB =
3009
- /^oklab\(\s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3010
- const RE_OKLCH =
3011
- /^oklch\(\s*(-?\d+(?:\.\d+)?%?) \s*(?:(-?\d+(?:\.\d+)?%?)|none) \s*(-?\d+(?:\.\d+)?(?:deg)?|none)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3099
+ const RE_LAB = new RegExp(
3100
+ '^lab\\(' +
3101
+ RE_S +
3102
+ [FLOAT_OR_PCT, FLOAT_OR_PCT, FLOAT_OR_PCT].join(SEP) +
3103
+ ALPHA +
3104
+ '\\)$'
3105
+ );
3106
+ const RE_LCH = new RegExp(
3107
+ '^lch\\(' +
3108
+ RE_S +
3109
+ [FLOAT_OR_PCT, FLOAT_OR_PCT, ANLGE].join(SEP) +
3110
+ ALPHA +
3111
+ '\\)$'
3112
+ );
3113
+ const RE_OKLAB = new RegExp(
3114
+ '^oklab\\(' +
3115
+ RE_S +
3116
+ [FLOAT_OR_PCT, FLOAT_OR_PCT, FLOAT_OR_PCT].join(SEP) +
3117
+ ALPHA +
3118
+ '\\)$'
3119
+ );
3120
+ const RE_OKLCH = new RegExp(
3121
+ '^oklch\\(' +
3122
+ RE_S +
3123
+ [FLOAT_OR_PCT, FLOAT_OR_PCT, ANLGE].join(SEP) +
3124
+ ALPHA +
3125
+ '\\)$'
3126
+ );
3012
3127
 
3013
3128
  const { round: round$1 } = Math;
3014
3129
 
@@ -3035,6 +3150,11 @@ const noneToValue = (v, noneValue) => {
3035
3150
 
3036
3151
  const css2rgb = (css) => {
3037
3152
  css = css.toLowerCase().trim();
3153
+
3154
+ if (css === 'transparent') {
3155
+ return [0, 0, 0, 0];
3156
+ }
3157
+
3038
3158
  let m;
3039
3159
 
3040
3160
  if (input.format.named) {
@@ -3046,58 +3166,39 @@ const css2rgb = (css) => {
3046
3166
 
3047
3167
  // rgb(250 20 0) or rgb(250,20,0)
3048
3168
  if ((m = css.match(RE_RGB)) || (m = css.match(RE_RGB_LEGACY))) {
3049
- const rgb = m.slice(1, 4);
3169
+ let rgb = m.slice(1, 4);
3050
3170
  for (let i = 0; i < 3; i++) {
3051
- rgb[i] = +rgb[i];
3171
+ rgb[i] = +percentToAbsolute(noneToValue(rgb[i], 0), 0, 255);
3052
3172
  }
3053
- rgb[3] = 1; // default alpha
3173
+ rgb = roundRGB(rgb);
3174
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3175
+ rgb[3] = alpha; // default alpha
3054
3176
  return rgb;
3055
3177
  }
3056
3178
 
3057
3179
  // rgba(250,20,0,0.4)
3058
- if ((m = css.match(RE_RGBA)) || (m = css.match(RE_RGBA_LEGACY))) {
3180
+ if ((m = css.match(RE_RGBA_LEGACY))) {
3059
3181
  const rgb = m.slice(1, 5);
3060
3182
  for (let i = 0; i < 4; i++) {
3061
- rgb[i] = +rgb[i];
3183
+ rgb[i] = +percentToAbsolute(rgb[i], 0, 255);
3062
3184
  }
3063
3185
  return rgb;
3064
3186
  }
3065
3187
 
3066
- // rgb(100%,0%,0%)
3067
- if ((m = css.match(RE_RGB_PCT)) || (m = css.match(RE_RGB_PCT_LEGACY))) {
3068
- const rgb = m.slice(1, 4);
3069
- for (let i = 0; i < 3; i++) {
3070
- rgb[i] = round$1(rgb[i] * 2.55);
3071
- }
3072
- rgb[3] = 1; // default alpha
3073
- return rgb;
3074
- }
3075
-
3076
- // rgba(100%,0%,0%,0.4)
3077
- if ((m = css.match(RE_RGBA_PCT)) || (m = css.match(RE_RGBA_PCT_LEGACY))) {
3078
- const rgb = m.slice(1, 5);
3079
- for (let i = 0; i < 3; i++) {
3080
- rgb[i] = round$1(rgb[i] * 2.55);
3081
- }
3082
- rgb[3] = +rgb[3];
3083
- return rgb;
3084
- }
3085
-
3086
3188
  // hsl(0,100%,50%)
3087
3189
  if ((m = css.match(RE_HSL)) || (m = css.match(RE_HSL_LEGACY))) {
3088
3190
  const hsl = m.slice(1, 4);
3089
- hsl[1] *= 0.01;
3090
- hsl[2] *= 0.01;
3091
- const rgb = hsl2rgb(hsl);
3092
- for (let i = 0; i < 3; i++) {
3093
- rgb[i] = round$1(rgb[i]);
3094
- }
3095
- rgb[3] = 1;
3191
+ hsl[0] = +noneToValue(hsl[0].replace('deg', ''), 0);
3192
+ hsl[1] = +percentToAbsolute(noneToValue(hsl[1], 0), 0, 100) * 0.01;
3193
+ hsl[2] = +percentToAbsolute(noneToValue(hsl[2], 0), 0, 100) * 0.01;
3194
+ const rgb = roundRGB(hsl2rgb(hsl));
3195
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3196
+ rgb[3] = alpha;
3096
3197
  return rgb;
3097
3198
  }
3098
3199
 
3099
3200
  // hsla(0,100%,50%,0.5)
3100
- if ((m = css.match(RE_HSLA)) || (m = css.match(RE_HSLA_LEGACY))) {
3201
+ if ((m = css.match(RE_HSLA_LEGACY))) {
3101
3202
  const hsl = m.slice(1, 4);
3102
3203
  hsl[1] *= 0.01;
3103
3204
  hsl[2] *= 0.01;
@@ -3111,16 +3212,17 @@ const css2rgb = (css) => {
3111
3212
 
3112
3213
  if ((m = css.match(RE_LAB))) {
3113
3214
  const lab = m.slice(1, 4);
3114
- lab[0] = percentToAbsolute(lab[0], 0, 100);
3115
- lab[1] = percentToAbsolute(lab[1], -125, 125, true);
3116
- lab[2] = percentToAbsolute(lab[2], -125, 125, true);
3215
+ lab[0] = percentToAbsolute(noneToValue(lab[0], 0), 0, 100);
3216
+ lab[1] = percentToAbsolute(noneToValue(lab[1], 0), -125, 125, true);
3217
+ lab[2] = percentToAbsolute(noneToValue(lab[2], 0), -125, 125, true);
3117
3218
  // convert to D50 Lab whitepoint
3118
3219
  const wp = getLabWhitePoint();
3119
3220
  setLabWhitePoint('d50');
3120
3221
  const rgb = roundRGB(lab2rgb(lab));
3121
3222
  // convert back to original Lab whitepoint
3122
3223
  setLabWhitePoint(wp);
3123
- rgb[3] = m[4] !== undefined ? +m[4] : 1;
3224
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3225
+ rgb[3] = alpha;
3124
3226
  return rgb;
3125
3227
  }
3126
3228
 
@@ -3135,27 +3237,30 @@ const css2rgb = (css) => {
3135
3237
  const rgb = roundRGB(lch2rgb(lch));
3136
3238
  // convert back to original Lab whitepoint
3137
3239
  setLabWhitePoint(wp);
3138
- rgb[3] = m[4] !== undefined ? +m[4] : 1;
3240
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3241
+ rgb[3] = alpha;
3139
3242
  return rgb;
3140
3243
  }
3141
3244
 
3142
3245
  if ((m = css.match(RE_OKLAB))) {
3143
3246
  const oklab = m.slice(1, 4);
3144
- oklab[0] = percentToAbsolute(oklab[0], 0, 1);
3145
- oklab[1] = percentToAbsolute(oklab[1], -0.4, 0.4, true);
3146
- oklab[2] = percentToAbsolute(oklab[2], -0.4, 0.4, true);
3247
+ oklab[0] = percentToAbsolute(noneToValue(oklab[0], 0), 0, 1);
3248
+ oklab[1] = percentToAbsolute(noneToValue(oklab[1], 0), -0.4, 0.4, true);
3249
+ oklab[2] = percentToAbsolute(noneToValue(oklab[2], 0), -0.4, 0.4, true);
3147
3250
  const rgb = roundRGB(oklab2rgb(oklab));
3148
- rgb[3] = m[4] !== undefined ? +m[4] : 1;
3251
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3252
+ rgb[3] = alpha;
3149
3253
  return rgb;
3150
3254
  }
3151
3255
 
3152
3256
  if ((m = css.match(RE_OKLCH))) {
3153
3257
  const oklch = m.slice(1, 4);
3154
- oklch[0] = percentToAbsolute(oklch[0], 0, 1);
3258
+ oklch[0] = percentToAbsolute(noneToValue(oklch[0], 0), 0, 1);
3155
3259
  oklch[1] = percentToAbsolute(noneToValue(oklch[1], 0), 0, 0.4, false);
3156
3260
  oklch[2] = +noneToValue(oklch[2].replace('deg', ''), 0);
3157
3261
  const rgb = roundRGB(oklch2rgb(oklch));
3158
- rgb[3] = m[4] !== undefined ? +m[4] : 1;
3262
+ const alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1;
3263
+ rgb[3] = alpha;
3159
3264
  return rgb;
3160
3265
  }
3161
3266
  };
@@ -3164,11 +3269,7 @@ css2rgb.test = (s) => {
3164
3269
  return (
3165
3270
  // modern
3166
3271
  RE_RGB.test(s) ||
3167
- RE_RGBA.test(s) ||
3168
- RE_RGB_PCT.test(s) ||
3169
- RE_RGBA_PCT.test(s) ||
3170
3272
  RE_HSL.test(s) ||
3171
- RE_HSLA.test(s) ||
3172
3273
  RE_LAB.test(s) ||
3173
3274
  RE_LCH.test(s) ||
3174
3275
  RE_OKLAB.test(s) ||
@@ -3176,10 +3277,9 @@ css2rgb.test = (s) => {
3176
3277
  // legacy
3177
3278
  RE_RGB_LEGACY.test(s) ||
3178
3279
  RE_RGBA_LEGACY.test(s) ||
3179
- RE_RGB_PCT_LEGACY.test(s) ||
3180
- RE_RGBA_PCT_LEGACY.test(s) ||
3181
3280
  RE_HSL_LEGACY.test(s) ||
3182
- RE_HSLA_LEGACY.test(s)
3281
+ RE_HSLA_LEGACY.test(s) ||
3282
+ s === 'transparent'
3183
3283
  );
3184
3284
  };
3185
3285
 
@@ -3345,10 +3445,11 @@ Object.assign(chroma, {
3345
3445
  average,
3346
3446
  bezier: bezier$1,
3347
3447
  blend,
3348
- brewer: colorbrewer,
3448
+ brewer: colorbrewerProxy,
3349
3449
  Color,
3350
3450
  colors: w3cx11,
3351
3451
  contrast,
3452
+ contrastAPCA,
3352
3453
  cubehelix,
3353
3454
  deltaE,
3354
3455
  distance,