@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
JavaScript
/*!
*
* 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