From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../components/shopping/content/shopping-card.mjs | 204 +++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 browser/components/shopping/content/shopping-card.mjs (limited to 'browser/components/shopping/content/shopping-card.mjs') diff --git a/browser/components/shopping/content/shopping-card.mjs b/browser/components/shopping/content/shopping-card.mjs new file mode 100644 index 0000000000..7b2448df36 --- /dev/null +++ b/browser/components/shopping/content/shopping-card.mjs @@ -0,0 +1,204 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { html, ifDefined } from "chrome://global/content/vendor/lit.all.mjs"; +import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; + +const MIN_SHOW_MORE_HEIGHT = 200; +/** + * A card container to be used in the shopping sidebar. There are three card types. + * The default type where no type attribute is required and the card will have no extra functionality. + * The "accordion" type will initially not show any content. The card will contain a arrow to expand the + * card so all of the content is visible. + * + * @property {string} label - The label text that will be used for the card header + * @property {string} type - (optional) The type of card. No type specified + * will be the default card. The other available types are "accordion" and "show-more". + */ +class ShoppingCard extends MozLitElement { + static properties = { + label: { type: String }, + type: { type: String }, + _isExpanded: { type: Boolean }, + }; + + static get queries() { + return { + detailsEl: "#shopping-details", + contentEl: "#content", + }; + } + + labelTemplate() { + if (this.label) { + if (this.type === "accordion") { + return html` +
+ + +
+ `; + } + return html` +
+ + +
+ `; + } + return ""; + } + + cardTemplate() { + if (this.type === "accordion") { + return html` +
+ ${this.labelTemplate()} +
+
+ `; + } else if (this.type === "show-more") { + return html` + ${this.labelTemplate()} +
+ + +
+ +
+
+ `; + } + return html` + ${this.labelTemplate()} +
+ +
+ `; + } + + onCardToggle() { + const action = this.detailsEl.open ? "expanded" : "collapsed"; + let l10nId = this.getAttribute("data-l10n-id"); + switch (l10nId) { + case "shopping-settings-label": + Glean.shopping.surfaceSettingsExpandClicked.record({ action }); + break; + case "shopping-analysis-explainer-label": + Glean.shopping.surfaceShowQualityExplainerClicked.record({ + action, + }); + break; + } + } + + handleShowMoreButtonClick(e) { + this._isExpanded = !this._isExpanded; + // toggle show more/show less text + e.target.setAttribute( + "data-l10n-id", + this._isExpanded + ? "shopping-show-less-button" + : "shopping-show-more-button" + ); + // toggle content expanded attribute + this.contentEl.attributes.expanded.value = this._isExpanded; + + let action = this._isExpanded ? "expanded" : "collapsed"; + Glean.shopping.surfaceShowMoreReviewsButtonClicked.record({ + action, + }); + } + + enableShowMoreButton() { + this._isExpanded = false; + this.toggleAttribute("showMoreButtonDisabled", false); + this.contentEl.attributes.expanded.value = false; + } + + disableShowMoreButton() { + this._isExpanded = true; + this.toggleAttribute("showMoreButtonDisabled", true); + this.contentEl.attributes.expanded.value = true; + } + + handleChevronButtonClick() { + this.detailsEl.open = !this.detailsEl.open; + } + + firstUpdated() { + if (this.type !== "show-more") { + return; + } + + let contentSlot = this.shadowRoot.querySelector("slot[name='content']"); + let contentSlotEls = contentSlot.assignedElements(); + if (!contentSlotEls.length) { + return; + } + + let slottedDiv = contentSlotEls[0]; + + this.handleContentSlotResize = this.handleContentSlotResize.bind(this); + this.contentResizeObserver = new ResizeObserver( + this.handleContentSlotResize + ); + this.contentResizeObserver.observe(slottedDiv); + } + + disconnectedCallback() { + this.contentResizeObserver?.disconnect(); + } + + handleContentSlotResize(entries) { + for (let entry of entries) { + if (entry.contentRect.height === 0) { + return; + } + + if (entry.contentRect.height < MIN_SHOW_MORE_HEIGHT) { + this.disableShowMoreButton(); + } else if (this.hasAttribute("showMoreButtonDisabled")) { + this.enableShowMoreButton(); + } + } + } + + render() { + return html` + + +
+ ${this.cardTemplate()} +
+ `; + } +} +customElements.define("shopping-card", ShoppingCard); -- cgit v1.2.3