UNPKG

@public-ui/components

Version:

Contains all web components that belong to KoliBri - The accessible HTML-Standard.

653 lines (652 loc) 28.2 kB
/*! * KoliBri - The accessible HTML-Standard */ import { h, Host } from "@stencil/core"; import { parseJson, STATE_CHANGE_EVENT, validateCustomClass, validateLabel, validateMax, validateTooltipAlign, watchJsonArrayString, watchNumber, watchValidator, } from "../../schema"; import { KolButtonWcTag, KolSelectWcTag } from "../../core/component-names"; import { translate } from "../../i18n"; import { nonce } from "../../utils/dev.utils"; import { dispatchDomEvent, KolEvent } from "../../utils/events"; import { addNavLabel, removeNavLabel } from "../../utils/unique-nav-labels"; const leftDoubleArrowIcon = { left: 'kolicon-chevron-double-left', }; const leftSingleArrow = { left: 'kolicon-chevron-left', }; const rightSingleArrowIcon = { right: 'kolicon-chevron-right', }; const rightDoubleArrowIcon = { right: 'kolicon-chevron-double-right', }; function getUserLanguage() { const userLanguage = navigator.language || 'de-DE'; const normalizedLanguage = userLanguage.includes('-') ? userLanguage : `${userLanguage}-${userLanguage.toUpperCase()}`; return normalizedLanguage; } const userLanguage = getUserLanguage(); const NUMBER_FORMATTER = new Intl.NumberFormat(userLanguage, { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0, }); export class KolPaginationWc { constructor() { this.translatePageFirst = translate('kol-page-first'); this.translatePageBack = translate('kol-page-back'); this.translatePageNext = translate('kol-page-next'); this.translatePageLast = translate('kol-page-last'); this.translateEntriesPerSite = translate('kol-entries-per-site'); this.translatePage = translate('kol-page'); this.translatePagination = translate('kol-pagination'); this.calcCount = (total, pageSize = 1) => Math.ceil(total / pageSize); this.getCount = () => this.calcCount(this.state._max, this.state._pageSize); this._boundaryCount = 1; this._hasButtons = true; this._pageSize = 1; this._pageSizeOptions = []; this._siblingCount = 1; this._tooltipAlign = 'top'; this.state = { _boundaryCount: 1, _label: this.translatePagination, _hasButtons: { first: true, last: true, next: true, previous: true, }, _on: { onClick: () => null, }, _page: 0, _pageSize: 1, _pageSizeOptions: [], _siblingCount: 1, _max: 0, }; this.onClick = (event, page) => { if (typeof this.state._on.onClick === 'function') { this.state._on.onClick(event, page); } if (this.host) { dispatchDomEvent(this.host, KolEvent.click, page); } this.onChangePage(event, page); }; this.onChangePage = (event, page) => { const timeout = setTimeout(() => { clearTimeout(timeout); if (typeof this.state._on.onChangePage === 'function') { this.state._on.onChangePage(event, page); } if (this.host) { dispatchDomEvent(this.host, KolEvent.changePage, page); } }); }; this.onChangePageSize = (event, value) => { value = parseInt(value); if (typeof value === 'number' && value > 0 && this._pageSize !== value) { this._pageSize = value; const timeout = setTimeout(() => { clearTimeout(timeout); if (typeof this.state._on.onChangePageSize === 'function') { this.state._on.onChangePageSize(event, this._pageSize); } if (this.host) { dispatchDomEvent(this.host, KolEvent.changePageSize, this._pageSize); } }); } }; this.onGoToFirst = { onClick: (event) => { this.onClick(event, 1); }, }; this.onGoToEnd = { onClick: (event) => { this.onClick(event, this.getCount()); }, }; this.onGoBackward = { onClick: (event) => { this.onClick(event, this.state._page - 1); }, }; this.onGoForward = { onClick: (event) => { this.onClick(event, this.state._page + 1); }, }; this.beforePageSize = (_nextValue, nextState) => { let pageSize = nextState.has('_pageSize') ? nextState.get('_pageSize') : this.state._pageSize; const pageSizeOptions = nextState.has('_pageSizeOptions') ? nextState.get('_pageSizeOptions') : this.state._pageSizeOptions; if (Array.isArray(pageSizeOptions) && pageSizeOptions.length > 0) { const find = pageSizeOptions.find((option) => option.value === pageSize); if (find === undefined) { pageSize = pageSizeOptions[0].value; } else { pageSize = find.value; } nextState.set('_pageSize', pageSize); } const page = nextState.has('_page') ? nextState.get('_page') : this.state._page; const total = nextState.has('_max') ? nextState.get('_max') : this.state._max; this.syncPage(nextState, page, nextState.get('_pageSize'), total); }; this.syncPage = (nextState, page, pageSize, total) => { if (total > 0) { const count = this.calcCount(total, pageSize); if (count > 0) { if (page > count) { nextState.set('_page', count); this.onChangePage(STATE_CHANGE_EVENT, count); } else if (page < 1) { nextState.set('_page', 1); this.onChangePage(STATE_CHANGE_EVENT, 1); } } } }; this.beforePageSizeOptions = (nextValue, nextState) => { const options = []; if (Array.isArray(nextValue)) { for (const value of nextValue) { if (typeof value === 'number') { options.push({ label: `${value}`, value: value, }); } } } nextState.set('_pageSizeOptions', options); this.beforePageSize(options, nextState); }; } getPageStart() { return Math.max(0, (this.state._page - 1) * this.state._pageSize + 1); } getPageEnd() { const highest = this.state._page * this.state._pageSize; if (this.state._max < highest) { return this.state._max; } return highest; } render() { var _a; let ellipsis = false; const count = this.getCount(); const pageButtons = Array.from({ length: count }, (_, i) => i + 1).map((page) => { if (page <= this.state._boundaryCount || page > count - this.state._boundaryCount || (page >= this.state._page - this.state._siblingCount && page <= this.state._page + this.state._siblingCount)) { ellipsis = true; if (this.state._page === page) { return this.getSelectedPageButton(page); } else { return this.getUnselectedPageButton(page); } } else if (ellipsis === true) { ellipsis = false; return (h("li", { key: nonce() }, h("span", { class: "kol-pagination__separator", "aria-hidden": "true" }))); } else { return null; } }); return (h(Host, { class: "kol-pagination" }, h("span", { role: "status", "aria-live": "polite", class: "kol-pagination__entries" }, translate('kol-table-visible-range', { placeholders: { start: NUMBER_FORMATTER.format(this.getPageStart()), end: NUMBER_FORMATTER.format(this.getPageEnd()), total: NUMBER_FORMATTER.format(this.state._max), }, })), h("nav", { class: "kol-pagination__navigation", "aria-label": this.state._label }, h("ul", { class: "kol-pagination__navigation-list" }, this.state._hasButtons.first && (h("li", null, h(KolButtonWcTag, { class: "kol-pagination__button kol-pagination__button--first", _customClass: this.state._customClass, _disabled: this.state._page <= 1, _icons: leftDoubleArrowIcon, _hideLabel: true, _label: this.translatePageFirst, _on: this.onGoToFirst, _tooltipAlign: this.state._tooltipAlign }))), this.state._hasButtons.previous && (h("li", null, h(KolButtonWcTag, { class: "kol-pagination__button kol-pagination__button--previous", _customClass: this.state._customClass, _disabled: this.state._page <= 1, _icons: leftSingleArrow, _hideLabel: true, _label: this.translatePageBack, _on: this.onGoBackward, _tooltipAlign: this.state._tooltipAlign }))), pageButtons, this.state._hasButtons.next && (h("li", null, h(KolButtonWcTag, { class: "kol-pagination__button kol-pagination__button--next", _customClass: this.state._customClass, _disabled: count <= this.state._page, _icons: rightSingleArrowIcon, _hideLabel: true, _label: this.translatePageNext, _on: this.onGoForward, _tooltipAlign: this.state._tooltipAlign }))), this.state._hasButtons.last && (h("li", null, h(KolButtonWcTag, { class: "kol-pagination__button kol-pagination__button--last", _customClass: this.state._customClass, _disabled: count <= this.state._page, _icons: rightDoubleArrowIcon, _hideLabel: true, _label: this.translatePageLast, _on: this.onGoToEnd, _tooltipAlign: this.state._tooltipAlign }))))), ((_a = this.state._pageSizeOptions) === null || _a === void 0 ? void 0 : _a.length) > 0 && (h("div", { class: "page-size" }, h(KolSelectWcTag, { class: "kol-pagination__page-size-select", _label: this.translateEntriesPerSite, _options: this.state._pageSizeOptions, _on: { onChange: this.onChangePageSize, }, _value: this.state._pageSize }))))); } getUnselectedPageButton(page) { const pageText = NUMBER_FORMATTER.format(page); const ariaDescription = `${this.translatePage} ${pageText}`; return (h("li", { key: nonce() }, h(KolButtonWcTag, { class: "kol-pagination__button kol-pagination__button--numbers", _ariaDescription: ariaDescription, _customClass: this.state._customClass, _label: pageText, _on: { onClick: (event) => { this.onClick(event, page); }, } }))); } getSelectedPageButton(page) { const pageText = NUMBER_FORMATTER.format(page); const ariaDescription = `${this.translatePage} ${pageText}`; return (h("li", { key: nonce() }, h(KolButtonWcTag, { "aria-current": "page", class: "kol-pagination__button kol-pagination__button--selected selected", _ariaDescription: ariaDescription, _customClass: this.state._customClass, _label: pageText }))); } validateBoundaryCount(value) { watchNumber(this, '_boundaryCount', Math.max(0, value !== null && value !== void 0 ? value : 1)); } validateCustomClass(value) { validateCustomClass(this, value); } validateLabel(label, _oldValue, initial = false) { if (!initial) { removeNavLabel(this.state._label); } validateLabel(this, label); addNavLabel(this.state._label); } validateHasButtons(value) { watchValidator(this, '_hasButtons', (value) => typeof value === 'boolean' || typeof value === 'string' || (typeof value === 'object' && value !== null), new Set(['Boolean', 'PaginationHasButton']), value, { hooks: { beforePatch: (nextValue, nextState) => { if (typeof nextValue === 'boolean') { nextState.set('_hasButtons', { first: nextValue, last: nextValue, next: nextValue, previous: nextValue, }); } else { if (typeof nextValue === 'string') { try { nextValue = parseJson(nextValue); } catch (_a) { nextState.delete('_hasButtons'); } } if (typeof nextValue === 'object' && nextValue !== null) { nextState.set('_hasButtons', Object.assign(Object.assign({}, this.state._hasButtons), { first: typeof nextValue.first === 'boolean' ? nextValue.first === true : this.state._hasButtons.first, last: typeof nextValue.last === 'boolean' ? nextValue.last === true : this.state._hasButtons.last, next: typeof nextValue.next === 'boolean' ? nextValue.next === true : this.state._hasButtons.next, previous: typeof nextValue.previous === 'boolean' ? nextValue.previous === true : this.state._hasButtons.previous })); } } }, }, }); } validateOn(value) { if (typeof value === 'object' && value !== null) { this.state = Object.assign(Object.assign({}, this.state), { _on: value }); } } validatePage(value) { watchNumber(this, '_page', value, { hooks: { beforePatch: (_nextValue, nextState) => { const pageSize = nextState.has('_pageSize') ? nextState.get('_pageSize') : this.state._pageSize; const total = nextState.has('_max') ? nextState.get('_max') : this.state._max; this.syncPage(nextState, _nextValue, pageSize, total); }, }, }); } validatePageSize(value) { watchNumber(this, '_pageSize', value, { hooks: { beforePatch: this.beforePageSize, }, }); } validatePageSizeOptions(value) { watchJsonArrayString(this, '_pageSizeOptions', (value) => typeof value === 'number', value, undefined, { hooks: { beforePatch: this.beforePageSizeOptions, }, }); } validateSiblingCount(value) { watchNumber(this, '_siblingCount', Math.max(0, value !== null && value !== void 0 ? value : 1)); } validateMax(value) { validateMax(this, value, { hooks: { beforePatch: (_nextValue, nextState) => { const page = nextState.has('_page') ? nextState.get('_page') : this.state._page; const pageSize = nextState.has('_pageSize') ? nextState.get('_pageSize') : this.state._pageSize; this.syncPage(nextState, page, pageSize, _nextValue); }, }, }); } validateTooltipAlign(value) { validateTooltipAlign(this, value); } componentWillLoad() { this.validateBoundaryCount(this._boundaryCount); this.validateCustomClass(this._customClass); this.validateHasButtons(this._hasButtons); this.validateLabel(this._label, undefined, true); this.validateOn(this._on); this.validatePage(this._page); this.validatePageSize(this._pageSize); this.validatePageSizeOptions(this._pageSizeOptions); this.validateSiblingCount(this._siblingCount); this.validateTooltipAlign(this._tooltipAlign); this.validateMax(this._max); this.validatePage(this._page); } disconnectedCallback() { removeNavLabel(this.state._label); } static get is() { return "kol-pagination-wc"; } static get properties() { return { "_boundaryCount": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines the amount of pages to show next to the outer arrow buttons." }, "getter": false, "setter": false, "reflect": false, "attribute": "_boundary-count", "defaultValue": "1" }, "_customClass": { "type": "string", "mutable": false, "complexType": { "original": "CustomClassPropType", "resolved": "string | undefined", "references": { "CustomClassPropType": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::CustomClassPropType" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines the custom class attribute if _variant=\"custom\" is set." }, "getter": false, "setter": false, "reflect": false, "attribute": "_custom-class" }, "_label": { "type": "string", "mutable": false, "complexType": { "original": "LabelPropType", "resolved": "string | undefined", "references": { "LabelPropType": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::LabelPropType" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.)." }, "getter": false, "setter": false, "reflect": false, "attribute": "_label" }, "_hasButtons": { "type": "any", "mutable": false, "complexType": { "original": "boolean | Stringified<PaginationHasButton>", "resolved": "boolean | string | undefined | { first: boolean; last: boolean; next: boolean; previous: boolean; }", "references": { "Stringified": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::Stringified" }, "PaginationHasButton": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::PaginationHasButton" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines which navigation buttons to render (first, last, next, previous buttons)." }, "getter": false, "setter": false, "reflect": false, "attribute": "_has-buttons", "defaultValue": "true" }, "_page": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": true, "optional": false, "docs": { "tags": [], "text": "Defines the current page." }, "getter": false, "setter": false, "reflect": false, "attribute": "_page" }, "_pageSize": { "type": "number", "mutable": true, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Defines the amount of entries to show per page." }, "getter": false, "setter": false, "reflect": false, "attribute": "_page-size", "defaultValue": "1" }, "_pageSizeOptions": { "type": "string", "mutable": false, "complexType": { "original": "Stringified<number[]>", "resolved": "number[] | string", "references": { "Stringified": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::Stringified" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Defines the options for the page-size-select." }, "getter": false, "setter": false, "reflect": false, "attribute": "_page-size-options", "defaultValue": "[]" }, "_on": { "type": "unknown", "mutable": false, "complexType": { "original": "KoliBriPaginationButtonCallbacks", "resolved": "{ onChangePage?: EventValueOrEventCallback<Event, number> | undefined; onChangePageSize?: EventValueOrEventCallback<Event, number> | undefined; onClick?: EventValueOrEventCallback<Event, number> | undefined; }", "references": { "KoliBriPaginationButtonCallbacks": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::KoliBriPaginationButtonCallbacks" } } }, "required": true, "optional": false, "docs": { "tags": [], "text": "Gibt an, auf welche Callback-Events reagiert werden." }, "getter": false, "setter": false }, "_siblingCount": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines the amount of pages to show next to the current page." }, "getter": false, "setter": false, "reflect": false, "attribute": "_sibling-count", "defaultValue": "1" }, "_tooltipAlign": { "type": "string", "mutable": false, "complexType": { "original": "TooltipAlignPropType", "resolved": "\"bottom\" | \"left\" | \"right\" | \"top\" | undefined", "references": { "TooltipAlignPropType": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::TooltipAlignPropType" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "Defines where to show the Tooltip preferably: top, right, bottom or left." }, "getter": false, "setter": false, "reflect": false, "attribute": "_tooltip-align", "defaultValue": "'top'" }, "_max": { "type": "number", "mutable": false, "complexType": { "original": "MaxPropType", "resolved": "number", "references": { "MaxPropType": { "location": "import", "path": "../../schema", "id": "src/schema/index.ts::MaxPropType" } } }, "required": true, "optional": false, "docs": { "tags": [], "text": "Defines the maximum value of the element." }, "getter": false, "setter": false, "reflect": false, "attribute": "_max" } }; } static get states() { return { "state": {} }; } static get elementRef() { return "host"; } static get watchers() { return [{ "propName": "_boundaryCount", "methodName": "validateBoundaryCount" }, { "propName": "_customClass", "methodName": "validateCustomClass" }, { "propName": "_label", "methodName": "validateLabel" }, { "propName": "_hasButtons", "methodName": "validateHasButtons" }, { "propName": "_on", "methodName": "validateOn" }, { "propName": "_page", "methodName": "validatePage" }, { "propName": "_pageSize", "methodName": "validatePageSize" }, { "propName": "_pageSizeOptions", "methodName": "validatePageSizeOptions" }, { "propName": "_siblingCount", "methodName": "validateSiblingCount" }, { "propName": "_max", "methodName": "validateMax" }, { "propName": "_tooltipAlign", "methodName": "validateTooltipAlign" }]; } } //# sourceMappingURL=component.js.map