|
| 1 | +/*! |
| 2 | + * PatternFly Elements: PfeAccordion 1.7.0 |
| 3 | + * @license |
| 4 | + * Copyright 2021 Red Hat, Inc. |
| 5 | + * |
| 6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | + * of this software and associated documentation files (the "Software"), to deal |
| 8 | + * in the Software without restriction, including without limitation the rights |
| 9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 10 | + * copies of the Software, and to permit persons to whom the Software is |
| 11 | + * furnished to do so, subject to the following conditions: |
| 12 | + * |
| 13 | + * The above copyright notice and this permission notice shall be included in |
| 14 | + * all copies or substantial portions of the Software. |
| 15 | + * |
| 16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 22 | + * SOFTWARE. |
| 23 | + * |
| 24 | +*/ |
| 25 | + |
| 26 | +import PFElement from "../../pfelement/dist/pfelement.js"; |
| 27 | + |
| 28 | +class PfeAccordionHeader extends PFElement { |
| 29 | + |
| 30 | + // Injected at build-time |
| 31 | + static get version() { |
| 32 | + return "1.7.0"; |
| 33 | + } |
| 34 | + |
| 35 | + // Injected at build-time |
| 36 | + get html() { |
| 37 | + return ` |
| 38 | +<style>:host{-webkit-transition:-webkit-transform .3s cubic-bezier(.465,.183,.153,.946);transition:-webkit-transform .3s cubic-bezier(.465,.183,.153,.946);transition:transform .3s cubic-bezier(.465,.183,.153,.946);transition:transform .3s cubic-bezier(.465,.183,.153,.946),-webkit-transform .3s cubic-bezier(.465,.183,.153,.946);-webkit-transition:-webkit-transform .3s var(--pfe-theme--animation-timing,cubic-bezier(.465,.183,.153,.946));transition:-webkit-transform .3s var(--pfe-theme--animation-timing,cubic-bezier(.465,.183,.153,.946));transition:transform .3s var(--pfe-theme--animation-timing,cubic-bezier(.465,.183,.153,.946));transition:transform .3s var(--pfe-theme--animation-timing,cubic-bezier(.465,.183,.153,.946)),-webkit-transform .3s var(--pfe-theme--animation-timing,cubic-bezier(.465,.183,.153,.946));display:block}:host([hidden]){display:none}:host>*{margin:0}:host button{--pfe-accordion--BorderBottomWidth:0;--pfe-accordion--ZIndex:3;--pfe-accordion__trigger--Padding:var(--pfe-accordion__base--Padding, var(--pfe-theme--container-spacer, 1rem)) 50px var(--pfe-accordion__base--Padding, var(--pfe-theme--container-spacer, 1rem)) calc(var(--pfe-accordion__base--Padding, var(--pfe-theme--container-spacer, 1rem)) * 1.5);margin:0;width:100%;width:var(--pfe-accordion--Width,100%);max-width:100%;height:auto;position:relative;background-color:transparent;background-color:var(--pfe-accordion--BackgroundColor,transparent);color:#3c3f42;color:var(--pfe-accordion--Color,var(--pfe-broadcasted--text,#3c3f42));border-width:0;border-style:solid;border-style:var(--pfe-theme--surface--border-style,solid);border-color:#d2d2d2;border-color:var(--pfe-accordion--BorderColor,var(--pfe-theme--color--surface--border,#d2d2d2));border-top-width:1px;border-top-width:var(--pfe-accordion--BorderTopWidth,var(--pfe-theme--surface--border-width,1px));border-right-width:0;border-right-width:var(--pfe-accordion--BorderRightWidth,0);border-bottom-width:1px;border-bottom-width:var(--pfe-accordion--BorderBottomWidth,var(--pfe-theme--surface--border-width,1px));border-left-width:4px;border-left-width:var(--pfe-accordion--BorderLeftWidth,var(--pfe-theme--surface--border-width--heavy,4px));border-left-color:transparent;border-left-color:var(--pfe-accordion--BorderColor--accent,transparent);-webkit-box-shadow:var(--pfe-accordion--BoxShadow);box-shadow:var(--pfe-accordion--BoxShadow);z-index:var(--pfe-accordion--ZIndex);cursor:pointer;font-family:inherit;font-size:calc(1rem * 1.1);font-size:var(--pfe-accordion--FontSize--header,calc(var(--pfe-theme--font-size,1rem) * 1.1));font-weight:700;font-weight:var(--pfe-theme--font-weight--bold,700);text-align:left;text-align:var(--pfe-accordion--TextAlign,left);line-height:1.5;line-height:var(--pfe-theme--line-height,1.5);padding:var(--pfe-accordion__trigger--Padding)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host button{border-top-width:1px;border-right-width:0;border-bottom-width:1px;border-left-width:4px}}:host button:focus,:host button:hover{--pfe-accordion--BorderColor--accent:var(--pfe-accordion--accent, var(--pfe-theme--color--ui-accent, #06c))}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host button:focus,:host button:hover{border-left-color:#06c}}:host button:hover{outline:0;border-left-width:4px;border-left-width:var(--pfe-theme--surface--border-width--heavy,4px)}:host button:focus{outline:0;text-decoration:underline}:host button::-moz-focus-inner{border:0}@supports (-ms-ime-align:auto){:host button{text-align:left}}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host button{padding:16px 24px}:host button:hover{border-left-color:#06c}}:host button[aria-expanded=true]{--pfe-accordion--BorderColor:var(--pfe-theme--color--surface--border, #d2d2d2);--pfe-accordion--BorderRightWidth:var(--pfe-theme--surface--border-width, 1px);--pfe-accordion--BorderLeftWidth:var(--pfe-theme--surface--border-width--heavy, 4px);--pfe-accordion--BackgroundColor:white;--pfe-accordion--Color:var(--pfe-theme--color--text, #151515);--pfe-accordion--BorderColor--accent:var(--pfe-accordion--accent, var(--pfe-theme--color--ui-accent, #06c));--pfe-accordion--BoxShadow:0 5px var(--pfe-theme--surface--border-width--heavy, 4px) rgba(140, 140, 140, 0.35);--pfe-accordion--ZIndex:3}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host button[aria-expanded=true]{border-bottom-width:0;border-left-color:#06c;border-right-color:#d2d2d2}}:host(:not([disclosure=true])) button::after{content:"";position:absolute;top:calc(1rem + .4em);top:calc(var(--pfe-theme--container-spacer,1rem) + .4em);display:block;border-style:solid;border-style:var(--pfe-theme--surface--border-style,solid);height:.4em;width:.4em;-webkit-transition:-webkit-transform .15s;transition:-webkit-transform .15s;transition:transform .15s;transition:transform .15s,-webkit-transform .15s;border-width:0 .1em .1em 0;-webkit-transform:rotate(45deg);transform:rotate(45deg);right:calc(1rem * 1.3125);right:calc(var(--pfe-theme--container-spacer,1rem) * 1.3125)}:host(:not([disclosure=true])) button[aria-expanded=true]::after{-webkit-transform:rotate(-135deg);transform:rotate(-135deg)}:host(:last-of-type) button:not([aria-expanded=true]){--pfe-accordion--BorderBottomWidth:var(--pfe-theme--surface--border-width, 1px)}:host(:last-of-type.animating) button{--pfe-accordion--BorderBottomWidth:0}:host([on=dark]) button[aria-expanded=true]{--pfe-accordion--BackgroundColor:rgba(247, 247, 249, 0.1);--pfe-accordion--Color:var(--pfe-broadcasted--text, #3c3f42);--pfe-accordion--BorderColor--accent:var(--pfe-theme--color--ui-accent--on-dark, #73bcf7);--pfe-accordion--BoxShadow:none}:host([on=saturated]) button[aria-expanded=true]{--pfe-accordion--BackgroundColor:rgba(0, 0, 0, 0.2);--pfe-accordion--Color:var(--pfe-broadcasted--text, #3c3f42);--pfe-accordion--BorderColor--accent:var(--pfe-theme--color--ui-accent--on-saturated, #fff);--pfe-accordion--BoxShadow:none}:host([disclosure=true]) button{padding-left:calc(1rem * 3);padding-left:calc(var(--pfe-accordion__base--Padding,var(--pfe-theme--container-spacer,1rem)) * 3)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([disclosure=true]) button{padding:16px 24px 16px 47px;border-right-color:#d2d2d2;border-left-color:#d2d2d2;border-left-width:1px}}:host([disclosure=true]) button::before{content:"";position:absolute;top:calc(1rem + .55em);top:calc(var(--pfe-theme--container-spacer,1rem) + .55em);display:block;border-style:solid;border-style:var(--pfe-theme--surface--border-style,solid);height:.4em;width:.4em;-webkit-transition:-webkit-transform .15s;transition:-webkit-transform .15s;transition:transform .15s;transition:transform .15s,-webkit-transform .15s;border-width:0 .1em .1em 0;-webkit-transform:rotate(45deg);transform:rotate(45deg);left:calc(1rem * 1.3125);left:calc(var(--pfe-theme--container-spacer,1rem) * 1.3125);-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}:host([disclosure=true]) button[aria-expanded=true]::before{-webkit-transform:rotate(45deg);transform:rotate(45deg)}:host([disclosure=true]) button:not([aria-expanded=true]):hover,:host([disclosure=true]) button[aria-expanded=true]{padding-left:calc(1rem * 3 - 4px + 1px);padding-left:calc(var(--pfe-accordion__base--Padding,var(--pfe-theme--container-spacer,1rem)) * 3 - var(--pfe-theme--surface--border-width--heavy,4px) + var(--pfe-theme--surface--border-width,1px))}:host([disclosure=true]) button:not([aria-expanded=true]):hover::before,:host([disclosure=true]) button[aria-expanded=true]::before{margin-left:calc((4px - 1px) * -1);margin-left:calc((var(--pfe-theme--surface--border-width--heavy,4px) - var(--pfe-theme--surface--border-width,1px)) * -1)}@media screen and (-ms-high-contrast:active),screen and (-ms-high-contrast:none){:host([disclosure=true]) button:not([aria-expanded=true]):hover,:host([disclosure=true]) button[aria-expanded=true]{border-left-color:#06c;border-left-width:4px;border-right-color:#d2d2d2}} /*# sourceMappingURL=pfe-accordion-header.min.css.map */</style> |
| 39 | +`; |
| 40 | + } |
| 41 | + |
| 42 | + static get tag() { |
| 43 | + return "pfe-accordion-header"; |
| 44 | + } |
| 45 | + |
| 46 | + get styleUrl() { |
| 47 | + return "pfe-accordion-header.scss"; |
| 48 | + } |
| 49 | + |
| 50 | + get templateUrl() { |
| 51 | + return "pfe-accordion-header.html"; |
| 52 | + } |
| 53 | + |
| 54 | + static get properties() { |
| 55 | + return { |
| 56 | + _id: { |
| 57 | + type: String, |
| 58 | + default: el => `${el.randomId.replace("pfe", el.tag)}`, |
| 59 | + prefix: false |
| 60 | + }, |
| 61 | + ariaControls: { |
| 62 | + type: String, |
| 63 | + prefix: false |
| 64 | + }, |
| 65 | + // @TODO Deprecated pfe-id in 1.0 |
| 66 | + oldPfeId: { |
| 67 | + type: String, |
| 68 | + alias: "_id", |
| 69 | + attr: "pfe-id" |
| 70 | + }, |
| 71 | + expanded: { |
| 72 | + title: "Expanded", |
| 73 | + type: Boolean, |
| 74 | + cascade: "#pfe-accordion-header--button", |
| 75 | + observer: "_expandedChanged" |
| 76 | + } |
| 77 | + }; |
| 78 | + } |
| 79 | + |
| 80 | + static get events() { |
| 81 | + return { |
| 82 | + change: `pfe-accordion:change` |
| 83 | + }; |
| 84 | + } |
| 85 | + |
| 86 | + constructor() { |
| 87 | + super(PfeAccordionHeader); |
| 88 | + |
| 89 | + this._init = this._init.bind(this); |
| 90 | + this._clickHandler = this._clickHandler.bind(this); |
| 91 | + this._observer = new MutationObserver(this._init); |
| 92 | + this._slotObserver = new MutationObserver(this._init); |
| 93 | + |
| 94 | + this._getHeaderElement = this._getHeaderElement.bind(this); |
| 95 | + this._createButton = this._createButton.bind(this); |
| 96 | + } |
| 97 | + |
| 98 | + connectedCallback() { |
| 99 | + super.connectedCallback(); |
| 100 | + |
| 101 | + if (this.hasLightDOM()) this._init(); |
| 102 | + |
| 103 | + this.addEventListener("click", this._clickHandler); |
| 104 | + this._observer.observe(this, { |
| 105 | + childList: true |
| 106 | + }); |
| 107 | + } |
| 108 | + |
| 109 | + disconnectedCallback() { |
| 110 | + super.disconnectedCallback(); |
| 111 | + |
| 112 | + this.removeEventListener("click", this._clickHandler); |
| 113 | + this._observer.disconnect(); |
| 114 | + } |
| 115 | + |
| 116 | + _init() { |
| 117 | + if (window.ShadyCSS) { |
| 118 | + this._observer.disconnect(); |
| 119 | + } |
| 120 | + |
| 121 | + const existingButton = this.shadowRoot.querySelector(`#${this.tag}--button`); |
| 122 | + const button = existingButton || this._createButton(); |
| 123 | + const existingHeader = existingButton ? existingButton.parentElement : null; |
| 124 | + const header = this._getHeaderElement(); |
| 125 | + |
| 126 | + if (header) { |
| 127 | + let wrapperTag = document.createElement(header.tagName.toLowerCase() || "h3"); |
| 128 | + if (existingHeader && existingHeader.tagName === header.tagName) { |
| 129 | + wrapperTag = existingHeader; |
| 130 | + } else if (existingHeader && existingHeader.tagName !== header.tagName) { |
| 131 | + existingHeader.remove(); |
| 132 | + } |
| 133 | + |
| 134 | + button.innerText = header.innerText; |
| 135 | + |
| 136 | + wrapperTag.appendChild(button); |
| 137 | + this.shadowRoot.appendChild(wrapperTag); |
| 138 | + } else { |
| 139 | + button.innerText = this.textContent.trim(); |
| 140 | + } |
| 141 | + |
| 142 | + if (window.ShadyCSS) { |
| 143 | + this._observer.observe(this, { |
| 144 | + childList: true |
| 145 | + }); |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + _getHeaderElement() { |
| 150 | + // Check if there is no nested element or nested textNodes |
| 151 | + if (!this.firstElementChild && !this.firstChild) { |
| 152 | + this.warn(`No header content provided`); |
| 153 | + return; |
| 154 | + } |
| 155 | + |
| 156 | + if (this.firstElementChild && this.firstElementChild.tagName) { |
| 157 | + // If the first element is a slot, query for it's content |
| 158 | + if (this.firstElementChild.tagName === "SLOT") { |
| 159 | + const slotted = this.firstElementChild.assignedNodes(); |
| 160 | + // If there is no content inside the slot, return empty with a warning |
| 161 | + if (slotted.length === 0) { |
| 162 | + this.warn(`No heading information exists within this slot.`); |
| 163 | + return; |
| 164 | + } |
| 165 | + // If there is more than 1 element in the slot, capture the first h-tag |
| 166 | + if (slotted.length > 1) this.warn(`Heading currently only supports 1 tag.`); |
| 167 | + const htags = slotted.filter(slot => slot.tagName.match(/^H[1-6]/) || slot.tagName === "P"); |
| 168 | + if (htags.length > 0) { |
| 169 | + // Return the first htag and attach an observer event to watch for it |
| 170 | + slotted.forEach(slot => |
| 171 | + this._slotObserver.observe(slot, { |
| 172 | + characterData: true, |
| 173 | + childList: true, |
| 174 | + subtree: true |
| 175 | + }) |
| 176 | + ); |
| 177 | + return htags[0]; |
| 178 | + } else return; |
| 179 | + } else if (this.firstElementChild.tagName.match(/^H[1-6]/) || this.firstElementChild.tagName === "P") { |
| 180 | + return this.firstElementChild; |
| 181 | + } else { |
| 182 | + this.warn(`Heading should contain at least 1 heading tag for correct semantics.`); |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + return; |
| 187 | + } |
| 188 | + |
| 189 | + _createButton(expanded = "false") { |
| 190 | + const button = document.createElement("button"); |
| 191 | + button.type = "button"; |
| 192 | + button.setAttribute("aria-expanded", expanded); |
| 193 | + button.id = `${this.tag}--button`; |
| 194 | + return button; |
| 195 | + } |
| 196 | + |
| 197 | + _clickHandler(event) { |
| 198 | + this.emitEvent(PfeAccordionHeader.events.change, { |
| 199 | + detail: { |
| 200 | + expanded: !this.expanded |
| 201 | + } |
| 202 | + }); |
| 203 | + } |
| 204 | + |
| 205 | + _expandedChanged() { |
| 206 | + this.setAttribute("aria-expanded", this.expanded); |
| 207 | + |
| 208 | + const button = this.shadowRoot.querySelector(`#${this.tag}--button`); |
| 209 | + if (button) button.setAttribute("aria-expanded", this.expanded); |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | +export default PfeAccordionHeader; |
0 commit comments