Skip to content

Commit cd6a903

Browse files
committed
Support missing channels in color.change()
1 parent 975fc86 commit cd6a903

File tree

1 file changed

+61
-37
lines changed

1 file changed

+61
-37
lines changed

lib/src/functions/color.dart

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ SassColor _updateComponents(List<Value> arguments,
717717
: _colorInSpace(originalColor, spaceKeyword ?? sassNull);
718718

719719
var oldChannels = color.channels;
720-
var channelArgs = List<SassNumber?>.filled(oldChannels.length, null);
720+
var channelArgs = List<Value?>.filled(oldChannels.length, null);
721721
var channelInfo = color.space.channels;
722722
for (var (name, value) in keywords.pairs) {
723723
var channelIndex = channelInfo.indexWhere((info) => name == info.name);
@@ -727,51 +727,75 @@ SassColor _updateComponents(List<Value> arguments,
727727
name);
728728
}
729729

730-
channelArgs[channelIndex] = value.assertNumber(name);
730+
channelArgs[channelIndex] = value;
731731
}
732732

733-
var result = change
734-
? _changeColor(color, channelArgs, alphaArg)
735-
: scale
736-
? _scaleColor(color, channelArgs, alphaArg)
737-
: _adjustColor(color, channelArgs, alphaArg);
733+
SassColor result;
734+
if (change) {
735+
result = _changeColor(color, channelArgs, alphaArg);
736+
} else {
737+
var channelNumbers = [
738+
for (var i = 0; i < channelInfo.length; i++)
739+
channelArgs[i]?.assertNumber(channelInfo[i].name)
740+
];
741+
result = scale
742+
? _scaleColor(color, channelNumbers, alphaArg)
743+
: _adjustColor(color, channelNumbers, alphaArg);
744+
}
738745

739746
return result.toSpace(originalColor.space);
740747
}
741748

742749
/// Returns a copy of [color] with its channel values replaced by those in
743750
/// [channelArgs] and [alphaArg], if specified.
744751
SassColor _changeColor(
745-
SassColor color, List<SassNumber?> channelArgs, SassNumber? alphaArg) {
746-
var latterUnits =
747-
color.space == ColorSpace.hsl || color.space == ColorSpace.hwb
748-
? '%'
749-
: null;
750-
return _colorFromChannels(
751-
color.space,
752-
channelArgs[0] ?? SassNumber(color.channel0),
753-
channelArgs[1] ?? SassNumber(color.channel1, latterUnits),
754-
channelArgs[2] ?? SassNumber(color.channel2, latterUnits),
755-
alphaArg.andThen((alphaArg) {
756-
if (!alphaArg.hasUnits) {
757-
return alphaArg.value;
758-
} else if (alphaArg.hasUnit('%')) {
759-
return alphaArg.value / 100;
760-
} else {
761-
warnForDeprecation(
762-
"\$alpha: Passing a unit other than % ($alphaArg) is "
763-
"deprecated.\n"
764-
"\n"
765-
"To preserve current behavior: "
766-
"${alphaArg.unitSuggestion('alpha')}\n"
767-
"\n"
768-
"See https://sass-lang.com/d/function-units",
769-
Deprecation.functionUnits);
770-
return alphaArg.value;
771-
}
772-
}) ??
773-
color.alpha,
774-
clamp: false);
752+
SassColor color, List<Value?> channelArgs, SassNumber? alphaArg) =>
753+
_colorFromChannels(
754+
color.space,
755+
_channelForChange(channelArgs[0], color, 0),
756+
_channelForChange(channelArgs[1], color, 1),
757+
_channelForChange(channelArgs[2], color, 2),
758+
alphaArg.andThen((alphaArg) {
759+
if (!alphaArg.hasUnits) {
760+
return alphaArg.value;
761+
} else if (alphaArg.hasUnit('%')) {
762+
return alphaArg.value / 100;
763+
} else {
764+
warnForDeprecation(
765+
"\$alpha: Passing a unit other than % ($alphaArg) is "
766+
"deprecated.\n"
767+
"\n"
768+
"To preserve current behavior: "
769+
"${alphaArg.unitSuggestion('alpha')}\n"
770+
"\n"
771+
"See https://sass-lang.com/d/function-units",
772+
Deprecation.functionUnits);
773+
return alphaArg.value;
774+
}
775+
}) ??
776+
color.alpha,
777+
clamp: false);
778+
779+
/// Returns the value for a single channel in `color.change()`.
780+
///
781+
/// The [channelArg] is the argument passed in by the user, if one exists. If no
782+
/// argument is passed, the channel at [index] in [color] is used instead.
783+
SassNumber? _channelForChange(Value? channelArg, SassColor color, int channel) {
784+
if (channelArg == null) {
785+
return switch (color.channelsOrNull[channel]) {
786+
var value? => SassNumber(
787+
value,
788+
(color.space == ColorSpace.hsl || color.space == ColorSpace.hwb) &&
789+
channel > 0
790+
? '%'
791+
: null),
792+
_ => null
793+
};
794+
}
795+
if (_isNone(channelArg)) return null;
796+
if (channelArg is SassNumber) return channelArg;
797+
throw SassScriptException('$channelArg is not a number or unquoted "none".',
798+
color.space.channels[channel].name);
775799
}
776800

777801
/// Returns a copy of [color] with its channel values scaled by the values in

0 commit comments

Comments
 (0)