1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
ash / webui / color_internals / resources / index.ts [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {COLOR_PROVIDER_CHANGED, ColorChangeUpdater} from 'chrome://resources/cr_components/color_change_listener/colors_css_updater.js';
import {assert} from 'chrome://resources/js/assert.js';
import {getRGBAFromComputedStyle} from './utils.js';
import {startObservingWallpaperColors} from './wallpaper_colors.js';
const CROS_TOKENS_JSON_URL = 'color_internals_tokens.json';
interface Token {
token_name: string;
css_variable: string;
mode_values?: {light: string, dark: string};
}
interface TokenArray {
ref_tokens: Token[];
sys_tokens: Token[];
}
function appendTokenRowToTable(
table: HTMLTableSectionElement, token: Token): void {
const newRow = table.insertRow();
function appendColorCell(color: string) {
const colorSwatch = document.createElement('span');
const cell = document.createElement('td');
const text = document.createElement('span');
colorSwatch.classList.add('color-swatch');
colorSwatch.style.backgroundColor = color;
cell.classList.add('monospace');
cell.appendChild(colorSwatch);
newRow.append(cell);
// Perform this step last so the style has actually been computed.
text.textContent = getRGBAFromComputedStyle(colorSwatch);
cell.appendChild(text);
}
function appendFormulaCell(formula: string) {
const cell = document.createElement('td');
cell.textContent = formula;
newRow.append(cell);
}
const header = document.createElement('td');
header.textContent = token.token_name;
header.classList.add('monospace');
newRow.append(header);
const cssVariableString = `var(${token.css_variable})`;
appendColorCell(cssVariableString);
// cros.sys.* tokens contain a definition of how they were calculated.
if (token.mode_values) {
appendFormulaCell(token.mode_values.light);
appendFormulaCell(token.mode_values.dark);
}
}
// The list of tokens and color values are provided as JSON resource by the
// backend.
async function requestJSON(): Promise<JSON> {
return new Promise(function(resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open('GET', CROS_TOKENS_JSON_URL, true);
xhr.responseType = 'json';
xhr.onload = () => {
resolve(xhr.response);
};
xhr.onerror = () => {
reject(xhr.response);
};
xhr.send();
});
}
async function populateTokenTable() {
function addTokens(table: HTMLTableSectionElement, tokens: Token[]) {
Object.values(tokens).forEach(
t => appendTokenRowToTable(table, t as Token));
}
const json = await requestJSON();
const tokens = json as unknown as TokenArray;
const refTable =
(document.querySelector('table#ref-tokens')!).querySelector('tbody')!;
const sysTable =
(document.querySelector('table#sys-tokens')!).querySelector('tbody')!;
addTokens(refTable, tokens.ref_tokens);
addTokens(sysTable, tokens.sys_tokens);
}
function onColorChange() {
const formatter = new Intl.DateTimeFormat('en', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
});
const span = document.querySelector<HTMLElement>('#last-updated');
assert(span);
span.innerText = formatter.format(new Date());
}
window.onload = () => {
populateTokenTable();
ColorChangeUpdater.forDocument().start();
startObservingWallpaperColors();
ColorChangeUpdater.forDocument().eventTarget.addEventListener(
COLOR_PROVIDER_CHANGED, onColorChange);
onColorChange();
};