From b1f271e63dfcc24b416dd12e06c270a7fa8b7cc9 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 10 May 2023 16:53:21 -0400 Subject: [PATCH] Made changes in package.json to include sourcesContent for dist/data-grid.css.map. --- dist/data-grid.css | 2 +- dist/data-grid.css.map | 2 +- dist/data-grid.js.map | 2 +- dist/data-grid.min.js.map | 2 +- package-lock.json | 512 +++++++++++++++++++------------------- package.json | 4 +- 6 files changed, 265 insertions(+), 259 deletions(-) diff --git a/dist/data-grid.css b/dist/data-grid.css index b724cc7..6d97541 100644 --- a/dist/data-grid.css +++ b/dist/data-grid.css @@ -646,4 +646,4 @@ data-grid .dg-responsive-table th { } } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3Njc3MvX2NvcmUuc2NzcyIsImRhdGEtZ3JpZC5jc3MiLCIuLi9zY3NzL19ydGwuc2NzcyIsIi4uL3Njc3MvX21lbnUuc2NzcyIsIi4uL3Njc3MvX2FjdGlvbnMuc2NzcyIsIi4uL3Njc3MvX3Jlc2l6ZXIuc2NzcyIsIi4uL3Njc3MvX3Jlc3BvbnNpdmUuc2NzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0VBQUE7QUFLQTtFQUNFO0lBQ0UsVUFBQTtFQ0FGO0VERUE7SUFDRSxZQUFBO0VDQUY7QUFDRjtBREdBO0VBQ0UsaUJBQUE7RUFDQSxvQkFBQTtFQUNBLG1CQUFBO0VBQ0EsMkJBQUE7RUFDQSx3Q0FBQTtFQUNBLGdEQUFBO0VBQ0EsOEJBQUE7RUFFQSwwQkFBQTtFQUNBLGdEQUFBO0VBQ0EsdUNBQUE7RUFDQSxzREFBQTtFQUNBLHFEQUFBO0VBQ0Esb0RBQUE7RUFDQSx5QkFBQTtFQUNBLG1EQUFBO0VBQ0EscUNBQUE7RUFDQSwyQ0FBQTtFQUNBLGVBQUE7RUFDQSx3QkFBQTtFQUNBLDJCQUFBO0VBQ0EsdUJBQUE7RUFFQSw4QkFBQTtFQUNBLDhCQUFBO0VBQ0EsK0JBQUE7RUFDQSx5Q0FBQTtFQUNBLHVDQUFBO0VBQ0EsdUNBQUE7RUFDQSx1Q0FBQTtFQUNBLHVDQUFBO0VBQ0EsdUNBQUE7RUFDQSx1Q0FBQTtFQUNBLHVDQUFBO0VBQ0EsdUNBQUE7RUFDQSx1Q0FBQTtFQUVBLGNBQUE7RUFDQSxnQkFBQTtFQUNBLGtCQUFBO0FDSkY7QURPRTtFQUNFLHVCQUFBO0VBQ0EsK0JBQUE7RUFDQSw0QkFBQTtFQUNBLDZFQUFBO0VBQ0EsK0JBQUE7RUFDQSx3SEFBQTtFQUNBLGtDQUFBO0VBQ0EsaUVBQUE7RUFDQSxxQkFBQTtBQ0xKO0FETUk7RUFDRSxVQUFBO0VBQ0EsV0FBQTtBQ0pOO0FETUk7RUFDRSx1QkFBQTtBQ0pOO0FETUk7RUFDRSxpQ0FBQTtBQ0pOO0FETUk7RUFDRSx1Q0FBQTtBQ0pOO0FEUUU7RUFDRSxZQUFBO0VBQ0Es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QSxRQUFBO0VBQ0EsVUFBQTtFQUNBLDZCQUFBO0VBQ0EsWUFBQTtBSmdmTjtBSTllSTtFQUNFLFlBQUE7QUpnZk47QUk5ZUk7RUFDRSxxQ0FBQTtBSmdmTjtBSTllTTtFQUNFLFlBQUE7QUpnZlI7O0FLM2dCRTtFQUNFLFVBQUE7RUFDQSxrQkFBQTtBTDhnQko7QUs1Z0JFO0VBQ0UsVUFBQTtBTDhnQko7QUs1Z0JFO0VBQ0Usa0JBQUE7RUFDQSxTQUFBO0FMOGdCSjtBSzVnQkk7O0VBRUUsbUJBQUE7QUw4Z0JOO0FLM2dCSTtFQUNFLGNBQUE7QUw2Z0JOOztBS3ZnQkE7RUFHSTtJQUNFLGFBQUE7RUx3Z0JKO0VLcGdCRTtJQUNFLGFBQUE7RUxzZ0JKO0VLcGdCRTtJQUNFLGFBQUE7RUxzZ0JKO0VLbGdCRTs7Ozs7O0lBTUUsY0FBQTtFTG9nQko7RUtoZ0JFO0lBQ0UsYUFBQTtJQVNBLGlEQUFBO0VMMGZKO0VLamdCSTtJQUNFLFlBQUE7RUxtZ0JOO0VLamdCSTtJQUNFLFdBQUE7RUxtZ0JOO0VLM2ZJO0lBQ0UsVUFBQTtJQUNBLDBDQUFBO0VMNmZOO0VLM2ZJO0lBQ0UsWUFBQTtJQUNBLGdEQUFBO0lBQ0Esa0JBQUE7SUFDQSx1RUFBQTtFTDZmTjtFSzNmTTtJQUNFLFNBQUE7RUw2ZlI7RUszZk07SUFDRSxrQkFBQTtJQUNBLE1BQUE7SUFDQSxPQUFBO0lBQ0EsdUJBQUE7SUFDQSxnRUFBQTtJQUNBLG1CQUFBO0lBQ0Esd0JBQUE7SUFDQSxjQUFBO0lBQ0EsaUJBQUE7SUFDQSwwQ0FBQTtFTDZmUjtFS3ZmRTtJQUNFLFlBQUE7SUFDQSxtQkFBQTtFTHlmSjtFS3JmSTtJQUVFLFVBQUE7RUxzZk47RUtwZkk7SUFDRSxZQUFBO0VMc2ZOO0VLcGZJO0lBQ0UsZ0JBQUE7SUFDQSxXQUFBO0VMc2ZOO0VLcGZJO0lBQ0UsWUFBQTtFTHNmTjtFS3BmSTtJQUNFLHFCQUFBO0lBQ0EsY0FBQTtFTHNmTjtFS25mRTtJQUNFLHlCQUFBO0VMcWZKO0VLbGZJO0lBQ0UsVUFBQTtJQUNBLGdFQUFBO0VMb2ZOO0VLbGZNO0lBQ0UsbUNBQUE7RUxvZlI7RUtqZkk7SUFDRSx1QkFBQTtJQUNBLG1CQUFBO0lBQ0EsVUFBQTtJQUNBLHlFQUFBO0VMbWZOO0VLaGZFO0lBQ0UsY0FBQTtFTGtmSjtFS2hmRTtJQUNFLHVCQUFBO0VMa2ZKO0VLaGZFO0lBQ0UseUJBQUE7RUxrZko7QUFDRiIsImZpbGUiOiJkYXRhLWdyaWQuY3NzIn0= */ \ No newline at end of file +/*# sourceMappingURL=data-grid.css.map */ \ No newline at end of file diff --git a/dist/data-grid.css.map b/dist/data-grid.css.map index ab810e1..350fadc 100644 --- a/dist/data-grid.css.map +++ b/dist/data-grid.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../scss/_core.scss","../scss/_rtl.scss","../scss/_menu.scss","../scss/_actions.scss","../scss/_resizer.scss","../scss/_responsive.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAKA;EACE;IACE;;EAEF;IACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;AACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAIJ;EACE;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EAGA;EACA;EACA;EACA;EAEA;;AAGF;AAAA;EAEE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;AAAA;EAEE;EACA;EACA;;AAEA;AAAA;EACE;EACA;;AAGJ;EACE;EACA;;AAIF;AAAA;EAEE;EACA;EACA;EAEA;EACA;;AAGA;AAAA;EACE;EACA;;AAKJ;EACE;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAMA;AAAA;EAEE;EACA;EACA;EACA;;AAGF;EACE;;AAEF;EACE;;AAKJ;AAAA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;EAEE;EACA;EACA;EACA;;AAGJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGA;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;EACA;;AAKJ;EACE;;AAEF;AAAA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;AAAA;EAEE;EACA;;AAKJ;EACE;EACA;;AACA;EACE;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAKJ;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKJ;EAKE;;AAJA;EACE;;AAKF;EACE;;AAEF;EACE;EACA;EACA;;AAKJ;EACE;;AACA;EACE;;AAEF;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;EACA;;AAEA;EAEE;EACA;;AAGJ;EAEE;EACA;;AAIA;EACE;;AAEF;EACE;;AAMN;EACE;EACA;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAEE;EACE;;;ACldF;AAAA;EAEE;;AAEF;EACE;EACA;;AAEF;AAAA;AAAA;AAAA;EAIE;EACA;;AAEF;EACE;;;ACjBJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;;ACrBJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;;AAGJ;EACE;EACA;;AAEF;EACE;;AAGF;EACE;;AAEF;EACE;;AAEA;EACE;;AAGJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEA;EACE;;AAIN;EACE;;AAEA;EACE;;;ACpDJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAEF;EACE;;AAEA;EACE;;;AC3BN;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;;AAEA;AAAA;EAEE;;AAGF;EACE;;;AAMN;EAGI;IACE;;EAIF;IACE;;EAEF;IACE;;EAIF;AAAA;AAAA;AAAA;AAAA;AAAA;IAME;;EAIF;IACE;IASA;;EAPA;IACE;;EAEF;IACE;;EAQF;IACE;IACA;;EAEF;IACE;IACA;IACA;IACA;;EAEA;IACE;;EAEF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAMN;IACE;IACA;;EAIA;IAEE;;EAEF;IACE;;EAEF;IACE;IACA;;EAEF;IACE;;EAEF;IACE;IACA;;EAGJ;IACE;;EAGA;IACE;IACA;;EAEA;IACE;;EAGJ;IACE;IACA;IACA;IACA;;EAGJ;IACE;;EAEF;IACE;;EAEF;IACE","file":"data-grid.css"} \ No newline at end of file +{"version":3,"sources":["../scss/_core.scss","data-grid.css","../scss/_rtl.scss","../scss/_menu.scss","../scss/_actions.scss","../scss/_resizer.scss","../scss/_responsive.scss"],"names":[],"mappings":"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","file":"data-grid.css","sourcesContent":["/**\r\n * Data Grid Web component \r\n * https://github.com/lekoala/data-grid\r\n */\r\n\r\n@keyframes dataGridShow {\r\n 0% {\r\n opacity: 1;\r\n }\r\n 100% {\r\n opacity: 0.5;\r\n }\r\n}\r\n\r\ndata-grid {\r\n --padding: 0.5rem;\r\n --padding-x: 0.75rem;\r\n --padding-y: 0.5rem;\r\n --padding-y-header: 0.75rem;\r\n --padding-half: calc(var(--padding) / 2);\r\n --color-rgb: var(--bs-primary-rgb, 13, 110, 253);\r\n --color: rgb(var(--color-rgb));\r\n\r\n --highlight-color: #fffcee;\r\n --header-background: var(--bs-gray-200, #e9ecef);\r\n --header-color: var(--bs-dark, #212529);\r\n --input-background: var(--bs-form-control-bg, #ffffff);\r\n --input-border-color: var(--bs-border-color, #e9ecef);\r\n --btn-background: var(--bs-form-control-bg, #ffffff);\r\n --btn-color: var(--color);\r\n --btn-border-color: var(--bs-border-color, #e9ecef);\r\n --body-bg: var(--bs-body-bg, #212529);\r\n --body-color: var(--bs-body-color, #212529);\r\n --icon-scale: 1;\r\n --border-radius: 0.25rem;\r\n --row-border-color: #f2f2f2;\r\n --responsive-width: 60%;\r\n\r\n --black: var(--bs-black, #000);\r\n --white: var(--bs-white, #fff);\r\n --gray: var(--bs-gray, #6c757d);\r\n --gray-dark: var(--bs-gray-dark, #343a40);\r\n --gray-100: var(--bs-gray-100, #f8f9fa);\r\n --gray-200: var(--bs-gray-200, #e9ecef);\r\n --gray-300: var(--bs-gray-300, #dee2e6);\r\n --gray-400: var(--bs-gray-400, #ced4da);\r\n --gray-500: var(--bs-gray-500, #adb5bd);\r\n --gray-600: var(--bs-gray-600, #6c757d);\r\n --gray-700: var(--bs-gray-700, #495057);\r\n --gray-800: var(--bs-gray-800, #343a40);\r\n --gray-900: var(--bs-gray-900, #212529);\r\n\r\n display: block;\r\n min-height: 6rem;\r\n position: relative;\r\n\r\n // When used with fixed height, have a nice scrollbar\r\n & {\r\n --scroller-color: 0, 0%;\r\n --scroller-color-lightness: 80%;\r\n --scroller-hover-factor: 0.8;\r\n --scroller-thumb: hsl(var(--scroller-color), var(--scroller-color-lightness));\r\n /* Replicate hover for webkit */\r\n --scroller-thumb-hover: hsl(var(--scroller-color), calc(var(--scroller-color-lightness) * var(--scroller-hover-factor)));\r\n --scroller-background: transparent;\r\n scrollbar-color: var(--scroller-thumb) var(--scroller-background);\r\n scrollbar-width: thin;\r\n &::-webkit-scrollbar {\r\n width: 8px;\r\n height: 8px;\r\n }\r\n &::-webkit-scrollbar-track {\r\n background: transparent;\r\n }\r\n &::-webkit-scrollbar-thumb {\r\n background: var(--scroller-thumb);\r\n }\r\n &::-webkit-scrollbar-thumb:hover {\r\n background: var(--scroller-thumb-hover);\r\n }\r\n }\r\n\r\n img {\r\n border: none;\r\n height: auto;\r\n max-width: 100%;\r\n vertical-align: middle;\r\n }\r\n\r\n [hidden] {\r\n display: none;\r\n }\r\n\r\n table {\r\n display: table;\r\n // Table and column widths are set by the widths of table and col elements\r\n // or by the width of the first row of cells. Cells in subsequent rows do not affect column widths.\r\n table-layout: fixed;\r\n width: 100%;\r\n max-width: 100%;\r\n white-space: normal;\r\n // Background needs to be on the table, not on the component in case the table overflows the component\r\n background: var(--header-background);\r\n }\r\n\r\n thead,\r\n tfoot {\r\n background-color: var(--header-background);\r\n color: var(--header-color);\r\n }\r\n\r\n &.dg-loading tbody {\r\n animation-name: dataGridShow;\r\n animation-timing-function: ease-in;\r\n animation-fill-mode: forwards;\r\n animation-duration: 0.3s; // only triggers after 300ms\r\n pointer-events: none; // disable clicks while loading\r\n }\r\n\r\n tr {\r\n position: relative;\r\n }\r\n\r\n th,\r\n td {\r\n empty-cells: show;\r\n padding: var(--padding-y) var(--padding-x);\r\n text-align: left;\r\n\r\n &[tabindex] {\r\n outline: none;\r\n word-break: normal;\r\n }\r\n }\r\n th {\r\n font-weight: bold;\r\n padding: var(--padding-y-header) var(--padding-x);\r\n }\r\n\r\n // Prevent overflow on headers and cells\r\n th,\r\n td {\r\n position: relative;\r\n overflow: hidden;\r\n text-align: left;\r\n // These two properties keep content on one line\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n\r\n // Use this to allow content to flow over multiple lines\r\n &.dg-wrap {\r\n white-space: normal;\r\n word-break: break-all;\r\n }\r\n }\r\n\r\n // Expand on multiple lines on row click\r\n .dg-expandable {\r\n cursor: pointer;\r\n\r\n &.dg-expanded td {\r\n white-space: normal;\r\n word-break: break-all;\r\n }\r\n }\r\n\r\n .dg-clickable-cell {\r\n margin: 0;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n // Stick headers\r\n // https://css-tricks.com/making-tables-with-sticky-header-and-footers-got-a-bit-easier/\r\n &[sticky] table {\r\n thead,\r\n tfoot {\r\n z-index: 2;\r\n position: sticky;\r\n margin: 0;\r\n border: 0;\r\n }\r\n // Use silly value to prevent sub pixel alignment issue\r\n thead {\r\n inset-block-start: -1px;\r\n }\r\n tfoot {\r\n inset-block-end: -1px;\r\n }\r\n }\r\n\r\n // Pagination icons\r\n .dg-nav-icon,\r\n .dg-skip-icon {\r\n width: 22px;\r\n height: 22px;\r\n box-sizing: border-box;\r\n position: absolute;\r\n display: block;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%) scale(var(--icon-scale, 1));\r\n\r\n &:before,\r\n &:after {\r\n content: \"\";\r\n display: block;\r\n box-sizing: border-box;\r\n position: absolute;\r\n }\r\n }\r\n .dg-nav-icon::before {\r\n width: 0;\r\n height: 10px;\r\n border-top: 5px solid transparent;\r\n border-bottom: 5px solid transparent;\r\n border-left: 6px solid;\r\n top: 6px;\r\n left: 9px;\r\n }\r\n .dg-skip-icon {\r\n &::before {\r\n width: 3px;\r\n height: 10px;\r\n background: currentColor;\r\n top: 6px;\r\n left: 14px;\r\n }\r\n &::after {\r\n width: 0;\r\n height: 10px;\r\n border-top: 5px solid transparent;\r\n border-bottom: 5px solid transparent;\r\n border-left: 6px solid;\r\n top: 6px;\r\n left: 7px;\r\n }\r\n }\r\n .dg-rotate {\r\n transform: rotate(-180deg);\r\n }\r\n\r\n // Default actions buttons\r\n button {\r\n background-color: var(--btn-background);\r\n border: solid 1px var(--btn-border-color);\r\n border-radius: var(--border-radius);\r\n color: var(--body-color);\r\n height: 2rem;\r\n margin: 0 0.2rem;\r\n padding: 0 0.5rem;\r\n pointer-events: all;\r\n text-align: center;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n opacity: 0.7;\r\n }\r\n &:disabled:hover {\r\n background-color: inherit;\r\n border-color: inherit;\r\n }\r\n }\r\n\r\n // Form elements\r\n input[type=\"checkbox\"] {\r\n margin: 0;\r\n }\r\n input:not([type=\"checkbox\"]),\r\n select {\r\n background-color: var(--input-background, \"#fff\");\r\n color: currentColor;\r\n box-sizing: border-box;\r\n border: 1px solid var(--input-border-color, \"#f0f0f0\");\r\n border-radius: var(--border-radius);\r\n height: 2rem;\r\n margin: 0 0.2rem;\r\n padding: 0 var(--padding);\r\n max-width: none;\r\n }\r\n input:not([type=\"checkbox\"]),\r\n select,\r\n button {\r\n &:focus {\r\n box-shadow: 0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);\r\n outline: 0;\r\n }\r\n\r\n &[disabled],\r\n &:disabled {\r\n opacity: 0.35;\r\n pointer-events: none;\r\n }\r\n }\r\n\r\n // Filters (2nd header row)\r\n thead tr:nth-child(2) th {\r\n padding: 0;\r\n background-color: transparent;\r\n input {\r\n width: 100%;\r\n border-radius: 0;\r\n margin: 0;\r\n }\r\n }\r\n\r\n // Editable\r\n tbody td input.dg-editable {\r\n width: 100%;\r\n background: transparent;\r\n border: 0;\r\n border-radius: 0;\r\n margin: 0;\r\n\r\n &:hover {\r\n box-shadow: 0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);\r\n }\r\n }\r\n\r\n // Empty table or error message (don't use :empty as it would create fouc on load)\r\n &:not([data-url]) tbody {\r\n height: 8rem;\r\n position: relative;\r\n &:before {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n content: attr(data-empty);\r\n transform: translate(-50%, -50%);\r\n opacity: 0.5;\r\n font-size: 2rem;\r\n text-align: center;\r\n white-space: nowrap;\r\n text-overflow: ellipsis;\r\n overflow: hidden;\r\n width: 90%;\r\n }\r\n }\r\n\r\n // Zebra rows\r\n tbody tr {\r\n &:nth-child(even) {\r\n background-color: var(--bs-table-striped-bg, #f8f9fa);\r\n }\r\n\r\n border-bottom: solid 1px var(--row-border-color);\r\n\r\n &:hover {\r\n background-color: var(--highlight-color) !important;\r\n }\r\n &:focus {\r\n background-color: var(--highlight-color) !important;\r\n border-bottom-color: var(--highlight-color) !important;\r\n outline: none;\r\n }\r\n }\r\n\r\n // Meta footer\r\n tfoot {\r\n min-width: 280px;\r\n td {\r\n padding: var(--padding-y-header) var(--padding-x);\r\n }\r\n .dg-page-nav {\r\n display: flex;\r\n align-items: center;\r\n }\r\n .dg-input-page {\r\n width: 4rem;\r\n }\r\n .dg-footer {\r\n display: flex;\r\n align-items: center;\r\n flex-direction: row;\r\n justify-content: space-between;\r\n }\r\n .dg-pagination {\r\n display: flex;\r\n text-align: center;\r\n\r\n button {\r\n // Fix icon inside button\r\n position: relative;\r\n width: 2rem;\r\n }\r\n }\r\n .dg-meta {\r\n // Prevent layout from jumping around\r\n min-width: 160px;\r\n text-align: right;\r\n }\r\n\r\n &.dg-footer-compact {\r\n .dg-meta {\r\n display: none;\r\n }\r\n .dg-input-page {\r\n display: none;\r\n }\r\n }\r\n }\r\n\r\n // Pagination in header\r\n [aria-sort] {\r\n cursor: pointer;\r\n padding-right: 1.5rem;\r\n }\r\n\r\n [aria-sort=\"none\"]:after,\r\n [aria-sort=\"none\"]:before,\r\n [aria-sort=\"ascending\"]:before,\r\n [aria-sort=\"descending\"]:after {\r\n right: 0.5rem;\r\n top: calc(50% - 0.5rem);\r\n border: solid transparent;\r\n content: \" \";\r\n height: 0;\r\n width: 0;\r\n position: absolute;\r\n border-color: rgba(0, 0, 0, 0);\r\n border-width: 0.25rem;\r\n margin-left: -0.25rem;\r\n }\r\n\r\n [aria-sort=\"none\"] {\r\n &:before {\r\n border-bottom-color: currentColor;\r\n opacity: 0.25;\r\n top: calc(50% - 0.6rem);\r\n }\r\n\r\n &:after {\r\n border-top-color: currentColor;\r\n opacity: 0.25;\r\n bottom: calc(50% - 0.5rem);\r\n top: auto;\r\n }\r\n }\r\n\r\n [aria-sort=\"ascending\"]:before {\r\n border-bottom-color: var(--body-color);\r\n opacity: 0.75;\r\n }\r\n\r\n [aria-sort=\"descending\"]:after {\r\n border-top-color: var(--body-color);\r\n opacity: 0.75;\r\n bottom: calc(50% - 0.5rem);\r\n top: auto;\r\n }\r\n}\r\n\r\n[data-bs-theme=\"dark\"] data-grid {\r\n --scroller-color-lightness: 20%;\r\n --highlight-color: #43423e;\r\n --header-background: var(--bs-gray-800, #34373b);\r\n --header-color: var(--bs-light, #e9ecef);\r\n --body-color: var(--bs-body-color, #494e53);\r\n --row-border-color: var(--bs-gray-900, #212325);\r\n tbody tr {\r\n &:nth-child(even) {\r\n background-color: var(--bs-table-striped-bg, #2c3034);\r\n }\r\n }\r\n}\r\n","/**\n * Data Grid Web component \n * https://github.com/lekoala/data-grid\n */\n@keyframes dataGridShow {\n 0% {\n opacity: 1;\n }\n 100% {\n opacity: 0.5;\n }\n}\ndata-grid {\n --padding: 0.5rem;\n --padding-x: 0.75rem;\n --padding-y: 0.5rem;\n --padding-y-header: 0.75rem;\n --padding-half: calc(var(--padding) / 2);\n --color-rgb: var(--bs-primary-rgb, 13, 110, 253);\n --color: rgb(var(--color-rgb));\n --highlight-color: #fffcee;\n --header-background: var(--bs-gray-200, #e9ecef);\n --header-color: var(--bs-dark, #212529);\n --input-background: var(--bs-form-control-bg, #ffffff);\n --input-border-color: var(--bs-border-color, #e9ecef);\n --btn-background: var(--bs-form-control-bg, #ffffff);\n --btn-color: var(--color);\n --btn-border-color: var(--bs-border-color, #e9ecef);\n --body-bg: var(--bs-body-bg, #212529);\n --body-color: var(--bs-body-color, #212529);\n --icon-scale: 1;\n --border-radius: 0.25rem;\n --row-border-color: #f2f2f2;\n --responsive-width: 60%;\n --black: var(--bs-black, #000);\n --white: var(--bs-white, #fff);\n --gray: var(--bs-gray, #6c757d);\n --gray-dark: var(--bs-gray-dark, #343a40);\n --gray-100: var(--bs-gray-100, #f8f9fa);\n --gray-200: var(--bs-gray-200, #e9ecef);\n --gray-300: var(--bs-gray-300, #dee2e6);\n --gray-400: var(--bs-gray-400, #ced4da);\n --gray-500: var(--bs-gray-500, #adb5bd);\n --gray-600: var(--bs-gray-600, #6c757d);\n --gray-700: var(--bs-gray-700, #495057);\n --gray-800: var(--bs-gray-800, #343a40);\n --gray-900: var(--bs-gray-900, #212529);\n display: block;\n min-height: 6rem;\n position: relative;\n}\ndata-grid {\n --scroller-color: 0, 0%;\n --scroller-color-lightness: 80%;\n --scroller-hover-factor: 0.8;\n --scroller-thumb: hsl(var(--scroller-color), var(--scroller-color-lightness));\n /* Replicate hover for webkit */\n --scroller-thumb-hover: hsl(var(--scroller-color), calc(var(--scroller-color-lightness) * var(--scroller-hover-factor)));\n --scroller-background: transparent;\n scrollbar-color: var(--scroller-thumb) var(--scroller-background);\n scrollbar-width: thin;\n}\ndata-grid::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\ndata-grid::-webkit-scrollbar-track {\n background: transparent;\n}\ndata-grid::-webkit-scrollbar-thumb {\n background: var(--scroller-thumb);\n}\ndata-grid::-webkit-scrollbar-thumb:hover {\n background: var(--scroller-thumb-hover);\n}\ndata-grid img {\n border: none;\n height: auto;\n max-width: 100%;\n vertical-align: middle;\n}\ndata-grid [hidden] {\n display: none;\n}\ndata-grid table {\n display: table;\n table-layout: fixed;\n width: 100%;\n max-width: 100%;\n white-space: normal;\n background: var(--header-background);\n}\ndata-grid thead,\ndata-grid tfoot {\n background-color: var(--header-background);\n color: var(--header-color);\n}\ndata-grid.dg-loading tbody {\n animation-name: dataGridShow;\n animation-timing-function: ease-in;\n animation-fill-mode: forwards;\n animation-duration: 0.3s;\n pointer-events: none;\n}\ndata-grid tr {\n position: relative;\n}\ndata-grid th,\ndata-grid td {\n empty-cells: show;\n padding: var(--padding-y) var(--padding-x);\n text-align: left;\n}\ndata-grid th[tabindex],\ndata-grid td[tabindex] {\n outline: none;\n word-break: normal;\n}\ndata-grid th {\n font-weight: bold;\n padding: var(--padding-y-header) var(--padding-x);\n}\ndata-grid th,\ndata-grid td {\n position: relative;\n overflow: hidden;\n text-align: left;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\ndata-grid th.dg-wrap,\ndata-grid td.dg-wrap {\n white-space: normal;\n word-break: break-all;\n}\ndata-grid .dg-expandable {\n cursor: pointer;\n}\ndata-grid .dg-expandable.dg-expanded td {\n white-space: normal;\n word-break: break-all;\n}\ndata-grid .dg-clickable-cell {\n margin: 0;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n}\ndata-grid[sticky] table thead,\ndata-grid[sticky] table tfoot {\n z-index: 2;\n position: sticky;\n margin: 0;\n border: 0;\n}\ndata-grid[sticky] table thead {\n inset-block-start: -1px;\n}\ndata-grid[sticky] table tfoot {\n inset-block-end: -1px;\n}\ndata-grid .dg-nav-icon,\ndata-grid .dg-skip-icon {\n width: 22px;\n height: 22px;\n box-sizing: border-box;\n position: absolute;\n display: block;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(var(--icon-scale, 1));\n}\ndata-grid .dg-nav-icon:before, data-grid .dg-nav-icon:after,\ndata-grid .dg-skip-icon:before,\ndata-grid .dg-skip-icon:after {\n content: \"\";\n display: block;\n box-sizing: border-box;\n position: absolute;\n}\ndata-grid .dg-nav-icon::before {\n width: 0;\n height: 10px;\n border-top: 5px solid transparent;\n border-bottom: 5px solid transparent;\n border-left: 6px solid;\n top: 6px;\n left: 9px;\n}\ndata-grid .dg-skip-icon::before {\n width: 3px;\n height: 10px;\n background: currentColor;\n top: 6px;\n left: 14px;\n}\ndata-grid .dg-skip-icon::after {\n width: 0;\n height: 10px;\n border-top: 5px solid transparent;\n border-bottom: 5px solid transparent;\n border-left: 6px solid;\n top: 6px;\n left: 7px;\n}\ndata-grid .dg-rotate {\n transform: rotate(-180deg);\n}\ndata-grid button {\n background-color: var(--btn-background);\n border: solid 1px var(--btn-border-color);\n border-radius: var(--border-radius);\n color: var(--body-color);\n height: 2rem;\n margin: 0 0.2rem;\n padding: 0 0.5rem;\n pointer-events: all;\n text-align: center;\n cursor: pointer;\n}\ndata-grid button:hover {\n opacity: 0.7;\n}\ndata-grid button:disabled:hover {\n background-color: inherit;\n border-color: inherit;\n}\ndata-grid input[type=checkbox] {\n margin: 0;\n}\ndata-grid input:not([type=checkbox]),\ndata-grid select {\n background-color: var(--input-background, \"#fff\");\n color: currentColor;\n box-sizing: border-box;\n border: 1px solid var(--input-border-color, \"#f0f0f0\");\n border-radius: var(--border-radius);\n height: 2rem;\n margin: 0 0.2rem;\n padding: 0 var(--padding);\n max-width: none;\n}\ndata-grid input:not([type=checkbox]):focus,\ndata-grid select:focus,\ndata-grid button:focus {\n box-shadow: 0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);\n outline: 0;\n}\ndata-grid input:not([type=checkbox])[disabled], data-grid input:not([type=checkbox]):disabled,\ndata-grid select[disabled],\ndata-grid select:disabled,\ndata-grid button[disabled],\ndata-grid button:disabled {\n opacity: 0.35;\n pointer-events: none;\n}\ndata-grid thead tr:nth-child(2) th {\n padding: 0;\n background-color: transparent;\n}\ndata-grid thead tr:nth-child(2) th input {\n width: 100%;\n border-radius: 0;\n margin: 0;\n}\ndata-grid tbody td input.dg-editable {\n width: 100%;\n background: transparent;\n border: 0;\n border-radius: 0;\n margin: 0;\n}\ndata-grid tbody td input.dg-editable:hover {\n box-shadow: 0 0 0 var(--padding-half) rgba(var(--color-rgb), 0.25);\n}\ndata-grid:not([data-url]) tbody {\n height: 8rem;\n position: relative;\n}\ndata-grid:not([data-url]) tbody:before {\n position: absolute;\n top: 50%;\n left: 50%;\n content: attr(data-empty);\n transform: translate(-50%, -50%);\n opacity: 0.5;\n font-size: 2rem;\n text-align: center;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n width: 90%;\n}\ndata-grid tbody tr {\n border-bottom: solid 1px var(--row-border-color);\n}\ndata-grid tbody tr:nth-child(even) {\n background-color: var(--bs-table-striped-bg, #f8f9fa);\n}\ndata-grid tbody tr:hover {\n background-color: var(--highlight-color) !important;\n}\ndata-grid tbody tr:focus {\n background-color: var(--highlight-color) !important;\n border-bottom-color: var(--highlight-color) !important;\n outline: none;\n}\ndata-grid tfoot {\n min-width: 280px;\n}\ndata-grid tfoot td {\n padding: var(--padding-y-header) var(--padding-x);\n}\ndata-grid tfoot .dg-page-nav {\n display: flex;\n align-items: center;\n}\ndata-grid tfoot .dg-input-page {\n width: 4rem;\n}\ndata-grid tfoot .dg-footer {\n display: flex;\n align-items: center;\n flex-direction: row;\n justify-content: space-between;\n}\ndata-grid tfoot .dg-pagination {\n display: flex;\n text-align: center;\n}\ndata-grid tfoot .dg-pagination button {\n position: relative;\n width: 2rem;\n}\ndata-grid tfoot .dg-meta {\n min-width: 160px;\n text-align: right;\n}\ndata-grid tfoot.dg-footer-compact .dg-meta {\n display: none;\n}\ndata-grid tfoot.dg-footer-compact .dg-input-page {\n display: none;\n}\ndata-grid [aria-sort] {\n cursor: pointer;\n padding-right: 1.5rem;\n}\ndata-grid [aria-sort=none]:after,\ndata-grid [aria-sort=none]:before,\ndata-grid [aria-sort=ascending]:before,\ndata-grid [aria-sort=descending]:after {\n right: 0.5rem;\n top: calc(50% - 0.5rem);\n border: solid transparent;\n content: \" \";\n height: 0;\n width: 0;\n position: absolute;\n border-color: rgba(0, 0, 0, 0);\n border-width: 0.25rem;\n margin-left: -0.25rem;\n}\ndata-grid [aria-sort=none]:before {\n border-bottom-color: currentColor;\n opacity: 0.25;\n top: calc(50% - 0.6rem);\n}\ndata-grid [aria-sort=none]:after {\n border-top-color: currentColor;\n opacity: 0.25;\n bottom: calc(50% - 0.5rem);\n top: auto;\n}\ndata-grid [aria-sort=ascending]:before {\n border-bottom-color: var(--body-color);\n opacity: 0.75;\n}\ndata-grid [aria-sort=descending]:after {\n border-top-color: var(--body-color);\n opacity: 0.75;\n bottom: calc(50% - 0.5rem);\n top: auto;\n}\n\n[data-bs-theme=dark] data-grid {\n --scroller-color-lightness: 20%;\n --highlight-color: #43423e;\n --header-background: var(--bs-gray-800, #34373b);\n --header-color: var(--bs-light, #e9ecef);\n --body-color: var(--bs-body-color, #494e53);\n --row-border-color: var(--bs-gray-900, #212325);\n}\n[data-bs-theme=dark] data-grid tbody tr:nth-child(even) {\n background-color: var(--bs-table-striped-bg, #2c3034);\n}\n\ndata-grid[dir=rtl] th,\ndata-grid[dir=rtl] td {\n text-align: right;\n}\ndata-grid[dir=rtl] [aria-sort] {\n padding-left: 1rem;\n padding-right: 0.5rem;\n}\ndata-grid[dir=rtl] [aria-sort=none]:after,\ndata-grid[dir=rtl] [aria-sort=none]:before,\ndata-grid[dir=rtl] [aria-sort=ascending]:before,\ndata-grid[dir=rtl] [aria-sort=descending]:after {\n left: 0.75rem;\n right: auto;\n}\ndata-grid[dir=rtl] tfoot .dg-meta {\n text-align: left;\n}\n\ndata-grid .dg-menu {\n position: absolute;\n z-index: 3;\n background: var(--body-bg);\n list-style: none;\n max-width: 150px;\n margin: 0;\n padding: var(--padding);\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.25);\n border-radius: var(--border-radius);\n}\ndata-grid .dg-menu li {\n margin: 0;\n padding: 0;\n}\ndata-grid .dg-menu label {\n display: flex;\n align-items: center;\n margin-bottom: 0.25em;\n}\ndata-grid .dg-menu input {\n margin-right: 0.5em;\n}\n\ndata-grid .dg-actions {\n text-overflow: initial;\n width: 100px;\n text-align: right;\n white-space: nowrap !important;\n}\ndata-grid .dg-actions button {\n margin: 0;\n}\ndata-grid .dg-actions button + button {\n margin-left: 0.5rem;\n}\ndata-grid .dg-actions .dg-actions-toggle {\n display: none;\n width: calc(100px - var(--padding-x) * 2);\n}\ndata-grid .dg-actions.dg-actions-1 {\n width: 100%;\n}\ndata-grid .dg-actions.dg-actions-2 button {\n width: calc(50% - 0.25rem);\n}\ndata-grid .dg-actions.dg-actions-more button {\n display: none;\n}\ndata-grid .dg-actions.dg-actions-more button.dg-actions-toggle {\n display: inline-block;\n}\ndata-grid .dg-actions.dg-actions-expand {\n position: absolute;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n width: 100%;\n height: 100%;\n}\ndata-grid .dg-actions.dg-actions-expand.dg-actions-more {\n width: 100%;\n}\ndata-grid .dg-actions.dg-actions-expand.dg-actions-more button {\n display: inline-block;\n}\ndata-grid tr.dg-actionable {\n cursor: pointer;\n}\ndata-grid tr.dg-actionable:hover td {\n background-color: var(--highlight-color);\n}\n\ndata-grid .dg-resizer {\n position: absolute;\n top: 0;\n right: 0;\n width: 6px;\n z-index: 2;\n cursor: col-resize;\n user-select: none;\n}\ndata-grid .dg-resizer:before {\n content: \"\";\n display: block;\n position: absolute;\n top: var(--padding-y-header);\n height: 1.5rem;\n right: 0;\n width: 2px;\n background: var(--body-color);\n opacity: 0.2;\n}\ndata-grid .dg-resizer:hover:before {\n opacity: 0.6;\n}\ndata-grid .dg-resizer.dg-resizer-active {\n border-right: 1px dashed var(--color);\n}\ndata-grid .dg-resizer.dg-resizer-active:before {\n opacity: 0.6;\n}\n\ndata-grid .dg-responsive-toggle {\n padding: 0;\n text-align: center;\n}\ndata-grid .dg-responsive-child-row > td {\n padding: 0;\n}\ndata-grid .dg-responsive-table {\n table-layout: auto;\n border: 0;\n}\ndata-grid .dg-responsive-table td,\ndata-grid .dg-responsive-table th {\n white-space: normal;\n}\ndata-grid .dg-responsive-table th {\n max-width: 40%;\n}\n\n@media only screen and (max-width: 767px) {\n data-grid[responsive] .dg-resizer {\n display: none;\n }\n data-grid[responsive] .dg-meta {\n display: none;\n }\n data-grid[responsive] .dg-input-page {\n display: none;\n }\n data-grid[responsive] table,\n data-grid[responsive] tbody,\n data-grid[responsive] tfoot,\n data-grid[responsive] th,\n data-grid[responsive] td,\n data-grid[responsive] tr:not([hidden]) {\n display: block;\n }\n data-grid[responsive] thead {\n display: flex;\n border-bottom: 2px solid var(--header-background);\n }\n data-grid[responsive] thead > tr {\n flex-grow: 1;\n }\n data-grid[responsive] thead th {\n width: auto;\n }\n data-grid[responsive] tbody tr {\n padding: 0;\n border: 1px solid var(--header-background);\n }\n data-grid[responsive] tbody td {\n border: none;\n border-bottom: 1px solid var(--row-border-color);\n position: relative;\n padding-left: calc(100% - var(--responsive-width) - var(--padding) * 2);\n }\n data-grid[responsive] tbody td:last-child {\n border: 0;\n }\n data-grid[responsive] tbody td:before {\n position: absolute;\n top: 0;\n left: 0;\n padding: var(--padding);\n width: calc(100% - var(--responsive-width) - var(--padding) * 4);\n white-space: nowrap;\n content: attr(data-name);\n display: block;\n font-weight: bold;\n background-color: var(--header-background);\n }\n data-grid[responsive] .dg-selectable {\n height: 28px;\n margin: 2px 1px 2px;\n }\n data-grid[responsive] td.dg-selectable::before, data-grid[responsive] td.dg-actions::before {\n padding: 0;\n }\n data-grid[responsive] td.dg-selectable label {\n padding: 5px;\n }\n data-grid[responsive] td[role=gridcell] {\n min-height: 35px;\n width: auto;\n }\n data-grid[responsive] td[data-name]::before {\n height: 100%;\n }\n data-grid[responsive] td.dg-actions {\n padding-left: inherit;\n width: inherit;\n }\n data-grid[responsive] .dg-actions button {\n width: inherit !important;\n }\n data-grid[responsive] tr.dg-head-columns {\n padding: 0;\n width: calc(100% - var(--responsive-width) - var(--padding) * 4);\n }\n data-grid[responsive] tr.dg-head-columns th[role=\"columnheader button\"] {\n padding: 0.36em 1.3em 0.36em 0.75em;\n }\n data-grid[responsive] tr.dg-head-filters {\n background: transparent;\n vertical-align: top;\n padding: 0;\n width: calc(100% - (100% - var(--responsive-width) - var(--padding) * 4));\n }\n data-grid[responsive] .dg-head-filters th input:not([type=checkbox], [type=radio]) {\n height: 2.25em;\n }\n data-grid[responsive] .dg-head-filters th.dg-selectable {\n background: transparent;\n }\n data-grid[responsive] .dg-head-filters th.dg-selectable label::before {\n content: \"Column Filters\";\n }\n}\n\n/*# sourceMappingURL=data-grid.css.map */\n","data-grid {\r\n &[dir=\"rtl\"] {\r\n th,\r\n td {\r\n text-align: right;\r\n }\r\n [aria-sort] {\r\n padding-left: 1rem;\r\n padding-right: 0.5rem;\r\n }\r\n [aria-sort=\"none\"]:after,\r\n [aria-sort=\"none\"]:before,\r\n [aria-sort=\"ascending\"]:before,\r\n [aria-sort=\"descending\"]:after {\r\n left: 0.75rem;\r\n right: auto;\r\n }\r\n tfoot .dg-meta {\r\n text-align: left;\r\n }\r\n }\r\n}\r\n","data-grid {\r\n .dg-menu {\r\n position: absolute;\r\n z-index: 3;\r\n background: var(--body-bg);\r\n list-style: none;\r\n max-width: 150px;\r\n margin: 0;\r\n padding: var(--padding);\r\n box-shadow: 0 0 1rem rgba(0, 0, 0, 0.25);\r\n border-radius: var(--border-radius);\r\n\r\n li {\r\n margin: 0;\r\n padding: 0;\r\n }\r\n label {\r\n display: flex;\r\n align-items: center;\r\n margin-bottom: 0.25em;\r\n }\r\n input {\r\n margin-right: 0.5em;\r\n }\r\n }\r\n}\r\n","data-grid {\r\n .dg-actions {\r\n text-overflow: initial;\r\n width: 100px;\r\n text-align: right;\r\n white-space: nowrap !important;\r\n\r\n button {\r\n margin: 0;\r\n\r\n + button {\r\n margin-left: 0.5rem;\r\n }\r\n }\r\n .dg-actions-toggle {\r\n display: none;\r\n width: calc(100px - var(--padding-x) * 2);\r\n }\r\n &.dg-actions-1 {\r\n width: 100%;\r\n }\r\n // This needs icons to work\r\n &.dg-actions-2 button {\r\n width: calc(50% - 0.25rem);\r\n }\r\n &.dg-actions-more button {\r\n display: none;\r\n\r\n &.dg-actions-toggle {\r\n display: inline-block;\r\n }\r\n }\r\n &.dg-actions-expand {\r\n position: absolute;\r\n right: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n width: 100%;\r\n height: 100%;\r\n }\r\n &.dg-actions-expand.dg-actions-more {\r\n width: 100%;\r\n\r\n button {\r\n display: inline-block;\r\n }\r\n }\r\n }\r\n tr.dg-actionable {\r\n cursor: pointer;\r\n\r\n &:hover td {\r\n background-color: var(--highlight-color);\r\n }\r\n }\r\n}\r\n","data-grid {\r\n .dg-resizer {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n width: 6px; // clickable zone\r\n z-index: 2;\r\n cursor: col-resize;\r\n user-select: none;\r\n\r\n &:before {\r\n content: \"\";\r\n display: block;\r\n position: absolute;\r\n top: var(--padding-y-header);\r\n height: 1.5rem;\r\n right: 0;\r\n width: 2px;\r\n background: var(--body-color);\r\n opacity: 0.2;\r\n }\r\n &:hover:before {\r\n opacity: 0.6;\r\n }\r\n &.dg-resizer-active {\r\n border-right: 1px dashed var(--color);\r\n\r\n &:before {\r\n opacity: 0.6;\r\n }\r\n }\r\n }\r\n}\r\n","data-grid {\r\n .dg-responsive-toggle {\r\n padding: 0;\r\n text-align: center;\r\n }\r\n .dg-responsive-child-row > td {\r\n padding: 0;\r\n }\r\n .dg-responsive-table {\r\n table-layout: auto;\r\n border: 0;\r\n\r\n td,\r\n th {\r\n white-space: normal;\r\n }\r\n\r\n th {\r\n max-width: 40%;\r\n }\r\n }\r\n}\r\n\r\n// CSS Only responsive\r\n@media only screen and (max-width: 767px) {\r\n data-grid[responsive] {\r\n // Doesn't make any sense to resize\r\n .dg-resizer {\r\n display: none;\r\n }\r\n\r\n // more compact footer\r\n .dg-meta {\r\n display: none;\r\n }\r\n .dg-input-page {\r\n display: none;\r\n }\r\n\r\n // everything as blocks\r\n table,\r\n tbody,\r\n tfoot,\r\n th,\r\n td,\r\n tr:not([hidden]) {\r\n display: block;\r\n }\r\n\r\n // use flex for thead\r\n thead {\r\n display: flex;\r\n\r\n > tr {\r\n flex-grow: 1;\r\n }\r\n th {\r\n width: auto;\r\n }\r\n\r\n border-bottom: 2px solid var(--header-background);\r\n }\r\n\r\n // use pseudo element to display column name\r\n tbody {\r\n tr {\r\n padding: 0;\r\n border: 1px solid var(--header-background);\r\n }\r\n td {\r\n border: none;\r\n border-bottom: 1px solid var(--row-border-color);\r\n position: relative;\r\n padding-left: calc(100% - var(--responsive-width) - var(--padding) * 2);\r\n\r\n &:last-child {\r\n border: 0;\r\n }\r\n &:before {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n padding: var(--padding);\r\n width: calc(100% - var(--responsive-width) - var(--padding) * 4);\r\n white-space: nowrap;\r\n content: attr(data-name);\r\n display: block;\r\n font-weight: bold;\r\n background-color: var(--header-background);\r\n }\r\n }\r\n }\r\n\r\n // give selectable some room\r\n .dg-selectable {\r\n height: 28px;\r\n margin: 2px 1px 2px;\r\n }\r\n\r\n td {\r\n &.dg-selectable::before,\r\n &.dg-actions::before {\r\n padding: 0;\r\n }\r\n &.dg-selectable label {\r\n padding: 5px;\r\n }\r\n &[role=\"gridcell\"] {\r\n min-height: 35px;\r\n width: auto;\r\n }\r\n &[data-name]::before {\r\n height: 100%;\r\n }\r\n &.dg-actions {\r\n padding-left: inherit;\r\n width: inherit;\r\n }\r\n }\r\n .dg-actions button {\r\n width: inherit !important;\r\n }\r\n tr {\r\n &.dg-head-columns {\r\n padding: 0;\r\n width: calc(100% - var(--responsive-width) - var(--padding) * 4);\r\n\r\n th[role=\"columnheader button\"] {\r\n padding: 0.36em 1.3em 0.36em 0.75em;\r\n }\r\n }\r\n &.dg-head-filters {\r\n background: transparent;\r\n vertical-align: top;\r\n padding: 0;\r\n width: calc(100% - (100% - var(--responsive-width) - var(--padding) * 4));\r\n }\r\n }\r\n .dg-head-filters th input:not([type=\"checkbox\"], [type=\"radio\"]) {\r\n height: 2.25em;\r\n }\r\n .dg-head-filters th.dg-selectable {\r\n background: transparent;\r\n }\r\n .dg-head-filters th.dg-selectable label::before {\r\n content: \"Column Filters\";\r\n }\r\n }\r\n}\r\n"]} \ No newline at end of file diff --git a/dist/data-grid.js.map b/dist/data-grid.js.map index e7582e3..a78c839 100644 --- a/dist/data-grid.js.map +++ b/dist/data-grid.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/utils/camelize.js", "../src/utils/normalizeData.js", "../src/utils/shortcuts.js", "../src/core/base-element.js", "../src/utils/addSelectOption.js", "../src/utils/appendParamsToUrl.js", "../src/utils/convertArray.js", "../src/utils/elementOffset.js", "../src/utils/interpolate.js", "../src/utils/getTextWidth.js", "../src/utils/randstr.js", "../src/data-grid.js", "../src/core/base-plugin.js", "../src/plugins/column-resizer.js", "../src/utils/getParentElement.js", "../src/plugins/context-menu.js", "../src/plugins/draggable-headers.js", "../src/plugins/touch-support.js", "../src/plugins/selectable-rows.js", "../src/plugins/fixed-height.js", "../src/plugins/autosize-column.js", "../src/utils/debounce.js", "../src/plugins/responsive-grid.js", "../src/plugins/row-actions.js", "../src/plugins/editable-column.js", "../data-grid.js"], - "sourcesContent": ["/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nexport default function camelize(str) {\r\n return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());\r\n}\r\n", "/**\r\n * Parse data attribute and return properly typed data\r\n * @param {String} v\r\n * @returns {any}\r\n */\r\nexport default function normalizeData(v) {\r\n // Bool\r\n if (v === \"true\") {\r\n return true;\r\n }\r\n if (v === \"false\") {\r\n return false;\r\n }\r\n // Null or empty\r\n if (v === \"\" || v === \"null\") {\r\n return null;\r\n }\r\n // Numeric attributes\r\n if (v === Number(v).toString()) {\r\n return Number(v);\r\n }\r\n // Only attempt json parsing for array or objects\r\n if (v && [\"[\", \"{\"].includes(v.substring(0, 1))) {\r\n try {\r\n // In case we have only single quoted values, like ['one', 'two', 'three']\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(decodeURIComponent(v));\r\n } catch {\r\n console.error(\"Failed to parse \" + v);\r\n return {};\r\n }\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @typedef FlexibleHTMLProps\r\n * @property {boolean} [checked] (HTMLInputElement)\r\n * @property {string} [value] (HTMLInputElement)\r\n * @property {number} [rowHeight] (HTMLTableRowElement)\r\n *\r\n * A flexible type HTMLElement type that does not require using instanceof all over the place\r\n * Make sure that your selector is indeed valid\r\n * Only includes most commons props\r\n * @typedef {HTMLElement & FlexibleHTMLProps} FlexibleHTMLElement\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {HTMLElement&HTMLInputElement&HTMLTableRowElement} MixedHTMLElement\r\n */\r\n\r\n/**\r\n * @typedef FlexibleEventProps\r\n * @property {FlexibleHTMLElement} target\r\n * @property {FlexibleHTMLElement} currentTarget\r\n * @property {DataTransfer} [dataTransfer] (DragEvent)\r\n * @property {number} [clientX] (MouseEvent)\r\n * @property {number} [clientY] (MouseEvent)\r\n *\r\n * @typedef {Event & FlexibleEventProps} FlexibleEvent\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {Event&MouseEvent&InputEvent&DragEvent&FocusEvent&KeyboardEvent&PointerEvent} MixedEvent\r\n */\r\n\r\n/**\r\n * @callback FlexibleListener\r\n * @param {FlexibleEvent} event\r\n */\r\n\r\nclass FlexibleEventListenerObject {\r\n /**\r\n * @param {FlexibleEvent} e\r\n */\r\n handleEvent(e) {}\r\n}\r\n\r\nconst supportedPassiveTypes = [\r\n \"scroll\",\r\n \"wheel\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n \"touchenter\",\r\n \"touchend\",\r\n \"touchleave\",\r\n \"mouseout\",\r\n \"mouseleave\",\r\n \"mouseup\",\r\n \"mousedown\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mousewheel\",\r\n \"mouseover\",\r\n];\r\n\r\n/**\r\n * Automatically set passive options based on type\r\n * @param {string} type\r\n * @returns {AddEventListenerOptions}\r\n */\r\nfunction passiveOpts(type) {\r\n if (supportedPassiveTypes.includes(type)) {\r\n return { passive: true };\r\n }\r\n return {};\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {any}\r\n */\r\nexport function getAttribute(el, name) {\r\n return el.getAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasAttribute(el, name) {\r\n return el.hasAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @param {any} v\r\n * @param {Boolean} check Prevent setting if attribute is already there\r\n */\r\nexport function setAttribute(el, name, v = \"\", check = false) {\r\n if (check && hasAttribute(el, name)) return;\r\n el.setAttribute(name, \"\" + v);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeAttribute(el, name) {\r\n if (hasAttribute(el, name)) {\r\n el.removeAttribute(name);\r\n }\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function on(el, type, listener) {\r\n el.addEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function off(el, type, listener) {\r\n el.removeEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function one(el, type, listener) {\r\n el.addEventListener(type, listener, {\r\n once: true,\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {String} name\r\n * @param {any} data\r\n * @param {Boolean} bubbles\r\n */\r\nexport function dispatch(el, name, data = {}, bubbles = false) {\r\n let opts = {};\r\n if (bubbles) {\r\n opts.bubbles = true;\r\n }\r\n if (data) {\r\n opts.detail = data;\r\n }\r\n el.dispatchEvent(new CustomEvent(name, opts));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasClass(el, name) {\r\n return el.classList.contains(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function addClass(el, name) {\r\n el.classList.add(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeClass(el, name) {\r\n el.classList.remove(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function toggleClass(el, name) {\r\n el.classList.toggle(name);\r\n}\r\n\r\n/**\r\n * @param {String|HTMLElement} selector\r\n * @param {HTMLElement|Document} base\r\n * @returns {FlexibleHTMLElement|null}\r\n */\r\nexport function $(selector, base = document) {\r\n if (selector instanceof HTMLElement) {\r\n return selector;\r\n }\r\n return base.querySelector(selector);\r\n}\r\n\r\n/**\r\n * @param {String} selector\r\n * @param {Element|Document} base\r\n * @returns {Array}\r\n */\r\nexport function $$(selector, base = document) {\r\n return Array.from(base.querySelectorAll(selector));\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped element\r\n * For actual type, prefer use of el.querySelector\r\n * @param {HTMLElement} el\r\n * @param {String|HTMLElement} selector\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function find(el, selector) {\r\n return $(selector, el);\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped elements\r\n * For actual type, prefer use of el.querySelectorAll\r\n * @param {Element} el\r\n * @param {String} selector\r\n * @returns {Array}\r\n */\r\nexport function findAll(el, selector) {\r\n return $$(selector, el);\r\n}\r\n\r\n/**\r\n * @param {*} el\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function el(el) {\r\n return el;\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K} tagName\r\n * @param {HTMLElement} parent\r\n * @returns {HTMLElementTagNameMap[K]}\r\n */\r\nexport function ce(tagName, parent = null) {\r\n const el = document.createElement(tagName);\r\n if (parent) {\r\n parent.appendChild(el);\r\n }\r\n return el;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} newNode\r\n * @param {HTMLElement} existingNode\r\n */\r\nexport function insertAfter(newNode, existingNode) {\r\n existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);\r\n}\r\n", "import camelize from \"../utils/camelize.js\";\r\nimport normalizeData from \"../utils/normalizeData.js\";\r\nimport { dispatch, getAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Base element that does not contain any specific logic\r\n * related to this project but makes HTMLElemnt usable\r\n */\r\nclass BaseElement extends HTMLElement {\r\n /**\r\n * @param {Object} options\r\n */\r\n constructor(options = {}) {\r\n super();\r\n this.options = Object.assign({}, this.defaultOptions, this.normalizedDataset, options);\r\n\r\n this.log(\"constructor\");\r\n\r\n this.fireEvents = true;\r\n this._ready();\r\n\r\n this.log(\"ready\");\r\n }\r\n\r\n get defaultOptions() {\r\n return {};\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @returns {any}\r\n */\r\n getOption(opt) {\r\n return this.options[opt];\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @param {any} v\r\n */\r\n setOption(opt, v) {\r\n setAttribute(this, `data-${opt}`, v);\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n */\r\n toggleOption(opt) {\r\n setAttribute(this, `data-${opt}`, !this.getOption(opt));\r\n }\r\n\r\n get normalizedDataset() {\r\n let data = { ...this.dataset };\r\n for (var key in data) {\r\n data[key] = normalizeData(data[key]);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * @returns {String}\r\n */\r\n static template() {\r\n return \"\";\r\n }\r\n\r\n /**\r\n * This is called at the end of constructor. Extend in subclass if needed.\r\n */\r\n _ready() {}\r\n\r\n /**\r\n * @param {String|Error} message\r\n */\r\n log(message) {\r\n if (this.options.debug) {\r\n console.log(\"[\" + getAttribute(this, \"id\") + \"] \" + message);\r\n }\r\n }\r\n\r\n /**\r\n * Handle events within the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * This is called when connected. Extend in subclass if needed.\r\n */\r\n _connected() {}\r\n\r\n connectedCallback() {\r\n // ensure whenDefined callbacks run first\r\n setTimeout(() => {\r\n this.log(\"connectedCallback\");\r\n\r\n // Append only when labels had the opportunity to be set\r\n // Don't use shadow dom as it makes theming super hard\r\n const template = document.createElement(\"template\");\r\n // @ts-ignore\r\n template.innerHTML = this.constructor.template();\r\n this.appendChild(template.content.cloneNode(true));\r\n\r\n this._connected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"connected\");\r\n }, 0);\r\n }\r\n\r\n /**\r\n * This is called when disconnected. Extend in subclass if needed.\r\n */\r\n _disconnected() {}\r\n\r\n disconnectedCallback() {\r\n this.log(\"disconnectedCallback\");\r\n this._disconnected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"disconnected\");\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#a-props-like-accessor\r\n * @returns {Object}\r\n */\r\n get transformAttributes() {\r\n return {};\r\n }\r\n\r\n /**\r\n * This is only meant to work with data attributes\r\n * This allows us to have properties that reflect automatically in the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dataset-attributes\r\n * @param {String} attributeName\r\n * @param {String} oldValue\r\n * @param {String} newValue\r\n */\r\n attributeChangedCallback(attributeName, oldValue, newValue) {\r\n // It didn't change\r\n if (oldValue === newValue) {\r\n return;\r\n }\r\n\r\n this.log(\"attributeChangedCallback: \" + attributeName);\r\n\r\n let isOption = false;\r\n const transformer = this.transformAttributes[attributeName] ?? normalizeData;\r\n\r\n // Data attributes are mapped to options while other attributes are mapped as properties\r\n if (attributeName.indexOf(\"data-\") === 0) {\r\n attributeName = attributeName.slice(5);\r\n isOption = true;\r\n }\r\n attributeName = camelize(attributeName);\r\n if (isOption) {\r\n this.options[attributeName] = transformer(newValue);\r\n } else {\r\n this[attributeName] = transformer(newValue);\r\n }\r\n\r\n // Fire internal event\r\n if (this.fireEvents && this[`${attributeName}Changed`]) {\r\n this[`${attributeName}Changed`]();\r\n }\r\n }\r\n}\r\n\r\nexport default BaseElement;\r\n", "/**\r\n * @param {HTMLSelectElement} el\r\n * @param {String} value\r\n * @param {String} label\r\n * @param {Boolean} checked\r\n */\r\nexport default function addSelectOption(el, value, label, checked = false) {\r\n let opt = document.createElement(\"option\");\r\n opt.value = \"\" + value;\r\n if (checked) {\r\n opt.selected = true;\r\n }\r\n opt.label = label;\r\n el.appendChild(opt);\r\n}\r\n", "/**\r\n * @param {URL} url\r\n * @param {Object} params\r\n */\r\nexport default function appendParamsToUrl(url, params = {}) {\r\n Object.keys(params).forEach((key) => {\r\n if (Array.isArray(params[key])) {\r\n // @ts-ignore\r\n Object.keys(params[key]).forEach((k) => url.searchParams.append(isNaN(k) ? `${key}[${k}]` : key, params[key][k]));\r\n } else {\r\n url.searchParams.append(key, params[key]);\r\n }\r\n });\r\n}\r\n", "/**\r\n * Force value as arrays\r\n * @param {String|Array} v\r\n * @returns {Array}\r\n */\r\nexport default function convertArray(v) {\r\n if (typeof v === \"string\") {\r\n if (v[0] === \"[\") {\r\n // \"['my', 'value']\" would fail as a json\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(v);\r\n }\r\n\r\n return v.split(\",\");\r\n }\r\n if (!Array.isArray(v)) {\r\n console.error(\"Invalid array\", v);\r\n return [];\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @returns {Object}\r\n */\r\nexport default function elementOffset(el) {\r\n var rect = el.getBoundingClientRect(),\r\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\r\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\r\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\r\n}\r\n", "/**\r\n * Replace element within {} by their data value\r\n * @param {String} str\r\n * @param {Object} data\r\n * @returns {String}\r\n */\r\nexport default function interpolate(str, data) {\r\n return str.replace(/\\{([^}]+)?\\}/g, function ($1, $2) {\r\n return data[$2];\r\n });\r\n}\r\n", "/**\r\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\r\n * Getting computed styles only works for dom that are added in the dom\r\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\r\n * @param {String} text The text to be rendered.\r\n * @param {Element} el Target element (defaults to body)\r\n * @param {Boolean} withPadding Include padding on element\r\n * @returns {Number}\r\n */\r\nexport default function getTextWidth(text, el = document.body, withPadding = false) {\r\n if (!el) {\r\n el = document.createElement(\"div\");\r\n }\r\n const styles = window.getComputedStyle(el);\r\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\r\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\r\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\r\n\r\n let padding = 0;\r\n if (withPadding) {\r\n const paddingLeft = styles.getPropertyValue(\"padding-left\") || \"0\";\r\n const paddingRight = styles.getPropertyValue(\"padding-right\") || \"0\";\r\n padding = parseInt(paddingLeft) + parseInt(paddingRight);\r\n }\r\n\r\n // re-use canvas object for better performance\r\n // @ts-ignore\r\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement(\"canvas\"));\r\n const context = canvas.getContext(\"2d\");\r\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\r\n const metrics = context.measureText(text);\r\n return parseInt(metrics.width) + padding;\r\n}\r\n", "/**\r\n * @param {String} prefix\r\n * @returns {String}\r\n */\r\nexport default function randstr(prefix) {\r\n return Math.random()\r\n .toString(36)\r\n .replace(\"0.\", prefix || \"\");\r\n}\r\n", "/**\n * Data Grid Web component\n *\n * Credits for inspiration\n * @link https://github.com/riverside/zino-grid\n */\n\"use strict\";\n\nimport BaseElement from \"./core/base-element.js\";\nimport addSelectOption from \"./utils/addSelectOption.js\";\nimport appendParamsToUrl from \"./utils/appendParamsToUrl.js\";\nimport camelize from \"./utils/camelize.js\";\nimport convertArray from \"./utils/convertArray.js\";\nimport elementOffset from \"./utils/elementOffset.js\";\nimport interpolate from \"./utils/interpolate.js\";\nimport getTextWidth from \"./utils/getTextWidth.js\";\nimport randstr from \"./utils/randstr.js\";\nimport {\n dispatch,\n find,\n findAll,\n hasClass,\n removeAttribute,\n getAttribute,\n setAttribute,\n addClass,\n toggleClass,\n on,\n} from \"./utils/shortcuts.js\";\n\n/**\n * Column definition\n * @typedef Column\n * @property {String} field - the key in the data\n * @property {String} title - the title to display in the header (defaults to \"field\" if not set)\n * @property {Number} width - the width of the column (auto otherwise)\n * @property {String} class - class to set on the column (target body or header with th.class or td.class)\n * @property {String} attr - don't render the column and set a matching attribute on the row with the value of the field\n * @property {Boolean} hidden - hide the column\n * @property {Boolean} noSort - allow disabling sort for a given column\n * @property {String} format - custom data formatting\n * @property {String} transform - custom value transformation\n * @property {Boolean} editable - replace with input (EditableColumn module)\n * @property {Number} responsive - the higher the value, the sooner it will be hidden, disable with 0 (ResponsiveGrid module)\n * @property {Boolean} responsiveHidden - hidden through responsive module (ResponsiveGrid module)\n */\n\n/**\n * Row action\n * @typedef Action\n * @property {String} title - the title of the button\n * @property {String} name - the name of the action\n * @property {String} class - the class for the button\n * @property {String} url - link for the action\n * @property {String} html - custom button data\n * @property {Boolean} confirm - needs confirmation\n * @property {Boolean} default - is the default row action\n */\n\n/** @typedef {import('./plugins/autosize-column').default} AutosizeColumn */\n/** @typedef {import('./plugins/column-resizer').default} ColumnResizer */\n/** @typedef {import('./plugins/context-menu').default} ContextMenu */\n/** @typedef {import('./plugins/draggable-headers').default} DraggableHeaders */\n/** @typedef {import('./plugins/editable-column').default} EditableColumn */\n/** @typedef {import('./plugins/fixed-height').default} FixedHeight */\n/** @typedef {import('./plugins/responsive-grid').default} ResponsiveGrid */\n/** @typedef {import('./plugins/row-actions').default} RowActions */\n/** @typedef {import('./plugins/selectable-rows').default} SelectableRows */\n/** @typedef {import('./plugins/touch-support').default} TouchSupport */\n\n/**\n * These plugins are all optional\n * @typedef {Object} Plugins\n * @property {ColumnResizer} [ColumnResizer] resize handlers in the headers\n * @property {ContextMenu} [ContextMenu] menu to show/hide columns\n * @property {DraggableHeaders} [DraggableHeaders] draggable headers columns\n * @property {EditableColumn} [EditableColumn] draggable headers columns\n * @property {TouchSupport} [TouchSupport] touch swipe\n * @property {SelectableRows} [SelectableRows] create a column with checkboxes to select rows\n * @property {FixedHeight} [FixedHeight] allows having fixed height tables\n * @property {AutosizeColumn} [AutosizeColumn] compute ideal width based on column content\n * @property {ResponsiveGrid} [ResponsiveGrid] hide/show column on the fly\n * @property {RowActions} [RowActions] add action on rows\n */\n\n/**\n * Parameters to pass along or receive from the server\n * @typedef ServerParams\n * @property {String} serverParams.start\n * @property {String} serverParams.length\n * @property {String} serverParams.search\n * @property {String} serverParams.sort\n * @property {String} serverParams.sortDir\n * @property {String} serverParams.dataKey\n * @property {String} serverParams.errorKey\n * @property {String} serverParams.metaKey\n * @property {String} serverParams.metaTotalKey\n * @property {String} serverParams.metaFilteredKey\n * @property {String} serverParams.optionsKey\n * @property {String} serverParams.paramsKey\n */\n\n/**\n * Available data grid options, plugins included\n * @typedef Options\n * @property {?String} id Custom id for the grid\n * @property {?String} url An URL with data to display in JSON format\n * @property {Boolean} debug Log actions in DevTools console\n * @property {Boolean} filter Allows a filtering functionality\n * @property {Boolean} sort Allows a sort by column functionality\n * @property {String} defaultSort Default sort field if sorting is enabled\n * @property {Boolean} server Is a server side powered grid\n * @property {ServerParams} serverParams Describe keys passed to the server backend\n * @property {String} dir Dir\n * @property {Array} perPageValues Available per page options\n * @property {Column[]} columns Available columns\n * @property {Number} defaultPage Starting page\n * @property {Number} perPage Number of records displayed per page\n * @property {Boolean} expand Allow cell content to spawn over multiple lines\n * @property {Action[]} actions Row actions (RowActions module)\n * @property {Boolean} collapseActions Group actions (RowActions module)\n * @property {Boolean} resizable Make columns resizable (ColumnResizer module)\n * @property {Boolean} selectable Allow selecting rows with a checkbox (SelectableRows module)\n * @property {Boolean} selectVisibleOnly Select all only selects visible rows (SelectableRows module)\n * @property {Boolean} autosize Compute column sizes based on given data (Autosize module)\n * @property {Boolean} autoheight Adjust height so that it matches table size (FixedHeight module)\n * @property {Boolean} menu Right click menu on column headers (ContextMenu module)\n * @property {Boolean} reorder Allows a column reordering functionality (DraggableHeaders module)\n * @property {Boolean} responsive Change display mode on small screens (ResponsiveGrid module)\n * @property {Boolean} responsiveToggle Show toggle column (ResponsiveGrid module)\n */\n\n/**\n * Available labels that can be translated\n * @typedef Labels\n * @property {String} itemsPerPage\n * @property {String} gotoPage\n * @property {String} gotoFirstPage\n * @property {String} gotoPrevPage\n * @property {String} gotoNextPage\n * @property {String} gotoLastPage\n * @property {String} of\n * @property {String} items\n * @property {String} resizeColumn\n * @property {String} noData\n * @property {String} areYouSure\n */\n\n/**\n * List of registered plugins\n * @type {Plugins}\n */\nlet plugins = {};\n\n/**\n * @type {Labels}\n */\nlet labels = {\n itemsPerPage: \"Items per page\",\n gotoPage: \"Go to page\",\n gotoFirstPage: \"Go to first page\",\n gotoPrevPage: \"Go to previous page\",\n gotoNextPage: \"Go to next page\",\n gotoLastPage: \"Go to last page\",\n of: \"of\",\n items: \"items\",\n resizeColumn: \"Resize column\",\n noData: \"No data\",\n areYouSure: \"Are you sure?\",\n};\n\n/**\n * Column definition will update some props on the html element\n * @param {HTMLElement} el\n * @param {Column} column\n */\nfunction applyColumnDefinition(el, column) {\n if (column.width) {\n setAttribute(el, \"width\", column.width);\n }\n if (column.class) {\n addClass(el, column.class);\n }\n if (column.hidden) {\n setAttribute(el, \"hidden\", \"\");\n if (column.responsiveHidden) {\n addClass(el, \"dg-responsive-hidden\");\n }\n }\n}\n\n/**\n */\nclass DataGrid extends BaseElement {\n _ready() {\n setAttribute(this, \"id\", this.options.id ?? randstr(\"el-\"), true);\n\n /**\n * The grid displays that data\n * @type {Array}\n */\n this.data = [];\n /**\n * We store the original data in this\n * @type {Array}\n */\n this.originalData = [];\n\n // Make the IDE happy\n /**\n * @type {Options}\n */\n this.options = this.options || this.defaultOptions;\n\n // Init values\n this.fireEvents = false;\n this.page = this.options.defaultPage || 1;\n this.pages = 0;\n this.meta = {};\n /**\n * @type {Plugins}\n */\n this.plugins = {};\n // Init plugins\n for (const [pluginName, pluginClass] of Object.entries(plugins)) {\n // @ts-ignore until we can set typeof import ...\n this.plugins[pluginName] = new pluginClass(this);\n }\n\n // Expose options as observed attributes in the dom\n // Do it when fireEvents is disabled to avoid firing change callbacks\n for (const attr of DataGrid.observedAttributes) {\n if (attr.indexOf(\"data-\") === 0) {\n setAttribute(this, attr, this.options[camelize(attr.slice(5))]);\n }\n }\n }\n\n static template() {\n return `\n\n \n \n \n \n \n \n \n \n \n \n \n
\n`;\n }\n\n /**\n * @returns {Labels}\n */\n get labels() {\n return labels;\n }\n\n /**\n * @returns {Labels}\n */\n static getLabels() {\n return labels;\n }\n\n /**\n * @param {Object} v\n */\n static setLabels(v) {\n labels = Object.assign(labels, v);\n }\n\n /**\n * @returns {Column}\n */\n get defaultColumn() {\n return {\n field: \"\",\n title: \"\",\n width: 0,\n class: \"\",\n attr: \"\",\n hidden: false,\n editable: false,\n noSort: false,\n responsive: 1,\n responsiveHidden: false,\n format: \"\",\n transform: \"\",\n };\n }\n\n /**\n * @returns {Options}\n */\n get defaultOptions() {\n return {\n id: null,\n url: null,\n perPage: 10,\n debug: false,\n filter: false,\n menu: false,\n sort: false,\n server: false,\n serverParams: {\n start: \"start\",\n length: \"length\",\n search: \"search\",\n sort: \"sort\",\n sortDir: \"sortDir\",\n dataKey: \"data\",\n errorKey: \"error\",\n metaKey: \"meta\",\n metaTotalKey: \"total\",\n metaFilteredKey: \"filtered\",\n optionsKey: \"options\",\n paramsKey: \"params\",\n },\n defaultSort: \"\",\n reorder: false,\n dir: \"ltr\",\n perPageValues: [10, 25, 50, 100, 250],\n columns: [],\n actions: [],\n collapseActions: false,\n selectable: false,\n selectVisibleOnly: true,\n defaultPage: 1,\n resizable: false,\n autosize: true,\n expand: false,\n autoheight: true,\n responsive: false,\n responsiveToggle: true,\n };\n }\n\n /**\n * @param {Plugins} list\n */\n static registerPlugins(list) {\n plugins = list;\n }\n\n /**\n * @param {String} plugin\n */\n static unregisterPlugins(plugin = null) {\n if (plugin === null) {\n plugins = {};\n } else {\n delete plugins[plugin];\n }\n }\n\n /**\n * @returns {Plugins}\n */\n static registeredPlugins() {\n return plugins;\n }\n\n /**\n * @param {Object|Array} columns\n * @returns {Column[]}\n */\n convertColumns(columns) {\n let cols = [];\n // Convert key:value objects to actual columns\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\n Object.keys(columns).forEach((key) => {\n let col = Object.assign({}, this.defaultColumn);\n col.title = columns[key];\n col.field = key;\n cols.push(col);\n });\n } else {\n columns.forEach((item) => {\n let col = Object.assign({}, this.defaultColumn);\n if (typeof item === \"string\") {\n col.title = item;\n col.field = item;\n } else if (typeof item === \"object\") {\n col = Object.assign(col, item);\n if (!col.field) {\n console.error(\"Invalid column definition\", item);\n }\n if (!col.title) {\n col.title = col.field;\n }\n } else {\n console.error(\"Column definition must be a string or an object\");\n }\n cols.push(col);\n });\n }\n return cols;\n }\n\n /**\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\n * @returns {Array}\n */\n static get observedAttributes() {\n return [\n \"page\",\n \"data-filter\",\n \"data-sort\",\n \"data-debug\",\n \"data-reorder\",\n \"data-menu\",\n \"data-selectable\",\n \"data-url\",\n \"data-per-page\",\n \"data-responsive\",\n ];\n }\n\n get transformAttributes() {\n return {\n columns: (v) => this.convertColumns(convertArray(v)),\n actions: (v) => convertArray(v),\n defaultPage: (v) => parseInt(v),\n perPage: (v) => parseInt(v),\n };\n }\n\n get page() {\n return parseInt(this.getAttribute(\"page\"));\n }\n\n set page(val) {\n setAttribute(this, \"page\", this.constrainPageValue(val));\n }\n\n urlChanged() {\n this.loadData().then(() => {\n this.configureUi();\n });\n }\n\n constrainPageValue(v) {\n if (this.pages < v) {\n v = this.pages;\n }\n if (v < 1 || !v) {\n v = 1;\n }\n return v;\n }\n\n fixPage() {\n this.pages = this.totalPages();\n this.page = this.constrainPageValue(this.page);\n\n // Show current page in input\n setAttribute(this.inputPage, \"max\", this.pages);\n this.inputPage.value = \"\" + this.page;\n this.inputPage.disabled = this.pages === 1;\n }\n\n pageChanged() {\n this.reload();\n }\n\n responsiveChanged() {\n if (!this.plugins.ResponsiveGrid) {\n return;\n }\n if (this.options.responsive) {\n this.plugins.ResponsiveGrid.observe();\n } else {\n this.plugins.ResponsiveGrid.unobserve();\n }\n }\n\n menuChanged() {\n this.renderHeader();\n }\n\n /**\n * This is the callback for the select control\n */\n changePerPage() {\n this.options.perPage = parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value);\n this.perPageChanged();\n }\n\n /**\n * This is the actual event triggered on attribute change\n */\n perPageChanged() {\n // Refresh UI\n if (this.options.perPage !== parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value)) {\n this.perPageValuesChanged();\n }\n // Make sure current page is still valid\n let updatePage = this.page;\n while (updatePage > 1 && this.page * this.options.perPage > this.totalRecords()) {\n updatePage--;\n }\n if (updatePage != this.page) {\n // Triggers pageChanged, which will trigger reload\n this.page = updatePage;\n } else {\n // Simply reload current page\n this.reload(() => {\n // Preserve distance between top of page and select control if no fixed height\n if (!this.plugins.FixedHeight || !this.plugins.FixedHeight.hasFixedHeight) {\n this.selectPerPage.scrollIntoView();\n }\n });\n }\n }\n\n dirChanged() {\n setAttribute(this, \"dir\", this.options.dir);\n }\n\n defaultSortChanged() {\n this.sortChanged();\n }\n\n /**\n * Populate the select dropdown according to options\n */\n perPageValuesChanged() {\n if (!this.selectPerPage) {\n return;\n }\n while (this.selectPerPage.lastChild) {\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\n }\n this.options.perPageValues.forEach((v) => {\n addSelectOption(this.selectPerPage, v, v, v === this.options.perPage);\n });\n }\n\n _connected() {\n /**\n * @type {HTMLTableElement}\n */\n this.table = this.querySelector(\"table\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnFirst = this.querySelector(\".dg-btn-first\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnPrev = this.querySelector(\".dg-btn-prev\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnNext = this.querySelector(\".dg-btn-next\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnLast = this.querySelector(\".dg-btn-last\");\n /**\n * @type {HTMLSelectElement}\n */\n this.selectPerPage = this.querySelector(\".dg-select-per-page\");\n /**\n * @type {HTMLInputElement}\n */\n this.inputPage = this.querySelector(\".dg-input-page\");\n\n this.getFirst = this.getFirst.bind(this);\n this.getPrev = this.getPrev.bind(this);\n this.getNext = this.getNext.bind(this);\n this.getLast = this.getLast.bind(this);\n this.changePerPage = this.changePerPage.bind(this);\n this.gotoPage = this.gotoPage.bind(this);\n\n this.btnFirst.addEventListener(\"click\", this.getFirst);\n this.btnPrev.addEventListener(\"click\", this.getPrev);\n this.btnNext.addEventListener(\"click\", this.getNext);\n this.btnLast.addEventListener(\"click\", this.getLast);\n this.selectPerPage.addEventListener(\"change\", this.changePerPage);\n this.inputPage.addEventListener(\"input\", this.gotoPage);\n\n Object.values(this.plugins).forEach((plugin) => {\n plugin.connected();\n });\n\n // Display even if we don't have data\n this.dirChanged();\n this.perPageValuesChanged();\n\n this.loadData().finally(() => {\n this.configureUi();\n\n this.sortChanged();\n this.filterChanged();\n this.reorderChanged();\n\n this.dirChanged();\n this.perPageValuesChanged();\n this.pageChanged();\n\n this.classList.add(\"dg-initialized\");\n this.fireEvents = true; // We can now fire attributeChangedCallback events\n\n this.log(\"initialized\");\n });\n }\n\n _disconnected() {\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\n this.btnNext.removeEventListener(\"click\", this.getNext);\n this.btnLast.removeEventListener(\"click\", this.getLast);\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage);\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\n\n Object.values(this.plugins).forEach((plugin) => {\n plugin.disconnected();\n });\n }\n\n /**\n * @param {string} field\n * @returns {Column}\n */\n getCol(field) {\n let found = null;\n this.options.columns.forEach((col) => {\n if (col.field == field) {\n found = col;\n }\n });\n return found;\n }\n\n getColProp(field, prop) {\n const c = this.getCol(field);\n return c ? c[prop] : null;\n }\n\n setColProp(field, prop, val) {\n const c = this.getCol(field);\n if (c) {\n c[prop] = val;\n }\n }\n\n visibleColumns() {\n return this.options.columns.filter((col) => {\n return !col.hidden;\n });\n }\n\n hiddenColumns() {\n return this.options.columns.filter((col) => {\n return col.hidden === true;\n });\n }\n\n showColumn(field, render = true) {\n this.setColProp(field, \"hidden\", false);\n\n // We need to render the whole table otherwise layout fixed won't do its job\n if (render) this.renderTable();\n\n dispatch(this, \"columnVisibility\", {\n col: field,\n visibility: \"visible\",\n });\n }\n\n hideColumn(field, render = true) {\n this.setColProp(field, \"hidden\", true);\n\n // We need to render the whole table otherwise layout fixed won't do its job\n if (render) this.renderTable();\n\n dispatch(this, \"columnVisibility\", {\n col: field,\n visibility: \"hidden\",\n });\n }\n\n /**\n * Returns the starting index of actual data\n * @returns {Number}\n */\n startColIndex() {\n let start = 1;\n if (this.options.selectable && this.plugins.SelectableRows) {\n start++;\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n start++;\n }\n return start;\n }\n\n /**\n * @returns {Boolean}\n */\n isSticky() {\n return this.hasAttribute(\"sticky\");\n }\n\n /**\n * @param {Boolean} visibleOnly\n * @returns {Number}\n */\n columnsLength(visibleOnly = false) {\n let len = 0;\n // One column per (visible) column\n this.options.columns.forEach((col) => {\n if (visibleOnly && col.hidden) {\n return;\n }\n if (!col.attr) {\n len++;\n }\n });\n // Add one col for selectable checkbox at the beginning\n if (this.options.selectable && this.plugins.SelectableRows) {\n len++;\n }\n // Add one col for actions at the end\n if (this.options.actions.length && this.plugins.RowActions) {\n len++;\n }\n // Add one col for the responsive toggle\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n len++;\n }\n return len;\n }\n\n /**\n * Global configuration and renderTable\n * This should be called after your data has been loaded\n */\n configureUi() {\n setAttribute(this.querySelector(\"table\"), \"aria-rowcount\", this.data.length);\n\n this.table.style.visibility = \"hidden\";\n this.renderTable();\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\n // Let the observer make the table visible\n } else {\n this.table.style.visibility = \"visible\";\n }\n\n // Store row height for later usage\n if (!this.rowHeight) {\n const tr = find(this, \"tbody tr\") || find(this, \"table tr\");\n if (tr) {\n this.rowHeight = tr.offsetHeight;\n }\n }\n }\n\n filterChanged() {\n const row = this.querySelector(\"thead tr.dg-head-filters\");\n if (this.options.filter) {\n removeAttribute(row, \"hidden\");\n } else {\n this.clearFilters();\n setAttribute(row, \"hidden\", \"\");\n }\n }\n\n reorderChanged() {\n const headers = findAll(this, \"thead tr.dg-head-columns th\");\n headers.forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.options.reorder && this.plugins.DraggableHeaders) {\n th.draggable = true;\n } else {\n th.removeAttribute(\"draggable\");\n }\n });\n }\n\n sortChanged() {\n this.log(\"toggle sort\");\n\n this.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n const fieldName = th.getAttribute(\"field\");\n if (th.classList.contains(\"dg-not-sortable\") || (!this.fireEvents && fieldName == this.options.defaultSort)) {\n return;\n }\n if (this.options.sort && !this.getColProp(fieldName, \"noSort\")) {\n setAttribute(th, \"aria-sort\", \"none\");\n } else {\n removeAttribute(th, \"aria-sort\");\n }\n });\n }\n\n selectableChanged() {\n this.renderTable();\n }\n\n addRow(row) {\n this.log(\"Add row\");\n this.originalData.push(row);\n this.data = this.originalData.slice();\n this.sortData();\n }\n\n /**\n * @param {any} value Value to remove. Defaults to last row.\n * @param {String} key The key of the item to remove. Defaults to first column\n */\n removeRow(value = null, key = null) {\n if (key === null) {\n key = this.options.columns[0][\"field\"];\n }\n if (value === null) {\n value = this.originalData[this.originalData.length - 1][key];\n }\n this.log(\"Removing \" + key + \":\" + value);\n for (let i = 0; i < this.originalData.length; i++) {\n if (this.originalData[i][key] === value) {\n this.originalData.splice(i, 1);\n break;\n }\n }\n this.data = this.originalData.slice();\n this.sortData();\n }\n\n /**\n * @param {String} key Return a specific key (eg: id) instead of the whole row\n * @returns {Array}\n */\n getSelection(key = null) {\n if (!this.plugins.SelectableRows) {\n return [];\n }\n return this.plugins.SelectableRows.getSelection(key);\n }\n\n getData() {\n return this.originalData;\n }\n\n clearData() {\n // Already empty\n if (this.data.length === 0) {\n return;\n }\n this.data = this.originalData = [];\n this.renderBody();\n }\n\n refresh(cb = null) {\n this.data = this.originalData = [];\n return this.reload(cb);\n }\n\n reload(cb = null) {\n this.log(\"reload\");\n\n // If the data was cleared, we need to render again\n const needRender = this.originalData.length === 0;\n this.fixPage();\n this.loadData().finally(() => {\n // If we load data from the server, we redraw the table body\n // Otherwise, we just need to paginate\n this.options.server || needRender ? this.renderBody() : this.paginate();\n if (cb) {\n cb();\n }\n });\n }\n\n /**\n * @returns {Promise}\n */\n loadData() {\n // We already have some data\n if (this.originalData.length) {\n // We don't use server side data\n if (!this.options.server || (this.options.server && !this.fireEvents)) {\n // if (!this.options.server) {\n this.log(\"skip loadData\");\n return new Promise((resolve) => {\n resolve();\n });\n }\n }\n this.log(\"loadData\");\n this.loading = true;\n this.classList.add(\"dg-loading\");\n return this.fetchData()\n .then((response) => {\n this.classList.remove(\"dg-loading\");\n this.loading = false;\n\n // We can get a straight array or an object\n if (Array.isArray(response)) {\n this.data = response;\n } else {\n // Object must contain data key\n if (response[this.options.serverParams.errorKey]) {\n this.querySelector(\"tbody\").setAttribute(\n \"data-empty\",\n response[this.options.serverParams.errorKey].replace(/^\\s+|\\r\\n|\\n|\\r$/g, \"\")\n );\n this.removeAttribute(\"data-url\");\n return;\n }\n if (!response[this.options.serverParams.dataKey]) {\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\n this.options.url = null;\n return;\n }\n\n // We may have a config object\n this.options = Object.assign(this.options, response[this.options.serverParams.optionsKey] ?? {});\n // It should return meta data (see metaFilteredKey)\n this.meta = response[this.options.serverParams.metaKey] ?? {};\n this.data = response[this.options.serverParams.dataKey];\n }\n this.originalData = this.data.slice();\n this.fixPage();\n\n // Make sure we have a proper set of columns\n if (this.options.columns.length === 0 && this.originalData.length) {\n this.options.columns = this.convertColumns(Object.keys(this.originalData[0]));\n } else {\n this.options.columns = this.convertColumns(this.options.columns);\n }\n })\n .catch((err) => {\n this.log(err);\n });\n }\n\n getFirst() {\n if (this.loading) {\n return;\n }\n this.page = 1;\n }\n\n getLast() {\n if (this.loading) {\n return;\n }\n this.page = this.pages;\n }\n\n getPrev() {\n if (this.loading) {\n return;\n }\n this.page = this.page - 1;\n }\n\n getNext() {\n if (this.loading) {\n return;\n }\n this.page = this.page + 1;\n }\n\n gotoPage(event) {\n if (event.type === \"keypress\") {\n const key = event.keyCode || event.key;\n if (key === 13 || key === \"Enter\") {\n event.preventDefault();\n } else {\n return;\n }\n }\n this.page = parseInt(this.inputPage.value);\n }\n\n getSort() {\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"field\");\n }\n return this.options.defaultSort;\n }\n\n getSortDir() {\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"aria-sort\") || \"\";\n }\n return \"\";\n }\n\n getFilters() {\n let filters = [];\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n filters[input.dataset.name] = input.value;\n });\n return filters;\n }\n\n clearFilters() {\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n input.value = \"\";\n });\n this.filterData();\n }\n\n filterData() {\n this.log(\"filter data\");\n\n this.page = 1;\n\n if (this.options.server) {\n this.reload();\n } else {\n this.data = this.originalData.slice();\n\n // Look for rows matching the filters\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n let value = input.value;\n if (value) {\n let name = input.dataset.name;\n this.data = this.data.filter((item) => {\n let str = item[name] + \"\";\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\n });\n }\n });\n this.pageChanged();\n\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (this.options.sort && col) {\n this.sortData();\n } else {\n this.renderBody();\n }\n }\n }\n\n /**\n * Data will be sorted then rendered using renderBody\n * @param {Element} col The column that was clicked or null to use current sort\n */\n sortData(col = null) {\n this.log(\"sort data\");\n\n // Early exit\n if (col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\n this.log(\"sorting prevented because column is not sortable\");\n return;\n }\n if (this.plugins.ColumnResizer && this.plugins.ColumnResizer.isResizing) {\n this.log(\"sorting prevented because resizing\");\n return;\n }\n if (this.loading) {\n this.log(\"sorting prevented because loading\");\n return;\n }\n\n // We clicked on a column, update sort state\n if (col !== null) {\n // Remove active sort if any\n const haveClasses = c => [\"dg-selectable\", \"dg-actions\", \"dg-responsive-toggle\"].includes(c);\n this.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\n // @ts-ignore\n if ([...th.classList].some(haveClasses)) {\n return;\n }\n if (th !== col) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n });\n\n // Set tristate col\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\n col.setAttribute(\"aria-sort\", \"ascending\");\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\n col.setAttribute(\"aria-sort\", \"descending\");\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\n col.setAttribute(\"aria-sort\", \"none\");\n }\n } else {\n // Or fetch current sort\n col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n }\n\n if (this.options.server) {\n // Reload data with updated sort\n this.loadData().finally(() => {\n this.renderBody();\n });\n } else {\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\n if (sort === \"none\") {\n let stack = [];\n\n // Restore order while keeping filters\n this.originalData.some((itemA) => {\n this.data.some((itemB) => {\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\n stack.push(itemB);\n return true;\n }\n return false;\n });\n return stack.length === this.data.length;\n });\n\n this.data = stack;\n } else {\n const field = col.getAttribute(\"field\");\n this.data.sort((a, b) => {\n if (!isNaN(a[field]) && !isNaN(b[field])) {\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\n }\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\n\n switch (true) {\n case valA > valB:\n return 1;\n case valA < valB:\n return -1;\n case valA === valB:\n return 0;\n }\n });\n }\n this.renderBody();\n }\n }\n\n fetchData() {\n if (!this.options.url) {\n return new Promise((resolve, reject) => reject(\"No url set\"));\n }\n\n let base = window.location.href;\n // Fix trailing slash if no extension is present\n if (!base.split(\"/\").pop().includes(\".\")) {\n base += base.endsWith(\"/\") ? \"\" : \"/\";\n }\n let url = new URL(this.options.url, base);\n let params = {\n r: Date.now(),\n };\n if (this.options.server) {\n // 0 based\n params[this.options.serverParams.start] = this.page - 1;\n params[this.options.serverParams.length] = this.options.perPage;\n params[this.options.serverParams.search] = this.getFilters();\n params[this.options.serverParams.sort] = this.getSort() || \"\";\n params[this.options.serverParams.sortDir] = this.getSortDir();\n\n // extra params ?\n if (this.meta[this.options.serverParams.paramsKey]) {\n params = Object.assign(params, this.meta[this.options.serverParams.paramsKey]);\n }\n }\n\n appendParamsToUrl(url, params);\n\n return fetch(url)\n .then((response) => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json();\n })\n .catch((err) => {\n return {\n error: err.message,\n };\n });\n }\n\n renderTable() {\n this.log(\"render table\");\n\n if (this.options.menu && this.plugins.ContextMenu) {\n this.plugins.ContextMenu.createMenu();\n }\n\n let sortedColumn;\n\n this.renderHeader();\n if (this.options.defaultSort) {\n // We can have a default sort even with sort disabled\n sortedColumn = this.querySelector(\"thead tr.dg-head-columns th[field='\" + this.options.defaultSort + \"']\");\n }\n\n if (sortedColumn) {\n this.sortData(sortedColumn);\n } else {\n this.renderBody();\n }\n\n this.renderFooter();\n }\n\n /**\n * Create table header\n * - One row for the column headers\n * - One row for the filters\n */\n renderHeader() {\n this.log(\"render header\");\n\n const thead = this.querySelector(\"thead\");\n this.createColumnHeaders(thead);\n this.createColumnFilters(thead);\n\n if (this.options.resizable && this.plugins.ColumnResizer) {\n this.plugins.ColumnResizer.renderResizer(labels.resizeColumn);\n }\n\n dispatch(this, \"headerRendered\");\n }\n\n renderFooter() {\n this.log(\"render footer\");\n\n const tfoot = this.querySelector(\"tfoot\");\n const td = tfoot.querySelector(\"td\");\n tfoot.removeAttribute(\"hidden\");\n setAttribute(td, \"colspan\", this.columnsLength(true));\n tfoot.style.display = \"\";\n }\n\n /**\n * Create the column headers based on column definitions and set options\n * @param {HTMLTableSectionElement} thead\n */\n createColumnHeaders(thead) {\n // @link https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively\n const availableWidth = this.clientWidth;\n const colMaxWidth = Math.round((availableWidth / this.columnsLength(true)) * 2);\n\n let idx = 0;\n let tr;\n\n // Create row\n tr = document.createElement(\"tr\");\n this.headerRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", \"1\");\n tr.setAttribute(\"class\", \"dg-head-columns\");\n\n // We need a real th from the dom to compute the size\n let sampleTh = thead.querySelector(\"tr.dg-head-columns th\");\n if (!sampleTh) {\n sampleTh = document.createElement(\"th\");\n thead.querySelector(\"tr\").appendChild(sampleTh);\n }\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createHeaderCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createHeaderCol(tr);\n }\n\n // Create columns\n idx = 0;\n let totalWidth = 0;\n this.options.columns.forEach((column) => {\n if (column.attr) {\n return;\n }\n const colIdx = idx + this.startColIndex();\n let th = document.createElement(\"th\");\n th.setAttribute(\"scope\", \"col\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\n th.setAttribute(\"id\", randstr(\"dg-col-\"));\n if (this.options.sort) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n th.setAttribute(\"field\", column.field);\n if (this.plugins.ResponsiveGrid && this.options.responsive) {\n setAttribute(th, \"data-responsive\", column.responsive || \"\");\n }\n // Make sure the header fits (+ add some room for sort icon if necessary)\n const computedWidth = getTextWidth(column.title, sampleTh, true) + 20;\n th.dataset.minWidth = \"\" + computedWidth;\n applyColumnDefinition(th, column);\n th.tabIndex = 0;\n th.textContent = column.title;\n\n let w = 0;\n // Autosize small based on first/last row ?\n // Take into account minWidth of the header and max available size based on col numbers\n if (this.options.autosize && this.plugins.AutosizeColumn) {\n const colAvailableWidth = Math.min(availableWidth - totalWidth, colMaxWidth);\n w = this.plugins.AutosizeColumn.computeSize(th, column, parseInt(th.dataset.minWidth), colAvailableWidth);\n } else {\n w = Math.max(parseInt(th.dataset.minWidth), parseInt(th.getAttribute(\"width\")));\n }\n\n setAttribute(th, \"width\", w);\n if (column.hidden) {\n th.setAttribute(\"hidden\", \"\");\n } else {\n totalWidth += w;\n }\n\n // Reorder columns with drag/drop\n if (this.options.reorder && this.plugins.DraggableHeaders) {\n this.plugins.DraggableHeaders.makeHeaderDraggable(th);\n }\n\n tr.appendChild(th);\n idx++;\n });\n\n // There is too much available width, and we want to avoid fixed layout to split remaining amount\n if (totalWidth < availableWidth) {\n const visibleCols = findAll(tr, \"th:not([hidden],.dg-not-resizable)\");\n if (visibleCols.length) {\n const lastCol = visibleCols[visibleCols.length - 1];\n removeAttribute(lastCol, \"width\");\n }\n }\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionHeader(tr);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\n\n // Once columns are inserted, we have an actual dom to query\n if (thead.offsetWidth > availableWidth) {\n this.log(`adjust width to fix size, ${thead.offsetWidth} > ${availableWidth}`);\n const scrollbarWidth = this.offsetWidth - this.clientWidth;\n let diff = thead.offsetWidth - availableWidth - scrollbarWidth;\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\n diff += scrollbarWidth;\n }\n // Remove diff for columns that can afford it\n const thWithWidth = findAll(tr, \"th[width]\");\n thWithWidth.forEach((th) => {\n if (hasClass(th, \"dg-not-resizable\")) {\n return;\n }\n if (diff <= 0) {\n return;\n }\n const actualWidth = parseInt(th.getAttribute(\"width\"));\n const minWidth = th.dataset.minWidth ? parseInt(th.dataset.minWidth) : 0;\n if (actualWidth > minWidth) {\n let newWidth = actualWidth - diff;\n if (newWidth < minWidth) {\n newWidth = minWidth;\n }\n diff -= actualWidth - newWidth;\n setAttribute(th, \"width\", newWidth);\n }\n });\n }\n\n // Context menu\n if (this.options.menu && this.plugins.ContextMenu) {\n this.plugins.ContextMenu.attachContextMenu();\n }\n\n // Sort col on click\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\n });\n\n setAttribute(this.querySelector(\"table\"), \"aria-colcount\", this.columnsLength(true));\n }\n\n createColumnFilters(thead) {\n let idx = 0;\n let tr;\n\n // Create row for filters\n tr = document.createElement(\"tr\");\n this.filterRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", \"2\");\n tr.setAttribute(\"class\", \"dg-head-filters\");\n if (!this.options.filter) {\n tr.setAttribute(\"hidden\", \"\");\n }\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createFilterCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createFilterCol(tr);\n }\n\n this.options.columns.forEach((column) => {\n if (column.attr) {\n return;\n }\n const colIdx = idx + this.startColIndex();\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + colIdx + \"']\");\n if (!relatedTh) {\n console.warn(\"Related th not found\", colIdx);\n return;\n }\n let th = document.createElement(\"th\");\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\n\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n // Allows binding filter to this column\n input.dataset.name = column.field;\n input.id = randstr(\"dg-filter-\");\n // Don't use aria-label as it triggers autocomplete\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\n if (!this.options.filter) {\n th.tabIndex = 0;\n } else {\n input.tabIndex = 0;\n }\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", \"\");\n }\n\n th.appendChild(input);\n tr.appendChild(th);\n idx++;\n });\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionFilter(tr);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\n\n // Filter content on enter\n tr.querySelectorAll(\"input\").forEach((input) => {\n input.addEventListener(\"keypress\", (e) => {\n const key = e.keyCode || e.key;\n if (key === 13 || key === \"Enter\") {\n this.filterData.call(this);\n }\n });\n });\n }\n\n /**\n * Render the data as rows in tbody\n * It will call paginate() at the end\n */\n renderBody() {\n this.log(\"render body\");\n let tr;\n let td;\n let idx;\n let tbody = document.createElement(\"tbody\");\n\n this.data.forEach((item, i) => {\n tr = document.createElement(\"tr\");\n setAttribute(tr, \"role\", \"row\");\n setAttribute(tr, \"hidden\", \"\");\n setAttribute(tr, \"aria-rowindex\", i + 1);\n tr.tabIndex = 0;\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createDataCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createDataCol(tr);\n }\n\n // Expandable\n if (this.options.expand) {\n tr.classList.add(\"dg-expandable\");\n\n on(tr, \"click\", (ev) => {\n if (this.plugins.ResponsiveGrid) {\n this.plugins.ResponsiveGrid.blockObserver();\n }\n toggleClass(ev.currentTarget, \"dg-expanded\");\n if (this.plugins.ResponsiveGrid) {\n this.plugins.ResponsiveGrid.unblockObserver();\n }\n });\n }\n\n idx = 0;\n this.options.columns.forEach((column) => {\n if (!column) {\n console.error(\"Empty column found!\", this.options.columns);\n }\n // It should be applied as an attr of the row\n if (column.attr) {\n if (item[column.field]) {\n // Special case if we try to write over the class attr\n if (column.attr === \"class\") {\n addClass(tr, item[column.field]);\n } else {\n tr.setAttribute(column.attr, item[column.field]);\n }\n }\n return;\n }\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", idx + this.startColIndex());\n applyColumnDefinition(td, column);\n // This is required for pure css responsive layout\n td.setAttribute(\"data-name\", column.title);\n td.tabIndex = -1;\n\n // Inline editing\n if (column.editable && this.plugins.EditableColumn) {\n this.plugins.EditableColumn.makeEditableInput(td, column, item, i);\n } else {\n const v = item[column.field] ?? \"\";\n let tv;\n // TODO: make this modular\n switch (column.transform) {\n case \"uppercase\":\n tv = v.toUpperCase();\n break;\n case \"lowercase\":\n tv = v.toLowerCase();\n break;\n default:\n tv = v;\n break;\n }\n if (column.format && tv) {\n td.innerHTML = interpolate(\n column.format,\n Object.assign(\n {\n _v: v,\n _tv: tv,\n },\n item\n )\n );\n } else {\n td.textContent = tv;\n }\n }\n tr.appendChild(td);\n idx++;\n });\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionRow(tr, item);\n }\n\n tbody.appendChild(tr);\n });\n\n tbody.setAttribute(\"role\", \"rowgroup\");\n\n // Keep data empty message\n const prev = this.querySelector(\"tbody\");\n tbody.setAttribute(\"data-empty\", prev.getAttribute(\"data-empty\"));\n this.querySelector(\"table\").replaceChild(tbody, prev);\n\n if (this.plugins.FixedHeight) {\n this.plugins.FixedHeight.createFakeRow();\n }\n\n this.paginate();\n\n if (this.plugins.SelectableRows) {\n this.plugins.SelectableRows.shouldSelectAll(tbody);\n }\n\n dispatch(this, \"bodyRendered\");\n }\n\n paginate() {\n this.log(\"paginate\");\n\n const total = this.totalRecords();\n const p = this.page || 1;\n\n let index;\n let high = p * this.options.perPage;\n let low = high - this.options.perPage + 1;\n const tbody = this.querySelector(\"tbody\");\n const tfoot = this.querySelector(\"tfoot\");\n\n if (high > total) {\n high = total;\n }\n if (!total) {\n low = 0;\n }\n\n // Display all rows within the set indexes\n // For server side paginated grids, we display everything\n // since the server is taking care of actual pagination\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\n if (this.options.server) {\n removeAttribute(tr, \"hidden\");\n return;\n }\n index = Number(getAttribute(tr, \"aria-rowindex\"));\n if (index > high || index < low) {\n setAttribute(tr, \"hidden\", \"\");\n } else {\n removeAttribute(tr, \"hidden\");\n }\n });\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.clearCheckboxes(tbody);\n }\n\n // Store default height and update styles if needed\n if (this.plugins.FixedHeight) {\n this.plugins.FixedHeight.updateFakeRow();\n }\n\n // Enable/disable buttons if shown\n if (this.btnFirst) {\n this.btnFirst.disabled = this.page <= 1;\n this.btnPrev.disabled = this.page <= 1;\n this.btnNext.disabled = this.page >= this.pages;\n this.btnLast.disabled = this.page >= this.pages;\n }\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\n tfoot.querySelector(\".dg-total\").textContent = \"\" + this.totalRecords();\n }\n\n /**\n * @returns {number}\n */\n totalPages() {\n return Math.ceil(this.totalRecords() / this.options.perPage);\n }\n\n /**\n * @returns {number}\n */\n totalRecords() {\n if (this.options.server) {\n return this.meta[this.options.serverParams.metaFilteredKey] || 0;\n }\n return this.data.length;\n }\n}\n\nexport default DataGrid;\n", "/** @typedef {import(\"../data-grid\").default} DataGrid */\r\n\r\nclass BasePlugin {\r\n /**\r\n * @param {DataGrid} grid\r\n */\r\n constructor(grid) {\r\n this.grid = grid;\r\n }\r\n\r\n connected() {}\r\n\r\n disconnected() {}\r\n\r\n /**\r\n * Handle events within the plugin\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n}\r\n\r\nexport default BasePlugin;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport elementOffset from \"../utils/elementOffset.js\";\r\nimport {\r\n addClass,\r\n dispatch,\r\n findAll,\r\n getAttribute,\r\n hasClass,\r\n off,\r\n on,\r\n removeAttribute,\r\n removeClass,\r\n setAttribute,\r\n} from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass ColumnResizer extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.isResizing = false;\r\n }\r\n\r\n /**\r\n * @param {String} resizeLabel\r\n */\r\n renderResizer(resizeLabel) {\r\n const grid = this.grid;\r\n const table = grid.table;\r\n const cols = findAll(grid, \"thead tr.dg-head-columns th\");\r\n\r\n cols.forEach((col) => {\r\n if (hasClass(col, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n // Create a resizer element\r\n const resizer = document.createElement(\"div\");\r\n addClass(resizer, \"dg-resizer\");\r\n resizer.ariaLabel = resizeLabel;\r\n\r\n // Add a resizer element to the column\r\n col.appendChild(resizer);\r\n\r\n // Handle resizing\r\n let startX = 0;\r\n let startW = 0;\r\n let remainingSpace = 0;\r\n let max = 0;\r\n\r\n const mouseMoveHandler = (e) => {\r\n if (e.clientX > max) {\r\n return;\r\n }\r\n const newWidth = startW + (e.clientX - startX);\r\n if (col.dataset.minWidth && newWidth > parseInt(col.dataset.minWidth)) {\r\n setAttribute(col, \"width\", newWidth);\r\n }\r\n };\r\n\r\n // When user releases the mouse, remove the existing event listeners\r\n const mouseUpHandler = () => {\r\n grid.log(\"resized column\");\r\n\r\n // Prevent accidental sorting if mouse is not over resize handler\r\n setTimeout(() => {\r\n this.isResizing = false;\r\n }, 0);\r\n\r\n removeClass(resizer, \"dg-resizer-active\");\r\n if (grid.options.reorder) {\r\n col.draggable = true;\r\n }\r\n col.style.overflow = \"hidden\";\r\n\r\n // Remove handlers\r\n off(document, \"mousemove\", mouseMoveHandler);\r\n off(document, \"mouseup\", mouseUpHandler);\r\n\r\n dispatch(grid, \"columnResized\", {\r\n col: getAttribute(col, \"field\"),\r\n width: getAttribute(col, \"width\"),\r\n });\r\n };\r\n\r\n // Otherwise it could sort the col\r\n on(resizer, \"click\", (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n on(resizer, \"mousedown\", (e) => {\r\n e.stopPropagation();\r\n\r\n this.isResizing = true;\r\n\r\n const target = e.target;\r\n const currentCols = findAll(grid, \"dg-head-columns th\");\r\n const visibleCols = currentCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n const columnIndex = visibleCols.findIndex((column) => column == target.parentNode);\r\n grid.log(\"resize column\");\r\n\r\n addClass(resizer, \"dg-resizer-active\");\r\n\r\n // Make sure we don't drag it\r\n removeAttribute(col, \"draggable\");\r\n\r\n // Allow overflow when resizing\r\n col.style.overflow = \"visible\";\r\n\r\n // Show full column height (-1 to avoid scrollbar)\r\n resizer.style.height = table.offsetHeight - 1 + \"px\";\r\n\r\n // Register initial data\r\n startX = e.clientX;\r\n startW = col.offsetWidth;\r\n\r\n remainingSpace = (visibleCols.length - columnIndex) * 30;\r\n max = elementOffset(target).left + grid.offsetWidth - remainingSpace;\r\n\r\n // Remove width from next columns to allow auto layout\r\n setAttribute(col, \"width\", startW);\r\n for (let j = 0; j < visibleCols.length; j++) {\r\n if (j > columnIndex) {\r\n removeAttribute(cols[j], \"width\");\r\n }\r\n }\r\n\r\n // Attach handlers\r\n on(document, \"mousemove\", mouseMoveHandler);\r\n on(document, \"mouseup\", mouseUpHandler);\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default ColumnResizer;\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @param {String} type\r\n * @param {String} prop\r\n * @returns {HTMLElement}\r\n */\r\nexport default function getParentElement(el, type, prop = \"nodeName\") {\r\n let parent = el;\r\n while (parent[prop] != type) {\r\n parent = parent.parentElement;\r\n }\r\n return parent;\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { find, off, on, removeAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Create a right click menu on the headers\r\n */\r\nclass ContextMenu extends BasePlugin {\r\n connected() {\r\n /**\r\n * @type {HTMLUListElement}\r\n */\r\n this.menu = this.grid.querySelector(\".dg-menu\");\r\n }\r\n disconnected() {\r\n if (this.grid.headerRow) {\r\n off(this.grid.headerRow, \"contextmenu\", this);\r\n }\r\n }\r\n\r\n attachContextMenu() {\r\n const grid = this.grid;\r\n on(grid.headerRow, \"contextmenu\", this);\r\n }\r\n\r\n onchange(e) {\r\n const grid = this.grid;\r\n const t = e.target;\r\n const field = t.dataset.name;\r\n if (t.checked) {\r\n grid.showColumn(field);\r\n } else {\r\n // Prevent hidding last\r\n if (grid.visibleColumns().length <= 1) {\r\n // Restore checkbox value\r\n t.checked = true;\r\n return;\r\n }\r\n grid.hideColumn(field);\r\n }\r\n }\r\n\r\n oncontextmenu(e) {\r\n e.preventDefault();\r\n const grid = this.grid;\r\n const target = getParentElement(e.target, \"THEAD\");\r\n const menu = this.menu;\r\n const rect = target.getBoundingClientRect();\r\n let x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n\r\n menu.style.top = `${y}px`;\r\n menu.style.left = `${x}px`;\r\n\r\n removeAttribute(menu, \"hidden\");\r\n if (x + 150 > rect.width) {\r\n x -= menu.offsetWidth;\r\n menu.style.left = `${x}px`;\r\n }\r\n\r\n const documentClickHandler = (e) => {\r\n if (!menu.contains(e.target)) {\r\n setAttribute(menu, \"hidden\", \"\");\r\n off(document, \"click\", documentClickHandler);\r\n }\r\n };\r\n on(document, \"click\", documentClickHandler);\r\n }\r\n createMenu() {\r\n const grid = this.grid;\r\n const menu = this.menu;\r\n while (menu.lastChild) {\r\n menu.removeChild(menu.lastChild);\r\n }\r\n menu.addEventListener(\"change\", this);\r\n grid.options.columns.forEach((col) => {\r\n if (col.attr) {\r\n return;\r\n }\r\n const li = document.createElement(\"li\");\r\n const label = document.createElement(\"label\");\r\n const checkbox = document.createElement(\"input\");\r\n setAttribute(checkbox, \"type\", \"checkbox\");\r\n setAttribute(checkbox, \"data-name\", col.field);\r\n if (!col.hidden) {\r\n checkbox.checked = true;\r\n }\r\n const text = document.createTextNode(col.title);\r\n\r\n label.appendChild(checkbox);\r\n label.appendChild(text);\r\n\r\n li.appendChild(label);\r\n menu.appendChild(li);\r\n });\r\n }\r\n}\r\n\r\nexport default ContextMenu;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport getParentElement from \"../utils/getParentElement.js\";\nimport { dispatch, findAll, getAttribute, on, setAttribute } from \"../utils/shortcuts.js\";\n\n/**\n * Allows to move headers\n */\nclass DraggableHeaders extends BasePlugin {\n /**\n * @param {HTMLTableCellElement} th\n */\n makeHeaderDraggable(th) {\n const grid = this.grid;\n th.draggable = true;\n on(th, \"dragstart\", (e) => {\n if (grid.plugins.ColumnResizer && grid.plugins.ColumnResizer.isResizing && e.preventDefault) {\n e.preventDefault();\n return;\n }\n grid.log(\"reorder col\");\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\n });\n on(th, \"dragover\", (e) => {\n if (e.preventDefault) {\n e.preventDefault();\n }\n e.dataTransfer.dropEffect = \"move\";\n return false;\n });\n on(th, \"drop\", (e) => {\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n const t = e.target;\n const target = getParentElement(t, \"TH\");\n const index = parseInt(e.dataTransfer.getData(\"text/plain\"));\n const targetIndex = parseInt(target.getAttribute(\"aria-colindex\"));\n\n if (index === targetIndex) {\n grid.log(\"reordered col stayed the same\");\n return;\n }\n grid.log(\"reordered col from \" + index + \" to \" + targetIndex);\n\n const offset = grid.startColIndex();\n const tmp = grid.options.columns[index - offset];\n grid.options.columns[index - offset] = grid.options.columns[targetIndex - offset];\n grid.options.columns[targetIndex - offset] = tmp;\n\n const swapNodes = (selector, el1) => {\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\n const el2 = grid.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\n setAttribute(el1, \"aria-colindex\", targetIndex);\n setAttribute(el2, \"aria-colindex\", index);\n const newNode = document.createElement(\"th\");\n el1.parentNode.insertBefore(newNode, el1);\n el2.parentNode.replaceChild(el1, el2);\n newNode.parentNode.replaceChild(el2, newNode);\n };\n\n // Swap all rows in header and body\n findAll(grid, \"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\n swapNodes(\"thead\", el1);\n });\n findAll(grid, 'tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\n swapNodes(\"tbody\", el1);\n });\n\n // Updates the columns\n grid.options.columns = findAll(grid, \"thead tr.dg-head-columns th[field]\").map((th) =>\n grid.options.columns.find((c) => c.field == getAttribute(th, \"field\"))\n );\n\n dispatch(grid, \"columnReordered\", {\n col: tmp.field,\n from: index,\n to: targetIndex,\n });\n return false;\n });\n }\n}\n\nexport default DraggableHeaders;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\n\r\n/**\r\n * Allows to paginate with horizontal swipe motions\r\n */\r\nclass TouchSupport extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.touch = null;\r\n }\r\n connected() {\r\n const grid = this.grid;\r\n grid.addEventListener(\"touchstart\", this, { passive: true });\r\n grid.addEventListener(\"touchmove\", this, { passive: true });\r\n }\r\n\r\n disconnected() {\r\n const grid = this.grid;\r\n grid.removeEventListener(\"touchstart\", this);\r\n grid.removeEventListener(\"touchmove\", this);\r\n }\r\n\r\n ontouchstart(e) {\r\n this.touch = e.touches[0];\r\n }\r\n\r\n ontouchmove(e) {\r\n if (!this.touch) {\r\n return;\r\n }\r\n const grid = this.grid;\r\n const xDiff = this.touch.clientX - e.touches[0].clientX;\r\n const yDiff = this.touch.clientY - e.touches[0].clientY;\r\n\r\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\r\n if (xDiff > 0) {\r\n grid.getNext();\r\n } else {\r\n grid.getPrev();\r\n }\r\n }\r\n this.touch = null;\r\n }\r\n}\r\n\r\nexport default TouchSupport;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport { dispatch, findAll, hasClass, setAttribute } from \"../utils/shortcuts.js\";\n\nconst SELECTABLE_CLASS = \"dg-selectable\";\nconst SELECT_ALL_CLASS = \"dg-select-all\";\nconst CHECKBOX_CLASS = \"form-check-input\"; //bs5\n\n/**\n * Allows to select rows\n */\nclass SelectableRows extends BasePlugin {\n disconnected() {\n if (this.selectAll) {\n this.selectAll.removeEventListener(\"change\", this);\n }\n }\n\n /**\n * @param {String} key Return a specific key (eg: id) instead of the whole row\n * @returns {Array}\n */\n getSelection(key = null) {\n const grid = this.grid;\n let selectedData = [];\n\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input:checked`);\n inputs.forEach((checkbox) => {\n const idx = parseInt(checkbox.dataset.id);\n const item = grid.data[idx - 1];\n if (!item) {\n console.warn(`Item ${idx} not found`);\n }\n if (key) {\n selectedData.push(item[key]);\n } else {\n selectedData.push(item);\n }\n });\n return selectedData;\n }\n\n /**\n * Uncheck box if hidden and visible only\n * @param {HTMLTableSectionElement} tbody\n */\n clearCheckboxes(tbody) {\n const grid = this.grid;\n if (!grid.options.selectVisibleOnly) {\n return;\n }\n const inputs = findAll(tbody, `tr[hidden] .${SELECTABLE_CLASS} input`);\n inputs.forEach((input) => {\n input.checked = false;\n });\n this.selectAll.checked = false;\n }\n\n colIndex() {\n return this.grid.startColIndex() - 2;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createHeaderCol(tr) {\n let th = document.createElement(\"th\");\n setAttribute(th, \"scope\", \"col\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(...[SELECTABLE_CLASS, \"dg-not-resizable\", \"dg-not-sortable\"]);\n th.tabIndex = 0;\n\n this.selectAll = document.createElement(\"input\");\n this.selectAll.type = \"checkbox\";\n this.selectAll.classList.add(SELECT_ALL_CLASS);\n this.selectAll.classList.add(CHECKBOX_CLASS);\n this.selectAll.addEventListener(\"change\", this);\n\n let label = document.createElement(\"label\");\n label.appendChild(this.selectAll);\n\n th.appendChild(label);\n\n th.setAttribute(\"width\", \"40\");\n tr.appendChild(th);\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createFilterCol(tr) {\n let th = document.createElement(\"th\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(SELECTABLE_CLASS);\n th.tabIndex = 0;\n\n tr.appendChild(th);\n }\n\n /**\n * Handles the selectAll checkbox when any other .dg-selectable checkbox is checked on table body.\n * It should check selectAll if all is checked\n * It should uncheck selectAll if any is unchecked\n * @param {HTMLTableSectionElement} tbody\n */\n shouldSelectAll(tbody) {\n if (!this.selectAll) {\n return;\n }\n // Delegate listener for change events on input checkboxes\n tbody.addEventListener(\"change\", this);\n // Make sure state is up to date\n tbody.dispatchEvent(new Event(\"change\"));\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createDataCol(tr) {\n // Create col\n let td = document.createElement(\"td\");\n setAttribute(td, \"role\", \"gridcell button\");\n setAttribute(td, \"aria-colindex\", this.colIndex());\n td.classList.add(SELECTABLE_CLASS);\n\n // Create input\n let selectOne = document.createElement(\"input\");\n // Alias row id for easy retrieval in getSelection\n selectOne.dataset.id = tr.getAttribute(\"aria-rowindex\");\n selectOne.type = \"checkbox\";\n selectOne.classList.add(CHECKBOX_CLASS);\n // Label need to take full space thanks to css to make the whole cell clickable\n let label = document.createElement(\"label\");\n label.classList.add(\"dg-clickable-cell\");\n label.appendChild(selectOne);\n td.appendChild(label);\n\n // Prevent unwanted click behaviour on row\n label.addEventListener(\"click\", this);\n\n tr.appendChild(td);\n }\n\n /**\n * @param {Event} e\n */\n onclick(e) {\n e.stopPropagation();\n }\n\n /**\n * Handle change event on select all or any select checkbox in the table body\n * @param {import(\"../utils/shortcuts.js\").FlexibleEvent} e\n */\n onchange(e) {\n const grid = this.grid;\n if (hasClass(e.target, SELECT_ALL_CLASS)) {\n const visibleOnly = grid.options.selectVisibleOnly;\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input`);\n inputs.forEach((cb) => {\n if (visibleOnly && !cb.offsetWidth) {\n return;\n }\n cb.checked = this.selectAll.checked;\n });\n\n dispatch(grid, \"rowsSelected\", {\n selection: this.getSelection(),\n });\n } else {\n if (!e.target.closest(`.${SELECTABLE_CLASS}`)) {\n return;\n }\n const totalCheckboxes = findAll(grid, `tbody .${SELECTABLE_CLASS} input[type=checkbox]`);\n // @ts-ignore\n const totalChecked = totalCheckboxes.filter((n) => n.checked);\n this.selectAll.checked = totalChecked.length == totalCheckboxes.length;\n\n dispatch(grid, \"rowsSelected\", {\n selection: grid.getSelection(),\n });\n }\n }\n}\n\nexport default SelectableRows;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Support for fixed table height\r\n *\r\n * We should add a fake row to push the footer down in case we don't have enough rows\r\n */\r\nclass FixedHeight extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.hasFixedHeight = false;\r\n // If we have a fixed height, make sure we have overflowY set\r\n if (grid.style.height) {\r\n grid.style.overflowY = \"auto\";\r\n this.hasFixedHeight = true;\r\n }\r\n }\r\n\r\n /**\r\n */\r\n createFakeRow() {\r\n const grid = this.grid;\r\n const tbody = grid.querySelector(\"tbody\");\r\n let tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n tr.classList.add(\"dg-fake-row\");\r\n tr.tabIndex = 0;\r\n tbody.appendChild(tr);\r\n }\r\n\r\n get fakeRow() {\r\n return this.grid.querySelector(\".dg-fake-row\");\r\n }\r\n\r\n /**\r\n * On last page, use a fake row to push footer down\r\n */\r\n updateFakeRow() {\r\n const grid = this.grid;\r\n const fakeRow = this.fakeRow;\r\n if (!fakeRow) {\r\n return;\r\n }\r\n\r\n // We don't need a fake row if we display everything\r\n if (grid.options.perPage > grid.totalRecords()) {\r\n return;\r\n }\r\n // We are not on last page\r\n if (grid.page !== grid.totalPages()) {\r\n return;\r\n }\r\n\r\n // Find remaining missing height\r\n const max = grid.options.perPage * grid.rowHeight;\r\n const visibleRows = grid.querySelectorAll(\"tbody tr:not([hidden])\").length;\r\n const fakeHeight = visibleRows > 1 ? max - visibleRows * grid.rowHeight : max;\r\n if (fakeHeight > 0) {\r\n setAttribute(fakeRow, \"height\", fakeHeight);\r\n fakeRow.removeAttribute(\"hidden\");\r\n } else {\r\n fakeRow.removeAttribute(\"height\");\r\n }\r\n }\r\n}\r\n\r\nexport default FixedHeight;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport getTextWidth from \"../utils/getTextWidth.js\";\nimport { getAttribute, hasAttribute, setAttribute } from \"../utils/shortcuts.js\";\n\n/**\n * Allows to resize columns\n */\nclass AutosizeColumn extends BasePlugin {\n /**\n * Autosize col based on column data\n * @param {HTMLTableCellElement} th\n * @param {import(\"../data-grid\").Column} column\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n computeSize(th, column, min, max) {\n const grid = this.grid;\n if (hasAttribute(th, \"width\")) {\n return getAttribute(th, \"width\");\n }\n if (!grid.data.length) {\n return;\n }\n const firstVal = grid.data[0];\n const lastVal = grid.data[grid.data.length - 1];\n let v = firstVal[column.field] ? firstVal[column.field].toString() : \"\";\n let v2 = lastVal[column.field] ? lastVal[column.field].toString() : \"\";\n if (v2.length > v.length) {\n v = v2;\n }\n let width = 0;\n if (v.length <= 6) {\n width = min;\n } else if (v.length > 50) {\n width = max;\n } else {\n // Add some extra room to have some spare space\n width = getTextWidth(v + \"0000\", th);\n }\n if (width > max) {\n width = max;\n }\n if (width < min) {\n width = min;\n }\n setAttribute(th, \"width\", width);\n return width;\n }\n}\n\nexport default AutosizeColumn;\n", "/**\r\n * Define a function that can be happily passed to addEventListener\r\n * @typedef {Function & EventListenerOrEventListenerObject} ExtendedFunction\r\n */\r\n\r\n/**\r\n * @param {Function} handler\r\n * @param {Number} timeout\r\n * @returns {ExtendedFunction}\r\n */\r\nexport default function debounce(handler, timeout = 300) {\r\n let timer = null;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n timer = null;\r\n handler(...args);\r\n }, timeout);\r\n };\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport debounce from \"../utils/debounce.js\";\nimport { addClass, ce, find, findAll, hasClass, insertAfter, removeAttribute, removeClass, setAttribute } from \"../utils/shortcuts.js\";\n\nconst RESPONSIVE_CLASS = \"dg-responsive\";\n\nlet obsTo;\n\n/**\n * @param {Array} list\n * @returns {Array}\n */\nfunction sortByPriority(list) {\n return list.sort((a, b) => {\n const v1 = parseInt(a.dataset.responsive) || 1;\n const v2 = parseInt(b.dataset.responsive) || 1;\n return v2 - v1;\n });\n}\n\n/**\n * @type {ResizeObserverCallback}\n */\n//@ts-ignore\nconst callback = debounce((entries) => {\n for (const entry of entries) {\n /**\n * @type {import(\"../data-grid\").default}\n */\n // @ts-ignore\n const grid = entry.target;\n const table = grid.table;\n if (grid.plugins.ResponsiveGrid.observerBlocked) {\n return;\n }\n // check inlineSize (width) and not blockSize (height)\n const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;\n const size = parseInt(contentBoxSize.inlineSize);\n const tableWidth = table.offsetWidth;\n const realTableWidth = findAll(grid.headerRow, \"th\").reduce((result, th) => {\n return result + th.offsetWidth;\n }, 0);\n const diff = (realTableWidth || tableWidth) - size - 1;\n const minWidth = 50;\n const prevAction = grid.plugins.ResponsiveGrid.prevAction;\n // We have an array with the columns to show/hide are in order, most important first\n const headerCols = sortByPriority(\n findAll(grid.headerRow, \"th[field]\")\n .reverse() // Order takes precedence if no priority is set\n .filter((col) => {\n // Leave out unresponsive columns\n return col.dataset.responsive !== \"0\";\n })\n );\n let changed = false;\n\n grid.log(`table is ${tableWidth}/${realTableWidth} and available size is ${size}. Diff: ${diff}`);\n\n // The table is too big when diff has a high value, otherwise it will be like -1 or -2\n if (diff > 0) {\n if (prevAction === \"show\") {\n return;\n }\n grid.plugins.ResponsiveGrid.prevAction = \"hide\";\n let remaining = diff;\n let cols = headerCols.filter((col) => {\n return !col.hasAttribute(\"hidden\") && col.hasAttribute(\"data-responsive\");\n });\n if (cols.length === 0) {\n cols = headerCols.filter((col) => {\n return !col.hasAttribute(\"hidden\");\n });\n // Always keep one column\n if (cols.length === 1) {\n return;\n }\n }\n cols.forEach((col) => {\n if (remaining < 0) {\n return;\n }\n\n const colWidth = col.offsetWidth;\n const field = col.getAttribute(\"field\");\n if (!field) {\n return;\n }\n col.dataset.baseWidth = \"\" + col.offsetWidth;\n\n grid.hideColumn(field, false);\n grid.setColProp(field, \"responsiveHidden\", true);\n changed = true;\n\n remaining -= colWidth;\n remaining = Math.round(remaining);\n });\n } else {\n if (prevAction === \"hide\") {\n return;\n }\n grid.plugins.ResponsiveGrid.prevAction = \"show\";\n\n const requiredWidth =\n headerCols\n .filter((col) => {\n return !col.hasAttribute(\"hidden\");\n })\n .reduce((result, col) => {\n const width = col.dataset.minWidth ? parseInt(col.dataset.minWidth) : col.offsetWidth;\n return result + width;\n }, 0) + minWidth; // Add an offset so that inserting column is smoother\n\n // Compute available width to insert columns\n let remaining = size - requiredWidth;\n // Do we have any hidden column that we can restore ?\n headerCols\n .slice()\n .reverse() // Reverse the array to restore the columns in the proper order\n .filter((col) => {\n return col.hasAttribute(\"hidden\");\n })\n .forEach((col) => {\n if (remaining < minWidth) {\n return;\n }\n const colWidth = parseInt(col.dataset.minWidth);\n\n // We need to have enough space to restore it\n if (colWidth > remaining) {\n remaining = -1; // break loop to keep restoring in order\n return;\n }\n\n const field = col.getAttribute(\"field\");\n if (!field) {\n return;\n }\n\n grid.showColumn(field, false);\n grid.setColProp(field, \"responsiveHidden\", false);\n changed = true;\n\n remaining -= colWidth;\n remaining = Math.round(remaining);\n });\n }\n\n // Check footer\n const footer = find(grid.table, \"tfoot\");\n const realFooterWidth = findAll(grid.table, \".dg-footer > div\").reduce((result, div) => {\n return result + div.offsetWidth;\n }, 0);\n const availableFooterWidth = footer.offsetWidth - realFooterWidth;\n if (realFooterWidth > size) {\n addClass(footer, \"dg-footer-compact\");\n } else if (availableFooterWidth > 250) {\n removeClass(footer, \"dg-footer-compact\");\n }\n if (changed) {\n grid.renderTable();\n }\n // Prevent resize loop\n setTimeout(() => {\n grid.plugins.ResponsiveGrid.prevAction = null;\n }, 1000);\n grid.table.style.visibility = \"visible\";\n }\n}, 100);\nconst resizeObserver = new ResizeObserver(callback);\n\n/**\n * Responsive data grid\n */\nclass ResponsiveGrid extends BasePlugin {\n constructor(grid) {\n super(grid);\n\n this.observerBlocked = false;\n this.prevAction = null;\n }\n\n connected() {\n if (this.grid.options.responsive) {\n this.observe();\n }\n }\n\n disconnected() {\n this.unobserve();\n }\n\n observe() {\n if (!this.grid.options.responsive) {\n return;\n }\n resizeObserver.observe(this.grid);\n this.grid.style.display = \"block\"; // Otherwise resize doesn't happen\n this.grid.style.overflowX = \"hidden\"; // Prevent scrollbars from appearing\n }\n\n unobserve() {\n resizeObserver.unobserve(this.grid);\n this.grid.style.display = \"unset\";\n this.grid.style.overflowX = \"unset\";\n }\n\n blockObserver() {\n this.observerBlocked = true;\n if (obsTo) {\n clearTimeout(obsTo);\n }\n }\n\n unblockObserver() {\n obsTo = setTimeout(() => {\n this.observerBlocked = false;\n }, 200); // more than debounce\n }\n\n /**\n * @returns {Boolean}\n */\n hasHiddenColumns() {\n let flag = false;\n this.grid.options.columns.forEach((col) => {\n if (col.responsiveHidden) {\n flag = true;\n }\n });\n return flag;\n }\n\n colIndex() {\n return this.grid.startColIndex() - 1;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createHeaderCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n let th = ce(\"th\", tr);\n setAttribute(th, \"scope\", \"col\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n setAttribute(th, \"width\", \"40\");\n th.classList.add(...[`${RESPONSIVE_CLASS}-toggle`, \"dg-not-resizable\", \"dg-not-sortable\"]);\n th.tabIndex = 0;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createFilterCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n let th = ce(\"th\", tr);\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(`${RESPONSIVE_CLASS}-toggle`);\n th.tabIndex = 0;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createDataCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n // Create col\n let td = document.createElement(\"td\");\n setAttribute(td, \"role\", \"gridcell button\");\n setAttribute(td, \"aria-colindex\", this.colIndex());\n td.classList.add(`${RESPONSIVE_CLASS}-toggle`);\n\n // Create icon\n td.innerHTML = `
\n \n \n\n\n \n
`;\n tr.appendChild(td);\n\n td.addEventListener(\"click\", this);\n td.addEventListener(\"mousedown\", this);\n }\n\n computeLabelWidth() {\n let idealWidth = 0;\n let consideredCol = 0;\n while (idealWidth < 120) {\n consideredCol++;\n const hCol = find(this.grid, `.dg-head-columns th[aria-colindex=\"${consideredCol}\"]`);\n if (hCol) {\n idealWidth += hCol.offsetWidth;\n } else {\n break;\n }\n }\n return idealWidth;\n }\n\n /**\n * @param {Event} ev\n */\n onmousedown(ev) {\n // Avoid selection through double click\n ev.preventDefault();\n }\n\n /**\n * @param {Event} ev\n */\n onclick(ev) {\n // Prevent expandable\n ev.stopPropagation();\n\n // target is the element that triggered the event (e.g., the user clicked on)\n // currentTarget is the element that the event listener is attached to.\n\n /**\n * @type {HTMLTableRowElement}\n */\n //@ts-ignore\n const td = ev.currentTarget;\n const tr = td.parentElement;\n const open = find(td, `.${RESPONSIVE_CLASS}-open`);\n const close = find(td, `.${RESPONSIVE_CLASS}-close`);\n\n this.blockObserver();\n\n const isExpanded = hasClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n if (isExpanded) {\n removeClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n open.style.display = \"unset\";\n close.style.display = \"none\";\n\n // Move back rows and cleanup row\n const childRow = tr.nextElementSibling;\n const hiddenCols = findAll(childRow, `.${RESPONSIVE_CLASS}-hidden`);\n hiddenCols.forEach((col) => {\n // We don't really need to care where we insert them since we are going to redraw anyway\n tr.appendChild(col);\n setAttribute(col, \"hidden\");\n });\n\n childRow.parentElement.removeChild(childRow);\n } else {\n addClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n open.style.display = \"none\";\n close.style.display = \"unset\";\n\n // Create a child row and move rows into it\n const childRow = ce(\"tr\");\n insertAfter(childRow, tr);\n addClass(childRow, `${RESPONSIVE_CLASS}-child-row`);\n\n const childRowTd = ce(\"td\", childRow);\n setAttribute(childRowTd, \"colspan\", this.grid.columnsLength(true));\n\n const childTable = ce(\"table\", childRowTd);\n addClass(childTable, `${RESPONSIVE_CLASS}-table`);\n\n const hiddenCols = findAll(tr, `.${RESPONSIVE_CLASS}-hidden`);\n const idealWidth = this.computeLabelWidth();\n hiddenCols.forEach((col) => {\n const childTableRow = ce(\"tr\", childTable);\n\n // Add label\n const label = col.dataset.name;\n const labelCol = ce(\"th\", childTableRow);\n // It looks much better when aligned with an actual col\n labelCol.style.width = `${idealWidth}px`;\n labelCol.innerHTML = label;\n\n // Add actual row\n childTableRow.appendChild(col);\n removeAttribute(col, \"hidden\");\n });\n }\n\n this.unblockObserver();\n }\n}\n\nexport default ResponsiveGrid;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport interpolate from \"../utils/interpolate.js\";\r\nimport { dispatch, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Add action on rows\r\n */\r\nclass RowActions extends BasePlugin {\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasActions() {\r\n return this.grid.options.actions.length > 0;\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionHeader(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n setAttribute(actionsTh, \"role\", \"columnheader button\");\r\n setAttribute(actionsTh, \"aria-colindex\", this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", \"dg-not-sortable\", \"dg-not-resizable\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionFilter(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n actionsTh.setAttribute(\"role\", \"columnheader button\");\r\n actionsTh.setAttribute(\"aria-colindex\", \"\" + this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n * @param {Object} item\r\n */\r\n makeActionRow(tr, item) {\r\n const labels = this.grid.labels;\r\n const td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell\");\r\n setAttribute(td, \"aria-colindex\", this.grid.columnsLength(true));\r\n td.classList.add(...[\"dg-actions\", this.actionClass]);\r\n td.tabIndex = 0;\r\n\r\n // Add menu toggle\r\n let actionsToggle = document.createElement(\"button\");\r\n actionsToggle.classList.add(\"dg-actions-toggle\");\r\n actionsToggle.innerHTML = \"\u2630\";\r\n td.appendChild(actionsToggle);\r\n on(actionsToggle, \"click\", (ev) => {\r\n ev.stopPropagation();\r\n ev.target.parentElement.classList.toggle(\"dg-actions-expand\");\r\n });\r\n\r\n this.grid.options.actions.forEach((action) => {\r\n let button = document.createElement(\"button\");\r\n if (action.html) {\r\n button.innerHTML = action.html;\r\n } else {\r\n button.innerText = action.title ?? action.name;\r\n }\r\n if (action.title) {\r\n button.title = action.title;\r\n }\r\n if (action.url) {\r\n button.type = \"submit\";\r\n button.formAction = interpolate(action.url, item);\r\n }\r\n if (action.class) {\r\n button.classList.add(...action.class.split(\" \"));\r\n }\r\n const actionHandler = (ev) => {\r\n ev.stopPropagation();\r\n if (action.confirm) {\r\n let c = confirm(labels.areYouSure);\r\n if (!c) {\r\n ev.preventDefault();\r\n return;\r\n }\r\n }\r\n dispatch(this.grid, \"action\", {\r\n data: item,\r\n action: action.name,\r\n });\r\n };\r\n button.addEventListener(\"click\", actionHandler);\r\n td.appendChild(button);\r\n\r\n // Row action\r\n if (action.default) {\r\n tr.classList.add(\"dg-actionable\");\r\n tr.addEventListener(\"click\", actionHandler);\r\n }\r\n });\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n get actionClass() {\r\n if (this.grid.options.actions.length < 3 && !this.grid.options.collapseActions) {\r\n return \"dg-actions-\" + this.grid.options.actions.length;\r\n }\r\n return \"dg-actions-more\";\r\n }\r\n}\r\n\r\nexport default RowActions;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Make editable inputs in rows\r\n */\r\nclass EditableColumn extends BasePlugin {\r\n /**\r\n *\r\n * @param {HTMLTableCellElement} td\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Object} item\r\n * @param {number} i\r\n */\r\n makeEditableInput(td, column, item, i) {\r\n const gridId = this.grid.getAttribute(\"id\");\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n input.tabIndex = 0;\r\n input.classList.add(\"dg-editable\");\r\n input.name = gridId.replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\r\n input.value = item[column.field];\r\n input.dataset.field = column.field;\r\n\r\n // Prevent row action\r\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\r\n // Enter validates edit\r\n input.addEventListener(\"keypress\", (ev) => {\r\n if (ev.type === \"keypress\") {\r\n const key = ev.keyCode || ev.key;\r\n if (key === 13 || key === \"Enter\") {\r\n input.blur();\r\n ev.preventDefault();\r\n }\r\n }\r\n });\r\n // Save on blur\r\n input.addEventListener(\"blur\", () => {\r\n // Only fire on update\r\n if (input.value == item[input.dataset.field]) {\r\n return;\r\n }\r\n // Update underlying data\r\n item[input.dataset.field] = input.value;\r\n // Notify\r\n dispatch(this.grid, \"edit\", {\r\n data: item,\r\n value: input.value,\r\n });\r\n });\r\n td.appendChild(input);\r\n }\r\n}\r\n\r\nexport default EditableColumn;\r\n", "import DataGrid from \"./src/data-grid.js\";\n// Optional plugins\nimport ColumnResizer from \"./src/plugins/column-resizer.js\";\nimport ContextMenu from \"./src/plugins/context-menu.js\";\nimport DraggableHeaders from \"./src/plugins/draggable-headers.js\";\nimport TouchSupport from \"./src/plugins/touch-support.js\";\nimport SelectableRows from \"./src/plugins/selectable-rows.js\";\nimport FixedHeight from \"./src/plugins/fixed-height.js\";\nimport AutosizeColumn from \"./src/plugins/autosize-column.js\";\nimport ResponsiveGrid from \"./src/plugins/responsive-grid.js\";\nimport RowActions from \"./src/plugins/row-actions.js\";\nimport EditableColumn from \"./src/plugins/editable-column.js\";\n\n// Using shorthand property names\n// This make them reserved and keys will be preserved\n// Actual class names are renamed\nDataGrid.registerPlugins({\n ColumnResizer,\n ContextMenu,\n DraggableHeaders,\n TouchSupport,\n SelectableRows,\n FixedHeight,\n AutosizeColumn,\n ResponsiveGrid,\n RowActions,\n EditableColumn,\n});\n\ncustomElements.define(\"data-grid\", DataGrid);\n\nexport default DataGrid;\n"], + "sourcesContent": ["/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nexport default function camelize(str) {\r\n return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());\r\n}\r\n", "/**\r\n * Parse data attribute and return properly typed data\r\n * @param {String} v\r\n * @returns {any}\r\n */\r\nexport default function normalizeData(v) {\r\n // Bool\r\n if (v === \"true\") {\r\n return true;\r\n }\r\n if (v === \"false\") {\r\n return false;\r\n }\r\n // Null or empty\r\n if (v === \"\" || v === \"null\") {\r\n return null;\r\n }\r\n // Numeric attributes\r\n if (v === Number(v).toString()) {\r\n return Number(v);\r\n }\r\n // Only attempt json parsing for array or objects\r\n if (v && [\"[\", \"{\"].includes(v.substring(0, 1))) {\r\n try {\r\n // In case we have only single quoted values, like ['one', 'two', 'three']\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(decodeURIComponent(v));\r\n } catch {\r\n console.error(\"Failed to parse \" + v);\r\n return {};\r\n }\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @typedef FlexibleHTMLProps\r\n * @property {boolean} [checked] (HTMLInputElement)\r\n * @property {string} [value] (HTMLInputElement)\r\n * @property {number} [rowHeight] (HTMLTableRowElement)\r\n *\r\n * A flexible type HTMLElement type that does not require using instanceof all over the place\r\n * Make sure that your selector is indeed valid\r\n * Only includes most commons props\r\n * @typedef {HTMLElement & FlexibleHTMLProps} FlexibleHTMLElement\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {HTMLElement&HTMLInputElement&HTMLTableRowElement} MixedHTMLElement\r\n */\r\n\r\n/**\r\n * @typedef FlexibleEventProps\r\n * @property {FlexibleHTMLElement} target\r\n * @property {FlexibleHTMLElement} currentTarget\r\n * @property {DataTransfer} [dataTransfer] (DragEvent)\r\n * @property {number} [clientX] (MouseEvent)\r\n * @property {number} [clientY] (MouseEvent)\r\n *\r\n * @typedef {Event & FlexibleEventProps} FlexibleEvent\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {Event&MouseEvent&InputEvent&DragEvent&FocusEvent&KeyboardEvent&PointerEvent} MixedEvent\r\n */\r\n\r\n/**\r\n * @callback FlexibleListener\r\n * @param {FlexibleEvent} event\r\n */\r\n\r\nclass FlexibleEventListenerObject {\r\n /**\r\n * @param {FlexibleEvent} e\r\n */\r\n handleEvent(e) {}\r\n}\r\n\r\nconst supportedPassiveTypes = [\r\n \"scroll\",\r\n \"wheel\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n \"touchenter\",\r\n \"touchend\",\r\n \"touchleave\",\r\n \"mouseout\",\r\n \"mouseleave\",\r\n \"mouseup\",\r\n \"mousedown\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mousewheel\",\r\n \"mouseover\",\r\n];\r\n\r\n/**\r\n * Automatically set passive options based on type\r\n * @param {string} type\r\n * @returns {AddEventListenerOptions}\r\n */\r\nfunction passiveOpts(type) {\r\n if (supportedPassiveTypes.includes(type)) {\r\n return { passive: true };\r\n }\r\n return {};\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {any}\r\n */\r\nexport function getAttribute(el, name) {\r\n return el.getAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasAttribute(el, name) {\r\n return el.hasAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @param {any} v\r\n * @param {Boolean} check Prevent setting if attribute is already there\r\n */\r\nexport function setAttribute(el, name, v = \"\", check = false) {\r\n if (check && hasAttribute(el, name)) return;\r\n el.setAttribute(name, \"\" + v);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeAttribute(el, name) {\r\n if (hasAttribute(el, name)) {\r\n el.removeAttribute(name);\r\n }\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function on(el, type, listener) {\r\n el.addEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function off(el, type, listener) {\r\n el.removeEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function one(el, type, listener) {\r\n el.addEventListener(type, listener, {\r\n once: true,\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {String} name\r\n * @param {any} data\r\n * @param {Boolean} bubbles\r\n */\r\nexport function dispatch(el, name, data = {}, bubbles = false) {\r\n let opts = {};\r\n if (bubbles) {\r\n opts.bubbles = true;\r\n }\r\n if (data) {\r\n opts.detail = data;\r\n }\r\n el.dispatchEvent(new CustomEvent(name, opts));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasClass(el, name) {\r\n return el.classList.contains(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function addClass(el, name) {\r\n el.classList.add(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeClass(el, name) {\r\n el.classList.remove(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function toggleClass(el, name) {\r\n el.classList.toggle(name);\r\n}\r\n\r\n/**\r\n * @param {String|HTMLElement} selector\r\n * @param {HTMLElement|Document} base\r\n * @returns {FlexibleHTMLElement|null}\r\n */\r\nexport function $(selector, base = document) {\r\n if (selector instanceof HTMLElement) {\r\n return selector;\r\n }\r\n return base.querySelector(selector);\r\n}\r\n\r\n/**\r\n * @param {String} selector\r\n * @param {Element|Document} base\r\n * @returns {Array}\r\n */\r\nexport function $$(selector, base = document) {\r\n return Array.from(base.querySelectorAll(selector));\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped element\r\n * For actual type, prefer use of el.querySelector\r\n * @param {HTMLElement} el\r\n * @param {String|HTMLElement} selector\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function find(el, selector) {\r\n return $(selector, el);\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped elements\r\n * For actual type, prefer use of el.querySelectorAll\r\n * @param {Element} el\r\n * @param {String} selector\r\n * @returns {Array}\r\n */\r\nexport function findAll(el, selector) {\r\n return $$(selector, el);\r\n}\r\n\r\n/**\r\n * @param {*} el\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function el(el) {\r\n return el;\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K} tagName\r\n * @param {HTMLElement} parent\r\n * @returns {HTMLElementTagNameMap[K]}\r\n */\r\nexport function ce(tagName, parent = null) {\r\n const el = document.createElement(tagName);\r\n if (parent) {\r\n parent.appendChild(el);\r\n }\r\n return el;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} newNode\r\n * @param {HTMLElement} existingNode\r\n */\r\nexport function insertAfter(newNode, existingNode) {\r\n existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);\r\n}\r\n", "import camelize from \"../utils/camelize.js\";\r\nimport normalizeData from \"../utils/normalizeData.js\";\r\nimport { dispatch, getAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Base element that does not contain any specific logic\r\n * related to this project but makes HTMLElemnt usable\r\n */\r\nclass BaseElement extends HTMLElement {\r\n /**\r\n * @param {Object} options\r\n */\r\n constructor(options = {}) {\r\n super();\r\n this.options = Object.assign({}, this.defaultOptions, this.normalizedDataset, options);\r\n\r\n this.log(\"constructor\");\r\n\r\n this.fireEvents = true;\r\n this._ready();\r\n\r\n this.log(\"ready\");\r\n }\r\n\r\n get defaultOptions() {\r\n return {};\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @returns {any}\r\n */\r\n getOption(opt) {\r\n return this.options[opt];\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @param {any} v\r\n */\r\n setOption(opt, v) {\r\n setAttribute(this, `data-${opt}`, v);\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n */\r\n toggleOption(opt) {\r\n setAttribute(this, `data-${opt}`, !this.getOption(opt));\r\n }\r\n\r\n get normalizedDataset() {\r\n let data = { ...this.dataset };\r\n for (var key in data) {\r\n data[key] = normalizeData(data[key]);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * @returns {String}\r\n */\r\n static template() {\r\n return \"\";\r\n }\r\n\r\n /**\r\n * This is called at the end of constructor. Extend in subclass if needed.\r\n */\r\n _ready() {}\r\n\r\n /**\r\n * @param {String|Error} message\r\n */\r\n log(message) {\r\n if (this.options.debug) {\r\n console.log(\"[\" + getAttribute(this, \"id\") + \"] \" + message);\r\n }\r\n }\r\n\r\n /**\r\n * Handle events within the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * This is called when connected. Extend in subclass if needed.\r\n */\r\n _connected() {}\r\n\r\n connectedCallback() {\r\n // ensure whenDefined callbacks run first\r\n setTimeout(() => {\r\n this.log(\"connectedCallback\");\r\n\r\n // Append only when labels had the opportunity to be set\r\n // Don't use shadow dom as it makes theming super hard\r\n const template = document.createElement(\"template\");\r\n // @ts-ignore\r\n template.innerHTML = this.constructor.template();\r\n this.appendChild(template.content.cloneNode(true));\r\n\r\n this._connected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"connected\");\r\n }, 0);\r\n }\r\n\r\n /**\r\n * This is called when disconnected. Extend in subclass if needed.\r\n */\r\n _disconnected() {}\r\n\r\n disconnectedCallback() {\r\n this.log(\"disconnectedCallback\");\r\n this._disconnected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"disconnected\");\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#a-props-like-accessor\r\n * @returns {Object}\r\n */\r\n get transformAttributes() {\r\n return {};\r\n }\r\n\r\n /**\r\n * This is only meant to work with data attributes\r\n * This allows us to have properties that reflect automatically in the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dataset-attributes\r\n * @param {String} attributeName\r\n * @param {String} oldValue\r\n * @param {String} newValue\r\n */\r\n attributeChangedCallback(attributeName, oldValue, newValue) {\r\n // It didn't change\r\n if (oldValue === newValue) {\r\n return;\r\n }\r\n\r\n this.log(\"attributeChangedCallback: \" + attributeName);\r\n\r\n let isOption = false;\r\n const transformer = this.transformAttributes[attributeName] ?? normalizeData;\r\n\r\n // Data attributes are mapped to options while other attributes are mapped as properties\r\n if (attributeName.indexOf(\"data-\") === 0) {\r\n attributeName = attributeName.slice(5);\r\n isOption = true;\r\n }\r\n attributeName = camelize(attributeName);\r\n if (isOption) {\r\n this.options[attributeName] = transformer(newValue);\r\n } else {\r\n this[attributeName] = transformer(newValue);\r\n }\r\n\r\n // Fire internal event\r\n if (this.fireEvents && this[`${attributeName}Changed`]) {\r\n this[`${attributeName}Changed`]();\r\n }\r\n }\r\n}\r\n\r\nexport default BaseElement;\r\n", "/**\r\n * @param {HTMLSelectElement} el\r\n * @param {String} value\r\n * @param {String} label\r\n * @param {Boolean} checked\r\n */\r\nexport default function addSelectOption(el, value, label, checked = false) {\r\n let opt = document.createElement(\"option\");\r\n opt.value = \"\" + value;\r\n if (checked) {\r\n opt.selected = true;\r\n }\r\n opt.label = label;\r\n el.appendChild(opt);\r\n}\r\n", "/**\r\n * @param {URL} url\r\n * @param {Object} params\r\n */\r\nexport default function appendParamsToUrl(url, params = {}) {\r\n Object.keys(params).forEach((key) => {\r\n if (Array.isArray(params[key])) {\r\n // @ts-ignore\r\n Object.keys(params[key]).forEach((k) => url.searchParams.append(isNaN(k) ? `${key}[${k}]` : key, params[key][k]));\r\n } else {\r\n url.searchParams.append(key, params[key]);\r\n }\r\n });\r\n}\r\n", "/**\r\n * Force value as arrays\r\n * @param {String|Array} v\r\n * @returns {Array}\r\n */\r\nexport default function convertArray(v) {\r\n if (typeof v === \"string\") {\r\n if (v[0] === \"[\") {\r\n // \"['my', 'value']\" would fail as a json\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(v);\r\n }\r\n\r\n return v.split(\",\");\r\n }\r\n if (!Array.isArray(v)) {\r\n console.error(\"Invalid array\", v);\r\n return [];\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @returns {Object}\r\n */\r\nexport default function elementOffset(el) {\r\n var rect = el.getBoundingClientRect(),\r\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\r\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\r\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\r\n}\r\n", "/**\r\n * Replace element within {} by their data value\r\n * @param {String} str\r\n * @param {Object} data\r\n * @returns {String}\r\n */\r\nexport default function interpolate(str, data) {\r\n return str.replace(/\\{([^}]+)?\\}/g, function ($1, $2) {\r\n return data[$2];\r\n });\r\n}\r\n", "/**\r\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\r\n * Getting computed styles only works for dom that are added in the dom\r\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\r\n * @param {String} text The text to be rendered.\r\n * @param {Element} el Target element (defaults to body)\r\n * @param {Boolean} withPadding Include padding on element\r\n * @returns {Number}\r\n */\r\nexport default function getTextWidth(text, el = document.body, withPadding = false) {\r\n if (!el) {\r\n el = document.createElement(\"div\");\r\n }\r\n const styles = window.getComputedStyle(el);\r\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\r\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\r\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\r\n\r\n let padding = 0;\r\n if (withPadding) {\r\n const paddingLeft = styles.getPropertyValue(\"padding-left\") || \"0\";\r\n const paddingRight = styles.getPropertyValue(\"padding-right\") || \"0\";\r\n padding = parseInt(paddingLeft) + parseInt(paddingRight);\r\n }\r\n\r\n // re-use canvas object for better performance\r\n // @ts-ignore\r\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement(\"canvas\"));\r\n const context = canvas.getContext(\"2d\");\r\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\r\n const metrics = context.measureText(text);\r\n return parseInt(metrics.width) + padding;\r\n}\r\n", "/**\r\n * @param {String} prefix\r\n * @returns {String}\r\n */\r\nexport default function randstr(prefix) {\r\n return Math.random()\r\n .toString(36)\r\n .replace(\"0.\", prefix || \"\");\r\n}\r\n", "/**\r\n * Data Grid Web component\r\n *\r\n * Credits for inspiration\r\n * @link https://github.com/riverside/zino-grid\r\n */\r\n\"use strict\";\r\n\r\nimport BaseElement from \"./core/base-element.js\";\r\nimport addSelectOption from \"./utils/addSelectOption.js\";\r\nimport appendParamsToUrl from \"./utils/appendParamsToUrl.js\";\r\nimport camelize from \"./utils/camelize.js\";\r\nimport convertArray from \"./utils/convertArray.js\";\r\nimport elementOffset from \"./utils/elementOffset.js\";\r\nimport interpolate from \"./utils/interpolate.js\";\r\nimport getTextWidth from \"./utils/getTextWidth.js\";\r\nimport randstr from \"./utils/randstr.js\";\r\nimport {\r\n dispatch,\r\n find,\r\n findAll,\r\n hasClass,\r\n removeAttribute,\r\n getAttribute,\r\n setAttribute,\r\n addClass,\r\n toggleClass,\r\n on,\r\n} from \"./utils/shortcuts.js\";\r\n\r\n/**\r\n * Column definition\r\n * @typedef Column\r\n * @property {String} field - the key in the data\r\n * @property {String} title - the title to display in the header (defaults to \"field\" if not set)\r\n * @property {Number} width - the width of the column (auto otherwise)\r\n * @property {String} class - class to set on the column (target body or header with th.class or td.class)\r\n * @property {String} attr - don't render the column and set a matching attribute on the row with the value of the field\r\n * @property {Boolean} hidden - hide the column\r\n * @property {Boolean} noSort - allow disabling sort for a given column\r\n * @property {String} format - custom data formatting\r\n * @property {String} transform - custom value transformation\r\n * @property {Boolean} editable - replace with input (EditableColumn module)\r\n * @property {Number} responsive - the higher the value, the sooner it will be hidden, disable with 0 (ResponsiveGrid module)\r\n * @property {Boolean} responsiveHidden - hidden through responsive module (ResponsiveGrid module)\r\n */\r\n\r\n/**\r\n * Row action\r\n * @typedef Action\r\n * @property {String} title - the title of the button\r\n * @property {String} name - the name of the action\r\n * @property {String} class - the class for the button\r\n * @property {String} url - link for the action\r\n * @property {String} html - custom button data\r\n * @property {Boolean} confirm - needs confirmation\r\n * @property {Boolean} default - is the default row action\r\n */\r\n\r\n/** @typedef {import('./plugins/autosize-column').default} AutosizeColumn */\r\n/** @typedef {import('./plugins/column-resizer').default} ColumnResizer */\r\n/** @typedef {import('./plugins/context-menu').default} ContextMenu */\r\n/** @typedef {import('./plugins/draggable-headers').default} DraggableHeaders */\r\n/** @typedef {import('./plugins/editable-column').default} EditableColumn */\r\n/** @typedef {import('./plugins/fixed-height').default} FixedHeight */\r\n/** @typedef {import('./plugins/responsive-grid').default} ResponsiveGrid */\r\n/** @typedef {import('./plugins/row-actions').default} RowActions */\r\n/** @typedef {import('./plugins/selectable-rows').default} SelectableRows */\r\n/** @typedef {import('./plugins/touch-support').default} TouchSupport */\r\n\r\n/**\r\n * These plugins are all optional\r\n * @typedef {Object} Plugins\r\n * @property {ColumnResizer} [ColumnResizer] resize handlers in the headers\r\n * @property {ContextMenu} [ContextMenu] menu to show/hide columns\r\n * @property {DraggableHeaders} [DraggableHeaders] draggable headers columns\r\n * @property {EditableColumn} [EditableColumn] draggable headers columns\r\n * @property {TouchSupport} [TouchSupport] touch swipe\r\n * @property {SelectableRows} [SelectableRows] create a column with checkboxes to select rows\r\n * @property {FixedHeight} [FixedHeight] allows having fixed height tables\r\n * @property {AutosizeColumn} [AutosizeColumn] compute ideal width based on column content\r\n * @property {ResponsiveGrid} [ResponsiveGrid] hide/show column on the fly\r\n * @property {RowActions} [RowActions] add action on rows\r\n */\r\n\r\n/**\r\n * Parameters to pass along or receive from the server\r\n * @typedef ServerParams\r\n * @property {String} serverParams.start\r\n * @property {String} serverParams.length\r\n * @property {String} serverParams.search\r\n * @property {String} serverParams.sort\r\n * @property {String} serverParams.sortDir\r\n * @property {String} serverParams.dataKey\r\n * @property {String} serverParams.errorKey\r\n * @property {String} serverParams.metaKey\r\n * @property {String} serverParams.metaTotalKey\r\n * @property {String} serverParams.metaFilteredKey\r\n * @property {String} serverParams.optionsKey\r\n * @property {String} serverParams.paramsKey\r\n */\r\n\r\n/**\r\n * Available data grid options, plugins included\r\n * @typedef Options\r\n * @property {?String} id Custom id for the grid\r\n * @property {?String} url An URL with data to display in JSON format\r\n * @property {Boolean} debug Log actions in DevTools console\r\n * @property {Boolean} filter Allows a filtering functionality\r\n * @property {Boolean} sort Allows a sort by column functionality\r\n * @property {String} defaultSort Default sort field if sorting is enabled\r\n * @property {Boolean} server Is a server side powered grid\r\n * @property {ServerParams} serverParams Describe keys passed to the server backend\r\n * @property {String} dir Dir\r\n * @property {Array} perPageValues Available per page options\r\n * @property {Column[]} columns Available columns\r\n * @property {Number} defaultPage Starting page\r\n * @property {Number} perPage Number of records displayed per page\r\n * @property {Boolean} expand Allow cell content to spawn over multiple lines\r\n * @property {Action[]} actions Row actions (RowActions module)\r\n * @property {Boolean} collapseActions Group actions (RowActions module)\r\n * @property {Boolean} resizable Make columns resizable (ColumnResizer module)\r\n * @property {Boolean} selectable Allow selecting rows with a checkbox (SelectableRows module)\r\n * @property {Boolean} selectVisibleOnly Select all only selects visible rows (SelectableRows module)\r\n * @property {Boolean} autosize Compute column sizes based on given data (Autosize module)\r\n * @property {Boolean} autoheight Adjust height so that it matches table size (FixedHeight module)\r\n * @property {Boolean} menu Right click menu on column headers (ContextMenu module)\r\n * @property {Boolean} reorder Allows a column reordering functionality (DraggableHeaders module)\r\n * @property {Boolean} responsive Change display mode on small screens (ResponsiveGrid module)\r\n * @property {Boolean} responsiveToggle Show toggle column (ResponsiveGrid module)\r\n */\r\n\r\n/**\r\n * Available labels that can be translated\r\n * @typedef Labels\r\n * @property {String} itemsPerPage\r\n * @property {String} gotoPage\r\n * @property {String} gotoFirstPage\r\n * @property {String} gotoPrevPage\r\n * @property {String} gotoNextPage\r\n * @property {String} gotoLastPage\r\n * @property {String} of\r\n * @property {String} items\r\n * @property {String} resizeColumn\r\n * @property {String} noData\r\n * @property {String} areYouSure\r\n */\r\n\r\n/**\r\n * List of registered plugins\r\n * @type {Plugins}\r\n */\r\nlet plugins = {};\r\n\r\n/**\r\n * @type {Labels}\r\n */\r\nlet labels = {\r\n itemsPerPage: \"Items per page\",\r\n gotoPage: \"Go to page\",\r\n gotoFirstPage: \"Go to first page\",\r\n gotoPrevPage: \"Go to previous page\",\r\n gotoNextPage: \"Go to next page\",\r\n gotoLastPage: \"Go to last page\",\r\n of: \"of\",\r\n items: \"items\",\r\n resizeColumn: \"Resize column\",\r\n noData: \"No data\",\r\n areYouSure: \"Are you sure?\",\r\n};\r\n\r\n/**\r\n * Column definition will update some props on the html element\r\n * @param {HTMLElement} el\r\n * @param {Column} column\r\n */\r\nfunction applyColumnDefinition(el, column) {\r\n if (column.width) {\r\n setAttribute(el, \"width\", column.width);\r\n }\r\n if (column.class) {\r\n addClass(el, column.class);\r\n }\r\n if (column.hidden) {\r\n setAttribute(el, \"hidden\", \"\");\r\n if (column.responsiveHidden) {\r\n addClass(el, \"dg-responsive-hidden\");\r\n }\r\n }\r\n}\r\n\r\n/**\r\n */\r\nclass DataGrid extends BaseElement {\r\n _ready() {\r\n setAttribute(this, \"id\", this.options.id ?? randstr(\"el-\"), true);\r\n\r\n /**\r\n * The grid displays that data\r\n * @type {Array}\r\n */\r\n this.data = [];\r\n /**\r\n * We store the original data in this\r\n * @type {Array}\r\n */\r\n this.originalData = [];\r\n\r\n // Make the IDE happy\r\n /**\r\n * @type {Options}\r\n */\r\n this.options = this.options || this.defaultOptions;\r\n\r\n // Init values\r\n this.fireEvents = false;\r\n this.page = this.options.defaultPage || 1;\r\n this.pages = 0;\r\n this.meta = {};\r\n /**\r\n * @type {Plugins}\r\n */\r\n this.plugins = {};\r\n // Init plugins\r\n for (const [pluginName, pluginClass] of Object.entries(plugins)) {\r\n // @ts-ignore until we can set typeof import ...\r\n this.plugins[pluginName] = new pluginClass(this);\r\n }\r\n\r\n // Expose options as observed attributes in the dom\r\n // Do it when fireEvents is disabled to avoid firing change callbacks\r\n for (const attr of DataGrid.observedAttributes) {\r\n if (attr.indexOf(\"data-\") === 0) {\r\n setAttribute(this, attr, this.options[camelize(attr.slice(5))]);\r\n }\r\n }\r\n }\r\n\r\n static template() {\r\n return `\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n`;\r\n }\r\n\r\n /**\r\n * @returns {Labels}\r\n */\r\n get labels() {\r\n return labels;\r\n }\r\n\r\n /**\r\n * @returns {Labels}\r\n */\r\n static getLabels() {\r\n return labels;\r\n }\r\n\r\n /**\r\n * @param {Object} v\r\n */\r\n static setLabels(v) {\r\n labels = Object.assign(labels, v);\r\n }\r\n\r\n /**\r\n * @returns {Column}\r\n */\r\n get defaultColumn() {\r\n return {\r\n field: \"\",\r\n title: \"\",\r\n width: 0,\r\n class: \"\",\r\n attr: \"\",\r\n hidden: false,\r\n editable: false,\r\n noSort: false,\r\n responsive: 1,\r\n responsiveHidden: false,\r\n format: \"\",\r\n transform: \"\",\r\n };\r\n }\r\n\r\n /**\r\n * @returns {Options}\r\n */\r\n get defaultOptions() {\r\n return {\r\n id: null,\r\n url: null,\r\n perPage: 10,\r\n debug: false,\r\n filter: false,\r\n menu: false,\r\n sort: false,\r\n server: false,\r\n serverParams: {\r\n start: \"start\",\r\n length: \"length\",\r\n search: \"search\",\r\n sort: \"sort\",\r\n sortDir: \"sortDir\",\r\n dataKey: \"data\",\r\n errorKey: \"error\",\r\n metaKey: \"meta\",\r\n metaTotalKey: \"total\",\r\n metaFilteredKey: \"filtered\",\r\n optionsKey: \"options\",\r\n paramsKey: \"params\",\r\n },\r\n defaultSort: \"\",\r\n reorder: false,\r\n dir: \"ltr\",\r\n perPageValues: [10, 25, 50, 100, 250],\r\n columns: [],\r\n actions: [],\r\n collapseActions: false,\r\n selectable: false,\r\n selectVisibleOnly: true,\r\n defaultPage: 1,\r\n resizable: false,\r\n autosize: true,\r\n expand: false,\r\n autoheight: true,\r\n responsive: false,\r\n responsiveToggle: true,\r\n };\r\n }\r\n\r\n /**\r\n * @param {Plugins} list\r\n */\r\n static registerPlugins(list) {\r\n plugins = list;\r\n }\r\n\r\n /**\r\n * @param {String} plugin\r\n */\r\n static unregisterPlugins(plugin = null) {\r\n if (plugin === null) {\r\n plugins = {};\r\n } else {\r\n delete plugins[plugin];\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Plugins}\r\n */\r\n static registeredPlugins() {\r\n return plugins;\r\n }\r\n\r\n /**\r\n * @param {Object|Array} columns\r\n * @returns {Column[]}\r\n */\r\n convertColumns(columns) {\r\n let cols = [];\r\n // Convert key:value objects to actual columns\r\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\r\n Object.keys(columns).forEach((key) => {\r\n let col = Object.assign({}, this.defaultColumn);\r\n col.title = columns[key];\r\n col.field = key;\r\n cols.push(col);\r\n });\r\n } else {\r\n columns.forEach((item) => {\r\n let col = Object.assign({}, this.defaultColumn);\r\n if (typeof item === \"string\") {\r\n col.title = item;\r\n col.field = item;\r\n } else if (typeof item === \"object\") {\r\n col = Object.assign(col, item);\r\n if (!col.field) {\r\n console.error(\"Invalid column definition\", item);\r\n }\r\n if (!col.title) {\r\n col.title = col.field;\r\n }\r\n } else {\r\n console.error(\"Column definition must be a string or an object\");\r\n }\r\n cols.push(col);\r\n });\r\n }\r\n return cols;\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\r\n * @returns {Array}\r\n */\r\n static get observedAttributes() {\r\n return [\r\n \"page\",\r\n \"data-filter\",\r\n \"data-sort\",\r\n \"data-debug\",\r\n \"data-reorder\",\r\n \"data-menu\",\r\n \"data-selectable\",\r\n \"data-url\",\r\n \"data-per-page\",\r\n \"data-responsive\",\r\n ];\r\n }\r\n\r\n get transformAttributes() {\r\n return {\r\n columns: (v) => this.convertColumns(convertArray(v)),\r\n actions: (v) => convertArray(v),\r\n defaultPage: (v) => parseInt(v),\r\n perPage: (v) => parseInt(v),\r\n };\r\n }\r\n\r\n get page() {\r\n return parseInt(this.getAttribute(\"page\"));\r\n }\r\n\r\n set page(val) {\r\n setAttribute(this, \"page\", this.constrainPageValue(val));\r\n }\r\n\r\n urlChanged() {\r\n this.loadData().then(() => {\r\n this.configureUi();\r\n });\r\n }\r\n\r\n constrainPageValue(v) {\r\n if (this.pages < v) {\r\n v = this.pages;\r\n }\r\n if (v < 1 || !v) {\r\n v = 1;\r\n }\r\n return v;\r\n }\r\n\r\n fixPage() {\r\n this.pages = this.totalPages();\r\n this.page = this.constrainPageValue(this.page);\r\n\r\n // Show current page in input\r\n setAttribute(this.inputPage, \"max\", this.pages);\r\n this.inputPage.value = \"\" + this.page;\r\n this.inputPage.disabled = this.pages === 1;\r\n }\r\n\r\n pageChanged() {\r\n this.reload();\r\n }\r\n\r\n responsiveChanged() {\r\n if (!this.plugins.ResponsiveGrid) {\r\n return;\r\n }\r\n if (this.options.responsive) {\r\n this.plugins.ResponsiveGrid.observe();\r\n } else {\r\n this.plugins.ResponsiveGrid.unobserve();\r\n }\r\n }\r\n\r\n menuChanged() {\r\n this.renderHeader();\r\n }\r\n\r\n /**\r\n * This is the callback for the select control\r\n */\r\n changePerPage() {\r\n this.options.perPage = parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value);\r\n this.perPageChanged();\r\n }\r\n\r\n /**\r\n * This is the actual event triggered on attribute change\r\n */\r\n perPageChanged() {\r\n // Refresh UI\r\n if (this.options.perPage !== parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value)) {\r\n this.perPageValuesChanged();\r\n }\r\n // Make sure current page is still valid\r\n let updatePage = this.page;\r\n while (updatePage > 1 && this.page * this.options.perPage > this.totalRecords()) {\r\n updatePage--;\r\n }\r\n if (updatePage != this.page) {\r\n // Triggers pageChanged, which will trigger reload\r\n this.page = updatePage;\r\n } else {\r\n // Simply reload current page\r\n this.reload(() => {\r\n // Preserve distance between top of page and select control if no fixed height\r\n if (!this.plugins.FixedHeight || !this.plugins.FixedHeight.hasFixedHeight) {\r\n this.selectPerPage.scrollIntoView();\r\n }\r\n });\r\n }\r\n }\r\n\r\n dirChanged() {\r\n setAttribute(this, \"dir\", this.options.dir);\r\n }\r\n\r\n defaultSortChanged() {\r\n this.sortChanged();\r\n }\r\n\r\n /**\r\n * Populate the select dropdown according to options\r\n */\r\n perPageValuesChanged() {\r\n if (!this.selectPerPage) {\r\n return;\r\n }\r\n while (this.selectPerPage.lastChild) {\r\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\r\n }\r\n this.options.perPageValues.forEach((v) => {\r\n addSelectOption(this.selectPerPage, v, v, v === this.options.perPage);\r\n });\r\n }\r\n\r\n _connected() {\r\n /**\r\n * @type {HTMLTableElement}\r\n */\r\n this.table = this.querySelector(\"table\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnFirst = this.querySelector(\".dg-btn-first\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnPrev = this.querySelector(\".dg-btn-prev\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnNext = this.querySelector(\".dg-btn-next\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnLast = this.querySelector(\".dg-btn-last\");\r\n /**\r\n * @type {HTMLSelectElement}\r\n */\r\n this.selectPerPage = this.querySelector(\".dg-select-per-page\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.inputPage = this.querySelector(\".dg-input-page\");\r\n\r\n this.getFirst = this.getFirst.bind(this);\r\n this.getPrev = this.getPrev.bind(this);\r\n this.getNext = this.getNext.bind(this);\r\n this.getLast = this.getLast.bind(this);\r\n this.changePerPage = this.changePerPage.bind(this);\r\n this.gotoPage = this.gotoPage.bind(this);\r\n\r\n this.btnFirst.addEventListener(\"click\", this.getFirst);\r\n this.btnPrev.addEventListener(\"click\", this.getPrev);\r\n this.btnNext.addEventListener(\"click\", this.getNext);\r\n this.btnLast.addEventListener(\"click\", this.getLast);\r\n this.selectPerPage.addEventListener(\"change\", this.changePerPage);\r\n this.inputPage.addEventListener(\"input\", this.gotoPage);\r\n\r\n Object.values(this.plugins).forEach((plugin) => {\r\n plugin.connected();\r\n });\r\n\r\n // Display even if we don't have data\r\n this.dirChanged();\r\n this.perPageValuesChanged();\r\n\r\n this.loadData().finally(() => {\r\n this.configureUi();\r\n\r\n this.sortChanged();\r\n this.filterChanged();\r\n this.reorderChanged();\r\n\r\n this.dirChanged();\r\n this.perPageValuesChanged();\r\n this.pageChanged();\r\n\r\n this.classList.add(\"dg-initialized\");\r\n this.fireEvents = true; // We can now fire attributeChangedCallback events\r\n\r\n this.log(\"initialized\");\r\n });\r\n }\r\n\r\n _disconnected() {\r\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\r\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\r\n this.btnNext.removeEventListener(\"click\", this.getNext);\r\n this.btnLast.removeEventListener(\"click\", this.getLast);\r\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage);\r\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\r\n\r\n Object.values(this.plugins).forEach((plugin) => {\r\n plugin.disconnected();\r\n });\r\n }\r\n\r\n /**\r\n * @param {string} field\r\n * @returns {Column}\r\n */\r\n getCol(field) {\r\n let found = null;\r\n this.options.columns.forEach((col) => {\r\n if (col.field == field) {\r\n found = col;\r\n }\r\n });\r\n return found;\r\n }\r\n\r\n getColProp(field, prop) {\r\n const c = this.getCol(field);\r\n return c ? c[prop] : null;\r\n }\r\n\r\n setColProp(field, prop, val) {\r\n const c = this.getCol(field);\r\n if (c) {\r\n c[prop] = val;\r\n }\r\n }\r\n\r\n visibleColumns() {\r\n return this.options.columns.filter((col) => {\r\n return !col.hidden;\r\n });\r\n }\r\n\r\n hiddenColumns() {\r\n return this.options.columns.filter((col) => {\r\n return col.hidden === true;\r\n });\r\n }\r\n\r\n showColumn(field, render = true) {\r\n this.setColProp(field, \"hidden\", false);\r\n\r\n // We need to render the whole table otherwise layout fixed won't do its job\r\n if (render) this.renderTable();\r\n\r\n dispatch(this, \"columnVisibility\", {\r\n col: field,\r\n visibility: \"visible\",\r\n });\r\n }\r\n\r\n hideColumn(field, render = true) {\r\n this.setColProp(field, \"hidden\", true);\r\n\r\n // We need to render the whole table otherwise layout fixed won't do its job\r\n if (render) this.renderTable();\r\n\r\n dispatch(this, \"columnVisibility\", {\r\n col: field,\r\n visibility: \"hidden\",\r\n });\r\n }\r\n\r\n /**\r\n * Returns the starting index of actual data\r\n * @returns {Number}\r\n */\r\n startColIndex() {\r\n let start = 1;\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n start++;\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n start++;\r\n }\r\n return start;\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isSticky() {\r\n return this.hasAttribute(\"sticky\");\r\n }\r\n\r\n /**\r\n * @param {Boolean} visibleOnly\r\n * @returns {Number}\r\n */\r\n columnsLength(visibleOnly = false) {\r\n let len = 0;\r\n // One column per (visible) column\r\n this.options.columns.forEach((col) => {\r\n if (visibleOnly && col.hidden) {\r\n return;\r\n }\r\n if (!col.attr) {\r\n len++;\r\n }\r\n });\r\n // Add one col for selectable checkbox at the beginning\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n len++;\r\n }\r\n // Add one col for actions at the end\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n len++;\r\n }\r\n // Add one col for the responsive toggle\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n len++;\r\n }\r\n return len;\r\n }\r\n\r\n /**\r\n * Global configuration and renderTable\r\n * This should be called after your data has been loaded\r\n */\r\n configureUi() {\r\n setAttribute(this.querySelector(\"table\"), \"aria-rowcount\", this.data.length);\r\n\r\n this.table.style.visibility = \"hidden\";\r\n this.renderTable();\r\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\r\n // Let the observer make the table visible\r\n } else {\r\n this.table.style.visibility = \"visible\";\r\n }\r\n\r\n // Store row height for later usage\r\n if (!this.rowHeight) {\r\n const tr = find(this, \"tbody tr\") || find(this, \"table tr\");\r\n if (tr) {\r\n this.rowHeight = tr.offsetHeight;\r\n }\r\n }\r\n }\r\n\r\n filterChanged() {\r\n const row = this.querySelector(\"thead tr.dg-head-filters\");\r\n if (this.options.filter) {\r\n removeAttribute(row, \"hidden\");\r\n } else {\r\n this.clearFilters();\r\n setAttribute(row, \"hidden\", \"\");\r\n }\r\n }\r\n\r\n reorderChanged() {\r\n const headers = findAll(this, \"thead tr.dg-head-columns th\");\r\n headers.forEach((th) => {\r\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\r\n return;\r\n }\r\n if (this.options.reorder && this.plugins.DraggableHeaders) {\r\n th.draggable = true;\r\n } else {\r\n th.removeAttribute(\"draggable\");\r\n }\r\n });\r\n }\r\n\r\n sortChanged() {\r\n this.log(\"toggle sort\");\r\n\r\n this.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\r\n const fieldName = th.getAttribute(\"field\");\r\n if (th.classList.contains(\"dg-not-sortable\") || (!this.fireEvents && fieldName == this.options.defaultSort)) {\r\n return;\r\n }\r\n if (this.options.sort && !this.getColProp(fieldName, \"noSort\")) {\r\n setAttribute(th, \"aria-sort\", \"none\");\r\n } else {\r\n removeAttribute(th, \"aria-sort\");\r\n }\r\n });\r\n }\r\n\r\n selectableChanged() {\r\n this.renderTable();\r\n }\r\n\r\n addRow(row) {\r\n this.log(\"Add row\");\r\n this.originalData.push(row);\r\n this.data = this.originalData.slice();\r\n this.sortData();\r\n }\r\n\r\n /**\r\n * @param {any} value Value to remove. Defaults to last row.\r\n * @param {String} key The key of the item to remove. Defaults to first column\r\n */\r\n removeRow(value = null, key = null) {\r\n if (key === null) {\r\n key = this.options.columns[0][\"field\"];\r\n }\r\n if (value === null) {\r\n value = this.originalData[this.originalData.length - 1][key];\r\n }\r\n this.log(\"Removing \" + key + \":\" + value);\r\n for (let i = 0; i < this.originalData.length; i++) {\r\n if (this.originalData[i][key] === value) {\r\n this.originalData.splice(i, 1);\r\n break;\r\n }\r\n }\r\n this.data = this.originalData.slice();\r\n this.sortData();\r\n }\r\n\r\n /**\r\n * @param {String} key Return a specific key (eg: id) instead of the whole row\r\n * @returns {Array}\r\n */\r\n getSelection(key = null) {\r\n if (!this.plugins.SelectableRows) {\r\n return [];\r\n }\r\n return this.plugins.SelectableRows.getSelection(key);\r\n }\r\n\r\n getData() {\r\n return this.originalData;\r\n }\r\n\r\n clearData() {\r\n // Already empty\r\n if (this.data.length === 0) {\r\n return;\r\n }\r\n this.data = this.originalData = [];\r\n this.renderBody();\r\n }\r\n\r\n refresh(cb = null) {\r\n this.data = this.originalData = [];\r\n return this.reload(cb);\r\n }\r\n\r\n reload(cb = null) {\r\n this.log(\"reload\");\r\n\r\n // If the data was cleared, we need to render again\r\n const needRender = this.originalData.length === 0;\r\n this.fixPage();\r\n this.loadData().finally(() => {\r\n // If we load data from the server, we redraw the table body\r\n // Otherwise, we just need to paginate\r\n this.options.server || needRender ? this.renderBody() : this.paginate();\r\n if (cb) {\r\n cb();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @returns {Promise}\r\n */\r\n loadData() {\r\n // We already have some data\r\n if (this.originalData.length) {\r\n // We don't use server side data\r\n if (!this.options.server || (this.options.server && !this.fireEvents)) {\r\n // if (!this.options.server) {\r\n this.log(\"skip loadData\");\r\n return new Promise((resolve) => {\r\n resolve();\r\n });\r\n }\r\n }\r\n this.log(\"loadData\");\r\n this.loading = true;\r\n this.classList.add(\"dg-loading\");\r\n return this.fetchData()\r\n .then((response) => {\r\n this.classList.remove(\"dg-loading\");\r\n this.loading = false;\r\n\r\n // We can get a straight array or an object\r\n if (Array.isArray(response)) {\r\n this.data = response;\r\n } else {\r\n // Object must contain data key\r\n if (response[this.options.serverParams.errorKey]) {\r\n this.querySelector(\"tbody\").setAttribute(\r\n \"data-empty\",\r\n response[this.options.serverParams.errorKey].replace(/^\\s+|\\r\\n|\\n|\\r$/g, \"\")\r\n );\r\n this.removeAttribute(\"data-url\");\r\n return;\r\n }\r\n if (!response[this.options.serverParams.dataKey]) {\r\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\r\n this.options.url = null;\r\n return;\r\n }\r\n\r\n // We may have a config object\r\n this.options = Object.assign(this.options, response[this.options.serverParams.optionsKey] ?? {});\r\n // It should return meta data (see metaFilteredKey)\r\n this.meta = response[this.options.serverParams.metaKey] ?? {};\r\n this.data = response[this.options.serverParams.dataKey];\r\n }\r\n this.originalData = this.data.slice();\r\n this.fixPage();\r\n\r\n // Make sure we have a proper set of columns\r\n if (this.options.columns.length === 0 && this.originalData.length) {\r\n this.options.columns = this.convertColumns(Object.keys(this.originalData[0]));\r\n } else {\r\n this.options.columns = this.convertColumns(this.options.columns);\r\n }\r\n })\r\n .catch((err) => {\r\n this.log(err);\r\n });\r\n }\r\n\r\n getFirst() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = 1;\r\n }\r\n\r\n getLast() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.pages;\r\n }\r\n\r\n getPrev() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.page - 1;\r\n }\r\n\r\n getNext() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.page + 1;\r\n }\r\n\r\n gotoPage(event) {\r\n if (event.type === \"keypress\") {\r\n const key = event.keyCode || event.key;\r\n if (key === 13 || key === \"Enter\") {\r\n event.preventDefault();\r\n } else {\r\n return;\r\n }\r\n }\r\n this.page = parseInt(this.inputPage.value);\r\n }\r\n\r\n getSort() {\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (col) {\r\n return col.getAttribute(\"field\");\r\n }\r\n return this.options.defaultSort;\r\n }\r\n\r\n getSortDir() {\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (col) {\r\n return col.getAttribute(\"aria-sort\") || \"\";\r\n }\r\n return \"\";\r\n }\r\n\r\n getFilters() {\r\n let filters = [];\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n filters[input.dataset.name] = input.value;\r\n });\r\n return filters;\r\n }\r\n\r\n clearFilters() {\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n input.value = \"\";\r\n });\r\n this.filterData();\r\n }\r\n\r\n filterData() {\r\n this.log(\"filter data\");\r\n\r\n this.page = 1;\r\n\r\n if (this.options.server) {\r\n this.reload();\r\n } else {\r\n this.data = this.originalData.slice();\r\n\r\n // Look for rows matching the filters\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n let value = input.value;\r\n if (value) {\r\n let name = input.dataset.name;\r\n this.data = this.data.filter((item) => {\r\n let str = item[name] + \"\";\r\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\r\n });\r\n }\r\n });\r\n this.pageChanged();\r\n\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (this.options.sort && col) {\r\n this.sortData();\r\n } else {\r\n this.renderBody();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Data will be sorted then rendered using renderBody\r\n * @param {Element} col The column that was clicked or null to use current sort\r\n */\r\n sortData(col = null) {\r\n this.log(\"sort data\");\r\n\r\n // Early exit\r\n if (col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\r\n this.log(\"sorting prevented because column is not sortable\");\r\n return;\r\n }\r\n if (this.plugins.ColumnResizer && this.plugins.ColumnResizer.isResizing) {\r\n this.log(\"sorting prevented because resizing\");\r\n return;\r\n }\r\n if (this.loading) {\r\n this.log(\"sorting prevented because loading\");\r\n return;\r\n }\r\n\r\n // We clicked on a column, update sort state\r\n if (col !== null) {\r\n // Remove active sort if any\r\n const haveClasses = c => [\"dg-selectable\", \"dg-actions\", \"dg-responsive-toggle\"].includes(c);\r\n this.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\r\n // @ts-ignore\r\n if ([...th.classList].some(haveClasses)) {\r\n return;\r\n }\r\n if (th !== col) {\r\n th.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n });\r\n\r\n // Set tristate col\r\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\r\n col.setAttribute(\"aria-sort\", \"ascending\");\r\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\r\n col.setAttribute(\"aria-sort\", \"descending\");\r\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\r\n col.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n } else {\r\n // Or fetch current sort\r\n col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n }\r\n\r\n if (this.options.server) {\r\n // Reload data with updated sort\r\n this.loadData().finally(() => {\r\n this.renderBody();\r\n });\r\n } else {\r\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\r\n if (sort === \"none\") {\r\n let stack = [];\r\n\r\n // Restore order while keeping filters\r\n this.originalData.some((itemA) => {\r\n this.data.some((itemB) => {\r\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\r\n stack.push(itemB);\r\n return true;\r\n }\r\n return false;\r\n });\r\n return stack.length === this.data.length;\r\n });\r\n\r\n this.data = stack;\r\n } else {\r\n const field = col.getAttribute(\"field\");\r\n this.data.sort((a, b) => {\r\n if (!isNaN(a[field]) && !isNaN(b[field])) {\r\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\r\n }\r\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\r\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\r\n\r\n switch (true) {\r\n case valA > valB:\r\n return 1;\r\n case valA < valB:\r\n return -1;\r\n case valA === valB:\r\n return 0;\r\n }\r\n });\r\n }\r\n this.renderBody();\r\n }\r\n }\r\n\r\n fetchData() {\r\n if (!this.options.url) {\r\n return new Promise((resolve, reject) => reject(\"No url set\"));\r\n }\r\n\r\n let base = window.location.href;\r\n // Fix trailing slash if no extension is present\r\n if (!base.split(\"/\").pop().includes(\".\")) {\r\n base += base.endsWith(\"/\") ? \"\" : \"/\";\r\n }\r\n let url = new URL(this.options.url, base);\r\n let params = {\r\n r: Date.now(),\r\n };\r\n if (this.options.server) {\r\n // 0 based\r\n params[this.options.serverParams.start] = this.page - 1;\r\n params[this.options.serverParams.length] = this.options.perPage;\r\n params[this.options.serverParams.search] = this.getFilters();\r\n params[this.options.serverParams.sort] = this.getSort() || \"\";\r\n params[this.options.serverParams.sortDir] = this.getSortDir();\r\n\r\n // extra params ?\r\n if (this.meta[this.options.serverParams.paramsKey]) {\r\n params = Object.assign(params, this.meta[this.options.serverParams.paramsKey]);\r\n }\r\n }\r\n\r\n appendParamsToUrl(url, params);\r\n\r\n return fetch(url)\r\n .then((response) => {\r\n if (!response.ok) {\r\n throw new Error(response.statusText);\r\n }\r\n return response.json();\r\n })\r\n .catch((err) => {\r\n return {\r\n error: err.message,\r\n };\r\n });\r\n }\r\n\r\n renderTable() {\r\n this.log(\"render table\");\r\n\r\n if (this.options.menu && this.plugins.ContextMenu) {\r\n this.plugins.ContextMenu.createMenu();\r\n }\r\n\r\n let sortedColumn;\r\n\r\n this.renderHeader();\r\n if (this.options.defaultSort) {\r\n // We can have a default sort even with sort disabled\r\n sortedColumn = this.querySelector(\"thead tr.dg-head-columns th[field='\" + this.options.defaultSort + \"']\");\r\n }\r\n\r\n if (sortedColumn) {\r\n this.sortData(sortedColumn);\r\n } else {\r\n this.renderBody();\r\n }\r\n\r\n this.renderFooter();\r\n }\r\n\r\n /**\r\n * Create table header\r\n * - One row for the column headers\r\n * - One row for the filters\r\n */\r\n renderHeader() {\r\n this.log(\"render header\");\r\n\r\n const thead = this.querySelector(\"thead\");\r\n this.createColumnHeaders(thead);\r\n this.createColumnFilters(thead);\r\n\r\n if (this.options.resizable && this.plugins.ColumnResizer) {\r\n this.plugins.ColumnResizer.renderResizer(labels.resizeColumn);\r\n }\r\n\r\n dispatch(this, \"headerRendered\");\r\n }\r\n\r\n renderFooter() {\r\n this.log(\"render footer\");\r\n\r\n const tfoot = this.querySelector(\"tfoot\");\r\n const td = tfoot.querySelector(\"td\");\r\n tfoot.removeAttribute(\"hidden\");\r\n setAttribute(td, \"colspan\", this.columnsLength(true));\r\n tfoot.style.display = \"\";\r\n }\r\n\r\n /**\r\n * Create the column headers based on column definitions and set options\r\n * @param {HTMLTableSectionElement} thead\r\n */\r\n createColumnHeaders(thead) {\r\n // @link https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively\r\n const availableWidth = this.clientWidth;\r\n const colMaxWidth = Math.round((availableWidth / this.columnsLength(true)) * 2);\r\n\r\n let idx = 0;\r\n let tr;\r\n\r\n // Create row\r\n tr = document.createElement(\"tr\");\r\n this.headerRow = tr;\r\n tr.setAttribute(\"role\", \"row\");\r\n tr.setAttribute(\"aria-rowindex\", \"1\");\r\n tr.setAttribute(\"class\", \"dg-head-columns\");\r\n\r\n // We need a real th from the dom to compute the size\r\n let sampleTh = thead.querySelector(\"tr.dg-head-columns th\");\r\n if (!sampleTh) {\r\n sampleTh = document.createElement(\"th\");\r\n thead.querySelector(\"tr\").appendChild(sampleTh);\r\n }\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createHeaderCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createHeaderCol(tr);\r\n }\r\n\r\n // Create columns\r\n idx = 0;\r\n let totalWidth = 0;\r\n this.options.columns.forEach((column) => {\r\n if (column.attr) {\r\n return;\r\n }\r\n const colIdx = idx + this.startColIndex();\r\n let th = document.createElement(\"th\");\r\n th.setAttribute(\"scope\", \"col\");\r\n th.setAttribute(\"role\", \"columnheader button\");\r\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\r\n th.setAttribute(\"id\", randstr(\"dg-col-\"));\r\n if (this.options.sort) {\r\n th.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n th.setAttribute(\"field\", column.field);\r\n if (this.plugins.ResponsiveGrid && this.options.responsive) {\r\n setAttribute(th, \"data-responsive\", column.responsive || \"\");\r\n }\r\n // Make sure the header fits (+ add some room for sort icon if necessary)\r\n const computedWidth = getTextWidth(column.title, sampleTh, true) + 20;\r\n th.dataset.minWidth = \"\" + computedWidth;\r\n applyColumnDefinition(th, column);\r\n th.tabIndex = 0;\r\n th.textContent = column.title;\r\n\r\n let w = 0;\r\n // Autosize small based on first/last row ?\r\n // Take into account minWidth of the header and max available size based on col numbers\r\n if (this.options.autosize && this.plugins.AutosizeColumn) {\r\n const colAvailableWidth = Math.min(availableWidth - totalWidth, colMaxWidth);\r\n w = this.plugins.AutosizeColumn.computeSize(th, column, parseInt(th.dataset.minWidth), colAvailableWidth);\r\n } else {\r\n w = Math.max(parseInt(th.dataset.minWidth), parseInt(th.getAttribute(\"width\")));\r\n }\r\n\r\n setAttribute(th, \"width\", w);\r\n if (column.hidden) {\r\n th.setAttribute(\"hidden\", \"\");\r\n } else {\r\n totalWidth += w;\r\n }\r\n\r\n // Reorder columns with drag/drop\r\n if (this.options.reorder && this.plugins.DraggableHeaders) {\r\n this.plugins.DraggableHeaders.makeHeaderDraggable(th);\r\n }\r\n\r\n tr.appendChild(th);\r\n idx++;\r\n });\r\n\r\n // There is too much available width, and we want to avoid fixed layout to split remaining amount\r\n if (totalWidth < availableWidth) {\r\n const visibleCols = findAll(tr, \"th:not([hidden],.dg-not-resizable)\");\r\n if (visibleCols.length) {\r\n const lastCol = visibleCols[visibleCols.length - 1];\r\n removeAttribute(lastCol, \"width\");\r\n }\r\n }\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionHeader(tr);\r\n }\r\n\r\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\r\n\r\n // Once columns are inserted, we have an actual dom to query\r\n if (thead.offsetWidth > availableWidth) {\r\n this.log(`adjust width to fix size, ${thead.offsetWidth} > ${availableWidth}`);\r\n const scrollbarWidth = this.offsetWidth - this.clientWidth;\r\n let diff = thead.offsetWidth - availableWidth - scrollbarWidth;\r\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\r\n diff += scrollbarWidth;\r\n }\r\n // Remove diff for columns that can afford it\r\n const thWithWidth = findAll(tr, \"th[width]\");\r\n thWithWidth.forEach((th) => {\r\n if (hasClass(th, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n if (diff <= 0) {\r\n return;\r\n }\r\n const actualWidth = parseInt(th.getAttribute(\"width\"));\r\n const minWidth = th.dataset.minWidth ? parseInt(th.dataset.minWidth) : 0;\r\n if (actualWidth > minWidth) {\r\n let newWidth = actualWidth - diff;\r\n if (newWidth < minWidth) {\r\n newWidth = minWidth;\r\n }\r\n diff -= actualWidth - newWidth;\r\n setAttribute(th, \"width\", newWidth);\r\n }\r\n });\r\n }\r\n\r\n // Context menu\r\n if (this.options.menu && this.plugins.ContextMenu) {\r\n this.plugins.ContextMenu.attachContextMenu();\r\n }\r\n\r\n // Sort col on click\r\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\r\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\r\n });\r\n\r\n setAttribute(this.querySelector(\"table\"), \"aria-colcount\", this.columnsLength(true));\r\n }\r\n\r\n createColumnFilters(thead) {\r\n let idx = 0;\r\n let tr;\r\n\r\n // Create row for filters\r\n tr = document.createElement(\"tr\");\r\n this.filterRow = tr;\r\n tr.setAttribute(\"role\", \"row\");\r\n tr.setAttribute(\"aria-rowindex\", \"2\");\r\n tr.setAttribute(\"class\", \"dg-head-filters\");\r\n if (!this.options.filter) {\r\n tr.setAttribute(\"hidden\", \"\");\r\n }\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createFilterCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createFilterCol(tr);\r\n }\r\n\r\n this.options.columns.forEach((column) => {\r\n if (column.attr) {\r\n return;\r\n }\r\n const colIdx = idx + this.startColIndex();\r\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + colIdx + \"']\");\r\n if (!relatedTh) {\r\n console.warn(\"Related th not found\", colIdx);\r\n return;\r\n }\r\n let th = document.createElement(\"th\");\r\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\r\n\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n // Allows binding filter to this column\r\n input.dataset.name = column.field;\r\n input.id = randstr(\"dg-filter-\");\r\n // Don't use aria-label as it triggers autocomplete\r\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\r\n if (!this.options.filter) {\r\n th.tabIndex = 0;\r\n } else {\r\n input.tabIndex = 0;\r\n }\r\n\r\n if (column.hidden) {\r\n th.setAttribute(\"hidden\", \"\");\r\n }\r\n\r\n th.appendChild(input);\r\n tr.appendChild(th);\r\n idx++;\r\n });\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionFilter(tr);\r\n }\r\n\r\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\r\n\r\n // Filter content on enter\r\n tr.querySelectorAll(\"input\").forEach((input) => {\r\n input.addEventListener(\"keypress\", (e) => {\r\n const key = e.keyCode || e.key;\r\n if (key === 13 || key === \"Enter\") {\r\n this.filterData.call(this);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Render the data as rows in tbody\r\n * It will call paginate() at the end\r\n */\r\n renderBody() {\r\n this.log(\"render body\");\r\n let tr;\r\n let td;\r\n let idx;\r\n let tbody = document.createElement(\"tbody\");\r\n\r\n this.data.forEach((item, i) => {\r\n tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n setAttribute(tr, \"aria-rowindex\", i + 1);\r\n tr.tabIndex = 0;\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createDataCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createDataCol(tr);\r\n }\r\n\r\n // Expandable\r\n if (this.options.expand) {\r\n tr.classList.add(\"dg-expandable\");\r\n\r\n on(tr, \"click\", (ev) => {\r\n if (this.plugins.ResponsiveGrid) {\r\n this.plugins.ResponsiveGrid.blockObserver();\r\n }\r\n toggleClass(ev.currentTarget, \"dg-expanded\");\r\n if (this.plugins.ResponsiveGrid) {\r\n this.plugins.ResponsiveGrid.unblockObserver();\r\n }\r\n });\r\n }\r\n\r\n idx = 0;\r\n this.options.columns.forEach((column) => {\r\n if (!column) {\r\n console.error(\"Empty column found!\", this.options.columns);\r\n }\r\n // It should be applied as an attr of the row\r\n if (column.attr) {\r\n if (item[column.field]) {\r\n // Special case if we try to write over the class attr\r\n if (column.attr === \"class\") {\r\n addClass(tr, item[column.field]);\r\n } else {\r\n tr.setAttribute(column.attr, item[column.field]);\r\n }\r\n }\r\n return;\r\n }\r\n td = document.createElement(\"td\");\r\n td.setAttribute(\"role\", \"gridcell\");\r\n td.setAttribute(\"aria-colindex\", idx + this.startColIndex());\r\n applyColumnDefinition(td, column);\r\n // This is required for pure css responsive layout\r\n td.setAttribute(\"data-name\", column.title);\r\n td.tabIndex = -1;\r\n\r\n // Inline editing\r\n if (column.editable && this.plugins.EditableColumn) {\r\n this.plugins.EditableColumn.makeEditableInput(td, column, item, i);\r\n } else {\r\n const v = item[column.field] ?? \"\";\r\n let tv;\r\n // TODO: make this modular\r\n switch (column.transform) {\r\n case \"uppercase\":\r\n tv = v.toUpperCase();\r\n break;\r\n case \"lowercase\":\r\n tv = v.toLowerCase();\r\n break;\r\n default:\r\n tv = v;\r\n break;\r\n }\r\n if (column.format && tv) {\r\n td.innerHTML = interpolate(\r\n column.format,\r\n Object.assign(\r\n {\r\n _v: v,\r\n _tv: tv,\r\n },\r\n item\r\n )\r\n );\r\n } else {\r\n td.textContent = tv;\r\n }\r\n }\r\n tr.appendChild(td);\r\n idx++;\r\n });\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionRow(tr, item);\r\n }\r\n\r\n tbody.appendChild(tr);\r\n });\r\n\r\n tbody.setAttribute(\"role\", \"rowgroup\");\r\n\r\n // Keep data empty message\r\n const prev = this.querySelector(\"tbody\");\r\n tbody.setAttribute(\"data-empty\", prev.getAttribute(\"data-empty\"));\r\n this.querySelector(\"table\").replaceChild(tbody, prev);\r\n\r\n if (this.plugins.FixedHeight) {\r\n this.plugins.FixedHeight.createFakeRow();\r\n }\r\n\r\n this.paginate();\r\n\r\n if (this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.shouldSelectAll(tbody);\r\n }\r\n\r\n dispatch(this, \"bodyRendered\");\r\n }\r\n\r\n paginate() {\r\n this.log(\"paginate\");\r\n\r\n const total = this.totalRecords();\r\n const p = this.page || 1;\r\n\r\n let index;\r\n let high = p * this.options.perPage;\r\n let low = high - this.options.perPage + 1;\r\n const tbody = this.querySelector(\"tbody\");\r\n const tfoot = this.querySelector(\"tfoot\");\r\n\r\n if (high > total) {\r\n high = total;\r\n }\r\n if (!total) {\r\n low = 0;\r\n }\r\n\r\n // Display all rows within the set indexes\r\n // For server side paginated grids, we display everything\r\n // since the server is taking care of actual pagination\r\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\r\n if (this.options.server) {\r\n removeAttribute(tr, \"hidden\");\r\n return;\r\n }\r\n index = Number(getAttribute(tr, \"aria-rowindex\"));\r\n if (index > high || index < low) {\r\n setAttribute(tr, \"hidden\", \"\");\r\n } else {\r\n removeAttribute(tr, \"hidden\");\r\n }\r\n });\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.clearCheckboxes(tbody);\r\n }\r\n\r\n // Store default height and update styles if needed\r\n if (this.plugins.FixedHeight) {\r\n this.plugins.FixedHeight.updateFakeRow();\r\n }\r\n\r\n // Enable/disable buttons if shown\r\n if (this.btnFirst) {\r\n this.btnFirst.disabled = this.page <= 1;\r\n this.btnPrev.disabled = this.page <= 1;\r\n this.btnNext.disabled = this.page >= this.pages;\r\n this.btnLast.disabled = this.page >= this.pages;\r\n }\r\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\r\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\r\n tfoot.querySelector(\".dg-total\").textContent = \"\" + this.totalRecords();\r\n }\r\n\r\n /**\r\n * @returns {number}\r\n */\r\n totalPages() {\r\n return Math.ceil(this.totalRecords() / this.options.perPage);\r\n }\r\n\r\n /**\r\n * @returns {number}\r\n */\r\n totalRecords() {\r\n if (this.options.server) {\r\n return this.meta[this.options.serverParams.metaFilteredKey] || 0;\r\n }\r\n return this.data.length;\r\n }\r\n}\r\n\r\nexport default DataGrid;\r\n", "/** @typedef {import(\"../data-grid\").default} DataGrid */\r\n\r\nclass BasePlugin {\r\n /**\r\n * @param {DataGrid} grid\r\n */\r\n constructor(grid) {\r\n this.grid = grid;\r\n }\r\n\r\n connected() {}\r\n\r\n disconnected() {}\r\n\r\n /**\r\n * Handle events within the plugin\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n}\r\n\r\nexport default BasePlugin;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport elementOffset from \"../utils/elementOffset.js\";\r\nimport {\r\n addClass,\r\n dispatch,\r\n findAll,\r\n getAttribute,\r\n hasClass,\r\n off,\r\n on,\r\n removeAttribute,\r\n removeClass,\r\n setAttribute,\r\n} from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass ColumnResizer extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.isResizing = false;\r\n }\r\n\r\n /**\r\n * @param {String} resizeLabel\r\n */\r\n renderResizer(resizeLabel) {\r\n const grid = this.grid;\r\n const table = grid.table;\r\n const cols = findAll(grid, \"thead tr.dg-head-columns th\");\r\n\r\n cols.forEach((col) => {\r\n if (hasClass(col, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n // Create a resizer element\r\n const resizer = document.createElement(\"div\");\r\n addClass(resizer, \"dg-resizer\");\r\n resizer.ariaLabel = resizeLabel;\r\n\r\n // Add a resizer element to the column\r\n col.appendChild(resizer);\r\n\r\n // Handle resizing\r\n let startX = 0;\r\n let startW = 0;\r\n let remainingSpace = 0;\r\n let max = 0;\r\n\r\n const mouseMoveHandler = (e) => {\r\n if (e.clientX > max) {\r\n return;\r\n }\r\n const newWidth = startW + (e.clientX - startX);\r\n if (col.dataset.minWidth && newWidth > parseInt(col.dataset.minWidth)) {\r\n setAttribute(col, \"width\", newWidth);\r\n }\r\n };\r\n\r\n // When user releases the mouse, remove the existing event listeners\r\n const mouseUpHandler = () => {\r\n grid.log(\"resized column\");\r\n\r\n // Prevent accidental sorting if mouse is not over resize handler\r\n setTimeout(() => {\r\n this.isResizing = false;\r\n }, 0);\r\n\r\n removeClass(resizer, \"dg-resizer-active\");\r\n if (grid.options.reorder) {\r\n col.draggable = true;\r\n }\r\n col.style.overflow = \"hidden\";\r\n\r\n // Remove handlers\r\n off(document, \"mousemove\", mouseMoveHandler);\r\n off(document, \"mouseup\", mouseUpHandler);\r\n\r\n dispatch(grid, \"columnResized\", {\r\n col: getAttribute(col, \"field\"),\r\n width: getAttribute(col, \"width\"),\r\n });\r\n };\r\n\r\n // Otherwise it could sort the col\r\n on(resizer, \"click\", (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n on(resizer, \"mousedown\", (e) => {\r\n e.stopPropagation();\r\n\r\n this.isResizing = true;\r\n\r\n const target = e.target;\r\n const currentCols = findAll(grid, \"dg-head-columns th\");\r\n const visibleCols = currentCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n const columnIndex = visibleCols.findIndex((column) => column == target.parentNode);\r\n grid.log(\"resize column\");\r\n\r\n addClass(resizer, \"dg-resizer-active\");\r\n\r\n // Make sure we don't drag it\r\n removeAttribute(col, \"draggable\");\r\n\r\n // Allow overflow when resizing\r\n col.style.overflow = \"visible\";\r\n\r\n // Show full column height (-1 to avoid scrollbar)\r\n resizer.style.height = table.offsetHeight - 1 + \"px\";\r\n\r\n // Register initial data\r\n startX = e.clientX;\r\n startW = col.offsetWidth;\r\n\r\n remainingSpace = (visibleCols.length - columnIndex) * 30;\r\n max = elementOffset(target).left + grid.offsetWidth - remainingSpace;\r\n\r\n // Remove width from next columns to allow auto layout\r\n setAttribute(col, \"width\", startW);\r\n for (let j = 0; j < visibleCols.length; j++) {\r\n if (j > columnIndex) {\r\n removeAttribute(cols[j], \"width\");\r\n }\r\n }\r\n\r\n // Attach handlers\r\n on(document, \"mousemove\", mouseMoveHandler);\r\n on(document, \"mouseup\", mouseUpHandler);\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default ColumnResizer;\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @param {String} type\r\n * @param {String} prop\r\n * @returns {HTMLElement}\r\n */\r\nexport default function getParentElement(el, type, prop = \"nodeName\") {\r\n let parent = el;\r\n while (parent[prop] != type) {\r\n parent = parent.parentElement;\r\n }\r\n return parent;\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { find, off, on, removeAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Create a right click menu on the headers\r\n */\r\nclass ContextMenu extends BasePlugin {\r\n connected() {\r\n /**\r\n * @type {HTMLUListElement}\r\n */\r\n this.menu = this.grid.querySelector(\".dg-menu\");\r\n }\r\n disconnected() {\r\n if (this.grid.headerRow) {\r\n off(this.grid.headerRow, \"contextmenu\", this);\r\n }\r\n }\r\n\r\n attachContextMenu() {\r\n const grid = this.grid;\r\n on(grid.headerRow, \"contextmenu\", this);\r\n }\r\n\r\n onchange(e) {\r\n const grid = this.grid;\r\n const t = e.target;\r\n const field = t.dataset.name;\r\n if (t.checked) {\r\n grid.showColumn(field);\r\n } else {\r\n // Prevent hidding last\r\n if (grid.visibleColumns().length <= 1) {\r\n // Restore checkbox value\r\n t.checked = true;\r\n return;\r\n }\r\n grid.hideColumn(field);\r\n }\r\n }\r\n\r\n oncontextmenu(e) {\r\n e.preventDefault();\r\n const grid = this.grid;\r\n const target = getParentElement(e.target, \"THEAD\");\r\n const menu = this.menu;\r\n const rect = target.getBoundingClientRect();\r\n let x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n\r\n menu.style.top = `${y}px`;\r\n menu.style.left = `${x}px`;\r\n\r\n removeAttribute(menu, \"hidden\");\r\n if (x + 150 > rect.width) {\r\n x -= menu.offsetWidth;\r\n menu.style.left = `${x}px`;\r\n }\r\n\r\n const documentClickHandler = (e) => {\r\n if (!menu.contains(e.target)) {\r\n setAttribute(menu, \"hidden\", \"\");\r\n off(document, \"click\", documentClickHandler);\r\n }\r\n };\r\n on(document, \"click\", documentClickHandler);\r\n }\r\n createMenu() {\r\n const grid = this.grid;\r\n const menu = this.menu;\r\n while (menu.lastChild) {\r\n menu.removeChild(menu.lastChild);\r\n }\r\n menu.addEventListener(\"change\", this);\r\n grid.options.columns.forEach((col) => {\r\n if (col.attr) {\r\n return;\r\n }\r\n const li = document.createElement(\"li\");\r\n const label = document.createElement(\"label\");\r\n const checkbox = document.createElement(\"input\");\r\n setAttribute(checkbox, \"type\", \"checkbox\");\r\n setAttribute(checkbox, \"data-name\", col.field);\r\n if (!col.hidden) {\r\n checkbox.checked = true;\r\n }\r\n const text = document.createTextNode(col.title);\r\n\r\n label.appendChild(checkbox);\r\n label.appendChild(text);\r\n\r\n li.appendChild(label);\r\n menu.appendChild(li);\r\n });\r\n }\r\n}\r\n\r\nexport default ContextMenu;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { dispatch, findAll, getAttribute, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to move headers\r\n */\r\nclass DraggableHeaders extends BasePlugin {\r\n /**\r\n * @param {HTMLTableCellElement} th\r\n */\r\n makeHeaderDraggable(th) {\r\n const grid = this.grid;\r\n th.draggable = true;\r\n on(th, \"dragstart\", (e) => {\r\n if (grid.plugins.ColumnResizer && grid.plugins.ColumnResizer.isResizing && e.preventDefault) {\r\n e.preventDefault();\r\n return;\r\n }\r\n grid.log(\"reorder col\");\r\n e.dataTransfer.effectAllowed = \"move\";\r\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\r\n });\r\n on(th, \"dragover\", (e) => {\r\n if (e.preventDefault) {\r\n e.preventDefault();\r\n }\r\n e.dataTransfer.dropEffect = \"move\";\r\n return false;\r\n });\r\n on(th, \"drop\", (e) => {\r\n if (e.stopPropagation) {\r\n e.stopPropagation();\r\n }\r\n const t = e.target;\r\n const target = getParentElement(t, \"TH\");\r\n const index = parseInt(e.dataTransfer.getData(\"text/plain\"));\r\n const targetIndex = parseInt(target.getAttribute(\"aria-colindex\"));\r\n\r\n if (index === targetIndex) {\r\n grid.log(\"reordered col stayed the same\");\r\n return;\r\n }\r\n grid.log(\"reordered col from \" + index + \" to \" + targetIndex);\r\n\r\n const offset = grid.startColIndex();\r\n const tmp = grid.options.columns[index - offset];\r\n grid.options.columns[index - offset] = grid.options.columns[targetIndex - offset];\r\n grid.options.columns[targetIndex - offset] = tmp;\r\n\r\n const swapNodes = (selector, el1) => {\r\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\r\n const el2 = grid.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\r\n setAttribute(el1, \"aria-colindex\", targetIndex);\r\n setAttribute(el2, \"aria-colindex\", index);\r\n const newNode = document.createElement(\"th\");\r\n el1.parentNode.insertBefore(newNode, el1);\r\n el2.parentNode.replaceChild(el1, el2);\r\n newNode.parentNode.replaceChild(el2, newNode);\r\n };\r\n\r\n // Swap all rows in header and body\r\n findAll(grid, \"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\r\n swapNodes(\"thead\", el1);\r\n });\r\n findAll(grid, 'tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\r\n swapNodes(\"tbody\", el1);\r\n });\r\n\r\n // Updates the columns\r\n grid.options.columns = findAll(grid, \"thead tr.dg-head-columns th[field]\").map((th) =>\r\n grid.options.columns.find((c) => c.field == getAttribute(th, \"field\"))\r\n );\r\n\r\n dispatch(grid, \"columnReordered\", {\r\n col: tmp.field,\r\n from: index,\r\n to: targetIndex,\r\n });\r\n return false;\r\n });\r\n }\r\n}\r\n\r\nexport default DraggableHeaders;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\n\r\n/**\r\n * Allows to paginate with horizontal swipe motions\r\n */\r\nclass TouchSupport extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.touch = null;\r\n }\r\n connected() {\r\n const grid = this.grid;\r\n grid.addEventListener(\"touchstart\", this, { passive: true });\r\n grid.addEventListener(\"touchmove\", this, { passive: true });\r\n }\r\n\r\n disconnected() {\r\n const grid = this.grid;\r\n grid.removeEventListener(\"touchstart\", this);\r\n grid.removeEventListener(\"touchmove\", this);\r\n }\r\n\r\n ontouchstart(e) {\r\n this.touch = e.touches[0];\r\n }\r\n\r\n ontouchmove(e) {\r\n if (!this.touch) {\r\n return;\r\n }\r\n const grid = this.grid;\r\n const xDiff = this.touch.clientX - e.touches[0].clientX;\r\n const yDiff = this.touch.clientY - e.touches[0].clientY;\r\n\r\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\r\n if (xDiff > 0) {\r\n grid.getNext();\r\n } else {\r\n grid.getPrev();\r\n }\r\n }\r\n this.touch = null;\r\n }\r\n}\r\n\r\nexport default TouchSupport;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch, findAll, hasClass, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\nconst SELECTABLE_CLASS = \"dg-selectable\";\r\nconst SELECT_ALL_CLASS = \"dg-select-all\";\r\nconst CHECKBOX_CLASS = \"form-check-input\"; //bs5\r\n\r\n/**\r\n * Allows to select rows\r\n */\r\nclass SelectableRows extends BasePlugin {\r\n disconnected() {\r\n if (this.selectAll) {\r\n this.selectAll.removeEventListener(\"change\", this);\r\n }\r\n }\r\n\r\n /**\r\n * @param {String} key Return a specific key (eg: id) instead of the whole row\r\n * @returns {Array}\r\n */\r\n getSelection(key = null) {\r\n const grid = this.grid;\r\n let selectedData = [];\r\n\r\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input:checked`);\r\n inputs.forEach((checkbox) => {\r\n const idx = parseInt(checkbox.dataset.id);\r\n const item = grid.data[idx - 1];\r\n if (!item) {\r\n console.warn(`Item ${idx} not found`);\r\n }\r\n if (key) {\r\n selectedData.push(item[key]);\r\n } else {\r\n selectedData.push(item);\r\n }\r\n });\r\n return selectedData;\r\n }\r\n\r\n /**\r\n * Uncheck box if hidden and visible only\r\n * @param {HTMLTableSectionElement} tbody\r\n */\r\n clearCheckboxes(tbody) {\r\n const grid = this.grid;\r\n if (!grid.options.selectVisibleOnly) {\r\n return;\r\n }\r\n const inputs = findAll(tbody, `tr[hidden] .${SELECTABLE_CLASS} input`);\r\n inputs.forEach((input) => {\r\n input.checked = false;\r\n });\r\n this.selectAll.checked = false;\r\n }\r\n\r\n colIndex() {\r\n return this.grid.startColIndex() - 2;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createHeaderCol(tr) {\r\n let th = document.createElement(\"th\");\r\n setAttribute(th, \"scope\", \"col\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(...[SELECTABLE_CLASS, \"dg-not-resizable\", \"dg-not-sortable\"]);\r\n th.tabIndex = 0;\r\n\r\n this.selectAll = document.createElement(\"input\");\r\n this.selectAll.type = \"checkbox\";\r\n this.selectAll.classList.add(SELECT_ALL_CLASS);\r\n this.selectAll.classList.add(CHECKBOX_CLASS);\r\n this.selectAll.addEventListener(\"change\", this);\r\n\r\n let label = document.createElement(\"label\");\r\n label.appendChild(this.selectAll);\r\n\r\n th.appendChild(label);\r\n\r\n th.setAttribute(\"width\", \"40\");\r\n tr.appendChild(th);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createFilterCol(tr) {\r\n let th = document.createElement(\"th\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(SELECTABLE_CLASS);\r\n th.tabIndex = 0;\r\n\r\n tr.appendChild(th);\r\n }\r\n\r\n /**\r\n * Handles the selectAll checkbox when any other .dg-selectable checkbox is checked on table body.\r\n * It should check selectAll if all is checked\r\n * It should uncheck selectAll if any is unchecked\r\n * @param {HTMLTableSectionElement} tbody\r\n */\r\n shouldSelectAll(tbody) {\r\n if (!this.selectAll) {\r\n return;\r\n }\r\n // Delegate listener for change events on input checkboxes\r\n tbody.addEventListener(\"change\", this);\r\n // Make sure state is up to date\r\n tbody.dispatchEvent(new Event(\"change\"));\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createDataCol(tr) {\r\n // Create col\r\n let td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell button\");\r\n setAttribute(td, \"aria-colindex\", this.colIndex());\r\n td.classList.add(SELECTABLE_CLASS);\r\n\r\n // Create input\r\n let selectOne = document.createElement(\"input\");\r\n // Alias row id for easy retrieval in getSelection\r\n selectOne.dataset.id = tr.getAttribute(\"aria-rowindex\");\r\n selectOne.type = \"checkbox\";\r\n selectOne.classList.add(CHECKBOX_CLASS);\r\n // Label need to take full space thanks to css to make the whole cell clickable\r\n let label = document.createElement(\"label\");\r\n label.classList.add(\"dg-clickable-cell\");\r\n label.appendChild(selectOne);\r\n td.appendChild(label);\r\n\r\n // Prevent unwanted click behaviour on row\r\n label.addEventListener(\"click\", this);\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n /**\r\n * @param {Event} e\r\n */\r\n onclick(e) {\r\n e.stopPropagation();\r\n }\r\n\r\n /**\r\n * Handle change event on select all or any select checkbox in the table body\r\n * @param {import(\"../utils/shortcuts.js\").FlexibleEvent} e\r\n */\r\n onchange(e) {\r\n const grid = this.grid;\r\n if (hasClass(e.target, SELECT_ALL_CLASS)) {\r\n const visibleOnly = grid.options.selectVisibleOnly;\r\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input`);\r\n inputs.forEach((cb) => {\r\n if (visibleOnly && !cb.offsetWidth) {\r\n return;\r\n }\r\n cb.checked = this.selectAll.checked;\r\n });\r\n\r\n dispatch(grid, \"rowsSelected\", {\r\n selection: this.getSelection(),\r\n });\r\n } else {\r\n if (!e.target.closest(`.${SELECTABLE_CLASS}`)) {\r\n return;\r\n }\r\n const totalCheckboxes = findAll(grid, `tbody .${SELECTABLE_CLASS} input[type=checkbox]`);\r\n // @ts-ignore\r\n const totalChecked = totalCheckboxes.filter((n) => n.checked);\r\n this.selectAll.checked = totalChecked.length == totalCheckboxes.length;\r\n\r\n dispatch(grid, \"rowsSelected\", {\r\n selection: grid.getSelection(),\r\n });\r\n }\r\n }\r\n}\r\n\r\nexport default SelectableRows;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Support for fixed table height\r\n *\r\n * We should add a fake row to push the footer down in case we don't have enough rows\r\n */\r\nclass FixedHeight extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.hasFixedHeight = false;\r\n // If we have a fixed height, make sure we have overflowY set\r\n if (grid.style.height) {\r\n grid.style.overflowY = \"auto\";\r\n this.hasFixedHeight = true;\r\n }\r\n }\r\n\r\n /**\r\n */\r\n createFakeRow() {\r\n const grid = this.grid;\r\n const tbody = grid.querySelector(\"tbody\");\r\n let tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n tr.classList.add(\"dg-fake-row\");\r\n tr.tabIndex = 0;\r\n tbody.appendChild(tr);\r\n }\r\n\r\n get fakeRow() {\r\n return this.grid.querySelector(\".dg-fake-row\");\r\n }\r\n\r\n /**\r\n * On last page, use a fake row to push footer down\r\n */\r\n updateFakeRow() {\r\n const grid = this.grid;\r\n const fakeRow = this.fakeRow;\r\n if (!fakeRow) {\r\n return;\r\n }\r\n\r\n // We don't need a fake row if we display everything\r\n if (grid.options.perPage > grid.totalRecords()) {\r\n return;\r\n }\r\n // We are not on last page\r\n if (grid.page !== grid.totalPages()) {\r\n return;\r\n }\r\n\r\n // Find remaining missing height\r\n const max = grid.options.perPage * grid.rowHeight;\r\n const visibleRows = grid.querySelectorAll(\"tbody tr:not([hidden])\").length;\r\n const fakeHeight = visibleRows > 1 ? max - visibleRows * grid.rowHeight : max;\r\n if (fakeHeight > 0) {\r\n setAttribute(fakeRow, \"height\", fakeHeight);\r\n fakeRow.removeAttribute(\"hidden\");\r\n } else {\r\n fakeRow.removeAttribute(\"height\");\r\n }\r\n }\r\n}\r\n\r\nexport default FixedHeight;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getTextWidth from \"../utils/getTextWidth.js\";\r\nimport { getAttribute, hasAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass AutosizeColumn extends BasePlugin {\r\n /**\r\n * Autosize col based on column data\r\n * @param {HTMLTableCellElement} th\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Number} min\r\n * @param {Number} max\r\n * @returns {Number}\r\n */\r\n computeSize(th, column, min, max) {\r\n const grid = this.grid;\r\n if (hasAttribute(th, \"width\")) {\r\n return getAttribute(th, \"width\");\r\n }\r\n if (!grid.data.length) {\r\n return;\r\n }\r\n const firstVal = grid.data[0];\r\n const lastVal = grid.data[grid.data.length - 1];\r\n let v = firstVal[column.field] ? firstVal[column.field].toString() : \"\";\r\n let v2 = lastVal[column.field] ? lastVal[column.field].toString() : \"\";\r\n if (v2.length > v.length) {\r\n v = v2;\r\n }\r\n let width = 0;\r\n if (v.length <= 6) {\r\n width = min;\r\n } else if (v.length > 50) {\r\n width = max;\r\n } else {\r\n // Add some extra room to have some spare space\r\n width = getTextWidth(v + \"0000\", th);\r\n }\r\n if (width > max) {\r\n width = max;\r\n }\r\n if (width < min) {\r\n width = min;\r\n }\r\n setAttribute(th, \"width\", width);\r\n return width;\r\n }\r\n}\r\n\r\nexport default AutosizeColumn;\r\n", "/**\r\n * Define a function that can be happily passed to addEventListener\r\n * @typedef {Function & EventListenerOrEventListenerObject} ExtendedFunction\r\n */\r\n\r\n/**\r\n * @param {Function} handler\r\n * @param {Number} timeout\r\n * @returns {ExtendedFunction}\r\n */\r\nexport default function debounce(handler, timeout = 300) {\r\n let timer = null;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n timer = null;\r\n handler(...args);\r\n }, timeout);\r\n };\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport debounce from \"../utils/debounce.js\";\r\nimport { addClass, ce, find, findAll, hasClass, insertAfter, removeAttribute, removeClass, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\nconst RESPONSIVE_CLASS = \"dg-responsive\";\r\n\r\nlet obsTo;\r\n\r\n/**\r\n * @param {Array} list\r\n * @returns {Array}\r\n */\r\nfunction sortByPriority(list) {\r\n return list.sort((a, b) => {\r\n const v1 = parseInt(a.dataset.responsive) || 1;\r\n const v2 = parseInt(b.dataset.responsive) || 1;\r\n return v2 - v1;\r\n });\r\n}\r\n\r\n/**\r\n * @type {ResizeObserverCallback}\r\n */\r\n//@ts-ignore\r\nconst callback = debounce((entries) => {\r\n for (const entry of entries) {\r\n /**\r\n * @type {import(\"../data-grid\").default}\r\n */\r\n // @ts-ignore\r\n const grid = entry.target;\r\n const table = grid.table;\r\n if (grid.plugins.ResponsiveGrid.observerBlocked) {\r\n return;\r\n }\r\n // check inlineSize (width) and not blockSize (height)\r\n const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;\r\n const size = parseInt(contentBoxSize.inlineSize);\r\n const tableWidth = table.offsetWidth;\r\n const realTableWidth = findAll(grid.headerRow, \"th\").reduce((result, th) => {\r\n return result + th.offsetWidth;\r\n }, 0);\r\n const diff = (realTableWidth || tableWidth) - size - 1;\r\n const minWidth = 50;\r\n const prevAction = grid.plugins.ResponsiveGrid.prevAction;\r\n // We have an array with the columns to show/hide are in order, most important first\r\n const headerCols = sortByPriority(\r\n findAll(grid.headerRow, \"th[field]\")\r\n .reverse() // Order takes precedence if no priority is set\r\n .filter((col) => {\r\n // Leave out unresponsive columns\r\n return col.dataset.responsive !== \"0\";\r\n })\r\n );\r\n let changed = false;\r\n\r\n grid.log(`table is ${tableWidth}/${realTableWidth} and available size is ${size}. Diff: ${diff}`);\r\n\r\n // The table is too big when diff has a high value, otherwise it will be like -1 or -2\r\n if (diff > 0) {\r\n if (prevAction === \"show\") {\r\n return;\r\n }\r\n grid.plugins.ResponsiveGrid.prevAction = \"hide\";\r\n let remaining = diff;\r\n let cols = headerCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\") && col.hasAttribute(\"data-responsive\");\r\n });\r\n if (cols.length === 0) {\r\n cols = headerCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n // Always keep one column\r\n if (cols.length === 1) {\r\n return;\r\n }\r\n }\r\n cols.forEach((col) => {\r\n if (remaining < 0) {\r\n return;\r\n }\r\n\r\n const colWidth = col.offsetWidth;\r\n const field = col.getAttribute(\"field\");\r\n if (!field) {\r\n return;\r\n }\r\n col.dataset.baseWidth = \"\" + col.offsetWidth;\r\n\r\n grid.hideColumn(field, false);\r\n grid.setColProp(field, \"responsiveHidden\", true);\r\n changed = true;\r\n\r\n remaining -= colWidth;\r\n remaining = Math.round(remaining);\r\n });\r\n } else {\r\n if (prevAction === \"hide\") {\r\n return;\r\n }\r\n grid.plugins.ResponsiveGrid.prevAction = \"show\";\r\n\r\n const requiredWidth =\r\n headerCols\r\n .filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n })\r\n .reduce((result, col) => {\r\n const width = col.dataset.minWidth ? parseInt(col.dataset.minWidth) : col.offsetWidth;\r\n return result + width;\r\n }, 0) + minWidth; // Add an offset so that inserting column is smoother\r\n\r\n // Compute available width to insert columns\r\n let remaining = size - requiredWidth;\r\n // Do we have any hidden column that we can restore ?\r\n headerCols\r\n .slice()\r\n .reverse() // Reverse the array to restore the columns in the proper order\r\n .filter((col) => {\r\n return col.hasAttribute(\"hidden\");\r\n })\r\n .forEach((col) => {\r\n if (remaining < minWidth) {\r\n return;\r\n }\r\n const colWidth = parseInt(col.dataset.minWidth);\r\n\r\n // We need to have enough space to restore it\r\n if (colWidth > remaining) {\r\n remaining = -1; // break loop to keep restoring in order\r\n return;\r\n }\r\n\r\n const field = col.getAttribute(\"field\");\r\n if (!field) {\r\n return;\r\n }\r\n\r\n grid.showColumn(field, false);\r\n grid.setColProp(field, \"responsiveHidden\", false);\r\n changed = true;\r\n\r\n remaining -= colWidth;\r\n remaining = Math.round(remaining);\r\n });\r\n }\r\n\r\n // Check footer\r\n const footer = find(grid.table, \"tfoot\");\r\n const realFooterWidth = findAll(grid.table, \".dg-footer > div\").reduce((result, div) => {\r\n return result + div.offsetWidth;\r\n }, 0);\r\n const availableFooterWidth = footer.offsetWidth - realFooterWidth;\r\n if (realFooterWidth > size) {\r\n addClass(footer, \"dg-footer-compact\");\r\n } else if (availableFooterWidth > 250) {\r\n removeClass(footer, \"dg-footer-compact\");\r\n }\r\n if (changed) {\r\n grid.renderTable();\r\n }\r\n // Prevent resize loop\r\n setTimeout(() => {\r\n grid.plugins.ResponsiveGrid.prevAction = null;\r\n }, 1000);\r\n grid.table.style.visibility = \"visible\";\r\n }\r\n}, 100);\r\nconst resizeObserver = new ResizeObserver(callback);\r\n\r\n/**\r\n * Responsive data grid\r\n */\r\nclass ResponsiveGrid extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.observerBlocked = false;\r\n this.prevAction = null;\r\n }\r\n\r\n connected() {\r\n if (this.grid.options.responsive) {\r\n this.observe();\r\n }\r\n }\r\n\r\n disconnected() {\r\n this.unobserve();\r\n }\r\n\r\n observe() {\r\n if (!this.grid.options.responsive) {\r\n return;\r\n }\r\n resizeObserver.observe(this.grid);\r\n this.grid.style.display = \"block\"; // Otherwise resize doesn't happen\r\n this.grid.style.overflowX = \"hidden\"; // Prevent scrollbars from appearing\r\n }\r\n\r\n unobserve() {\r\n resizeObserver.unobserve(this.grid);\r\n this.grid.style.display = \"unset\";\r\n this.grid.style.overflowX = \"unset\";\r\n }\r\n\r\n blockObserver() {\r\n this.observerBlocked = true;\r\n if (obsTo) {\r\n clearTimeout(obsTo);\r\n }\r\n }\r\n\r\n unblockObserver() {\r\n obsTo = setTimeout(() => {\r\n this.observerBlocked = false;\r\n }, 200); // more than debounce\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasHiddenColumns() {\r\n let flag = false;\r\n this.grid.options.columns.forEach((col) => {\r\n if (col.responsiveHidden) {\r\n flag = true;\r\n }\r\n });\r\n return flag;\r\n }\r\n\r\n colIndex() {\r\n return this.grid.startColIndex() - 1;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createHeaderCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n let th = ce(\"th\", tr);\r\n setAttribute(th, \"scope\", \"col\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n setAttribute(th, \"width\", \"40\");\r\n th.classList.add(...[`${RESPONSIVE_CLASS}-toggle`, \"dg-not-resizable\", \"dg-not-sortable\"]);\r\n th.tabIndex = 0;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createFilterCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n let th = ce(\"th\", tr);\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(`${RESPONSIVE_CLASS}-toggle`);\r\n th.tabIndex = 0;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createDataCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n // Create col\r\n let td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell button\");\r\n setAttribute(td, \"aria-colindex\", this.colIndex());\r\n td.classList.add(`${RESPONSIVE_CLASS}-toggle`);\r\n\r\n // Create icon\r\n td.innerHTML = `
\r\n \r\n \r\n\r\n\r\n \r\n
`;\r\n tr.appendChild(td);\r\n\r\n td.addEventListener(\"click\", this);\r\n td.addEventListener(\"mousedown\", this);\r\n }\r\n\r\n computeLabelWidth() {\r\n let idealWidth = 0;\r\n let consideredCol = 0;\r\n while (idealWidth < 120) {\r\n consideredCol++;\r\n const hCol = find(this.grid, `.dg-head-columns th[aria-colindex=\"${consideredCol}\"]`);\r\n if (hCol) {\r\n idealWidth += hCol.offsetWidth;\r\n } else {\r\n break;\r\n }\r\n }\r\n return idealWidth;\r\n }\r\n\r\n /**\r\n * @param {Event} ev\r\n */\r\n onmousedown(ev) {\r\n // Avoid selection through double click\r\n ev.preventDefault();\r\n }\r\n\r\n /**\r\n * @param {Event} ev\r\n */\r\n onclick(ev) {\r\n // Prevent expandable\r\n ev.stopPropagation();\r\n\r\n // target is the element that triggered the event (e.g., the user clicked on)\r\n // currentTarget is the element that the event listener is attached to.\r\n\r\n /**\r\n * @type {HTMLTableRowElement}\r\n */\r\n //@ts-ignore\r\n const td = ev.currentTarget;\r\n const tr = td.parentElement;\r\n const open = find(td, `.${RESPONSIVE_CLASS}-open`);\r\n const close = find(td, `.${RESPONSIVE_CLASS}-close`);\r\n\r\n this.blockObserver();\r\n\r\n const isExpanded = hasClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n if (isExpanded) {\r\n removeClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n open.style.display = \"unset\";\r\n close.style.display = \"none\";\r\n\r\n // Move back rows and cleanup row\r\n const childRow = tr.nextElementSibling;\r\n const hiddenCols = findAll(childRow, `.${RESPONSIVE_CLASS}-hidden`);\r\n hiddenCols.forEach((col) => {\r\n // We don't really need to care where we insert them since we are going to redraw anyway\r\n tr.appendChild(col);\r\n setAttribute(col, \"hidden\");\r\n });\r\n\r\n childRow.parentElement.removeChild(childRow);\r\n } else {\r\n addClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n open.style.display = \"none\";\r\n close.style.display = \"unset\";\r\n\r\n // Create a child row and move rows into it\r\n const childRow = ce(\"tr\");\r\n insertAfter(childRow, tr);\r\n addClass(childRow, `${RESPONSIVE_CLASS}-child-row`);\r\n\r\n const childRowTd = ce(\"td\", childRow);\r\n setAttribute(childRowTd, \"colspan\", this.grid.columnsLength(true));\r\n\r\n const childTable = ce(\"table\", childRowTd);\r\n addClass(childTable, `${RESPONSIVE_CLASS}-table`);\r\n\r\n const hiddenCols = findAll(tr, `.${RESPONSIVE_CLASS}-hidden`);\r\n const idealWidth = this.computeLabelWidth();\r\n hiddenCols.forEach((col) => {\r\n const childTableRow = ce(\"tr\", childTable);\r\n\r\n // Add label\r\n const label = col.dataset.name;\r\n const labelCol = ce(\"th\", childTableRow);\r\n // It looks much better when aligned with an actual col\r\n labelCol.style.width = `${idealWidth}px`;\r\n labelCol.innerHTML = label;\r\n\r\n // Add actual row\r\n childTableRow.appendChild(col);\r\n removeAttribute(col, \"hidden\");\r\n });\r\n }\r\n\r\n this.unblockObserver();\r\n }\r\n}\r\n\r\nexport default ResponsiveGrid;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport interpolate from \"../utils/interpolate.js\";\r\nimport { dispatch, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Add action on rows\r\n */\r\nclass RowActions extends BasePlugin {\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasActions() {\r\n return this.grid.options.actions.length > 0;\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionHeader(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n setAttribute(actionsTh, \"role\", \"columnheader button\");\r\n setAttribute(actionsTh, \"aria-colindex\", this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", \"dg-not-sortable\", \"dg-not-resizable\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionFilter(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n actionsTh.setAttribute(\"role\", \"columnheader button\");\r\n actionsTh.setAttribute(\"aria-colindex\", \"\" + this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n * @param {Object} item\r\n */\r\n makeActionRow(tr, item) {\r\n const labels = this.grid.labels;\r\n const td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell\");\r\n setAttribute(td, \"aria-colindex\", this.grid.columnsLength(true));\r\n td.classList.add(...[\"dg-actions\", this.actionClass]);\r\n td.tabIndex = 0;\r\n\r\n // Add menu toggle\r\n let actionsToggle = document.createElement(\"button\");\r\n actionsToggle.classList.add(\"dg-actions-toggle\");\r\n actionsToggle.innerHTML = \"\u2630\";\r\n td.appendChild(actionsToggle);\r\n on(actionsToggle, \"click\", (ev) => {\r\n ev.stopPropagation();\r\n ev.target.parentElement.classList.toggle(\"dg-actions-expand\");\r\n });\r\n\r\n this.grid.options.actions.forEach((action) => {\r\n let button = document.createElement(\"button\");\r\n if (action.html) {\r\n button.innerHTML = action.html;\r\n } else {\r\n button.innerText = action.title ?? action.name;\r\n }\r\n if (action.title) {\r\n button.title = action.title;\r\n }\r\n if (action.url) {\r\n button.type = \"submit\";\r\n button.formAction = interpolate(action.url, item);\r\n }\r\n if (action.class) {\r\n button.classList.add(...action.class.split(\" \"));\r\n }\r\n const actionHandler = (ev) => {\r\n ev.stopPropagation();\r\n if (action.confirm) {\r\n let c = confirm(labels.areYouSure);\r\n if (!c) {\r\n ev.preventDefault();\r\n return;\r\n }\r\n }\r\n dispatch(this.grid, \"action\", {\r\n data: item,\r\n action: action.name,\r\n });\r\n };\r\n button.addEventListener(\"click\", actionHandler);\r\n td.appendChild(button);\r\n\r\n // Row action\r\n if (action.default) {\r\n tr.classList.add(\"dg-actionable\");\r\n tr.addEventListener(\"click\", actionHandler);\r\n }\r\n });\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n get actionClass() {\r\n if (this.grid.options.actions.length < 3 && !this.grid.options.collapseActions) {\r\n return \"dg-actions-\" + this.grid.options.actions.length;\r\n }\r\n return \"dg-actions-more\";\r\n }\r\n}\r\n\r\nexport default RowActions;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Make editable inputs in rows\r\n */\r\nclass EditableColumn extends BasePlugin {\r\n /**\r\n *\r\n * @param {HTMLTableCellElement} td\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Object} item\r\n * @param {number} i\r\n */\r\n makeEditableInput(td, column, item, i) {\r\n const gridId = this.grid.getAttribute(\"id\");\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n input.tabIndex = 0;\r\n input.classList.add(\"dg-editable\");\r\n input.name = gridId.replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\r\n input.value = item[column.field];\r\n input.dataset.field = column.field;\r\n\r\n // Prevent row action\r\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\r\n // Enter validates edit\r\n input.addEventListener(\"keypress\", (ev) => {\r\n if (ev.type === \"keypress\") {\r\n const key = ev.keyCode || ev.key;\r\n if (key === 13 || key === \"Enter\") {\r\n input.blur();\r\n ev.preventDefault();\r\n }\r\n }\r\n });\r\n // Save on blur\r\n input.addEventListener(\"blur\", () => {\r\n // Only fire on update\r\n if (input.value == item[input.dataset.field]) {\r\n return;\r\n }\r\n // Update underlying data\r\n item[input.dataset.field] = input.value;\r\n // Notify\r\n dispatch(this.grid, \"edit\", {\r\n data: item,\r\n value: input.value,\r\n });\r\n });\r\n td.appendChild(input);\r\n }\r\n}\r\n\r\nexport default EditableColumn;\r\n", "import DataGrid from \"./src/data-grid.js\";\r\n// Optional plugins\r\nimport ColumnResizer from \"./src/plugins/column-resizer.js\";\r\nimport ContextMenu from \"./src/plugins/context-menu.js\";\r\nimport DraggableHeaders from \"./src/plugins/draggable-headers.js\";\r\nimport TouchSupport from \"./src/plugins/touch-support.js\";\r\nimport SelectableRows from \"./src/plugins/selectable-rows.js\";\r\nimport FixedHeight from \"./src/plugins/fixed-height.js\";\r\nimport AutosizeColumn from \"./src/plugins/autosize-column.js\";\r\nimport ResponsiveGrid from \"./src/plugins/responsive-grid.js\";\r\nimport RowActions from \"./src/plugins/row-actions.js\";\r\nimport EditableColumn from \"./src/plugins/editable-column.js\";\r\n\r\n// Using shorthand property names\r\n// This make them reserved and keys will be preserved\r\n// Actual class names are renamed\r\nDataGrid.registerPlugins({\r\n ColumnResizer,\r\n ContextMenu,\r\n DraggableHeaders,\r\n TouchSupport,\r\n SelectableRows,\r\n FixedHeight,\r\n AutosizeColumn,\r\n ResponsiveGrid,\r\n RowActions,\r\n EditableColumn,\r\n});\r\n\r\ncustomElements.define(\"data-grid\", DataGrid);\r\n\r\nexport default DataGrid;\r\n"], "mappings": "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", "names": ["col", "e", "th", "labels", "data_grid_default"] } diff --git a/dist/data-grid.min.js.map b/dist/data-grid.min.js.map index f35db5f..353cd20 100644 --- a/dist/data-grid.min.js.map +++ b/dist/data-grid.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/utils/camelize.js", "../src/utils/normalizeData.js", "../src/utils/shortcuts.js", "../src/core/base-element.js", "../src/utils/addSelectOption.js", "../src/utils/appendParamsToUrl.js", "../src/utils/convertArray.js", "../src/utils/elementOffset.js", "../src/utils/interpolate.js", "../src/utils/getTextWidth.js", "../src/utils/randstr.js", "../src/data-grid.js", "../src/core/base-plugin.js", "../src/plugins/column-resizer.js", "../src/utils/getParentElement.js", "../src/plugins/context-menu.js", "../src/plugins/draggable-headers.js", "../src/plugins/touch-support.js", "../src/plugins/selectable-rows.js", "../src/plugins/fixed-height.js", "../src/plugins/autosize-column.js", "../src/utils/debounce.js", "../src/plugins/responsive-grid.js", "../src/plugins/row-actions.js", "../src/plugins/editable-column.js", "../data-grid.js"], - "sourcesContent": ["/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nexport default function camelize(str) {\r\n return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());\r\n}\r\n", "/**\r\n * Parse data attribute and return properly typed data\r\n * @param {String} v\r\n * @returns {any}\r\n */\r\nexport default function normalizeData(v) {\r\n // Bool\r\n if (v === \"true\") {\r\n return true;\r\n }\r\n if (v === \"false\") {\r\n return false;\r\n }\r\n // Null or empty\r\n if (v === \"\" || v === \"null\") {\r\n return null;\r\n }\r\n // Numeric attributes\r\n if (v === Number(v).toString()) {\r\n return Number(v);\r\n }\r\n // Only attempt json parsing for array or objects\r\n if (v && [\"[\", \"{\"].includes(v.substring(0, 1))) {\r\n try {\r\n // In case we have only single quoted values, like ['one', 'two', 'three']\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(decodeURIComponent(v));\r\n } catch {\r\n console.error(\"Failed to parse \" + v);\r\n return {};\r\n }\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @typedef FlexibleHTMLProps\r\n * @property {boolean} [checked] (HTMLInputElement)\r\n * @property {string} [value] (HTMLInputElement)\r\n * @property {number} [rowHeight] (HTMLTableRowElement)\r\n *\r\n * A flexible type HTMLElement type that does not require using instanceof all over the place\r\n * Make sure that your selector is indeed valid\r\n * Only includes most commons props\r\n * @typedef {HTMLElement & FlexibleHTMLProps} FlexibleHTMLElement\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {HTMLElement&HTMLInputElement&HTMLTableRowElement} MixedHTMLElement\r\n */\r\n\r\n/**\r\n * @typedef FlexibleEventProps\r\n * @property {FlexibleHTMLElement} target\r\n * @property {FlexibleHTMLElement} currentTarget\r\n * @property {DataTransfer} [dataTransfer] (DragEvent)\r\n * @property {number} [clientX] (MouseEvent)\r\n * @property {number} [clientY] (MouseEvent)\r\n *\r\n * @typedef {Event & FlexibleEventProps} FlexibleEvent\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {Event&MouseEvent&InputEvent&DragEvent&FocusEvent&KeyboardEvent&PointerEvent} MixedEvent\r\n */\r\n\r\n/**\r\n * @callback FlexibleListener\r\n * @param {FlexibleEvent} event\r\n */\r\n\r\nclass FlexibleEventListenerObject {\r\n /**\r\n * @param {FlexibleEvent} e\r\n */\r\n handleEvent(e) {}\r\n}\r\n\r\nconst supportedPassiveTypes = [\r\n \"scroll\",\r\n \"wheel\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n \"touchenter\",\r\n \"touchend\",\r\n \"touchleave\",\r\n \"mouseout\",\r\n \"mouseleave\",\r\n \"mouseup\",\r\n \"mousedown\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mousewheel\",\r\n \"mouseover\",\r\n];\r\n\r\n/**\r\n * Automatically set passive options based on type\r\n * @param {string} type\r\n * @returns {AddEventListenerOptions}\r\n */\r\nfunction passiveOpts(type) {\r\n if (supportedPassiveTypes.includes(type)) {\r\n return { passive: true };\r\n }\r\n return {};\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {any}\r\n */\r\nexport function getAttribute(el, name) {\r\n return el.getAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasAttribute(el, name) {\r\n return el.hasAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @param {any} v\r\n * @param {Boolean} check Prevent setting if attribute is already there\r\n */\r\nexport function setAttribute(el, name, v = \"\", check = false) {\r\n if (check && hasAttribute(el, name)) return;\r\n el.setAttribute(name, \"\" + v);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeAttribute(el, name) {\r\n if (hasAttribute(el, name)) {\r\n el.removeAttribute(name);\r\n }\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function on(el, type, listener) {\r\n el.addEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function off(el, type, listener) {\r\n el.removeEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function one(el, type, listener) {\r\n el.addEventListener(type, listener, {\r\n once: true,\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {String} name\r\n * @param {any} data\r\n * @param {Boolean} bubbles\r\n */\r\nexport function dispatch(el, name, data = {}, bubbles = false) {\r\n let opts = {};\r\n if (bubbles) {\r\n opts.bubbles = true;\r\n }\r\n if (data) {\r\n opts.detail = data;\r\n }\r\n el.dispatchEvent(new CustomEvent(name, opts));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasClass(el, name) {\r\n return el.classList.contains(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function addClass(el, name) {\r\n el.classList.add(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeClass(el, name) {\r\n el.classList.remove(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function toggleClass(el, name) {\r\n el.classList.toggle(name);\r\n}\r\n\r\n/**\r\n * @param {String|HTMLElement} selector\r\n * @param {HTMLElement|Document} base\r\n * @returns {FlexibleHTMLElement|null}\r\n */\r\nexport function $(selector, base = document) {\r\n if (selector instanceof HTMLElement) {\r\n return selector;\r\n }\r\n return base.querySelector(selector);\r\n}\r\n\r\n/**\r\n * @param {String} selector\r\n * @param {Element|Document} base\r\n * @returns {Array}\r\n */\r\nexport function $$(selector, base = document) {\r\n return Array.from(base.querySelectorAll(selector));\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped element\r\n * For actual type, prefer use of el.querySelector\r\n * @param {HTMLElement} el\r\n * @param {String|HTMLElement} selector\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function find(el, selector) {\r\n return $(selector, el);\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped elements\r\n * For actual type, prefer use of el.querySelectorAll\r\n * @param {Element} el\r\n * @param {String} selector\r\n * @returns {Array}\r\n */\r\nexport function findAll(el, selector) {\r\n return $$(selector, el);\r\n}\r\n\r\n/**\r\n * @param {*} el\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function el(el) {\r\n return el;\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K} tagName\r\n * @param {HTMLElement} parent\r\n * @returns {HTMLElementTagNameMap[K]}\r\n */\r\nexport function ce(tagName, parent = null) {\r\n const el = document.createElement(tagName);\r\n if (parent) {\r\n parent.appendChild(el);\r\n }\r\n return el;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} newNode\r\n * @param {HTMLElement} existingNode\r\n */\r\nexport function insertAfter(newNode, existingNode) {\r\n existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);\r\n}\r\n", "import camelize from \"../utils/camelize.js\";\r\nimport normalizeData from \"../utils/normalizeData.js\";\r\nimport { dispatch, getAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Base element that does not contain any specific logic\r\n * related to this project but makes HTMLElemnt usable\r\n */\r\nclass BaseElement extends HTMLElement {\r\n /**\r\n * @param {Object} options\r\n */\r\n constructor(options = {}) {\r\n super();\r\n this.options = Object.assign({}, this.defaultOptions, this.normalizedDataset, options);\r\n\r\n this.log(\"constructor\");\r\n\r\n this.fireEvents = true;\r\n this._ready();\r\n\r\n this.log(\"ready\");\r\n }\r\n\r\n get defaultOptions() {\r\n return {};\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @returns {any}\r\n */\r\n getOption(opt) {\r\n return this.options[opt];\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @param {any} v\r\n */\r\n setOption(opt, v) {\r\n setAttribute(this, `data-${opt}`, v);\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n */\r\n toggleOption(opt) {\r\n setAttribute(this, `data-${opt}`, !this.getOption(opt));\r\n }\r\n\r\n get normalizedDataset() {\r\n let data = { ...this.dataset };\r\n for (var key in data) {\r\n data[key] = normalizeData(data[key]);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * @returns {String}\r\n */\r\n static template() {\r\n return \"\";\r\n }\r\n\r\n /**\r\n * This is called at the end of constructor. Extend in subclass if needed.\r\n */\r\n _ready() {}\r\n\r\n /**\r\n * @param {String|Error} message\r\n */\r\n log(message) {\r\n if (this.options.debug) {\r\n console.log(\"[\" + getAttribute(this, \"id\") + \"] \" + message);\r\n }\r\n }\r\n\r\n /**\r\n * Handle events within the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * This is called when connected. Extend in subclass if needed.\r\n */\r\n _connected() {}\r\n\r\n connectedCallback() {\r\n // ensure whenDefined callbacks run first\r\n setTimeout(() => {\r\n this.log(\"connectedCallback\");\r\n\r\n // Append only when labels had the opportunity to be set\r\n // Don't use shadow dom as it makes theming super hard\r\n const template = document.createElement(\"template\");\r\n // @ts-ignore\r\n template.innerHTML = this.constructor.template();\r\n this.appendChild(template.content.cloneNode(true));\r\n\r\n this._connected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"connected\");\r\n }, 0);\r\n }\r\n\r\n /**\r\n * This is called when disconnected. Extend in subclass if needed.\r\n */\r\n _disconnected() {}\r\n\r\n disconnectedCallback() {\r\n this.log(\"disconnectedCallback\");\r\n this._disconnected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"disconnected\");\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#a-props-like-accessor\r\n * @returns {Object}\r\n */\r\n get transformAttributes() {\r\n return {};\r\n }\r\n\r\n /**\r\n * This is only meant to work with data attributes\r\n * This allows us to have properties that reflect automatically in the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dataset-attributes\r\n * @param {String} attributeName\r\n * @param {String} oldValue\r\n * @param {String} newValue\r\n */\r\n attributeChangedCallback(attributeName, oldValue, newValue) {\r\n // It didn't change\r\n if (oldValue === newValue) {\r\n return;\r\n }\r\n\r\n this.log(\"attributeChangedCallback: \" + attributeName);\r\n\r\n let isOption = false;\r\n const transformer = this.transformAttributes[attributeName] ?? normalizeData;\r\n\r\n // Data attributes are mapped to options while other attributes are mapped as properties\r\n if (attributeName.indexOf(\"data-\") === 0) {\r\n attributeName = attributeName.slice(5);\r\n isOption = true;\r\n }\r\n attributeName = camelize(attributeName);\r\n if (isOption) {\r\n this.options[attributeName] = transformer(newValue);\r\n } else {\r\n this[attributeName] = transformer(newValue);\r\n }\r\n\r\n // Fire internal event\r\n if (this.fireEvents && this[`${attributeName}Changed`]) {\r\n this[`${attributeName}Changed`]();\r\n }\r\n }\r\n}\r\n\r\nexport default BaseElement;\r\n", "/**\r\n * @param {HTMLSelectElement} el\r\n * @param {String} value\r\n * @param {String} label\r\n * @param {Boolean} checked\r\n */\r\nexport default function addSelectOption(el, value, label, checked = false) {\r\n let opt = document.createElement(\"option\");\r\n opt.value = \"\" + value;\r\n if (checked) {\r\n opt.selected = true;\r\n }\r\n opt.label = label;\r\n el.appendChild(opt);\r\n}\r\n", "/**\r\n * @param {URL} url\r\n * @param {Object} params\r\n */\r\nexport default function appendParamsToUrl(url, params = {}) {\r\n Object.keys(params).forEach((key) => {\r\n if (Array.isArray(params[key])) {\r\n // @ts-ignore\r\n Object.keys(params[key]).forEach((k) => url.searchParams.append(isNaN(k) ? `${key}[${k}]` : key, params[key][k]));\r\n } else {\r\n url.searchParams.append(key, params[key]);\r\n }\r\n });\r\n}\r\n", "/**\r\n * Force value as arrays\r\n * @param {String|Array} v\r\n * @returns {Array}\r\n */\r\nexport default function convertArray(v) {\r\n if (typeof v === \"string\") {\r\n if (v[0] === \"[\") {\r\n // \"['my', 'value']\" would fail as a json\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(v);\r\n }\r\n\r\n return v.split(\",\");\r\n }\r\n if (!Array.isArray(v)) {\r\n console.error(\"Invalid array\", v);\r\n return [];\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @returns {Object}\r\n */\r\nexport default function elementOffset(el) {\r\n var rect = el.getBoundingClientRect(),\r\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\r\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\r\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\r\n}\r\n", "/**\r\n * Replace element within {} by their data value\r\n * @param {String} str\r\n * @param {Object} data\r\n * @returns {String}\r\n */\r\nexport default function interpolate(str, data) {\r\n return str.replace(/\\{([^}]+)?\\}/g, function ($1, $2) {\r\n return data[$2];\r\n });\r\n}\r\n", "/**\r\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\r\n * Getting computed styles only works for dom that are added in the dom\r\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\r\n * @param {String} text The text to be rendered.\r\n * @param {Element} el Target element (defaults to body)\r\n * @param {Boolean} withPadding Include padding on element\r\n * @returns {Number}\r\n */\r\nexport default function getTextWidth(text, el = document.body, withPadding = false) {\r\n if (!el) {\r\n el = document.createElement(\"div\");\r\n }\r\n const styles = window.getComputedStyle(el);\r\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\r\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\r\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\r\n\r\n let padding = 0;\r\n if (withPadding) {\r\n const paddingLeft = styles.getPropertyValue(\"padding-left\") || \"0\";\r\n const paddingRight = styles.getPropertyValue(\"padding-right\") || \"0\";\r\n padding = parseInt(paddingLeft) + parseInt(paddingRight);\r\n }\r\n\r\n // re-use canvas object for better performance\r\n // @ts-ignore\r\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement(\"canvas\"));\r\n const context = canvas.getContext(\"2d\");\r\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\r\n const metrics = context.measureText(text);\r\n return parseInt(metrics.width) + padding;\r\n}\r\n", "/**\r\n * @param {String} prefix\r\n * @returns {String}\r\n */\r\nexport default function randstr(prefix) {\r\n return Math.random()\r\n .toString(36)\r\n .replace(\"0.\", prefix || \"\");\r\n}\r\n", "/**\n * Data Grid Web component\n *\n * Credits for inspiration\n * @link https://github.com/riverside/zino-grid\n */\n\"use strict\";\n\nimport BaseElement from \"./core/base-element.js\";\nimport addSelectOption from \"./utils/addSelectOption.js\";\nimport appendParamsToUrl from \"./utils/appendParamsToUrl.js\";\nimport camelize from \"./utils/camelize.js\";\nimport convertArray from \"./utils/convertArray.js\";\nimport elementOffset from \"./utils/elementOffset.js\";\nimport interpolate from \"./utils/interpolate.js\";\nimport getTextWidth from \"./utils/getTextWidth.js\";\nimport randstr from \"./utils/randstr.js\";\nimport {\n dispatch,\n find,\n findAll,\n hasClass,\n removeAttribute,\n getAttribute,\n setAttribute,\n addClass,\n toggleClass,\n on,\n} from \"./utils/shortcuts.js\";\n\n/**\n * Column definition\n * @typedef Column\n * @property {String} field - the key in the data\n * @property {String} title - the title to display in the header (defaults to \"field\" if not set)\n * @property {Number} width - the width of the column (auto otherwise)\n * @property {String} class - class to set on the column (target body or header with th.class or td.class)\n * @property {String} attr - don't render the column and set a matching attribute on the row with the value of the field\n * @property {Boolean} hidden - hide the column\n * @property {Boolean} noSort - allow disabling sort for a given column\n * @property {String} format - custom data formatting\n * @property {String} transform - custom value transformation\n * @property {Boolean} editable - replace with input (EditableColumn module)\n * @property {Number} responsive - the higher the value, the sooner it will be hidden, disable with 0 (ResponsiveGrid module)\n * @property {Boolean} responsiveHidden - hidden through responsive module (ResponsiveGrid module)\n */\n\n/**\n * Row action\n * @typedef Action\n * @property {String} title - the title of the button\n * @property {String} name - the name of the action\n * @property {String} class - the class for the button\n * @property {String} url - link for the action\n * @property {String} html - custom button data\n * @property {Boolean} confirm - needs confirmation\n * @property {Boolean} default - is the default row action\n */\n\n/** @typedef {import('./plugins/autosize-column').default} AutosizeColumn */\n/** @typedef {import('./plugins/column-resizer').default} ColumnResizer */\n/** @typedef {import('./plugins/context-menu').default} ContextMenu */\n/** @typedef {import('./plugins/draggable-headers').default} DraggableHeaders */\n/** @typedef {import('./plugins/editable-column').default} EditableColumn */\n/** @typedef {import('./plugins/fixed-height').default} FixedHeight */\n/** @typedef {import('./plugins/responsive-grid').default} ResponsiveGrid */\n/** @typedef {import('./plugins/row-actions').default} RowActions */\n/** @typedef {import('./plugins/selectable-rows').default} SelectableRows */\n/** @typedef {import('./plugins/touch-support').default} TouchSupport */\n\n/**\n * These plugins are all optional\n * @typedef {Object} Plugins\n * @property {ColumnResizer} [ColumnResizer] resize handlers in the headers\n * @property {ContextMenu} [ContextMenu] menu to show/hide columns\n * @property {DraggableHeaders} [DraggableHeaders] draggable headers columns\n * @property {EditableColumn} [EditableColumn] draggable headers columns\n * @property {TouchSupport} [TouchSupport] touch swipe\n * @property {SelectableRows} [SelectableRows] create a column with checkboxes to select rows\n * @property {FixedHeight} [FixedHeight] allows having fixed height tables\n * @property {AutosizeColumn} [AutosizeColumn] compute ideal width based on column content\n * @property {ResponsiveGrid} [ResponsiveGrid] hide/show column on the fly\n * @property {RowActions} [RowActions] add action on rows\n */\n\n/**\n * Parameters to pass along or receive from the server\n * @typedef ServerParams\n * @property {String} serverParams.start\n * @property {String} serverParams.length\n * @property {String} serverParams.search\n * @property {String} serverParams.sort\n * @property {String} serverParams.sortDir\n * @property {String} serverParams.dataKey\n * @property {String} serverParams.errorKey\n * @property {String} serverParams.metaKey\n * @property {String} serverParams.metaTotalKey\n * @property {String} serverParams.metaFilteredKey\n * @property {String} serverParams.optionsKey\n * @property {String} serverParams.paramsKey\n */\n\n/**\n * Available data grid options, plugins included\n * @typedef Options\n * @property {?String} id Custom id for the grid\n * @property {?String} url An URL with data to display in JSON format\n * @property {Boolean} debug Log actions in DevTools console\n * @property {Boolean} filter Allows a filtering functionality\n * @property {Boolean} sort Allows a sort by column functionality\n * @property {String} defaultSort Default sort field if sorting is enabled\n * @property {Boolean} server Is a server side powered grid\n * @property {ServerParams} serverParams Describe keys passed to the server backend\n * @property {String} dir Dir\n * @property {Array} perPageValues Available per page options\n * @property {Column[]} columns Available columns\n * @property {Number} defaultPage Starting page\n * @property {Number} perPage Number of records displayed per page\n * @property {Boolean} expand Allow cell content to spawn over multiple lines\n * @property {Action[]} actions Row actions (RowActions module)\n * @property {Boolean} collapseActions Group actions (RowActions module)\n * @property {Boolean} resizable Make columns resizable (ColumnResizer module)\n * @property {Boolean} selectable Allow selecting rows with a checkbox (SelectableRows module)\n * @property {Boolean} selectVisibleOnly Select all only selects visible rows (SelectableRows module)\n * @property {Boolean} autosize Compute column sizes based on given data (Autosize module)\n * @property {Boolean} autoheight Adjust height so that it matches table size (FixedHeight module)\n * @property {Boolean} menu Right click menu on column headers (ContextMenu module)\n * @property {Boolean} reorder Allows a column reordering functionality (DraggableHeaders module)\n * @property {Boolean} responsive Change display mode on small screens (ResponsiveGrid module)\n * @property {Boolean} responsiveToggle Show toggle column (ResponsiveGrid module)\n */\n\n/**\n * Available labels that can be translated\n * @typedef Labels\n * @property {String} itemsPerPage\n * @property {String} gotoPage\n * @property {String} gotoFirstPage\n * @property {String} gotoPrevPage\n * @property {String} gotoNextPage\n * @property {String} gotoLastPage\n * @property {String} of\n * @property {String} items\n * @property {String} resizeColumn\n * @property {String} noData\n * @property {String} areYouSure\n */\n\n/**\n * List of registered plugins\n * @type {Plugins}\n */\nlet plugins = {};\n\n/**\n * @type {Labels}\n */\nlet labels = {\n itemsPerPage: \"Items per page\",\n gotoPage: \"Go to page\",\n gotoFirstPage: \"Go to first page\",\n gotoPrevPage: \"Go to previous page\",\n gotoNextPage: \"Go to next page\",\n gotoLastPage: \"Go to last page\",\n of: \"of\",\n items: \"items\",\n resizeColumn: \"Resize column\",\n noData: \"No data\",\n areYouSure: \"Are you sure?\",\n};\n\n/**\n * Column definition will update some props on the html element\n * @param {HTMLElement} el\n * @param {Column} column\n */\nfunction applyColumnDefinition(el, column) {\n if (column.width) {\n setAttribute(el, \"width\", column.width);\n }\n if (column.class) {\n addClass(el, column.class);\n }\n if (column.hidden) {\n setAttribute(el, \"hidden\", \"\");\n if (column.responsiveHidden) {\n addClass(el, \"dg-responsive-hidden\");\n }\n }\n}\n\n/**\n */\nclass DataGrid extends BaseElement {\n _ready() {\n setAttribute(this, \"id\", this.options.id ?? randstr(\"el-\"), true);\n\n /**\n * The grid displays that data\n * @type {Array}\n */\n this.data = [];\n /**\n * We store the original data in this\n * @type {Array}\n */\n this.originalData = [];\n\n // Make the IDE happy\n /**\n * @type {Options}\n */\n this.options = this.options || this.defaultOptions;\n\n // Init values\n this.fireEvents = false;\n this.page = this.options.defaultPage || 1;\n this.pages = 0;\n this.meta = {};\n /**\n * @type {Plugins}\n */\n this.plugins = {};\n // Init plugins\n for (const [pluginName, pluginClass] of Object.entries(plugins)) {\n // @ts-ignore until we can set typeof import ...\n this.plugins[pluginName] = new pluginClass(this);\n }\n\n // Expose options as observed attributes in the dom\n // Do it when fireEvents is disabled to avoid firing change callbacks\n for (const attr of DataGrid.observedAttributes) {\n if (attr.indexOf(\"data-\") === 0) {\n setAttribute(this, attr, this.options[camelize(attr.slice(5))]);\n }\n }\n }\n\n static template() {\n return `\n\n \n \n \n \n \n \n \n \n \n \n \n
\n`;\n }\n\n /**\n * @returns {Labels}\n */\n get labels() {\n return labels;\n }\n\n /**\n * @returns {Labels}\n */\n static getLabels() {\n return labels;\n }\n\n /**\n * @param {Object} v\n */\n static setLabels(v) {\n labels = Object.assign(labels, v);\n }\n\n /**\n * @returns {Column}\n */\n get defaultColumn() {\n return {\n field: \"\",\n title: \"\",\n width: 0,\n class: \"\",\n attr: \"\",\n hidden: false,\n editable: false,\n noSort: false,\n responsive: 1,\n responsiveHidden: false,\n format: \"\",\n transform: \"\",\n };\n }\n\n /**\n * @returns {Options}\n */\n get defaultOptions() {\n return {\n id: null,\n url: null,\n perPage: 10,\n debug: false,\n filter: false,\n menu: false,\n sort: false,\n server: false,\n serverParams: {\n start: \"start\",\n length: \"length\",\n search: \"search\",\n sort: \"sort\",\n sortDir: \"sortDir\",\n dataKey: \"data\",\n errorKey: \"error\",\n metaKey: \"meta\",\n metaTotalKey: \"total\",\n metaFilteredKey: \"filtered\",\n optionsKey: \"options\",\n paramsKey: \"params\",\n },\n defaultSort: \"\",\n reorder: false,\n dir: \"ltr\",\n perPageValues: [10, 25, 50, 100, 250],\n columns: [],\n actions: [],\n collapseActions: false,\n selectable: false,\n selectVisibleOnly: true,\n defaultPage: 1,\n resizable: false,\n autosize: true,\n expand: false,\n autoheight: true,\n responsive: false,\n responsiveToggle: true,\n };\n }\n\n /**\n * @param {Plugins} list\n */\n static registerPlugins(list) {\n plugins = list;\n }\n\n /**\n * @param {String} plugin\n */\n static unregisterPlugins(plugin = null) {\n if (plugin === null) {\n plugins = {};\n } else {\n delete plugins[plugin];\n }\n }\n\n /**\n * @returns {Plugins}\n */\n static registeredPlugins() {\n return plugins;\n }\n\n /**\n * @param {Object|Array} columns\n * @returns {Column[]}\n */\n convertColumns(columns) {\n let cols = [];\n // Convert key:value objects to actual columns\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\n Object.keys(columns).forEach((key) => {\n let col = Object.assign({}, this.defaultColumn);\n col.title = columns[key];\n col.field = key;\n cols.push(col);\n });\n } else {\n columns.forEach((item) => {\n let col = Object.assign({}, this.defaultColumn);\n if (typeof item === \"string\") {\n col.title = item;\n col.field = item;\n } else if (typeof item === \"object\") {\n col = Object.assign(col, item);\n if (!col.field) {\n console.error(\"Invalid column definition\", item);\n }\n if (!col.title) {\n col.title = col.field;\n }\n } else {\n console.error(\"Column definition must be a string or an object\");\n }\n cols.push(col);\n });\n }\n return cols;\n }\n\n /**\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\n * @returns {Array}\n */\n static get observedAttributes() {\n return [\n \"page\",\n \"data-filter\",\n \"data-sort\",\n \"data-debug\",\n \"data-reorder\",\n \"data-menu\",\n \"data-selectable\",\n \"data-url\",\n \"data-per-page\",\n \"data-responsive\",\n ];\n }\n\n get transformAttributes() {\n return {\n columns: (v) => this.convertColumns(convertArray(v)),\n actions: (v) => convertArray(v),\n defaultPage: (v) => parseInt(v),\n perPage: (v) => parseInt(v),\n };\n }\n\n get page() {\n return parseInt(this.getAttribute(\"page\"));\n }\n\n set page(val) {\n setAttribute(this, \"page\", this.constrainPageValue(val));\n }\n\n urlChanged() {\n this.loadData().then(() => {\n this.configureUi();\n });\n }\n\n constrainPageValue(v) {\n if (this.pages < v) {\n v = this.pages;\n }\n if (v < 1 || !v) {\n v = 1;\n }\n return v;\n }\n\n fixPage() {\n this.pages = this.totalPages();\n this.page = this.constrainPageValue(this.page);\n\n // Show current page in input\n setAttribute(this.inputPage, \"max\", this.pages);\n this.inputPage.value = \"\" + this.page;\n this.inputPage.disabled = this.pages === 1;\n }\n\n pageChanged() {\n this.reload();\n }\n\n responsiveChanged() {\n if (!this.plugins.ResponsiveGrid) {\n return;\n }\n if (this.options.responsive) {\n this.plugins.ResponsiveGrid.observe();\n } else {\n this.plugins.ResponsiveGrid.unobserve();\n }\n }\n\n menuChanged() {\n this.renderHeader();\n }\n\n /**\n * This is the callback for the select control\n */\n changePerPage() {\n this.options.perPage = parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value);\n this.perPageChanged();\n }\n\n /**\n * This is the actual event triggered on attribute change\n */\n perPageChanged() {\n // Refresh UI\n if (this.options.perPage !== parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value)) {\n this.perPageValuesChanged();\n }\n // Make sure current page is still valid\n let updatePage = this.page;\n while (updatePage > 1 && this.page * this.options.perPage > this.totalRecords()) {\n updatePage--;\n }\n if (updatePage != this.page) {\n // Triggers pageChanged, which will trigger reload\n this.page = updatePage;\n } else {\n // Simply reload current page\n this.reload(() => {\n // Preserve distance between top of page and select control if no fixed height\n if (!this.plugins.FixedHeight || !this.plugins.FixedHeight.hasFixedHeight) {\n this.selectPerPage.scrollIntoView();\n }\n });\n }\n }\n\n dirChanged() {\n setAttribute(this, \"dir\", this.options.dir);\n }\n\n defaultSortChanged() {\n this.sortChanged();\n }\n\n /**\n * Populate the select dropdown according to options\n */\n perPageValuesChanged() {\n if (!this.selectPerPage) {\n return;\n }\n while (this.selectPerPage.lastChild) {\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\n }\n this.options.perPageValues.forEach((v) => {\n addSelectOption(this.selectPerPage, v, v, v === this.options.perPage);\n });\n }\n\n _connected() {\n /**\n * @type {HTMLTableElement}\n */\n this.table = this.querySelector(\"table\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnFirst = this.querySelector(\".dg-btn-first\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnPrev = this.querySelector(\".dg-btn-prev\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnNext = this.querySelector(\".dg-btn-next\");\n /**\n * @type {HTMLInputElement}\n */\n this.btnLast = this.querySelector(\".dg-btn-last\");\n /**\n * @type {HTMLSelectElement}\n */\n this.selectPerPage = this.querySelector(\".dg-select-per-page\");\n /**\n * @type {HTMLInputElement}\n */\n this.inputPage = this.querySelector(\".dg-input-page\");\n\n this.getFirst = this.getFirst.bind(this);\n this.getPrev = this.getPrev.bind(this);\n this.getNext = this.getNext.bind(this);\n this.getLast = this.getLast.bind(this);\n this.changePerPage = this.changePerPage.bind(this);\n this.gotoPage = this.gotoPage.bind(this);\n\n this.btnFirst.addEventListener(\"click\", this.getFirst);\n this.btnPrev.addEventListener(\"click\", this.getPrev);\n this.btnNext.addEventListener(\"click\", this.getNext);\n this.btnLast.addEventListener(\"click\", this.getLast);\n this.selectPerPage.addEventListener(\"change\", this.changePerPage);\n this.inputPage.addEventListener(\"input\", this.gotoPage);\n\n Object.values(this.plugins).forEach((plugin) => {\n plugin.connected();\n });\n\n // Display even if we don't have data\n this.dirChanged();\n this.perPageValuesChanged();\n\n this.loadData().finally(() => {\n this.configureUi();\n\n this.sortChanged();\n this.filterChanged();\n this.reorderChanged();\n\n this.dirChanged();\n this.perPageValuesChanged();\n this.pageChanged();\n\n this.classList.add(\"dg-initialized\");\n this.fireEvents = true; // We can now fire attributeChangedCallback events\n\n this.log(\"initialized\");\n });\n }\n\n _disconnected() {\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\n this.btnNext.removeEventListener(\"click\", this.getNext);\n this.btnLast.removeEventListener(\"click\", this.getLast);\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage);\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\n\n Object.values(this.plugins).forEach((plugin) => {\n plugin.disconnected();\n });\n }\n\n /**\n * @param {string} field\n * @returns {Column}\n */\n getCol(field) {\n let found = null;\n this.options.columns.forEach((col) => {\n if (col.field == field) {\n found = col;\n }\n });\n return found;\n }\n\n getColProp(field, prop) {\n const c = this.getCol(field);\n return c ? c[prop] : null;\n }\n\n setColProp(field, prop, val) {\n const c = this.getCol(field);\n if (c) {\n c[prop] = val;\n }\n }\n\n visibleColumns() {\n return this.options.columns.filter((col) => {\n return !col.hidden;\n });\n }\n\n hiddenColumns() {\n return this.options.columns.filter((col) => {\n return col.hidden === true;\n });\n }\n\n showColumn(field, render = true) {\n this.setColProp(field, \"hidden\", false);\n\n // We need to render the whole table otherwise layout fixed won't do its job\n if (render) this.renderTable();\n\n dispatch(this, \"columnVisibility\", {\n col: field,\n visibility: \"visible\",\n });\n }\n\n hideColumn(field, render = true) {\n this.setColProp(field, \"hidden\", true);\n\n // We need to render the whole table otherwise layout fixed won't do its job\n if (render) this.renderTable();\n\n dispatch(this, \"columnVisibility\", {\n col: field,\n visibility: \"hidden\",\n });\n }\n\n /**\n * Returns the starting index of actual data\n * @returns {Number}\n */\n startColIndex() {\n let start = 1;\n if (this.options.selectable && this.plugins.SelectableRows) {\n start++;\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n start++;\n }\n return start;\n }\n\n /**\n * @returns {Boolean}\n */\n isSticky() {\n return this.hasAttribute(\"sticky\");\n }\n\n /**\n * @param {Boolean} visibleOnly\n * @returns {Number}\n */\n columnsLength(visibleOnly = false) {\n let len = 0;\n // One column per (visible) column\n this.options.columns.forEach((col) => {\n if (visibleOnly && col.hidden) {\n return;\n }\n if (!col.attr) {\n len++;\n }\n });\n // Add one col for selectable checkbox at the beginning\n if (this.options.selectable && this.plugins.SelectableRows) {\n len++;\n }\n // Add one col for actions at the end\n if (this.options.actions.length && this.plugins.RowActions) {\n len++;\n }\n // Add one col for the responsive toggle\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n len++;\n }\n return len;\n }\n\n /**\n * Global configuration and renderTable\n * This should be called after your data has been loaded\n */\n configureUi() {\n setAttribute(this.querySelector(\"table\"), \"aria-rowcount\", this.data.length);\n\n this.table.style.visibility = \"hidden\";\n this.renderTable();\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\n // Let the observer make the table visible\n } else {\n this.table.style.visibility = \"visible\";\n }\n\n // Store row height for later usage\n if (!this.rowHeight) {\n const tr = find(this, \"tbody tr\") || find(this, \"table tr\");\n if (tr) {\n this.rowHeight = tr.offsetHeight;\n }\n }\n }\n\n filterChanged() {\n const row = this.querySelector(\"thead tr.dg-head-filters\");\n if (this.options.filter) {\n removeAttribute(row, \"hidden\");\n } else {\n this.clearFilters();\n setAttribute(row, \"hidden\", \"\");\n }\n }\n\n reorderChanged() {\n const headers = findAll(this, \"thead tr.dg-head-columns th\");\n headers.forEach((th) => {\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\n return;\n }\n if (this.options.reorder && this.plugins.DraggableHeaders) {\n th.draggable = true;\n } else {\n th.removeAttribute(\"draggable\");\n }\n });\n }\n\n sortChanged() {\n this.log(\"toggle sort\");\n\n this.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\n const fieldName = th.getAttribute(\"field\");\n if (th.classList.contains(\"dg-not-sortable\") || (!this.fireEvents && fieldName == this.options.defaultSort)) {\n return;\n }\n if (this.options.sort && !this.getColProp(fieldName, \"noSort\")) {\n setAttribute(th, \"aria-sort\", \"none\");\n } else {\n removeAttribute(th, \"aria-sort\");\n }\n });\n }\n\n selectableChanged() {\n this.renderTable();\n }\n\n addRow(row) {\n this.log(\"Add row\");\n this.originalData.push(row);\n this.data = this.originalData.slice();\n this.sortData();\n }\n\n /**\n * @param {any} value Value to remove. Defaults to last row.\n * @param {String} key The key of the item to remove. Defaults to first column\n */\n removeRow(value = null, key = null) {\n if (key === null) {\n key = this.options.columns[0][\"field\"];\n }\n if (value === null) {\n value = this.originalData[this.originalData.length - 1][key];\n }\n this.log(\"Removing \" + key + \":\" + value);\n for (let i = 0; i < this.originalData.length; i++) {\n if (this.originalData[i][key] === value) {\n this.originalData.splice(i, 1);\n break;\n }\n }\n this.data = this.originalData.slice();\n this.sortData();\n }\n\n /**\n * @param {String} key Return a specific key (eg: id) instead of the whole row\n * @returns {Array}\n */\n getSelection(key = null) {\n if (!this.plugins.SelectableRows) {\n return [];\n }\n return this.plugins.SelectableRows.getSelection(key);\n }\n\n getData() {\n return this.originalData;\n }\n\n clearData() {\n // Already empty\n if (this.data.length === 0) {\n return;\n }\n this.data = this.originalData = [];\n this.renderBody();\n }\n\n refresh(cb = null) {\n this.data = this.originalData = [];\n return this.reload(cb);\n }\n\n reload(cb = null) {\n this.log(\"reload\");\n\n // If the data was cleared, we need to render again\n const needRender = this.originalData.length === 0;\n this.fixPage();\n this.loadData().finally(() => {\n // If we load data from the server, we redraw the table body\n // Otherwise, we just need to paginate\n this.options.server || needRender ? this.renderBody() : this.paginate();\n if (cb) {\n cb();\n }\n });\n }\n\n /**\n * @returns {Promise}\n */\n loadData() {\n // We already have some data\n if (this.originalData.length) {\n // We don't use server side data\n if (!this.options.server || (this.options.server && !this.fireEvents)) {\n // if (!this.options.server) {\n this.log(\"skip loadData\");\n return new Promise((resolve) => {\n resolve();\n });\n }\n }\n this.log(\"loadData\");\n this.loading = true;\n this.classList.add(\"dg-loading\");\n return this.fetchData()\n .then((response) => {\n this.classList.remove(\"dg-loading\");\n this.loading = false;\n\n // We can get a straight array or an object\n if (Array.isArray(response)) {\n this.data = response;\n } else {\n // Object must contain data key\n if (response[this.options.serverParams.errorKey]) {\n this.querySelector(\"tbody\").setAttribute(\n \"data-empty\",\n response[this.options.serverParams.errorKey].replace(/^\\s+|\\r\\n|\\n|\\r$/g, \"\")\n );\n this.removeAttribute(\"data-url\");\n return;\n }\n if (!response[this.options.serverParams.dataKey]) {\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\n this.options.url = null;\n return;\n }\n\n // We may have a config object\n this.options = Object.assign(this.options, response[this.options.serverParams.optionsKey] ?? {});\n // It should return meta data (see metaFilteredKey)\n this.meta = response[this.options.serverParams.metaKey] ?? {};\n this.data = response[this.options.serverParams.dataKey];\n }\n this.originalData = this.data.slice();\n this.fixPage();\n\n // Make sure we have a proper set of columns\n if (this.options.columns.length === 0 && this.originalData.length) {\n this.options.columns = this.convertColumns(Object.keys(this.originalData[0]));\n } else {\n this.options.columns = this.convertColumns(this.options.columns);\n }\n })\n .catch((err) => {\n this.log(err);\n });\n }\n\n getFirst() {\n if (this.loading) {\n return;\n }\n this.page = 1;\n }\n\n getLast() {\n if (this.loading) {\n return;\n }\n this.page = this.pages;\n }\n\n getPrev() {\n if (this.loading) {\n return;\n }\n this.page = this.page - 1;\n }\n\n getNext() {\n if (this.loading) {\n return;\n }\n this.page = this.page + 1;\n }\n\n gotoPage(event) {\n if (event.type === \"keypress\") {\n const key = event.keyCode || event.key;\n if (key === 13 || key === \"Enter\") {\n event.preventDefault();\n } else {\n return;\n }\n }\n this.page = parseInt(this.inputPage.value);\n }\n\n getSort() {\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"field\");\n }\n return this.options.defaultSort;\n }\n\n getSortDir() {\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (col) {\n return col.getAttribute(\"aria-sort\") || \"\";\n }\n return \"\";\n }\n\n getFilters() {\n let filters = [];\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n filters[input.dataset.name] = input.value;\n });\n return filters;\n }\n\n clearFilters() {\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n input.value = \"\";\n });\n this.filterData();\n }\n\n filterData() {\n this.log(\"filter data\");\n\n this.page = 1;\n\n if (this.options.server) {\n this.reload();\n } else {\n this.data = this.originalData.slice();\n\n // Look for rows matching the filters\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\n inputs.forEach((input) => {\n let value = input.value;\n if (value) {\n let name = input.dataset.name;\n this.data = this.data.filter((item) => {\n let str = item[name] + \"\";\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\n });\n }\n });\n this.pageChanged();\n\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n if (this.options.sort && col) {\n this.sortData();\n } else {\n this.renderBody();\n }\n }\n }\n\n /**\n * Data will be sorted then rendered using renderBody\n * @param {Element} col The column that was clicked or null to use current sort\n */\n sortData(col = null) {\n this.log(\"sort data\");\n\n // Early exit\n if (col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\n this.log(\"sorting prevented because column is not sortable\");\n return;\n }\n if (this.plugins.ColumnResizer && this.plugins.ColumnResizer.isResizing) {\n this.log(\"sorting prevented because resizing\");\n return;\n }\n if (this.loading) {\n this.log(\"sorting prevented because loading\");\n return;\n }\n\n // We clicked on a column, update sort state\n if (col !== null) {\n // Remove active sort if any\n const haveClasses = c => [\"dg-selectable\", \"dg-actions\", \"dg-responsive-toggle\"].includes(c);\n this.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\n // @ts-ignore\n if ([...th.classList].some(haveClasses)) {\n return;\n }\n if (th !== col) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n });\n\n // Set tristate col\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\n col.setAttribute(\"aria-sort\", \"ascending\");\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\n col.setAttribute(\"aria-sort\", \"descending\");\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\n col.setAttribute(\"aria-sort\", \"none\");\n }\n } else {\n // Or fetch current sort\n col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\n }\n\n if (this.options.server) {\n // Reload data with updated sort\n this.loadData().finally(() => {\n this.renderBody();\n });\n } else {\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\n if (sort === \"none\") {\n let stack = [];\n\n // Restore order while keeping filters\n this.originalData.some((itemA) => {\n this.data.some((itemB) => {\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\n stack.push(itemB);\n return true;\n }\n return false;\n });\n return stack.length === this.data.length;\n });\n\n this.data = stack;\n } else {\n const field = col.getAttribute(\"field\");\n this.data.sort((a, b) => {\n if (!isNaN(a[field]) && !isNaN(b[field])) {\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\n }\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\n\n switch (true) {\n case valA > valB:\n return 1;\n case valA < valB:\n return -1;\n case valA === valB:\n return 0;\n }\n });\n }\n this.renderBody();\n }\n }\n\n fetchData() {\n if (!this.options.url) {\n return new Promise((resolve, reject) => reject(\"No url set\"));\n }\n\n let base = window.location.href;\n // Fix trailing slash if no extension is present\n if (!base.split(\"/\").pop().includes(\".\")) {\n base += base.endsWith(\"/\") ? \"\" : \"/\";\n }\n let url = new URL(this.options.url, base);\n let params = {\n r: Date.now(),\n };\n if (this.options.server) {\n // 0 based\n params[this.options.serverParams.start] = this.page - 1;\n params[this.options.serverParams.length] = this.options.perPage;\n params[this.options.serverParams.search] = this.getFilters();\n params[this.options.serverParams.sort] = this.getSort() || \"\";\n params[this.options.serverParams.sortDir] = this.getSortDir();\n\n // extra params ?\n if (this.meta[this.options.serverParams.paramsKey]) {\n params = Object.assign(params, this.meta[this.options.serverParams.paramsKey]);\n }\n }\n\n appendParamsToUrl(url, params);\n\n return fetch(url)\n .then((response) => {\n if (!response.ok) {\n throw new Error(response.statusText);\n }\n return response.json();\n })\n .catch((err) => {\n return {\n error: err.message,\n };\n });\n }\n\n renderTable() {\n this.log(\"render table\");\n\n if (this.options.menu && this.plugins.ContextMenu) {\n this.plugins.ContextMenu.createMenu();\n }\n\n let sortedColumn;\n\n this.renderHeader();\n if (this.options.defaultSort) {\n // We can have a default sort even with sort disabled\n sortedColumn = this.querySelector(\"thead tr.dg-head-columns th[field='\" + this.options.defaultSort + \"']\");\n }\n\n if (sortedColumn) {\n this.sortData(sortedColumn);\n } else {\n this.renderBody();\n }\n\n this.renderFooter();\n }\n\n /**\n * Create table header\n * - One row for the column headers\n * - One row for the filters\n */\n renderHeader() {\n this.log(\"render header\");\n\n const thead = this.querySelector(\"thead\");\n this.createColumnHeaders(thead);\n this.createColumnFilters(thead);\n\n if (this.options.resizable && this.plugins.ColumnResizer) {\n this.plugins.ColumnResizer.renderResizer(labels.resizeColumn);\n }\n\n dispatch(this, \"headerRendered\");\n }\n\n renderFooter() {\n this.log(\"render footer\");\n\n const tfoot = this.querySelector(\"tfoot\");\n const td = tfoot.querySelector(\"td\");\n tfoot.removeAttribute(\"hidden\");\n setAttribute(td, \"colspan\", this.columnsLength(true));\n tfoot.style.display = \"\";\n }\n\n /**\n * Create the column headers based on column definitions and set options\n * @param {HTMLTableSectionElement} thead\n */\n createColumnHeaders(thead) {\n // @link https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively\n const availableWidth = this.clientWidth;\n const colMaxWidth = Math.round((availableWidth / this.columnsLength(true)) * 2);\n\n let idx = 0;\n let tr;\n\n // Create row\n tr = document.createElement(\"tr\");\n this.headerRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", \"1\");\n tr.setAttribute(\"class\", \"dg-head-columns\");\n\n // We need a real th from the dom to compute the size\n let sampleTh = thead.querySelector(\"tr.dg-head-columns th\");\n if (!sampleTh) {\n sampleTh = document.createElement(\"th\");\n thead.querySelector(\"tr\").appendChild(sampleTh);\n }\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createHeaderCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createHeaderCol(tr);\n }\n\n // Create columns\n idx = 0;\n let totalWidth = 0;\n this.options.columns.forEach((column) => {\n if (column.attr) {\n return;\n }\n const colIdx = idx + this.startColIndex();\n let th = document.createElement(\"th\");\n th.setAttribute(\"scope\", \"col\");\n th.setAttribute(\"role\", \"columnheader button\");\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\n th.setAttribute(\"id\", randstr(\"dg-col-\"));\n if (this.options.sort) {\n th.setAttribute(\"aria-sort\", \"none\");\n }\n th.setAttribute(\"field\", column.field);\n if (this.plugins.ResponsiveGrid && this.options.responsive) {\n setAttribute(th, \"data-responsive\", column.responsive || \"\");\n }\n // Make sure the header fits (+ add some room for sort icon if necessary)\n const computedWidth = getTextWidth(column.title, sampleTh, true) + 20;\n th.dataset.minWidth = \"\" + computedWidth;\n applyColumnDefinition(th, column);\n th.tabIndex = 0;\n th.textContent = column.title;\n\n let w = 0;\n // Autosize small based on first/last row ?\n // Take into account minWidth of the header and max available size based on col numbers\n if (this.options.autosize && this.plugins.AutosizeColumn) {\n const colAvailableWidth = Math.min(availableWidth - totalWidth, colMaxWidth);\n w = this.plugins.AutosizeColumn.computeSize(th, column, parseInt(th.dataset.minWidth), colAvailableWidth);\n } else {\n w = Math.max(parseInt(th.dataset.minWidth), parseInt(th.getAttribute(\"width\")));\n }\n\n setAttribute(th, \"width\", w);\n if (column.hidden) {\n th.setAttribute(\"hidden\", \"\");\n } else {\n totalWidth += w;\n }\n\n // Reorder columns with drag/drop\n if (this.options.reorder && this.plugins.DraggableHeaders) {\n this.plugins.DraggableHeaders.makeHeaderDraggable(th);\n }\n\n tr.appendChild(th);\n idx++;\n });\n\n // There is too much available width, and we want to avoid fixed layout to split remaining amount\n if (totalWidth < availableWidth) {\n const visibleCols = findAll(tr, \"th:not([hidden],.dg-not-resizable)\");\n if (visibleCols.length) {\n const lastCol = visibleCols[visibleCols.length - 1];\n removeAttribute(lastCol, \"width\");\n }\n }\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionHeader(tr);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\n\n // Once columns are inserted, we have an actual dom to query\n if (thead.offsetWidth > availableWidth) {\n this.log(`adjust width to fix size, ${thead.offsetWidth} > ${availableWidth}`);\n const scrollbarWidth = this.offsetWidth - this.clientWidth;\n let diff = thead.offsetWidth - availableWidth - scrollbarWidth;\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\n diff += scrollbarWidth;\n }\n // Remove diff for columns that can afford it\n const thWithWidth = findAll(tr, \"th[width]\");\n thWithWidth.forEach((th) => {\n if (hasClass(th, \"dg-not-resizable\")) {\n return;\n }\n if (diff <= 0) {\n return;\n }\n const actualWidth = parseInt(th.getAttribute(\"width\"));\n const minWidth = th.dataset.minWidth ? parseInt(th.dataset.minWidth) : 0;\n if (actualWidth > minWidth) {\n let newWidth = actualWidth - diff;\n if (newWidth < minWidth) {\n newWidth = minWidth;\n }\n diff -= actualWidth - newWidth;\n setAttribute(th, \"width\", newWidth);\n }\n });\n }\n\n // Context menu\n if (this.options.menu && this.plugins.ContextMenu) {\n this.plugins.ContextMenu.attachContextMenu();\n }\n\n // Sort col on click\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\n });\n\n setAttribute(this.querySelector(\"table\"), \"aria-colcount\", this.columnsLength(true));\n }\n\n createColumnFilters(thead) {\n let idx = 0;\n let tr;\n\n // Create row for filters\n tr = document.createElement(\"tr\");\n this.filterRow = tr;\n tr.setAttribute(\"role\", \"row\");\n tr.setAttribute(\"aria-rowindex\", \"2\");\n tr.setAttribute(\"class\", \"dg-head-filters\");\n if (!this.options.filter) {\n tr.setAttribute(\"hidden\", \"\");\n }\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createFilterCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createFilterCol(tr);\n }\n\n this.options.columns.forEach((column) => {\n if (column.attr) {\n return;\n }\n const colIdx = idx + this.startColIndex();\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + colIdx + \"']\");\n if (!relatedTh) {\n console.warn(\"Related th not found\", colIdx);\n return;\n }\n let th = document.createElement(\"th\");\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\n\n let input = document.createElement(\"input\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n // Allows binding filter to this column\n input.dataset.name = column.field;\n input.id = randstr(\"dg-filter-\");\n // Don't use aria-label as it triggers autocomplete\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\n if (!this.options.filter) {\n th.tabIndex = 0;\n } else {\n input.tabIndex = 0;\n }\n\n if (column.hidden) {\n th.setAttribute(\"hidden\", \"\");\n }\n\n th.appendChild(input);\n tr.appendChild(th);\n idx++;\n });\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionFilter(tr);\n }\n\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\n\n // Filter content on enter\n tr.querySelectorAll(\"input\").forEach((input) => {\n input.addEventListener(\"keypress\", (e) => {\n const key = e.keyCode || e.key;\n if (key === 13 || key === \"Enter\") {\n this.filterData.call(this);\n }\n });\n });\n }\n\n /**\n * Render the data as rows in tbody\n * It will call paginate() at the end\n */\n renderBody() {\n this.log(\"render body\");\n let tr;\n let td;\n let idx;\n let tbody = document.createElement(\"tbody\");\n\n this.data.forEach((item, i) => {\n tr = document.createElement(\"tr\");\n setAttribute(tr, \"role\", \"row\");\n setAttribute(tr, \"hidden\", \"\");\n setAttribute(tr, \"aria-rowindex\", i + 1);\n tr.tabIndex = 0;\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.createDataCol(tr);\n }\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\n this.plugins.ResponsiveGrid.createDataCol(tr);\n }\n\n // Expandable\n if (this.options.expand) {\n tr.classList.add(\"dg-expandable\");\n\n on(tr, \"click\", (ev) => {\n if (this.plugins.ResponsiveGrid) {\n this.plugins.ResponsiveGrid.blockObserver();\n }\n toggleClass(ev.currentTarget, \"dg-expanded\");\n if (this.plugins.ResponsiveGrid) {\n this.plugins.ResponsiveGrid.unblockObserver();\n }\n });\n }\n\n idx = 0;\n this.options.columns.forEach((column) => {\n if (!column) {\n console.error(\"Empty column found!\", this.options.columns);\n }\n // It should be applied as an attr of the row\n if (column.attr) {\n if (item[column.field]) {\n // Special case if we try to write over the class attr\n if (column.attr === \"class\") {\n addClass(tr, item[column.field]);\n } else {\n tr.setAttribute(column.attr, item[column.field]);\n }\n }\n return;\n }\n td = document.createElement(\"td\");\n td.setAttribute(\"role\", \"gridcell\");\n td.setAttribute(\"aria-colindex\", idx + this.startColIndex());\n applyColumnDefinition(td, column);\n // This is required for pure css responsive layout\n td.setAttribute(\"data-name\", column.title);\n td.tabIndex = -1;\n\n // Inline editing\n if (column.editable && this.plugins.EditableColumn) {\n this.plugins.EditableColumn.makeEditableInput(td, column, item, i);\n } else {\n const v = item[column.field] ?? \"\";\n let tv;\n // TODO: make this modular\n switch (column.transform) {\n case \"uppercase\":\n tv = v.toUpperCase();\n break;\n case \"lowercase\":\n tv = v.toLowerCase();\n break;\n default:\n tv = v;\n break;\n }\n if (column.format && tv) {\n td.innerHTML = interpolate(\n column.format,\n Object.assign(\n {\n _v: v,\n _tv: tv,\n },\n item\n )\n );\n } else {\n td.textContent = tv;\n }\n }\n tr.appendChild(td);\n idx++;\n });\n\n // Actions\n if (this.options.actions.length && this.plugins.RowActions) {\n this.plugins.RowActions.makeActionRow(tr, item);\n }\n\n tbody.appendChild(tr);\n });\n\n tbody.setAttribute(\"role\", \"rowgroup\");\n\n // Keep data empty message\n const prev = this.querySelector(\"tbody\");\n tbody.setAttribute(\"data-empty\", prev.getAttribute(\"data-empty\"));\n this.querySelector(\"table\").replaceChild(tbody, prev);\n\n if (this.plugins.FixedHeight) {\n this.plugins.FixedHeight.createFakeRow();\n }\n\n this.paginate();\n\n if (this.plugins.SelectableRows) {\n this.plugins.SelectableRows.shouldSelectAll(tbody);\n }\n\n dispatch(this, \"bodyRendered\");\n }\n\n paginate() {\n this.log(\"paginate\");\n\n const total = this.totalRecords();\n const p = this.page || 1;\n\n let index;\n let high = p * this.options.perPage;\n let low = high - this.options.perPage + 1;\n const tbody = this.querySelector(\"tbody\");\n const tfoot = this.querySelector(\"tfoot\");\n\n if (high > total) {\n high = total;\n }\n if (!total) {\n low = 0;\n }\n\n // Display all rows within the set indexes\n // For server side paginated grids, we display everything\n // since the server is taking care of actual pagination\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\n if (this.options.server) {\n removeAttribute(tr, \"hidden\");\n return;\n }\n index = Number(getAttribute(tr, \"aria-rowindex\"));\n if (index > high || index < low) {\n setAttribute(tr, \"hidden\", \"\");\n } else {\n removeAttribute(tr, \"hidden\");\n }\n });\n\n if (this.options.selectable && this.plugins.SelectableRows) {\n this.plugins.SelectableRows.clearCheckboxes(tbody);\n }\n\n // Store default height and update styles if needed\n if (this.plugins.FixedHeight) {\n this.plugins.FixedHeight.updateFakeRow();\n }\n\n // Enable/disable buttons if shown\n if (this.btnFirst) {\n this.btnFirst.disabled = this.page <= 1;\n this.btnPrev.disabled = this.page <= 1;\n this.btnNext.disabled = this.page >= this.pages;\n this.btnLast.disabled = this.page >= this.pages;\n }\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\n tfoot.querySelector(\".dg-total\").textContent = \"\" + this.totalRecords();\n }\n\n /**\n * @returns {number}\n */\n totalPages() {\n return Math.ceil(this.totalRecords() / this.options.perPage);\n }\n\n /**\n * @returns {number}\n */\n totalRecords() {\n if (this.options.server) {\n return this.meta[this.options.serverParams.metaFilteredKey] || 0;\n }\n return this.data.length;\n }\n}\n\nexport default DataGrid;\n", "/** @typedef {import(\"../data-grid\").default} DataGrid */\r\n\r\nclass BasePlugin {\r\n /**\r\n * @param {DataGrid} grid\r\n */\r\n constructor(grid) {\r\n this.grid = grid;\r\n }\r\n\r\n connected() {}\r\n\r\n disconnected() {}\r\n\r\n /**\r\n * Handle events within the plugin\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n}\r\n\r\nexport default BasePlugin;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport elementOffset from \"../utils/elementOffset.js\";\r\nimport {\r\n addClass,\r\n dispatch,\r\n findAll,\r\n getAttribute,\r\n hasClass,\r\n off,\r\n on,\r\n removeAttribute,\r\n removeClass,\r\n setAttribute,\r\n} from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass ColumnResizer extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.isResizing = false;\r\n }\r\n\r\n /**\r\n * @param {String} resizeLabel\r\n */\r\n renderResizer(resizeLabel) {\r\n const grid = this.grid;\r\n const table = grid.table;\r\n const cols = findAll(grid, \"thead tr.dg-head-columns th\");\r\n\r\n cols.forEach((col) => {\r\n if (hasClass(col, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n // Create a resizer element\r\n const resizer = document.createElement(\"div\");\r\n addClass(resizer, \"dg-resizer\");\r\n resizer.ariaLabel = resizeLabel;\r\n\r\n // Add a resizer element to the column\r\n col.appendChild(resizer);\r\n\r\n // Handle resizing\r\n let startX = 0;\r\n let startW = 0;\r\n let remainingSpace = 0;\r\n let max = 0;\r\n\r\n const mouseMoveHandler = (e) => {\r\n if (e.clientX > max) {\r\n return;\r\n }\r\n const newWidth = startW + (e.clientX - startX);\r\n if (col.dataset.minWidth && newWidth > parseInt(col.dataset.minWidth)) {\r\n setAttribute(col, \"width\", newWidth);\r\n }\r\n };\r\n\r\n // When user releases the mouse, remove the existing event listeners\r\n const mouseUpHandler = () => {\r\n grid.log(\"resized column\");\r\n\r\n // Prevent accidental sorting if mouse is not over resize handler\r\n setTimeout(() => {\r\n this.isResizing = false;\r\n }, 0);\r\n\r\n removeClass(resizer, \"dg-resizer-active\");\r\n if (grid.options.reorder) {\r\n col.draggable = true;\r\n }\r\n col.style.overflow = \"hidden\";\r\n\r\n // Remove handlers\r\n off(document, \"mousemove\", mouseMoveHandler);\r\n off(document, \"mouseup\", mouseUpHandler);\r\n\r\n dispatch(grid, \"columnResized\", {\r\n col: getAttribute(col, \"field\"),\r\n width: getAttribute(col, \"width\"),\r\n });\r\n };\r\n\r\n // Otherwise it could sort the col\r\n on(resizer, \"click\", (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n on(resizer, \"mousedown\", (e) => {\r\n e.stopPropagation();\r\n\r\n this.isResizing = true;\r\n\r\n const target = e.target;\r\n const currentCols = findAll(grid, \"dg-head-columns th\");\r\n const visibleCols = currentCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n const columnIndex = visibleCols.findIndex((column) => column == target.parentNode);\r\n grid.log(\"resize column\");\r\n\r\n addClass(resizer, \"dg-resizer-active\");\r\n\r\n // Make sure we don't drag it\r\n removeAttribute(col, \"draggable\");\r\n\r\n // Allow overflow when resizing\r\n col.style.overflow = \"visible\";\r\n\r\n // Show full column height (-1 to avoid scrollbar)\r\n resizer.style.height = table.offsetHeight - 1 + \"px\";\r\n\r\n // Register initial data\r\n startX = e.clientX;\r\n startW = col.offsetWidth;\r\n\r\n remainingSpace = (visibleCols.length - columnIndex) * 30;\r\n max = elementOffset(target).left + grid.offsetWidth - remainingSpace;\r\n\r\n // Remove width from next columns to allow auto layout\r\n setAttribute(col, \"width\", startW);\r\n for (let j = 0; j < visibleCols.length; j++) {\r\n if (j > columnIndex) {\r\n removeAttribute(cols[j], \"width\");\r\n }\r\n }\r\n\r\n // Attach handlers\r\n on(document, \"mousemove\", mouseMoveHandler);\r\n on(document, \"mouseup\", mouseUpHandler);\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default ColumnResizer;\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @param {String} type\r\n * @param {String} prop\r\n * @returns {HTMLElement}\r\n */\r\nexport default function getParentElement(el, type, prop = \"nodeName\") {\r\n let parent = el;\r\n while (parent[prop] != type) {\r\n parent = parent.parentElement;\r\n }\r\n return parent;\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { find, off, on, removeAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Create a right click menu on the headers\r\n */\r\nclass ContextMenu extends BasePlugin {\r\n connected() {\r\n /**\r\n * @type {HTMLUListElement}\r\n */\r\n this.menu = this.grid.querySelector(\".dg-menu\");\r\n }\r\n disconnected() {\r\n if (this.grid.headerRow) {\r\n off(this.grid.headerRow, \"contextmenu\", this);\r\n }\r\n }\r\n\r\n attachContextMenu() {\r\n const grid = this.grid;\r\n on(grid.headerRow, \"contextmenu\", this);\r\n }\r\n\r\n onchange(e) {\r\n const grid = this.grid;\r\n const t = e.target;\r\n const field = t.dataset.name;\r\n if (t.checked) {\r\n grid.showColumn(field);\r\n } else {\r\n // Prevent hidding last\r\n if (grid.visibleColumns().length <= 1) {\r\n // Restore checkbox value\r\n t.checked = true;\r\n return;\r\n }\r\n grid.hideColumn(field);\r\n }\r\n }\r\n\r\n oncontextmenu(e) {\r\n e.preventDefault();\r\n const grid = this.grid;\r\n const target = getParentElement(e.target, \"THEAD\");\r\n const menu = this.menu;\r\n const rect = target.getBoundingClientRect();\r\n let x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n\r\n menu.style.top = `${y}px`;\r\n menu.style.left = `${x}px`;\r\n\r\n removeAttribute(menu, \"hidden\");\r\n if (x + 150 > rect.width) {\r\n x -= menu.offsetWidth;\r\n menu.style.left = `${x}px`;\r\n }\r\n\r\n const documentClickHandler = (e) => {\r\n if (!menu.contains(e.target)) {\r\n setAttribute(menu, \"hidden\", \"\");\r\n off(document, \"click\", documentClickHandler);\r\n }\r\n };\r\n on(document, \"click\", documentClickHandler);\r\n }\r\n createMenu() {\r\n const grid = this.grid;\r\n const menu = this.menu;\r\n while (menu.lastChild) {\r\n menu.removeChild(menu.lastChild);\r\n }\r\n menu.addEventListener(\"change\", this);\r\n grid.options.columns.forEach((col) => {\r\n if (col.attr) {\r\n return;\r\n }\r\n const li = document.createElement(\"li\");\r\n const label = document.createElement(\"label\");\r\n const checkbox = document.createElement(\"input\");\r\n setAttribute(checkbox, \"type\", \"checkbox\");\r\n setAttribute(checkbox, \"data-name\", col.field);\r\n if (!col.hidden) {\r\n checkbox.checked = true;\r\n }\r\n const text = document.createTextNode(col.title);\r\n\r\n label.appendChild(checkbox);\r\n label.appendChild(text);\r\n\r\n li.appendChild(label);\r\n menu.appendChild(li);\r\n });\r\n }\r\n}\r\n\r\nexport default ContextMenu;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport getParentElement from \"../utils/getParentElement.js\";\nimport { dispatch, findAll, getAttribute, on, setAttribute } from \"../utils/shortcuts.js\";\n\n/**\n * Allows to move headers\n */\nclass DraggableHeaders extends BasePlugin {\n /**\n * @param {HTMLTableCellElement} th\n */\n makeHeaderDraggable(th) {\n const grid = this.grid;\n th.draggable = true;\n on(th, \"dragstart\", (e) => {\n if (grid.plugins.ColumnResizer && grid.plugins.ColumnResizer.isResizing && e.preventDefault) {\n e.preventDefault();\n return;\n }\n grid.log(\"reorder col\");\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\n });\n on(th, \"dragover\", (e) => {\n if (e.preventDefault) {\n e.preventDefault();\n }\n e.dataTransfer.dropEffect = \"move\";\n return false;\n });\n on(th, \"drop\", (e) => {\n if (e.stopPropagation) {\n e.stopPropagation();\n }\n const t = e.target;\n const target = getParentElement(t, \"TH\");\n const index = parseInt(e.dataTransfer.getData(\"text/plain\"));\n const targetIndex = parseInt(target.getAttribute(\"aria-colindex\"));\n\n if (index === targetIndex) {\n grid.log(\"reordered col stayed the same\");\n return;\n }\n grid.log(\"reordered col from \" + index + \" to \" + targetIndex);\n\n const offset = grid.startColIndex();\n const tmp = grid.options.columns[index - offset];\n grid.options.columns[index - offset] = grid.options.columns[targetIndex - offset];\n grid.options.columns[targetIndex - offset] = tmp;\n\n const swapNodes = (selector, el1) => {\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\n const el2 = grid.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\n setAttribute(el1, \"aria-colindex\", targetIndex);\n setAttribute(el2, \"aria-colindex\", index);\n const newNode = document.createElement(\"th\");\n el1.parentNode.insertBefore(newNode, el1);\n el2.parentNode.replaceChild(el1, el2);\n newNode.parentNode.replaceChild(el2, newNode);\n };\n\n // Swap all rows in header and body\n findAll(grid, \"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\n swapNodes(\"thead\", el1);\n });\n findAll(grid, 'tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\n swapNodes(\"tbody\", el1);\n });\n\n // Updates the columns\n grid.options.columns = findAll(grid, \"thead tr.dg-head-columns th[field]\").map((th) =>\n grid.options.columns.find((c) => c.field == getAttribute(th, \"field\"))\n );\n\n dispatch(grid, \"columnReordered\", {\n col: tmp.field,\n from: index,\n to: targetIndex,\n });\n return false;\n });\n }\n}\n\nexport default DraggableHeaders;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\n\r\n/**\r\n * Allows to paginate with horizontal swipe motions\r\n */\r\nclass TouchSupport extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.touch = null;\r\n }\r\n connected() {\r\n const grid = this.grid;\r\n grid.addEventListener(\"touchstart\", this, { passive: true });\r\n grid.addEventListener(\"touchmove\", this, { passive: true });\r\n }\r\n\r\n disconnected() {\r\n const grid = this.grid;\r\n grid.removeEventListener(\"touchstart\", this);\r\n grid.removeEventListener(\"touchmove\", this);\r\n }\r\n\r\n ontouchstart(e) {\r\n this.touch = e.touches[0];\r\n }\r\n\r\n ontouchmove(e) {\r\n if (!this.touch) {\r\n return;\r\n }\r\n const grid = this.grid;\r\n const xDiff = this.touch.clientX - e.touches[0].clientX;\r\n const yDiff = this.touch.clientY - e.touches[0].clientY;\r\n\r\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\r\n if (xDiff > 0) {\r\n grid.getNext();\r\n } else {\r\n grid.getPrev();\r\n }\r\n }\r\n this.touch = null;\r\n }\r\n}\r\n\r\nexport default TouchSupport;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport { dispatch, findAll, hasClass, setAttribute } from \"../utils/shortcuts.js\";\n\nconst SELECTABLE_CLASS = \"dg-selectable\";\nconst SELECT_ALL_CLASS = \"dg-select-all\";\nconst CHECKBOX_CLASS = \"form-check-input\"; //bs5\n\n/**\n * Allows to select rows\n */\nclass SelectableRows extends BasePlugin {\n disconnected() {\n if (this.selectAll) {\n this.selectAll.removeEventListener(\"change\", this);\n }\n }\n\n /**\n * @param {String} key Return a specific key (eg: id) instead of the whole row\n * @returns {Array}\n */\n getSelection(key = null) {\n const grid = this.grid;\n let selectedData = [];\n\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input:checked`);\n inputs.forEach((checkbox) => {\n const idx = parseInt(checkbox.dataset.id);\n const item = grid.data[idx - 1];\n if (!item) {\n console.warn(`Item ${idx} not found`);\n }\n if (key) {\n selectedData.push(item[key]);\n } else {\n selectedData.push(item);\n }\n });\n return selectedData;\n }\n\n /**\n * Uncheck box if hidden and visible only\n * @param {HTMLTableSectionElement} tbody\n */\n clearCheckboxes(tbody) {\n const grid = this.grid;\n if (!grid.options.selectVisibleOnly) {\n return;\n }\n const inputs = findAll(tbody, `tr[hidden] .${SELECTABLE_CLASS} input`);\n inputs.forEach((input) => {\n input.checked = false;\n });\n this.selectAll.checked = false;\n }\n\n colIndex() {\n return this.grid.startColIndex() - 2;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createHeaderCol(tr) {\n let th = document.createElement(\"th\");\n setAttribute(th, \"scope\", \"col\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(...[SELECTABLE_CLASS, \"dg-not-resizable\", \"dg-not-sortable\"]);\n th.tabIndex = 0;\n\n this.selectAll = document.createElement(\"input\");\n this.selectAll.type = \"checkbox\";\n this.selectAll.classList.add(SELECT_ALL_CLASS);\n this.selectAll.classList.add(CHECKBOX_CLASS);\n this.selectAll.addEventListener(\"change\", this);\n\n let label = document.createElement(\"label\");\n label.appendChild(this.selectAll);\n\n th.appendChild(label);\n\n th.setAttribute(\"width\", \"40\");\n tr.appendChild(th);\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createFilterCol(tr) {\n let th = document.createElement(\"th\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(SELECTABLE_CLASS);\n th.tabIndex = 0;\n\n tr.appendChild(th);\n }\n\n /**\n * Handles the selectAll checkbox when any other .dg-selectable checkbox is checked on table body.\n * It should check selectAll if all is checked\n * It should uncheck selectAll if any is unchecked\n * @param {HTMLTableSectionElement} tbody\n */\n shouldSelectAll(tbody) {\n if (!this.selectAll) {\n return;\n }\n // Delegate listener for change events on input checkboxes\n tbody.addEventListener(\"change\", this);\n // Make sure state is up to date\n tbody.dispatchEvent(new Event(\"change\"));\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createDataCol(tr) {\n // Create col\n let td = document.createElement(\"td\");\n setAttribute(td, \"role\", \"gridcell button\");\n setAttribute(td, \"aria-colindex\", this.colIndex());\n td.classList.add(SELECTABLE_CLASS);\n\n // Create input\n let selectOne = document.createElement(\"input\");\n // Alias row id for easy retrieval in getSelection\n selectOne.dataset.id = tr.getAttribute(\"aria-rowindex\");\n selectOne.type = \"checkbox\";\n selectOne.classList.add(CHECKBOX_CLASS);\n // Label need to take full space thanks to css to make the whole cell clickable\n let label = document.createElement(\"label\");\n label.classList.add(\"dg-clickable-cell\");\n label.appendChild(selectOne);\n td.appendChild(label);\n\n // Prevent unwanted click behaviour on row\n label.addEventListener(\"click\", this);\n\n tr.appendChild(td);\n }\n\n /**\n * @param {Event} e\n */\n onclick(e) {\n e.stopPropagation();\n }\n\n /**\n * Handle change event on select all or any select checkbox in the table body\n * @param {import(\"../utils/shortcuts.js\").FlexibleEvent} e\n */\n onchange(e) {\n const grid = this.grid;\n if (hasClass(e.target, SELECT_ALL_CLASS)) {\n const visibleOnly = grid.options.selectVisibleOnly;\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input`);\n inputs.forEach((cb) => {\n if (visibleOnly && !cb.offsetWidth) {\n return;\n }\n cb.checked = this.selectAll.checked;\n });\n\n dispatch(grid, \"rowsSelected\", {\n selection: this.getSelection(),\n });\n } else {\n if (!e.target.closest(`.${SELECTABLE_CLASS}`)) {\n return;\n }\n const totalCheckboxes = findAll(grid, `tbody .${SELECTABLE_CLASS} input[type=checkbox]`);\n // @ts-ignore\n const totalChecked = totalCheckboxes.filter((n) => n.checked);\n this.selectAll.checked = totalChecked.length == totalCheckboxes.length;\n\n dispatch(grid, \"rowsSelected\", {\n selection: grid.getSelection(),\n });\n }\n }\n}\n\nexport default SelectableRows;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Support for fixed table height\r\n *\r\n * We should add a fake row to push the footer down in case we don't have enough rows\r\n */\r\nclass FixedHeight extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.hasFixedHeight = false;\r\n // If we have a fixed height, make sure we have overflowY set\r\n if (grid.style.height) {\r\n grid.style.overflowY = \"auto\";\r\n this.hasFixedHeight = true;\r\n }\r\n }\r\n\r\n /**\r\n */\r\n createFakeRow() {\r\n const grid = this.grid;\r\n const tbody = grid.querySelector(\"tbody\");\r\n let tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n tr.classList.add(\"dg-fake-row\");\r\n tr.tabIndex = 0;\r\n tbody.appendChild(tr);\r\n }\r\n\r\n get fakeRow() {\r\n return this.grid.querySelector(\".dg-fake-row\");\r\n }\r\n\r\n /**\r\n * On last page, use a fake row to push footer down\r\n */\r\n updateFakeRow() {\r\n const grid = this.grid;\r\n const fakeRow = this.fakeRow;\r\n if (!fakeRow) {\r\n return;\r\n }\r\n\r\n // We don't need a fake row if we display everything\r\n if (grid.options.perPage > grid.totalRecords()) {\r\n return;\r\n }\r\n // We are not on last page\r\n if (grid.page !== grid.totalPages()) {\r\n return;\r\n }\r\n\r\n // Find remaining missing height\r\n const max = grid.options.perPage * grid.rowHeight;\r\n const visibleRows = grid.querySelectorAll(\"tbody tr:not([hidden])\").length;\r\n const fakeHeight = visibleRows > 1 ? max - visibleRows * grid.rowHeight : max;\r\n if (fakeHeight > 0) {\r\n setAttribute(fakeRow, \"height\", fakeHeight);\r\n fakeRow.removeAttribute(\"hidden\");\r\n } else {\r\n fakeRow.removeAttribute(\"height\");\r\n }\r\n }\r\n}\r\n\r\nexport default FixedHeight;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport getTextWidth from \"../utils/getTextWidth.js\";\nimport { getAttribute, hasAttribute, setAttribute } from \"../utils/shortcuts.js\";\n\n/**\n * Allows to resize columns\n */\nclass AutosizeColumn extends BasePlugin {\n /**\n * Autosize col based on column data\n * @param {HTMLTableCellElement} th\n * @param {import(\"../data-grid\").Column} column\n * @param {Number} min\n * @param {Number} max\n * @returns {Number}\n */\n computeSize(th, column, min, max) {\n const grid = this.grid;\n if (hasAttribute(th, \"width\")) {\n return getAttribute(th, \"width\");\n }\n if (!grid.data.length) {\n return;\n }\n const firstVal = grid.data[0];\n const lastVal = grid.data[grid.data.length - 1];\n let v = firstVal[column.field] ? firstVal[column.field].toString() : \"\";\n let v2 = lastVal[column.field] ? lastVal[column.field].toString() : \"\";\n if (v2.length > v.length) {\n v = v2;\n }\n let width = 0;\n if (v.length <= 6) {\n width = min;\n } else if (v.length > 50) {\n width = max;\n } else {\n // Add some extra room to have some spare space\n width = getTextWidth(v + \"0000\", th);\n }\n if (width > max) {\n width = max;\n }\n if (width < min) {\n width = min;\n }\n setAttribute(th, \"width\", width);\n return width;\n }\n}\n\nexport default AutosizeColumn;\n", "/**\r\n * Define a function that can be happily passed to addEventListener\r\n * @typedef {Function & EventListenerOrEventListenerObject} ExtendedFunction\r\n */\r\n\r\n/**\r\n * @param {Function} handler\r\n * @param {Number} timeout\r\n * @returns {ExtendedFunction}\r\n */\r\nexport default function debounce(handler, timeout = 300) {\r\n let timer = null;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n timer = null;\r\n handler(...args);\r\n }, timeout);\r\n };\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\nimport debounce from \"../utils/debounce.js\";\nimport { addClass, ce, find, findAll, hasClass, insertAfter, removeAttribute, removeClass, setAttribute } from \"../utils/shortcuts.js\";\n\nconst RESPONSIVE_CLASS = \"dg-responsive\";\n\nlet obsTo;\n\n/**\n * @param {Array} list\n * @returns {Array}\n */\nfunction sortByPriority(list) {\n return list.sort((a, b) => {\n const v1 = parseInt(a.dataset.responsive) || 1;\n const v2 = parseInt(b.dataset.responsive) || 1;\n return v2 - v1;\n });\n}\n\n/**\n * @type {ResizeObserverCallback}\n */\n//@ts-ignore\nconst callback = debounce((entries) => {\n for (const entry of entries) {\n /**\n * @type {import(\"../data-grid\").default}\n */\n // @ts-ignore\n const grid = entry.target;\n const table = grid.table;\n if (grid.plugins.ResponsiveGrid.observerBlocked) {\n return;\n }\n // check inlineSize (width) and not blockSize (height)\n const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;\n const size = parseInt(contentBoxSize.inlineSize);\n const tableWidth = table.offsetWidth;\n const realTableWidth = findAll(grid.headerRow, \"th\").reduce((result, th) => {\n return result + th.offsetWidth;\n }, 0);\n const diff = (realTableWidth || tableWidth) - size - 1;\n const minWidth = 50;\n const prevAction = grid.plugins.ResponsiveGrid.prevAction;\n // We have an array with the columns to show/hide are in order, most important first\n const headerCols = sortByPriority(\n findAll(grid.headerRow, \"th[field]\")\n .reverse() // Order takes precedence if no priority is set\n .filter((col) => {\n // Leave out unresponsive columns\n return col.dataset.responsive !== \"0\";\n })\n );\n let changed = false;\n\n grid.log(`table is ${tableWidth}/${realTableWidth} and available size is ${size}. Diff: ${diff}`);\n\n // The table is too big when diff has a high value, otherwise it will be like -1 or -2\n if (diff > 0) {\n if (prevAction === \"show\") {\n return;\n }\n grid.plugins.ResponsiveGrid.prevAction = \"hide\";\n let remaining = diff;\n let cols = headerCols.filter((col) => {\n return !col.hasAttribute(\"hidden\") && col.hasAttribute(\"data-responsive\");\n });\n if (cols.length === 0) {\n cols = headerCols.filter((col) => {\n return !col.hasAttribute(\"hidden\");\n });\n // Always keep one column\n if (cols.length === 1) {\n return;\n }\n }\n cols.forEach((col) => {\n if (remaining < 0) {\n return;\n }\n\n const colWidth = col.offsetWidth;\n const field = col.getAttribute(\"field\");\n if (!field) {\n return;\n }\n col.dataset.baseWidth = \"\" + col.offsetWidth;\n\n grid.hideColumn(field, false);\n grid.setColProp(field, \"responsiveHidden\", true);\n changed = true;\n\n remaining -= colWidth;\n remaining = Math.round(remaining);\n });\n } else {\n if (prevAction === \"hide\") {\n return;\n }\n grid.plugins.ResponsiveGrid.prevAction = \"show\";\n\n const requiredWidth =\n headerCols\n .filter((col) => {\n return !col.hasAttribute(\"hidden\");\n })\n .reduce((result, col) => {\n const width = col.dataset.minWidth ? parseInt(col.dataset.minWidth) : col.offsetWidth;\n return result + width;\n }, 0) + minWidth; // Add an offset so that inserting column is smoother\n\n // Compute available width to insert columns\n let remaining = size - requiredWidth;\n // Do we have any hidden column that we can restore ?\n headerCols\n .slice()\n .reverse() // Reverse the array to restore the columns in the proper order\n .filter((col) => {\n return col.hasAttribute(\"hidden\");\n })\n .forEach((col) => {\n if (remaining < minWidth) {\n return;\n }\n const colWidth = parseInt(col.dataset.minWidth);\n\n // We need to have enough space to restore it\n if (colWidth > remaining) {\n remaining = -1; // break loop to keep restoring in order\n return;\n }\n\n const field = col.getAttribute(\"field\");\n if (!field) {\n return;\n }\n\n grid.showColumn(field, false);\n grid.setColProp(field, \"responsiveHidden\", false);\n changed = true;\n\n remaining -= colWidth;\n remaining = Math.round(remaining);\n });\n }\n\n // Check footer\n const footer = find(grid.table, \"tfoot\");\n const realFooterWidth = findAll(grid.table, \".dg-footer > div\").reduce((result, div) => {\n return result + div.offsetWidth;\n }, 0);\n const availableFooterWidth = footer.offsetWidth - realFooterWidth;\n if (realFooterWidth > size) {\n addClass(footer, \"dg-footer-compact\");\n } else if (availableFooterWidth > 250) {\n removeClass(footer, \"dg-footer-compact\");\n }\n if (changed) {\n grid.renderTable();\n }\n // Prevent resize loop\n setTimeout(() => {\n grid.plugins.ResponsiveGrid.prevAction = null;\n }, 1000);\n grid.table.style.visibility = \"visible\";\n }\n}, 100);\nconst resizeObserver = new ResizeObserver(callback);\n\n/**\n * Responsive data grid\n */\nclass ResponsiveGrid extends BasePlugin {\n constructor(grid) {\n super(grid);\n\n this.observerBlocked = false;\n this.prevAction = null;\n }\n\n connected() {\n if (this.grid.options.responsive) {\n this.observe();\n }\n }\n\n disconnected() {\n this.unobserve();\n }\n\n observe() {\n if (!this.grid.options.responsive) {\n return;\n }\n resizeObserver.observe(this.grid);\n this.grid.style.display = \"block\"; // Otherwise resize doesn't happen\n this.grid.style.overflowX = \"hidden\"; // Prevent scrollbars from appearing\n }\n\n unobserve() {\n resizeObserver.unobserve(this.grid);\n this.grid.style.display = \"unset\";\n this.grid.style.overflowX = \"unset\";\n }\n\n blockObserver() {\n this.observerBlocked = true;\n if (obsTo) {\n clearTimeout(obsTo);\n }\n }\n\n unblockObserver() {\n obsTo = setTimeout(() => {\n this.observerBlocked = false;\n }, 200); // more than debounce\n }\n\n /**\n * @returns {Boolean}\n */\n hasHiddenColumns() {\n let flag = false;\n this.grid.options.columns.forEach((col) => {\n if (col.responsiveHidden) {\n flag = true;\n }\n });\n return flag;\n }\n\n colIndex() {\n return this.grid.startColIndex() - 1;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createHeaderCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n let th = ce(\"th\", tr);\n setAttribute(th, \"scope\", \"col\");\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n setAttribute(th, \"width\", \"40\");\n th.classList.add(...[`${RESPONSIVE_CLASS}-toggle`, \"dg-not-resizable\", \"dg-not-sortable\"]);\n th.tabIndex = 0;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createFilterCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n let th = ce(\"th\", tr);\n setAttribute(th, \"role\", \"columnheader button\");\n setAttribute(th, \"aria-colindex\", this.colIndex());\n th.classList.add(`${RESPONSIVE_CLASS}-toggle`);\n th.tabIndex = 0;\n }\n\n /**\n * @param {HTMLTableRowElement} tr\n */\n createDataCol(tr) {\n if (!this.grid.options.responsiveToggle) {\n return;\n }\n // Create col\n let td = document.createElement(\"td\");\n setAttribute(td, \"role\", \"gridcell button\");\n setAttribute(td, \"aria-colindex\", this.colIndex());\n td.classList.add(`${RESPONSIVE_CLASS}-toggle`);\n\n // Create icon\n td.innerHTML = `
\n \n \n\n\n \n
`;\n tr.appendChild(td);\n\n td.addEventListener(\"click\", this);\n td.addEventListener(\"mousedown\", this);\n }\n\n computeLabelWidth() {\n let idealWidth = 0;\n let consideredCol = 0;\n while (idealWidth < 120) {\n consideredCol++;\n const hCol = find(this.grid, `.dg-head-columns th[aria-colindex=\"${consideredCol}\"]`);\n if (hCol) {\n idealWidth += hCol.offsetWidth;\n } else {\n break;\n }\n }\n return idealWidth;\n }\n\n /**\n * @param {Event} ev\n */\n onmousedown(ev) {\n // Avoid selection through double click\n ev.preventDefault();\n }\n\n /**\n * @param {Event} ev\n */\n onclick(ev) {\n // Prevent expandable\n ev.stopPropagation();\n\n // target is the element that triggered the event (e.g., the user clicked on)\n // currentTarget is the element that the event listener is attached to.\n\n /**\n * @type {HTMLTableRowElement}\n */\n //@ts-ignore\n const td = ev.currentTarget;\n const tr = td.parentElement;\n const open = find(td, `.${RESPONSIVE_CLASS}-open`);\n const close = find(td, `.${RESPONSIVE_CLASS}-close`);\n\n this.blockObserver();\n\n const isExpanded = hasClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n if (isExpanded) {\n removeClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n open.style.display = \"unset\";\n close.style.display = \"none\";\n\n // Move back rows and cleanup row\n const childRow = tr.nextElementSibling;\n const hiddenCols = findAll(childRow, `.${RESPONSIVE_CLASS}-hidden`);\n hiddenCols.forEach((col) => {\n // We don't really need to care where we insert them since we are going to redraw anyway\n tr.appendChild(col);\n setAttribute(col, \"hidden\");\n });\n\n childRow.parentElement.removeChild(childRow);\n } else {\n addClass(tr, `${RESPONSIVE_CLASS}-expanded`);\n open.style.display = \"none\";\n close.style.display = \"unset\";\n\n // Create a child row and move rows into it\n const childRow = ce(\"tr\");\n insertAfter(childRow, tr);\n addClass(childRow, `${RESPONSIVE_CLASS}-child-row`);\n\n const childRowTd = ce(\"td\", childRow);\n setAttribute(childRowTd, \"colspan\", this.grid.columnsLength(true));\n\n const childTable = ce(\"table\", childRowTd);\n addClass(childTable, `${RESPONSIVE_CLASS}-table`);\n\n const hiddenCols = findAll(tr, `.${RESPONSIVE_CLASS}-hidden`);\n const idealWidth = this.computeLabelWidth();\n hiddenCols.forEach((col) => {\n const childTableRow = ce(\"tr\", childTable);\n\n // Add label\n const label = col.dataset.name;\n const labelCol = ce(\"th\", childTableRow);\n // It looks much better when aligned with an actual col\n labelCol.style.width = `${idealWidth}px`;\n labelCol.innerHTML = label;\n\n // Add actual row\n childTableRow.appendChild(col);\n removeAttribute(col, \"hidden\");\n });\n }\n\n this.unblockObserver();\n }\n}\n\nexport default ResponsiveGrid;\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport interpolate from \"../utils/interpolate.js\";\r\nimport { dispatch, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Add action on rows\r\n */\r\nclass RowActions extends BasePlugin {\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasActions() {\r\n return this.grid.options.actions.length > 0;\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionHeader(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n setAttribute(actionsTh, \"role\", \"columnheader button\");\r\n setAttribute(actionsTh, \"aria-colindex\", this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", \"dg-not-sortable\", \"dg-not-resizable\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionFilter(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n actionsTh.setAttribute(\"role\", \"columnheader button\");\r\n actionsTh.setAttribute(\"aria-colindex\", \"\" + this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n * @param {Object} item\r\n */\r\n makeActionRow(tr, item) {\r\n const labels = this.grid.labels;\r\n const td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell\");\r\n setAttribute(td, \"aria-colindex\", this.grid.columnsLength(true));\r\n td.classList.add(...[\"dg-actions\", this.actionClass]);\r\n td.tabIndex = 0;\r\n\r\n // Add menu toggle\r\n let actionsToggle = document.createElement(\"button\");\r\n actionsToggle.classList.add(\"dg-actions-toggle\");\r\n actionsToggle.innerHTML = \"\u2630\";\r\n td.appendChild(actionsToggle);\r\n on(actionsToggle, \"click\", (ev) => {\r\n ev.stopPropagation();\r\n ev.target.parentElement.classList.toggle(\"dg-actions-expand\");\r\n });\r\n\r\n this.grid.options.actions.forEach((action) => {\r\n let button = document.createElement(\"button\");\r\n if (action.html) {\r\n button.innerHTML = action.html;\r\n } else {\r\n button.innerText = action.title ?? action.name;\r\n }\r\n if (action.title) {\r\n button.title = action.title;\r\n }\r\n if (action.url) {\r\n button.type = \"submit\";\r\n button.formAction = interpolate(action.url, item);\r\n }\r\n if (action.class) {\r\n button.classList.add(...action.class.split(\" \"));\r\n }\r\n const actionHandler = (ev) => {\r\n ev.stopPropagation();\r\n if (action.confirm) {\r\n let c = confirm(labels.areYouSure);\r\n if (!c) {\r\n ev.preventDefault();\r\n return;\r\n }\r\n }\r\n dispatch(this.grid, \"action\", {\r\n data: item,\r\n action: action.name,\r\n });\r\n };\r\n button.addEventListener(\"click\", actionHandler);\r\n td.appendChild(button);\r\n\r\n // Row action\r\n if (action.default) {\r\n tr.classList.add(\"dg-actionable\");\r\n tr.addEventListener(\"click\", actionHandler);\r\n }\r\n });\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n get actionClass() {\r\n if (this.grid.options.actions.length < 3 && !this.grid.options.collapseActions) {\r\n return \"dg-actions-\" + this.grid.options.actions.length;\r\n }\r\n return \"dg-actions-more\";\r\n }\r\n}\r\n\r\nexport default RowActions;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Make editable inputs in rows\r\n */\r\nclass EditableColumn extends BasePlugin {\r\n /**\r\n *\r\n * @param {HTMLTableCellElement} td\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Object} item\r\n * @param {number} i\r\n */\r\n makeEditableInput(td, column, item, i) {\r\n const gridId = this.grid.getAttribute(\"id\");\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n input.tabIndex = 0;\r\n input.classList.add(\"dg-editable\");\r\n input.name = gridId.replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\r\n input.value = item[column.field];\r\n input.dataset.field = column.field;\r\n\r\n // Prevent row action\r\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\r\n // Enter validates edit\r\n input.addEventListener(\"keypress\", (ev) => {\r\n if (ev.type === \"keypress\") {\r\n const key = ev.keyCode || ev.key;\r\n if (key === 13 || key === \"Enter\") {\r\n input.blur();\r\n ev.preventDefault();\r\n }\r\n }\r\n });\r\n // Save on blur\r\n input.addEventListener(\"blur\", () => {\r\n // Only fire on update\r\n if (input.value == item[input.dataset.field]) {\r\n return;\r\n }\r\n // Update underlying data\r\n item[input.dataset.field] = input.value;\r\n // Notify\r\n dispatch(this.grid, \"edit\", {\r\n data: item,\r\n value: input.value,\r\n });\r\n });\r\n td.appendChild(input);\r\n }\r\n}\r\n\r\nexport default EditableColumn;\r\n", "import DataGrid from \"./src/data-grid.js\";\n// Optional plugins\nimport ColumnResizer from \"./src/plugins/column-resizer.js\";\nimport ContextMenu from \"./src/plugins/context-menu.js\";\nimport DraggableHeaders from \"./src/plugins/draggable-headers.js\";\nimport TouchSupport from \"./src/plugins/touch-support.js\";\nimport SelectableRows from \"./src/plugins/selectable-rows.js\";\nimport FixedHeight from \"./src/plugins/fixed-height.js\";\nimport AutosizeColumn from \"./src/plugins/autosize-column.js\";\nimport ResponsiveGrid from \"./src/plugins/responsive-grid.js\";\nimport RowActions from \"./src/plugins/row-actions.js\";\nimport EditableColumn from \"./src/plugins/editable-column.js\";\n\n// Using shorthand property names\n// This make them reserved and keys will be preserved\n// Actual class names are renamed\nDataGrid.registerPlugins({\n ColumnResizer,\n ContextMenu,\n DraggableHeaders,\n TouchSupport,\n SelectableRows,\n FixedHeight,\n AutosizeColumn,\n ResponsiveGrid,\n RowActions,\n EditableColumn,\n});\n\ncustomElements.define(\"data-grid\", DataGrid);\n\nexport default DataGrid;\n"], + "sourcesContent": ["/**\r\n * @param {String} str\r\n * @returns {String}\r\n */\r\nexport default function camelize(str) {\r\n return str.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase());\r\n}\r\n", "/**\r\n * Parse data attribute and return properly typed data\r\n * @param {String} v\r\n * @returns {any}\r\n */\r\nexport default function normalizeData(v) {\r\n // Bool\r\n if (v === \"true\") {\r\n return true;\r\n }\r\n if (v === \"false\") {\r\n return false;\r\n }\r\n // Null or empty\r\n if (v === \"\" || v === \"null\") {\r\n return null;\r\n }\r\n // Numeric attributes\r\n if (v === Number(v).toString()) {\r\n return Number(v);\r\n }\r\n // Only attempt json parsing for array or objects\r\n if (v && [\"[\", \"{\"].includes(v.substring(0, 1))) {\r\n try {\r\n // In case we have only single quoted values, like ['one', 'two', 'three']\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(decodeURIComponent(v));\r\n } catch {\r\n console.error(\"Failed to parse \" + v);\r\n return {};\r\n }\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @typedef FlexibleHTMLProps\r\n * @property {boolean} [checked] (HTMLInputElement)\r\n * @property {string} [value] (HTMLInputElement)\r\n * @property {number} [rowHeight] (HTMLTableRowElement)\r\n *\r\n * A flexible type HTMLElement type that does not require using instanceof all over the place\r\n * Make sure that your selector is indeed valid\r\n * Only includes most commons props\r\n * @typedef {HTMLElement & FlexibleHTMLProps} FlexibleHTMLElement\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {HTMLElement&HTMLInputElement&HTMLTableRowElement} MixedHTMLElement\r\n */\r\n\r\n/**\r\n * @typedef FlexibleEventProps\r\n * @property {FlexibleHTMLElement} target\r\n * @property {FlexibleHTMLElement} currentTarget\r\n * @property {DataTransfer} [dataTransfer] (DragEvent)\r\n * @property {number} [clientX] (MouseEvent)\r\n * @property {number} [clientY] (MouseEvent)\r\n *\r\n * @typedef {Event & FlexibleEventProps} FlexibleEvent\r\n */\r\n\r\n/**\r\n * Keep this as reference for easy documentation\r\n * @typedef {Event&MouseEvent&InputEvent&DragEvent&FocusEvent&KeyboardEvent&PointerEvent} MixedEvent\r\n */\r\n\r\n/**\r\n * @callback FlexibleListener\r\n * @param {FlexibleEvent} event\r\n */\r\n\r\nclass FlexibleEventListenerObject {\r\n /**\r\n * @param {FlexibleEvent} e\r\n */\r\n handleEvent(e) {}\r\n}\r\n\r\nconst supportedPassiveTypes = [\r\n \"scroll\",\r\n \"wheel\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n \"touchenter\",\r\n \"touchend\",\r\n \"touchleave\",\r\n \"mouseout\",\r\n \"mouseleave\",\r\n \"mouseup\",\r\n \"mousedown\",\r\n \"mousemove\",\r\n \"mouseenter\",\r\n \"mousewheel\",\r\n \"mouseover\",\r\n];\r\n\r\n/**\r\n * Automatically set passive options based on type\r\n * @param {string} type\r\n * @returns {AddEventListenerOptions}\r\n */\r\nfunction passiveOpts(type) {\r\n if (supportedPassiveTypes.includes(type)) {\r\n return { passive: true };\r\n }\r\n return {};\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {any}\r\n */\r\nexport function getAttribute(el, name) {\r\n return el.getAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasAttribute(el, name) {\r\n return el.hasAttribute(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @param {any} v\r\n * @param {Boolean} check Prevent setting if attribute is already there\r\n */\r\nexport function setAttribute(el, name, v = \"\", check = false) {\r\n if (check && hasAttribute(el, name)) return;\r\n el.setAttribute(name, \"\" + v);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeAttribute(el, name) {\r\n if (hasAttribute(el, name)) {\r\n el.removeAttribute(name);\r\n }\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function on(el, type, listener) {\r\n el.addEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function off(el, type, listener) {\r\n el.removeEventListener(type, listener, passiveOpts(type));\r\n}\r\n\r\n/**\r\n * @param {EventTarget} el\r\n * @param {String} type\r\n * @param {EventListenerObject|FlexibleListener} listener\r\n */\r\nexport function one(el, type, listener) {\r\n el.addEventListener(type, listener, {\r\n once: true,\r\n });\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el\r\n * @param {String} name\r\n * @param {any} data\r\n * @param {Boolean} bubbles\r\n */\r\nexport function dispatch(el, name, data = {}, bubbles = false) {\r\n let opts = {};\r\n if (bubbles) {\r\n opts.bubbles = true;\r\n }\r\n if (data) {\r\n opts.detail = data;\r\n }\r\n el.dispatchEvent(new CustomEvent(name, opts));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n * @returns {Boolean}\r\n */\r\nexport function hasClass(el, name) {\r\n return el.classList.contains(name);\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function addClass(el, name) {\r\n el.classList.add(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function removeClass(el, name) {\r\n el.classList.remove(...name.split(\" \"));\r\n}\r\n\r\n/**\r\n * @param {Element} el\r\n * @param {String} name\r\n */\r\nexport function toggleClass(el, name) {\r\n el.classList.toggle(name);\r\n}\r\n\r\n/**\r\n * @param {String|HTMLElement} selector\r\n * @param {HTMLElement|Document} base\r\n * @returns {FlexibleHTMLElement|null}\r\n */\r\nexport function $(selector, base = document) {\r\n if (selector instanceof HTMLElement) {\r\n return selector;\r\n }\r\n return base.querySelector(selector);\r\n}\r\n\r\n/**\r\n * @param {String} selector\r\n * @param {Element|Document} base\r\n * @returns {Array}\r\n */\r\nexport function $$(selector, base = document) {\r\n return Array.from(base.querySelectorAll(selector));\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped element\r\n * For actual type, prefer use of el.querySelector\r\n * @param {HTMLElement} el\r\n * @param {String|HTMLElement} selector\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function find(el, selector) {\r\n return $(selector, el);\r\n}\r\n\r\n/**\r\n * Easily retrieve untyped elements\r\n * For actual type, prefer use of el.querySelectorAll\r\n * @param {Element} el\r\n * @param {String} selector\r\n * @returns {Array}\r\n */\r\nexport function findAll(el, selector) {\r\n return $$(selector, el);\r\n}\r\n\r\n/**\r\n * @param {*} el\r\n * @returns {FlexibleHTMLElement}\r\n */\r\nexport function el(el) {\r\n return el;\r\n}\r\n\r\n/**\r\n * @template {keyof HTMLElementTagNameMap} K\r\n * @param {K} tagName\r\n * @param {HTMLElement} parent\r\n * @returns {HTMLElementTagNameMap[K]}\r\n */\r\nexport function ce(tagName, parent = null) {\r\n const el = document.createElement(tagName);\r\n if (parent) {\r\n parent.appendChild(el);\r\n }\r\n return el;\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} newNode\r\n * @param {HTMLElement} existingNode\r\n */\r\nexport function insertAfter(newNode, existingNode) {\r\n existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);\r\n}\r\n", "import camelize from \"../utils/camelize.js\";\r\nimport normalizeData from \"../utils/normalizeData.js\";\r\nimport { dispatch, getAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Base element that does not contain any specific logic\r\n * related to this project but makes HTMLElemnt usable\r\n */\r\nclass BaseElement extends HTMLElement {\r\n /**\r\n * @param {Object} options\r\n */\r\n constructor(options = {}) {\r\n super();\r\n this.options = Object.assign({}, this.defaultOptions, this.normalizedDataset, options);\r\n\r\n this.log(\"constructor\");\r\n\r\n this.fireEvents = true;\r\n this._ready();\r\n\r\n this.log(\"ready\");\r\n }\r\n\r\n get defaultOptions() {\r\n return {};\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @returns {any}\r\n */\r\n getOption(opt) {\r\n return this.options[opt];\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n * @param {any} v\r\n */\r\n setOption(opt, v) {\r\n setAttribute(this, `data-${opt}`, v);\r\n }\r\n\r\n /**\r\n * @param {String} opt\r\n */\r\n toggleOption(opt) {\r\n setAttribute(this, `data-${opt}`, !this.getOption(opt));\r\n }\r\n\r\n get normalizedDataset() {\r\n let data = { ...this.dataset };\r\n for (var key in data) {\r\n data[key] = normalizeData(data[key]);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * @returns {String}\r\n */\r\n static template() {\r\n return \"\";\r\n }\r\n\r\n /**\r\n * This is called at the end of constructor. Extend in subclass if needed.\r\n */\r\n _ready() {}\r\n\r\n /**\r\n * @param {String|Error} message\r\n */\r\n log(message) {\r\n if (this.options.debug) {\r\n console.log(\"[\" + getAttribute(this, \"id\") + \"] \" + message);\r\n }\r\n }\r\n\r\n /**\r\n * Handle events within the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n\r\n /**\r\n * This is called when connected. Extend in subclass if needed.\r\n */\r\n _connected() {}\r\n\r\n connectedCallback() {\r\n // ensure whenDefined callbacks run first\r\n setTimeout(() => {\r\n this.log(\"connectedCallback\");\r\n\r\n // Append only when labels had the opportunity to be set\r\n // Don't use shadow dom as it makes theming super hard\r\n const template = document.createElement(\"template\");\r\n // @ts-ignore\r\n template.innerHTML = this.constructor.template();\r\n this.appendChild(template.content.cloneNode(true));\r\n\r\n this._connected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"connected\");\r\n }, 0);\r\n }\r\n\r\n /**\r\n * This is called when disconnected. Extend in subclass if needed.\r\n */\r\n _disconnected() {}\r\n\r\n disconnectedCallback() {\r\n this.log(\"disconnectedCallback\");\r\n this._disconnected();\r\n // @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#life-cycle-events\r\n dispatch(this, \"disconnected\");\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#a-props-like-accessor\r\n * @returns {Object}\r\n */\r\n get transformAttributes() {\r\n return {};\r\n }\r\n\r\n /**\r\n * This is only meant to work with data attributes\r\n * This allows us to have properties that reflect automatically in the component\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dataset-attributes\r\n * @param {String} attributeName\r\n * @param {String} oldValue\r\n * @param {String} newValue\r\n */\r\n attributeChangedCallback(attributeName, oldValue, newValue) {\r\n // It didn't change\r\n if (oldValue === newValue) {\r\n return;\r\n }\r\n\r\n this.log(\"attributeChangedCallback: \" + attributeName);\r\n\r\n let isOption = false;\r\n const transformer = this.transformAttributes[attributeName] ?? normalizeData;\r\n\r\n // Data attributes are mapped to options while other attributes are mapped as properties\r\n if (attributeName.indexOf(\"data-\") === 0) {\r\n attributeName = attributeName.slice(5);\r\n isOption = true;\r\n }\r\n attributeName = camelize(attributeName);\r\n if (isOption) {\r\n this.options[attributeName] = transformer(newValue);\r\n } else {\r\n this[attributeName] = transformer(newValue);\r\n }\r\n\r\n // Fire internal event\r\n if (this.fireEvents && this[`${attributeName}Changed`]) {\r\n this[`${attributeName}Changed`]();\r\n }\r\n }\r\n}\r\n\r\nexport default BaseElement;\r\n", "/**\r\n * @param {HTMLSelectElement} el\r\n * @param {String} value\r\n * @param {String} label\r\n * @param {Boolean} checked\r\n */\r\nexport default function addSelectOption(el, value, label, checked = false) {\r\n let opt = document.createElement(\"option\");\r\n opt.value = \"\" + value;\r\n if (checked) {\r\n opt.selected = true;\r\n }\r\n opt.label = label;\r\n el.appendChild(opt);\r\n}\r\n", "/**\r\n * @param {URL} url\r\n * @param {Object} params\r\n */\r\nexport default function appendParamsToUrl(url, params = {}) {\r\n Object.keys(params).forEach((key) => {\r\n if (Array.isArray(params[key])) {\r\n // @ts-ignore\r\n Object.keys(params[key]).forEach((k) => url.searchParams.append(isNaN(k) ? `${key}[${k}]` : key, params[key][k]));\r\n } else {\r\n url.searchParams.append(key, params[key]);\r\n }\r\n });\r\n}\r\n", "/**\r\n * Force value as arrays\r\n * @param {String|Array} v\r\n * @returns {Array}\r\n */\r\nexport default function convertArray(v) {\r\n if (typeof v === \"string\") {\r\n if (v[0] === \"[\") {\r\n // \"['my', 'value']\" would fail as a json\r\n if (v.indexOf('\"') === -1) {\r\n v = v.replace(/'/g, '\"');\r\n }\r\n return JSON.parse(v);\r\n }\r\n\r\n return v.split(\",\");\r\n }\r\n if (!Array.isArray(v)) {\r\n console.error(\"Invalid array\", v);\r\n return [];\r\n }\r\n return v;\r\n}\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @returns {Object}\r\n */\r\nexport default function elementOffset(el) {\r\n var rect = el.getBoundingClientRect(),\r\n scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,\r\n scrollTop = window.pageYOffset || document.documentElement.scrollTop;\r\n return { top: rect.top + scrollTop, left: rect.left + scrollLeft };\r\n}\r\n", "/**\r\n * Replace element within {} by their data value\r\n * @param {String} str\r\n * @param {Object} data\r\n * @returns {String}\r\n */\r\nexport default function interpolate(str, data) {\r\n return str.replace(/\\{([^}]+)?\\}/g, function ($1, $2) {\r\n return data[$2];\r\n });\r\n}\r\n", "/**\r\n * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.\r\n * Getting computed styles only works for dom that are added in the dom\r\n * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\r\n * @param {String} text The text to be rendered.\r\n * @param {Element} el Target element (defaults to body)\r\n * @param {Boolean} withPadding Include padding on element\r\n * @returns {Number}\r\n */\r\nexport default function getTextWidth(text, el = document.body, withPadding = false) {\r\n if (!el) {\r\n el = document.createElement(\"div\");\r\n }\r\n const styles = window.getComputedStyle(el);\r\n const fontWeight = styles.getPropertyValue(\"font-weight\") || \"normal\";\r\n const fontSize = styles.getPropertyValue(\"font-size\") || \"1rem\";\r\n const fontFamily = styles.getPropertyValue(\"font-family\") || \"Arial\";\r\n\r\n let padding = 0;\r\n if (withPadding) {\r\n const paddingLeft = styles.getPropertyValue(\"padding-left\") || \"0\";\r\n const paddingRight = styles.getPropertyValue(\"padding-right\") || \"0\";\r\n padding = parseInt(paddingLeft) + parseInt(paddingRight);\r\n }\r\n\r\n // re-use canvas object for better performance\r\n // @ts-ignore\r\n const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement(\"canvas\"));\r\n const context = canvas.getContext(\"2d\");\r\n context.font = `${fontWeight} ${fontSize} ${fontFamily}`;\r\n const metrics = context.measureText(text);\r\n return parseInt(metrics.width) + padding;\r\n}\r\n", "/**\r\n * @param {String} prefix\r\n * @returns {String}\r\n */\r\nexport default function randstr(prefix) {\r\n return Math.random()\r\n .toString(36)\r\n .replace(\"0.\", prefix || \"\");\r\n}\r\n", "/**\r\n * Data Grid Web component\r\n *\r\n * Credits for inspiration\r\n * @link https://github.com/riverside/zino-grid\r\n */\r\n\"use strict\";\r\n\r\nimport BaseElement from \"./core/base-element.js\";\r\nimport addSelectOption from \"./utils/addSelectOption.js\";\r\nimport appendParamsToUrl from \"./utils/appendParamsToUrl.js\";\r\nimport camelize from \"./utils/camelize.js\";\r\nimport convertArray from \"./utils/convertArray.js\";\r\nimport elementOffset from \"./utils/elementOffset.js\";\r\nimport interpolate from \"./utils/interpolate.js\";\r\nimport getTextWidth from \"./utils/getTextWidth.js\";\r\nimport randstr from \"./utils/randstr.js\";\r\nimport {\r\n dispatch,\r\n find,\r\n findAll,\r\n hasClass,\r\n removeAttribute,\r\n getAttribute,\r\n setAttribute,\r\n addClass,\r\n toggleClass,\r\n on,\r\n} from \"./utils/shortcuts.js\";\r\n\r\n/**\r\n * Column definition\r\n * @typedef Column\r\n * @property {String} field - the key in the data\r\n * @property {String} title - the title to display in the header (defaults to \"field\" if not set)\r\n * @property {Number} width - the width of the column (auto otherwise)\r\n * @property {String} class - class to set on the column (target body or header with th.class or td.class)\r\n * @property {String} attr - don't render the column and set a matching attribute on the row with the value of the field\r\n * @property {Boolean} hidden - hide the column\r\n * @property {Boolean} noSort - allow disabling sort for a given column\r\n * @property {String} format - custom data formatting\r\n * @property {String} transform - custom value transformation\r\n * @property {Boolean} editable - replace with input (EditableColumn module)\r\n * @property {Number} responsive - the higher the value, the sooner it will be hidden, disable with 0 (ResponsiveGrid module)\r\n * @property {Boolean} responsiveHidden - hidden through responsive module (ResponsiveGrid module)\r\n */\r\n\r\n/**\r\n * Row action\r\n * @typedef Action\r\n * @property {String} title - the title of the button\r\n * @property {String} name - the name of the action\r\n * @property {String} class - the class for the button\r\n * @property {String} url - link for the action\r\n * @property {String} html - custom button data\r\n * @property {Boolean} confirm - needs confirmation\r\n * @property {Boolean} default - is the default row action\r\n */\r\n\r\n/** @typedef {import('./plugins/autosize-column').default} AutosizeColumn */\r\n/** @typedef {import('./plugins/column-resizer').default} ColumnResizer */\r\n/** @typedef {import('./plugins/context-menu').default} ContextMenu */\r\n/** @typedef {import('./plugins/draggable-headers').default} DraggableHeaders */\r\n/** @typedef {import('./plugins/editable-column').default} EditableColumn */\r\n/** @typedef {import('./plugins/fixed-height').default} FixedHeight */\r\n/** @typedef {import('./plugins/responsive-grid').default} ResponsiveGrid */\r\n/** @typedef {import('./plugins/row-actions').default} RowActions */\r\n/** @typedef {import('./plugins/selectable-rows').default} SelectableRows */\r\n/** @typedef {import('./plugins/touch-support').default} TouchSupport */\r\n\r\n/**\r\n * These plugins are all optional\r\n * @typedef {Object} Plugins\r\n * @property {ColumnResizer} [ColumnResizer] resize handlers in the headers\r\n * @property {ContextMenu} [ContextMenu] menu to show/hide columns\r\n * @property {DraggableHeaders} [DraggableHeaders] draggable headers columns\r\n * @property {EditableColumn} [EditableColumn] draggable headers columns\r\n * @property {TouchSupport} [TouchSupport] touch swipe\r\n * @property {SelectableRows} [SelectableRows] create a column with checkboxes to select rows\r\n * @property {FixedHeight} [FixedHeight] allows having fixed height tables\r\n * @property {AutosizeColumn} [AutosizeColumn] compute ideal width based on column content\r\n * @property {ResponsiveGrid} [ResponsiveGrid] hide/show column on the fly\r\n * @property {RowActions} [RowActions] add action on rows\r\n */\r\n\r\n/**\r\n * Parameters to pass along or receive from the server\r\n * @typedef ServerParams\r\n * @property {String} serverParams.start\r\n * @property {String} serverParams.length\r\n * @property {String} serverParams.search\r\n * @property {String} serverParams.sort\r\n * @property {String} serverParams.sortDir\r\n * @property {String} serverParams.dataKey\r\n * @property {String} serverParams.errorKey\r\n * @property {String} serverParams.metaKey\r\n * @property {String} serverParams.metaTotalKey\r\n * @property {String} serverParams.metaFilteredKey\r\n * @property {String} serverParams.optionsKey\r\n * @property {String} serverParams.paramsKey\r\n */\r\n\r\n/**\r\n * Available data grid options, plugins included\r\n * @typedef Options\r\n * @property {?String} id Custom id for the grid\r\n * @property {?String} url An URL with data to display in JSON format\r\n * @property {Boolean} debug Log actions in DevTools console\r\n * @property {Boolean} filter Allows a filtering functionality\r\n * @property {Boolean} sort Allows a sort by column functionality\r\n * @property {String} defaultSort Default sort field if sorting is enabled\r\n * @property {Boolean} server Is a server side powered grid\r\n * @property {ServerParams} serverParams Describe keys passed to the server backend\r\n * @property {String} dir Dir\r\n * @property {Array} perPageValues Available per page options\r\n * @property {Column[]} columns Available columns\r\n * @property {Number} defaultPage Starting page\r\n * @property {Number} perPage Number of records displayed per page\r\n * @property {Boolean} expand Allow cell content to spawn over multiple lines\r\n * @property {Action[]} actions Row actions (RowActions module)\r\n * @property {Boolean} collapseActions Group actions (RowActions module)\r\n * @property {Boolean} resizable Make columns resizable (ColumnResizer module)\r\n * @property {Boolean} selectable Allow selecting rows with a checkbox (SelectableRows module)\r\n * @property {Boolean} selectVisibleOnly Select all only selects visible rows (SelectableRows module)\r\n * @property {Boolean} autosize Compute column sizes based on given data (Autosize module)\r\n * @property {Boolean} autoheight Adjust height so that it matches table size (FixedHeight module)\r\n * @property {Boolean} menu Right click menu on column headers (ContextMenu module)\r\n * @property {Boolean} reorder Allows a column reordering functionality (DraggableHeaders module)\r\n * @property {Boolean} responsive Change display mode on small screens (ResponsiveGrid module)\r\n * @property {Boolean} responsiveToggle Show toggle column (ResponsiveGrid module)\r\n */\r\n\r\n/**\r\n * Available labels that can be translated\r\n * @typedef Labels\r\n * @property {String} itemsPerPage\r\n * @property {String} gotoPage\r\n * @property {String} gotoFirstPage\r\n * @property {String} gotoPrevPage\r\n * @property {String} gotoNextPage\r\n * @property {String} gotoLastPage\r\n * @property {String} of\r\n * @property {String} items\r\n * @property {String} resizeColumn\r\n * @property {String} noData\r\n * @property {String} areYouSure\r\n */\r\n\r\n/**\r\n * List of registered plugins\r\n * @type {Plugins}\r\n */\r\nlet plugins = {};\r\n\r\n/**\r\n * @type {Labels}\r\n */\r\nlet labels = {\r\n itemsPerPage: \"Items per page\",\r\n gotoPage: \"Go to page\",\r\n gotoFirstPage: \"Go to first page\",\r\n gotoPrevPage: \"Go to previous page\",\r\n gotoNextPage: \"Go to next page\",\r\n gotoLastPage: \"Go to last page\",\r\n of: \"of\",\r\n items: \"items\",\r\n resizeColumn: \"Resize column\",\r\n noData: \"No data\",\r\n areYouSure: \"Are you sure?\",\r\n};\r\n\r\n/**\r\n * Column definition will update some props on the html element\r\n * @param {HTMLElement} el\r\n * @param {Column} column\r\n */\r\nfunction applyColumnDefinition(el, column) {\r\n if (column.width) {\r\n setAttribute(el, \"width\", column.width);\r\n }\r\n if (column.class) {\r\n addClass(el, column.class);\r\n }\r\n if (column.hidden) {\r\n setAttribute(el, \"hidden\", \"\");\r\n if (column.responsiveHidden) {\r\n addClass(el, \"dg-responsive-hidden\");\r\n }\r\n }\r\n}\r\n\r\n/**\r\n */\r\nclass DataGrid extends BaseElement {\r\n _ready() {\r\n setAttribute(this, \"id\", this.options.id ?? randstr(\"el-\"), true);\r\n\r\n /**\r\n * The grid displays that data\r\n * @type {Array}\r\n */\r\n this.data = [];\r\n /**\r\n * We store the original data in this\r\n * @type {Array}\r\n */\r\n this.originalData = [];\r\n\r\n // Make the IDE happy\r\n /**\r\n * @type {Options}\r\n */\r\n this.options = this.options || this.defaultOptions;\r\n\r\n // Init values\r\n this.fireEvents = false;\r\n this.page = this.options.defaultPage || 1;\r\n this.pages = 0;\r\n this.meta = {};\r\n /**\r\n * @type {Plugins}\r\n */\r\n this.plugins = {};\r\n // Init plugins\r\n for (const [pluginName, pluginClass] of Object.entries(plugins)) {\r\n // @ts-ignore until we can set typeof import ...\r\n this.plugins[pluginName] = new pluginClass(this);\r\n }\r\n\r\n // Expose options as observed attributes in the dom\r\n // Do it when fireEvents is disabled to avoid firing change callbacks\r\n for (const attr of DataGrid.observedAttributes) {\r\n if (attr.indexOf(\"data-\") === 0) {\r\n setAttribute(this, attr, this.options[camelize(attr.slice(5))]);\r\n }\r\n }\r\n }\r\n\r\n static template() {\r\n return `\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n`;\r\n }\r\n\r\n /**\r\n * @returns {Labels}\r\n */\r\n get labels() {\r\n return labels;\r\n }\r\n\r\n /**\r\n * @returns {Labels}\r\n */\r\n static getLabels() {\r\n return labels;\r\n }\r\n\r\n /**\r\n * @param {Object} v\r\n */\r\n static setLabels(v) {\r\n labels = Object.assign(labels, v);\r\n }\r\n\r\n /**\r\n * @returns {Column}\r\n */\r\n get defaultColumn() {\r\n return {\r\n field: \"\",\r\n title: \"\",\r\n width: 0,\r\n class: \"\",\r\n attr: \"\",\r\n hidden: false,\r\n editable: false,\r\n noSort: false,\r\n responsive: 1,\r\n responsiveHidden: false,\r\n format: \"\",\r\n transform: \"\",\r\n };\r\n }\r\n\r\n /**\r\n * @returns {Options}\r\n */\r\n get defaultOptions() {\r\n return {\r\n id: null,\r\n url: null,\r\n perPage: 10,\r\n debug: false,\r\n filter: false,\r\n menu: false,\r\n sort: false,\r\n server: false,\r\n serverParams: {\r\n start: \"start\",\r\n length: \"length\",\r\n search: \"search\",\r\n sort: \"sort\",\r\n sortDir: \"sortDir\",\r\n dataKey: \"data\",\r\n errorKey: \"error\",\r\n metaKey: \"meta\",\r\n metaTotalKey: \"total\",\r\n metaFilteredKey: \"filtered\",\r\n optionsKey: \"options\",\r\n paramsKey: \"params\",\r\n },\r\n defaultSort: \"\",\r\n reorder: false,\r\n dir: \"ltr\",\r\n perPageValues: [10, 25, 50, 100, 250],\r\n columns: [],\r\n actions: [],\r\n collapseActions: false,\r\n selectable: false,\r\n selectVisibleOnly: true,\r\n defaultPage: 1,\r\n resizable: false,\r\n autosize: true,\r\n expand: false,\r\n autoheight: true,\r\n responsive: false,\r\n responsiveToggle: true,\r\n };\r\n }\r\n\r\n /**\r\n * @param {Plugins} list\r\n */\r\n static registerPlugins(list) {\r\n plugins = list;\r\n }\r\n\r\n /**\r\n * @param {String} plugin\r\n */\r\n static unregisterPlugins(plugin = null) {\r\n if (plugin === null) {\r\n plugins = {};\r\n } else {\r\n delete plugins[plugin];\r\n }\r\n }\r\n\r\n /**\r\n * @returns {Plugins}\r\n */\r\n static registeredPlugins() {\r\n return plugins;\r\n }\r\n\r\n /**\r\n * @param {Object|Array} columns\r\n * @returns {Column[]}\r\n */\r\n convertColumns(columns) {\r\n let cols = [];\r\n // Convert key:value objects to actual columns\r\n if (typeof columns === \"object\" && !Array.isArray(columns)) {\r\n Object.keys(columns).forEach((key) => {\r\n let col = Object.assign({}, this.defaultColumn);\r\n col.title = columns[key];\r\n col.field = key;\r\n cols.push(col);\r\n });\r\n } else {\r\n columns.forEach((item) => {\r\n let col = Object.assign({}, this.defaultColumn);\r\n if (typeof item === \"string\") {\r\n col.title = item;\r\n col.field = item;\r\n } else if (typeof item === \"object\") {\r\n col = Object.assign(col, item);\r\n if (!col.field) {\r\n console.error(\"Invalid column definition\", item);\r\n }\r\n if (!col.title) {\r\n col.title = col.field;\r\n }\r\n } else {\r\n console.error(\"Column definition must be a string or an object\");\r\n }\r\n cols.push(col);\r\n });\r\n }\r\n return cols;\r\n }\r\n\r\n /**\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#reflected-dom-attributes\r\n * @returns {Array}\r\n */\r\n static get observedAttributes() {\r\n return [\r\n \"page\",\r\n \"data-filter\",\r\n \"data-sort\",\r\n \"data-debug\",\r\n \"data-reorder\",\r\n \"data-menu\",\r\n \"data-selectable\",\r\n \"data-url\",\r\n \"data-per-page\",\r\n \"data-responsive\",\r\n ];\r\n }\r\n\r\n get transformAttributes() {\r\n return {\r\n columns: (v) => this.convertColumns(convertArray(v)),\r\n actions: (v) => convertArray(v),\r\n defaultPage: (v) => parseInt(v),\r\n perPage: (v) => parseInt(v),\r\n };\r\n }\r\n\r\n get page() {\r\n return parseInt(this.getAttribute(\"page\"));\r\n }\r\n\r\n set page(val) {\r\n setAttribute(this, \"page\", this.constrainPageValue(val));\r\n }\r\n\r\n urlChanged() {\r\n this.loadData().then(() => {\r\n this.configureUi();\r\n });\r\n }\r\n\r\n constrainPageValue(v) {\r\n if (this.pages < v) {\r\n v = this.pages;\r\n }\r\n if (v < 1 || !v) {\r\n v = 1;\r\n }\r\n return v;\r\n }\r\n\r\n fixPage() {\r\n this.pages = this.totalPages();\r\n this.page = this.constrainPageValue(this.page);\r\n\r\n // Show current page in input\r\n setAttribute(this.inputPage, \"max\", this.pages);\r\n this.inputPage.value = \"\" + this.page;\r\n this.inputPage.disabled = this.pages === 1;\r\n }\r\n\r\n pageChanged() {\r\n this.reload();\r\n }\r\n\r\n responsiveChanged() {\r\n if (!this.plugins.ResponsiveGrid) {\r\n return;\r\n }\r\n if (this.options.responsive) {\r\n this.plugins.ResponsiveGrid.observe();\r\n } else {\r\n this.plugins.ResponsiveGrid.unobserve();\r\n }\r\n }\r\n\r\n menuChanged() {\r\n this.renderHeader();\r\n }\r\n\r\n /**\r\n * This is the callback for the select control\r\n */\r\n changePerPage() {\r\n this.options.perPage = parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value);\r\n this.perPageChanged();\r\n }\r\n\r\n /**\r\n * This is the actual event triggered on attribute change\r\n */\r\n perPageChanged() {\r\n // Refresh UI\r\n if (this.options.perPage !== parseInt(this.selectPerPage.options[this.selectPerPage.selectedIndex].value)) {\r\n this.perPageValuesChanged();\r\n }\r\n // Make sure current page is still valid\r\n let updatePage = this.page;\r\n while (updatePage > 1 && this.page * this.options.perPage > this.totalRecords()) {\r\n updatePage--;\r\n }\r\n if (updatePage != this.page) {\r\n // Triggers pageChanged, which will trigger reload\r\n this.page = updatePage;\r\n } else {\r\n // Simply reload current page\r\n this.reload(() => {\r\n // Preserve distance between top of page and select control if no fixed height\r\n if (!this.plugins.FixedHeight || !this.plugins.FixedHeight.hasFixedHeight) {\r\n this.selectPerPage.scrollIntoView();\r\n }\r\n });\r\n }\r\n }\r\n\r\n dirChanged() {\r\n setAttribute(this, \"dir\", this.options.dir);\r\n }\r\n\r\n defaultSortChanged() {\r\n this.sortChanged();\r\n }\r\n\r\n /**\r\n * Populate the select dropdown according to options\r\n */\r\n perPageValuesChanged() {\r\n if (!this.selectPerPage) {\r\n return;\r\n }\r\n while (this.selectPerPage.lastChild) {\r\n this.selectPerPage.removeChild(this.selectPerPage.lastChild);\r\n }\r\n this.options.perPageValues.forEach((v) => {\r\n addSelectOption(this.selectPerPage, v, v, v === this.options.perPage);\r\n });\r\n }\r\n\r\n _connected() {\r\n /**\r\n * @type {HTMLTableElement}\r\n */\r\n this.table = this.querySelector(\"table\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnFirst = this.querySelector(\".dg-btn-first\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnPrev = this.querySelector(\".dg-btn-prev\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnNext = this.querySelector(\".dg-btn-next\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.btnLast = this.querySelector(\".dg-btn-last\");\r\n /**\r\n * @type {HTMLSelectElement}\r\n */\r\n this.selectPerPage = this.querySelector(\".dg-select-per-page\");\r\n /**\r\n * @type {HTMLInputElement}\r\n */\r\n this.inputPage = this.querySelector(\".dg-input-page\");\r\n\r\n this.getFirst = this.getFirst.bind(this);\r\n this.getPrev = this.getPrev.bind(this);\r\n this.getNext = this.getNext.bind(this);\r\n this.getLast = this.getLast.bind(this);\r\n this.changePerPage = this.changePerPage.bind(this);\r\n this.gotoPage = this.gotoPage.bind(this);\r\n\r\n this.btnFirst.addEventListener(\"click\", this.getFirst);\r\n this.btnPrev.addEventListener(\"click\", this.getPrev);\r\n this.btnNext.addEventListener(\"click\", this.getNext);\r\n this.btnLast.addEventListener(\"click\", this.getLast);\r\n this.selectPerPage.addEventListener(\"change\", this.changePerPage);\r\n this.inputPage.addEventListener(\"input\", this.gotoPage);\r\n\r\n Object.values(this.plugins).forEach((plugin) => {\r\n plugin.connected();\r\n });\r\n\r\n // Display even if we don't have data\r\n this.dirChanged();\r\n this.perPageValuesChanged();\r\n\r\n this.loadData().finally(() => {\r\n this.configureUi();\r\n\r\n this.sortChanged();\r\n this.filterChanged();\r\n this.reorderChanged();\r\n\r\n this.dirChanged();\r\n this.perPageValuesChanged();\r\n this.pageChanged();\r\n\r\n this.classList.add(\"dg-initialized\");\r\n this.fireEvents = true; // We can now fire attributeChangedCallback events\r\n\r\n this.log(\"initialized\");\r\n });\r\n }\r\n\r\n _disconnected() {\r\n this.btnFirst.removeEventListener(\"click\", this.getFirst);\r\n this.btnPrev.removeEventListener(\"click\", this.getPrev);\r\n this.btnNext.removeEventListener(\"click\", this.getNext);\r\n this.btnLast.removeEventListener(\"click\", this.getLast);\r\n this.selectPerPage.removeEventListener(\"change\", this.changePerPage);\r\n this.inputPage.removeEventListener(\"input\", this.gotoPage);\r\n\r\n Object.values(this.plugins).forEach((plugin) => {\r\n plugin.disconnected();\r\n });\r\n }\r\n\r\n /**\r\n * @param {string} field\r\n * @returns {Column}\r\n */\r\n getCol(field) {\r\n let found = null;\r\n this.options.columns.forEach((col) => {\r\n if (col.field == field) {\r\n found = col;\r\n }\r\n });\r\n return found;\r\n }\r\n\r\n getColProp(field, prop) {\r\n const c = this.getCol(field);\r\n return c ? c[prop] : null;\r\n }\r\n\r\n setColProp(field, prop, val) {\r\n const c = this.getCol(field);\r\n if (c) {\r\n c[prop] = val;\r\n }\r\n }\r\n\r\n visibleColumns() {\r\n return this.options.columns.filter((col) => {\r\n return !col.hidden;\r\n });\r\n }\r\n\r\n hiddenColumns() {\r\n return this.options.columns.filter((col) => {\r\n return col.hidden === true;\r\n });\r\n }\r\n\r\n showColumn(field, render = true) {\r\n this.setColProp(field, \"hidden\", false);\r\n\r\n // We need to render the whole table otherwise layout fixed won't do its job\r\n if (render) this.renderTable();\r\n\r\n dispatch(this, \"columnVisibility\", {\r\n col: field,\r\n visibility: \"visible\",\r\n });\r\n }\r\n\r\n hideColumn(field, render = true) {\r\n this.setColProp(field, \"hidden\", true);\r\n\r\n // We need to render the whole table otherwise layout fixed won't do its job\r\n if (render) this.renderTable();\r\n\r\n dispatch(this, \"columnVisibility\", {\r\n col: field,\r\n visibility: \"hidden\",\r\n });\r\n }\r\n\r\n /**\r\n * Returns the starting index of actual data\r\n * @returns {Number}\r\n */\r\n startColIndex() {\r\n let start = 1;\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n start++;\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n start++;\r\n }\r\n return start;\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n isSticky() {\r\n return this.hasAttribute(\"sticky\");\r\n }\r\n\r\n /**\r\n * @param {Boolean} visibleOnly\r\n * @returns {Number}\r\n */\r\n columnsLength(visibleOnly = false) {\r\n let len = 0;\r\n // One column per (visible) column\r\n this.options.columns.forEach((col) => {\r\n if (visibleOnly && col.hidden) {\r\n return;\r\n }\r\n if (!col.attr) {\r\n len++;\r\n }\r\n });\r\n // Add one col for selectable checkbox at the beginning\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n len++;\r\n }\r\n // Add one col for actions at the end\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n len++;\r\n }\r\n // Add one col for the responsive toggle\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n len++;\r\n }\r\n return len;\r\n }\r\n\r\n /**\r\n * Global configuration and renderTable\r\n * This should be called after your data has been loaded\r\n */\r\n configureUi() {\r\n setAttribute(this.querySelector(\"table\"), \"aria-rowcount\", this.data.length);\r\n\r\n this.table.style.visibility = \"hidden\";\r\n this.renderTable();\r\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\r\n // Let the observer make the table visible\r\n } else {\r\n this.table.style.visibility = \"visible\";\r\n }\r\n\r\n // Store row height for later usage\r\n if (!this.rowHeight) {\r\n const tr = find(this, \"tbody tr\") || find(this, \"table tr\");\r\n if (tr) {\r\n this.rowHeight = tr.offsetHeight;\r\n }\r\n }\r\n }\r\n\r\n filterChanged() {\r\n const row = this.querySelector(\"thead tr.dg-head-filters\");\r\n if (this.options.filter) {\r\n removeAttribute(row, \"hidden\");\r\n } else {\r\n this.clearFilters();\r\n setAttribute(row, \"hidden\", \"\");\r\n }\r\n }\r\n\r\n reorderChanged() {\r\n const headers = findAll(this, \"thead tr.dg-head-columns th\");\r\n headers.forEach((th) => {\r\n if (th.classList.contains(\"dg-selectable\") || th.classList.contains(\"dg-actions\")) {\r\n return;\r\n }\r\n if (this.options.reorder && this.plugins.DraggableHeaders) {\r\n th.draggable = true;\r\n } else {\r\n th.removeAttribute(\"draggable\");\r\n }\r\n });\r\n }\r\n\r\n sortChanged() {\r\n this.log(\"toggle sort\");\r\n\r\n this.querySelectorAll(\"thead tr.dg-head-columns th\").forEach((th) => {\r\n const fieldName = th.getAttribute(\"field\");\r\n if (th.classList.contains(\"dg-not-sortable\") || (!this.fireEvents && fieldName == this.options.defaultSort)) {\r\n return;\r\n }\r\n if (this.options.sort && !this.getColProp(fieldName, \"noSort\")) {\r\n setAttribute(th, \"aria-sort\", \"none\");\r\n } else {\r\n removeAttribute(th, \"aria-sort\");\r\n }\r\n });\r\n }\r\n\r\n selectableChanged() {\r\n this.renderTable();\r\n }\r\n\r\n addRow(row) {\r\n this.log(\"Add row\");\r\n this.originalData.push(row);\r\n this.data = this.originalData.slice();\r\n this.sortData();\r\n }\r\n\r\n /**\r\n * @param {any} value Value to remove. Defaults to last row.\r\n * @param {String} key The key of the item to remove. Defaults to first column\r\n */\r\n removeRow(value = null, key = null) {\r\n if (key === null) {\r\n key = this.options.columns[0][\"field\"];\r\n }\r\n if (value === null) {\r\n value = this.originalData[this.originalData.length - 1][key];\r\n }\r\n this.log(\"Removing \" + key + \":\" + value);\r\n for (let i = 0; i < this.originalData.length; i++) {\r\n if (this.originalData[i][key] === value) {\r\n this.originalData.splice(i, 1);\r\n break;\r\n }\r\n }\r\n this.data = this.originalData.slice();\r\n this.sortData();\r\n }\r\n\r\n /**\r\n * @param {String} key Return a specific key (eg: id) instead of the whole row\r\n * @returns {Array}\r\n */\r\n getSelection(key = null) {\r\n if (!this.plugins.SelectableRows) {\r\n return [];\r\n }\r\n return this.plugins.SelectableRows.getSelection(key);\r\n }\r\n\r\n getData() {\r\n return this.originalData;\r\n }\r\n\r\n clearData() {\r\n // Already empty\r\n if (this.data.length === 0) {\r\n return;\r\n }\r\n this.data = this.originalData = [];\r\n this.renderBody();\r\n }\r\n\r\n refresh(cb = null) {\r\n this.data = this.originalData = [];\r\n return this.reload(cb);\r\n }\r\n\r\n reload(cb = null) {\r\n this.log(\"reload\");\r\n\r\n // If the data was cleared, we need to render again\r\n const needRender = this.originalData.length === 0;\r\n this.fixPage();\r\n this.loadData().finally(() => {\r\n // If we load data from the server, we redraw the table body\r\n // Otherwise, we just need to paginate\r\n this.options.server || needRender ? this.renderBody() : this.paginate();\r\n if (cb) {\r\n cb();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * @returns {Promise}\r\n */\r\n loadData() {\r\n // We already have some data\r\n if (this.originalData.length) {\r\n // We don't use server side data\r\n if (!this.options.server || (this.options.server && !this.fireEvents)) {\r\n // if (!this.options.server) {\r\n this.log(\"skip loadData\");\r\n return new Promise((resolve) => {\r\n resolve();\r\n });\r\n }\r\n }\r\n this.log(\"loadData\");\r\n this.loading = true;\r\n this.classList.add(\"dg-loading\");\r\n return this.fetchData()\r\n .then((response) => {\r\n this.classList.remove(\"dg-loading\");\r\n this.loading = false;\r\n\r\n // We can get a straight array or an object\r\n if (Array.isArray(response)) {\r\n this.data = response;\r\n } else {\r\n // Object must contain data key\r\n if (response[this.options.serverParams.errorKey]) {\r\n this.querySelector(\"tbody\").setAttribute(\r\n \"data-empty\",\r\n response[this.options.serverParams.errorKey].replace(/^\\s+|\\r\\n|\\n|\\r$/g, \"\")\r\n );\r\n this.removeAttribute(\"data-url\");\r\n return;\r\n }\r\n if (!response[this.options.serverParams.dataKey]) {\r\n console.error(\"Invalid response, it should contain a data key with an array or be a plain array\", response);\r\n this.options.url = null;\r\n return;\r\n }\r\n\r\n // We may have a config object\r\n this.options = Object.assign(this.options, response[this.options.serverParams.optionsKey] ?? {});\r\n // It should return meta data (see metaFilteredKey)\r\n this.meta = response[this.options.serverParams.metaKey] ?? {};\r\n this.data = response[this.options.serverParams.dataKey];\r\n }\r\n this.originalData = this.data.slice();\r\n this.fixPage();\r\n\r\n // Make sure we have a proper set of columns\r\n if (this.options.columns.length === 0 && this.originalData.length) {\r\n this.options.columns = this.convertColumns(Object.keys(this.originalData[0]));\r\n } else {\r\n this.options.columns = this.convertColumns(this.options.columns);\r\n }\r\n })\r\n .catch((err) => {\r\n this.log(err);\r\n });\r\n }\r\n\r\n getFirst() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = 1;\r\n }\r\n\r\n getLast() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.pages;\r\n }\r\n\r\n getPrev() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.page - 1;\r\n }\r\n\r\n getNext() {\r\n if (this.loading) {\r\n return;\r\n }\r\n this.page = this.page + 1;\r\n }\r\n\r\n gotoPage(event) {\r\n if (event.type === \"keypress\") {\r\n const key = event.keyCode || event.key;\r\n if (key === 13 || key === \"Enter\") {\r\n event.preventDefault();\r\n } else {\r\n return;\r\n }\r\n }\r\n this.page = parseInt(this.inputPage.value);\r\n }\r\n\r\n getSort() {\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (col) {\r\n return col.getAttribute(\"field\");\r\n }\r\n return this.options.defaultSort;\r\n }\r\n\r\n getSortDir() {\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (col) {\r\n return col.getAttribute(\"aria-sort\") || \"\";\r\n }\r\n return \"\";\r\n }\r\n\r\n getFilters() {\r\n let filters = [];\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n filters[input.dataset.name] = input.value;\r\n });\r\n return filters;\r\n }\r\n\r\n clearFilters() {\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n input.value = \"\";\r\n });\r\n this.filterData();\r\n }\r\n\r\n filterData() {\r\n this.log(\"filter data\");\r\n\r\n this.page = 1;\r\n\r\n if (this.options.server) {\r\n this.reload();\r\n } else {\r\n this.data = this.originalData.slice();\r\n\r\n // Look for rows matching the filters\r\n const inputs = findAll(this, \"thead tr.dg-head-filters input\");\r\n inputs.forEach((input) => {\r\n let value = input.value;\r\n if (value) {\r\n let name = input.dataset.name;\r\n this.data = this.data.filter((item) => {\r\n let str = item[name] + \"\";\r\n return str.toLowerCase().indexOf(value.toLowerCase()) !== -1;\r\n });\r\n }\r\n });\r\n this.pageChanged();\r\n\r\n let col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n if (this.options.sort && col) {\r\n this.sortData();\r\n } else {\r\n this.renderBody();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Data will be sorted then rendered using renderBody\r\n * @param {Element} col The column that was clicked or null to use current sort\r\n */\r\n sortData(col = null) {\r\n this.log(\"sort data\");\r\n\r\n // Early exit\r\n if (col && this.getColProp(col.getAttribute(\"field\"), \"noSort\")) {\r\n this.log(\"sorting prevented because column is not sortable\");\r\n return;\r\n }\r\n if (this.plugins.ColumnResizer && this.plugins.ColumnResizer.isResizing) {\r\n this.log(\"sorting prevented because resizing\");\r\n return;\r\n }\r\n if (this.loading) {\r\n this.log(\"sorting prevented because loading\");\r\n return;\r\n }\r\n\r\n // We clicked on a column, update sort state\r\n if (col !== null) {\r\n // Remove active sort if any\r\n const haveClasses = c => [\"dg-selectable\", \"dg-actions\", \"dg-responsive-toggle\"].includes(c);\r\n this.querySelectorAll(\"thead tr:first-child th\").forEach((th) => {\r\n // @ts-ignore\r\n if ([...th.classList].some(haveClasses)) {\r\n return;\r\n }\r\n if (th !== col) {\r\n th.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n });\r\n\r\n // Set tristate col\r\n if (!col.hasAttribute(\"aria-sort\") || col.getAttribute(\"aria-sort\") === \"none\") {\r\n col.setAttribute(\"aria-sort\", \"ascending\");\r\n } else if (col.getAttribute(\"aria-sort\") === \"ascending\") {\r\n col.setAttribute(\"aria-sort\", \"descending\");\r\n } else if (col.getAttribute(\"aria-sort\") === \"descending\") {\r\n col.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n } else {\r\n // Or fetch current sort\r\n col = this.querySelector(\"thead tr.dg-head-columns th[aria-sort$='scending']\");\r\n }\r\n\r\n if (this.options.server) {\r\n // Reload data with updated sort\r\n this.loadData().finally(() => {\r\n this.renderBody();\r\n });\r\n } else {\r\n const sort = col ? col.getAttribute(\"aria-sort\") : \"none\";\r\n if (sort === \"none\") {\r\n let stack = [];\r\n\r\n // Restore order while keeping filters\r\n this.originalData.some((itemA) => {\r\n this.data.some((itemB) => {\r\n if (JSON.stringify(itemA) === JSON.stringify(itemB)) {\r\n stack.push(itemB);\r\n return true;\r\n }\r\n return false;\r\n });\r\n return stack.length === this.data.length;\r\n });\r\n\r\n this.data = stack;\r\n } else {\r\n const field = col.getAttribute(\"field\");\r\n this.data.sort((a, b) => {\r\n if (!isNaN(a[field]) && !isNaN(b[field])) {\r\n return sort === \"ascending\" ? a[field] - b[field] : b[field] - a[field];\r\n }\r\n const valA = sort === \"ascending\" ? a[field].toUpperCase() : b[field].toUpperCase();\r\n const valB = sort === \"ascending\" ? b[field].toUpperCase() : a[field].toUpperCase();\r\n\r\n switch (true) {\r\n case valA > valB:\r\n return 1;\r\n case valA < valB:\r\n return -1;\r\n case valA === valB:\r\n return 0;\r\n }\r\n });\r\n }\r\n this.renderBody();\r\n }\r\n }\r\n\r\n fetchData() {\r\n if (!this.options.url) {\r\n return new Promise((resolve, reject) => reject(\"No url set\"));\r\n }\r\n\r\n let base = window.location.href;\r\n // Fix trailing slash if no extension is present\r\n if (!base.split(\"/\").pop().includes(\".\")) {\r\n base += base.endsWith(\"/\") ? \"\" : \"/\";\r\n }\r\n let url = new URL(this.options.url, base);\r\n let params = {\r\n r: Date.now(),\r\n };\r\n if (this.options.server) {\r\n // 0 based\r\n params[this.options.serverParams.start] = this.page - 1;\r\n params[this.options.serverParams.length] = this.options.perPage;\r\n params[this.options.serverParams.search] = this.getFilters();\r\n params[this.options.serverParams.sort] = this.getSort() || \"\";\r\n params[this.options.serverParams.sortDir] = this.getSortDir();\r\n\r\n // extra params ?\r\n if (this.meta[this.options.serverParams.paramsKey]) {\r\n params = Object.assign(params, this.meta[this.options.serverParams.paramsKey]);\r\n }\r\n }\r\n\r\n appendParamsToUrl(url, params);\r\n\r\n return fetch(url)\r\n .then((response) => {\r\n if (!response.ok) {\r\n throw new Error(response.statusText);\r\n }\r\n return response.json();\r\n })\r\n .catch((err) => {\r\n return {\r\n error: err.message,\r\n };\r\n });\r\n }\r\n\r\n renderTable() {\r\n this.log(\"render table\");\r\n\r\n if (this.options.menu && this.plugins.ContextMenu) {\r\n this.plugins.ContextMenu.createMenu();\r\n }\r\n\r\n let sortedColumn;\r\n\r\n this.renderHeader();\r\n if (this.options.defaultSort) {\r\n // We can have a default sort even with sort disabled\r\n sortedColumn = this.querySelector(\"thead tr.dg-head-columns th[field='\" + this.options.defaultSort + \"']\");\r\n }\r\n\r\n if (sortedColumn) {\r\n this.sortData(sortedColumn);\r\n } else {\r\n this.renderBody();\r\n }\r\n\r\n this.renderFooter();\r\n }\r\n\r\n /**\r\n * Create table header\r\n * - One row for the column headers\r\n * - One row for the filters\r\n */\r\n renderHeader() {\r\n this.log(\"render header\");\r\n\r\n const thead = this.querySelector(\"thead\");\r\n this.createColumnHeaders(thead);\r\n this.createColumnFilters(thead);\r\n\r\n if (this.options.resizable && this.plugins.ColumnResizer) {\r\n this.plugins.ColumnResizer.renderResizer(labels.resizeColumn);\r\n }\r\n\r\n dispatch(this, \"headerRendered\");\r\n }\r\n\r\n renderFooter() {\r\n this.log(\"render footer\");\r\n\r\n const tfoot = this.querySelector(\"tfoot\");\r\n const td = tfoot.querySelector(\"td\");\r\n tfoot.removeAttribute(\"hidden\");\r\n setAttribute(td, \"colspan\", this.columnsLength(true));\r\n tfoot.style.display = \"\";\r\n }\r\n\r\n /**\r\n * Create the column headers based on column definitions and set options\r\n * @param {HTMLTableSectionElement} thead\r\n */\r\n createColumnHeaders(thead) {\r\n // @link https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively\r\n const availableWidth = this.clientWidth;\r\n const colMaxWidth = Math.round((availableWidth / this.columnsLength(true)) * 2);\r\n\r\n let idx = 0;\r\n let tr;\r\n\r\n // Create row\r\n tr = document.createElement(\"tr\");\r\n this.headerRow = tr;\r\n tr.setAttribute(\"role\", \"row\");\r\n tr.setAttribute(\"aria-rowindex\", \"1\");\r\n tr.setAttribute(\"class\", \"dg-head-columns\");\r\n\r\n // We need a real th from the dom to compute the size\r\n let sampleTh = thead.querySelector(\"tr.dg-head-columns th\");\r\n if (!sampleTh) {\r\n sampleTh = document.createElement(\"th\");\r\n thead.querySelector(\"tr\").appendChild(sampleTh);\r\n }\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createHeaderCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createHeaderCol(tr);\r\n }\r\n\r\n // Create columns\r\n idx = 0;\r\n let totalWidth = 0;\r\n this.options.columns.forEach((column) => {\r\n if (column.attr) {\r\n return;\r\n }\r\n const colIdx = idx + this.startColIndex();\r\n let th = document.createElement(\"th\");\r\n th.setAttribute(\"scope\", \"col\");\r\n th.setAttribute(\"role\", \"columnheader button\");\r\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\r\n th.setAttribute(\"id\", randstr(\"dg-col-\"));\r\n if (this.options.sort) {\r\n th.setAttribute(\"aria-sort\", \"none\");\r\n }\r\n th.setAttribute(\"field\", column.field);\r\n if (this.plugins.ResponsiveGrid && this.options.responsive) {\r\n setAttribute(th, \"data-responsive\", column.responsive || \"\");\r\n }\r\n // Make sure the header fits (+ add some room for sort icon if necessary)\r\n const computedWidth = getTextWidth(column.title, sampleTh, true) + 20;\r\n th.dataset.minWidth = \"\" + computedWidth;\r\n applyColumnDefinition(th, column);\r\n th.tabIndex = 0;\r\n th.textContent = column.title;\r\n\r\n let w = 0;\r\n // Autosize small based on first/last row ?\r\n // Take into account minWidth of the header and max available size based on col numbers\r\n if (this.options.autosize && this.plugins.AutosizeColumn) {\r\n const colAvailableWidth = Math.min(availableWidth - totalWidth, colMaxWidth);\r\n w = this.plugins.AutosizeColumn.computeSize(th, column, parseInt(th.dataset.minWidth), colAvailableWidth);\r\n } else {\r\n w = Math.max(parseInt(th.dataset.minWidth), parseInt(th.getAttribute(\"width\")));\r\n }\r\n\r\n setAttribute(th, \"width\", w);\r\n if (column.hidden) {\r\n th.setAttribute(\"hidden\", \"\");\r\n } else {\r\n totalWidth += w;\r\n }\r\n\r\n // Reorder columns with drag/drop\r\n if (this.options.reorder && this.plugins.DraggableHeaders) {\r\n this.plugins.DraggableHeaders.makeHeaderDraggable(th);\r\n }\r\n\r\n tr.appendChild(th);\r\n idx++;\r\n });\r\n\r\n // There is too much available width, and we want to avoid fixed layout to split remaining amount\r\n if (totalWidth < availableWidth) {\r\n const visibleCols = findAll(tr, \"th:not([hidden],.dg-not-resizable)\");\r\n if (visibleCols.length) {\r\n const lastCol = visibleCols[visibleCols.length - 1];\r\n removeAttribute(lastCol, \"width\");\r\n }\r\n }\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionHeader(tr);\r\n }\r\n\r\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-columns\"));\r\n\r\n // Once columns are inserted, we have an actual dom to query\r\n if (thead.offsetWidth > availableWidth) {\r\n this.log(`adjust width to fix size, ${thead.offsetWidth} > ${availableWidth}`);\r\n const scrollbarWidth = this.offsetWidth - this.clientWidth;\r\n let diff = thead.offsetWidth - availableWidth - scrollbarWidth;\r\n if (this.options.responsive && this.plugins.ResponsiveGrid) {\r\n diff += scrollbarWidth;\r\n }\r\n // Remove diff for columns that can afford it\r\n const thWithWidth = findAll(tr, \"th[width]\");\r\n thWithWidth.forEach((th) => {\r\n if (hasClass(th, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n if (diff <= 0) {\r\n return;\r\n }\r\n const actualWidth = parseInt(th.getAttribute(\"width\"));\r\n const minWidth = th.dataset.minWidth ? parseInt(th.dataset.minWidth) : 0;\r\n if (actualWidth > minWidth) {\r\n let newWidth = actualWidth - diff;\r\n if (newWidth < minWidth) {\r\n newWidth = minWidth;\r\n }\r\n diff -= actualWidth - newWidth;\r\n setAttribute(th, \"width\", newWidth);\r\n }\r\n });\r\n }\r\n\r\n // Context menu\r\n if (this.options.menu && this.plugins.ContextMenu) {\r\n this.plugins.ContextMenu.attachContextMenu();\r\n }\r\n\r\n // Sort col on click\r\n tr.querySelectorAll(\"[aria-sort]\").forEach((sortableRow) => {\r\n sortableRow.addEventListener(\"click\", () => this.sortData(sortableRow));\r\n });\r\n\r\n setAttribute(this.querySelector(\"table\"), \"aria-colcount\", this.columnsLength(true));\r\n }\r\n\r\n createColumnFilters(thead) {\r\n let idx = 0;\r\n let tr;\r\n\r\n // Create row for filters\r\n tr = document.createElement(\"tr\");\r\n this.filterRow = tr;\r\n tr.setAttribute(\"role\", \"row\");\r\n tr.setAttribute(\"aria-rowindex\", \"2\");\r\n tr.setAttribute(\"class\", \"dg-head-filters\");\r\n if (!this.options.filter) {\r\n tr.setAttribute(\"hidden\", \"\");\r\n }\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createFilterCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createFilterCol(tr);\r\n }\r\n\r\n this.options.columns.forEach((column) => {\r\n if (column.attr) {\r\n return;\r\n }\r\n const colIdx = idx + this.startColIndex();\r\n let relatedTh = thead.querySelector(\"tr.dg-head-columns th[aria-colindex='\" + colIdx + \"']\");\r\n if (!relatedTh) {\r\n console.warn(\"Related th not found\", colIdx);\r\n return;\r\n }\r\n let th = document.createElement(\"th\");\r\n th.setAttribute(\"aria-colindex\", \"\" + colIdx);\r\n\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n // Allows binding filter to this column\r\n input.dataset.name = column.field;\r\n input.id = randstr(\"dg-filter-\");\r\n // Don't use aria-label as it triggers autocomplete\r\n input.setAttribute(\"aria-labelledby\", relatedTh.getAttribute(\"id\"));\r\n if (!this.options.filter) {\r\n th.tabIndex = 0;\r\n } else {\r\n input.tabIndex = 0;\r\n }\r\n\r\n if (column.hidden) {\r\n th.setAttribute(\"hidden\", \"\");\r\n }\r\n\r\n th.appendChild(input);\r\n tr.appendChild(th);\r\n idx++;\r\n });\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionFilter(tr);\r\n }\r\n\r\n thead.replaceChild(tr, thead.querySelector(\"tr.dg-head-filters\"));\r\n\r\n // Filter content on enter\r\n tr.querySelectorAll(\"input\").forEach((input) => {\r\n input.addEventListener(\"keypress\", (e) => {\r\n const key = e.keyCode || e.key;\r\n if (key === 13 || key === \"Enter\") {\r\n this.filterData.call(this);\r\n }\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Render the data as rows in tbody\r\n * It will call paginate() at the end\r\n */\r\n renderBody() {\r\n this.log(\"render body\");\r\n let tr;\r\n let td;\r\n let idx;\r\n let tbody = document.createElement(\"tbody\");\r\n\r\n this.data.forEach((item, i) => {\r\n tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n setAttribute(tr, \"aria-rowindex\", i + 1);\r\n tr.tabIndex = 0;\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.createDataCol(tr);\r\n }\r\n if (this.options.responsive && this.plugins.ResponsiveGrid && this.plugins.ResponsiveGrid.hasHiddenColumns()) {\r\n this.plugins.ResponsiveGrid.createDataCol(tr);\r\n }\r\n\r\n // Expandable\r\n if (this.options.expand) {\r\n tr.classList.add(\"dg-expandable\");\r\n\r\n on(tr, \"click\", (ev) => {\r\n if (this.plugins.ResponsiveGrid) {\r\n this.plugins.ResponsiveGrid.blockObserver();\r\n }\r\n toggleClass(ev.currentTarget, \"dg-expanded\");\r\n if (this.plugins.ResponsiveGrid) {\r\n this.plugins.ResponsiveGrid.unblockObserver();\r\n }\r\n });\r\n }\r\n\r\n idx = 0;\r\n this.options.columns.forEach((column) => {\r\n if (!column) {\r\n console.error(\"Empty column found!\", this.options.columns);\r\n }\r\n // It should be applied as an attr of the row\r\n if (column.attr) {\r\n if (item[column.field]) {\r\n // Special case if we try to write over the class attr\r\n if (column.attr === \"class\") {\r\n addClass(tr, item[column.field]);\r\n } else {\r\n tr.setAttribute(column.attr, item[column.field]);\r\n }\r\n }\r\n return;\r\n }\r\n td = document.createElement(\"td\");\r\n td.setAttribute(\"role\", \"gridcell\");\r\n td.setAttribute(\"aria-colindex\", idx + this.startColIndex());\r\n applyColumnDefinition(td, column);\r\n // This is required for pure css responsive layout\r\n td.setAttribute(\"data-name\", column.title);\r\n td.tabIndex = -1;\r\n\r\n // Inline editing\r\n if (column.editable && this.plugins.EditableColumn) {\r\n this.plugins.EditableColumn.makeEditableInput(td, column, item, i);\r\n } else {\r\n const v = item[column.field] ?? \"\";\r\n let tv;\r\n // TODO: make this modular\r\n switch (column.transform) {\r\n case \"uppercase\":\r\n tv = v.toUpperCase();\r\n break;\r\n case \"lowercase\":\r\n tv = v.toLowerCase();\r\n break;\r\n default:\r\n tv = v;\r\n break;\r\n }\r\n if (column.format && tv) {\r\n td.innerHTML = interpolate(\r\n column.format,\r\n Object.assign(\r\n {\r\n _v: v,\r\n _tv: tv,\r\n },\r\n item\r\n )\r\n );\r\n } else {\r\n td.textContent = tv;\r\n }\r\n }\r\n tr.appendChild(td);\r\n idx++;\r\n });\r\n\r\n // Actions\r\n if (this.options.actions.length && this.plugins.RowActions) {\r\n this.plugins.RowActions.makeActionRow(tr, item);\r\n }\r\n\r\n tbody.appendChild(tr);\r\n });\r\n\r\n tbody.setAttribute(\"role\", \"rowgroup\");\r\n\r\n // Keep data empty message\r\n const prev = this.querySelector(\"tbody\");\r\n tbody.setAttribute(\"data-empty\", prev.getAttribute(\"data-empty\"));\r\n this.querySelector(\"table\").replaceChild(tbody, prev);\r\n\r\n if (this.plugins.FixedHeight) {\r\n this.plugins.FixedHeight.createFakeRow();\r\n }\r\n\r\n this.paginate();\r\n\r\n if (this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.shouldSelectAll(tbody);\r\n }\r\n\r\n dispatch(this, \"bodyRendered\");\r\n }\r\n\r\n paginate() {\r\n this.log(\"paginate\");\r\n\r\n const total = this.totalRecords();\r\n const p = this.page || 1;\r\n\r\n let index;\r\n let high = p * this.options.perPage;\r\n let low = high - this.options.perPage + 1;\r\n const tbody = this.querySelector(\"tbody\");\r\n const tfoot = this.querySelector(\"tfoot\");\r\n\r\n if (high > total) {\r\n high = total;\r\n }\r\n if (!total) {\r\n low = 0;\r\n }\r\n\r\n // Display all rows within the set indexes\r\n // For server side paginated grids, we display everything\r\n // since the server is taking care of actual pagination\r\n tbody.querySelectorAll(\"tr\").forEach((tr) => {\r\n if (this.options.server) {\r\n removeAttribute(tr, \"hidden\");\r\n return;\r\n }\r\n index = Number(getAttribute(tr, \"aria-rowindex\"));\r\n if (index > high || index < low) {\r\n setAttribute(tr, \"hidden\", \"\");\r\n } else {\r\n removeAttribute(tr, \"hidden\");\r\n }\r\n });\r\n\r\n if (this.options.selectable && this.plugins.SelectableRows) {\r\n this.plugins.SelectableRows.clearCheckboxes(tbody);\r\n }\r\n\r\n // Store default height and update styles if needed\r\n if (this.plugins.FixedHeight) {\r\n this.plugins.FixedHeight.updateFakeRow();\r\n }\r\n\r\n // Enable/disable buttons if shown\r\n if (this.btnFirst) {\r\n this.btnFirst.disabled = this.page <= 1;\r\n this.btnPrev.disabled = this.page <= 1;\r\n this.btnNext.disabled = this.page >= this.pages;\r\n this.btnLast.disabled = this.page >= this.pages;\r\n }\r\n tfoot.querySelector(\".dg-low\").textContent = low.toString();\r\n tfoot.querySelector(\".dg-high\").textContent = high.toString();\r\n tfoot.querySelector(\".dg-total\").textContent = \"\" + this.totalRecords();\r\n }\r\n\r\n /**\r\n * @returns {number}\r\n */\r\n totalPages() {\r\n return Math.ceil(this.totalRecords() / this.options.perPage);\r\n }\r\n\r\n /**\r\n * @returns {number}\r\n */\r\n totalRecords() {\r\n if (this.options.server) {\r\n return this.meta[this.options.serverParams.metaFilteredKey] || 0;\r\n }\r\n return this.data.length;\r\n }\r\n}\r\n\r\nexport default DataGrid;\r\n", "/** @typedef {import(\"../data-grid\").default} DataGrid */\r\n\r\nclass BasePlugin {\r\n /**\r\n * @param {DataGrid} grid\r\n */\r\n constructor(grid) {\r\n this.grid = grid;\r\n }\r\n\r\n connected() {}\r\n\r\n disconnected() {}\r\n\r\n /**\r\n * Handle events within the plugin\r\n * @link https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4#handling-events\r\n * @param {Event} event\r\n */\r\n handleEvent(event) {\r\n if (this[`on${event.type}`]) {\r\n this[`on${event.type}`](event);\r\n }\r\n }\r\n}\r\n\r\nexport default BasePlugin;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport elementOffset from \"../utils/elementOffset.js\";\r\nimport {\r\n addClass,\r\n dispatch,\r\n findAll,\r\n getAttribute,\r\n hasClass,\r\n off,\r\n on,\r\n removeAttribute,\r\n removeClass,\r\n setAttribute,\r\n} from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass ColumnResizer extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.isResizing = false;\r\n }\r\n\r\n /**\r\n * @param {String} resizeLabel\r\n */\r\n renderResizer(resizeLabel) {\r\n const grid = this.grid;\r\n const table = grid.table;\r\n const cols = findAll(grid, \"thead tr.dg-head-columns th\");\r\n\r\n cols.forEach((col) => {\r\n if (hasClass(col, \"dg-not-resizable\")) {\r\n return;\r\n }\r\n // Create a resizer element\r\n const resizer = document.createElement(\"div\");\r\n addClass(resizer, \"dg-resizer\");\r\n resizer.ariaLabel = resizeLabel;\r\n\r\n // Add a resizer element to the column\r\n col.appendChild(resizer);\r\n\r\n // Handle resizing\r\n let startX = 0;\r\n let startW = 0;\r\n let remainingSpace = 0;\r\n let max = 0;\r\n\r\n const mouseMoveHandler = (e) => {\r\n if (e.clientX > max) {\r\n return;\r\n }\r\n const newWidth = startW + (e.clientX - startX);\r\n if (col.dataset.minWidth && newWidth > parseInt(col.dataset.minWidth)) {\r\n setAttribute(col, \"width\", newWidth);\r\n }\r\n };\r\n\r\n // When user releases the mouse, remove the existing event listeners\r\n const mouseUpHandler = () => {\r\n grid.log(\"resized column\");\r\n\r\n // Prevent accidental sorting if mouse is not over resize handler\r\n setTimeout(() => {\r\n this.isResizing = false;\r\n }, 0);\r\n\r\n removeClass(resizer, \"dg-resizer-active\");\r\n if (grid.options.reorder) {\r\n col.draggable = true;\r\n }\r\n col.style.overflow = \"hidden\";\r\n\r\n // Remove handlers\r\n off(document, \"mousemove\", mouseMoveHandler);\r\n off(document, \"mouseup\", mouseUpHandler);\r\n\r\n dispatch(grid, \"columnResized\", {\r\n col: getAttribute(col, \"field\"),\r\n width: getAttribute(col, \"width\"),\r\n });\r\n };\r\n\r\n // Otherwise it could sort the col\r\n on(resizer, \"click\", (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n on(resizer, \"mousedown\", (e) => {\r\n e.stopPropagation();\r\n\r\n this.isResizing = true;\r\n\r\n const target = e.target;\r\n const currentCols = findAll(grid, \"dg-head-columns th\");\r\n const visibleCols = currentCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n const columnIndex = visibleCols.findIndex((column) => column == target.parentNode);\r\n grid.log(\"resize column\");\r\n\r\n addClass(resizer, \"dg-resizer-active\");\r\n\r\n // Make sure we don't drag it\r\n removeAttribute(col, \"draggable\");\r\n\r\n // Allow overflow when resizing\r\n col.style.overflow = \"visible\";\r\n\r\n // Show full column height (-1 to avoid scrollbar)\r\n resizer.style.height = table.offsetHeight - 1 + \"px\";\r\n\r\n // Register initial data\r\n startX = e.clientX;\r\n startW = col.offsetWidth;\r\n\r\n remainingSpace = (visibleCols.length - columnIndex) * 30;\r\n max = elementOffset(target).left + grid.offsetWidth - remainingSpace;\r\n\r\n // Remove width from next columns to allow auto layout\r\n setAttribute(col, \"width\", startW);\r\n for (let j = 0; j < visibleCols.length; j++) {\r\n if (j > columnIndex) {\r\n removeAttribute(cols[j], \"width\");\r\n }\r\n }\r\n\r\n // Attach handlers\r\n on(document, \"mousemove\", mouseMoveHandler);\r\n on(document, \"mouseup\", mouseUpHandler);\r\n });\r\n });\r\n }\r\n}\r\n\r\nexport default ColumnResizer;\r\n", "/**\r\n * @param {HTMLElement} el\r\n * @param {String} type\r\n * @param {String} prop\r\n * @returns {HTMLElement}\r\n */\r\nexport default function getParentElement(el, type, prop = \"nodeName\") {\r\n let parent = el;\r\n while (parent[prop] != type) {\r\n parent = parent.parentElement;\r\n }\r\n return parent;\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { find, off, on, removeAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Create a right click menu on the headers\r\n */\r\nclass ContextMenu extends BasePlugin {\r\n connected() {\r\n /**\r\n * @type {HTMLUListElement}\r\n */\r\n this.menu = this.grid.querySelector(\".dg-menu\");\r\n }\r\n disconnected() {\r\n if (this.grid.headerRow) {\r\n off(this.grid.headerRow, \"contextmenu\", this);\r\n }\r\n }\r\n\r\n attachContextMenu() {\r\n const grid = this.grid;\r\n on(grid.headerRow, \"contextmenu\", this);\r\n }\r\n\r\n onchange(e) {\r\n const grid = this.grid;\r\n const t = e.target;\r\n const field = t.dataset.name;\r\n if (t.checked) {\r\n grid.showColumn(field);\r\n } else {\r\n // Prevent hidding last\r\n if (grid.visibleColumns().length <= 1) {\r\n // Restore checkbox value\r\n t.checked = true;\r\n return;\r\n }\r\n grid.hideColumn(field);\r\n }\r\n }\r\n\r\n oncontextmenu(e) {\r\n e.preventDefault();\r\n const grid = this.grid;\r\n const target = getParentElement(e.target, \"THEAD\");\r\n const menu = this.menu;\r\n const rect = target.getBoundingClientRect();\r\n let x = e.clientX - rect.left;\r\n const y = e.clientY - rect.top;\r\n\r\n menu.style.top = `${y}px`;\r\n menu.style.left = `${x}px`;\r\n\r\n removeAttribute(menu, \"hidden\");\r\n if (x + 150 > rect.width) {\r\n x -= menu.offsetWidth;\r\n menu.style.left = `${x}px`;\r\n }\r\n\r\n const documentClickHandler = (e) => {\r\n if (!menu.contains(e.target)) {\r\n setAttribute(menu, \"hidden\", \"\");\r\n off(document, \"click\", documentClickHandler);\r\n }\r\n };\r\n on(document, \"click\", documentClickHandler);\r\n }\r\n createMenu() {\r\n const grid = this.grid;\r\n const menu = this.menu;\r\n while (menu.lastChild) {\r\n menu.removeChild(menu.lastChild);\r\n }\r\n menu.addEventListener(\"change\", this);\r\n grid.options.columns.forEach((col) => {\r\n if (col.attr) {\r\n return;\r\n }\r\n const li = document.createElement(\"li\");\r\n const label = document.createElement(\"label\");\r\n const checkbox = document.createElement(\"input\");\r\n setAttribute(checkbox, \"type\", \"checkbox\");\r\n setAttribute(checkbox, \"data-name\", col.field);\r\n if (!col.hidden) {\r\n checkbox.checked = true;\r\n }\r\n const text = document.createTextNode(col.title);\r\n\r\n label.appendChild(checkbox);\r\n label.appendChild(text);\r\n\r\n li.appendChild(label);\r\n menu.appendChild(li);\r\n });\r\n }\r\n}\r\n\r\nexport default ContextMenu;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getParentElement from \"../utils/getParentElement.js\";\r\nimport { dispatch, findAll, getAttribute, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to move headers\r\n */\r\nclass DraggableHeaders extends BasePlugin {\r\n /**\r\n * @param {HTMLTableCellElement} th\r\n */\r\n makeHeaderDraggable(th) {\r\n const grid = this.grid;\r\n th.draggable = true;\r\n on(th, \"dragstart\", (e) => {\r\n if (grid.plugins.ColumnResizer && grid.plugins.ColumnResizer.isResizing && e.preventDefault) {\r\n e.preventDefault();\r\n return;\r\n }\r\n grid.log(\"reorder col\");\r\n e.dataTransfer.effectAllowed = \"move\";\r\n e.dataTransfer.setData(\"text/plain\", e.target.getAttribute(\"aria-colindex\"));\r\n });\r\n on(th, \"dragover\", (e) => {\r\n if (e.preventDefault) {\r\n e.preventDefault();\r\n }\r\n e.dataTransfer.dropEffect = \"move\";\r\n return false;\r\n });\r\n on(th, \"drop\", (e) => {\r\n if (e.stopPropagation) {\r\n e.stopPropagation();\r\n }\r\n const t = e.target;\r\n const target = getParentElement(t, \"TH\");\r\n const index = parseInt(e.dataTransfer.getData(\"text/plain\"));\r\n const targetIndex = parseInt(target.getAttribute(\"aria-colindex\"));\r\n\r\n if (index === targetIndex) {\r\n grid.log(\"reordered col stayed the same\");\r\n return;\r\n }\r\n grid.log(\"reordered col from \" + index + \" to \" + targetIndex);\r\n\r\n const offset = grid.startColIndex();\r\n const tmp = grid.options.columns[index - offset];\r\n grid.options.columns[index - offset] = grid.options.columns[targetIndex - offset];\r\n grid.options.columns[targetIndex - offset] = tmp;\r\n\r\n const swapNodes = (selector, el1) => {\r\n const rowIndex = el1.parentNode.getAttribute(\"aria-rowindex\");\r\n const el2 = grid.querySelector(selector + \" tr[aria-rowindex='\" + rowIndex + \"'] [aria-colindex='\" + targetIndex + \"']\");\r\n setAttribute(el1, \"aria-colindex\", targetIndex);\r\n setAttribute(el2, \"aria-colindex\", index);\r\n const newNode = document.createElement(\"th\");\r\n el1.parentNode.insertBefore(newNode, el1);\r\n el2.parentNode.replaceChild(el1, el2);\r\n newNode.parentNode.replaceChild(el2, newNode);\r\n };\r\n\r\n // Swap all rows in header and body\r\n findAll(grid, \"thead th[aria-colindex='\" + index + \"']\").forEach((el1) => {\r\n swapNodes(\"thead\", el1);\r\n });\r\n findAll(grid, 'tbody td[aria-colindex=\"' + index + '\"]').forEach((el1) => {\r\n swapNodes(\"tbody\", el1);\r\n });\r\n\r\n // Updates the columns\r\n grid.options.columns = findAll(grid, \"thead tr.dg-head-columns th[field]\").map((th) =>\r\n grid.options.columns.find((c) => c.field == getAttribute(th, \"field\"))\r\n );\r\n\r\n dispatch(grid, \"columnReordered\", {\r\n col: tmp.field,\r\n from: index,\r\n to: targetIndex,\r\n });\r\n return false;\r\n });\r\n }\r\n}\r\n\r\nexport default DraggableHeaders;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\n\r\n/**\r\n * Allows to paginate with horizontal swipe motions\r\n */\r\nclass TouchSupport extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n this.touch = null;\r\n }\r\n connected() {\r\n const grid = this.grid;\r\n grid.addEventListener(\"touchstart\", this, { passive: true });\r\n grid.addEventListener(\"touchmove\", this, { passive: true });\r\n }\r\n\r\n disconnected() {\r\n const grid = this.grid;\r\n grid.removeEventListener(\"touchstart\", this);\r\n grid.removeEventListener(\"touchmove\", this);\r\n }\r\n\r\n ontouchstart(e) {\r\n this.touch = e.touches[0];\r\n }\r\n\r\n ontouchmove(e) {\r\n if (!this.touch) {\r\n return;\r\n }\r\n const grid = this.grid;\r\n const xDiff = this.touch.clientX - e.touches[0].clientX;\r\n const yDiff = this.touch.clientY - e.touches[0].clientY;\r\n\r\n if (Math.abs(xDiff) > Math.abs(yDiff)) {\r\n if (xDiff > 0) {\r\n grid.getNext();\r\n } else {\r\n grid.getPrev();\r\n }\r\n }\r\n this.touch = null;\r\n }\r\n}\r\n\r\nexport default TouchSupport;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch, findAll, hasClass, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\nconst SELECTABLE_CLASS = \"dg-selectable\";\r\nconst SELECT_ALL_CLASS = \"dg-select-all\";\r\nconst CHECKBOX_CLASS = \"form-check-input\"; //bs5\r\n\r\n/**\r\n * Allows to select rows\r\n */\r\nclass SelectableRows extends BasePlugin {\r\n disconnected() {\r\n if (this.selectAll) {\r\n this.selectAll.removeEventListener(\"change\", this);\r\n }\r\n }\r\n\r\n /**\r\n * @param {String} key Return a specific key (eg: id) instead of the whole row\r\n * @returns {Array}\r\n */\r\n getSelection(key = null) {\r\n const grid = this.grid;\r\n let selectedData = [];\r\n\r\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input:checked`);\r\n inputs.forEach((checkbox) => {\r\n const idx = parseInt(checkbox.dataset.id);\r\n const item = grid.data[idx - 1];\r\n if (!item) {\r\n console.warn(`Item ${idx} not found`);\r\n }\r\n if (key) {\r\n selectedData.push(item[key]);\r\n } else {\r\n selectedData.push(item);\r\n }\r\n });\r\n return selectedData;\r\n }\r\n\r\n /**\r\n * Uncheck box if hidden and visible only\r\n * @param {HTMLTableSectionElement} tbody\r\n */\r\n clearCheckboxes(tbody) {\r\n const grid = this.grid;\r\n if (!grid.options.selectVisibleOnly) {\r\n return;\r\n }\r\n const inputs = findAll(tbody, `tr[hidden] .${SELECTABLE_CLASS} input`);\r\n inputs.forEach((input) => {\r\n input.checked = false;\r\n });\r\n this.selectAll.checked = false;\r\n }\r\n\r\n colIndex() {\r\n return this.grid.startColIndex() - 2;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createHeaderCol(tr) {\r\n let th = document.createElement(\"th\");\r\n setAttribute(th, \"scope\", \"col\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(...[SELECTABLE_CLASS, \"dg-not-resizable\", \"dg-not-sortable\"]);\r\n th.tabIndex = 0;\r\n\r\n this.selectAll = document.createElement(\"input\");\r\n this.selectAll.type = \"checkbox\";\r\n this.selectAll.classList.add(SELECT_ALL_CLASS);\r\n this.selectAll.classList.add(CHECKBOX_CLASS);\r\n this.selectAll.addEventListener(\"change\", this);\r\n\r\n let label = document.createElement(\"label\");\r\n label.appendChild(this.selectAll);\r\n\r\n th.appendChild(label);\r\n\r\n th.setAttribute(\"width\", \"40\");\r\n tr.appendChild(th);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createFilterCol(tr) {\r\n let th = document.createElement(\"th\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(SELECTABLE_CLASS);\r\n th.tabIndex = 0;\r\n\r\n tr.appendChild(th);\r\n }\r\n\r\n /**\r\n * Handles the selectAll checkbox when any other .dg-selectable checkbox is checked on table body.\r\n * It should check selectAll if all is checked\r\n * It should uncheck selectAll if any is unchecked\r\n * @param {HTMLTableSectionElement} tbody\r\n */\r\n shouldSelectAll(tbody) {\r\n if (!this.selectAll) {\r\n return;\r\n }\r\n // Delegate listener for change events on input checkboxes\r\n tbody.addEventListener(\"change\", this);\r\n // Make sure state is up to date\r\n tbody.dispatchEvent(new Event(\"change\"));\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createDataCol(tr) {\r\n // Create col\r\n let td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell button\");\r\n setAttribute(td, \"aria-colindex\", this.colIndex());\r\n td.classList.add(SELECTABLE_CLASS);\r\n\r\n // Create input\r\n let selectOne = document.createElement(\"input\");\r\n // Alias row id for easy retrieval in getSelection\r\n selectOne.dataset.id = tr.getAttribute(\"aria-rowindex\");\r\n selectOne.type = \"checkbox\";\r\n selectOne.classList.add(CHECKBOX_CLASS);\r\n // Label need to take full space thanks to css to make the whole cell clickable\r\n let label = document.createElement(\"label\");\r\n label.classList.add(\"dg-clickable-cell\");\r\n label.appendChild(selectOne);\r\n td.appendChild(label);\r\n\r\n // Prevent unwanted click behaviour on row\r\n label.addEventListener(\"click\", this);\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n /**\r\n * @param {Event} e\r\n */\r\n onclick(e) {\r\n e.stopPropagation();\r\n }\r\n\r\n /**\r\n * Handle change event on select all or any select checkbox in the table body\r\n * @param {import(\"../utils/shortcuts.js\").FlexibleEvent} e\r\n */\r\n onchange(e) {\r\n const grid = this.grid;\r\n if (hasClass(e.target, SELECT_ALL_CLASS)) {\r\n const visibleOnly = grid.options.selectVisibleOnly;\r\n const inputs = findAll(grid, `tbody .${SELECTABLE_CLASS} input`);\r\n inputs.forEach((cb) => {\r\n if (visibleOnly && !cb.offsetWidth) {\r\n return;\r\n }\r\n cb.checked = this.selectAll.checked;\r\n });\r\n\r\n dispatch(grid, \"rowsSelected\", {\r\n selection: this.getSelection(),\r\n });\r\n } else {\r\n if (!e.target.closest(`.${SELECTABLE_CLASS}`)) {\r\n return;\r\n }\r\n const totalCheckboxes = findAll(grid, `tbody .${SELECTABLE_CLASS} input[type=checkbox]`);\r\n // @ts-ignore\r\n const totalChecked = totalCheckboxes.filter((n) => n.checked);\r\n this.selectAll.checked = totalChecked.length == totalCheckboxes.length;\r\n\r\n dispatch(grid, \"rowsSelected\", {\r\n selection: grid.getSelection(),\r\n });\r\n }\r\n }\r\n}\r\n\r\nexport default SelectableRows;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Support for fixed table height\r\n *\r\n * We should add a fake row to push the footer down in case we don't have enough rows\r\n */\r\nclass FixedHeight extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.hasFixedHeight = false;\r\n // If we have a fixed height, make sure we have overflowY set\r\n if (grid.style.height) {\r\n grid.style.overflowY = \"auto\";\r\n this.hasFixedHeight = true;\r\n }\r\n }\r\n\r\n /**\r\n */\r\n createFakeRow() {\r\n const grid = this.grid;\r\n const tbody = grid.querySelector(\"tbody\");\r\n let tr = document.createElement(\"tr\");\r\n setAttribute(tr, \"role\", \"row\");\r\n setAttribute(tr, \"hidden\", \"\");\r\n tr.classList.add(\"dg-fake-row\");\r\n tr.tabIndex = 0;\r\n tbody.appendChild(tr);\r\n }\r\n\r\n get fakeRow() {\r\n return this.grid.querySelector(\".dg-fake-row\");\r\n }\r\n\r\n /**\r\n * On last page, use a fake row to push footer down\r\n */\r\n updateFakeRow() {\r\n const grid = this.grid;\r\n const fakeRow = this.fakeRow;\r\n if (!fakeRow) {\r\n return;\r\n }\r\n\r\n // We don't need a fake row if we display everything\r\n if (grid.options.perPage > grid.totalRecords()) {\r\n return;\r\n }\r\n // We are not on last page\r\n if (grid.page !== grid.totalPages()) {\r\n return;\r\n }\r\n\r\n // Find remaining missing height\r\n const max = grid.options.perPage * grid.rowHeight;\r\n const visibleRows = grid.querySelectorAll(\"tbody tr:not([hidden])\").length;\r\n const fakeHeight = visibleRows > 1 ? max - visibleRows * grid.rowHeight : max;\r\n if (fakeHeight > 0) {\r\n setAttribute(fakeRow, \"height\", fakeHeight);\r\n fakeRow.removeAttribute(\"hidden\");\r\n } else {\r\n fakeRow.removeAttribute(\"height\");\r\n }\r\n }\r\n}\r\n\r\nexport default FixedHeight;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport getTextWidth from \"../utils/getTextWidth.js\";\r\nimport { getAttribute, hasAttribute, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Allows to resize columns\r\n */\r\nclass AutosizeColumn extends BasePlugin {\r\n /**\r\n * Autosize col based on column data\r\n * @param {HTMLTableCellElement} th\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Number} min\r\n * @param {Number} max\r\n * @returns {Number}\r\n */\r\n computeSize(th, column, min, max) {\r\n const grid = this.grid;\r\n if (hasAttribute(th, \"width\")) {\r\n return getAttribute(th, \"width\");\r\n }\r\n if (!grid.data.length) {\r\n return;\r\n }\r\n const firstVal = grid.data[0];\r\n const lastVal = grid.data[grid.data.length - 1];\r\n let v = firstVal[column.field] ? firstVal[column.field].toString() : \"\";\r\n let v2 = lastVal[column.field] ? lastVal[column.field].toString() : \"\";\r\n if (v2.length > v.length) {\r\n v = v2;\r\n }\r\n let width = 0;\r\n if (v.length <= 6) {\r\n width = min;\r\n } else if (v.length > 50) {\r\n width = max;\r\n } else {\r\n // Add some extra room to have some spare space\r\n width = getTextWidth(v + \"0000\", th);\r\n }\r\n if (width > max) {\r\n width = max;\r\n }\r\n if (width < min) {\r\n width = min;\r\n }\r\n setAttribute(th, \"width\", width);\r\n return width;\r\n }\r\n}\r\n\r\nexport default AutosizeColumn;\r\n", "/**\r\n * Define a function that can be happily passed to addEventListener\r\n * @typedef {Function & EventListenerOrEventListenerObject} ExtendedFunction\r\n */\r\n\r\n/**\r\n * @param {Function} handler\r\n * @param {Number} timeout\r\n * @returns {ExtendedFunction}\r\n */\r\nexport default function debounce(handler, timeout = 300) {\r\n let timer = null;\r\n return (...args) => {\r\n clearTimeout(timer);\r\n timer = setTimeout(() => {\r\n timer = null;\r\n handler(...args);\r\n }, timeout);\r\n };\r\n}\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport debounce from \"../utils/debounce.js\";\r\nimport { addClass, ce, find, findAll, hasClass, insertAfter, removeAttribute, removeClass, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\nconst RESPONSIVE_CLASS = \"dg-responsive\";\r\n\r\nlet obsTo;\r\n\r\n/**\r\n * @param {Array} list\r\n * @returns {Array}\r\n */\r\nfunction sortByPriority(list) {\r\n return list.sort((a, b) => {\r\n const v1 = parseInt(a.dataset.responsive) || 1;\r\n const v2 = parseInt(b.dataset.responsive) || 1;\r\n return v2 - v1;\r\n });\r\n}\r\n\r\n/**\r\n * @type {ResizeObserverCallback}\r\n */\r\n//@ts-ignore\r\nconst callback = debounce((entries) => {\r\n for (const entry of entries) {\r\n /**\r\n * @type {import(\"../data-grid\").default}\r\n */\r\n // @ts-ignore\r\n const grid = entry.target;\r\n const table = grid.table;\r\n if (grid.plugins.ResponsiveGrid.observerBlocked) {\r\n return;\r\n }\r\n // check inlineSize (width) and not blockSize (height)\r\n const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;\r\n const size = parseInt(contentBoxSize.inlineSize);\r\n const tableWidth = table.offsetWidth;\r\n const realTableWidth = findAll(grid.headerRow, \"th\").reduce((result, th) => {\r\n return result + th.offsetWidth;\r\n }, 0);\r\n const diff = (realTableWidth || tableWidth) - size - 1;\r\n const minWidth = 50;\r\n const prevAction = grid.plugins.ResponsiveGrid.prevAction;\r\n // We have an array with the columns to show/hide are in order, most important first\r\n const headerCols = sortByPriority(\r\n findAll(grid.headerRow, \"th[field]\")\r\n .reverse() // Order takes precedence if no priority is set\r\n .filter((col) => {\r\n // Leave out unresponsive columns\r\n return col.dataset.responsive !== \"0\";\r\n })\r\n );\r\n let changed = false;\r\n\r\n grid.log(`table is ${tableWidth}/${realTableWidth} and available size is ${size}. Diff: ${diff}`);\r\n\r\n // The table is too big when diff has a high value, otherwise it will be like -1 or -2\r\n if (diff > 0) {\r\n if (prevAction === \"show\") {\r\n return;\r\n }\r\n grid.plugins.ResponsiveGrid.prevAction = \"hide\";\r\n let remaining = diff;\r\n let cols = headerCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\") && col.hasAttribute(\"data-responsive\");\r\n });\r\n if (cols.length === 0) {\r\n cols = headerCols.filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n });\r\n // Always keep one column\r\n if (cols.length === 1) {\r\n return;\r\n }\r\n }\r\n cols.forEach((col) => {\r\n if (remaining < 0) {\r\n return;\r\n }\r\n\r\n const colWidth = col.offsetWidth;\r\n const field = col.getAttribute(\"field\");\r\n if (!field) {\r\n return;\r\n }\r\n col.dataset.baseWidth = \"\" + col.offsetWidth;\r\n\r\n grid.hideColumn(field, false);\r\n grid.setColProp(field, \"responsiveHidden\", true);\r\n changed = true;\r\n\r\n remaining -= colWidth;\r\n remaining = Math.round(remaining);\r\n });\r\n } else {\r\n if (prevAction === \"hide\") {\r\n return;\r\n }\r\n grid.plugins.ResponsiveGrid.prevAction = \"show\";\r\n\r\n const requiredWidth =\r\n headerCols\r\n .filter((col) => {\r\n return !col.hasAttribute(\"hidden\");\r\n })\r\n .reduce((result, col) => {\r\n const width = col.dataset.minWidth ? parseInt(col.dataset.minWidth) : col.offsetWidth;\r\n return result + width;\r\n }, 0) + minWidth; // Add an offset so that inserting column is smoother\r\n\r\n // Compute available width to insert columns\r\n let remaining = size - requiredWidth;\r\n // Do we have any hidden column that we can restore ?\r\n headerCols\r\n .slice()\r\n .reverse() // Reverse the array to restore the columns in the proper order\r\n .filter((col) => {\r\n return col.hasAttribute(\"hidden\");\r\n })\r\n .forEach((col) => {\r\n if (remaining < minWidth) {\r\n return;\r\n }\r\n const colWidth = parseInt(col.dataset.minWidth);\r\n\r\n // We need to have enough space to restore it\r\n if (colWidth > remaining) {\r\n remaining = -1; // break loop to keep restoring in order\r\n return;\r\n }\r\n\r\n const field = col.getAttribute(\"field\");\r\n if (!field) {\r\n return;\r\n }\r\n\r\n grid.showColumn(field, false);\r\n grid.setColProp(field, \"responsiveHidden\", false);\r\n changed = true;\r\n\r\n remaining -= colWidth;\r\n remaining = Math.round(remaining);\r\n });\r\n }\r\n\r\n // Check footer\r\n const footer = find(grid.table, \"tfoot\");\r\n const realFooterWidth = findAll(grid.table, \".dg-footer > div\").reduce((result, div) => {\r\n return result + div.offsetWidth;\r\n }, 0);\r\n const availableFooterWidth = footer.offsetWidth - realFooterWidth;\r\n if (realFooterWidth > size) {\r\n addClass(footer, \"dg-footer-compact\");\r\n } else if (availableFooterWidth > 250) {\r\n removeClass(footer, \"dg-footer-compact\");\r\n }\r\n if (changed) {\r\n grid.renderTable();\r\n }\r\n // Prevent resize loop\r\n setTimeout(() => {\r\n grid.plugins.ResponsiveGrid.prevAction = null;\r\n }, 1000);\r\n grid.table.style.visibility = \"visible\";\r\n }\r\n}, 100);\r\nconst resizeObserver = new ResizeObserver(callback);\r\n\r\n/**\r\n * Responsive data grid\r\n */\r\nclass ResponsiveGrid extends BasePlugin {\r\n constructor(grid) {\r\n super(grid);\r\n\r\n this.observerBlocked = false;\r\n this.prevAction = null;\r\n }\r\n\r\n connected() {\r\n if (this.grid.options.responsive) {\r\n this.observe();\r\n }\r\n }\r\n\r\n disconnected() {\r\n this.unobserve();\r\n }\r\n\r\n observe() {\r\n if (!this.grid.options.responsive) {\r\n return;\r\n }\r\n resizeObserver.observe(this.grid);\r\n this.grid.style.display = \"block\"; // Otherwise resize doesn't happen\r\n this.grid.style.overflowX = \"hidden\"; // Prevent scrollbars from appearing\r\n }\r\n\r\n unobserve() {\r\n resizeObserver.unobserve(this.grid);\r\n this.grid.style.display = \"unset\";\r\n this.grid.style.overflowX = \"unset\";\r\n }\r\n\r\n blockObserver() {\r\n this.observerBlocked = true;\r\n if (obsTo) {\r\n clearTimeout(obsTo);\r\n }\r\n }\r\n\r\n unblockObserver() {\r\n obsTo = setTimeout(() => {\r\n this.observerBlocked = false;\r\n }, 200); // more than debounce\r\n }\r\n\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasHiddenColumns() {\r\n let flag = false;\r\n this.grid.options.columns.forEach((col) => {\r\n if (col.responsiveHidden) {\r\n flag = true;\r\n }\r\n });\r\n return flag;\r\n }\r\n\r\n colIndex() {\r\n return this.grid.startColIndex() - 1;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createHeaderCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n let th = ce(\"th\", tr);\r\n setAttribute(th, \"scope\", \"col\");\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n setAttribute(th, \"width\", \"40\");\r\n th.classList.add(...[`${RESPONSIVE_CLASS}-toggle`, \"dg-not-resizable\", \"dg-not-sortable\"]);\r\n th.tabIndex = 0;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createFilterCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n let th = ce(\"th\", tr);\r\n setAttribute(th, \"role\", \"columnheader button\");\r\n setAttribute(th, \"aria-colindex\", this.colIndex());\r\n th.classList.add(`${RESPONSIVE_CLASS}-toggle`);\r\n th.tabIndex = 0;\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n createDataCol(tr) {\r\n if (!this.grid.options.responsiveToggle) {\r\n return;\r\n }\r\n // Create col\r\n let td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell button\");\r\n setAttribute(td, \"aria-colindex\", this.colIndex());\r\n td.classList.add(`${RESPONSIVE_CLASS}-toggle`);\r\n\r\n // Create icon\r\n td.innerHTML = `
\r\n \r\n \r\n\r\n\r\n \r\n
`;\r\n tr.appendChild(td);\r\n\r\n td.addEventListener(\"click\", this);\r\n td.addEventListener(\"mousedown\", this);\r\n }\r\n\r\n computeLabelWidth() {\r\n let idealWidth = 0;\r\n let consideredCol = 0;\r\n while (idealWidth < 120) {\r\n consideredCol++;\r\n const hCol = find(this.grid, `.dg-head-columns th[aria-colindex=\"${consideredCol}\"]`);\r\n if (hCol) {\r\n idealWidth += hCol.offsetWidth;\r\n } else {\r\n break;\r\n }\r\n }\r\n return idealWidth;\r\n }\r\n\r\n /**\r\n * @param {Event} ev\r\n */\r\n onmousedown(ev) {\r\n // Avoid selection through double click\r\n ev.preventDefault();\r\n }\r\n\r\n /**\r\n * @param {Event} ev\r\n */\r\n onclick(ev) {\r\n // Prevent expandable\r\n ev.stopPropagation();\r\n\r\n // target is the element that triggered the event (e.g., the user clicked on)\r\n // currentTarget is the element that the event listener is attached to.\r\n\r\n /**\r\n * @type {HTMLTableRowElement}\r\n */\r\n //@ts-ignore\r\n const td = ev.currentTarget;\r\n const tr = td.parentElement;\r\n const open = find(td, `.${RESPONSIVE_CLASS}-open`);\r\n const close = find(td, `.${RESPONSIVE_CLASS}-close`);\r\n\r\n this.blockObserver();\r\n\r\n const isExpanded = hasClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n if (isExpanded) {\r\n removeClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n open.style.display = \"unset\";\r\n close.style.display = \"none\";\r\n\r\n // Move back rows and cleanup row\r\n const childRow = tr.nextElementSibling;\r\n const hiddenCols = findAll(childRow, `.${RESPONSIVE_CLASS}-hidden`);\r\n hiddenCols.forEach((col) => {\r\n // We don't really need to care where we insert them since we are going to redraw anyway\r\n tr.appendChild(col);\r\n setAttribute(col, \"hidden\");\r\n });\r\n\r\n childRow.parentElement.removeChild(childRow);\r\n } else {\r\n addClass(tr, `${RESPONSIVE_CLASS}-expanded`);\r\n open.style.display = \"none\";\r\n close.style.display = \"unset\";\r\n\r\n // Create a child row and move rows into it\r\n const childRow = ce(\"tr\");\r\n insertAfter(childRow, tr);\r\n addClass(childRow, `${RESPONSIVE_CLASS}-child-row`);\r\n\r\n const childRowTd = ce(\"td\", childRow);\r\n setAttribute(childRowTd, \"colspan\", this.grid.columnsLength(true));\r\n\r\n const childTable = ce(\"table\", childRowTd);\r\n addClass(childTable, `${RESPONSIVE_CLASS}-table`);\r\n\r\n const hiddenCols = findAll(tr, `.${RESPONSIVE_CLASS}-hidden`);\r\n const idealWidth = this.computeLabelWidth();\r\n hiddenCols.forEach((col) => {\r\n const childTableRow = ce(\"tr\", childTable);\r\n\r\n // Add label\r\n const label = col.dataset.name;\r\n const labelCol = ce(\"th\", childTableRow);\r\n // It looks much better when aligned with an actual col\r\n labelCol.style.width = `${idealWidth}px`;\r\n labelCol.innerHTML = label;\r\n\r\n // Add actual row\r\n childTableRow.appendChild(col);\r\n removeAttribute(col, \"hidden\");\r\n });\r\n }\r\n\r\n this.unblockObserver();\r\n }\r\n}\r\n\r\nexport default ResponsiveGrid;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport interpolate from \"../utils/interpolate.js\";\r\nimport { dispatch, on, setAttribute } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Add action on rows\r\n */\r\nclass RowActions extends BasePlugin {\r\n /**\r\n * @returns {Boolean}\r\n */\r\n hasActions() {\r\n return this.grid.options.actions.length > 0;\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionHeader(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n setAttribute(actionsTh, \"role\", \"columnheader button\");\r\n setAttribute(actionsTh, \"aria-colindex\", this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", \"dg-not-sortable\", \"dg-not-resizable\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n *\r\n * @param {HTMLTableRowElement} tr\r\n */\r\n makeActionFilter(tr) {\r\n let actionsTh = document.createElement(\"th\");\r\n actionsTh.setAttribute(\"role\", \"columnheader button\");\r\n actionsTh.setAttribute(\"aria-colindex\", \"\" + this.grid.columnsLength(true));\r\n actionsTh.classList.add(...[\"dg-actions\", this.actionClass]);\r\n actionsTh.tabIndex = 0;\r\n tr.appendChild(actionsTh);\r\n }\r\n\r\n /**\r\n * @param {HTMLTableRowElement} tr\r\n * @param {Object} item\r\n */\r\n makeActionRow(tr, item) {\r\n const labels = this.grid.labels;\r\n const td = document.createElement(\"td\");\r\n setAttribute(td, \"role\", \"gridcell\");\r\n setAttribute(td, \"aria-colindex\", this.grid.columnsLength(true));\r\n td.classList.add(...[\"dg-actions\", this.actionClass]);\r\n td.tabIndex = 0;\r\n\r\n // Add menu toggle\r\n let actionsToggle = document.createElement(\"button\");\r\n actionsToggle.classList.add(\"dg-actions-toggle\");\r\n actionsToggle.innerHTML = \"\u2630\";\r\n td.appendChild(actionsToggle);\r\n on(actionsToggle, \"click\", (ev) => {\r\n ev.stopPropagation();\r\n ev.target.parentElement.classList.toggle(\"dg-actions-expand\");\r\n });\r\n\r\n this.grid.options.actions.forEach((action) => {\r\n let button = document.createElement(\"button\");\r\n if (action.html) {\r\n button.innerHTML = action.html;\r\n } else {\r\n button.innerText = action.title ?? action.name;\r\n }\r\n if (action.title) {\r\n button.title = action.title;\r\n }\r\n if (action.url) {\r\n button.type = \"submit\";\r\n button.formAction = interpolate(action.url, item);\r\n }\r\n if (action.class) {\r\n button.classList.add(...action.class.split(\" \"));\r\n }\r\n const actionHandler = (ev) => {\r\n ev.stopPropagation();\r\n if (action.confirm) {\r\n let c = confirm(labels.areYouSure);\r\n if (!c) {\r\n ev.preventDefault();\r\n return;\r\n }\r\n }\r\n dispatch(this.grid, \"action\", {\r\n data: item,\r\n action: action.name,\r\n });\r\n };\r\n button.addEventListener(\"click\", actionHandler);\r\n td.appendChild(button);\r\n\r\n // Row action\r\n if (action.default) {\r\n tr.classList.add(\"dg-actionable\");\r\n tr.addEventListener(\"click\", actionHandler);\r\n }\r\n });\r\n\r\n tr.appendChild(td);\r\n }\r\n\r\n get actionClass() {\r\n if (this.grid.options.actions.length < 3 && !this.grid.options.collapseActions) {\r\n return \"dg-actions-\" + this.grid.options.actions.length;\r\n }\r\n return \"dg-actions-more\";\r\n }\r\n}\r\n\r\nexport default RowActions;\r\n", "import BasePlugin from \"../core/base-plugin.js\";\r\nimport { dispatch } from \"../utils/shortcuts.js\";\r\n\r\n/**\r\n * Make editable inputs in rows\r\n */\r\nclass EditableColumn extends BasePlugin {\r\n /**\r\n *\r\n * @param {HTMLTableCellElement} td\r\n * @param {import(\"../data-grid\").Column} column\r\n * @param {Object} item\r\n * @param {number} i\r\n */\r\n makeEditableInput(td, column, item, i) {\r\n const gridId = this.grid.getAttribute(\"id\");\r\n let input = document.createElement(\"input\");\r\n input.type = \"text\";\r\n input.autocomplete = \"off\";\r\n input.spellcheck = false;\r\n input.tabIndex = 0;\r\n input.classList.add(\"dg-editable\");\r\n input.name = gridId.replace(\"-\", \"_\") + \"[\" + (i + 1) + \"]\" + \"[\" + column.field + \"]\";\r\n input.value = item[column.field];\r\n input.dataset.field = column.field;\r\n\r\n // Prevent row action\r\n input.addEventListener(\"click\", (ev) => ev.stopPropagation());\r\n // Enter validates edit\r\n input.addEventListener(\"keypress\", (ev) => {\r\n if (ev.type === \"keypress\") {\r\n const key = ev.keyCode || ev.key;\r\n if (key === 13 || key === \"Enter\") {\r\n input.blur();\r\n ev.preventDefault();\r\n }\r\n }\r\n });\r\n // Save on blur\r\n input.addEventListener(\"blur\", () => {\r\n // Only fire on update\r\n if (input.value == item[input.dataset.field]) {\r\n return;\r\n }\r\n // Update underlying data\r\n item[input.dataset.field] = input.value;\r\n // Notify\r\n dispatch(this.grid, \"edit\", {\r\n data: item,\r\n value: input.value,\r\n });\r\n });\r\n td.appendChild(input);\r\n }\r\n}\r\n\r\nexport default EditableColumn;\r\n", "import DataGrid from \"./src/data-grid.js\";\r\n// Optional plugins\r\nimport ColumnResizer from \"./src/plugins/column-resizer.js\";\r\nimport ContextMenu from \"./src/plugins/context-menu.js\";\r\nimport DraggableHeaders from \"./src/plugins/draggable-headers.js\";\r\nimport TouchSupport from \"./src/plugins/touch-support.js\";\r\nimport SelectableRows from \"./src/plugins/selectable-rows.js\";\r\nimport FixedHeight from \"./src/plugins/fixed-height.js\";\r\nimport AutosizeColumn from \"./src/plugins/autosize-column.js\";\r\nimport ResponsiveGrid from \"./src/plugins/responsive-grid.js\";\r\nimport RowActions from \"./src/plugins/row-actions.js\";\r\nimport EditableColumn from \"./src/plugins/editable-column.js\";\r\n\r\n// Using shorthand property names\r\n// This make them reserved and keys will be preserved\r\n// Actual class names are renamed\r\nDataGrid.registerPlugins({\r\n ColumnResizer,\r\n ContextMenu,\r\n DraggableHeaders,\r\n TouchSupport,\r\n SelectableRows,\r\n FixedHeight,\r\n AutosizeColumn,\r\n ResponsiveGrid,\r\n RowActions,\r\n EditableColumn,\r\n});\r\n\r\ncustomElements.define(\"data-grid\", DataGrid);\r\n\r\nexport default DataGrid;\r\n"], "mappings": "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", "names": ["camelize", "str", "m", "chr", "normalizeData", "v", "supportedPassiveTypes", "passiveOpts", "type", "getAttribute", "el", "name", "hasAttribute", "setAttribute", "v", "check", "removeAttribute", "on", "listener", "off", "dispatch", "el", "name", "data", "bubbles", "opts", "hasClass", "addClass", "removeClass", "toggleClass", "$", "selector", "base", "$$", "find", "findAll", "ce", "tagName", "parent", "el", "insertAfter", "newNode", "existingNode", "BaseElement", "options", "opt", "v", "setAttribute", "data", "key", "normalizeData", "message", "getAttribute", "event", "template", "dispatch", "attributeName", "oldValue", "newValue", "isOption", "transformer", "camelize", "base_element_default", "addSelectOption", "el", "value", "label", "checked", "opt", "appendParamsToUrl", "url", "params", "key", "k", "convertArray", "v", "elementOffset", "el", "rect", "scrollLeft", "scrollTop", "interpolate", "str", "data", "$1", "$2", "getTextWidth", "text", "el", "withPadding", "styles", "fontWeight", "fontSize", "fontFamily", "padding", "paddingLeft", "paddingRight", "context", "metrics", "randstr", "prefix", "plugins", "labels", "applyColumnDefinition", "el", "column", "setAttribute", "addClass", "DataGrid", "base_element_default", "randstr", "pluginName", "pluginClass", "attr", "camelize", "v", "list", "plugin", "columns", "cols", "key", "col", "item", "convertArray", "val", "updatePage", "addSelectOption", "field", "found", "prop", "c", "render", "dispatch", "start", "visibleOnly", "len", "tr", "find", "row", "removeAttribute", "findAll", "th", "fieldName", "value", "cb", "needRender", "resolve", "response", "err", "event", "filters", "input", "name", "haveClasses", "sort", "stack", "itemA", "itemB", "a", "b", "valA", "valB", "reject", "base", "url", "params", "appendParamsToUrl", "sortedColumn", "thead", "tfoot", "td", "availableWidth", "colMaxWidth", "idx", "sampleTh", "totalWidth", "colIdx", "computedWidth", "getTextWidth", "w", "colAvailableWidth", "visibleCols", "lastCol", "scrollbarWidth", "diff", "hasClass", "actualWidth", "minWidth", "newWidth", "sortableRow", "relatedTh", "e", "tbody", "i", "on", "ev", "toggleClass", "tv", "interpolate", "prev", "total", "p", "index", "high", "low", "getAttribute", "data_grid_default", "BasePlugin", "grid", "event", "base_plugin_default", "ColumnResizer", "base_plugin_default", "grid", "resizeLabel", "table", "cols", "findAll", "col", "hasClass", "resizer", "addClass", "startX", "startW", "remainingSpace", "max", "mouseMoveHandler", "e", "newWidth", "setAttribute", "mouseUpHandler", "removeClass", "off", "dispatch", "getAttribute", "on", "target", "visibleCols", "columnIndex", "column", "removeAttribute", "elementOffset", "j", "column_resizer_default", "getParentElement", "el", "type", "prop", "parent", "ContextMenu", "base_plugin_default", "off", "grid", "on", "e", "t", "field", "target", "getParentElement", "menu", "rect", "x", "y", "removeAttribute", "documentClickHandler", "setAttribute", "col", "li", "label", "checkbox", "text", "context_menu_default", "DraggableHeaders", "base_plugin_default", "th", "grid", "on", "e", "t", "target", "getParentElement", "index", "targetIndex", "offset", "tmp", "swapNodes", "selector", "el1", "rowIndex", "el2", "setAttribute", "newNode", "findAll", "c", "getAttribute", "dispatch", "draggable_headers_default", "TouchSupport", "base_plugin_default", "grid", "e", "xDiff", "yDiff", "touch_support_default", "SELECTABLE_CLASS", "SELECT_ALL_CLASS", "CHECKBOX_CLASS", "SelectableRows", "base_plugin_default", "key", "grid", "selectedData", "findAll", "checkbox", "idx", "item", "tbody", "input", "tr", "th", "setAttribute", "label", "td", "selectOne", "e", "hasClass", "visibleOnly", "cb", "dispatch", "totalCheckboxes", "totalChecked", "n", "selectable_rows_default", "FixedHeight", "base_plugin_default", "grid", "tbody", "tr", "setAttribute", "fakeRow", "max", "visibleRows", "fakeHeight", "fixed_height_default", "AutosizeColumn", "base_plugin_default", "th", "column", "min", "max", "grid", "hasAttribute", "getAttribute", "firstVal", "lastVal", "v", "v2", "width", "getTextWidth", "setAttribute", "autosize_column_default", "debounce", "handler", "timeout", "timer", "args", "RESPONSIVE_CLASS", "obsTo", "sortByPriority", "list", "a", "b", "v1", "callback", "debounce", "entries", "entry", "grid", "table", "contentBoxSize", "size", "tableWidth", "realTableWidth", "findAll", "result", "th", "diff", "minWidth", "prevAction", "headerCols", "col", "changed", "remaining", "cols", "colWidth", "field", "requiredWidth", "width", "footer", "find", "realFooterWidth", "div", "availableFooterWidth", "addClass", "removeClass", "resizeObserver", "ResponsiveGrid", "base_plugin_default", "flag", "tr", "ce", "setAttribute", "td", "idealWidth", "consideredCol", "hCol", "ev", "open", "close", "hasClass", "childRow", "insertAfter", "childRowTd", "childTable", "hiddenCols", "childTableRow", "label", "labelCol", "removeAttribute", "responsive_grid_default", "RowActions", "base_plugin_default", "tr", "actionsTh", "setAttribute", "item", "labels", "td", "actionsToggle", "on", "ev", "action", "button", "interpolate", "actionHandler", "dispatch", "row_actions_default", "EditableColumn", "base_plugin_default", "td", "column", "item", "i", "gridId", "input", "ev", "key", "dispatch", "editable_column_default", "data_grid_default", "column_resizer_default", "context_menu_default", "draggable_headers_default", "touch_support_default", "selectable_rows_default", "fixed_height_default", "autosize_column_default", "responsive_grid_default", "row_actions_default", "editable_column_default"] } diff --git a/package-lock.json b/package-lock.json index ca0e9a6..64a2901 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", + "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -37,9 +37,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", - "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", + "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", "cpu": [ "arm" ], @@ -53,9 +53,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", - "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", + "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", "cpu": [ "arm64" ], @@ -69,9 +69,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", - "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", + "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", "cpu": [ "x64" ], @@ -85,9 +85,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", - "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", + "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", "cpu": [ "arm64" ], @@ -101,9 +101,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", - "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", + "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", "cpu": [ "x64" ], @@ -117,9 +117,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", - "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", + "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", "cpu": [ "arm64" ], @@ -133,9 +133,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", - "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", + "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", "cpu": [ "x64" ], @@ -149,9 +149,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", - "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", + "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", "cpu": [ "arm" ], @@ -165,9 +165,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", - "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", + "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", "cpu": [ "arm64" ], @@ -181,9 +181,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", - "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", + "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", "cpu": [ "ia32" ], @@ -197,9 +197,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", - "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", + "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", "cpu": [ "loong64" ], @@ -213,9 +213,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", - "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", + "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", "cpu": [ "mips64el" ], @@ -229,9 +229,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", - "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", + "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", "cpu": [ "ppc64" ], @@ -245,9 +245,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", - "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", + "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", "cpu": [ "riscv64" ], @@ -261,9 +261,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", - "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", + "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", "cpu": [ "s390x" ], @@ -277,9 +277,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", - "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", + "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", "cpu": [ "x64" ], @@ -293,9 +293,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", - "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", + "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", "cpu": [ "x64" ], @@ -309,9 +309,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", - "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", + "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", "cpu": [ "x64" ], @@ -325,9 +325,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", - "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", + "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", "cpu": [ "x64" ], @@ -341,9 +341,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", - "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", + "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", "cpu": [ "arm64" ], @@ -357,9 +357,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", - "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", + "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", "cpu": [ "ia32" ], @@ -373,9 +373,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", - "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", + "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", "cpu": [ "x64" ], @@ -389,12 +389,12 @@ } }, "node_modules/@happy-dom/global-registrator": { - "version": "9.8.4", - "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-9.8.4.tgz", - "integrity": "sha512-jBKbrVPohIraO0TEy+96sFj/y/1XXaOFPYVlUD09+h0UfF0WXLHGGFjvpy8+tBW4H1aSQviHLScT/p+6BdPi5g==", + "version": "9.10.9", + "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-9.10.9.tgz", + "integrity": "sha512-Bu17IVFpxSmBp5bRlm0/MNukXhiNDtktD+RKGJYFYx2LZz5is2+INlRynsdylSxYiKUXJ+gOorQL85XQ9JQBoQ==", "dev": true, "dependencies": { - "happy-dom": "^9.8.4" + "happy-dom": "^9.10.9" } }, "node_modules/@jsdoc/salty": { @@ -811,9 +811,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001480", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", - "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==", + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==", "funding": [ { "type": "opencollective", @@ -1357,9 +1357,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.368", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.368.tgz", - "integrity": "sha512-e2aeCAixCj9M7nJxdB/wDjO6mbYX+lJJxSJCXDzlr5YPGYVofuJwGN9nKg2o6wWInjX6XmxRinn3AeJMK81ltw==" + "version": "1.4.390", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.390.tgz", + "integrity": "sha512-9h6KDGTynRfpM16U40uLSCxRO3diIKcXXI0mPChKls7sfkxOlCH1sgSJ14Rb00BFomQNHY/p67gaZSu5Mu8j6w==" }, "node_modules/emittery": { "version": "1.0.1", @@ -1389,9 +1389,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", - "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", + "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", "dev": true, "hasInstallScript": true, "bin": { @@ -1401,28 +1401,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.17", - "@esbuild/android-arm64": "0.17.17", - "@esbuild/android-x64": "0.17.17", - "@esbuild/darwin-arm64": "0.17.17", - "@esbuild/darwin-x64": "0.17.17", - "@esbuild/freebsd-arm64": "0.17.17", - "@esbuild/freebsd-x64": "0.17.17", - "@esbuild/linux-arm": "0.17.17", - "@esbuild/linux-arm64": "0.17.17", - "@esbuild/linux-ia32": "0.17.17", - "@esbuild/linux-loong64": "0.17.17", - "@esbuild/linux-mips64el": "0.17.17", - "@esbuild/linux-ppc64": "0.17.17", - "@esbuild/linux-riscv64": "0.17.17", - "@esbuild/linux-s390x": "0.17.17", - "@esbuild/linux-x64": "0.17.17", - "@esbuild/netbsd-x64": "0.17.17", - "@esbuild/openbsd-x64": "0.17.17", - "@esbuild/sunos-x64": "0.17.17", - "@esbuild/win32-arm64": "0.17.17", - "@esbuild/win32-ia32": "0.17.17", - "@esbuild/win32-x64": "0.17.17" + "@esbuild/android-arm": "0.17.18", + "@esbuild/android-arm64": "0.17.18", + "@esbuild/android-x64": "0.17.18", + "@esbuild/darwin-arm64": "0.17.18", + "@esbuild/darwin-x64": "0.17.18", + "@esbuild/freebsd-arm64": "0.17.18", + "@esbuild/freebsd-x64": "0.17.18", + "@esbuild/linux-arm": "0.17.18", + "@esbuild/linux-arm64": "0.17.18", + "@esbuild/linux-ia32": "0.17.18", + "@esbuild/linux-loong64": "0.17.18", + "@esbuild/linux-mips64el": "0.17.18", + "@esbuild/linux-ppc64": "0.17.18", + "@esbuild/linux-riscv64": "0.17.18", + "@esbuild/linux-s390x": "0.17.18", + "@esbuild/linux-x64": "0.17.18", + "@esbuild/netbsd-x64": "0.17.18", + "@esbuild/openbsd-x64": "0.17.18", + "@esbuild/sunos-x64": "0.17.18", + "@esbuild/win32-arm64": "0.17.18", + "@esbuild/win32-ia32": "0.17.18", + "@esbuild/win32-x64": "0.17.18" } }, "node_modules/escalade": { @@ -1741,9 +1741,9 @@ } }, "node_modules/happy-dom": { - "version": "9.8.4", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-9.8.4.tgz", - "integrity": "sha512-IB2glIailsAloOmTfRRQfpA3aW/bbhpdw9wX1CKvDrmj8tMVtdabjM+579YLdHpBXVyOku+p07+aea7TdnGnyw==", + "version": "9.10.9", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-9.10.9.tgz", + "integrity": "sha512-3RnOyu6buPMpDAyOpp8yfR5Xi/k2p5MhrDwlG/dgpVHkptFN5IqubdbGOQU5luB7ANh6a08GOuiB+Bo9JCzCBw==", "dev": true, "dependencies": { "css.escape": "^1.5.1", @@ -2687,9 +2687,9 @@ } }, "node_modules/postcss-cli/node_modules/slash": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.0.0.tgz", - "integrity": "sha512-n6KkmvKS0623igEVj3FF0OZs1gYYJ0o0Hj939yc1fyxl2xt+xYpLnzJB6xBSqOfV9ZFLEWodBBN/heZJahuIJQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "engines": { "node": ">=14.16" }, @@ -2993,9 +2993,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.62.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz", - "integrity": "sha512-Q4USplo4pLYgCi+XlipZCWUQz5pkg/ruSSgJ0WRDSb/+3z9tXUOkQ7QPYn4XrhZKYAK4HlpaQecRwKLJX6+DBg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz", + "integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -3039,10 +3039,16 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/slash": { "version": "3.0.0", @@ -3567,13 +3573,13 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz", - "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -3600,17 +3606,17 @@ "dev": true }, "node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", "engines": { "node": ">= 14" } }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -3692,172 +3698,172 @@ }, "dependencies": { "@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", + "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true }, "@esbuild/android-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", - "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", + "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", - "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", + "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", - "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", + "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", - "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", + "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", - "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", + "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", - "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", + "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", - "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", + "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", - "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", + "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", - "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", + "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", - "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", + "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", - "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", + "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", - "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", + "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", - "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", + "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", - "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", + "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", - "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", + "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", - "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", + "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", - "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", + "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", - "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", + "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", - "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", + "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", - "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", + "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", - "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", + "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", - "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", + "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", "dev": true, "optional": true }, "@happy-dom/global-registrator": { - "version": "9.8.4", - "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-9.8.4.tgz", - "integrity": "sha512-jBKbrVPohIraO0TEy+96sFj/y/1XXaOFPYVlUD09+h0UfF0WXLHGGFjvpy8+tBW4H1aSQviHLScT/p+6BdPi5g==", + "version": "9.10.9", + "resolved": "https://registry.npmjs.org/@happy-dom/global-registrator/-/global-registrator-9.10.9.tgz", + "integrity": "sha512-Bu17IVFpxSmBp5bRlm0/MNukXhiNDtktD+RKGJYFYx2LZz5is2+INlRynsdylSxYiKUXJ+gOorQL85XQ9JQBoQ==", "dev": true, "requires": { - "happy-dom": "^9.8.4" + "happy-dom": "^9.10.9" } }, "@jsdoc/salty": { @@ -4148,9 +4154,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001480", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", - "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==" + "version": "1.0.30001486", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz", + "integrity": "sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg==" }, "catharsis": { "version": "0.9.0", @@ -4552,9 +4558,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.368", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.368.tgz", - "integrity": "sha512-e2aeCAixCj9M7nJxdB/wDjO6mbYX+lJJxSJCXDzlr5YPGYVofuJwGN9nKg2o6wWInjX6XmxRinn3AeJMK81ltw==" + "version": "1.4.390", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.390.tgz", + "integrity": "sha512-9h6KDGTynRfpM16U40uLSCxRO3diIKcXXI0mPChKls7sfkxOlCH1sgSJ14Rb00BFomQNHY/p67gaZSu5Mu8j6w==" }, "emittery": { "version": "1.0.1", @@ -4575,33 +4581,33 @@ "dev": true }, "esbuild": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", - "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", + "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", "dev": true, "requires": { - "@esbuild/android-arm": "0.17.17", - "@esbuild/android-arm64": "0.17.17", - "@esbuild/android-x64": "0.17.17", - "@esbuild/darwin-arm64": "0.17.17", - "@esbuild/darwin-x64": "0.17.17", - "@esbuild/freebsd-arm64": "0.17.17", - "@esbuild/freebsd-x64": "0.17.17", - "@esbuild/linux-arm": "0.17.17", - "@esbuild/linux-arm64": "0.17.17", - "@esbuild/linux-ia32": "0.17.17", - "@esbuild/linux-loong64": "0.17.17", - "@esbuild/linux-mips64el": "0.17.17", - "@esbuild/linux-ppc64": "0.17.17", - "@esbuild/linux-riscv64": "0.17.17", - "@esbuild/linux-s390x": "0.17.17", - "@esbuild/linux-x64": "0.17.17", - "@esbuild/netbsd-x64": "0.17.17", - "@esbuild/openbsd-x64": "0.17.17", - "@esbuild/sunos-x64": "0.17.17", - "@esbuild/win32-arm64": "0.17.17", - "@esbuild/win32-ia32": "0.17.17", - "@esbuild/win32-x64": "0.17.17" + "@esbuild/android-arm": "0.17.18", + "@esbuild/android-arm64": "0.17.18", + "@esbuild/android-x64": "0.17.18", + "@esbuild/darwin-arm64": "0.17.18", + "@esbuild/darwin-x64": "0.17.18", + "@esbuild/freebsd-arm64": "0.17.18", + "@esbuild/freebsd-x64": "0.17.18", + "@esbuild/linux-arm": "0.17.18", + "@esbuild/linux-arm64": "0.17.18", + "@esbuild/linux-ia32": "0.17.18", + "@esbuild/linux-loong64": "0.17.18", + "@esbuild/linux-mips64el": "0.17.18", + "@esbuild/linux-ppc64": "0.17.18", + "@esbuild/linux-riscv64": "0.17.18", + "@esbuild/linux-s390x": "0.17.18", + "@esbuild/linux-x64": "0.17.18", + "@esbuild/netbsd-x64": "0.17.18", + "@esbuild/openbsd-x64": "0.17.18", + "@esbuild/sunos-x64": "0.17.18", + "@esbuild/win32-arm64": "0.17.18", + "@esbuild/win32-ia32": "0.17.18", + "@esbuild/win32-x64": "0.17.18" } }, "escalade": { @@ -4819,9 +4825,9 @@ } }, "happy-dom": { - "version": "9.8.4", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-9.8.4.tgz", - "integrity": "sha512-IB2glIailsAloOmTfRRQfpA3aW/bbhpdw9wX1CKvDrmj8tMVtdabjM+579YLdHpBXVyOku+p07+aea7TdnGnyw==", + "version": "9.10.9", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-9.10.9.tgz", + "integrity": "sha512-3RnOyu6buPMpDAyOpp8yfR5Xi/k2p5MhrDwlG/dgpVHkptFN5IqubdbGOQU5luB7ANh6a08GOuiB+Bo9JCzCBw==", "dev": true, "requires": { "css.escape": "^1.5.1", @@ -5486,9 +5492,9 @@ }, "dependencies": { "slash": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.0.0.tgz", - "integrity": "sha512-n6KkmvKS0623igEVj3FF0OZs1gYYJ0o0Hj939yc1fyxl2xt+xYpLnzJB6xBSqOfV9ZFLEWodBBN/heZJahuIJQ==" + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==" } } }, @@ -5680,9 +5686,9 @@ "dev": true }, "sass": { - "version": "1.62.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz", - "integrity": "sha512-Q4USplo4pLYgCi+XlipZCWUQz5pkg/ruSSgJ0WRDSb/+3z9tXUOkQ7QPYn4XrhZKYAK4HlpaQecRwKLJX6+DBg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz", + "integrity": "sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==", "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -5708,9 +5714,9 @@ } }, "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", "dev": true }, "slash": { @@ -6089,13 +6095,13 @@ "dev": true }, "write-file-atomic": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz", - "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "requires": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" } }, "xmlcreate": { @@ -6116,14 +6122,14 @@ "dev": true }, "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==" }, "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", diff --git a/package.json b/package.json index 8cdb110..9d36972 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "start": "npm run build-dev -- --servedir=.", "watch": "npm run build-dev -- --watch", "compile-css-min": "sass data-grid.scss:dist/data-grid.min.css --style compressed", - "compile-css-dev": "sass data-grid.scss dist/data-grid.css", + "compile-css-dev": "sass data-grid.scss dist/data-grid.css --embed-sources", "watch-css": "npm run compile-css-dev -- --watch --poll", "prefix-css-min": "postcss dist/data-grid.min.css --replace --use autoprefixer", - "prefix-css-dev": "postcss dist/data-grid.css --replace --use autoprefixer", + "prefix-css-dev": "postcss dist/data-grid.css --replace --use autoprefixer --map", "build-css-min": "npm run compile-css-min && npm run prefix-css-min", "build-css-dev": "npm run compile-css-dev && npm run prefix-css-dev", "build-css": "npm run build-css-min && npm run build-css-dev",