diff --git a/lib/core/custom-theme/material-theme.scss b/lib/core/custom-theme/material-theme.scss new file mode 100644 index 0000000000..0878eb6bac --- /dev/null +++ b/lib/core/custom-theme/material-theme.scss @@ -0,0 +1,24 @@ +@use 'sass:map'; +@import './theme/theme-data'; + +$custom-theme: mat-light-theme( + ( + color: ( + primary: map.get($palettes, primary), + accent: map.get($palettes, accent), + warn: map.get($palettes, warning), + ), + typography: $app-typography, + ) +); + +@if $background-color { + $custom-theme: get-custom-background-color( + $background-color, + $custom-theme + ); +} + +@if $text-color { + $custom-theme: get-custom-text-color($text-color, $custom-theme); +} diff --git a/lib/core/custom-theme/theme/custom-background-color.scss b/lib/core/custom-theme/theme/custom-background-color.scss new file mode 100644 index 0000000000..4c2783daf4 --- /dev/null +++ b/lib/core/custom-theme/theme/custom-background-color.scss @@ -0,0 +1,25 @@ +@use 'sass:map'; +@use 'sass:color'; + +@function get-custom-background-color($background-color, $theme) { + $background: map.get($theme, background); + $card: map.get($background, card); + + $new-card-color: color.adjust($background-color, $lightness: 10%); + $new-selected-button: color.adjust($background-color, $lightness: 5%); + + $background: map.merge($background, (background: $background-color)); + $background: map.merge($background, (card: $new-card-color)); + $background: map.merge($background, (modal: $new-card-color)); + $background: map.merge($background, (dialog: $new-card-color)); + $background: map.merge($background, (selected-button: $new-selected-button)); + + $theme-with-new-background: map.merge($theme, (background: $background)); + + $theme-color: map.get($theme-with-new-background, color); + $theme-color-background: map.merge($theme-color, (background: $background)); + + $theme-with-new-background: map.merge($theme-with-new-background, (color: $theme-color-background)); + + @return $theme-with-new-background; +} diff --git a/lib/core/custom-theme/theme/custom-palette-creator.scss b/lib/core/custom-theme/theme/custom-palette-creator.scss new file mode 100644 index 0000000000..1ef972c6d5 --- /dev/null +++ b/lib/core/custom-theme/theme/custom-palette-creator.scss @@ -0,0 +1,153 @@ +@use 'sass:map'; +@use 'sass:math'; +@use 'sass:color'; +@use '../../colors'; + +@function multiply($fore, $back) { + $red: color.red($back) * color.red($fore) / 255; + $green: color.green($back) * color.green($fore) / 255; + $blue: color.blue($back) * color.blue($fore) / 255; + + @return rgb($red, $green, $blue); +} + +@function get-color-luminance($color) { + $colors: ( + red: color.red($color), + green: color.green($color), + blue: color.blue($color), + ); + + @each $name, $value in $colors { + $adjusted: 0; + $value: $value / 255; + + @if ($value < 0.0393) { + $value: $value / 12.92; + } @else { + $value: ($value + 0.055) / 1.055; + $value: math.pow($value, 2.4); + } + + $colors: map.merge( + $colors, + ( + $name: $value, + ) + ); + } + + @return (map.get($colors, red) * 0.2126) + (map.get($colors, green) * 0.7152) + (map.get($colors, blue) * 0.0722); +} + +@function create-text-color($color, $colorType: 'primary') { + $red: color.red($color); + $green: color.green($color); + $blue: color.blue($color); + + $light-text: $light-primary-text; + $dark-text: $dark-primary-text; + + @if $colorType == 'accent' { + $light-text: $light-secondary-text; + $dark-text: $dark-secondary-text; + } + + $light-text-luminance: get-color-luminance($light-text); + $dark-text-luminance: get-color-luminance($dark-text); + $background-color-luminance: get-color-luminance($color); + + $light-text-luminance: $light-text-luminance + 0.5; + $dark-text-luminance: $dark-text-luminance + 0.5; + $background-color-luminance: $background-color-luminance + 0.5; + + $luminance-contrast-for-light-text: $light-text-luminance / $background-color-luminance; + $luminance-contrast-for-dark-text: $background-color-luminance / $dark-text-luminance; + $text-colour: $light-text; + + @if $luminance-contrast-for-dark-text > $luminance-contrast-for-light-text { + $text-colour: $dark-text; + } + + @return $text-colour; +} + +@function create-color-palette($color, $colorType: 'primary') { + $light: #fff; + $dark: multiply($color, $color); + + $color50: color.mix($light, $color, 88%); + $color100: color.mix($light, $color, 70%); + $color200: color.mix($light, $color, 50%); + $color300: color.mix($light, $color, 30%); + $color400: color.mix($light, $color, 15%); + $color500: color.mix($light, $color, 0%); + $color600: color.mix($dark, $color, 13%); + $color700: color.mix($dark, $color, 30%); + $color800: color.mix($dark, $color, 46%); + $color900: color.mix($dark, $color, 75%); + + /* stylelint-disable scss/dollar-variable-pattern */ + $colorA100: color.adjust(saturate(color.mix($dark, $color, 15%), 80%), $lightness: 45.6%); + $colorA200: color.adjust(saturate(color.mix($dark, $color, 15%), 80%), $lightness: 35.6%); + $colorA400: color.adjust(saturate(color.mix($dark, $color, 15%), 100%), $lightness: 25.6%); + $colorA700: color.adjust(saturate(color.mix($dark, $color, 15%), 100%), $lightness: 20.5%); + /* stylelint-enable scss/dollar-variable-pattern */ + + $contrast50: create-text-color($color50, $colorType); + $contrast100: create-text-color($color100, $colorType); + $contrast200: create-text-color($color200, $colorType); + $contrast300: create-text-color($color300, $colorType); + $contrast400: create-text-color($color400, $colorType); + $contrast500: create-text-color($color500, $colorType); + $contrast600: create-text-color($color600, $colorType); + $contrast700: create-text-color($color700, $colorType); + $contrast800: create-text-color($color800, $colorType); + $contrast900: create-text-color($color900, $colorType); + + /* stylelint-disable scss/dollar-variable-pattern */ + $contrastA100: create-text-color($colorA100, $colorType); + $contrastA200: create-text-color($colorA200, $colorType); + $contrastA400: create-text-color($colorA400, $colorType); + $contrastA700: create-text-color($colorA700, $colorType); + /* stylelint-enable scss/dollar-variable-pattern */ + + $palette: ( + 50: $color50, + 100: $color50, + 200: $color50, + 300: $color50, + 400: $color400, + 500: $color500, + 600: $color600, + 700: $color700, + 800: $color800, + 900: $color900, + /* stylelint-disable value-keyword-case */ + A100: $colorA100, + A200: $colorA200, + A400: $colorA400, + A700: $colorA700, + /* stylelint-enable value-keyword-case */ + contrast: ( + 50: $contrast50, + 100: $contrast100, + 200: $contrast200, + 300: $contrast300, + 400: $contrast400, + 500: $contrast500, + 600: $contrast600, + 700: $contrast700, + 800: $contrast800, + 900: $contrast900, + /* stylelint-disable value-keyword-case */ + A100: $contrastA100, + A200: $contrastA200, + A400: $contrastA400, + A700: $contrastA700, + /* stylelint-enable value-keyword-case */ + ), + ); + + @return $palette; +} diff --git a/lib/core/custom-theme/theme/custom-text-color.scss b/lib/core/custom-theme/theme/custom-text-color.scss new file mode 100644 index 0000000000..becd6fecdc --- /dev/null +++ b/lib/core/custom-theme/theme/custom-text-color.scss @@ -0,0 +1,17 @@ +@use 'sass:map'; + +@function get-custom-text-color($text-color, $theme) { + $foreground: map.get($theme, foreground); + + $foreground: map.merge($foreground, (text: $text-color)); + $foreground: map.merge($foreground, (secondary-text: $text-color)); + + $theme-with-new-foreground: map.merge($theme, (foreground: $foreground)); + + $theme-foreground-color: map.get($theme-with-new-foreground, color); + $theme-color-foreground: map.merge($theme-foreground-color, (foreground: $foreground)); + + $theme-with-new-foreground: map.merge($theme-with-new-foreground, (color: $theme-color-foreground)); + + @return $theme-with-new-foreground; +} diff --git a/lib/core/custom-theme/theme/custom-theme-palettes.scss b/lib/core/custom-theme/theme/custom-theme-palettes.scss new file mode 100644 index 0000000000..68863f3d3c --- /dev/null +++ b/lib/core/custom-theme/theme/custom-theme-palettes.scss @@ -0,0 +1,31 @@ +@use '@angular/material' as mat; +@import '../../colors'; +@import './custom-palette-creator.scss'; + +@function get-mat-palettes($primary-color, $accent-color) { + $mat-primary-palette: null; + + @if ($primary-color) { + $custom-theme-primary-palette: create-color-palette($primary-color, 'primary'); + $mat-primary-palette: mat.define-palette($custom-theme-primary-palette, 500); + } @else { + $mat-primary-palette: mat.define-palette($aca-primary-blue, A100); + } + + $mat-accent-palette: null; + + @if ($accent-color) { + $custom-theme-accent-palette: create-color-palette($accent-color, 'accent'); + $mat-accent-palette: mat.define-palette($custom-theme-accent-palette, 500); + } @else { + $mat-accent-palette: mat.define-palette($aca-accent-green, A200); + } + + $mat-warn-palette: mat.define-palette($aca-warn, A100); + + @return ( + primary: $mat-primary-palette, + accent: $mat-accent-palette, + warning: $mat-warn-palette, + ) +} diff --git a/lib/core/custom-theme/theme/theme-configuration.scss.tpl b/lib/core/custom-theme/theme/theme-configuration.scss.tpl new file mode 100644 index 0000000000..b96d9a679d --- /dev/null +++ b/lib/core/custom-theme/theme/theme-configuration.scss.tpl @@ -0,0 +1,14 @@ +/* +Specify theme parameters e.g.: + +$theme-config: ( + primaryColor: #5175d2, + backgroundColor: #FAFAFA, + textColor: #793942, + accentColor: #C64F73, + baseFontSize: 26px, + fontFamily: Cursive +); +*/ + +${THEME_CONFIGURATION} diff --git a/lib/core/custom-theme/theme/theme-data.scss b/lib/core/custom-theme/theme/theme-data.scss new file mode 100644 index 0000000000..66afaa6f5b --- /dev/null +++ b/lib/core/custom-theme/theme/theme-data.scss @@ -0,0 +1,22 @@ +@use 'sass:map'; +@import '@angular/material/theming'; +@import './theme-configuration'; +@import './typography'; +@import './custom-theme-palettes'; +@import './custom-background-color'; +@import './custom-text-color'; + +$primary-color: map.get($theme-config, 'primaryColor'); +$accent-color: map.get($theme-config, 'accentColor'); +$background-color: map.get($theme-config, 'backgroundColor'); + +$text-color: map.get($theme-config, 'textColor'); +$base-font-size: map.get($theme-config, 'baseFontSize'); +$font-family: map.get($theme-config, 'fontFamily'); + +$app-typography: get-mat-typography( + $base-font-size, + $font-family +); + +$palettes: get-mat-palettes($primary-color, $accent-color); diff --git a/lib/core/custom-theme/theme/typography.scss b/lib/core/custom-theme/theme/typography.scss new file mode 100644 index 0000000000..152eaf5ac5 --- /dev/null +++ b/lib/core/custom-theme/theme/typography.scss @@ -0,0 +1,93 @@ +@use 'sass:map'; +@use '@angular/material' as mat; +@import "../variables/font-family.scss"; + +@function get-mat-typography($base-font-size, $font-family) { + $custom-typography: mat.define-typography-config( + $font-family: 'Muli, Roboto, "Helvetica Neue", sans-serif', + $display-4: mat.define-typography-level(112px, 112px, 300), + $display-3: mat.define-typography-level(56px, 56px, 400), + $display-2: mat.define-typography-level(45px, 48px, 400), + $display-1: mat.define-typography-level(34px, 40px, 400), + $headline: mat.define-typography-level(24px, 32px, 400), + $title: mat.define-typography-level(20px, 32px, 500), + $subheading-2: mat.define-typography-level(16px, 28px, 400), + $subheading-1: mat.define-typography-level(15px, 24px, 400), + $body-2: mat.define-typography-level(14px, 24px, 500), + $body-1: mat.define-typography-level(14px, 20px, 400), + $caption: mat.define-typography-level(12px, 20px, 400), + $button: mat.define-typography-level(14px, 14px, 500), + // Line-height must be unit-less fraction of the font-size. + $input: mat.define-typography-level(16px, 1.25, 400), + ); + + @if $base-font-size { + $custom-typography: mat.define-typography-config( + $display-4: mat.define-typography-level(8rem, 8rem, 300), + $display-3: mat.define-typography-level(4rem, 4rem, 400), + $display-2: mat.define-typography-level(3.21rem, 3.21rem, 400), + $display-1: mat.define-typography-level(2.42rem, 2.85rem, 400), + $headline: mat.define-typography-level(1.71rem, 2.28rem, 400), + $title: mat.define-typography-level(1.42rem, 2.28rem, 500), + $subheading-2: mat.define-typography-level(1.14rem, 2rem, 400), + $subheading-1: mat.define-typography-level(1.07rem, 1.71rem, 400), + $body-2: mat.define-typography-level(1rem, 1.71rem, 500), + $body-1: mat.define-typography-level(1rem, 1.42rem, 400), + $caption: mat.define-typography-level(0.86rem, 1.42rem, 400), + $button: mat.define-typography-level(1rem, 1rem, 500), + $font-family: $default-font-family, + $input: mat.define-typography-level(1.14em, 1.25, 400), + ); + } + + @if $font-family { + @each $key, $level in $custom-typography { + @if type-of($level) == 'map' { + $new-level: map.merge( + $level, + ( + font-family: $font-family, + ) + ); + $custom-typography: map.merge( + $custom-typography, + ( + $key: $new-level, + ) + ); + } + } + + $custom-typography: map.merge( + $custom-typography, + ( + font-family: $font-family, + ) + ); + } + + @return $custom-typography; +} + +@function get-custom-adf-font-sizes() { + @return ( + 'theme-adf-icon-1-font-size': 1.2rem, + 'theme-adf-picture-1-font-size': 1.28rem, + 'theme-adf-task-footer-font-size': 1.28rem, + 'theme-adf-task-title-font-size': 1.28rem + ); +} + +@mixin base-font-size($font-size) { + html, + body { + font-size: $font-size !important; + } +} + +@mixin base-font-family($font-family) { + html, + body { + font-family: $font-family !important; + } +} diff --git a/lib/core/custom-theme/variables/font-family.scss b/lib/core/custom-theme/variables/font-family.scss new file mode 100644 index 0000000000..5d03830b89 --- /dev/null +++ b/lib/core/custom-theme/variables/font-family.scss @@ -0,0 +1 @@ +$default-font-family: 'Open Sans'; diff --git a/lib/core/ng-package.json b/lib/core/ng-package.json index 6c880927db..d93bc63342 100644 --- a/lib/core/ng-package.json +++ b/lib/core/ng-package.json @@ -2,6 +2,11 @@ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", "dest": "../../dist/libs/core", "assets": [ + { + "glob": "custom-theme/**/*", + "input": "./", + "output": "/" + }, { "glob": "assets/**/*", "input": "./src/lib", diff --git a/stylelint-config.json b/stylelint-config.json index 8f9063443b..0294b8e491 100644 --- a/stylelint-config.json +++ b/stylelint-config.json @@ -31,7 +31,8 @@ "vh", "vw", "vmin", - "s" + "s", + "rem" ], "value-list-comma-space-after": "always-single-line", "value-list-comma-space-before": "never", @@ -62,7 +63,12 @@ "message": "The `initial` value is not supported in IE." } ], - "block-closing-brace-newline-after": "always", + "block-closing-brace-newline-after": [ + "always", + { + "ignoreAtRules": ["if", "else"] + } + ], "block-closing-brace-newline-before": "always-multi-line", "block-opening-brace-newline-after": "always-multi-line", "block-opening-brace-space-before": "always-multi-line", @@ -89,6 +95,8 @@ { "resolveNestedSelectors": true } - ] + ], + "scss/dollar-variable-empty-line-before": null, + "scss/at-rule-conditional-no-parentheses": null } }