UNPKG

@kit-data-manager/pid-component

Version:

The PID-Component is a web component that can be used to evaluate and display FAIR Digital Objects, PIDs, ORCiDs, and possibly other identifiers in a user-friendly way. It is easily extensible to support other identifier types.

334 lines (333 loc) 15.3 kB
/*! * * Copyright 2024-2026 Karlsruhe Institute of Technology. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { h } from "@stencil/core"; export class PidDataTable { constructor() { this.items = []; this.itemsPerPage = 10; this.currentPage = 0; this.pageSizes = [5, 10, 25, 50, 100]; this.loadSubcomponents = false; this.hideSubcomponents = false; this.currentLevelOfSubcomponents = 0; this.levelOfSubcomponents = 1; this.settings = '[]'; this.darkMode = 'system'; this.filteredItems = []; this.tableId = `pid-data-table-${Math.random().toString(36).substring(2, 9)}`; } updateFilteredItems() { this.filteredItems = this.items.filter((_, index) => { return index >= this.currentPage * this.itemsPerPage && index < this.currentPage * this.itemsPerPage + this.itemsPerPage; }); const maxPage = Math.ceil(this.items.length / this.itemsPerPage) - 1; if (this.currentPage > maxPage && maxPage >= 0) { this.currentPage = maxPage; } this.recalculateContentDimensions(); } componentWillLoad() { this.updateFilteredItems(); } componentDidLoad() { setTimeout(() => { this.recalculateContentDimensions(); }, 0); } render() { const isDarkMode = this.darkMode === 'dark' || (this.darkMode === 'system' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches); if (this.items.length === 0) { return (h("div", { class: isDarkMode ? 'm-1 rounded-lg border border-gray-700 bg-gray-800 p-4 text-center text-gray-300' : 'm-1 rounded-lg border border-gray-200 bg-gray-50 p-4 text-center text-gray-500', role: "status", "aria-live": "polite", "aria-label": "No data available" }, h("p", { class: "m-0" }, "No data available"))); } return (h("table", { id: this.tableId, class: `w-full h-full table-auto border-collapse text-left font-sans text-sm select-text rounded-md overflow-y-auto ${isDarkMode ? 'text-gray-200 bg-gray-800' : 'bg-gray-50'}`, "aria-label": "Data table with properties and values", role: "table" }, h("thead", { class: "sticky top-0 z-20 p-1 rounded-md bg-slate-600 text-slate-200" }, h("tr", { class: "font-semibold flex-col", role: "row" }, h("th", { class: "w-1/5 flex-2 resize-x rounded-l-md p-1", scope: "col", role: "columnheader" }, "Key"), h("th", { class: "min-w-36 w-4/5 flex-6 resize-x rounded-r-md p-1", scope: "col", role: "columnheader" }, "Value"))), h("tbody", { class: isDarkMode ? 'bg-gray-800 overflow-y-auto relative' : 'bg-gray-50 overflow-y-auto relative', role: "rowgroup" }, this.filteredItems.map((value, index) => (h("tr", { key: `item-${value.keyTitle}-${index}`, class: isDarkMode ? `odd:bg-gray-700 even:bg-gray-800 border-b border-gray-700 flex-col` : `odd:bg-slate-200 even:bg-gray-50 border-b border-gray-200 flex-col`, "aria-label": `Row for ${value.keyTitle} with value ${value.value}`, role: "row" }, h("td", { class: 'w-auto p-1 align-top font-mono flex-2 resize-x', role: "cell" }, h("pid-tooltip", { text: value.keyTooltip || `Details for ${value.keyTitle}`, position: "top", maxHeight: "200px", "aria-label": `Information about ${value.keyTitle}` }, h("div", { slot: "trigger", class: "flex min-h-7 w-full items-center overflow-hidden" }, h("a", { href: value.keyLink, target: '_blank', rel: 'noopener noreferrer', class: "mr-2 truncate rounded-sm text-blue-600 underline hover:text-blue-800 focus:text-blue-900 focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 focus:outline-hidden", onClick: e => e.stopPropagation(), "aria-label": `Open ${value.keyTitle} in new tab` }, value.keyTitle)))), h("td", { class: 'relative w-full p-1 align-top text-sm select-text flex-6 resize-x', role: "cell" }, h("div", { class: "grid w-full grid-cols-[minmax(0,1fr)_auto] items-start gap-2" }, h("div", { class: "min-w-0 overflow-x-auto whitespace-normal" }, this.loadSubcomponents && !this.hideSubcomponents && value.renderDynamically ? (h("pid-component", { value: value.value, levelOfSubcomponents: this.levelOfSubcomponents, currentLevelOfSubcomponents: this.currentLevelOfSubcomponents + 1, itemsPerPage: this.itemsPerPage, settings: this.settings, openByDefault: false, darkMode: this.darkMode, class: "block w-full min-w-0" })) : !this.hideSubcomponents && this.currentLevelOfSubcomponents === this.levelOfSubcomponents && value.renderDynamically ? (h("pid-component", { value: value.value, levelOfSubcomponents: this.currentLevelOfSubcomponents, currentLevelOfSubcomponents: this.currentLevelOfSubcomponents + 1, itemsPerPage: this.itemsPerPage, settings: this.settings, hideSubcomponents: true, openByDefault: false, darkMode: this.darkMode, class: "block w-full min-w-0" })) : (h("span", { class: 'inline-block w-full max-w-full overflow-x-auto font-mono text-sm break-words whitespace-normal' }, value.value))), h("div", { class: "shrink-0 px-2" }, h("copy-button", { value: value.value, "dark-mode": this.darkMode, class: `visible z-50 cursor-pointer rounded-xs ${isDarkMode ? 'bg-gray-700/90 hover:bg-gray-600' : 'bg-white/90 hover:bg-white'} opacity-100 shadow-xs transition-all duration-200 hover:shadow-md`, "aria-label": `Copy ${value.keyTitle} value to clipboard`, title: `Copy ${value.keyTitle} value to clipboard` })))))))))); } recalculateContentDimensions() { requestAnimationFrame(() => { requestAnimationFrame(() => { const collapsible = this.el.closest('pid-collapsible'); if (collapsible && typeof collapsible.recalculateContentDimensions === 'function') { collapsible.recalculateContentDimensions(); } }); }); } static get is() { return "pid-data-table"; } static get properties() { return { "items": { "type": "unknown", "mutable": false, "complexType": { "original": "FoldableItem[]", "resolved": "FoldableItem[]", "references": { "FoldableItem": { "location": "import", "path": "../../utils/FoldableItem", "id": "src/utils/FoldableItem.ts::FoldableItem", "referenceLocation": "FoldableItem" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Array of items to display in the table" }, "getter": false, "setter": false, "defaultValue": "[]" }, "itemsPerPage": { "type": "number", "mutable": true, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Number of items to show per page" }, "getter": false, "setter": false, "reflect": false, "attribute": "items-per-page", "defaultValue": "10" }, "currentPage": { "type": "number", "mutable": true, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Current page (0-based index)" }, "getter": false, "setter": false, "reflect": false, "attribute": "current-page", "defaultValue": "0" }, "pageSizes": { "type": "unknown", "mutable": false, "complexType": { "original": "number[]", "resolved": "number[]", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Available page sizes" }, "getter": false, "setter": false, "defaultValue": "[5, 10, 25, 50, 100]" }, "loadSubcomponents": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Whether to load subcomponents" }, "getter": false, "setter": false, "reflect": false, "attribute": "load-subcomponents", "defaultValue": "false" }, "hideSubcomponents": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Whether to hide subcomponents" }, "getter": false, "setter": false, "reflect": false, "attribute": "hide-subcomponents", "defaultValue": "false" }, "currentLevelOfSubcomponents": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Current level of subcomponents" }, "getter": false, "setter": false, "reflect": false, "attribute": "current-level-of-subcomponents", "defaultValue": "0" }, "levelOfSubcomponents": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Total level of subcomponents" }, "getter": false, "setter": false, "reflect": false, "attribute": "level-of-subcomponents", "defaultValue": "1" }, "settings": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Settings to pass to subcomponents" }, "getter": false, "setter": false, "reflect": false, "attribute": "settings", "defaultValue": "'[]'" }, "darkMode": { "type": "string", "mutable": false, "complexType": { "original": "'light' | 'dark' | 'system'", "resolved": "\"dark\" | \"light\" | \"system\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The dark mode setting for the component\nOptions: \"light\", \"dark\", \"system\"\nDefault: \"system\"" }, "getter": false, "setter": false, "reflect": false, "attribute": "dark-mode", "defaultValue": "'system'" } }; } static get states() { return { "filteredItems": {} }; } static get events() { return [{ "method": "pageChange", "name": "pageChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Event emitted when page changes" }, "complexType": { "original": "number", "resolved": "number", "references": {} } }, { "method": "itemsPerPageChange", "name": "itemsPerPageChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Event emitted when items per page changes" }, "complexType": { "original": "number", "resolved": "number", "references": {} } }]; } static get elementRef() { return "el"; } static get watchers() { return [{ "propName": "items", "methodName": "updateFilteredItems" }, { "propName": "currentPage", "methodName": "updateFilteredItems" }, { "propName": "itemsPerPage", "methodName": "updateFilteredItems" }]; } } //# sourceMappingURL=pid-data-table.js.map