Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ color3.getAlpha(); // 0
### setAlpha

Sets the alpha value on a current color. Accepted range is in between `0-1`.
Finite values outside this range are clamped: negative values become `0`
(fully transparent), and values above `1` become `1` (fully opaque).
Non-numeric values and infinities default to `1`. The same rules apply to alpha
values in color strings and objects.
```js
var color = tinycolor("red");
color.getAlpha(); // 1
Expand Down
2 changes: 1 addition & 1 deletion dist/tinycolor-min.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions mod.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,12 +1054,14 @@ function flip(o) {
return flipped;
}

// Return a valid alpha value [0,1] with all invalid values being set to 1
// Clamp finite alpha values to [0,1], defaulting invalid values to 1
function boundAlpha(a) {
a = parseFloat(a);

if (isNaN(a) || a < 0 || a > 1) {
if (!isFinite(a) || a > 1) {
a = 1;
} else if (a < 0) {
a = 0;
}

return a;
Expand Down
4 changes: 4 additions & 0 deletions npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ color3.getAlpha(); // 0
### setAlpha

Sets the alpha value on a current color. Accepted range is in between `0-1`.
Finite values outside this range are clamped: negative values become `0`
(fully transparent), and values above `1` become `1` (fully opaque).
Non-numeric values and infinities default to `1`. The same rules apply to alpha
values in color strings and objects.
```js
var color = tinycolor("red");
color.getAlpha(); // 1
Expand Down
70 changes: 64 additions & 6 deletions npm/cjs/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ Deno.test("With Ratio", function () {
);
assertEquals(
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -1 }).toRgbString(),
"rgb(255, 0, 0)",
"alpha < 1 works when ratio is parsed"
"rgba(255, 0, 0, 0)",
"negative alpha is clamped to 0 when ratio is parsed"
);
});

Expand Down Expand Up @@ -709,10 +709,10 @@ Deno.test("Named colors", function () {
assertEquals(tinycolor("#fa0a0a").toName(), false);
});

Deno.test("Invalid alpha should normalize to 1", function () {
Deno.test("Alpha is clamped with invalid values defaulting to 1", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: -1 }).toRgbString(),
"rgb(255, 20, 10)",
"rgba(255, 20, 10, 0)",
"Negative value"
);
assertEquals(
Expand Down Expand Up @@ -865,8 +865,8 @@ Deno.test("setting alpha", function () {
hexSetter.setAlpha(-1);
assertEquals(
hexSetter.getAlpha(),
1,
"setAlpha with value < 0 should be bound to 1"
0,
"setAlpha with value < 0 should be bound to 0"
);
hexSetter.setAlpha(2);
assertEquals(
Expand Down Expand Up @@ -894,6 +894,64 @@ Deno.test("setting alpha", function () {
);
});

Deno.test("Negative alpha is transparent across input formats", function () {
var inputs = [
"rgba(255, 0, 0, -0.5)",
"rgba(100%, 0%, 0%, -0.5)",
"hsla(0, 100%, 50%, -0.5)",
"hsva(0, 100%, 100%, -0.5)",
{ r: 255, g: 0, b: 0, a: -0.5 },
{ h: 0, s: 1, l: 0.5, a: -0.5 },
{ h: 0, s: 1, v: 1, a: -0.5 },
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -0.5 }),
tinycolor("red").setAlpha(-0.5),
];
inputs.forEach(function (input) {
var color = tinycolor(input);
assert(color.isValid());
assertEquals(color.getAlpha(), 0);
assertEquals(color.toRgbString(), "rgba(255, 0, 0, 0)");
assertEquals(color.toHsl().a, 0);
assertEquals(color.toHsv().a, 0);
assertEquals(color.toHex8String(), "#ff000000");
assertEquals(color.toName(), "transparent");
assertEquals(color.clone().getAlpha(), 0);
assertEquals(color.lighten(10).getAlpha(), 0);
});
});

Deno.test("Alpha boundaries and invalid defaults", function () {
var cases = [
[-Number.MAX_VALUE, 0],
[-Number.MIN_VALUE, 0],
["-0.5", 0],
[-0, 0],
[0, 0],
[Number.MIN_VALUE, Number.MIN_VALUE],
[0.5, 0.5],
["0.5", 0.5],
[1, 1],
[Number.MAX_VALUE, 1],
[NaN, 1],
[Infinity, 1],
[-Infinity, 1],
["Infinity", 1],
["-Infinity", 1],
["not a number", 1],
["", 1],
[null, 1],
[undefined, 1],
];
cases.forEach(function (testCase) {
var input = testCase[0];
var expected = testCase[1];
var color = tinycolor("red");
assertEquals(color.setAlpha(input), color);
assertEquals(color.getAlpha(), expected);
assertEquals(tinycolor({ r: 255, g: 0, b: 0, a: input }).getAlpha(), expected);
});
});

Deno.test("Alpha = 0 should act differently on toName()", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: 0 }).toName(),
Expand Down
6 changes: 4 additions & 2 deletions npm/cjs/tinycolor.js
Original file line number Diff line number Diff line change
Expand Up @@ -948,11 +948,13 @@
return flipped;
}

// Return a valid alpha value [0,1] with all invalid values being set to 1
// Clamp finite alpha values to [0,1], defaulting invalid values to 1
function boundAlpha(a) {
a = parseFloat(a);
if (isNaN(a) || a < 0 || a > 1) {
if (!isFinite(a) || a > 1) {
a = 1;
} else if (a < 0) {
a = 0;
}
return a;
}
Expand Down
2 changes: 1 addition & 1 deletion npm/dist/tinycolor-min.js

Large diffs are not rendered by default.

70 changes: 64 additions & 6 deletions npm/esm/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ Deno.test("With Ratio", function () {
);
assertEquals(
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -1 }).toRgbString(),
"rgb(255, 0, 0)",
"alpha < 1 works when ratio is parsed"
"rgba(255, 0, 0, 0)",
"negative alpha is clamped to 0 when ratio is parsed"
);
});

Expand Down Expand Up @@ -708,10 +708,10 @@ Deno.test("Named colors", function () {
assertEquals(tinycolor("#fa0a0a").toName(), false);
});

Deno.test("Invalid alpha should normalize to 1", function () {
Deno.test("Alpha is clamped with invalid values defaulting to 1", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: -1 }).toRgbString(),
"rgb(255, 20, 10)",
"rgba(255, 20, 10, 0)",
"Negative value"
);
assertEquals(
Expand Down Expand Up @@ -864,8 +864,8 @@ Deno.test("setting alpha", function () {
hexSetter.setAlpha(-1);
assertEquals(
hexSetter.getAlpha(),
1,
"setAlpha with value < 0 should be bound to 1"
0,
"setAlpha with value < 0 should be bound to 0"
);
hexSetter.setAlpha(2);
assertEquals(
Expand Down Expand Up @@ -893,6 +893,64 @@ Deno.test("setting alpha", function () {
);
});

Deno.test("Negative alpha is transparent across input formats", function () {
var inputs = [
"rgba(255, 0, 0, -0.5)",
"rgba(100%, 0%, 0%, -0.5)",
"hsla(0, 100%, 50%, -0.5)",
"hsva(0, 100%, 100%, -0.5)",
{ r: 255, g: 0, b: 0, a: -0.5 },
{ h: 0, s: 1, l: 0.5, a: -0.5 },
{ h: 0, s: 1, v: 1, a: -0.5 },
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -0.5 }),
tinycolor("red").setAlpha(-0.5),
];
inputs.forEach(function (input) {
var color = tinycolor(input);
assert(color.isValid());
assertEquals(color.getAlpha(), 0);
assertEquals(color.toRgbString(), "rgba(255, 0, 0, 0)");
assertEquals(color.toHsl().a, 0);
assertEquals(color.toHsv().a, 0);
assertEquals(color.toHex8String(), "#ff000000");
assertEquals(color.toName(), "transparent");
assertEquals(color.clone().getAlpha(), 0);
assertEquals(color.lighten(10).getAlpha(), 0);
});
});

Deno.test("Alpha boundaries and invalid defaults", function () {
var cases = [
[-Number.MAX_VALUE, 0],
[-Number.MIN_VALUE, 0],
["-0.5", 0],
[-0, 0],
[0, 0],
[Number.MIN_VALUE, Number.MIN_VALUE],
[0.5, 0.5],
["0.5", 0.5],
[1, 1],
[Number.MAX_VALUE, 1],
[NaN, 1],
[Infinity, 1],
[-Infinity, 1],
["Infinity", 1],
["-Infinity", 1],
["not a number", 1],
["", 1],
[null, 1],
[undefined, 1],
];
cases.forEach(function (testCase) {
var input = testCase[0];
var expected = testCase[1];
var color = tinycolor("red");
assertEquals(color.setAlpha(input), color);
assertEquals(color.getAlpha(), expected);
assertEquals(tinycolor({ r: 255, g: 0, b: 0, a: input }).getAlpha(), expected);
});
});

Deno.test("Alpha = 0 should act differently on toName()", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: 0 }).toName(),
Expand Down
6 changes: 4 additions & 2 deletions npm/esm/tinycolor.js
Original file line number Diff line number Diff line change
Expand Up @@ -942,11 +942,13 @@ function flip(o) {
return flipped;
}

// Return a valid alpha value [0,1] with all invalid values being set to 1
// Clamp finite alpha values to [0,1], defaulting invalid values to 1
function boundAlpha(a) {
a = parseFloat(a);
if (isNaN(a) || a < 0 || a > 1) {
if (!isFinite(a) || a > 1) {
a = 1;
} else if (a < 0) {
a = 0;
}
return a;
}
Expand Down
6 changes: 4 additions & 2 deletions npm/tinycolor.js
Original file line number Diff line number Diff line change
Expand Up @@ -951,11 +951,13 @@
return flipped;
}

// Return a valid alpha value [0,1] with all invalid values being set to 1
// Clamp finite alpha values to [0,1], defaulting invalid values to 1
function boundAlpha(a) {
a = parseFloat(a);
if (isNaN(a) || a < 0 || a > 1) {
if (!isFinite(a) || a > 1) {
a = 1;
} else if (a < 0) {
a = 0;
}
return a;
}
Expand Down
70 changes: 64 additions & 6 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ Deno.test("With Ratio", function () {
);
assertEquals(
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -1 }).toRgbString(),
"rgb(255, 0, 0)",
"alpha < 1 works when ratio is parsed"
"rgba(255, 0, 0, 0)",
"negative alpha is clamped to 0 when ratio is parsed"
);
});

Expand Down Expand Up @@ -695,10 +695,10 @@ Deno.test("Named colors", function () {
assertEquals(tinycolor("#fa0a0a").toName(), false);
});

Deno.test("Invalid alpha should normalize to 1", function () {
Deno.test("Alpha is clamped with invalid values defaulting to 1", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: -1 }).toRgbString(),
"rgb(255, 20, 10)",
"rgba(255, 20, 10, 0)",
"Negative value"
);
assertEquals(
Expand Down Expand Up @@ -851,8 +851,8 @@ Deno.test("setting alpha", function () {
hexSetter.setAlpha(-1);
assertEquals(
hexSetter.getAlpha(),
1,
"setAlpha with value < 0 should be bound to 1"
0,
"setAlpha with value < 0 should be bound to 0"
);
hexSetter.setAlpha(2);
assertEquals(
Expand Down Expand Up @@ -880,6 +880,64 @@ Deno.test("setting alpha", function () {
);
});

Deno.test("Negative alpha is transparent across input formats", function () {
var inputs = [
"rgba(255, 0, 0, -0.5)",
"rgba(100%, 0%, 0%, -0.5)",
"hsla(0, 100%, 50%, -0.5)",
"hsva(0, 100%, 100%, -0.5)",
{ r: 255, g: 0, b: 0, a: -0.5 },
{ h: 0, s: 1, l: 0.5, a: -0.5 },
{ h: 0, s: 1, v: 1, a: -0.5 },
tinycolor.fromRatio({ r: 1, g: 0, b: 0, a: -0.5 }),
tinycolor("red").setAlpha(-0.5),
];
inputs.forEach(function (input) {
var color = tinycolor(input);
assert(color.isValid());
assertEquals(color.getAlpha(), 0);
assertEquals(color.toRgbString(), "rgba(255, 0, 0, 0)");
assertEquals(color.toHsl().a, 0);
assertEquals(color.toHsv().a, 0);
assertEquals(color.toHex8String(), "#ff000000");
assertEquals(color.toName(), "transparent");
assertEquals(color.clone().getAlpha(), 0);
assertEquals(color.lighten(10).getAlpha(), 0);
});
});

Deno.test("Alpha boundaries and invalid defaults", function () {
var cases = [
[-Number.MAX_VALUE, 0],
[-Number.MIN_VALUE, 0],
["-0.5", 0],
[-0, 0],
[0, 0],
[Number.MIN_VALUE, Number.MIN_VALUE],
[0.5, 0.5],
["0.5", 0.5],
[1, 1],
[Number.MAX_VALUE, 1],
[NaN, 1],
[Infinity, 1],
[-Infinity, 1],
["Infinity", 1],
["-Infinity", 1],
["not a number", 1],
["", 1],
[null, 1],
[undefined, 1],
];
cases.forEach(function (testCase) {
var input = testCase[0];
var expected = testCase[1];
var color = tinycolor("red");
assertEquals(color.setAlpha(input), color);
assertEquals(color.getAlpha(), expected);
assertEquals(tinycolor({ r: 255, g: 0, b: 0, a: input }).getAlpha(), expected);
});
});

Deno.test("Alpha = 0 should act differently on toName()", function () {
assertEquals(
tinycolor({ r: 255, g: 20, b: 10, a: 0 }).toName(),
Expand Down
Loading