| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugin; |
|
|
| use Piwik\Piwik; |
|
|
| class ThemeStyles |
| { |
| public const AUTO_MODE = 'auto'; |
| public const LIGHT_MODE = 'light'; |
| public const DARK_MODE = 'dark'; |
|
|
| |
| private static $propertyNamesToLessVariableNames = [ |
| 'fontFamilyBase' => 'theme-fontFamily-base', |
| 'colorBrand' => 'theme-color-brand', |
| 'colorBrandContrast' => 'theme-color-brand-contrast', |
| 'colorNewBrand' => 'theme-color-new-brand', |
| 'colorFocusRing' => 'theme-color-focus-ring', |
| 'colorFocusRingAlternative' => 'theme-color-focus-ring-alternative', |
| 'colorTextHighContrast' => 'theme-color-text-highContrast', |
| 'colorText' => 'theme-color-text', |
| 'colorTextContrast' => 'theme-color-text-contrast', |
| 'colorTextLight' => 'theme-color-text-light', |
| 'colorTextLighter' => 'theme-color-text-lighter', |
| 'colorTextOnDisabled' => 'theme-color-text-on-disabled', |
| 'colorTextPlaceholder' => 'theme-color-text-placeholder', |
| 'colorTextInvert' => 'theme-color-text-invert', |
| 'colorTextInvertContrast' => 'theme-color-text-invert-contrast', |
| 'colorTextInvertLight' => 'theme-color-text-invert-light', |
| 'colorTextDisabled' => 'theme-color-text-disabled', |
| 'colorLink' => 'theme-color-link', |
| 'colorBaseSeries' => 'theme-color-base-series', |
| 'colorHeadlineAlternative' => 'theme-color-headline-alternative', |
| 'colorHeaderBackground' => 'theme-color-header-background', |
| 'colorHeaderText' => 'theme-color-header-text', |
| 'colorMenuContrastText' => 'theme-color-menu-contrast-text', |
| 'colorMenuContrastTextSelected' => 'theme-color-menu-contrast-textSelected', |
| 'colorMenuContrastTextActive' => 'theme-color-menu-contrast-textActive', |
| 'colorMenuContrastBackground' => 'theme-color-menu-contrast-background', |
| 'colorWidgetExportedBackgroundBase' => 'theme-color-widget-exported-background-base', |
| 'colorWidgetTitleText' => 'theme-color-widget-title-text', |
| 'colorWidgetTitleBackground' => 'theme-color-widget-title-background', |
| 'colorBackgroundBase' => 'theme-color-background-base', |
| 'colorBackgroundTinyContrast' => 'theme-color-background-tinyContrast', |
| 'colorBackgroundLowContrast' => 'theme-color-background-lowContrast', |
| 'colorBackgroundContrast' => 'theme-color-background-contrast', |
| 'colorBackgroundHighContrast' => 'theme-color-background-highContrast', |
| 'colorBackgroundDisabled' => 'theme-color-background-disabled', |
| 'colorBorder' => 'theme-color-border', |
| 'colorBorderAlternative' => 'theme-color-border-alternative', |
| 'colorBorderLight' => 'theme-color-border-light', |
| 'colorBoxShadow' => 'theme-color-boxShadow', |
| 'shadowOverlay' => 'theme-shadow-overlay', |
| 'colorCode' => 'theme-color-code', |
| 'colorCodeBackground' => 'theme-color-code-background', |
| 'colorWidgetBackground' => 'theme-color-widget-background', |
| 'colorWidgetBorder' => 'theme-color-widget-border', |
| 'filterOnIllustration' => 'theme-filter-on-illustration', |
| 'colorMenuContrastBackgroundHover' => 'theme-color-menu-contrast-backgroundHover', |
| ]; |
|
|
| |
| |
| |
| protected $themeMode = self::AUTO_MODE; |
|
|
| |
| |
| |
| public $fontFamilyBase = '-apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, Oxygen-Sans, Cantarell, \'Helvetica Neue\', sans-serif'; |
|
|
| |
| |
| |
| public $colorBrand = ['#43a047', '#778fd4']; |
|
|
| |
| |
| |
| public $colorBrandContrast = ['#fff', '#ffffff']; |
|
|
| |
| |
| |
| public $colorNewBrand = '#00b4be'; |
|
|
| |
| |
| |
| public $colorFocusRing = '#0969da'; |
|
|
| |
| |
| |
| public $colorFocusRingAlternative = '#00b4bE'; |
|
|
| |
| |
| |
| public $colorTextHighContrast = ['#000', '#d9d9d9']; |
|
|
| |
| |
| |
| public $colorText = ['#212121', '#ccc']; |
|
|
| |
| |
| |
| public $colorTextContrast = ['#37474f', '#bbb']; |
|
|
| |
| |
| |
| public $colorTextLight = ['#444', '#aaa']; |
|
|
| |
| |
| |
| public $colorTextLighter = ['#646464', '#999']; |
|
|
| |
| |
| |
| public $colorTextOnDisabled = ['#666666', '#999']; |
|
|
| |
| |
| |
| |
| public $colorTextPlaceholder = ['#d1d1d1', '#565656']; |
|
|
| |
| |
| |
| public $colorTextInvert = ['#ccc', '#555']; |
|
|
| |
| |
| |
| public $colorTextInvertContrast = ['#fff', '#000']; |
|
|
| |
| |
| |
| public $colorTextInvertLight = ['#b9b9b9', '#666']; |
|
|
| |
| |
| |
| public $colorTextDisabled = ['#aaa', '#666']; |
|
|
| |
| |
| |
| public $colorLink = ['#1976D2', '#778fd4']; |
|
|
| |
| |
| |
| public $colorBaseSeries = '#ee3024'; |
|
|
| |
| |
| |
| public $colorHeadlineAlternative = ['#4E4E4E', '#aaa']; |
|
|
| |
| |
| |
| public $colorHeaderBackground; |
|
|
| |
| |
| |
| public $colorHeaderText; |
|
|
| |
| |
| |
| public $colorMenuContrastText; |
|
|
| |
| |
| |
| public $colorMenuContrastTextSelected; |
|
|
| |
| |
| |
| public $colorMenuContrastTextActive = ['#1976D2', '#fff']; |
|
|
| |
| |
| |
| public $colorMenuContrastBackgroundHover = ['#eff0f1', '#151819']; |
|
|
| |
| |
| |
| public $colorMenuContrastBackground; |
|
|
| |
| |
| |
| public $colorWidgetExportedBackgroundBase; |
|
|
| |
| |
| |
| public $colorWidgetTitleText; |
|
|
| |
| |
| |
| public $colorWidgetTitleBackground; |
|
|
| |
| |
| |
| public $colorBackgroundBase = ['#f5f5f5', '#151819']; |
|
|
| |
| |
| |
| public $colorBackgroundTinyContrast = ['#f2f2f2', '#182c32']; |
|
|
| |
| |
| |
| public $colorBackgroundLowContrast = ['#d9d9d9', '#192d33']; |
|
|
| |
| |
| |
| public $colorBackgroundContrast = ['#fff', '#202329']; |
|
|
| |
| |
| |
| public $colorBackgroundHighContrast = ['#202020', '#404349']; |
|
|
| |
| |
| |
| public $colorBackgroundDisabled = ['#d9d9d9', '#303339']; |
|
|
| |
| |
| |
| public $colorBorderLight = ['#a9a399', '#645e54']; |
|
|
| |
| |
| |
| |
| |
| public $colorBorder = ['#cccccc', '#555555']; |
|
|
| |
| |
| |
| |
| |
| |
| public $colorBorderAlternative = ['#E0E0E0', '#555555']; |
|
|
| |
| |
| |
| public $colorBoxShadow = ['rgba(0, 0, 0, 0.1)', 'rgba(0, 0, 0, 0.1)']; |
|
|
| |
| |
| |
| public $shadowOverlay = ['0 0 3px #A5B1CA4D, 0 10px 40px #A5B1CA4D', '0 0 3px #00000080, 0 10px 40px #00000080']; |
|
|
| |
| |
| |
| public $colorCode = '#f3f3f3'; |
|
|
| |
| |
| |
| public $colorCodeBackground = '#4d4d4d'; |
|
|
| |
| |
| |
| public $colorWidgetBackground; |
|
|
| |
| |
| |
| public $colorWidgetBorder; |
|
|
| |
| |
| |
| public $filterOnIllustration = ['none', 'brightness(89%) invert(100%) hue-rotate(180deg)']; |
|
|
| public function __construct(string $themeMode) |
| { |
| $this->themeMode = $themeMode; |
| $this->colorMenuContrastText = $this->colorText; |
| $this->colorMenuContrastTextSelected = $this->colorMenuContrastText; |
| $this->colorMenuContrastBackground = $this->colorBackgroundContrast; |
| $this->colorWidgetExportedBackgroundBase = $this->colorBackgroundContrast; |
| $this->colorWidgetTitleText = $this->colorText; |
| $this->colorWidgetTitleBackground = $this->colorBackgroundContrast; |
| $this->colorWidgetBackground = $this->colorBackgroundContrast; |
| $this->colorWidgetBorder = $this->colorBackgroundTinyContrast; |
| $this->colorHeaderBackground = $this->colorBackgroundContrast; |
| $this->colorHeaderText = $this->colorTextLighter; |
| } |
|
|
| |
| |
| |
| public static function get(string $mode = self::AUTO_MODE) |
| { |
| $result = new self($mode); |
|
|
| |
| |
| |
| Piwik::postEvent('Theme.configureThemeVariables', [$result]); |
|
|
| return $result; |
| } |
|
|
| public function getIsLightMode(): bool |
| { |
| return $this->themeMode === self::LIGHT_MODE; |
| } |
|
|
| public function getIsDarkMode(): bool |
| { |
| return $this->themeMode === self::DARK_MODE; |
| } |
|
|
| public function getThemeMode(): string |
| { |
| return $this->themeMode; |
| } |
|
|
| public function getPropertyValue(string $name): string |
| { |
| if (!property_exists($this, $name)) { |
| return ''; |
| } |
|
|
| return $this->resolvePropertyValue($this->$name, $this->getIsDarkMode() ? 1 : 0); |
| } |
|
|
| public function toLessCode() |
| { |
| $rootCssVars = []; |
| $darkCssVars = []; |
|
|
| foreach (get_object_vars($this) as $name => $value) { |
| $varName = isset(self::$propertyNamesToLessVariableNames[$name]) ? self::$propertyNamesToLessVariableNames[$name] : $this->getGenericThemeVarName($name); |
| if (is_array($value)) { |
| $rootCssVars[] = " --$varName: " . $this->resolvePropertyValue($value, 0) . ";\n"; |
| $darkCssVars[] = " --$varName: " . $this->resolvePropertyValue($value, 1) . ";\n"; |
| } else { |
| $rootCssVars[] = " --$varName: " . $this->resolvePropertyValue($value, 0) . ";\n"; |
| } |
| } |
|
|
| $result = ":root {\n color-scheme: light;\n" . implode('', $rootCssVars) . "}\n\n"; |
| if (!empty($darkCssVars)) { |
| $result .= "[data-theme-mode=\"dark\"] {\n color-scheme: dark;\n" . implode('', $darkCssVars) . "}\n\n"; |
| $result .= "@media (prefers-color-scheme: dark) {\n"; |
| $result .= " [data-theme-mode=\"auto\"] {\n color-scheme: dark;\n" . implode('', $darkCssVars) . " }\n"; |
| $result .= "}\n\n"; |
| } |
|
|
| foreach (get_object_vars($this) as $name => $_) { |
| $varName = isset(self::$propertyNamesToLessVariableNames[$name]) ? self::$propertyNamesToLessVariableNames[$name] : $this->getGenericThemeVarName($name); |
| $result .= "@$varName: ~\"var(--$varName)\";\n"; |
| } |
| return $result; |
| } |
|
|
| private function getGenericThemeVarName($propertyName) |
| { |
| return 'theme-' . $propertyName; |
| } |
|
|
| |
| |
| |
| private function resolvePropertyValue($value, int $preferredIndex): string |
| { |
| if (!is_array($value)) { |
| return is_string($value) ? $value : ''; |
| } |
|
|
| $fallbackIndex = $preferredIndex === 1 ? 0 : 1; |
|
|
| if (isset($value[$preferredIndex]) && is_string($value[$preferredIndex])) { |
| return $value[$preferredIndex]; |
| } |
|
|
| if (isset($value[$fallbackIndex]) && is_string($value[$fallbackIndex])) { |
| return $value[$fallbackIndex]; |
| } |
|
|
| return ''; |
| } |
| } |
|
|