UNPKG

@rhds/elements

Version:

Red Hat Design System Elements

313 lines (310 loc) 18.7 kB
var _RhPagination_instances, _RhPagination_dir, _RhPagination_mo, _RhPagination_screen, _RhPagination_logger, _RhPagination_ol, _RhPagination_links, _RhPagination_firstLink, _RhPagination_lastLink, _RhPagination_nextLink, _RhPagination_prevLink, _RhPagination_currentLink, _RhPagination_currentIndex, _RhPagination_currentPage_get, _RhPagination_update, _RhPagination_getOverflow, _RhPagination_getCurrentLink, _RhPagination_updateLightDOMRefs, _RhPagination_checkValidity, _RhPagination_go, _RhPagination_onKeyup, _RhPagination_onChange; import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib"; import { LitElement, html } from 'lit'; import { customElement } from 'lit/decorators/custom-element.js'; import { property } from 'lit/decorators/property.js'; import { query } from 'lit/decorators/query.js'; import { classMap } from 'lit/directives/class-map.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { Logger } from '@patternfly/pfe-core/controllers/logger.js'; import { ScreenSizeController } from '../../lib/ScreenSizeController.js'; import { DirController } from '../../lib/DirController.js'; import { css } from "lit"; const styles = css `:host{display:block;min-height:4em}[hidden]{display:none!important}#container{display:flex;gap:calc(var(--rh-space-xs,4px)/ 2);flex-wrap:wrap}nav{display:contents}svg{fill:currentcolor}.stepper{display:flex;align-items:center;justify-content:center;height:50px;width:50px;background:var(--rh-color-surface-lighter,#f2f2f2);outline:0;color:var(--rh-pagination-stepper-color,var(--rh-color-icon-subtle,#707070));box-sizing:border-box}.stepper:focus{border:2px solid var(--rh-color-border-interactive-on-light,#06c)}.stepper svg{height:14px}.rtl :not(#next,#last) svg,:is(#next,#last) svg{rotate:180deg}.rtl :is(#next,#last) svg{rotate:0deg}.stepper[inert]{pointer-events:none;color:var(--rh-pagination-background-focused,var(--rh-color-gray-30,#c7c7c7))}.mobile .stepper:hover{background:var(--rh-color-surface-light,#e0e0e0)}#numeric{margin-block-start:var(--rh-space-2xl,32px);width:100%;display:flex;align-items:center;flex:1 1 100%;gap:.5em}input{height:var(--rh-length-2xl,32px);width:var(--rh-length-4xl,64px);font-size:var(--rh-font-size-body-text-md, 1rem);background:var(--rh-color-surface-lightest,#fff);border:1px solid var(--rh-color-border-subtle-on-light,#c7c7c7);border-block-end:1px solid var(--rh-color-gray-40,#a3a3a3);box-sizing:border-box;padding:2px}input:focus{outline:0;border:2px solid var(--rh-pagination-accent-color,var(--rh-color-interactive-blue-darker,#06c));padding:1px}input:invalid{border-block-end:1px solid var(--rh-color-red-60,#a60000)}:host([on=dark]) input:invalid{border-block-end:1px solid var(--rh-color-red-40,#f56e6e)}#numeric a{text-decoration:none;color:var(--rh-color-interactive-blue-darker,#06c)}#numeric a:hover{color:var(--rh-color-interactive-blue-darkest,#036)}#numeric a:visited{color:var(--rh-color-interactive-purple-darker,#5e40be)}#numeric a:visited:hover{color:var(--rh-color-interactive-purple-darkest,#21134d)}@media (min-width:700px){#numeric{margin-block-start:0;margin-inline-start:var(--rh-space-xl,24px);flex:1 0 0%}#container{flex-wrap:nowrap}}`; const L1 = html ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 14"> <path d="M.3 6.26 6.24.3C6.63-.1 7.3-.1 7.7.3l.99.99c.4.4.4 1.07 0 1.48L4.49 7l4.2 4.22c.41.4.41 1.07 0 1.48l-.98 1c-.41.4-1.07.4-1.48 0L.31 7.73a1.05 1.05 0 0 1 0-1.48Z"/> </svg>`; const L2 = html ` <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17.44 14"> <path d="M8.7 6.26 14.66.3a1.05 1.05 0 0 1 1.49 0l.98.99c.42.4.42 1.07 0 1.48L12.92 7l4.2 4.22c.42.4.42 1.07 0 1.48l-.98 1c-.41.4-1.08.4-1.48 0L8.7 7.73a1.05 1.05 0 0 1 0-1.48zM.3 7.74l5.96 5.95c.4.41 1.07.41 1.48 0l.99-.99c.4-.4.4-1.07 0-1.48L4.52 7l4.21-4.22c.41-.4.41-1.07 0-1.48l-.99-1a1.05 1.05 0 0 0-1.48 0L.31 6.27a1.05 1.05 0 0 0 0 1.48z"/> </svg>`; /** * A paginator allows users to navigate between pages of related content. * * @summary Allows users to navigate content divided into pages * * @slot - An ordered list of links * @slot go-to-page - "Go to page" text * @slot out-of - "of" text * * @cssprop {<color>} --rh-pagination-accent-color * Sets the outline color when the page input has focus. * {@default `var(--rh-color-interactive-blue, #0066cc)`} * @cssprop {<color>} --rh-pagination-background-focused * Sets the disabled stepper color. * {@default `var(--rh-color-gray-20, #c7c7c7)`} * @cssprop {<color>} --rh-pagination-stepper-color * Sets the stepper color. * {@default `var(--rh-color-icon-subtle, #707070)`} */ let RhPagination = class RhPagination extends LitElement { constructor() { super(...arguments); _RhPagination_instances.add(this); /** * Override `overflow` values set from HTML or JS. * `overflow` should ideally be private, but because * we can't do `::slotted(nav ol li)`, we need to reflect * it to a host attribute, so that lightdom CSS can target * the list items. */ this.overflow = null; /** Accessible label for the 'nav' element */ this.label = 'Page navigation'; /** Accessible label for the 'first page' button */ this.labelFirst = 'first page'; /** Accessible label for the 'previous page' button */ this.labelPrevious = 'previous page'; /** Accessible label for the 'next page' button */ this.labelNext = 'next page'; /** Accessible label for the 'last page' button */ this.labelLast = 'last page'; _RhPagination_dir.set(this, new DirController(this)); _RhPagination_mo.set(this, new MutationObserver(() => __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_update).call(this))); _RhPagination_screen.set(this, new ScreenSizeController(this)); _RhPagination_logger.set(this, new Logger(this)); _RhPagination_ol.set(this, this.querySelector('ol')); _RhPagination_links.set(this, __classPrivateFieldGet(this, _RhPagination_ol, "f")?.querySelectorAll('li a')); _RhPagination_firstLink.set(this, null); _RhPagination_lastLink.set(this, null); _RhPagination_nextLink.set(this, null); _RhPagination_prevLink.set(this, null); _RhPagination_currentLink.set(this, __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_getCurrentLink).call(this)); _RhPagination_currentIndex.set(this, 0); } connectedCallback() { super.connectedCallback(); __classPrivateFieldGet(this, _RhPagination_mo, "f").observe(this, { childList: true, subtree: true }); } disconnectedCallback() { super.disconnectedCallback(); __classPrivateFieldGet(this, _RhPagination_mo, "f").disconnect(); } update(changed) { __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_update).call(this); super.update(changed); } render() { const { mobile, size } = __classPrivateFieldGet(this, _RhPagination_screen, "f"); const { dir } = __classPrivateFieldGet(this, _RhPagination_dir, "f"); const { label, labelFirst, labelPrevious, labelNext, labelLast } = this; const firstHref = __classPrivateFieldGet(this, _RhPagination_currentLink, "f") === __classPrivateFieldGet(this, _RhPagination_firstLink, "f") ? undefined : __classPrivateFieldGet(this, _RhPagination_firstLink, "f")?.href; const prevHref = __classPrivateFieldGet(this, _RhPagination_prevLink, "f")?.href; const nextHref = __classPrivateFieldGet(this, _RhPagination_nextLink, "f")?.href; const lastHref = __classPrivateFieldGet(this, _RhPagination_currentLink, "f") === __classPrivateFieldGet(this, _RhPagination_lastLink, "f") ? undefined : __classPrivateFieldGet(this, _RhPagination_lastLink, "f")?.href; const currentPage = __classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get).toString(); return html ` <div id="container" class=${classMap({ mobile, [size]: true, [dir]: true })}> <a id="first" class="stepper" href=${ifDefined(firstHref)} ?inert=${!firstHref} aria-label=${labelFirst}>${L2}</a> <a id="prev" class="stepper" href=${ifDefined(prevHref)} ?inert=${!prevHref} aria-label=${labelPrevious}>${L1}</a> <nav ?hidden=${mobile} ?inert=${mobile} aria-label=${label}> <slot></slot> </nav> <a id="next" class="stepper" href=${ifDefined(nextHref)} ?inert=${!nextHref} aria-label=${labelNext}>${L1}</a> <a id="last" class="stepper" href=${ifDefined(lastHref)} ?inert=${!lastHref} aria-label=${labelLast}>${L2}</a> <div id="numeric" part="numeric"> <span id="go-to-page"> <slot name="go-to-page">Go to page</slot> </span> <input inputmode="numeric" required min=1 max=${__classPrivateFieldGet(this, _RhPagination_links, "f")?.length ?? 1} aria-labelledby="go-to-page" @change=${__classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_onChange)} @keyup=${__classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_onKeyup)} .value=${currentPage}> <slot name="out-of">of</slot> <a href=${ifDefined(lastHref)}>${__classPrivateFieldGet(this, _RhPagination_links, "f")?.length}</a> </div> </div> `; } /** Navigate to the first page */ first() { return __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, 'first'); } /** Navigate to the previous page */ prev() { return __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, 'prev'); } /** Navigate to the next page */ next() { return __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, 'next'); } /** Navigate to the last page */ last() { return __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, 'last'); } /** Navigate to a specific page */ go(page) { return __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, page); } }; _RhPagination_dir = new WeakMap(); _RhPagination_mo = new WeakMap(); _RhPagination_screen = new WeakMap(); _RhPagination_logger = new WeakMap(); _RhPagination_ol = new WeakMap(); _RhPagination_links = new WeakMap(); _RhPagination_firstLink = new WeakMap(); _RhPagination_lastLink = new WeakMap(); _RhPagination_nextLink = new WeakMap(); _RhPagination_prevLink = new WeakMap(); _RhPagination_currentLink = new WeakMap(); _RhPagination_currentIndex = new WeakMap(); _RhPagination_instances = new WeakSet(); _RhPagination_currentPage_get = function _RhPagination_currentPage_get() { return __classPrivateFieldGet(this, _RhPagination_currentIndex, "f") + 1; }; _RhPagination_update = function _RhPagination_update() { this.querySelector('[aria-current="page"]')?.removeAttribute('aria-current'); __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_updateLightDOMRefs).call(this); this.overflow = __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_getOverflow).call(this); __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_checkValidity).call(this); }; _RhPagination_getOverflow = function _RhPagination_getOverflow() { const overflowAt = 9; const length = __classPrivateFieldGet(this, _RhPagination_links, "f")?.length ?? 0; if (length <= overflowAt) { return null; } const current = __classPrivateFieldGet(this, _RhPagination_currentIndex, "f") + 1; if (current > (overflowAt - 4) && current < (length - 4)) { return 'both'; } else if (current <= (overflowAt - 4)) { return 'end'; } else { return 'start'; } }; _RhPagination_getCurrentLink = function _RhPagination_getCurrentLink() { const ariaCurrent = this.querySelector('li a[aria-current="page"]'); if (ariaCurrent) { return ariaCurrent; } for (const link of __classPrivateFieldGet(this, _RhPagination_links, "f") ?? []) { const url = new URL(link.href); if (url.pathname === location.pathname && url.search === location.search && url.hash === location.hash) { return link; } } __classPrivateFieldGet(this, _RhPagination_logger, "f").warn('could not determine current link'); return null; }; _RhPagination_updateLightDOMRefs = function _RhPagination_updateLightDOMRefs() { // NB: order of operations! must set up state __classPrivateFieldSet(this, _RhPagination_ol, this.querySelector('ol'), "f"); __classPrivateFieldSet(this, _RhPagination_links, this.querySelectorAll('li a'), "f"); __classPrivateFieldSet(this, _RhPagination_firstLink, this.querySelector('li:first-child a'), "f"); __classPrivateFieldSet(this, _RhPagination_lastLink, this.querySelector('li:last-child a'), "f"); __classPrivateFieldSet(this, _RhPagination_currentLink, __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_getCurrentLink).call(this), "f"); if (__classPrivateFieldGet(this, _RhPagination_currentLink, "f")) { const links = Array.from(__classPrivateFieldGet(this, _RhPagination_links, "f")); __classPrivateFieldSet(this, _RhPagination_currentIndex, links.indexOf(__classPrivateFieldGet(this, _RhPagination_currentLink, "f")), "f"); __classPrivateFieldSet(this, _RhPagination_prevLink, __classPrivateFieldGet(this, _RhPagination_links, "f")[__classPrivateFieldGet(this, _RhPagination_currentIndex, "f") - 1], "f"); __classPrivateFieldSet(this, _RhPagination_nextLink, __classPrivateFieldGet(this, _RhPagination_links, "f")[__classPrivateFieldGet(this, _RhPagination_currentIndex, "f") + 1], "f"); for (const link of this.querySelectorAll('[data-page]')) { link.removeAttribute('data-page'); } __classPrivateFieldGet(this, _RhPagination_currentLink, "f").closest('li')?.setAttribute('data-page', 'current'); __classPrivateFieldGet(this, _RhPagination_prevLink, "f")?.closest('li')?.setAttribute('data-page', 'previous'); __classPrivateFieldGet(this, _RhPagination_nextLink, "f")?.closest('li')?.setAttribute('data-page', 'next'); if (__classPrivateFieldGet(this, _RhPagination_currentLink, "f")?.getAttribute('aria-current') !== 'page') { __classPrivateFieldGet(this, _RhPagination_currentLink, "f")?.setAttribute('aria-current', 'page'); } } }; _RhPagination_checkValidity = function _RhPagination_checkValidity() { let message = ''; // Validate DOM if (!__classPrivateFieldGet(this, _RhPagination_ol, "f") || [...this.children].filter(x => !x.slot).length > 1) { message = 'must have a single <ol> element as it\'s only child'; } // Validate user input if (this.input && __classPrivateFieldGet(this, _RhPagination_links, "f")) { if (Number.isNaN(__classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get))) { message = `${__classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get)} is not a valid page number`; } else if (__classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get) > __classPrivateFieldGet(this, _RhPagination_links, "f").length || __classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get) < 1) { message = `cannot navigate to page ${__classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get)}`; } this.input.setCustomValidity(message); } if (message) { __classPrivateFieldGet(this, _RhPagination_logger, "f").warn(this.input?.validationMessage || 'could not navigate'); } this.input?.reportValidity(); return !message; }; _RhPagination_go = /** * 1. Normalize the element state * 2. validate and act on the input * 3. update the element in case a full browser navigation was prevented (e.g. SPA routing) */ async function _RhPagination_go(id) { await this.updateComplete; if (typeof id === 'number') { const link = __classPrivateFieldGet(this, _RhPagination_links, "f")?.[id - 1]; link?.click?.(); } else { this.shadowRoot?.getElementById(id)?.click(); } this.requestUpdate(); await this.updateComplete; return __classPrivateFieldGet(this, _RhPagination_currentIndex, "f"); }; _RhPagination_onKeyup = function _RhPagination_onKeyup(event) { if (!(event.target instanceof HTMLInputElement) || !__classPrivateFieldGet(this, _RhPagination_links, "f")) { return; } const max = __classPrivateFieldGet(this, _RhPagination_links, "f").length.toString(); const input = event.target; if (parseInt(input.value) > parseInt(max)) { input.value = max; } }; _RhPagination_onChange = function _RhPagination_onChange() { if (!this.input || !__classPrivateFieldGet(this, _RhPagination_links, "f")) { return; } const inputNum = parseInt(this.input.value); __classPrivateFieldSet(this, _RhPagination_currentIndex, inputNum - 1, "f"); if (__classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_checkValidity).call(this)) { __classPrivateFieldGet(this, _RhPagination_instances, "m", _RhPagination_go).call(this, __classPrivateFieldGet(this, _RhPagination_instances, "a", _RhPagination_currentPage_get)); } }; RhPagination.version = '{{version}}'; RhPagination.styles = [styles]; __decorate([ property({ reflect: true }) ], RhPagination.prototype, "overflow", void 0); __decorate([ property() ], RhPagination.prototype, "label", void 0); __decorate([ property({ attribute: 'label-first' }) ], RhPagination.prototype, "labelFirst", void 0); __decorate([ property({ attribute: 'label-previous' }) ], RhPagination.prototype, "labelPrevious", void 0); __decorate([ property({ attribute: 'label-next' }) ], RhPagination.prototype, "labelNext", void 0); __decorate([ property({ attribute: 'label-last' }) ], RhPagination.prototype, "labelLast", void 0); __decorate([ query('input') ], RhPagination.prototype, "input", void 0); RhPagination = __decorate([ customElement('rh-pagination') ], RhPagination); export { RhPagination }; //# sourceMappingURL=rh-pagination.js.map