@m3e/web 2.5.2 → 2.5.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/all.js +1039 -40
- package/dist/all.js.map +1 -1
- package/dist/all.min.js +158 -45
- package/dist/all.min.js.map +1 -1
- package/dist/autocomplete.js +2 -2
- package/dist/autocomplete.js.map +1 -1
- package/dist/autocomplete.min.js +1 -1
- package/dist/autocomplete.min.js.map +1 -1
- package/dist/bottom-sheet.js +2 -2
- package/dist/bottom-sheet.js.map +1 -1
- package/dist/bottom-sheet.min.js +1 -1
- package/dist/bottom-sheet.min.js.map +1 -1
- package/dist/calendar.js +12 -0
- package/dist/calendar.js.map +1 -1
- package/dist/calendar.min.js +5 -5
- package/dist/calendar.min.js.map +1 -1
- package/dist/chips.js +2 -2
- package/dist/chips.js.map +1 -1
- package/dist/chips.min.js +1 -1
- package/dist/chips.min.js.map +1 -1
- package/dist/core.js +2 -25
- package/dist/core.js.map +1 -1
- package/dist/core.min.js +1 -1
- package/dist/core.min.js.map +1 -1
- package/dist/css-custom-data.json +262 -262
- package/dist/custom-elements.json +1954 -2000
- package/dist/datepicker.js +6 -0
- package/dist/datepicker.js.map +1 -1
- package/dist/datepicker.min.js +1 -1
- package/dist/datepicker.min.js.map +1 -1
- package/dist/dialog.js +2 -2
- package/dist/dialog.js.map +1 -1
- package/dist/dialog.min.js +1 -1
- package/dist/dialog.min.js.map +1 -1
- package/dist/expansion-panel.js +2 -2
- package/dist/expansion-panel.js.map +1 -1
- package/dist/expansion-panel.min.js +1 -1
- package/dist/expansion-panel.min.js.map +1 -1
- package/dist/html-custom-data.json +92 -92
- package/dist/icon.js +1 -1
- package/dist/icon.js.map +1 -1
- package/dist/icon.min.js +1 -1
- package/dist/icon.min.js.map +1 -1
- package/dist/list.js +1 -1
- package/dist/list.js.map +1 -1
- package/dist/list.min.js +1 -1
- package/dist/list.min.js.map +1 -1
- package/dist/nav-bar.js +1 -1
- package/dist/nav-bar.js.map +1 -1
- package/dist/nav-bar.min.js +1 -1
- package/dist/nav-bar.min.js.map +1 -1
- package/dist/nav-menu.js +2 -2
- package/dist/nav-menu.js.map +1 -1
- package/dist/nav-menu.min.js +1 -1
- package/dist/nav-menu.min.js.map +1 -1
- package/dist/paginator.js +2 -2
- package/dist/paginator.js.map +1 -1
- package/dist/paginator.min.js +2 -2
- package/dist/paginator.min.js.map +1 -1
- package/dist/search.js +3 -3
- package/dist/search.js.map +1 -1
- package/dist/search.min.js +1 -1
- package/dist/search.min.js.map +1 -1
- package/dist/src/autocomplete/AutocompleteElement.d.ts.map +1 -1
- package/dist/src/bottom-sheet/BottomSheetElement.d.ts.map +1 -1
- package/dist/src/calendar/CalendarElement.d.ts.map +1 -1
- package/dist/src/chips/InputChipElement.d.ts.map +1 -1
- package/dist/src/core/shared/mixins/index.d.ts +0 -1
- package/dist/src/core/shared/mixins/index.d.ts.map +1 -1
- package/dist/src/core/shared/primitives/CollapsibleElement.d.ts.map +1 -1
- package/dist/src/datepicker/DatepickerElement.d.ts.map +1 -1
- package/dist/src/dialog/DialogElement.d.ts.map +1 -1
- package/dist/src/expansion-panel/ExpansionPanelElement.d.ts.map +1 -1
- package/dist/src/icon/IconElement.d.ts.map +1 -1
- package/dist/src/list/ListItemButtonElement.d.ts +0 -5
- package/dist/src/list/ListItemButtonElement.d.ts.map +1 -1
- package/dist/src/nav-bar/NavItemElement.d.ts.map +1 -1
- package/dist/src/nav-menu/NavMenuItemElement.d.ts.map +1 -1
- package/dist/src/paginator/PaginatorElement.d.ts.map +1 -1
- package/dist/src/search/SearchBarElement.d.ts.map +1 -1
- package/dist/src/search/SearchViewElement.d.ts.map +1 -1
- package/dist/src/theme/getColorFromImage.d.ts +12 -0
- package/dist/src/theme/getColorFromImage.d.ts.map +1 -0
- package/dist/src/theme/index.d.ts +1 -0
- package/dist/src/theme/index.d.ts.map +1 -1
- package/dist/src/tree/TreeItemElement.d.ts.map +1 -1
- package/dist/theme.js +1005 -1
- package/dist/theme.js.map +1 -1
- package/dist/theme.min.js +133 -20
- package/dist/theme.min.js.map +1 -1
- package/dist/toc.js +1 -1
- package/dist/toc.js.map +1 -1
- package/dist/toc.min.js +1 -1
- package/dist/toc.min.js.map +1 -1
- package/dist/tree.js +2 -2
- package/dist/tree.js.map +1 -1
- package/dist/tree.min.js +1 -1
- package/dist/tree.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/core/shared/mixins/EventAttribute.d.ts +0 -11
- package/dist/src/core/shared/mixins/EventAttribute.d.ts.map +0 -1
package/dist/all.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { __classPrivateFieldGet, __decorate, __classPrivateFieldSet } from 'tslib';
|
|
7
7
|
import { unsafeCSS, css, LitElement, html, nothing, isServer, noChange, svg } from 'lit';
|
|
8
8
|
import { query, property, queryAssignedElements, state } from 'lit/decorators.js';
|
|
9
|
-
import { DesignToken as DesignToken$1, HtmlFor as HtmlFor$1, Role as Role$1, hasAssignedNodes as hasAssignedNodes$1, debounce as debounce$1, customElement as customElement$1,
|
|
9
|
+
import { DesignToken as DesignToken$1, HtmlFor as HtmlFor$1, Role as Role$1, hasAssignedNodes as hasAssignedNodes$1, debounce as debounce$1, customElement as customElement$1, MutationController as MutationController$1, setCustomState as setCustomState$1, deleteCustomState as deleteCustomState$1, prefersReducedMotion as prefersReducedMotion$1, scrollIntoViewIfNeeded as scrollIntoViewIfNeeded$1, forcedColorsActive as forcedColorsActive$1, addCustomState as addCustomState$1, ActionElementBase as ActionElementBase$1, ReconnectedCallback as ReconnectedCallback$1, SuppressInitialAnimation as SuppressInitialAnimation$1, AttachInternals as AttachInternals$1, VelocityTracker as VelocityTracker$1, ScrollLockController as ScrollLockController$1, InertController as InertController$1, ResizeController as ResizeController$1, focusWhenReady as focusWhenReady$1, hasCustomState as hasCustomState$1, computeCssSize as computeCssSize$1, registerStyleSheet as registerStyleSheet$1, spaceSeparatedStringConverter as spaceSeparatedStringConverter$1, KeyboardClick as KeyboardClick$1, LinkButton as LinkButton$1, Focusable as Focusable$1, Disabled as Disabled$1, renderPseudoLink as renderPseudoLink$1, FormSubmitter as FormSubmitter$1, DisabledInteractive as DisabledInteractive$1, FocusController as FocusController$1, PressedController as PressedController$1, isSelectedMixin as isSelectedMixin$1, dateConverter as dateConverter$1, Labelled as Labelled$1, RequiredConstraintValidation as RequiredConstraintValidation$1, Dirty as Dirty$1, Touched as Touched$1, Required as Required$1, ConstraintValidation as ConstraintValidation$1, CheckedIndeterminate as CheckedIndeterminate$1, FormAssociated as FormAssociated$1, HoverController as HoverController$1, formValue as formValue$1, isDisabledMixin as isDisabledMixin$1, isDisabledInteractiveMixin as isDisabledInteractiveMixin$1, isLinkButtonMixin as isLinkButtonMixin$1, getTextContent as getTextContent$1, Vertical as Vertical$1, Selected as Selected$1, getScrollbarWidth as getScrollbarWidth$1, ScrollController as ScrollController$1, isReadOnlyMixin as isReadOnlyMixin$1, interceptProperty as interceptProperty$1, computeLineCount as computeLineCount$1, generateClipPaths as generateClipPaths$1, Checked as Checked$1, AnimationLoopController as AnimationLoopController$1, resolveFragmentUrl as resolveFragmentUrl$1, safeStyleMap as safeStyleMap$1, updateLabels as updateLabels$1, waitForUpgrade as waitForUpgrade$1, guid as guid$1, IntersectionController as IntersectionController$1, LongPressController as LongPressController$1 } from '@m3e/web/core';
|
|
10
10
|
import { ListKeyManager, M3eLiveAnnouncer, M3eInteractivityChecker, isModifierAllowed, addAriaReferencedId, removeAriaReferencedId, selectionManager, SelectionManager, ListManager, RovingTabIndexManager, M3eAriaDescriber, typeaheadLabel } from '@m3e/web/core/a11y';
|
|
11
11
|
import { M3eOptGroupElement as M3eOptGroupElement$1 } from '@m3e/web/option';
|
|
12
12
|
import { M3eDirectionality } from '@m3e/web/core/bidi';
|
|
@@ -407,7 +407,7 @@ var M3eAutocompleteElement_1;
|
|
|
407
407
|
* @fires query - Emitted when the input is focused or when the user modifies its value.
|
|
408
408
|
* @fires change - Emitted when the committed value changes due to selecting an option or clearing the input.
|
|
409
409
|
*/
|
|
410
|
-
let M3eAutocompleteElement = M3eAutocompleteElement_1 = class M3eAutocompleteElement extends
|
|
410
|
+
let M3eAutocompleteElement = M3eAutocompleteElement_1 = class M3eAutocompleteElement extends HtmlFor$1(LitElement) {
|
|
411
411
|
constructor() {
|
|
412
412
|
super();
|
|
413
413
|
_M3eAutocompleteElement_instances.add(this);
|
|
@@ -1507,7 +1507,7 @@ var M3eBottomSheetElement_1;
|
|
|
1507
1507
|
* @cssprop --m3e-bottom-sheet-header-line-height - Line height for the sheet header.
|
|
1508
1508
|
* @cssprop --m3e-bottom-sheet-header-tracking - Letter spacing (tracking) for the sheet header.
|
|
1509
1509
|
*/
|
|
1510
|
-
let M3eBottomSheetElement = M3eBottomSheetElement_1 = class M3eBottomSheetElement extends
|
|
1510
|
+
let M3eBottomSheetElement = M3eBottomSheetElement_1 = class M3eBottomSheetElement extends ReconnectedCallback$1(SuppressInitialAnimation$1(AttachInternals$1(LitElement))) {
|
|
1511
1511
|
constructor() {
|
|
1512
1512
|
super(...arguments);
|
|
1513
1513
|
_M3eBottomSheetElement_instances.add(this);
|
|
@@ -4862,6 +4862,18 @@ let M3eCalendarElement = class M3eCalendarElement extends LitElement {
|
|
|
4862
4862
|
if (changedProperties.has("startAt")) {
|
|
4863
4863
|
this._activeDate = new Date(this.startAt ?? this.date ?? this._today);
|
|
4864
4864
|
}
|
|
4865
|
+
if (changedProperties.has("rangeStart") && this.rangeStart) {
|
|
4866
|
+
this._activeDate = new Date(this.rangeStart);
|
|
4867
|
+
if (!changedProperties.has("date")) {
|
|
4868
|
+
this.date = new Date(this.rangeStart);
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
if (changedProperties.has("rangeEnd") && this.rangeEnd) {
|
|
4872
|
+
this._activeDate = new Date(this.rangeEnd);
|
|
4873
|
+
if (!changedProperties.has("date")) {
|
|
4874
|
+
this.date = new Date(this.rangeEnd);
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4865
4877
|
if (changedProperties.has("startView")) {
|
|
4866
4878
|
this._activeView = this.startView;
|
|
4867
4879
|
}
|
|
@@ -6225,7 +6237,7 @@ var _M3eInputChipElement_instances, _M3eInputChipElement_handleAvatarSlotChange,
|
|
|
6225
6237
|
* @cssprop --m3e-chip-disabled-avatar-opacity - Opacity applied to the avatar when disabled.
|
|
6226
6238
|
* @cssprop --m3e-chip-with-avatar-padding-start - Start padding when an avatar is present.
|
|
6227
6239
|
*/
|
|
6228
|
-
let M3eInputChipElement = class M3eInputChipElement extends
|
|
6240
|
+
let M3eInputChipElement = class M3eInputChipElement extends DisabledInteractive$1(Disabled$1(Role$1(M3eChipElement, "row"))) {
|
|
6229
6241
|
constructor() {
|
|
6230
6242
|
super(...arguments);
|
|
6231
6243
|
_M3eInputChipElement_instances.add(this);
|
|
@@ -9810,29 +9822,6 @@ function ConstraintValidation(base) {
|
|
|
9810
9822
|
return _ConstraintValidation;
|
|
9811
9823
|
}
|
|
9812
9824
|
|
|
9813
|
-
/**
|
|
9814
|
-
* Mixin that adds support for custom event attributes.
|
|
9815
|
-
* @template T The type of base class from which to inherit.
|
|
9816
|
-
* @param {T} base The base class from which to inherit.
|
|
9817
|
-
* @param {string[]} types The types of event attributes.
|
|
9818
|
-
* @returns {T} A class extending `base` that supports custom event attributes.
|
|
9819
|
-
*/
|
|
9820
|
-
function EventAttribute(base, ...types) {
|
|
9821
|
-
class _EventAttribute extends base {
|
|
9822
|
-
/** @internal */
|
|
9823
|
-
dispatchEvent(event) {
|
|
9824
|
-
if (types.includes(event.type)) {
|
|
9825
|
-
const eventAttribute = this.getAttribute(`on${event.type}`);
|
|
9826
|
-
if (eventAttribute) {
|
|
9827
|
-
new Function("e", `${eventAttribute};`).call(this, event);
|
|
9828
|
-
}
|
|
9829
|
-
}
|
|
9830
|
-
return super.dispatchEvent(event);
|
|
9831
|
-
}
|
|
9832
|
-
}
|
|
9833
|
-
return _EventAttribute;
|
|
9834
|
-
}
|
|
9835
|
-
|
|
9836
9825
|
const _tabindex = Symbol("_tabindex");
|
|
9837
9826
|
/**
|
|
9838
9827
|
* Mixin to augment an element with behavior that supports a focused state.
|
|
@@ -10563,7 +10552,7 @@ var _M3eCollapsibleElement_instances, _M3eCollapsibleElement_slotChanged, _M3eCo
|
|
|
10563
10552
|
*
|
|
10564
10553
|
* @cssprop --m3e-collapsible-animation-duration - The duration of the expand / collapse animation.
|
|
10565
10554
|
*/
|
|
10566
|
-
let M3eCollapsibleElement = class M3eCollapsibleElement extends
|
|
10555
|
+
let M3eCollapsibleElement = class M3eCollapsibleElement extends AttachInternals(LitElement) {
|
|
10567
10556
|
constructor() {
|
|
10568
10557
|
super(...arguments);
|
|
10569
10558
|
_M3eCollapsibleElement_instances.add(this);
|
|
@@ -12224,6 +12213,12 @@ let M3eDatepickerElement = M3eDatepickerElement_1 = class M3eDatepickerElement e
|
|
|
12224
12213
|
if (["date", "rangeStart", "rangeEnd"].some(x => changedProperties.has(x))) {
|
|
12225
12214
|
__classPrivateFieldGet(this, _M3eDatepickerElement_instances, "m", _M3eDatepickerElement_clearSelectionState).call(this);
|
|
12226
12215
|
}
|
|
12216
|
+
if (changedProperties.has("rangeStart") && this.rangeStart && !changedProperties.has("date")) {
|
|
12217
|
+
this.date = new Date(this.rangeStart);
|
|
12218
|
+
}
|
|
12219
|
+
if (changedProperties.has("rangeEnd") && this.rangeEnd && !changedProperties.has("date")) {
|
|
12220
|
+
this.date = new Date(this.rangeEnd);
|
|
12221
|
+
}
|
|
12227
12222
|
if (changedProperties.has("variant")) {
|
|
12228
12223
|
__classPrivateFieldGet(this, _M3eDatepickerElement_breakpointUnobserve, "f")?.call(this);
|
|
12229
12224
|
if (this.variant === "auto") {
|
|
@@ -12561,7 +12556,7 @@ var M3eDialogElement_1;
|
|
|
12561
12556
|
* @cssprop --m3e-dialog-content-line-height - Line height for the dialog content.
|
|
12562
12557
|
* @cssprop --m3e-dialog-content-tracking - Letter spacing for the dialog content.
|
|
12563
12558
|
*/
|
|
12564
|
-
let M3eDialogElement = M3eDialogElement_1 = class M3eDialogElement extends
|
|
12559
|
+
let M3eDialogElement = M3eDialogElement_1 = class M3eDialogElement extends AttachInternals$1(LitElement) {
|
|
12565
12560
|
constructor() {
|
|
12566
12561
|
super(...arguments);
|
|
12567
12562
|
_M3eDialogElement_instances.add(this);
|
|
@@ -13596,7 +13591,7 @@ var M3eExpansionPanelElement_1;
|
|
|
13596
13591
|
* @cssprop --m3e-expansion-panel-actions-divider-thickness - Thickness of the divider above actions.
|
|
13597
13592
|
* @cssprop --m3e-expansion-panel-actions-divider-color - Color of the divider above actions.
|
|
13598
13593
|
*/
|
|
13599
|
-
let M3eExpansionPanelElement = M3eExpansionPanelElement_1 = class M3eExpansionPanelElement extends
|
|
13594
|
+
let M3eExpansionPanelElement = M3eExpansionPanelElement_1 = class M3eExpansionPanelElement extends Disabled$1(ReconnectedCallback$1(AttachInternals$1(LitElement, true))) {
|
|
13600
13595
|
constructor() {
|
|
13601
13596
|
super(...arguments);
|
|
13602
13597
|
_M3eExpansionPanelElement_instances.add(this);
|
|
@@ -16088,7 +16083,7 @@ let M3eIconElement = class M3eIconElement extends Role$1(LitElement, "img") {
|
|
|
16088
16083
|
};
|
|
16089
16084
|
_M3eIconElement_iconRegistryUnobserve = new WeakMap();
|
|
16090
16085
|
/** The styles of the element. */
|
|
16091
|
-
M3eIconElement.styles = css`:host { display: inline-block; user-select: none; font-size: var(--m3e-icon-size, 1.5rem); width: 1em; height: 1em; vertical-align: middle; overflow: hidden; } .icon { font-weight: normal; font-style: normal; line-height: 1; letter-spacing: normal; text-transform: none; white-space: nowrap; word-wrap: normal; direction: ltr; font-feature-settings: "liga"; -webkit-font-smoothing: antialiased; width: inherit; height: inherit; vertical-align: inherit; font-variation-settings: "FILL" var(--_icon-fill, 0), "wght" var(--_icon-weight, 400), "GRAD" var(--_icon-grade, 0), "opsz" var(--_icon-optical-size, 24); } :host([variant="outlined"]) .icon { font-family: "Material Symbols Outlined"; } :host([variant="rounded"]) .icon { font-family: "Material Symbols Rounded"; } :host([variant="sharp"]) .icon { font-family: "Material Symbols Sharp"; } svg { font-size: inherit; width: 1em; height: 1em; }`;
|
|
16086
|
+
M3eIconElement.styles = css`:host { display: inline-block; user-select: none; font-size: var(--m3e-icon-size, 1.5rem); width: 1em; height: 1em; vertical-align: middle; overflow: hidden; } .icon { font-weight: normal; font-style: normal; line-height: 1; letter-spacing: normal; text-transform: none; white-space: nowrap; word-wrap: normal; direction: ltr; font-feature-settings: "liga"; -webkit-font-smoothing: antialiased; width: inherit; height: inherit; vertical-align: inherit; font-variation-settings: "FILL" var(--_icon-fill, 0), "wght" var(--_icon-weight, 400), "GRAD" var(--_icon-grade, 0), "opsz" var(--_icon-optical-size, 24); } :host([variant="outlined"]) .icon { font-family: "Material Symbols Outlined"; } :host([variant="rounded"]) .icon { font-family: "Material Symbols Rounded"; } :host([variant="sharp"]) .icon { font-family: "Material Symbols Sharp"; } svg { fill: currentColor; font-size: inherit; width: 1em; height: 1em; }`;
|
|
16092
16087
|
__decorate([query(".icon")], M3eIconElement.prototype, "_icon", void 0);
|
|
16093
16088
|
__decorate([property()], M3eIconElement.prototype, "name", void 0);
|
|
16094
16089
|
__decorate([property({
|
|
@@ -18127,7 +18122,7 @@ _M3eListOptionElement_handleClick = function _M3eListOptionElement_handleClick(e
|
|
|
18127
18122
|
}
|
|
18128
18123
|
};
|
|
18129
18124
|
/** The styles of the element. */
|
|
18130
|
-
M3eListOptionElement.styles = [M3eListItemElement.styles, css`:host { outline: none; user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .base { position: relative; } .indicator { min-width: 1.5rem; min-height: 1.5rem; display: flex; align-items: center; justify-content: center; } :host(:not(:disabled)) { cursor: pointer; } :host(:state(-three-line)) .indicator { align-self: flex-start; margin-top: var(--m3e-list-item-three-line-top-offset, 0.25rem); } :host([selected]) .base, :host([selected]) .state-layer, :host([selected]) .ripple, :host([selected]) .focus-ring { border-radius: var(--m3e-list-item-selected-container-shape, ${DesignToken$1.shape.corner.large}); } :host([selected]:not(:disabled)) .
|
|
18125
|
+
M3eListOptionElement.styles = [M3eListItemElement.styles, css`:host { outline: none; user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .base { position: relative; } .indicator { min-width: 1.5rem; min-height: 1.5rem; display: flex; align-items: center; justify-content: center; } :host(:not(:disabled)) { cursor: pointer; } :host(:state(-three-line)) .indicator { align-self: flex-start; margin-top: var(--m3e-list-item-three-line-top-offset, 0.25rem); } :host([selected]) .base, :host([selected]) .state-layer, :host([selected]) .ripple, :host([selected]) .focus-ring { border-radius: var(--m3e-list-item-selected-container-shape, ${DesignToken$1.shape.corner.large}); } :host([selected]:not(:disabled)) .content { color: var(--m3e-list-item-selected-label-text-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([selected]:not(:disabled)) ::slotted([slot="overline"]) { color: var(--m3e-list-item-selected-overline-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([selected]:not(:disabled)) ::slotted([slot="supporting-text"]) { color: var(--m3e-list-item-selected-supporting-text-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([selected]:not(:disabled)) ::slotted([slot="leading"]) { color: var(--m3e-list-item-selected-leading-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([selected]:not(:disabled)) ::slotted([slot="trailing"]) { color: var(--m3e-list-item-selected-trailing-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([selected]:not(:disabled)) .base { background-color: var(--m3e-list-item-selected-container-color, ${DesignToken$1.color.secondaryContainer}); } :host([selected]:disabled) .base { background-color: color-mix( in srgb, var(--m3e-list-item-selected-disabled-container-color, ${DesignToken$1.color.onSurface}) var(--m3e-list-item-selected-disabled-container-opacity, 10%), transparent ); } :host([selected]:not(:disabled)) .state-layer { --m3e-state-layer-hover-color: var( --m3e-list-item-selected-hover-state-layer-color, ${DesignToken$1.color.onSurface} ); --m3e-state-layer-hover-opacity: var( --m3e-list-item-selected-hover-state-layer-opacity, ${DesignToken$1.state.hoverStateLayerOpacity} ); --m3e-state-layer-focus-color: var( --m3e-list-item-selected-focus-state-layer-color, ${DesignToken$1.color.onSurface} ); --m3e-state-layer-focus-opacity: var( --m3e-list-item-selected-focus-state-layer-opacity, ${DesignToken$1.state.focusStateLayerOpacity} ); } :host([selected]:not(:disabled)) .ripple { --m3e-ripple-color: var(--m3e-list-item-selected-pressed-state-layer-color, ${DesignToken$1.color.onSurface}); --m3e-ripple-opacity: var( --m3e-list-item-selected-pressed-state-layer-opacity, ${DesignToken$1.state.pressedStateLayerOpacity} ); } :host(:state(-hide-selection)) .indicator, :host(:not(:state(-hide-selection))) ::slotted([slot="trailing"]) { display: none; } @media (forced-colors: active) { :host([selected]:not(:disabled)) .content, :host([selected]:not(:disabled)) ::slotted([slot="overline"]), :host([selected]:not(:disabled)) ::slotted([slot="supporting-text"]), :host([selected]:not(:disabled)) ::slotted([slot="leading"]), :host([selected]:not(:disabled)) ::slotted([slot="trailing"]) { color: HighlightText; forced-color-adjust: none; } :host([selected]:not(:disabled)) .base { background-color: Highlight; } }`];
|
|
18131
18126
|
__decorate([query(".focus-ring")], M3eListOptionElement.prototype, "_focusRing", void 0);
|
|
18132
18127
|
__decorate([query(".state-layer")], M3eListOptionElement.prototype, "_stateLayer", void 0);
|
|
18133
18128
|
__decorate([query(".ripple")], M3eListOptionElement.prototype, "_ripple", void 0);
|
|
@@ -19721,7 +19716,7 @@ _M3eNavItemElement_handleSelectedIconSlotChange = function _M3eNavItemElement_ha
|
|
|
19721
19716
|
setCustomState$1(this, "-with-selected-icon", hasAssignedNodes$1(e.target));
|
|
19722
19717
|
};
|
|
19723
19718
|
/** The styles of the element. */
|
|
19724
|
-
M3eNavItemElement.styles = css`:host { display: inline-block; vertical-align: middle; position: relative; outline: none; user-select: none; flex: 1; font-size: var(--m3e-nav-item-label-text-font-size, ${DesignToken$1.typescale.standard.label.medium.fontSize}); font-weight: var( --m3e-nav-item-label-text-font-weight, ${DesignToken$1.typescale.standard.label.medium.fontWeight} ); line-height: var( --m3e-nav-item-label-text-line-height, ${DesignToken$1.typescale.standard.label.medium.lineHeight} ); letter-spacing: var(--m3e-nav-item-label-text-tracking, ${DesignToken$1.typescale.standard.label.medium.tracking}); border-radius: var(--m3e-nav-item-shape, ${DesignToken$1.shape.corner.full}); min-width: var(--_nav-item-min-width); align-self: var(--_nav-item-align-self); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } :host([orientation="horizontal"]) { max-width: fit-content; } :host(:not(:disabled):not([disabled-interactive])) { cursor: pointer; } :host([disabled-interactive]) { cursor: not-allowed; } .outer { height: 100%; } .outer, .inner { display: flex; align-items: center; justify-content: var(--_nav-item-justify-content, center); position: relative; border-radius: inherit; } .icon-wrapper { position: relative; flex: none; } .base { justify-content: unset; box-sizing: border-box; vertical-align: middle; display: inline-flex; align-items: center; justify-content: center; position: relative; width: 100%; } .icon { position: absolute; } .label { vertical-align: middle; } ::slotted([slot="icon"]), ::slotted([slot="selected-icon"]) { width: 1em; font-size: var(--m3e-nav-item-icon-size, 1.5rem) !important; } :host(:not([selected])) slot[name="selected-icon"], :host(:not(:state(-with-selected-icon))) slot[name="selected-icon"], :host([selected]:state(-with-selected-icon)) slot[name="icon"] { display: none; } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .outer { --m3e-state-layer-hover-color: var( --m3e-nav-item-inactive-hover-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-state-layer-focus-color: var( --m3e-nav-item-inactive-focus-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-ripple-color: var( --m3e-nav-item-inactive-pressed-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .label { color: var(--m3e-nav-item-inactive-label-text-color, ${DesignToken$1.color.onSurfaceVariant}); } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .icon { color: var(--m3e-nav-item-inactive-icon-color, ${DesignToken$1.color.
|
|
19719
|
+
M3eNavItemElement.styles = css`:host { display: inline-block; vertical-align: middle; position: relative; outline: none; user-select: none; flex: 1; font-size: var(--m3e-nav-item-label-text-font-size, ${DesignToken$1.typescale.standard.label.medium.fontSize}); font-weight: var( --m3e-nav-item-label-text-font-weight, ${DesignToken$1.typescale.standard.label.medium.fontWeight} ); line-height: var( --m3e-nav-item-label-text-line-height, ${DesignToken$1.typescale.standard.label.medium.lineHeight} ); letter-spacing: var(--m3e-nav-item-label-text-tracking, ${DesignToken$1.typescale.standard.label.medium.tracking}); border-radius: var(--m3e-nav-item-shape, ${DesignToken$1.shape.corner.full}); min-width: var(--_nav-item-min-width); align-self: var(--_nav-item-align-self); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } :host([orientation="horizontal"]) { max-width: fit-content; } :host(:not(:disabled):not([disabled-interactive])) { cursor: pointer; } :host([disabled-interactive]) { cursor: not-allowed; } .outer { height: 100%; } .outer, .inner { display: flex; align-items: center; justify-content: var(--_nav-item-justify-content, center); position: relative; border-radius: inherit; } .icon-wrapper { position: relative; flex: none; } .base { justify-content: unset; box-sizing: border-box; vertical-align: middle; display: inline-flex; align-items: center; justify-content: center; position: relative; width: 100%; } .icon { position: absolute; } .label { vertical-align: middle; } ::slotted([slot="icon"]), ::slotted([slot="selected-icon"]) { width: 1em; font-size: var(--m3e-nav-item-icon-size, 1.5rem) !important; } :host(:not([selected])) slot[name="selected-icon"], :host(:not(:state(-with-selected-icon))) slot[name="selected-icon"], :host([selected]:state(-with-selected-icon)) slot[name="icon"] { display: none; } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .outer { --m3e-state-layer-hover-color: var( --m3e-nav-item-inactive-hover-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-state-layer-focus-color: var( --m3e-nav-item-inactive-focus-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-ripple-color: var( --m3e-nav-item-inactive-pressed-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .label { color: var(--m3e-nav-item-inactive-label-text-color, ${DesignToken$1.color.onSurfaceVariant}); } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .icon { color: var(--m3e-nav-item-inactive-icon-color, ${DesignToken$1.color.onSurfaceVariant}); } :host([selected]:not(:disabled):not([disabled-interactive])) .outer { --m3e-state-layer-hover-color: var( --m3e-nav-item-active-hover-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-state-layer-focus-color: var( --m3e-nav-item-active-focus-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); --m3e-ripple-color: var( --m3e-nav-item-active-pressed-state-layer-color, ${DesignToken$1.color.onSecondaryContainer} ); } :host([selected]:not(:disabled):not([disabled-interactive]):not([orientation="horizontal"])) .label { color: var(--m3e-nav-item-active-label-text-color, ${DesignToken$1.color.secondary}); } :host([selected]:not(:disabled):not([disabled-interactive])) .state-layer { background-color: var(--m3e-nav-item-active-container-color, ${DesignToken$1.color.secondaryContainer}); } :host([selected]:not(:disabled):not([disabled-interactive])[orientation="horizontal"]) .label, :host([selected]:not(:disabled):not([disabled-interactive])) .icon { color: var(--m3e-nav-item-active-icon-color, ${DesignToken$1.color.onSecondaryContainer}); } :host([orientation="vertical"]) .outer { align-self: stretch; align-items: flex-start; } :host([orientation="vertical"]) .label { text-align: center; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-clamp: 2; } :host([orientation="vertical"]) .base { flex-direction: column; row-gap: var(--m3e-nav-item-spacing, 0.25rem); } :host([orientation="vertical"]) .base { margin-block: var(--m3e-vertical-nav-item-active-indicator-margin, 0.375rem); } :host([orientation="vertical"]) .state-layer, :host([orientation="vertical"]) .ripple { top: var(--m3e-vertical-nav-item-active-indicator-margin, 0.375rem); bottom: unset; } :host([orientation="vertical"]) .state-layer, :host([orientation="vertical"]) .ripple, :host([orientation="vertical"]) .icon-wrapper { width: var(--m3e-vertical-nav-item-active-indicator-width, 3.5rem); } :host([orientation="vertical"]) .state-layer, :host([orientation="vertical"]) .ripple, :host([orientation="vertical"]) .icon-wrapper { height: var(--m3e-vertical-nav-item-active-indicator-height, 2rem); } :host([orientation="vertical"]) .icon { top: calc( calc(var(--m3e-vertical-nav-item-active-indicator-height, 2rem) / 2) - calc( var(--m3e-nav-item-icon-size, 1.5rem) / 2 ) ); left: calc( calc(var(--m3e-vertical-nav-item-active-indicator-width, 3.5rem) / 2) - calc( var(--m3e-nav-item-icon-size, 1.5rem) / 2 ) ); } :host([orientation="vertical"]) .focus-ring { border-radius: var(--m3e-nav-item-focus-ring-shape, ${DesignToken$1.shape.corner.medium}); } :host([orientation="horizontal"]) .icon-wrapper { width: var(--m3e-nav-item-icon-size, 1.5rem); height: var(--m3e-nav-item-icon-size, 1.5rem); } :host([orientation="horizontal"]) .base { padding: var(--m3e-horizontal-nav-item-padding, 1rem); } :host([orientation="horizontal"]) .label { flex: 1 1 auto; } :host([orientation="horizontal"]) .base { column-gap: var(--m3e-nav-item-spacing, 0.25rem); } :host([orientation="horizontal"]) .inner { height: var(--m3e-horizontal-nav-item-active-indicator-height, 2.5rem); width: fit-content; } .state-layer, .ripple { margin-inline: auto; } :host(:disabled) .label, :host([disabled-interactive]) .label { color: color-mix( in srgb, var(--m3e-nav-item-disabled-label-text-color, ${DesignToken$1.color.onSurface}) var(--m3e-nav-item-disabled-label-text-opacity, 38%), transparent ); } :host(:disabled) .icon, :host([disabled-interactive]) .icon { color: color-mix( in srgb, var(--m3e-nav-item-disabled-icon-color, ${DesignToken$1.color.onSurface}) var(--m3e-nav-item-disabled-icon-opacity, 38%), transparent ); } a { all: unset; display: block; position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; z-index: 1; } @media (forced-colors: active) { :host(:disabled) .label, :host([disabled-interactive]) .label, :host(:disabled) .icon, :host([disabled-interactive]) .icon { color: GrayText; } :host(:not([selected]):not(:disabled):not([disabled-interactive])) .label, :host(:not([selected]):not(:disabled):not([disabled-interactive])) .icon { color: ButtonText; } :host([selected]:not(:disabled):not([disabled-interactive])) .state-layer { background-color: ButtonText; } :host([orientation="vertical"][selected]:not(:disabled):not([disabled-interactive])) .label { color: ButtonText; } :host([orientation="horizontal"][selected]:not(:disabled):not([disabled-interactive])) .label, :host([selected]:not(:disabled):not([disabled-interactive])) .icon { forced-color-adjust: none; color: ButtonFace; } }`;
|
|
19725
19720
|
__decorate([query(".focus-ring")], M3eNavItemElement.prototype, "_focusRing", void 0);
|
|
19726
19721
|
__decorate([query(".state-layer")], M3eNavItemElement.prototype, "_stateLayer", void 0);
|
|
19727
19722
|
__decorate([query(".ripple")], M3eNavItemElement.prototype, "_ripple", void 0);
|
|
@@ -19844,7 +19839,7 @@ var M3eNavMenuItemElement_1;
|
|
|
19844
19839
|
* @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements.
|
|
19845
19840
|
* @cssprop --m3e-nav-menu-item-vertical-inset - Vertical margin for first/last child items.
|
|
19846
19841
|
*/
|
|
19847
|
-
let M3eNavMenuItemElement = M3eNavMenuItemElement_1 = class M3eNavMenuItemElement extends Selected$1(Disabled$1(
|
|
19842
|
+
let M3eNavMenuItemElement = M3eNavMenuItemElement_1 = class M3eNavMenuItemElement extends Selected$1(Disabled$1(AttachInternals$1(Role$1(LitElement, "treeitem"), true))) {
|
|
19848
19843
|
constructor() {
|
|
19849
19844
|
super(...arguments);
|
|
19850
19845
|
_M3eNavMenuItemElement_instances.add(this);
|
|
@@ -21015,7 +21010,7 @@ var M3ePaginatorElement_1;
|
|
|
21015
21010
|
* @cssprop --m3e-paginator-line-height - The line height used for paginator text.
|
|
21016
21011
|
* @cssprop --m3e-paginator-tracking - The letter-spacing used for paginator text.
|
|
21017
21012
|
*/
|
|
21018
|
-
let M3ePaginatorElement = M3ePaginatorElement_1 = class M3ePaginatorElement extends
|
|
21013
|
+
let M3ePaginatorElement = M3ePaginatorElement_1 = class M3ePaginatorElement extends Role$1(LitElement, "group") {
|
|
21019
21014
|
constructor() {
|
|
21020
21015
|
super(...arguments);
|
|
21021
21016
|
_M3ePaginatorElement_instances.add(this);
|
|
@@ -22345,7 +22340,7 @@ var _M3eSearchBarElement_instances, _M3eSearchBarElement_input, _M3eSearchBarEle
|
|
|
22345
22340
|
* @cssprop --m3e-search-bar-trailing-actions-leading-space - Space between the input and trailing actions.
|
|
22346
22341
|
* @cssprop --m3e-search-bar-actions-gap - Gap between action icons.
|
|
22347
22342
|
*/
|
|
22348
|
-
let M3eSearchBarElement = class M3eSearchBarElement extends
|
|
22343
|
+
let M3eSearchBarElement = class M3eSearchBarElement extends AttachInternals$1(LitElement) {
|
|
22349
22344
|
constructor() {
|
|
22350
22345
|
super(...arguments);
|
|
22351
22346
|
_M3eSearchBarElement_instances.add(this);
|
|
@@ -22502,7 +22497,7 @@ var _M3eSearchViewElement_instances, _M3eSearchViewElement_input, _M3eSearchView
|
|
|
22502
22497
|
* @cssprop --m3e-search-view-docked-scrim-color - Color of the scrim behind the docked view.
|
|
22503
22498
|
* @cssprop --m3e-search-view-docked-scrim-opacity - Opacity of the scrim behind the docked view.
|
|
22504
22499
|
*/
|
|
22505
|
-
let M3eSearchViewElement = class M3eSearchViewElement extends
|
|
22500
|
+
let M3eSearchViewElement = class M3eSearchViewElement extends ReconnectedCallback$1(AttachInternals$1(LitElement)) {
|
|
22506
22501
|
constructor() {
|
|
22507
22502
|
super();
|
|
22508
22503
|
_M3eSearchViewElement_instances.add(this);
|
|
@@ -27856,6 +27851,19 @@ function clampDouble(min, max, input) {
|
|
|
27856
27851
|
}
|
|
27857
27852
|
return input;
|
|
27858
27853
|
}
|
|
27854
|
+
/**
|
|
27855
|
+
* Sanitizes a degree measure as an integer.
|
|
27856
|
+
*
|
|
27857
|
+
* @return a degree measure between 0 (inclusive) and 360
|
|
27858
|
+
* (exclusive).
|
|
27859
|
+
*/
|
|
27860
|
+
function sanitizeDegreesInt(degrees) {
|
|
27861
|
+
degrees = degrees % 360;
|
|
27862
|
+
if (degrees < 0) {
|
|
27863
|
+
degrees = degrees + 360;
|
|
27864
|
+
}
|
|
27865
|
+
return degrees;
|
|
27866
|
+
}
|
|
27859
27867
|
/**
|
|
27860
27868
|
* Sanitizes a degree measure as a floating-point number.
|
|
27861
27869
|
*
|
|
@@ -27869,6 +27877,12 @@ function sanitizeDegreesDouble(degrees) {
|
|
|
27869
27877
|
}
|
|
27870
27878
|
return degrees;
|
|
27871
27879
|
}
|
|
27880
|
+
/**
|
|
27881
|
+
* Distance of two points on a circle, represented using degrees.
|
|
27882
|
+
*/
|
|
27883
|
+
function differenceDegrees(a, b) {
|
|
27884
|
+
return 180.0 - Math.abs(Math.abs(a - b) - 180.0);
|
|
27885
|
+
}
|
|
27872
27886
|
/**
|
|
27873
27887
|
* Multiplies a 1x3 row vector with a 3x3 matrix.
|
|
27874
27888
|
*/
|
|
@@ -27920,6 +27934,12 @@ function argbFromLinrgb(linrgb) {
|
|
|
27920
27934
|
const b = delinearized(linrgb[2]);
|
|
27921
27935
|
return argbFromRgb(r, g, b);
|
|
27922
27936
|
}
|
|
27937
|
+
/**
|
|
27938
|
+
* Returns the alpha component of a color in ARGB format.
|
|
27939
|
+
*/
|
|
27940
|
+
function alphaFromArgb(argb) {
|
|
27941
|
+
return argb >> 24 & 255;
|
|
27942
|
+
}
|
|
27923
27943
|
/**
|
|
27924
27944
|
* Returns the red component of a color in ARGB format.
|
|
27925
27945
|
*/
|
|
@@ -27960,6 +27980,50 @@ function xyzFromArgb(argb) {
|
|
|
27960
27980
|
const b = linearized(blueFromArgb(argb));
|
|
27961
27981
|
return matrixMultiply([r, g, b], SRGB_TO_XYZ);
|
|
27962
27982
|
}
|
|
27983
|
+
/**
|
|
27984
|
+
* Converts a color represented in Lab color space into an ARGB
|
|
27985
|
+
* integer.
|
|
27986
|
+
*/
|
|
27987
|
+
function argbFromLab(l, a, b) {
|
|
27988
|
+
const whitePoint = WHITE_POINT_D65;
|
|
27989
|
+
const fy = (l + 16.0) / 116.0;
|
|
27990
|
+
const fx = a / 500.0 + fy;
|
|
27991
|
+
const fz = fy - b / 200.0;
|
|
27992
|
+
const xNormalized = labInvf(fx);
|
|
27993
|
+
const yNormalized = labInvf(fy);
|
|
27994
|
+
const zNormalized = labInvf(fz);
|
|
27995
|
+
const x = xNormalized * whitePoint[0];
|
|
27996
|
+
const y = yNormalized * whitePoint[1];
|
|
27997
|
+
const z = zNormalized * whitePoint[2];
|
|
27998
|
+
return argbFromXyz(x, y, z);
|
|
27999
|
+
}
|
|
28000
|
+
/**
|
|
28001
|
+
* Converts a color from ARGB representation to L*a*b*
|
|
28002
|
+
* representation.
|
|
28003
|
+
*
|
|
28004
|
+
* @param argb the ARGB representation of a color
|
|
28005
|
+
* @return a Lab object representing the color
|
|
28006
|
+
*/
|
|
28007
|
+
function labFromArgb(argb) {
|
|
28008
|
+
const linearR = linearized(redFromArgb(argb));
|
|
28009
|
+
const linearG = linearized(greenFromArgb(argb));
|
|
28010
|
+
const linearB = linearized(blueFromArgb(argb));
|
|
28011
|
+
const matrix = SRGB_TO_XYZ;
|
|
28012
|
+
const x = matrix[0][0] * linearR + matrix[0][1] * linearG + matrix[0][2] * linearB;
|
|
28013
|
+
const y = matrix[1][0] * linearR + matrix[1][1] * linearG + matrix[1][2] * linearB;
|
|
28014
|
+
const z = matrix[2][0] * linearR + matrix[2][1] * linearG + matrix[2][2] * linearB;
|
|
28015
|
+
const whitePoint = WHITE_POINT_D65;
|
|
28016
|
+
const xNormalized = x / whitePoint[0];
|
|
28017
|
+
const yNormalized = y / whitePoint[1];
|
|
28018
|
+
const zNormalized = z / whitePoint[2];
|
|
28019
|
+
const fx = labF(xNormalized);
|
|
28020
|
+
const fy = labF(yNormalized);
|
|
28021
|
+
const fz = labF(zNormalized);
|
|
28022
|
+
const l = 116.0 * fy - 16;
|
|
28023
|
+
const a = 500.0 * (fx - fy);
|
|
28024
|
+
const b = 200.0 * (fy - fz);
|
|
28025
|
+
return [l, a, b];
|
|
28026
|
+
}
|
|
27963
28027
|
/**
|
|
27964
28028
|
* Converts an L* value to an ARGB representation.
|
|
27965
28029
|
*
|
|
@@ -30667,6 +30731,712 @@ class CorePalette {
|
|
|
30667
30731
|
}
|
|
30668
30732
|
}
|
|
30669
30733
|
|
|
30734
|
+
/**
|
|
30735
|
+
* @license
|
|
30736
|
+
* Copyright 2021 Google LLC
|
|
30737
|
+
*
|
|
30738
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
30739
|
+
* you may not use this file except in compliance with the License.
|
|
30740
|
+
* You may obtain a copy of the License at
|
|
30741
|
+
*
|
|
30742
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
30743
|
+
*
|
|
30744
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
30745
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
30746
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
30747
|
+
* See the License for the specific language governing permissions and
|
|
30748
|
+
* limitations under the License.
|
|
30749
|
+
*/
|
|
30750
|
+
/**
|
|
30751
|
+
* Provides conversions needed for K-Means quantization. Converting input to
|
|
30752
|
+
* points, and converting the final state of the K-Means algorithm to colors.
|
|
30753
|
+
*/
|
|
30754
|
+
class LabPointProvider {
|
|
30755
|
+
/**
|
|
30756
|
+
* Convert a color represented in ARGB to a 3-element array of L*a*b*
|
|
30757
|
+
* coordinates of the color.
|
|
30758
|
+
*/
|
|
30759
|
+
fromInt(argb) {
|
|
30760
|
+
return labFromArgb(argb);
|
|
30761
|
+
}
|
|
30762
|
+
/**
|
|
30763
|
+
* Convert a 3-element array to a color represented in ARGB.
|
|
30764
|
+
*/
|
|
30765
|
+
toInt(point) {
|
|
30766
|
+
return argbFromLab(point[0], point[1], point[2]);
|
|
30767
|
+
}
|
|
30768
|
+
/**
|
|
30769
|
+
* Standard CIE 1976 delta E formula also takes the square root, unneeded
|
|
30770
|
+
* here. This method is used by quantization algorithms to compare distance,
|
|
30771
|
+
* and the relative ordering is the same, with or without a square root.
|
|
30772
|
+
*
|
|
30773
|
+
* This relatively minor optimization is helpful because this method is
|
|
30774
|
+
* called at least once for each pixel in an image.
|
|
30775
|
+
*/
|
|
30776
|
+
distance(from, to) {
|
|
30777
|
+
const dL = from[0] - to[0];
|
|
30778
|
+
const dA = from[1] - to[1];
|
|
30779
|
+
const dB = from[2] - to[2];
|
|
30780
|
+
return dL * dL + dA * dA + dB * dB;
|
|
30781
|
+
}
|
|
30782
|
+
}
|
|
30783
|
+
|
|
30784
|
+
/**
|
|
30785
|
+
* @license
|
|
30786
|
+
* Copyright 2021 Google LLC
|
|
30787
|
+
*
|
|
30788
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
30789
|
+
* you may not use this file except in compliance with the License.
|
|
30790
|
+
* You may obtain a copy of the License at
|
|
30791
|
+
*
|
|
30792
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
30793
|
+
*
|
|
30794
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
30795
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
30796
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
30797
|
+
* See the License for the specific language governing permissions and
|
|
30798
|
+
* limitations under the License.
|
|
30799
|
+
*/
|
|
30800
|
+
const MAX_ITERATIONS = 10;
|
|
30801
|
+
const MIN_MOVEMENT_DISTANCE = 3.0;
|
|
30802
|
+
/**
|
|
30803
|
+
* An image quantizer that improves on the speed of a standard K-Means algorithm
|
|
30804
|
+
* by implementing several optimizations, including deduping identical pixels
|
|
30805
|
+
* and a triangle inequality rule that reduces the number of comparisons needed
|
|
30806
|
+
* to identify which cluster a point should be moved to.
|
|
30807
|
+
*
|
|
30808
|
+
* Wsmeans stands for Weighted Square Means.
|
|
30809
|
+
*
|
|
30810
|
+
* This algorithm was designed by M. Emre Celebi, and was found in their 2011
|
|
30811
|
+
* paper, Improving the Performance of K-Means for Color Quantization.
|
|
30812
|
+
* https://arxiv.org/abs/1101.0395
|
|
30813
|
+
*/
|
|
30814
|
+
// material_color_utilities is designed to have a consistent API across
|
|
30815
|
+
// platforms and modular components that can be moved around easily. Using a
|
|
30816
|
+
// class as a namespace facilitates this.
|
|
30817
|
+
//
|
|
30818
|
+
// tslint:disable-next-line:class-as-namespace
|
|
30819
|
+
class QuantizerWsmeans {
|
|
30820
|
+
/**
|
|
30821
|
+
* @param inputPixels Colors in ARGB format.
|
|
30822
|
+
* @param startingClusters Defines the initial state of the quantizer. Passing
|
|
30823
|
+
* an empty array is fine, the implementation will create its own initial
|
|
30824
|
+
* state that leads to reproducible results for the same inputs.
|
|
30825
|
+
* Passing an array that is the result of Wu quantization leads to higher
|
|
30826
|
+
* quality results.
|
|
30827
|
+
* @param maxColors The number of colors to divide the image into. A lower
|
|
30828
|
+
* number of colors may be returned.
|
|
30829
|
+
* @return Colors in ARGB format.
|
|
30830
|
+
*/
|
|
30831
|
+
static quantize(inputPixels, startingClusters, maxColors) {
|
|
30832
|
+
const pixelToCount = new Map();
|
|
30833
|
+
const points = new Array();
|
|
30834
|
+
const pixels = new Array();
|
|
30835
|
+
const pointProvider = new LabPointProvider();
|
|
30836
|
+
let pointCount = 0;
|
|
30837
|
+
for (let i = 0; i < inputPixels.length; i++) {
|
|
30838
|
+
const inputPixel = inputPixels[i];
|
|
30839
|
+
const pixelCount = pixelToCount.get(inputPixel);
|
|
30840
|
+
if (pixelCount === undefined) {
|
|
30841
|
+
pointCount++;
|
|
30842
|
+
points.push(pointProvider.fromInt(inputPixel));
|
|
30843
|
+
pixels.push(inputPixel);
|
|
30844
|
+
pixelToCount.set(inputPixel, 1);
|
|
30845
|
+
} else {
|
|
30846
|
+
pixelToCount.set(inputPixel, pixelCount + 1);
|
|
30847
|
+
}
|
|
30848
|
+
}
|
|
30849
|
+
const counts = new Array();
|
|
30850
|
+
for (let i = 0; i < pointCount; i++) {
|
|
30851
|
+
const pixel = pixels[i];
|
|
30852
|
+
const count = pixelToCount.get(pixel);
|
|
30853
|
+
if (count !== undefined) {
|
|
30854
|
+
counts[i] = count;
|
|
30855
|
+
}
|
|
30856
|
+
}
|
|
30857
|
+
let clusterCount = Math.min(maxColors, pointCount);
|
|
30858
|
+
if (startingClusters.length > 0) {
|
|
30859
|
+
clusterCount = Math.min(clusterCount, startingClusters.length);
|
|
30860
|
+
}
|
|
30861
|
+
const clusters = new Array();
|
|
30862
|
+
for (let i = 0; i < startingClusters.length; i++) {
|
|
30863
|
+
clusters.push(pointProvider.fromInt(startingClusters[i]));
|
|
30864
|
+
}
|
|
30865
|
+
const additionalClustersNeeded = clusterCount - clusters.length;
|
|
30866
|
+
if (startingClusters.length === 0 && additionalClustersNeeded > 0) {
|
|
30867
|
+
for (let i = 0; i < additionalClustersNeeded; i++) {
|
|
30868
|
+
const l = Math.random() * 100.0;
|
|
30869
|
+
const a = Math.random() * (100.0 - -100 + 1) + -100;
|
|
30870
|
+
const b = Math.random() * (100.0 - -100 + 1) + -100;
|
|
30871
|
+
clusters.push(new Array(l, a, b));
|
|
30872
|
+
}
|
|
30873
|
+
}
|
|
30874
|
+
const clusterIndices = new Array();
|
|
30875
|
+
for (let i = 0; i < pointCount; i++) {
|
|
30876
|
+
clusterIndices.push(Math.floor(Math.random() * clusterCount));
|
|
30877
|
+
}
|
|
30878
|
+
const indexMatrix = new Array();
|
|
30879
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30880
|
+
indexMatrix.push(new Array());
|
|
30881
|
+
for (let j = 0; j < clusterCount; j++) {
|
|
30882
|
+
indexMatrix[i].push(0);
|
|
30883
|
+
}
|
|
30884
|
+
}
|
|
30885
|
+
const distanceToIndexMatrix = new Array();
|
|
30886
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30887
|
+
distanceToIndexMatrix.push(new Array());
|
|
30888
|
+
for (let j = 0; j < clusterCount; j++) {
|
|
30889
|
+
distanceToIndexMatrix[i].push(new DistanceAndIndex());
|
|
30890
|
+
}
|
|
30891
|
+
}
|
|
30892
|
+
const pixelCountSums = new Array();
|
|
30893
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30894
|
+
pixelCountSums.push(0);
|
|
30895
|
+
}
|
|
30896
|
+
for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
|
|
30897
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30898
|
+
for (let j = i + 1; j < clusterCount; j++) {
|
|
30899
|
+
const distance = pointProvider.distance(clusters[i], clusters[j]);
|
|
30900
|
+
distanceToIndexMatrix[j][i].distance = distance;
|
|
30901
|
+
distanceToIndexMatrix[j][i].index = i;
|
|
30902
|
+
distanceToIndexMatrix[i][j].distance = distance;
|
|
30903
|
+
distanceToIndexMatrix[i][j].index = j;
|
|
30904
|
+
}
|
|
30905
|
+
distanceToIndexMatrix[i].sort();
|
|
30906
|
+
for (let j = 0; j < clusterCount; j++) {
|
|
30907
|
+
indexMatrix[i][j] = distanceToIndexMatrix[i][j].index;
|
|
30908
|
+
}
|
|
30909
|
+
}
|
|
30910
|
+
let pointsMoved = 0;
|
|
30911
|
+
for (let i = 0; i < pointCount; i++) {
|
|
30912
|
+
const point = points[i];
|
|
30913
|
+
const previousClusterIndex = clusterIndices[i];
|
|
30914
|
+
const previousCluster = clusters[previousClusterIndex];
|
|
30915
|
+
const previousDistance = pointProvider.distance(point, previousCluster);
|
|
30916
|
+
let minimumDistance = previousDistance;
|
|
30917
|
+
let newClusterIndex = -1;
|
|
30918
|
+
for (let j = 0; j < clusterCount; j++) {
|
|
30919
|
+
if (distanceToIndexMatrix[previousClusterIndex][j].distance >= 4 * previousDistance) {
|
|
30920
|
+
continue;
|
|
30921
|
+
}
|
|
30922
|
+
const distance = pointProvider.distance(point, clusters[j]);
|
|
30923
|
+
if (distance < minimumDistance) {
|
|
30924
|
+
minimumDistance = distance;
|
|
30925
|
+
newClusterIndex = j;
|
|
30926
|
+
}
|
|
30927
|
+
}
|
|
30928
|
+
if (newClusterIndex !== -1) {
|
|
30929
|
+
const distanceChange = Math.abs(Math.sqrt(minimumDistance) - Math.sqrt(previousDistance));
|
|
30930
|
+
if (distanceChange > MIN_MOVEMENT_DISTANCE) {
|
|
30931
|
+
pointsMoved++;
|
|
30932
|
+
clusterIndices[i] = newClusterIndex;
|
|
30933
|
+
}
|
|
30934
|
+
}
|
|
30935
|
+
}
|
|
30936
|
+
if (pointsMoved === 0 && iteration !== 0) {
|
|
30937
|
+
break;
|
|
30938
|
+
}
|
|
30939
|
+
const componentASums = new Array(clusterCount).fill(0);
|
|
30940
|
+
const componentBSums = new Array(clusterCount).fill(0);
|
|
30941
|
+
const componentCSums = new Array(clusterCount).fill(0);
|
|
30942
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30943
|
+
pixelCountSums[i] = 0;
|
|
30944
|
+
}
|
|
30945
|
+
for (let i = 0; i < pointCount; i++) {
|
|
30946
|
+
const clusterIndex = clusterIndices[i];
|
|
30947
|
+
const point = points[i];
|
|
30948
|
+
const count = counts[i];
|
|
30949
|
+
pixelCountSums[clusterIndex] += count;
|
|
30950
|
+
componentASums[clusterIndex] += point[0] * count;
|
|
30951
|
+
componentBSums[clusterIndex] += point[1] * count;
|
|
30952
|
+
componentCSums[clusterIndex] += point[2] * count;
|
|
30953
|
+
}
|
|
30954
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30955
|
+
const count = pixelCountSums[i];
|
|
30956
|
+
if (count === 0) {
|
|
30957
|
+
clusters[i] = [0.0, 0.0, 0.0];
|
|
30958
|
+
continue;
|
|
30959
|
+
}
|
|
30960
|
+
const a = componentASums[i] / count;
|
|
30961
|
+
const b = componentBSums[i] / count;
|
|
30962
|
+
const c = componentCSums[i] / count;
|
|
30963
|
+
clusters[i] = [a, b, c];
|
|
30964
|
+
}
|
|
30965
|
+
}
|
|
30966
|
+
const argbToPopulation = new Map();
|
|
30967
|
+
for (let i = 0; i < clusterCount; i++) {
|
|
30968
|
+
const count = pixelCountSums[i];
|
|
30969
|
+
if (count === 0) {
|
|
30970
|
+
continue;
|
|
30971
|
+
}
|
|
30972
|
+
const possibleNewCluster = pointProvider.toInt(clusters[i]);
|
|
30973
|
+
if (argbToPopulation.has(possibleNewCluster)) {
|
|
30974
|
+
continue;
|
|
30975
|
+
}
|
|
30976
|
+
argbToPopulation.set(possibleNewCluster, count);
|
|
30977
|
+
}
|
|
30978
|
+
return argbToPopulation;
|
|
30979
|
+
}
|
|
30980
|
+
}
|
|
30981
|
+
/**
|
|
30982
|
+
* A wrapper for maintaining a table of distances between K-Means clusters.
|
|
30983
|
+
*/
|
|
30984
|
+
class DistanceAndIndex {
|
|
30985
|
+
constructor() {
|
|
30986
|
+
this.distance = -1;
|
|
30987
|
+
this.index = -1;
|
|
30988
|
+
}
|
|
30989
|
+
}
|
|
30990
|
+
|
|
30991
|
+
/**
|
|
30992
|
+
* @license
|
|
30993
|
+
* Copyright 2021 Google LLC
|
|
30994
|
+
*
|
|
30995
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
30996
|
+
* you may not use this file except in compliance with the License.
|
|
30997
|
+
* You may obtain a copy of the License at
|
|
30998
|
+
*
|
|
30999
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
31000
|
+
*
|
|
31001
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
31002
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
31003
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31004
|
+
* See the License for the specific language governing permissions and
|
|
31005
|
+
* limitations under the License.
|
|
31006
|
+
*/
|
|
31007
|
+
/**
|
|
31008
|
+
* Quantizes an image into a map, with keys of ARGB colors, and values of the
|
|
31009
|
+
* number of times that color appears in the image.
|
|
31010
|
+
*/
|
|
31011
|
+
// material_color_utilities is designed to have a consistent API across
|
|
31012
|
+
// platforms and modular components that can be moved around easily. Using a
|
|
31013
|
+
// class as a namespace facilitates this.
|
|
31014
|
+
//
|
|
31015
|
+
// tslint:disable-next-line:class-as-namespace
|
|
31016
|
+
class QuantizerMap {
|
|
31017
|
+
/**
|
|
31018
|
+
* @param pixels Colors in ARGB format.
|
|
31019
|
+
* @return A Map with keys of ARGB colors, and values of the number of times
|
|
31020
|
+
* the color appears in the image.
|
|
31021
|
+
*/
|
|
31022
|
+
static quantize(pixels) {
|
|
31023
|
+
const countByColor = new Map();
|
|
31024
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
31025
|
+
const pixel = pixels[i];
|
|
31026
|
+
const alpha = alphaFromArgb(pixel);
|
|
31027
|
+
if (alpha < 255) {
|
|
31028
|
+
continue;
|
|
31029
|
+
}
|
|
31030
|
+
countByColor.set(pixel, (countByColor.get(pixel) ?? 0) + 1);
|
|
31031
|
+
}
|
|
31032
|
+
return countByColor;
|
|
31033
|
+
}
|
|
31034
|
+
}
|
|
31035
|
+
|
|
31036
|
+
/**
|
|
31037
|
+
* @license
|
|
31038
|
+
* Copyright 2021 Google LLC
|
|
31039
|
+
*
|
|
31040
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
31041
|
+
* you may not use this file except in compliance with the License.
|
|
31042
|
+
* You may obtain a copy of the License at
|
|
31043
|
+
*
|
|
31044
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
31045
|
+
*
|
|
31046
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
31047
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
31048
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31049
|
+
* See the License for the specific language governing permissions and
|
|
31050
|
+
* limitations under the License.
|
|
31051
|
+
*/
|
|
31052
|
+
const INDEX_BITS = 5;
|
|
31053
|
+
const SIDE_LENGTH = 33; // ((1 << INDEX_INDEX_BITS) + 1)
|
|
31054
|
+
const TOTAL_SIZE = 35937; // SIDE_LENGTH * SIDE_LENGTH * SIDE_LENGTH
|
|
31055
|
+
const directions = {
|
|
31056
|
+
RED: 'red',
|
|
31057
|
+
GREEN: 'green',
|
|
31058
|
+
BLUE: 'blue'
|
|
31059
|
+
};
|
|
31060
|
+
/**
|
|
31061
|
+
* An image quantizer that divides the image's pixels into clusters by
|
|
31062
|
+
* recursively cutting an RGB cube, based on the weight of pixels in each area
|
|
31063
|
+
* of the cube.
|
|
31064
|
+
*
|
|
31065
|
+
* The algorithm was described by Xiaolin Wu in Graphic Gems II, published in
|
|
31066
|
+
* 1991.
|
|
31067
|
+
*/
|
|
31068
|
+
class QuantizerWu {
|
|
31069
|
+
constructor(weights = [], momentsR = [], momentsG = [], momentsB = [], moments = [], cubes = []) {
|
|
31070
|
+
this.weights = weights;
|
|
31071
|
+
this.momentsR = momentsR;
|
|
31072
|
+
this.momentsG = momentsG;
|
|
31073
|
+
this.momentsB = momentsB;
|
|
31074
|
+
this.moments = moments;
|
|
31075
|
+
this.cubes = cubes;
|
|
31076
|
+
}
|
|
31077
|
+
/**
|
|
31078
|
+
* @param pixels Colors in ARGB format.
|
|
31079
|
+
* @param maxColors The number of colors to divide the image into. A lower
|
|
31080
|
+
* number of colors may be returned.
|
|
31081
|
+
* @return Colors in ARGB format.
|
|
31082
|
+
*/
|
|
31083
|
+
quantize(pixels, maxColors) {
|
|
31084
|
+
this.constructHistogram(pixels);
|
|
31085
|
+
this.computeMoments();
|
|
31086
|
+
const createBoxesResult = this.createBoxes(maxColors);
|
|
31087
|
+
const results = this.createResult(createBoxesResult.resultCount);
|
|
31088
|
+
return results;
|
|
31089
|
+
}
|
|
31090
|
+
constructHistogram(pixels) {
|
|
31091
|
+
this.weights = Array.from({
|
|
31092
|
+
length: TOTAL_SIZE
|
|
31093
|
+
}).fill(0);
|
|
31094
|
+
this.momentsR = Array.from({
|
|
31095
|
+
length: TOTAL_SIZE
|
|
31096
|
+
}).fill(0);
|
|
31097
|
+
this.momentsG = Array.from({
|
|
31098
|
+
length: TOTAL_SIZE
|
|
31099
|
+
}).fill(0);
|
|
31100
|
+
this.momentsB = Array.from({
|
|
31101
|
+
length: TOTAL_SIZE
|
|
31102
|
+
}).fill(0);
|
|
31103
|
+
this.moments = Array.from({
|
|
31104
|
+
length: TOTAL_SIZE
|
|
31105
|
+
}).fill(0);
|
|
31106
|
+
const countByColor = QuantizerMap.quantize(pixels);
|
|
31107
|
+
for (const [pixel, count] of countByColor.entries()) {
|
|
31108
|
+
const red = redFromArgb(pixel);
|
|
31109
|
+
const green = greenFromArgb(pixel);
|
|
31110
|
+
const blue = blueFromArgb(pixel);
|
|
31111
|
+
const bitsToRemove = 8 - INDEX_BITS;
|
|
31112
|
+
const iR = (red >> bitsToRemove) + 1;
|
|
31113
|
+
const iG = (green >> bitsToRemove) + 1;
|
|
31114
|
+
const iB = (blue >> bitsToRemove) + 1;
|
|
31115
|
+
const index = this.getIndex(iR, iG, iB);
|
|
31116
|
+
this.weights[index] = (this.weights[index] ?? 0) + count;
|
|
31117
|
+
this.momentsR[index] += count * red;
|
|
31118
|
+
this.momentsG[index] += count * green;
|
|
31119
|
+
this.momentsB[index] += count * blue;
|
|
31120
|
+
this.moments[index] += count * (red * red + green * green + blue * blue);
|
|
31121
|
+
}
|
|
31122
|
+
}
|
|
31123
|
+
computeMoments() {
|
|
31124
|
+
for (let r = 1; r < SIDE_LENGTH; r++) {
|
|
31125
|
+
const area = Array.from({
|
|
31126
|
+
length: SIDE_LENGTH
|
|
31127
|
+
}).fill(0);
|
|
31128
|
+
const areaR = Array.from({
|
|
31129
|
+
length: SIDE_LENGTH
|
|
31130
|
+
}).fill(0);
|
|
31131
|
+
const areaG = Array.from({
|
|
31132
|
+
length: SIDE_LENGTH
|
|
31133
|
+
}).fill(0);
|
|
31134
|
+
const areaB = Array.from({
|
|
31135
|
+
length: SIDE_LENGTH
|
|
31136
|
+
}).fill(0);
|
|
31137
|
+
const area2 = Array.from({
|
|
31138
|
+
length: SIDE_LENGTH
|
|
31139
|
+
}).fill(0.0);
|
|
31140
|
+
for (let g = 1; g < SIDE_LENGTH; g++) {
|
|
31141
|
+
let line = 0;
|
|
31142
|
+
let lineR = 0;
|
|
31143
|
+
let lineG = 0;
|
|
31144
|
+
let lineB = 0;
|
|
31145
|
+
let line2 = 0.0;
|
|
31146
|
+
for (let b = 1; b < SIDE_LENGTH; b++) {
|
|
31147
|
+
const index = this.getIndex(r, g, b);
|
|
31148
|
+
line += this.weights[index];
|
|
31149
|
+
lineR += this.momentsR[index];
|
|
31150
|
+
lineG += this.momentsG[index];
|
|
31151
|
+
lineB += this.momentsB[index];
|
|
31152
|
+
line2 += this.moments[index];
|
|
31153
|
+
area[b] += line;
|
|
31154
|
+
areaR[b] += lineR;
|
|
31155
|
+
areaG[b] += lineG;
|
|
31156
|
+
areaB[b] += lineB;
|
|
31157
|
+
area2[b] += line2;
|
|
31158
|
+
const previousIndex = this.getIndex(r - 1, g, b);
|
|
31159
|
+
this.weights[index] = this.weights[previousIndex] + area[b];
|
|
31160
|
+
this.momentsR[index] = this.momentsR[previousIndex] + areaR[b];
|
|
31161
|
+
this.momentsG[index] = this.momentsG[previousIndex] + areaG[b];
|
|
31162
|
+
this.momentsB[index] = this.momentsB[previousIndex] + areaB[b];
|
|
31163
|
+
this.moments[index] = this.moments[previousIndex] + area2[b];
|
|
31164
|
+
}
|
|
31165
|
+
}
|
|
31166
|
+
}
|
|
31167
|
+
}
|
|
31168
|
+
createBoxes(maxColors) {
|
|
31169
|
+
this.cubes = Array.from({
|
|
31170
|
+
length: maxColors
|
|
31171
|
+
}).fill(0).map(() => new Box());
|
|
31172
|
+
const volumeVariance = Array.from({
|
|
31173
|
+
length: maxColors
|
|
31174
|
+
}).fill(0.0);
|
|
31175
|
+
this.cubes[0].r0 = 0;
|
|
31176
|
+
this.cubes[0].g0 = 0;
|
|
31177
|
+
this.cubes[0].b0 = 0;
|
|
31178
|
+
this.cubes[0].r1 = SIDE_LENGTH - 1;
|
|
31179
|
+
this.cubes[0].g1 = SIDE_LENGTH - 1;
|
|
31180
|
+
this.cubes[0].b1 = SIDE_LENGTH - 1;
|
|
31181
|
+
let generatedColorCount = maxColors;
|
|
31182
|
+
let next = 0;
|
|
31183
|
+
for (let i = 1; i < maxColors; i++) {
|
|
31184
|
+
if (this.cut(this.cubes[next], this.cubes[i])) {
|
|
31185
|
+
volumeVariance[next] = this.cubes[next].vol > 1 ? this.variance(this.cubes[next]) : 0.0;
|
|
31186
|
+
volumeVariance[i] = this.cubes[i].vol > 1 ? this.variance(this.cubes[i]) : 0.0;
|
|
31187
|
+
} else {
|
|
31188
|
+
volumeVariance[next] = 0.0;
|
|
31189
|
+
i--;
|
|
31190
|
+
}
|
|
31191
|
+
next = 0;
|
|
31192
|
+
let temp = volumeVariance[0];
|
|
31193
|
+
for (let j = 1; j <= i; j++) {
|
|
31194
|
+
if (volumeVariance[j] > temp) {
|
|
31195
|
+
temp = volumeVariance[j];
|
|
31196
|
+
next = j;
|
|
31197
|
+
}
|
|
31198
|
+
}
|
|
31199
|
+
if (temp <= 0.0) {
|
|
31200
|
+
generatedColorCount = i + 1;
|
|
31201
|
+
break;
|
|
31202
|
+
}
|
|
31203
|
+
}
|
|
31204
|
+
return new CreateBoxesResult(maxColors, generatedColorCount);
|
|
31205
|
+
}
|
|
31206
|
+
createResult(colorCount) {
|
|
31207
|
+
const colors = [];
|
|
31208
|
+
for (let i = 0; i < colorCount; ++i) {
|
|
31209
|
+
const cube = this.cubes[i];
|
|
31210
|
+
const weight = this.volume(cube, this.weights);
|
|
31211
|
+
if (weight > 0) {
|
|
31212
|
+
const r = Math.round(this.volume(cube, this.momentsR) / weight);
|
|
31213
|
+
const g = Math.round(this.volume(cube, this.momentsG) / weight);
|
|
31214
|
+
const b = Math.round(this.volume(cube, this.momentsB) / weight);
|
|
31215
|
+
const color = 255 << 24 | (r & 0x0ff) << 16 | (g & 0x0ff) << 8 | b & 0x0ff;
|
|
31216
|
+
colors.push(color);
|
|
31217
|
+
}
|
|
31218
|
+
}
|
|
31219
|
+
return colors;
|
|
31220
|
+
}
|
|
31221
|
+
variance(cube) {
|
|
31222
|
+
const dr = this.volume(cube, this.momentsR);
|
|
31223
|
+
const dg = this.volume(cube, this.momentsG);
|
|
31224
|
+
const db = this.volume(cube, this.momentsB);
|
|
31225
|
+
const xx = this.moments[this.getIndex(cube.r1, cube.g1, cube.b1)] - this.moments[this.getIndex(cube.r1, cube.g1, cube.b0)] - this.moments[this.getIndex(cube.r1, cube.g0, cube.b1)] + this.moments[this.getIndex(cube.r1, cube.g0, cube.b0)] - this.moments[this.getIndex(cube.r0, cube.g1, cube.b1)] + this.moments[this.getIndex(cube.r0, cube.g1, cube.b0)] + this.moments[this.getIndex(cube.r0, cube.g0, cube.b1)] - this.moments[this.getIndex(cube.r0, cube.g0, cube.b0)];
|
|
31226
|
+
const hypotenuse = dr * dr + dg * dg + db * db;
|
|
31227
|
+
const volume = this.volume(cube, this.weights);
|
|
31228
|
+
return xx - hypotenuse / volume;
|
|
31229
|
+
}
|
|
31230
|
+
cut(one, two) {
|
|
31231
|
+
const wholeR = this.volume(one, this.momentsR);
|
|
31232
|
+
const wholeG = this.volume(one, this.momentsG);
|
|
31233
|
+
const wholeB = this.volume(one, this.momentsB);
|
|
31234
|
+
const wholeW = this.volume(one, this.weights);
|
|
31235
|
+
const maxRResult = this.maximize(one, directions.RED, one.r0 + 1, one.r1, wholeR, wholeG, wholeB, wholeW);
|
|
31236
|
+
const maxGResult = this.maximize(one, directions.GREEN, one.g0 + 1, one.g1, wholeR, wholeG, wholeB, wholeW);
|
|
31237
|
+
const maxBResult = this.maximize(one, directions.BLUE, one.b0 + 1, one.b1, wholeR, wholeG, wholeB, wholeW);
|
|
31238
|
+
let direction;
|
|
31239
|
+
const maxR = maxRResult.maximum;
|
|
31240
|
+
const maxG = maxGResult.maximum;
|
|
31241
|
+
const maxB = maxBResult.maximum;
|
|
31242
|
+
if (maxR >= maxG && maxR >= maxB) {
|
|
31243
|
+
if (maxRResult.cutLocation < 0) {
|
|
31244
|
+
return false;
|
|
31245
|
+
}
|
|
31246
|
+
direction = directions.RED;
|
|
31247
|
+
} else if (maxG >= maxR && maxG >= maxB) {
|
|
31248
|
+
direction = directions.GREEN;
|
|
31249
|
+
} else {
|
|
31250
|
+
direction = directions.BLUE;
|
|
31251
|
+
}
|
|
31252
|
+
two.r1 = one.r1;
|
|
31253
|
+
two.g1 = one.g1;
|
|
31254
|
+
two.b1 = one.b1;
|
|
31255
|
+
switch (direction) {
|
|
31256
|
+
case directions.RED:
|
|
31257
|
+
one.r1 = maxRResult.cutLocation;
|
|
31258
|
+
two.r0 = one.r1;
|
|
31259
|
+
two.g0 = one.g0;
|
|
31260
|
+
two.b0 = one.b0;
|
|
31261
|
+
break;
|
|
31262
|
+
case directions.GREEN:
|
|
31263
|
+
one.g1 = maxGResult.cutLocation;
|
|
31264
|
+
two.r0 = one.r0;
|
|
31265
|
+
two.g0 = one.g1;
|
|
31266
|
+
two.b0 = one.b0;
|
|
31267
|
+
break;
|
|
31268
|
+
case directions.BLUE:
|
|
31269
|
+
one.b1 = maxBResult.cutLocation;
|
|
31270
|
+
two.r0 = one.r0;
|
|
31271
|
+
two.g0 = one.g0;
|
|
31272
|
+
two.b0 = one.b1;
|
|
31273
|
+
break;
|
|
31274
|
+
default:
|
|
31275
|
+
throw new Error('unexpected direction ' + direction);
|
|
31276
|
+
}
|
|
31277
|
+
one.vol = (one.r1 - one.r0) * (one.g1 - one.g0) * (one.b1 - one.b0);
|
|
31278
|
+
two.vol = (two.r1 - two.r0) * (two.g1 - two.g0) * (two.b1 - two.b0);
|
|
31279
|
+
return true;
|
|
31280
|
+
}
|
|
31281
|
+
maximize(cube, direction, first, last, wholeR, wholeG, wholeB, wholeW) {
|
|
31282
|
+
const bottomR = this.bottom(cube, direction, this.momentsR);
|
|
31283
|
+
const bottomG = this.bottom(cube, direction, this.momentsG);
|
|
31284
|
+
const bottomB = this.bottom(cube, direction, this.momentsB);
|
|
31285
|
+
const bottomW = this.bottom(cube, direction, this.weights);
|
|
31286
|
+
let max = 0.0;
|
|
31287
|
+
let cut = -1;
|
|
31288
|
+
let halfR = 0;
|
|
31289
|
+
let halfG = 0;
|
|
31290
|
+
let halfB = 0;
|
|
31291
|
+
let halfW = 0;
|
|
31292
|
+
for (let i = first; i < last; i++) {
|
|
31293
|
+
halfR = bottomR + this.top(cube, direction, i, this.momentsR);
|
|
31294
|
+
halfG = bottomG + this.top(cube, direction, i, this.momentsG);
|
|
31295
|
+
halfB = bottomB + this.top(cube, direction, i, this.momentsB);
|
|
31296
|
+
halfW = bottomW + this.top(cube, direction, i, this.weights);
|
|
31297
|
+
if (halfW === 0) {
|
|
31298
|
+
continue;
|
|
31299
|
+
}
|
|
31300
|
+
let tempNumerator = (halfR * halfR + halfG * halfG + halfB * halfB) * 1.0;
|
|
31301
|
+
let tempDenominator = halfW * 1.0;
|
|
31302
|
+
let temp = tempNumerator / tempDenominator;
|
|
31303
|
+
halfR = wholeR - halfR;
|
|
31304
|
+
halfG = wholeG - halfG;
|
|
31305
|
+
halfB = wholeB - halfB;
|
|
31306
|
+
halfW = wholeW - halfW;
|
|
31307
|
+
if (halfW === 0) {
|
|
31308
|
+
continue;
|
|
31309
|
+
}
|
|
31310
|
+
tempNumerator = (halfR * halfR + halfG * halfG + halfB * halfB) * 1.0;
|
|
31311
|
+
tempDenominator = halfW * 1.0;
|
|
31312
|
+
temp += tempNumerator / tempDenominator;
|
|
31313
|
+
if (temp > max) {
|
|
31314
|
+
max = temp;
|
|
31315
|
+
cut = i;
|
|
31316
|
+
}
|
|
31317
|
+
}
|
|
31318
|
+
return new MaximizeResult(cut, max);
|
|
31319
|
+
}
|
|
31320
|
+
volume(cube, moment) {
|
|
31321
|
+
return moment[this.getIndex(cube.r1, cube.g1, cube.b1)] - moment[this.getIndex(cube.r1, cube.g1, cube.b0)] - moment[this.getIndex(cube.r1, cube.g0, cube.b1)] + moment[this.getIndex(cube.r1, cube.g0, cube.b0)] - moment[this.getIndex(cube.r0, cube.g1, cube.b1)] + moment[this.getIndex(cube.r0, cube.g1, cube.b0)] + moment[this.getIndex(cube.r0, cube.g0, cube.b1)] - moment[this.getIndex(cube.r0, cube.g0, cube.b0)];
|
|
31322
|
+
}
|
|
31323
|
+
bottom(cube, direction, moment) {
|
|
31324
|
+
switch (direction) {
|
|
31325
|
+
case directions.RED:
|
|
31326
|
+
return -moment[this.getIndex(cube.r0, cube.g1, cube.b1)] + moment[this.getIndex(cube.r0, cube.g1, cube.b0)] + moment[this.getIndex(cube.r0, cube.g0, cube.b1)] - moment[this.getIndex(cube.r0, cube.g0, cube.b0)];
|
|
31327
|
+
case directions.GREEN:
|
|
31328
|
+
return -moment[this.getIndex(cube.r1, cube.g0, cube.b1)] + moment[this.getIndex(cube.r1, cube.g0, cube.b0)] + moment[this.getIndex(cube.r0, cube.g0, cube.b1)] - moment[this.getIndex(cube.r0, cube.g0, cube.b0)];
|
|
31329
|
+
case directions.BLUE:
|
|
31330
|
+
return -moment[this.getIndex(cube.r1, cube.g1, cube.b0)] + moment[this.getIndex(cube.r1, cube.g0, cube.b0)] + moment[this.getIndex(cube.r0, cube.g1, cube.b0)] - moment[this.getIndex(cube.r0, cube.g0, cube.b0)];
|
|
31331
|
+
default:
|
|
31332
|
+
throw new Error('unexpected direction $direction');
|
|
31333
|
+
}
|
|
31334
|
+
}
|
|
31335
|
+
top(cube, direction, position, moment) {
|
|
31336
|
+
switch (direction) {
|
|
31337
|
+
case directions.RED:
|
|
31338
|
+
return moment[this.getIndex(position, cube.g1, cube.b1)] - moment[this.getIndex(position, cube.g1, cube.b0)] - moment[this.getIndex(position, cube.g0, cube.b1)] + moment[this.getIndex(position, cube.g0, cube.b0)];
|
|
31339
|
+
case directions.GREEN:
|
|
31340
|
+
return moment[this.getIndex(cube.r1, position, cube.b1)] - moment[this.getIndex(cube.r1, position, cube.b0)] - moment[this.getIndex(cube.r0, position, cube.b1)] + moment[this.getIndex(cube.r0, position, cube.b0)];
|
|
31341
|
+
case directions.BLUE:
|
|
31342
|
+
return moment[this.getIndex(cube.r1, cube.g1, position)] - moment[this.getIndex(cube.r1, cube.g0, position)] - moment[this.getIndex(cube.r0, cube.g1, position)] + moment[this.getIndex(cube.r0, cube.g0, position)];
|
|
31343
|
+
default:
|
|
31344
|
+
throw new Error('unexpected direction $direction');
|
|
31345
|
+
}
|
|
31346
|
+
}
|
|
31347
|
+
getIndex(r, g, b) {
|
|
31348
|
+
return (r << INDEX_BITS * 2) + (r << INDEX_BITS + 1) + r + (g << INDEX_BITS) + g + b;
|
|
31349
|
+
}
|
|
31350
|
+
}
|
|
31351
|
+
/**
|
|
31352
|
+
* Keeps track of the state of each box created as the Wu quantization
|
|
31353
|
+
* algorithm progresses through dividing the image's pixels as plotted in RGB.
|
|
31354
|
+
*/
|
|
31355
|
+
class Box {
|
|
31356
|
+
constructor(r0 = 0, r1 = 0, g0 = 0, g1 = 0, b0 = 0, b1 = 0, vol = 0) {
|
|
31357
|
+
this.r0 = r0;
|
|
31358
|
+
this.r1 = r1;
|
|
31359
|
+
this.g0 = g0;
|
|
31360
|
+
this.g1 = g1;
|
|
31361
|
+
this.b0 = b0;
|
|
31362
|
+
this.b1 = b1;
|
|
31363
|
+
this.vol = vol;
|
|
31364
|
+
}
|
|
31365
|
+
}
|
|
31366
|
+
/**
|
|
31367
|
+
* Represents final result of Wu algorithm.
|
|
31368
|
+
*/
|
|
31369
|
+
class CreateBoxesResult {
|
|
31370
|
+
/**
|
|
31371
|
+
* @param requestedCount how many colors the caller asked to be returned from
|
|
31372
|
+
* quantization.
|
|
31373
|
+
* @param resultCount the actual number of colors achieved from quantization.
|
|
31374
|
+
* May be lower than the requested count.
|
|
31375
|
+
*/
|
|
31376
|
+
constructor(requestedCount, resultCount) {
|
|
31377
|
+
this.requestedCount = requestedCount;
|
|
31378
|
+
this.resultCount = resultCount;
|
|
31379
|
+
}
|
|
31380
|
+
}
|
|
31381
|
+
/**
|
|
31382
|
+
* Represents the result of calculating where to cut an existing box in such
|
|
31383
|
+
* a way to maximize variance between the two new boxes created by a cut.
|
|
31384
|
+
*/
|
|
31385
|
+
class MaximizeResult {
|
|
31386
|
+
constructor(cutLocation, maximum) {
|
|
31387
|
+
this.cutLocation = cutLocation;
|
|
31388
|
+
this.maximum = maximum;
|
|
31389
|
+
}
|
|
31390
|
+
}
|
|
31391
|
+
|
|
31392
|
+
/**
|
|
31393
|
+
* @license
|
|
31394
|
+
* Copyright 2021 Google LLC
|
|
31395
|
+
*
|
|
31396
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
31397
|
+
* you may not use this file except in compliance with the License.
|
|
31398
|
+
* You may obtain a copy of the License at
|
|
31399
|
+
*
|
|
31400
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
31401
|
+
*
|
|
31402
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
31403
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
31404
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31405
|
+
* See the License for the specific language governing permissions and
|
|
31406
|
+
* limitations under the License.
|
|
31407
|
+
*/
|
|
31408
|
+
/**
|
|
31409
|
+
* An image quantizer that improves on the quality of a standard K-Means
|
|
31410
|
+
* algorithm by setting the K-Means initial state to the output of a Wu
|
|
31411
|
+
* quantizer, instead of random centroids. Improves on speed by several
|
|
31412
|
+
* optimizations, as implemented in Wsmeans, or Weighted Square Means, K-Means
|
|
31413
|
+
* with those optimizations.
|
|
31414
|
+
*
|
|
31415
|
+
* This algorithm was designed by M. Emre Celebi, and was found in their 2011
|
|
31416
|
+
* paper, Improving the Performance of K-Means for Color Quantization.
|
|
31417
|
+
* https://arxiv.org/abs/1101.0395
|
|
31418
|
+
*/
|
|
31419
|
+
// material_color_utilities is designed to have a consistent API across
|
|
31420
|
+
// platforms and modular components that can be moved around easily. Using a
|
|
31421
|
+
// class as a namespace facilitates this.
|
|
31422
|
+
//
|
|
31423
|
+
// tslint:disable-next-line:class-as-namespace
|
|
31424
|
+
class QuantizerCelebi {
|
|
31425
|
+
/**
|
|
31426
|
+
* @param pixels Colors in ARGB format.
|
|
31427
|
+
* @param maxColors The number of colors to divide the image into. A lower
|
|
31428
|
+
* number of colors may be returned.
|
|
31429
|
+
* @return Map with keys of colors in ARGB format, and values of number of
|
|
31430
|
+
* pixels in the original image that correspond to the color in the
|
|
31431
|
+
* quantized image.
|
|
31432
|
+
*/
|
|
31433
|
+
static quantize(pixels, maxColors) {
|
|
31434
|
+
const wu = new QuantizerWu();
|
|
31435
|
+
const wuResult = wu.quantize(pixels, maxColors);
|
|
31436
|
+
return QuantizerWsmeans.quantize(pixels, wuResult, maxColors);
|
|
31437
|
+
}
|
|
31438
|
+
}
|
|
31439
|
+
|
|
30670
31440
|
/**
|
|
30671
31441
|
* @license
|
|
30672
31442
|
* Copyright 2022 Google LLC
|
|
@@ -30768,6 +31538,145 @@ SchemeVibrant.secondaryRotations = [18.0, 15.0, 10.0, 12.0, 15.0, 18.0, 15.0, 12
|
|
|
30768
31538
|
*/
|
|
30769
31539
|
SchemeVibrant.tertiaryRotations = [35.0, 30.0, 20.0, 25.0, 30.0, 35.0, 30.0, 25.0, 25.0];
|
|
30770
31540
|
|
|
31541
|
+
/**
|
|
31542
|
+
* @license
|
|
31543
|
+
* Copyright 2021 Google LLC
|
|
31544
|
+
*
|
|
31545
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
31546
|
+
* you may not use this file except in compliance with the License.
|
|
31547
|
+
* You may obtain a copy of the License at
|
|
31548
|
+
*
|
|
31549
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
31550
|
+
*
|
|
31551
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
31552
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
31553
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31554
|
+
* See the License for the specific language governing permissions and
|
|
31555
|
+
* limitations under the License.
|
|
31556
|
+
*/
|
|
31557
|
+
const SCORE_OPTION_DEFAULTS = {
|
|
31558
|
+
desired: 4,
|
|
31559
|
+
fallbackColorARGB: 0xff4285f4,
|
|
31560
|
+
filter: true // Avoid unsuitable colors.
|
|
31561
|
+
};
|
|
31562
|
+
function compare(a, b) {
|
|
31563
|
+
if (a.score > b.score) {
|
|
31564
|
+
return -1;
|
|
31565
|
+
} else if (a.score < b.score) {
|
|
31566
|
+
return 1;
|
|
31567
|
+
}
|
|
31568
|
+
return 0;
|
|
31569
|
+
}
|
|
31570
|
+
/**
|
|
31571
|
+
* Given a large set of colors, remove colors that are unsuitable for a UI
|
|
31572
|
+
* theme, and rank the rest based on suitability.
|
|
31573
|
+
*
|
|
31574
|
+
* Enables use of a high cluster count for image quantization, thus ensuring
|
|
31575
|
+
* colors aren't muddied, while curating the high cluster count to a much
|
|
31576
|
+
* smaller number of appropriate choices.
|
|
31577
|
+
*/
|
|
31578
|
+
class Score {
|
|
31579
|
+
constructor() {}
|
|
31580
|
+
/**
|
|
31581
|
+
* Given a map with keys of colors and values of how often the color appears,
|
|
31582
|
+
* rank the colors based on suitability for being used for a UI theme.
|
|
31583
|
+
*
|
|
31584
|
+
* @param colorsToPopulation map with keys of colors and values of how often
|
|
31585
|
+
* the color appears, usually from a source image.
|
|
31586
|
+
* @param {ScoreOptions} options optional parameters.
|
|
31587
|
+
* @return Colors sorted by suitability for a UI theme. The most suitable
|
|
31588
|
+
* color is the first item, the least suitable is the last. There will
|
|
31589
|
+
* always be at least one color returned. If all the input colors
|
|
31590
|
+
* were not suitable for a theme, a default fallback color will be
|
|
31591
|
+
* provided, Google Blue.
|
|
31592
|
+
*/
|
|
31593
|
+
static score(colorsToPopulation, options) {
|
|
31594
|
+
const {
|
|
31595
|
+
desired,
|
|
31596
|
+
fallbackColorARGB,
|
|
31597
|
+
filter
|
|
31598
|
+
} = {
|
|
31599
|
+
...SCORE_OPTION_DEFAULTS,
|
|
31600
|
+
...options
|
|
31601
|
+
};
|
|
31602
|
+
// Get the HCT color for each Argb value, while finding the per hue count and
|
|
31603
|
+
// total count.
|
|
31604
|
+
const colorsHct = [];
|
|
31605
|
+
const huePopulation = new Array(360).fill(0);
|
|
31606
|
+
let populationSum = 0;
|
|
31607
|
+
for (const [argb, population] of colorsToPopulation.entries()) {
|
|
31608
|
+
const hct = Hct.fromInt(argb);
|
|
31609
|
+
colorsHct.push(hct);
|
|
31610
|
+
const hue = Math.floor(hct.hue);
|
|
31611
|
+
huePopulation[hue] += population;
|
|
31612
|
+
populationSum += population;
|
|
31613
|
+
}
|
|
31614
|
+
// Hues with more usage in neighboring 30 degree slice get a larger number.
|
|
31615
|
+
const hueExcitedProportions = new Array(360).fill(0.0);
|
|
31616
|
+
for (let hue = 0; hue < 360; hue++) {
|
|
31617
|
+
const proportion = huePopulation[hue] / populationSum;
|
|
31618
|
+
for (let i = hue - 14; i < hue + 16; i++) {
|
|
31619
|
+
const neighborHue = sanitizeDegreesInt(i);
|
|
31620
|
+
hueExcitedProportions[neighborHue] += proportion;
|
|
31621
|
+
}
|
|
31622
|
+
}
|
|
31623
|
+
// Scores each HCT color based on usage and chroma, while optionally
|
|
31624
|
+
// filtering out values that do not have enough chroma or usage.
|
|
31625
|
+
const scoredHct = new Array();
|
|
31626
|
+
for (const hct of colorsHct) {
|
|
31627
|
+
const hue = sanitizeDegreesInt(Math.round(hct.hue));
|
|
31628
|
+
const proportion = hueExcitedProportions[hue];
|
|
31629
|
+
if (filter && (hct.chroma < Score.CUTOFF_CHROMA || proportion <= Score.CUTOFF_EXCITED_PROPORTION)) {
|
|
31630
|
+
continue;
|
|
31631
|
+
}
|
|
31632
|
+
const proportionScore = proportion * 100.0 * Score.WEIGHT_PROPORTION;
|
|
31633
|
+
const chromaWeight = hct.chroma < Score.TARGET_CHROMA ? Score.WEIGHT_CHROMA_BELOW : Score.WEIGHT_CHROMA_ABOVE;
|
|
31634
|
+
const chromaScore = (hct.chroma - Score.TARGET_CHROMA) * chromaWeight;
|
|
31635
|
+
const score = proportionScore + chromaScore;
|
|
31636
|
+
scoredHct.push({
|
|
31637
|
+
hct,
|
|
31638
|
+
score
|
|
31639
|
+
});
|
|
31640
|
+
}
|
|
31641
|
+
// Sorted so that colors with higher scores come first.
|
|
31642
|
+
scoredHct.sort(compare);
|
|
31643
|
+
// Iterates through potential hue differences in degrees in order to select
|
|
31644
|
+
// the colors with the largest distribution of hues possible. Starting at
|
|
31645
|
+
// 90 degrees(maximum difference for 4 colors) then decreasing down to a
|
|
31646
|
+
// 15 degree minimum.
|
|
31647
|
+
const chosenColors = [];
|
|
31648
|
+
for (let differenceDegrees$1 = 90; differenceDegrees$1 >= 15; differenceDegrees$1--) {
|
|
31649
|
+
chosenColors.length = 0;
|
|
31650
|
+
for (const {
|
|
31651
|
+
hct
|
|
31652
|
+
} of scoredHct) {
|
|
31653
|
+
const duplicateHue = chosenColors.find(chosenHct => {
|
|
31654
|
+
return differenceDegrees(hct.hue, chosenHct.hue) < differenceDegrees$1;
|
|
31655
|
+
});
|
|
31656
|
+
if (!duplicateHue) {
|
|
31657
|
+
chosenColors.push(hct);
|
|
31658
|
+
}
|
|
31659
|
+
if (chosenColors.length >= desired) break;
|
|
31660
|
+
}
|
|
31661
|
+
if (chosenColors.length >= desired) break;
|
|
31662
|
+
}
|
|
31663
|
+
const colors = [];
|
|
31664
|
+
if (chosenColors.length === 0) {
|
|
31665
|
+
colors.push(fallbackColorARGB);
|
|
31666
|
+
}
|
|
31667
|
+
for (const chosenHct of chosenColors) {
|
|
31668
|
+
colors.push(chosenHct.toInt());
|
|
31669
|
+
}
|
|
31670
|
+
return colors;
|
|
31671
|
+
}
|
|
31672
|
+
}
|
|
31673
|
+
Score.TARGET_CHROMA = 48.0; // A1 Chroma
|
|
31674
|
+
Score.WEIGHT_PROPORTION = 0.7;
|
|
31675
|
+
Score.WEIGHT_CHROMA_ABOVE = 0.3;
|
|
31676
|
+
Score.WEIGHT_CHROMA_BELOW = 0.1;
|
|
31677
|
+
Score.CUTOFF_CHROMA = 5.0;
|
|
31678
|
+
Score.CUTOFF_EXCITED_PROPORTION = 0.01;
|
|
31679
|
+
|
|
30771
31680
|
/**
|
|
30772
31681
|
* @license
|
|
30773
31682
|
* Copyright 2021 Google LLC
|
|
@@ -30841,6 +31750,96 @@ function parseIntHex(value) {
|
|
|
30841
31750
|
return parseInt(value, 16);
|
|
30842
31751
|
}
|
|
30843
31752
|
|
|
31753
|
+
/**
|
|
31754
|
+
* @license
|
|
31755
|
+
* Copyright 2021 Google LLC
|
|
31756
|
+
*
|
|
31757
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
31758
|
+
* you may not use this file except in compliance with the License.
|
|
31759
|
+
* You may obtain a copy of the License at
|
|
31760
|
+
*
|
|
31761
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
31762
|
+
*
|
|
31763
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
31764
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
31765
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31766
|
+
* See the License for the specific language governing permissions and
|
|
31767
|
+
* limitations under the License.
|
|
31768
|
+
*/
|
|
31769
|
+
/**
|
|
31770
|
+
* Get the source color from an image.
|
|
31771
|
+
*
|
|
31772
|
+
* @param image The image element
|
|
31773
|
+
* @return Source color - the color most suitable for creating a UI theme
|
|
31774
|
+
*/
|
|
31775
|
+
async function sourceColorFromImage(image) {
|
|
31776
|
+
// Convert Image data to Pixel Array
|
|
31777
|
+
const imageBytes = await new Promise((resolve, reject) => {
|
|
31778
|
+
const canvas = document.createElement('canvas');
|
|
31779
|
+
const context = canvas.getContext('2d');
|
|
31780
|
+
if (!context) {
|
|
31781
|
+
reject(new Error('Could not get canvas context'));
|
|
31782
|
+
return;
|
|
31783
|
+
}
|
|
31784
|
+
const loadCallback = () => {
|
|
31785
|
+
canvas.width = image.width;
|
|
31786
|
+
canvas.height = image.height;
|
|
31787
|
+
context.drawImage(image, 0, 0);
|
|
31788
|
+
let rect = [0, 0, image.width, image.height];
|
|
31789
|
+
const area = image.dataset['area'];
|
|
31790
|
+
if (area && /^\d+(\s*,\s*\d+){3}$/.test(area)) {
|
|
31791
|
+
rect = area.split(/\s*,\s*/).map(s => {
|
|
31792
|
+
// tslint:disable-next-line:ban
|
|
31793
|
+
return parseInt(s, 10);
|
|
31794
|
+
});
|
|
31795
|
+
}
|
|
31796
|
+
const [sx, sy, sw, sh] = rect;
|
|
31797
|
+
resolve(context.getImageData(sx, sy, sw, sh).data);
|
|
31798
|
+
};
|
|
31799
|
+
const errorCallback = () => {
|
|
31800
|
+
reject(new Error('Image load failed'));
|
|
31801
|
+
};
|
|
31802
|
+
if (image.complete) {
|
|
31803
|
+
loadCallback();
|
|
31804
|
+
} else {
|
|
31805
|
+
image.onload = loadCallback;
|
|
31806
|
+
image.onerror = errorCallback;
|
|
31807
|
+
}
|
|
31808
|
+
});
|
|
31809
|
+
// Convert Image data to Pixel Array
|
|
31810
|
+
const pixels = [];
|
|
31811
|
+
for (let i = 0; i < imageBytes.length; i += 4) {
|
|
31812
|
+
const r = imageBytes[i];
|
|
31813
|
+
const g = imageBytes[i + 1];
|
|
31814
|
+
const b = imageBytes[i + 2];
|
|
31815
|
+
const a = imageBytes[i + 3];
|
|
31816
|
+
if (a < 255) {
|
|
31817
|
+
continue;
|
|
31818
|
+
}
|
|
31819
|
+
const argb = argbFromRgb(r, g, b);
|
|
31820
|
+
pixels.push(argb);
|
|
31821
|
+
}
|
|
31822
|
+
// Convert Pixels to Material Colors
|
|
31823
|
+
const result = QuantizerCelebi.quantize(pixels, 128);
|
|
31824
|
+
const ranked = Score.score(result);
|
|
31825
|
+
const top = ranked[0];
|
|
31826
|
+
return top;
|
|
31827
|
+
}
|
|
31828
|
+
|
|
31829
|
+
/**
|
|
31830
|
+
* Extracts the Material source color from an image and returns it as a hex string.
|
|
31831
|
+
* @param {HTMLImageElement} image - A fully loaded image element. Pixel data is sampled to derive the source color.
|
|
31832
|
+
* @returns {Promise<string>} A hex color string (`#RRGGBB`) representing the extracted source color.
|
|
31833
|
+
*
|
|
31834
|
+
* @example
|
|
31835
|
+
* const img = document.querySelector("img");
|
|
31836
|
+
* const color = await getColorFromImage(img);
|
|
31837
|
+
* // "#6750A4"
|
|
31838
|
+
*/
|
|
31839
|
+
async function getColorFromImage(image) {
|
|
31840
|
+
return hexFromArgb(await sourceColorFromImage(image));
|
|
31841
|
+
}
|
|
31842
|
+
|
|
30844
31843
|
var _M3eThemeElement_instances, _M3eThemeElement_styleSheet, _M3eThemeElement_firstUpdated, _M3eThemeElement_light, _M3eThemeElement_dark, _M3eThemeElement_forcedColor, _M3eThemeElement_colorSchemeChangeHandler, _M3eThemeElement_apply, _M3eThemeElement_getContrastLevel;
|
|
30845
31844
|
/**
|
|
30846
31845
|
* A non-visual element responsible for application-level theming.
|
|
@@ -31132,7 +32131,7 @@ let M3eTocItemElement = class M3eTocItemElement extends Selected$1(Disabled$1(At
|
|
|
31132
32131
|
}
|
|
31133
32132
|
};
|
|
31134
32133
|
/** The styles of the element. */
|
|
31135
|
-
M3eTocItemElement.styles = css`:host { display: inline-block; position: relative; user-select: none; outline: none; border-radius: var(--m3e-toc-item-shape, ${DesignToken$1.shape.corner.largeIncreased}); padding-block: var(--m3e-toc-item-padding-block, 0.5rem); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } :host(:not(:disabled)) { cursor: pointer; } .base { padding-inline-start: calc( var(--m3e-toc-item-padding, 1rem) + calc(var(--m3e-toc-item-inset, 0.75rem) * var(--_level, 0)) ); padding-inline-end: var(--m3e-toc-item-padding, 1rem); transition: ${unsafeCSS(`color var(--m3e-toc-active-indicator-animation-duration, ${DesignToken$1.motion.duration.long1}) ${DesignToken$1.motion.easing.standard}`)}; } :host(:not([selected])) { font-size: var(--m3e-toc-item-font-size, ${DesignToken$1.typescale.standard.body.large.fontSize}); font-weight: var(--m3e-toc-item-font-weight, ${DesignToken$1.typescale.standard.body.large.fontWeight}); line-height: var(--m3e-toc-item-line-height, ${DesignToken$1.typescale.standard.body.large.lineHeight}); letter-spacing: var(--m3e-toc-item-tracking, ${DesignToken$1.typescale.standard.body.large.tracking}); color: var(--m3e-toc-item-color, ${DesignToken$1.color.onSurfaceVariant}); } :host([selected]) { font-size: var(--m3e-toc-item-selected-font-size, ${DesignToken$1.typescale.emphasized.body.large.fontSize}); font-weight: var(--m3e-toc-item-selected-font-weight, ${DesignToken$1.typescale.emphasized.body.large.fontWeight}); line-height: var(--m3e-toc-item-selected-line-height, ${DesignToken$1.typescale.emphasized.body.large.lineHeight}); letter-spacing: var(--m3e-toc-item-selected-tracking, ${DesignToken$1.typescale.emphasized.body.large.tracking}); color: var(--m3e-toc-item-selected-color, ${DesignToken$1.color.
|
|
32134
|
+
M3eTocItemElement.styles = css`:host { display: inline-block; position: relative; user-select: none; outline: none; border-radius: var(--m3e-toc-item-shape, ${DesignToken$1.shape.corner.largeIncreased}); padding-block: var(--m3e-toc-item-padding-block, 0.5rem); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } :host(:not(:disabled)) { cursor: pointer; } .base { padding-inline-start: calc( var(--m3e-toc-item-padding, 1rem) + calc(var(--m3e-toc-item-inset, 0.75rem) * var(--_level, 0)) ); padding-inline-end: var(--m3e-toc-item-padding, 1rem); transition: ${unsafeCSS(`color var(--m3e-toc-active-indicator-animation-duration, ${DesignToken$1.motion.duration.long1}) ${DesignToken$1.motion.easing.standard}`)}; } :host(:not([selected])) { font-size: var(--m3e-toc-item-font-size, ${DesignToken$1.typescale.standard.body.large.fontSize}); font-weight: var(--m3e-toc-item-font-weight, ${DesignToken$1.typescale.standard.body.large.fontWeight}); line-height: var(--m3e-toc-item-line-height, ${DesignToken$1.typescale.standard.body.large.lineHeight}); letter-spacing: var(--m3e-toc-item-tracking, ${DesignToken$1.typescale.standard.body.large.tracking}); color: var(--m3e-toc-item-color, ${DesignToken$1.color.onSurfaceVariant}); } :host([selected]) { font-size: var(--m3e-toc-item-selected-font-size, ${DesignToken$1.typescale.emphasized.body.large.fontSize}); font-weight: var(--m3e-toc-item-selected-font-weight, ${DesignToken$1.typescale.emphasized.body.large.fontWeight}); line-height: var(--m3e-toc-item-selected-line-height, ${DesignToken$1.typescale.emphasized.body.large.lineHeight}); letter-spacing: var(--m3e-toc-item-selected-tracking, ${DesignToken$1.typescale.emphasized.body.large.tracking}); color: var(--m3e-toc-item-selected-color, ${DesignToken$1.color.onSurface}); } .base { justify-content: unset; } .state-layer { --m3e-state-layer-focus-opacity: 0; } @media (prefers-reduced-motion) { .base { transition: none; } }`;
|
|
31136
32135
|
__decorate([query(".base")], M3eTocItemElement.prototype, "_base", void 0);
|
|
31137
32136
|
__decorate([query(".state-layer")], M3eTocItemElement.prototype, "_stateLayer", void 0);
|
|
31138
32137
|
__decorate([state()], M3eTocItemElement.prototype, "node", void 0);
|
|
@@ -32226,7 +33225,7 @@ var M3eTreeItemElement_1;
|
|
|
32226
33225
|
* @cssprop --m3e-tree-item-disabled-color - Text color for disabled item.
|
|
32227
33226
|
* @cssprop --m3e-tree-item-disabled-color-opacity - Opacity for disabled item text color.
|
|
32228
33227
|
*/
|
|
32229
|
-
let M3eTreeItemElement = M3eTreeItemElement_1 = class M3eTreeItemElement extends Selected$1(Disabled$1(
|
|
33228
|
+
let M3eTreeItemElement = M3eTreeItemElement_1 = class M3eTreeItemElement extends Selected$1(Disabled$1(AttachInternals$1(Role$1(LitElement, "treeitem"), true))) {
|
|
32230
33229
|
constructor() {
|
|
32231
33230
|
super(...arguments);
|
|
32232
33231
|
_M3eTreeItemElement_instances.add(this);
|
|
@@ -32896,5 +33895,5 @@ __decorate([property({
|
|
|
32896
33895
|
})], M3eTreeElement.prototype, "cascade", void 0);
|
|
32897
33896
|
M3eTreeElement = M3eTreeElement_1 = __decorate([customElement$1("m3e-tree")], M3eTreeElement);
|
|
32898
33897
|
|
|
32899
|
-
export { ActionElementBase, AnimationLoopController, AttachInternals, CalendarViewElementBase, Checked, CheckedIndeterminate, ConstraintValidation, DesignToken, Dirty, Disabled, DisabledInteractive,
|
|
33898
|
+
export { ActionElementBase, AnimationLoopController, AttachInternals, CalendarViewElementBase, Checked, CheckedIndeterminate, ConstraintValidation, DesignToken, Dirty, Disabled, DisabledInteractive, FocusController, Focusable, FormAssociated, FormSubmitter, HoverController, HtmlFor, InertController, IntersectionController, KeyboardClick, Labelled, LinkButton, LongPressController, M3eAccordionElement, M3eActionListElement, M3eAppBarElement, M3eAssistChipElement, M3eAutocompleteElement, M3eAvatarElement, M3eBadgeElement, M3eBottomSheetActionElement, M3eBottomSheetElement, M3eBottomSheetTriggerElement, M3eBreadcrumbElement, M3eBreadcrumbItemElement, M3eButtonElement, M3eButtonGroupElement, M3eButtonSegmentElement, M3eCalendarElement, M3eCardElement, M3eCheckboxElement, M3eChipElement, M3eChipSetElement, M3eCircularProgressIndicatorElement, M3eCollapsibleElement, M3eContentPaneElement, M3eDatepickerElement, M3eDatepickerToggleElement, M3eDialogActionElement, M3eDialogElement, M3eDialogTriggerElement, M3eDividerElement, M3eDrawerContainerElement, M3eDrawerToggleElement, M3eElevationElement, M3eExpandableListItemElement, M3eExpansionHeaderElement, M3eExpansionPanelElement, M3eFabElement, M3eFabMenuElement, M3eFabMenuItemElement, M3eFabMenuTriggerElement, M3eFilterChipElement, M3eFilterChipSetElement, M3eFocusRingElement, M3eFormFieldElement, M3eHeadingElement, M3eIconButtonElement, M3eIconElement, M3eInputChipElement, M3eInputChipSetElement, M3eLinearProgressIndicatorElement, M3eListActionElement, M3eListElement, M3eListItemElement, M3eListOptionElement, M3eLoadingIndicatorElement, M3eMenuElement, M3eMenuItemCheckboxElement, M3eMenuItemElement, M3eMenuItemGroupElement, M3eMenuItemRadioElement, M3eMenuTriggerElement, M3eMonthViewElement, M3eMultiYearViewElement, M3eNavBarElement, M3eNavItemElement, M3eNavMenuElement, M3eNavMenuItemElement, M3eNavMenuItemGroupElement, M3eNavRailElement, M3eNavRailToggleElement, M3eOptGroupElement, M3eOptionElement, M3eOptionPanelElement, M3ePaginatorElement, M3ePseudoCheckboxElement, M3ePseudoRadioElement, M3eRadioElement, M3eRadioGroupElement, M3eRichTooltipActionElement, M3eRichTooltipElement, M3eRippleElement, M3eScrollContainerElement, M3eSearchBarElement, M3eSearchViewElement, M3eSegmentedButtonElement, M3eSelectElement, M3eSelectionListElement, M3eShapeElement, M3eSkeletonElement, M3eSlideElement, M3eSlideGroupElement, M3eSliderElement, M3eSliderThumbElement, M3eSnackbar, M3eSnackbarElement, M3eSplitButtonElement, M3eSplitPaneElement, M3eStateLayerElement, M3eStepElement, M3eStepPanelElement, M3eStepperElement, M3eStepperNextElement, M3eStepperPreviousElement, M3eStepperResetElement, M3eSuggestionChipElement, M3eSwitchElement, M3eTabElement, M3eTabPanelElement, M3eTabsElement, M3eTextHighlightElement, M3eTextOverflowElement, M3eTextareaAutosizeElement, M3eThemeElement, M3eTocElement, M3eTocItemElement, M3eToolbarElement, M3eTooltipElement, M3eTreeElement, M3eTreeItemElement, M3eYearViewElement, MutationController, PressedController, ProgressElementIndicatorBase, ReadOnly, ReconnectedCallback, Required, RequiredConstraintValidation, ResizeController, Role, ScrollController, ScrollLockController, Selected, StepperButtonElementBase, SuppressInitialAnimation, TocGenerator, TooltipElementBase, Touched, VelocityTracker, Vertical, addCustomState, checkOrSelect, computeCssSize, computeLineCount, customElement, dateConverter, debounce, defaultValue, deleteCustomState, findFormFieldControl, focusWhenReady, forcedColorsActive, formValue, generateClipPaths, getColorFromImage, getScrollbarWidth, getTextContent, guid, hasAssignedNodes, hasCustomState, hasKeys, interceptProperty, internals, isAttachInternalsMixin, isCheckedIndeterminateMixin, isCheckedMixin, isCheckedOrSelected, isCheckedOrSelectedMixin, isConstraintValidationMixin, isDirtyMixin, isDisabledInteractiveMixin, isDisabledMixin, isFormAssociatedMixin, isFormFieldControl, isFormSubmitterMixin, isHtmlForMixin, isLabelledMixin, isLinkButtonMixin, isReadOnlyMixin, isRequiredConstraintValidationMixin, isRequiredMixin, isSelectedMixin, isTouchedMixin, isVerticalMixin, prefersReducedMotion, registerIcon, registerStyleSheet, renderPseudoLink, resolveElementById, resolveFragmentUrl, safeStyleMap, scrollIntoViewIfNeeded, setCustomState, spaceSeparatedStringConverter, updateLabels, validate, waitForUpgrade };
|
|
32900
33899
|
//# sourceMappingURL=all.js.map
|