@m3e/theme 1.0.0-rc.2 → 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/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, _M3eThemeElement_apply, _M3eThemeElement_getVariant, _M3eThemeElement_getContrastLevel;
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="#7D67BE" scheme="auto" motion="expressive" strong-focus>
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 "#7D67BE"
4071
+ * @default "#6750A4"
3505
4072
  */
3506
- this.color = "#7D67BE";
4073
+ this.color = "#6750A4";
3507
4074
  /**
3508
4075
  * The color variant of the theme.
3509
- * @default "vibrant"
4076
+ * @default "content"
3510
4077
  */
3511
- this.variant = "vibrant";
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 = new DynamicScheme({
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":