@public-ui/components
Version:
Contains all web components that belong to KoliBri - The accessible HTML-Standard.
653 lines (652 loc) • 28.2 kB
JavaScript
/*!
* 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