diff --git a/app/src/scss/_functions-override.scss b/app/src/scss/_functions-override.scss new file mode 100644 index 00000000..bf9f5793 --- /dev/null +++ b/app/src/scss/_functions-override.scss @@ -0,0 +1,245 @@ +// Taken from https://gist.github.com/johanlef/518a511b2b2f6b96c4f429b3af2f169a +// Those functions overrides built-in bootstrap's computation color functions (that +// generate flat variants and its darken/lighten alterations) to allow `var(--color)` CSS +// variables to be used as primary colors and be instead computed on the fly with `calc()`s + +@function is-color($color) { + @if (type-of($color) == color) { + @return true; + } + @return false; +} + +@function count-occurrences($string, $search) { + $searchIndex: str-index($string, $search); + $searchCount: 0; + @while $searchIndex { + $searchCount: $searchCount + 1; + $string: str-slice($string, $searchIndex + 1); + $searchIndex: str-index($string, $search); + } + @return $searchCount; +} + +@function str-is-between($string, $first, $last) { + $firstCount: count-occurrences($string, $first); + $lastCount: count-occurrences($string, $last); + @return $firstCount == $lastCount; +} + +@function recursive-color($color, $index: 0) { + $indices: ( + 0: h, + 1: s, + 2: l, + 3: a + ); + // find end of part + $end: str-index($color, ','); + @while ($end and not str-is-between(str-slice($color, 0, $end - 1), '(', ')')) { + $newEnd: str-index(str-slice($color, $end + 1), ','); + @if (not $newEnd) { + $newEnd: 0; + } + $end: 2 + $end + $newEnd; + } + @if ($end) { + $part: str-slice($color, 0, $end - 1); + $value: map-merge( + ( + map-get($indices, $index): $part + ), + recursive-color(str-slice($color, $end + 1), $index + 1) + ); + @return $value; + } + @return (); +} + +@function to-hsl($color) { + $c: inspect($color); + + $h: 0; + $s: 0; + $l: 0; + $a: 1; + + @if (is-color($color)) { + // std color + $h: hue($color); + $s: saturation($color); + $l: lightness($color); + $a: alpha($color); + + @return (h: $h, s: $s, l: $l, a: $a); + } + + @if (str-slice($c, 0, 3) == 'var') { + // var(--color) + $commaPos: str-index($c, ','); + $end: -2; + @if ($commaPos) { + $end: $commaPos - 1; + } + $var: str-slice($c, 7, $end); + + $h: var(--#{$var}-h); + $s: var(--#{$var}-s); + $l: var(--#{$var}-l); + $a: var(--#{$var}-a, 1); + + @return (h: $h, s: $s, l: $l, a: $a); + } + + @if ($c == '0') { + @return (h: $h, s: $s, l: $l, a: $a); + } + + // color is (maybe complex) calculated color + // e.g.: hsla(calc((var(--white-h) + var(--primary-h)) / 2), calc((var(--white-s) + var(--primary-s)) / 2), calc((var(--white-l) + var(--primary-l)) / 2), calc((var(--white-a, 1) + var(--primary-a, 1)) / 2)), hsla(calc((var(--white-h) + var(--primary-h)) / 2), calc((var(--white-s) + var(--primary-s)) / 2), calc((var(--white-l) + var(--primary-l)) / 2), calc((var(--white-a, 1) + var(--primary-a, 1)) / 2)) + $startPos: str-index($c, '('); + $c: str-slice($c, $startPos + 1, -2); // 3 or 4 comma-separated vomplex values + @return recursive-color($c); + // $hEnd: str-index($c, ','); + // @if ($hEnd) { + // $h: str-slice($c, 0, $hEnd - 1); + // $c: str-slice($c, $hEnd + 1); + // $sEnd: str-index($c, ','); + // @if ($hEnd) { + // $h: str-slice($c, 0, $hEnd - 1); + // $c: str-slice($c, $hEnd + 1); + // $sEnd: str-index($c, ','); + // } + // } + + // @return (h: $h, s: $s, l: $l, a: $a); +} + +@function render-hsla($h, $s, $l, $a: 1) { + @return hsla($h, $s, $l, $a); +} + +@function lighten($color, $amount) { + @if (is-color($color)) { + @return scale-color($color: $color, $lightness: $amount); + } + + $c: to-hsl($color); + $h: map-get($c, h); + $s: map-get($c, s); + $l: map-get($c, l); + $a: map-get($c, a); + @return render-hsla($h, $s, calc(#{$l} + #{$amount}), $a); +} + +@function darken($color, $amount) { + @return lighten($color, $amount * -1); +} + +@function rgba($red, $green, $blue: false, $alpha: false) { + $color: $red; + + @if (not $blue and not $alpha) { + $alpha: $green; + $color: $red; + } + + $c: to-hsl($color); + $h: map-get($c, h); + $s: map-get($c, s); + $l: map-get($c, l); + @return render-hsla($h, $s, $l, $alpha); +} + +@function rgb($red, $green, $blue) { + @return rgba($red, $green, $blue, 1); +} + +@function mix($color-1, $color-2, $weight: 50%) { + $c1: to-hsl($color-1); + $c2: to-hsl($color-2); + + $h1: map-get($c1, h); + $s1: map-get($c1, s); + $l1: map-get($c1, l); + $a1: map-get($c1, a); + + $h2: map-get($c2, h); + $s2: map-get($c2, s); + $l2: map-get($c2, l); + $a2: map-get($c2, a); + + $h: calc((#{$h1} + #{$h2}) / 2); + $s: calc((#{$s1} + #{$s2}) / 2); + $l: calc((#{$l1} + #{$l2}) / 2); + $a: calc((#{$a1} + #{$a2}) / 2); + + @return render-hsla($h, $s, $l, $a); +} + +@function fade-in($color, $amount) { + $c: to-hsl($color); + + $h: map-get($c, h); + $s: map-get($c, s); + $l: map-get($c, l); + $a: map-get($c, a); + @if (not $a) { + $a: 1; + } + + @return render-hsla($h, $s, $l, $a + $amount); +} + +@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) { + @if (is-color($color)) { + $r: red($color); + $g: green($color); + $b: blue($color); + + $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; + + @if ($yiq >= $yiq-contrasted-threshold) { + @return $dark; + } @else { + @return $light; + } + } @else { + $c: to-hsl($color); + $l: map-get($c, l); + + $th: $yiq-contrasted-threshold / 2.56; // convert hex to dec + $lightness: calc(-100 * calc(#{$l} - calc(#{$th} * 1%))); + + // ignoring hue and saturation, just a light or dark gray + @return render-hsla(0, 0%, $lightness, 1); + } +} + + +// Taken from https://gist.github.com/johanlef/518a511b2b2f6b96c4f429b3af2f169a?permalink_comment_id=4053335#gistcomment-4053335 +@function theme-color-level($color-name: "primary", $level: 0) { + $color: theme-color($color-name); + @if ($level == 0) { + @return $color; + } + + $amount: $theme-color-interval * abs($level) / 100%; + $c: to-hsl($color); + $h: map-get($c, h); + $s: map-get($c, s); + $l: map-get($c, l); + $a: map-get($c, a); + + @if ($level > 0) { + // Darken -X%: L = L * (1 - X) + // $rl: calc((#{$l} * #{1 - $amount})); + $rl: calc((#{$l} * #{$amount})); + @return render-hsla($h, $s, $rl, $a); + } + @if ($level < 0) { + // Ligthen +X%: L = L + X * (100 - L) + $rl: calc(#{$l} + #{$amount} * (100% - #{$l})); + @return render-hsla($h, $s, $rl, $a); + } +}