@m3e/theme 1.0.0-rc.3 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/custom-elements.json +30 -19
- package/dist/index.js +596 -39
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +153 -25
- package/dist/index.min.js.map +1 -1
- package/dist/src/ThemeElement.d.ts +3 -3
- package/dist/src/ThemeElement.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -148,6 +148,19 @@ function clampDouble(min, max, input) {
|
|
|
148
148
|
}
|
|
149
149
|
return input;
|
|
150
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Sanitizes a degree measure as an integer.
|
|
153
|
+
*
|
|
154
|
+
* @return a degree measure between 0 (inclusive) and 360
|
|
155
|
+
* (exclusive).
|
|
156
|
+
*/
|
|
157
|
+
function sanitizeDegreesInt(degrees) {
|
|
158
|
+
degrees = degrees % 360;
|
|
159
|
+
if (degrees < 0) {
|
|
160
|
+
degrees = degrees + 360;
|
|
161
|
+
}
|
|
162
|
+
return degrees;
|
|
163
|
+
}
|
|
151
164
|
/**
|
|
152
165
|
* Sanitizes a degree measure as a floating-point number.
|
|
153
166
|
*
|
|
@@ -273,6 +286,33 @@ function xyzFromArgb(argb) {
|
|
|
273
286
|
const b = linearized(blueFromArgb(argb));
|
|
274
287
|
return matrixMultiply([r, g, b], SRGB_TO_XYZ);
|
|
275
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Converts a color from ARGB representation to L*a*b*
|
|
291
|
+
* representation.
|
|
292
|
+
*
|
|
293
|
+
* @param argb the ARGB representation of a color
|
|
294
|
+
* @return a Lab object representing the color
|
|
295
|
+
*/
|
|
296
|
+
function labFromArgb(argb) {
|
|
297
|
+
const linearR = linearized(redFromArgb(argb));
|
|
298
|
+
const linearG = linearized(greenFromArgb(argb));
|
|
299
|
+
const linearB = linearized(blueFromArgb(argb));
|
|
300
|
+
const matrix = SRGB_TO_XYZ;
|
|
301
|
+
const x = matrix[0][0] * linearR + matrix[0][1] * linearG + matrix[0][2] * linearB;
|
|
302
|
+
const y = matrix[1][0] * linearR + matrix[1][1] * linearG + matrix[1][2] * linearB;
|
|
303
|
+
const z = matrix[2][0] * linearR + matrix[2][1] * linearG + matrix[2][2] * linearB;
|
|
304
|
+
const whitePoint = WHITE_POINT_D65;
|
|
305
|
+
const xNormalized = x / whitePoint[0];
|
|
306
|
+
const yNormalized = y / whitePoint[1];
|
|
307
|
+
const zNormalized = z / whitePoint[2];
|
|
308
|
+
const fx = labF(xNormalized);
|
|
309
|
+
const fy = labF(yNormalized);
|
|
310
|
+
const fz = labF(zNormalized);
|
|
311
|
+
const l = 116.0 * fy - 16;
|
|
312
|
+
const a = 500.0 * (fx - fy);
|
|
313
|
+
const b = 200.0 * (fy - fz);
|
|
314
|
+
return [l, a, b];
|
|
315
|
+
}
|
|
276
316
|
/**
|
|
277
317
|
* Converts an L* value to an ARGB representation.
|
|
278
318
|
*
|
|
@@ -3215,6 +3255,316 @@ class CorePalette {
|
|
|
3215
3255
|
}
|
|
3216
3256
|
}
|
|
3217
3257
|
|
|
3258
|
+
/**
|
|
3259
|
+
* @license
|
|
3260
|
+
* Copyright 2023 Google LLC
|
|
3261
|
+
*
|
|
3262
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3263
|
+
* you may not use this file except in compliance with the License.
|
|
3264
|
+
* You may obtain a copy of the License at
|
|
3265
|
+
*
|
|
3266
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3267
|
+
*
|
|
3268
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3269
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3270
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3271
|
+
* See the License for the specific language governing permissions and
|
|
3272
|
+
* limitations under the License.
|
|
3273
|
+
*/
|
|
3274
|
+
// This file is automatically generated. Do not modify it.
|
|
3275
|
+
/**
|
|
3276
|
+
* Design utilities using color temperature theory.
|
|
3277
|
+
*
|
|
3278
|
+
* Analogous colors, complementary color, and cache to efficiently, lazily,
|
|
3279
|
+
* generate data for calculations when needed.
|
|
3280
|
+
*/
|
|
3281
|
+
class TemperatureCache {
|
|
3282
|
+
constructor(input) {
|
|
3283
|
+
this.input = input;
|
|
3284
|
+
this.hctsByTempCache = [];
|
|
3285
|
+
this.hctsByHueCache = [];
|
|
3286
|
+
this.tempsByHctCache = new Map();
|
|
3287
|
+
this.inputRelativeTemperatureCache = -1;
|
|
3288
|
+
this.complementCache = null;
|
|
3289
|
+
}
|
|
3290
|
+
get hctsByTemp() {
|
|
3291
|
+
if (this.hctsByTempCache.length > 0) {
|
|
3292
|
+
return this.hctsByTempCache;
|
|
3293
|
+
}
|
|
3294
|
+
const hcts = this.hctsByHue.concat([this.input]);
|
|
3295
|
+
const temperaturesByHct = this.tempsByHct;
|
|
3296
|
+
hcts.sort((a, b) => temperaturesByHct.get(a) - temperaturesByHct.get(b));
|
|
3297
|
+
this.hctsByTempCache = hcts;
|
|
3298
|
+
return hcts;
|
|
3299
|
+
}
|
|
3300
|
+
get warmest() {
|
|
3301
|
+
return this.hctsByTemp[this.hctsByTemp.length - 1];
|
|
3302
|
+
}
|
|
3303
|
+
get coldest() {
|
|
3304
|
+
return this.hctsByTemp[0];
|
|
3305
|
+
}
|
|
3306
|
+
/**
|
|
3307
|
+
* A set of colors with differing hues, equidistant in temperature.
|
|
3308
|
+
*
|
|
3309
|
+
* In art, this is usually described as a set of 5 colors on a color wheel
|
|
3310
|
+
* divided into 12 sections. This method allows provision of either of those
|
|
3311
|
+
* values.
|
|
3312
|
+
*
|
|
3313
|
+
* Behavior is undefined when [count] or [divisions] is 0.
|
|
3314
|
+
* When divisions < count, colors repeat.
|
|
3315
|
+
*
|
|
3316
|
+
* [count] The number of colors to return, includes the input color.
|
|
3317
|
+
* [divisions] The number of divisions on the color wheel.
|
|
3318
|
+
*/
|
|
3319
|
+
analogous(count = 5, divisions = 12) {
|
|
3320
|
+
const startHue = Math.round(this.input.hue);
|
|
3321
|
+
const startHct = this.hctsByHue[startHue];
|
|
3322
|
+
let lastTemp = this.relativeTemperature(startHct);
|
|
3323
|
+
const allColors = [startHct];
|
|
3324
|
+
let absoluteTotalTempDelta = 0.0;
|
|
3325
|
+
for (let i = 0; i < 360; i++) {
|
|
3326
|
+
const hue = sanitizeDegreesInt(startHue + i);
|
|
3327
|
+
const hct = this.hctsByHue[hue];
|
|
3328
|
+
const temp = this.relativeTemperature(hct);
|
|
3329
|
+
const tempDelta = Math.abs(temp - lastTemp);
|
|
3330
|
+
lastTemp = temp;
|
|
3331
|
+
absoluteTotalTempDelta += tempDelta;
|
|
3332
|
+
}
|
|
3333
|
+
let hueAddend = 1;
|
|
3334
|
+
const tempStep = absoluteTotalTempDelta / divisions;
|
|
3335
|
+
let totalTempDelta = 0.0;
|
|
3336
|
+
lastTemp = this.relativeTemperature(startHct);
|
|
3337
|
+
while (allColors.length < divisions) {
|
|
3338
|
+
const hue = sanitizeDegreesInt(startHue + hueAddend);
|
|
3339
|
+
const hct = this.hctsByHue[hue];
|
|
3340
|
+
const temp = this.relativeTemperature(hct);
|
|
3341
|
+
const tempDelta = Math.abs(temp - lastTemp);
|
|
3342
|
+
totalTempDelta += tempDelta;
|
|
3343
|
+
const desiredTotalTempDeltaForIndex = allColors.length * tempStep;
|
|
3344
|
+
let indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
|
|
3345
|
+
let indexAddend = 1;
|
|
3346
|
+
// Keep adding this hue to the answers until its temperature is
|
|
3347
|
+
// insufficient. This ensures consistent behavior when there aren't
|
|
3348
|
+
// [divisions] discrete steps between 0 and 360 in hue with [tempStep]
|
|
3349
|
+
// delta in temperature between them.
|
|
3350
|
+
//
|
|
3351
|
+
// For example, white and black have no analogues: there are no other
|
|
3352
|
+
// colors at T100/T0. Therefore, they should just be added to the array
|
|
3353
|
+
// as answers.
|
|
3354
|
+
while (indexSatisfied && allColors.length < divisions) {
|
|
3355
|
+
allColors.push(hct);
|
|
3356
|
+
const desiredTotalTempDeltaForIndex = ((allColors.length + indexAddend) * tempStep);
|
|
3357
|
+
indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
|
|
3358
|
+
indexAddend++;
|
|
3359
|
+
}
|
|
3360
|
+
lastTemp = temp;
|
|
3361
|
+
hueAddend++;
|
|
3362
|
+
if (hueAddend > 360) {
|
|
3363
|
+
while (allColors.length < divisions) {
|
|
3364
|
+
allColors.push(hct);
|
|
3365
|
+
}
|
|
3366
|
+
break;
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
const answers = [this.input];
|
|
3370
|
+
// First, generate analogues from rotating counter-clockwise.
|
|
3371
|
+
const increaseHueCount = Math.floor((count - 1) / 2.0);
|
|
3372
|
+
for (let i = 1; i < (increaseHueCount + 1); i++) {
|
|
3373
|
+
let index = 0 - i;
|
|
3374
|
+
while (index < 0) {
|
|
3375
|
+
index = allColors.length + index;
|
|
3376
|
+
}
|
|
3377
|
+
if (index >= allColors.length) {
|
|
3378
|
+
index = index % allColors.length;
|
|
3379
|
+
}
|
|
3380
|
+
answers.splice(0, 0, allColors[index]);
|
|
3381
|
+
}
|
|
3382
|
+
// Second, generate analogues from rotating clockwise.
|
|
3383
|
+
const decreaseHueCount = count - increaseHueCount - 1;
|
|
3384
|
+
for (let i = 1; i < (decreaseHueCount + 1); i++) {
|
|
3385
|
+
let index = i;
|
|
3386
|
+
while (index < 0) {
|
|
3387
|
+
index = allColors.length + index;
|
|
3388
|
+
}
|
|
3389
|
+
if (index >= allColors.length) {
|
|
3390
|
+
index = index % allColors.length;
|
|
3391
|
+
}
|
|
3392
|
+
answers.push(allColors[index]);
|
|
3393
|
+
}
|
|
3394
|
+
return answers;
|
|
3395
|
+
}
|
|
3396
|
+
/**
|
|
3397
|
+
* A color that complements the input color aesthetically.
|
|
3398
|
+
*
|
|
3399
|
+
* In art, this is usually described as being across the color wheel.
|
|
3400
|
+
* History of this shows intent as a color that is just as cool-warm as the
|
|
3401
|
+
* input color is warm-cool.
|
|
3402
|
+
*/
|
|
3403
|
+
get complement() {
|
|
3404
|
+
if (this.complementCache != null) {
|
|
3405
|
+
return this.complementCache;
|
|
3406
|
+
}
|
|
3407
|
+
const coldestHue = this.coldest.hue;
|
|
3408
|
+
const coldestTemp = this.tempsByHct.get(this.coldest);
|
|
3409
|
+
const warmestHue = this.warmest.hue;
|
|
3410
|
+
const warmestTemp = this.tempsByHct.get(this.warmest);
|
|
3411
|
+
const range = warmestTemp - coldestTemp;
|
|
3412
|
+
const startHueIsColdestToWarmest = TemperatureCache.isBetween(this.input.hue, coldestHue, warmestHue);
|
|
3413
|
+
const startHue = startHueIsColdestToWarmest ? warmestHue : coldestHue;
|
|
3414
|
+
const endHue = startHueIsColdestToWarmest ? coldestHue : warmestHue;
|
|
3415
|
+
const directionOfRotation = 1.0;
|
|
3416
|
+
let smallestError = 1000.0;
|
|
3417
|
+
let answer = this.hctsByHue[Math.round(this.input.hue)];
|
|
3418
|
+
const complementRelativeTemp = 1.0 - this.inputRelativeTemperature;
|
|
3419
|
+
// Find the color in the other section, closest to the inverse percentile
|
|
3420
|
+
// of the input color. This is the complement.
|
|
3421
|
+
for (let hueAddend = 0.0; hueAddend <= 360.0; hueAddend += 1.0) {
|
|
3422
|
+
const hue = sanitizeDegreesDouble(startHue + directionOfRotation * hueAddend);
|
|
3423
|
+
if (!TemperatureCache.isBetween(hue, startHue, endHue)) {
|
|
3424
|
+
continue;
|
|
3425
|
+
}
|
|
3426
|
+
const possibleAnswer = this.hctsByHue[Math.round(hue)];
|
|
3427
|
+
const relativeTemp = (this.tempsByHct.get(possibleAnswer) - coldestTemp) / range;
|
|
3428
|
+
const error = Math.abs(complementRelativeTemp - relativeTemp);
|
|
3429
|
+
if (error < smallestError) {
|
|
3430
|
+
smallestError = error;
|
|
3431
|
+
answer = possibleAnswer;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
this.complementCache = answer;
|
|
3435
|
+
return this.complementCache;
|
|
3436
|
+
}
|
|
3437
|
+
/**
|
|
3438
|
+
* Temperature relative to all colors with the same chroma and tone.
|
|
3439
|
+
* Value on a scale from 0 to 1.
|
|
3440
|
+
*/
|
|
3441
|
+
relativeTemperature(hct) {
|
|
3442
|
+
const range = this.tempsByHct.get(this.warmest) - this.tempsByHct.get(this.coldest);
|
|
3443
|
+
const differenceFromColdest = this.tempsByHct.get(hct) - this.tempsByHct.get(this.coldest);
|
|
3444
|
+
// Handle when there's no difference in temperature between warmest and
|
|
3445
|
+
// coldest: for example, at T100, only one color is available, white.
|
|
3446
|
+
if (range === 0.0) {
|
|
3447
|
+
return 0.5;
|
|
3448
|
+
}
|
|
3449
|
+
return differenceFromColdest / range;
|
|
3450
|
+
}
|
|
3451
|
+
/** Relative temperature of the input color. See [relativeTemperature]. */
|
|
3452
|
+
get inputRelativeTemperature() {
|
|
3453
|
+
if (this.inputRelativeTemperatureCache >= 0.0) {
|
|
3454
|
+
return this.inputRelativeTemperatureCache;
|
|
3455
|
+
}
|
|
3456
|
+
this.inputRelativeTemperatureCache = this.relativeTemperature(this.input);
|
|
3457
|
+
return this.inputRelativeTemperatureCache;
|
|
3458
|
+
}
|
|
3459
|
+
/** A Map with keys of HCTs in [hctsByTemp], values of raw temperature. */
|
|
3460
|
+
get tempsByHct() {
|
|
3461
|
+
if (this.tempsByHctCache.size > 0) {
|
|
3462
|
+
return this.tempsByHctCache;
|
|
3463
|
+
}
|
|
3464
|
+
const allHcts = this.hctsByHue.concat([this.input]);
|
|
3465
|
+
const temperaturesByHct = new Map();
|
|
3466
|
+
for (const e of allHcts) {
|
|
3467
|
+
temperaturesByHct.set(e, TemperatureCache.rawTemperature(e));
|
|
3468
|
+
}
|
|
3469
|
+
this.tempsByHctCache = temperaturesByHct;
|
|
3470
|
+
return temperaturesByHct;
|
|
3471
|
+
}
|
|
3472
|
+
/**
|
|
3473
|
+
* HCTs for all hues, with the same chroma/tone as the input.
|
|
3474
|
+
* Sorted ascending, hue 0 to 360.
|
|
3475
|
+
*/
|
|
3476
|
+
get hctsByHue() {
|
|
3477
|
+
if (this.hctsByHueCache.length > 0) {
|
|
3478
|
+
return this.hctsByHueCache;
|
|
3479
|
+
}
|
|
3480
|
+
const hcts = [];
|
|
3481
|
+
for (let hue = 0.0; hue <= 360.0; hue += 1.0) {
|
|
3482
|
+
const colorAtHue = Hct.from(hue, this.input.chroma, this.input.tone);
|
|
3483
|
+
hcts.push(colorAtHue);
|
|
3484
|
+
}
|
|
3485
|
+
this.hctsByHueCache = hcts;
|
|
3486
|
+
return this.hctsByHueCache;
|
|
3487
|
+
}
|
|
3488
|
+
/** Determines if an angle is between two other angles, rotating clockwise. */
|
|
3489
|
+
static isBetween(angle, a, b) {
|
|
3490
|
+
if (a < b) {
|
|
3491
|
+
return a <= angle && angle <= b;
|
|
3492
|
+
}
|
|
3493
|
+
return a <= angle || angle <= b;
|
|
3494
|
+
}
|
|
3495
|
+
/**
|
|
3496
|
+
* Value representing cool-warm factor of a color.
|
|
3497
|
+
* Values below 0 are considered cool, above, warm.
|
|
3498
|
+
*
|
|
3499
|
+
* Color science has researched emotion and harmony, which art uses to select
|
|
3500
|
+
* colors. Warm-cool is the foundation of analogous and complementary colors.
|
|
3501
|
+
* See:
|
|
3502
|
+
* - Li-Chen Ou's Chapter 19 in Handbook of Color Psychology (2015).
|
|
3503
|
+
* - Josef Albers' Interaction of Color chapters 19 and 21.
|
|
3504
|
+
*
|
|
3505
|
+
* Implementation of Ou, Woodcock and Wright's algorithm, which uses
|
|
3506
|
+
* L*a*b* / LCH color space.
|
|
3507
|
+
* Return value has these properties:
|
|
3508
|
+
* - Values below 0 are cool, above 0 are warm.
|
|
3509
|
+
* - Lower bound: -0.52 - (chroma ^ 1.07 / 20). L*a*b* chroma is infinite.
|
|
3510
|
+
* Assuming max of 130 chroma, -9.66.
|
|
3511
|
+
* - Upper bound: -0.52 + (chroma ^ 1.07 / 20). L*a*b* chroma is infinite.
|
|
3512
|
+
* Assuming max of 130 chroma, 8.61.
|
|
3513
|
+
*/
|
|
3514
|
+
static rawTemperature(color) {
|
|
3515
|
+
const lab = labFromArgb(color.toInt());
|
|
3516
|
+
const hue = sanitizeDegreesDouble(Math.atan2(lab[2], lab[1]) * 180.0 / Math.PI);
|
|
3517
|
+
const chroma = Math.sqrt((lab[1] * lab[1]) + (lab[2] * lab[2]));
|
|
3518
|
+
const temperature = -0.5 +
|
|
3519
|
+
0.02 * Math.pow(chroma, 1.07) *
|
|
3520
|
+
Math.cos(sanitizeDegreesDouble(hue - 50.0) * Math.PI / 180.0);
|
|
3521
|
+
return temperature;
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
/**
|
|
3526
|
+
* @license
|
|
3527
|
+
* Copyright 2023 Google LLC
|
|
3528
|
+
*
|
|
3529
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3530
|
+
* you may not use this file except in compliance with the License.
|
|
3531
|
+
* You may obtain a copy of the License at
|
|
3532
|
+
*
|
|
3533
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3534
|
+
*
|
|
3535
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3536
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3537
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3538
|
+
* See the License for the specific language governing permissions and
|
|
3539
|
+
* limitations under the License.
|
|
3540
|
+
*/
|
|
3541
|
+
/**
|
|
3542
|
+
* A scheme that places the source color in `Scheme.primaryContainer`.
|
|
3543
|
+
*
|
|
3544
|
+
* Primary Container is the source color, adjusted for color relativity.
|
|
3545
|
+
* It maintains constant appearance in light mode and dark mode.
|
|
3546
|
+
* This adds ~5 tone in light mode, and subtracts ~5 tone in dark mode.
|
|
3547
|
+
* Tertiary Container is the complement to the source color, using
|
|
3548
|
+
* `TemperatureCache`. It also maintains constant appearance.
|
|
3549
|
+
*/
|
|
3550
|
+
class SchemeContent extends DynamicScheme {
|
|
3551
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3552
|
+
super({
|
|
3553
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3554
|
+
variant: Variant.CONTENT,
|
|
3555
|
+
contrastLevel,
|
|
3556
|
+
isDark,
|
|
3557
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma),
|
|
3558
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, Math.max(sourceColorHct.chroma - 32.0, sourceColorHct.chroma * 0.5)),
|
|
3559
|
+
tertiaryPalette: TonalPalette.fromInt(DislikeAnalyzer
|
|
3560
|
+
.fixIfDisliked(new TemperatureCache(sourceColorHct).analogous(3, 6)[2])
|
|
3561
|
+
.toInt()),
|
|
3562
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma / 8.0),
|
|
3563
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma / 8.0 + 4.0),
|
|
3564
|
+
});
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3218
3568
|
/**
|
|
3219
3569
|
* @license
|
|
3220
3570
|
* Copyright 2022 Google LLC
|
|
@@ -3295,6 +3645,223 @@ SchemeExpressive.tertiaryRotations = [
|
|
|
3295
3645
|
120.0,
|
|
3296
3646
|
];
|
|
3297
3647
|
|
|
3648
|
+
/**
|
|
3649
|
+
* @license
|
|
3650
|
+
* Copyright 2023 Google LLC
|
|
3651
|
+
*
|
|
3652
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3653
|
+
* you may not use this file except in compliance with the License.
|
|
3654
|
+
* You may obtain a copy of the License at
|
|
3655
|
+
*
|
|
3656
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3657
|
+
*
|
|
3658
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3659
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3660
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3661
|
+
* See the License for the specific language governing permissions and
|
|
3662
|
+
* limitations under the License.
|
|
3663
|
+
*/
|
|
3664
|
+
/**
|
|
3665
|
+
* A scheme that places the source color in `Scheme.primaryContainer`.
|
|
3666
|
+
*
|
|
3667
|
+
* Primary Container is the source color, adjusted for color relativity.
|
|
3668
|
+
* It maintains constant appearance in light mode and dark mode.
|
|
3669
|
+
* This adds ~5 tone in light mode, and subtracts ~5 tone in dark mode.
|
|
3670
|
+
* Tertiary Container is the complement to the source color, using
|
|
3671
|
+
* `TemperatureCache`. It also maintains constant appearance.
|
|
3672
|
+
*/
|
|
3673
|
+
class SchemeFidelity extends DynamicScheme {
|
|
3674
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3675
|
+
super({
|
|
3676
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3677
|
+
variant: Variant.FIDELITY,
|
|
3678
|
+
contrastLevel,
|
|
3679
|
+
isDark,
|
|
3680
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma),
|
|
3681
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, Math.max(sourceColorHct.chroma - 32.0, sourceColorHct.chroma * 0.5)),
|
|
3682
|
+
tertiaryPalette: TonalPalette.fromInt(DislikeAnalyzer
|
|
3683
|
+
.fixIfDisliked(new TemperatureCache(sourceColorHct).complement)
|
|
3684
|
+
.toInt()),
|
|
3685
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma / 8.0),
|
|
3686
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, sourceColorHct.chroma / 8.0 + 4.0),
|
|
3687
|
+
});
|
|
3688
|
+
}
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3691
|
+
/**
|
|
3692
|
+
* @license
|
|
3693
|
+
* Copyright 2022 Google LLC
|
|
3694
|
+
*
|
|
3695
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3696
|
+
* you may not use this file except in compliance with the License.
|
|
3697
|
+
* You may obtain a copy of the License at
|
|
3698
|
+
*
|
|
3699
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3700
|
+
*
|
|
3701
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3702
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3703
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3704
|
+
* See the License for the specific language governing permissions and
|
|
3705
|
+
* limitations under the License.
|
|
3706
|
+
*/
|
|
3707
|
+
/**
|
|
3708
|
+
* A playful theme - the source color's hue does not appear in the theme.
|
|
3709
|
+
*/
|
|
3710
|
+
class SchemeFruitSalad extends DynamicScheme {
|
|
3711
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3712
|
+
super({
|
|
3713
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3714
|
+
variant: Variant.FRUIT_SALAD,
|
|
3715
|
+
contrastLevel,
|
|
3716
|
+
isDark,
|
|
3717
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sanitizeDegreesDouble(sourceColorHct.hue - 50.0), 48.0),
|
|
3718
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sanitizeDegreesDouble(sourceColorHct.hue - 50.0), 36.0),
|
|
3719
|
+
tertiaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 36.0),
|
|
3720
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 10.0),
|
|
3721
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 16.0),
|
|
3722
|
+
});
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
/**
|
|
3727
|
+
* @license
|
|
3728
|
+
* Copyright 2022 Google LLC
|
|
3729
|
+
*
|
|
3730
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3731
|
+
* you may not use this file except in compliance with the License.
|
|
3732
|
+
* You may obtain a copy of the License at
|
|
3733
|
+
*
|
|
3734
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3735
|
+
*
|
|
3736
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3737
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3738
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3739
|
+
* See the License for the specific language governing permissions and
|
|
3740
|
+
* limitations under the License.
|
|
3741
|
+
*/
|
|
3742
|
+
/** A Dynamic Color theme that is grayscale. */
|
|
3743
|
+
class SchemeMonochrome extends DynamicScheme {
|
|
3744
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3745
|
+
super({
|
|
3746
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3747
|
+
variant: Variant.MONOCHROME,
|
|
3748
|
+
contrastLevel,
|
|
3749
|
+
isDark,
|
|
3750
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3751
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3752
|
+
tertiaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3753
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3754
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3755
|
+
});
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
/**
|
|
3760
|
+
* @license
|
|
3761
|
+
* Copyright 2022 Google LLC
|
|
3762
|
+
*
|
|
3763
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3764
|
+
* you may not use this file except in compliance with the License.
|
|
3765
|
+
* You may obtain a copy of the License at
|
|
3766
|
+
*
|
|
3767
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3768
|
+
*
|
|
3769
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3770
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3771
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3772
|
+
* See the License for the specific language governing permissions and
|
|
3773
|
+
* limitations under the License.
|
|
3774
|
+
*/
|
|
3775
|
+
/** A Dynamic Color theme that is near grayscale. */
|
|
3776
|
+
class SchemeNeutral extends DynamicScheme {
|
|
3777
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3778
|
+
super({
|
|
3779
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3780
|
+
variant: Variant.NEUTRAL,
|
|
3781
|
+
contrastLevel,
|
|
3782
|
+
isDark,
|
|
3783
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 12.0),
|
|
3784
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 8.0),
|
|
3785
|
+
tertiaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 16.0),
|
|
3786
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 2.0),
|
|
3787
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 2.0),
|
|
3788
|
+
});
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
/**
|
|
3793
|
+
* @license
|
|
3794
|
+
* Copyright 2022 Google LLC
|
|
3795
|
+
*
|
|
3796
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3797
|
+
* you may not use this file except in compliance with the License.
|
|
3798
|
+
* You may obtain a copy of the License at
|
|
3799
|
+
*
|
|
3800
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3801
|
+
*
|
|
3802
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3803
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3804
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3805
|
+
* See the License for the specific language governing permissions and
|
|
3806
|
+
* limitations under the License.
|
|
3807
|
+
*/
|
|
3808
|
+
/**
|
|
3809
|
+
* A playful theme - the source color's hue does not appear in the theme.
|
|
3810
|
+
*/
|
|
3811
|
+
class SchemeRainbow extends DynamicScheme {
|
|
3812
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3813
|
+
super({
|
|
3814
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3815
|
+
variant: Variant.RAINBOW,
|
|
3816
|
+
contrastLevel,
|
|
3817
|
+
isDark,
|
|
3818
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 48.0),
|
|
3819
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 16.0),
|
|
3820
|
+
tertiaryPalette: TonalPalette.fromHueAndChroma(sanitizeDegreesDouble(sourceColorHct.hue + 60.0), 24.0),
|
|
3821
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3822
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 0.0),
|
|
3823
|
+
});
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
/**
|
|
3828
|
+
* @license
|
|
3829
|
+
* Copyright 2022 Google LLC
|
|
3830
|
+
*
|
|
3831
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3832
|
+
* you may not use this file except in compliance with the License.
|
|
3833
|
+
* You may obtain a copy of the License at
|
|
3834
|
+
*
|
|
3835
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3836
|
+
*
|
|
3837
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3838
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3839
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3840
|
+
* See the License for the specific language governing permissions and
|
|
3841
|
+
* limitations under the License.
|
|
3842
|
+
*/
|
|
3843
|
+
/**
|
|
3844
|
+
* A Dynamic Color theme with low to medium colorfulness and a Tertiary
|
|
3845
|
+
* TonalPalette with a hue related to the source color.
|
|
3846
|
+
*
|
|
3847
|
+
* The default Material You theme on Android 12 and 13.
|
|
3848
|
+
*/
|
|
3849
|
+
class SchemeTonalSpot extends DynamicScheme {
|
|
3850
|
+
constructor(sourceColorHct, isDark, contrastLevel) {
|
|
3851
|
+
super({
|
|
3852
|
+
sourceColorArgb: sourceColorHct.toInt(),
|
|
3853
|
+
variant: Variant.TONAL_SPOT,
|
|
3854
|
+
contrastLevel,
|
|
3855
|
+
isDark,
|
|
3856
|
+
primaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 36.0),
|
|
3857
|
+
secondaryPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 16.0),
|
|
3858
|
+
tertiaryPalette: TonalPalette.fromHueAndChroma(sanitizeDegreesDouble(sourceColorHct.hue + 60.0), 24.0),
|
|
3859
|
+
neutralPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 6.0),
|
|
3860
|
+
neutralVariantPalette: TonalPalette.fromHueAndChroma(sourceColorHct.hue, 8.0),
|
|
3861
|
+
});
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3298
3865
|
/**
|
|
3299
3866
|
* @license
|
|
3300
3867
|
* Copyright 2022 Google LLC
|
|
@@ -3452,7 +4019,7 @@ function parseIntHex(value) {
|
|
|
3452
4019
|
return parseInt(value, 16);
|
|
3453
4020
|
}
|
|
3454
4021
|
|
|
3455
|
-
var _M3eThemeElement_instances, _M3eThemeElement_styleSheet, _M3eThemeElement_firstUpdated, _M3eThemeElement_light, _M3eThemeElement_dark, _M3eThemeElement_forcedColor, _M3eThemeElement_colorSchemeChangeHandler,
|
|
4022
|
+
var _M3eThemeElement_instances, _M3eThemeElement_styleSheet, _M3eThemeElement_firstUpdated, _M3eThemeElement_light, _M3eThemeElement_dark, _M3eThemeElement_forcedColor, _M3eThemeElement_colorSchemeChangeHandler, _M3eThemeElement_createScheme, _M3eThemeElement_apply, _M3eThemeElement_getContrastLevel;
|
|
3456
4023
|
/**
|
|
3457
4024
|
* A non-visual element responsible for application-level theming.
|
|
3458
4025
|
*
|
|
@@ -3473,7 +4040,7 @@ var _M3eThemeElement_instances, _M3eThemeElement_styleSheet, _M3eThemeElement_fi
|
|
|
3473
4040
|
*
|
|
3474
4041
|
* ```html
|
|
3475
4042
|
* <body>
|
|
3476
|
-
* <m3e-theme color="#
|
|
4043
|
+
* <m3e-theme color="#6750A4" scheme="auto" motion="expressive" strong-focus>
|
|
3477
4044
|
* <!-- Normal body content here. -->
|
|
3478
4045
|
* </m3e-theme>
|
|
3479
4046
|
* <body/>
|
|
@@ -3501,14 +4068,14 @@ let M3eThemeElement = class M3eThemeElement extends LitElement {
|
|
|
3501
4068
|
/** @private */ _M3eThemeElement_colorSchemeChangeHandler.set(this, () => __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_apply).call(this));
|
|
3502
4069
|
/**
|
|
3503
4070
|
* The hex color from which to derive dynamic color palettes.
|
|
3504
|
-
* @default "#
|
|
4071
|
+
* @default "#6750A4"
|
|
3505
4072
|
*/
|
|
3506
|
-
this.color = "#
|
|
4073
|
+
this.color = "#6750A4";
|
|
3507
4074
|
/**
|
|
3508
4075
|
* The color variant of the theme.
|
|
3509
|
-
* @default "
|
|
4076
|
+
* @default "content"
|
|
3510
4077
|
*/
|
|
3511
|
-
this.variant = "
|
|
4078
|
+
this.variant = "content";
|
|
3512
4079
|
/**
|
|
3513
4080
|
* The color scheme of the theme.
|
|
3514
4081
|
* @default "auto"
|
|
@@ -3584,20 +4151,32 @@ _M3eThemeElement_dark = new WeakMap();
|
|
|
3584
4151
|
_M3eThemeElement_forcedColor = new WeakMap();
|
|
3585
4152
|
_M3eThemeElement_colorSchemeChangeHandler = new WeakMap();
|
|
3586
4153
|
_M3eThemeElement_instances = new WeakSet();
|
|
4154
|
+
_M3eThemeElement_createScheme = function _M3eThemeElement_createScheme(sourceColor) {
|
|
4155
|
+
switch (this.variant) {
|
|
4156
|
+
case "content":
|
|
4157
|
+
return new SchemeContent(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4158
|
+
case "expressive":
|
|
4159
|
+
return new SchemeExpressive(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4160
|
+
case "fidelity":
|
|
4161
|
+
return new SchemeFidelity(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4162
|
+
case "fruit-salad":
|
|
4163
|
+
return new SchemeFruitSalad(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4164
|
+
case "monochrome":
|
|
4165
|
+
return new SchemeMonochrome(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4166
|
+
case "neutral":
|
|
4167
|
+
return new SchemeNeutral(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4168
|
+
case "rainbow":
|
|
4169
|
+
return new SchemeRainbow(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4170
|
+
case "tonal-spot":
|
|
4171
|
+
return new SchemeTonalSpot(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4172
|
+
case "vibrant":
|
|
4173
|
+
return new SchemeVibrant(sourceColor, this.isDark, __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this));
|
|
4174
|
+
}
|
|
4175
|
+
};
|
|
3587
4176
|
_M3eThemeElement_apply = function _M3eThemeElement_apply() {
|
|
3588
4177
|
const color = argbFromHex(this.color);
|
|
3589
4178
|
const palette = CorePalette.of(color);
|
|
3590
|
-
const scheme =
|
|
3591
|
-
sourceColorArgb: color,
|
|
3592
|
-
variant: __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getVariant).call(this),
|
|
3593
|
-
contrastLevel: __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_getContrastLevel).call(this),
|
|
3594
|
-
isDark: this.isDark,
|
|
3595
|
-
primaryPalette: palette.a1,
|
|
3596
|
-
secondaryPalette: palette.a2,
|
|
3597
|
-
tertiaryPalette: palette.a3,
|
|
3598
|
-
neutralPalette: palette.n1,
|
|
3599
|
-
neutralVariantPalette: palette.n2,
|
|
3600
|
-
});
|
|
4179
|
+
const scheme = __classPrivateFieldGet(this, _M3eThemeElement_instances, "m", _M3eThemeElement_createScheme).call(this, Hct.fromInt(color));
|
|
3601
4180
|
let css = "";
|
|
3602
4181
|
for (const key in MaterialDynamicColors) {
|
|
3603
4182
|
if (!key.endsWith("PaletteKeyColor")) {
|
|
@@ -3639,28 +4218,6 @@ _M3eThemeElement_apply = function _M3eThemeElement_apply() {
|
|
|
3639
4218
|
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
3640
4219
|
}
|
|
3641
4220
|
};
|
|
3642
|
-
_M3eThemeElement_getVariant = function _M3eThemeElement_getVariant() {
|
|
3643
|
-
switch (this.variant) {
|
|
3644
|
-
case "monochrome":
|
|
3645
|
-
return 0;
|
|
3646
|
-
case "neutral":
|
|
3647
|
-
return 1;
|
|
3648
|
-
case "tonal-spot":
|
|
3649
|
-
return 2;
|
|
3650
|
-
case "vibrant":
|
|
3651
|
-
return 3;
|
|
3652
|
-
case "expressive":
|
|
3653
|
-
return 4;
|
|
3654
|
-
case "fidelity":
|
|
3655
|
-
return 5;
|
|
3656
|
-
case "rainbow":
|
|
3657
|
-
return 7;
|
|
3658
|
-
case "fruit-salad":
|
|
3659
|
-
return 8;
|
|
3660
|
-
default: // content
|
|
3661
|
-
return 6;
|
|
3662
|
-
}
|
|
3663
|
-
};
|
|
3664
4221
|
_M3eThemeElement_getContrastLevel = function _M3eThemeElement_getContrastLevel() {
|
|
3665
4222
|
switch (this.contrast) {
|
|
3666
4223
|
case "high":
|