@kodaris/krubble-components 1.0.73 → 1.0.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +1111 -49
- package/dist/button/button.d.ts.map +1 -1
- package/dist/button/button.js +14 -2
- package/dist/button/button.js.map +1 -1
- package/dist/grid/grid.d.ts +187 -0
- package/dist/grid/grid.d.ts.map +1 -0
- package/dist/grid/grid.js +2419 -0
- package/dist/grid/grid.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/krubble-components.bundled.js +2535 -118
- package/dist/krubble-components.bundled.js.map +1 -1
- package/dist/krubble-components.bundled.min.js +1362 -131
- package/dist/krubble-components.bundled.min.js.map +1 -1
- package/dist/krubble-components.umd.js +2534 -117
- package/dist/krubble-components.umd.js.map +1 -1
- package/dist/krubble-components.umd.min.js +1413 -182
- package/dist/krubble-components.umd.min.js.map +1 -1
- package/package.json +5 -1
|
@@ -89,7 +89,7 @@ const e$4=(e,t,c)=>(c.configurable=true,c.enumerable=true,Reflect.decorate&&"obj
|
|
|
89
89
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
90
90
|
*/function e$3(e,r){return (n,s,i)=>{const o=t=>t.renderRoot?.querySelector(e)??null;return e$4(n,s,{get(){return o(this)}})}}
|
|
91
91
|
|
|
92
|
-
var __decorate$
|
|
92
|
+
var __decorate$o = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
93
93
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
94
94
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
95
95
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -196,13 +196,13 @@ KRAccordion.styles = i$5 `
|
|
|
196
196
|
padding: 16px 16px 8px 16px;
|
|
197
197
|
}
|
|
198
198
|
`;
|
|
199
|
-
__decorate$
|
|
199
|
+
__decorate$o([
|
|
200
200
|
n$1({ type: String })
|
|
201
201
|
], KRAccordion.prototype, "header", void 0);
|
|
202
|
-
__decorate$
|
|
202
|
+
__decorate$o([
|
|
203
203
|
n$1({ type: Boolean, reflect: true })
|
|
204
204
|
], KRAccordion.prototype, "expanded", void 0);
|
|
205
|
-
KRAccordion = __decorate$
|
|
205
|
+
KRAccordion = __decorate$o([
|
|
206
206
|
t$1('kr-accordion')
|
|
207
207
|
], KRAccordion);
|
|
208
208
|
|
|
@@ -219,7 +219,7 @@ const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4},e$2=t=>(...e)=>({_$
|
|
|
219
219
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
220
220
|
*/const e$1=e$2(class extends i$1{constructor(t$1){if(super(t$1),t$1.type!==t.ATTRIBUTE||"class"!==t$1.name||t$1.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return " "+Object.keys(t).filter(s=>t[s]).join(" ")+" "}update(s,[i]){if(void 0===this.st){this.st=new Set,void 0!==s.strings&&(this.nt=new Set(s.strings.join(" ").split(/\s/).filter(t=>""!==t)));for(const t in i)i[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(i)}const r=s.element.classList;for(const t of this.st)t in i||(r.remove(t),this.st.delete(t));for(const t in i){const s=!!i[t];s===this.st.has(t)||this.nt?.has(t)||(s?(r.add(t),this.st.add(t)):(r.remove(t),this.st.delete(t)));}return E}});
|
|
221
221
|
|
|
222
|
-
var __decorate$
|
|
222
|
+
var __decorate$n = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
223
223
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
224
224
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
225
225
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -417,23 +417,23 @@ KRAlert.styles = i$5 `
|
|
|
417
417
|
outline-offset: 2px;
|
|
418
418
|
}
|
|
419
419
|
`;
|
|
420
|
-
__decorate$
|
|
420
|
+
__decorate$n([
|
|
421
421
|
n$1({ type: String })
|
|
422
422
|
], KRAlert.prototype, "type", void 0);
|
|
423
|
-
__decorate$
|
|
423
|
+
__decorate$n([
|
|
424
424
|
n$1({ type: String })
|
|
425
425
|
], KRAlert.prototype, "title", void 0);
|
|
426
|
-
__decorate$
|
|
426
|
+
__decorate$n([
|
|
427
427
|
n$1({ type: Boolean })
|
|
428
428
|
], KRAlert.prototype, "dismissible", void 0);
|
|
429
|
-
__decorate$
|
|
429
|
+
__decorate$n([
|
|
430
430
|
n$1({ type: Boolean })
|
|
431
431
|
], KRAlert.prototype, "visible", void 0);
|
|
432
|
-
KRAlert = __decorate$
|
|
432
|
+
KRAlert = __decorate$n([
|
|
433
433
|
t$1('kr-alert')
|
|
434
434
|
], KRAlert);
|
|
435
435
|
|
|
436
|
-
var __decorate$
|
|
436
|
+
var __decorate$m = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
437
437
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
438
438
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
439
439
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -565,16 +565,27 @@ let KRButton = class KRButton extends i$2 {
|
|
|
565
565
|
dropdown.style.right = '';
|
|
566
566
|
dropdown.style.minWidth = hostRect.width + 'px';
|
|
567
567
|
dropdown.style.transformOrigin = 'top left';
|
|
568
|
+
dropdown.style.maxHeight = '';
|
|
569
|
+
dropdown.style.overflowY = '';
|
|
568
570
|
const dropdownRect = dropdown.getBoundingClientRect();
|
|
569
|
-
// Open above if dropdown
|
|
570
|
-
|
|
571
|
+
// Open above only if the dropdown doesn't fit below and there's more room above than below
|
|
572
|
+
// 8 = 4px gap between button and dropdown + 4px margin from viewport edge
|
|
573
|
+
if (dropdownRect.height > window.innerHeight - hostRect.bottom - 8 && hostRect.top > window.innerHeight - hostRect.bottom) {
|
|
571
574
|
dropdown.style.top = '';
|
|
572
575
|
dropdown.style.bottom = window.innerHeight - hostRect.top + 4 + 'px';
|
|
573
576
|
dropdown.style.transformOrigin = 'bottom left';
|
|
574
577
|
dropdown.classList.add('dropdown--above');
|
|
578
|
+
if (dropdownRect.height > hostRect.top - 8) {
|
|
579
|
+
dropdown.style.maxHeight = hostRect.top - 8 + 'px';
|
|
580
|
+
dropdown.style.overflowY = 'auto';
|
|
581
|
+
}
|
|
575
582
|
}
|
|
576
583
|
else {
|
|
577
584
|
dropdown.classList.remove('dropdown--above');
|
|
585
|
+
if (dropdownRect.height > window.innerHeight - hostRect.bottom - 8) {
|
|
586
|
+
dropdown.style.maxHeight = window.innerHeight - hostRect.bottom - 8 + 'px';
|
|
587
|
+
dropdown.style.overflowY = 'auto';
|
|
588
|
+
}
|
|
578
589
|
}
|
|
579
590
|
// Align right if dropdown overflows viewport right
|
|
580
591
|
if (dropdownRect.right > window.innerWidth) {
|
|
@@ -895,6 +906,7 @@ KRButton.styles = i$5 `
|
|
|
895
906
|
.dropdown {
|
|
896
907
|
position: fixed;
|
|
897
908
|
min-width: 100%;
|
|
909
|
+
box-sizing: border-box;
|
|
898
910
|
background: white;
|
|
899
911
|
border: 1px solid #9ba7b6;
|
|
900
912
|
border-radius: 8px;
|
|
@@ -1143,43 +1155,43 @@ KRButton.styles = i$5 `
|
|
|
1143
1155
|
opacity: 0.6;
|
|
1144
1156
|
}
|
|
1145
1157
|
`;
|
|
1146
|
-
__decorate$
|
|
1158
|
+
__decorate$m([
|
|
1147
1159
|
n$1({ type: String, reflect: true })
|
|
1148
1160
|
], KRButton.prototype, "variant", void 0);
|
|
1149
|
-
__decorate$
|
|
1161
|
+
__decorate$m([
|
|
1150
1162
|
n$1({ type: String, reflect: true })
|
|
1151
1163
|
], KRButton.prototype, "color", void 0);
|
|
1152
|
-
__decorate$
|
|
1164
|
+
__decorate$m([
|
|
1153
1165
|
n$1({ type: String, reflect: true })
|
|
1154
1166
|
], KRButton.prototype, "size", void 0);
|
|
1155
|
-
__decorate$
|
|
1167
|
+
__decorate$m([
|
|
1156
1168
|
n$1({ type: Boolean, reflect: true })
|
|
1157
1169
|
], KRButton.prototype, "disabled", void 0);
|
|
1158
|
-
__decorate$
|
|
1170
|
+
__decorate$m([
|
|
1159
1171
|
n$1({ type: String })
|
|
1160
1172
|
], KRButton.prototype, "href", void 0);
|
|
1161
|
-
__decorate$
|
|
1173
|
+
__decorate$m([
|
|
1162
1174
|
n$1({ type: String })
|
|
1163
1175
|
], KRButton.prototype, "target", void 0);
|
|
1164
|
-
__decorate$
|
|
1176
|
+
__decorate$m([
|
|
1165
1177
|
n$1({ type: Array })
|
|
1166
1178
|
], KRButton.prototype, "options", void 0);
|
|
1167
|
-
__decorate$
|
|
1179
|
+
__decorate$m([
|
|
1168
1180
|
n$1({ type: String, reflect: true, attribute: 'icon-position' })
|
|
1169
1181
|
], KRButton.prototype, "iconPosition", void 0);
|
|
1170
|
-
__decorate$
|
|
1182
|
+
__decorate$m([
|
|
1171
1183
|
n$1({ type: Boolean, reflect: true })
|
|
1172
1184
|
], KRButton.prototype, "split", void 0);
|
|
1173
|
-
__decorate$
|
|
1185
|
+
__decorate$m([
|
|
1174
1186
|
r$1()
|
|
1175
1187
|
], KRButton.prototype, "_state", void 0);
|
|
1176
|
-
__decorate$
|
|
1188
|
+
__decorate$m([
|
|
1177
1189
|
r$1()
|
|
1178
1190
|
], KRButton.prototype, "_stateText", void 0);
|
|
1179
|
-
__decorate$
|
|
1191
|
+
__decorate$m([
|
|
1180
1192
|
r$1()
|
|
1181
1193
|
], KRButton.prototype, "_dropdownOpened", void 0);
|
|
1182
|
-
KRButton = __decorate$
|
|
1194
|
+
KRButton = __decorate$m([
|
|
1183
1195
|
t$1('kr-button')
|
|
1184
1196
|
], KRButton);
|
|
1185
1197
|
|
|
@@ -1189,7 +1201,7 @@ KRButton = __decorate$l([
|
|
|
1189
1201
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
1190
1202
|
*/class e extends i$1{constructor(i){if(super(i),this.it=A,i.type!==t.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(r){if(r===A||null==r)return this._t=void 0,this.it=r;if(r===E)return r;if("string"!=typeof r)throw Error(this.constructor.directiveName+"() called with a non-string value");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}e.directiveName="unsafeHTML",e.resultType=1;const o$2=e$2(e);
|
|
1191
1203
|
|
|
1192
|
-
var __decorate$
|
|
1204
|
+
var __decorate$l = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
1193
1205
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1194
1206
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1195
1207
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -1423,26 +1435,26 @@ KRCodeDemo.styles = [krBaseCSS, i$5 `
|
|
|
1423
1435
|
.hljs-property { color: #005cc5; }
|
|
1424
1436
|
|
|
1425
1437
|
`];
|
|
1426
|
-
__decorate$
|
|
1438
|
+
__decorate$l([
|
|
1427
1439
|
n$1({ type: String })
|
|
1428
1440
|
], KRCodeDemo.prototype, "language", void 0);
|
|
1429
|
-
__decorate$
|
|
1441
|
+
__decorate$l([
|
|
1430
1442
|
r$1()
|
|
1431
1443
|
], KRCodeDemo.prototype, "code", void 0);
|
|
1432
|
-
__decorate$
|
|
1444
|
+
__decorate$l([
|
|
1433
1445
|
r$1()
|
|
1434
1446
|
], KRCodeDemo.prototype, "activeTab", void 0);
|
|
1435
|
-
__decorate$
|
|
1447
|
+
__decorate$l([
|
|
1436
1448
|
r$1()
|
|
1437
1449
|
], KRCodeDemo.prototype, "copied", void 0);
|
|
1438
|
-
__decorate$
|
|
1450
|
+
__decorate$l([
|
|
1439
1451
|
r$1()
|
|
1440
1452
|
], KRCodeDemo.prototype, "highlightedCode", void 0);
|
|
1441
|
-
KRCodeDemo = __decorate$
|
|
1453
|
+
KRCodeDemo = __decorate$l([
|
|
1442
1454
|
t$1('kr-code-demo')
|
|
1443
1455
|
], KRCodeDemo);
|
|
1444
1456
|
|
|
1445
|
-
var __decorate$
|
|
1457
|
+
var __decorate$k = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
1446
1458
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1447
1459
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1448
1460
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -1611,10 +1623,10 @@ KRContextMenu.styles = i$5 `
|
|
|
1611
1623
|
margin: 4px 0;
|
|
1612
1624
|
}
|
|
1613
1625
|
`;
|
|
1614
|
-
__decorate$
|
|
1626
|
+
__decorate$k([
|
|
1615
1627
|
r$1()
|
|
1616
1628
|
], KRContextMenu.prototype, "items", void 0);
|
|
1617
|
-
KRContextMenu = __decorate$
|
|
1629
|
+
KRContextMenu = __decorate$k([
|
|
1618
1630
|
t$1('kr-context-menu')
|
|
1619
1631
|
], KRContextMenu);
|
|
1620
1632
|
|
|
@@ -1624,7 +1636,7 @@ KRContextMenu = __decorate$j([
|
|
|
1624
1636
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
1625
1637
|
*/const n="important",i=" !"+n,o$1=e$2(class extends i$1{constructor(t$1){if(super(t$1),t$1.type!==t.ATTRIBUTE||"style"!==t$1.name||t$1.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce((e,r)=>{const s=t[r];return null==s?e:e+`${r=r.includes("-")?r:r.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(e,[r]){const{style:s}=e.element;if(void 0===this.ft)return this.ft=new Set(Object.keys(r)),this.render(r);for(const t of this.ft)null==r[t]&&(this.ft.delete(t),t.includes("-")?s.removeProperty(t):s[t]=null);for(const t in r){const e=r[t];if(null!=e){this.ft.add(t);const r="string"==typeof e&&e.endsWith(i);t.includes("-")||r?s.setProperty(t,r?e.slice(0,-11):e,r?n:""):s[t]=e;}}return E}});
|
|
1626
1638
|
|
|
1627
|
-
var __decorate$
|
|
1639
|
+
var __decorate$j = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
1628
1640
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1629
1641
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1630
1642
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -1651,7 +1663,7 @@ KRDialogHeader.styles = i$5 `
|
|
|
1651
1663
|
font-weight: 600;
|
|
1652
1664
|
}
|
|
1653
1665
|
`;
|
|
1654
|
-
KRDialogHeader = __decorate$
|
|
1666
|
+
KRDialogHeader = __decorate$j([
|
|
1655
1667
|
t$1('kr-dialog-header')
|
|
1656
1668
|
], KRDialogHeader);
|
|
1657
1669
|
let KRDialogContent = class KRDialogContent extends i$2 {
|
|
@@ -1667,7 +1679,7 @@ KRDialogContent.styles = i$5 `
|
|
|
1667
1679
|
flex: 1 1 auto;
|
|
1668
1680
|
}
|
|
1669
1681
|
`;
|
|
1670
|
-
KRDialogContent = __decorate$
|
|
1682
|
+
KRDialogContent = __decorate$j([
|
|
1671
1683
|
t$1('kr-dialog-content')
|
|
1672
1684
|
], KRDialogContent);
|
|
1673
1685
|
let KRDialogFooter = class KRDialogFooter extends i$2 {
|
|
@@ -1687,7 +1699,7 @@ KRDialogFooter.styles = i$5 `
|
|
|
1687
1699
|
justify-content: flex-end;
|
|
1688
1700
|
}
|
|
1689
1701
|
`;
|
|
1690
|
-
KRDialogFooter = __decorate$
|
|
1702
|
+
KRDialogFooter = __decorate$j([
|
|
1691
1703
|
t$1('kr-dialog-footer')
|
|
1692
1704
|
], KRDialogFooter);
|
|
1693
1705
|
/**
|
|
@@ -1903,23 +1915,23 @@ KRDialog.styles = i$5 `
|
|
|
1903
1915
|
flex-direction: column;
|
|
1904
1916
|
}
|
|
1905
1917
|
`;
|
|
1906
|
-
__decorate$
|
|
1918
|
+
__decorate$j([
|
|
1907
1919
|
r$1()
|
|
1908
1920
|
], KRDialog.prototype, "_contentElement", void 0);
|
|
1909
|
-
__decorate$
|
|
1921
|
+
__decorate$j([
|
|
1910
1922
|
n$1({ type: Boolean, reflect: true })
|
|
1911
1923
|
], KRDialog.prototype, "opened", void 0);
|
|
1912
|
-
__decorate$
|
|
1924
|
+
__decorate$j([
|
|
1913
1925
|
n$1({ type: String })
|
|
1914
1926
|
], KRDialog.prototype, "label", void 0);
|
|
1915
|
-
__decorate$
|
|
1927
|
+
__decorate$j([
|
|
1916
1928
|
n$1({ type: String })
|
|
1917
1929
|
], KRDialog.prototype, "width", void 0);
|
|
1918
|
-
KRDialog = __decorate$
|
|
1930
|
+
KRDialog = __decorate$j([
|
|
1919
1931
|
t$1('kr-dialog')
|
|
1920
1932
|
], KRDialog);
|
|
1921
1933
|
|
|
1922
|
-
var __decorate$
|
|
1934
|
+
var __decorate$i = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
1923
1935
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1924
1936
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1925
1937
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -2439,47 +2451,47 @@ KRDateRangePicker.styles = i$5 `
|
|
|
2439
2451
|
border-top: 1px solid #e5e7eb;
|
|
2440
2452
|
}
|
|
2441
2453
|
`;
|
|
2442
|
-
__decorate$
|
|
2454
|
+
__decorate$i([
|
|
2443
2455
|
n$1({ type: Object })
|
|
2444
2456
|
], KRDateRangePicker.prototype, "value", void 0);
|
|
2445
|
-
__decorate$
|
|
2457
|
+
__decorate$i([
|
|
2446
2458
|
n$1({ type: Array })
|
|
2447
2459
|
], KRDateRangePicker.prototype, "relativeOptions", void 0);
|
|
2448
|
-
__decorate$
|
|
2460
|
+
__decorate$i([
|
|
2449
2461
|
n$1({ type: Boolean })
|
|
2450
2462
|
], KRDateRangePicker.prototype, "disabled", void 0);
|
|
2451
|
-
__decorate$
|
|
2463
|
+
__decorate$i([
|
|
2452
2464
|
n$1({ type: Boolean })
|
|
2453
2465
|
], KRDateRangePicker.prototype, "invalid", void 0);
|
|
2454
|
-
__decorate$
|
|
2466
|
+
__decorate$i([
|
|
2455
2467
|
n$1({ type: String })
|
|
2456
2468
|
], KRDateRangePicker.prototype, "placeholder", void 0);
|
|
2457
|
-
__decorate$
|
|
2469
|
+
__decorate$i([
|
|
2458
2470
|
n$1({ type: String })
|
|
2459
2471
|
], KRDateRangePicker.prototype, "startDate", void 0);
|
|
2460
|
-
__decorate$
|
|
2472
|
+
__decorate$i([
|
|
2461
2473
|
n$1({ type: String })
|
|
2462
2474
|
], KRDateRangePicker.prototype, "endDate", void 0);
|
|
2463
|
-
__decorate$
|
|
2475
|
+
__decorate$i([
|
|
2464
2476
|
n$1({ type: String })
|
|
2465
2477
|
], KRDateRangePicker.prototype, "mode", void 0);
|
|
2466
|
-
__decorate$
|
|
2478
|
+
__decorate$i([
|
|
2467
2479
|
r$1()
|
|
2468
2480
|
], KRDateRangePicker.prototype, "_isOpen", void 0);
|
|
2469
|
-
__decorate$
|
|
2481
|
+
__decorate$i([
|
|
2470
2482
|
r$1()
|
|
2471
2483
|
], KRDateRangePicker.prototype, "_activeTab", void 0);
|
|
2472
|
-
__decorate$
|
|
2484
|
+
__decorate$i([
|
|
2473
2485
|
r$1()
|
|
2474
2486
|
], KRDateRangePicker.prototype, "_tempStartDate", void 0);
|
|
2475
|
-
__decorate$
|
|
2487
|
+
__decorate$i([
|
|
2476
2488
|
r$1()
|
|
2477
2489
|
], KRDateRangePicker.prototype, "_tempEndDate", void 0);
|
|
2478
|
-
KRDateRangePicker = __decorate$
|
|
2490
|
+
KRDateRangePicker = __decorate$i([
|
|
2479
2491
|
t$1('kr-date-range-picker')
|
|
2480
2492
|
], KRDateRangePicker);
|
|
2481
2493
|
|
|
2482
|
-
var __decorate$
|
|
2494
|
+
var __decorate$h = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
2483
2495
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2484
2496
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2485
2497
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -2781,23 +2793,23 @@ KRSnackbar.styles = i$5 `
|
|
|
2781
2793
|
`;
|
|
2782
2794
|
/** Track active snackbars for stacking */
|
|
2783
2795
|
KRSnackbar.activeSnackbars = [];
|
|
2784
|
-
__decorate$
|
|
2796
|
+
__decorate$h([
|
|
2785
2797
|
n$1({ type: String })
|
|
2786
2798
|
], KRSnackbar.prototype, "type", void 0);
|
|
2787
|
-
__decorate$
|
|
2799
|
+
__decorate$h([
|
|
2788
2800
|
n$1({ type: String })
|
|
2789
2801
|
], KRSnackbar.prototype, "title", void 0);
|
|
2790
|
-
__decorate$
|
|
2802
|
+
__decorate$h([
|
|
2791
2803
|
n$1({ type: String })
|
|
2792
2804
|
], KRSnackbar.prototype, "message", void 0);
|
|
2793
|
-
__decorate$
|
|
2805
|
+
__decorate$h([
|
|
2794
2806
|
n$1({ type: Number })
|
|
2795
2807
|
], KRSnackbar.prototype, "duration", void 0);
|
|
2796
|
-
KRSnackbar = KRSnackbar_1 = __decorate$
|
|
2808
|
+
KRSnackbar = KRSnackbar_1 = __decorate$h([
|
|
2797
2809
|
t$1('kr-snackbar')
|
|
2798
2810
|
], KRSnackbar);
|
|
2799
2811
|
|
|
2800
|
-
var __decorate$
|
|
2812
|
+
var __decorate$g = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
2801
2813
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
2802
2814
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
2803
2815
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -3100,20 +3112,20 @@ KRTabGroup.styles = [
|
|
|
3100
3112
|
}
|
|
3101
3113
|
`,
|
|
3102
3114
|
];
|
|
3103
|
-
__decorate$
|
|
3115
|
+
__decorate$g([
|
|
3104
3116
|
n$1({ type: String, attribute: 'active-tab-id' })
|
|
3105
3117
|
], KRTabGroup.prototype, "activeTabId", void 0);
|
|
3106
|
-
__decorate$
|
|
3118
|
+
__decorate$g([
|
|
3107
3119
|
n$1({ type: Boolean })
|
|
3108
3120
|
], KRTabGroup.prototype, "justified", void 0);
|
|
3109
|
-
__decorate$
|
|
3121
|
+
__decorate$g([
|
|
3110
3122
|
n$1({ type: String, reflect: true })
|
|
3111
3123
|
], KRTabGroup.prototype, "size", void 0);
|
|
3112
|
-
KRTabGroup = __decorate$
|
|
3124
|
+
KRTabGroup = __decorate$g([
|
|
3113
3125
|
t$1('kr-tab-group')
|
|
3114
3126
|
], KRTabGroup);
|
|
3115
3127
|
|
|
3116
|
-
var __decorate$
|
|
3128
|
+
var __decorate$f = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
3117
3129
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3118
3130
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3119
3131
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -3194,35 +3206,35 @@ KRTab.styles = [
|
|
|
3194
3206
|
}
|
|
3195
3207
|
`,
|
|
3196
3208
|
];
|
|
3197
|
-
__decorate$
|
|
3209
|
+
__decorate$f([
|
|
3198
3210
|
n$1({ type: String, reflect: true })
|
|
3199
3211
|
], KRTab.prototype, "id", void 0);
|
|
3200
|
-
__decorate$
|
|
3212
|
+
__decorate$f([
|
|
3201
3213
|
n$1({ type: String })
|
|
3202
3214
|
], KRTab.prototype, "label", void 0);
|
|
3203
|
-
__decorate$
|
|
3215
|
+
__decorate$f([
|
|
3204
3216
|
n$1({ type: String })
|
|
3205
3217
|
], KRTab.prototype, "badge", void 0);
|
|
3206
|
-
__decorate$
|
|
3218
|
+
__decorate$f([
|
|
3207
3219
|
n$1({ type: String, attribute: 'badge-background' })
|
|
3208
3220
|
], KRTab.prototype, "badgeBackground", void 0);
|
|
3209
|
-
__decorate$
|
|
3221
|
+
__decorate$f([
|
|
3210
3222
|
n$1({ type: String, attribute: 'badge-color' })
|
|
3211
3223
|
], KRTab.prototype, "badgeColor", void 0);
|
|
3212
|
-
__decorate$
|
|
3224
|
+
__decorate$f([
|
|
3213
3225
|
n$1({ type: Boolean })
|
|
3214
3226
|
], KRTab.prototype, "disabled", void 0);
|
|
3215
|
-
__decorate$
|
|
3227
|
+
__decorate$f([
|
|
3216
3228
|
n$1({ type: Boolean })
|
|
3217
3229
|
], KRTab.prototype, "dismissible", void 0);
|
|
3218
|
-
__decorate$
|
|
3230
|
+
__decorate$f([
|
|
3219
3231
|
n$1({ type: Boolean, reflect: true })
|
|
3220
3232
|
], KRTab.prototype, "active", void 0);
|
|
3221
|
-
KRTab = __decorate$
|
|
3233
|
+
KRTab = __decorate$f([
|
|
3222
3234
|
t$1('kr-tab')
|
|
3223
3235
|
], KRTab);
|
|
3224
3236
|
|
|
3225
|
-
var __decorate$
|
|
3237
|
+
var __decorate$e = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
3226
3238
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3227
3239
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3228
3240
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -3694,47 +3706,47 @@ KRSelectField.styles = [krBaseCSS, i$5 `
|
|
|
3694
3706
|
`];
|
|
3695
3707
|
// Enable form association
|
|
3696
3708
|
KRSelectField.formAssociated = true;
|
|
3697
|
-
__decorate$
|
|
3709
|
+
__decorate$e([
|
|
3698
3710
|
n$1({ type: String })
|
|
3699
3711
|
], KRSelectField.prototype, "label", void 0);
|
|
3700
|
-
__decorate$
|
|
3712
|
+
__decorate$e([
|
|
3701
3713
|
n$1({ type: String })
|
|
3702
3714
|
], KRSelectField.prototype, "name", void 0);
|
|
3703
|
-
__decorate$
|
|
3715
|
+
__decorate$e([
|
|
3704
3716
|
n$1({ type: String })
|
|
3705
3717
|
], KRSelectField.prototype, "value", void 0);
|
|
3706
|
-
__decorate$
|
|
3718
|
+
__decorate$e([
|
|
3707
3719
|
n$1({ type: String })
|
|
3708
3720
|
], KRSelectField.prototype, "placeholder", void 0);
|
|
3709
|
-
__decorate$
|
|
3721
|
+
__decorate$e([
|
|
3710
3722
|
n$1({ type: Boolean })
|
|
3711
3723
|
], KRSelectField.prototype, "disabled", void 0);
|
|
3712
|
-
__decorate$
|
|
3724
|
+
__decorate$e([
|
|
3713
3725
|
n$1({ type: Boolean })
|
|
3714
3726
|
], KRSelectField.prototype, "required", void 0);
|
|
3715
|
-
__decorate$
|
|
3727
|
+
__decorate$e([
|
|
3716
3728
|
n$1({ type: Boolean })
|
|
3717
3729
|
], KRSelectField.prototype, "readonly", void 0);
|
|
3718
|
-
__decorate$
|
|
3730
|
+
__decorate$e([
|
|
3719
3731
|
n$1({ type: String })
|
|
3720
3732
|
], KRSelectField.prototype, "hint", void 0);
|
|
3721
|
-
__decorate$
|
|
3733
|
+
__decorate$e([
|
|
3722
3734
|
r$1()
|
|
3723
3735
|
], KRSelectField.prototype, "_isOpen", void 0);
|
|
3724
|
-
__decorate$
|
|
3736
|
+
__decorate$e([
|
|
3725
3737
|
r$1()
|
|
3726
3738
|
], KRSelectField.prototype, "_highlightedIndex", void 0);
|
|
3727
|
-
__decorate$
|
|
3739
|
+
__decorate$e([
|
|
3728
3740
|
r$1()
|
|
3729
3741
|
], KRSelectField.prototype, "_touched", void 0);
|
|
3730
|
-
__decorate$
|
|
3742
|
+
__decorate$e([
|
|
3731
3743
|
e$3('.select-trigger')
|
|
3732
3744
|
], KRSelectField.prototype, "_triggerElement", void 0);
|
|
3733
|
-
KRSelectField = __decorate$
|
|
3745
|
+
KRSelectField = __decorate$e([
|
|
3734
3746
|
t$1('kr-select-field')
|
|
3735
3747
|
], KRSelectField);
|
|
3736
3748
|
|
|
3737
|
-
var __decorate$
|
|
3749
|
+
var __decorate$d = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
3738
3750
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3739
3751
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3740
3752
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -3771,13 +3783,13 @@ KRSelectOption.styles = i$5 `
|
|
|
3771
3783
|
display: none;
|
|
3772
3784
|
}
|
|
3773
3785
|
`;
|
|
3774
|
-
__decorate$
|
|
3786
|
+
__decorate$d([
|
|
3775
3787
|
n$1({ type: String })
|
|
3776
3788
|
], KRSelectOption.prototype, "value", void 0);
|
|
3777
|
-
__decorate$
|
|
3789
|
+
__decorate$d([
|
|
3778
3790
|
n$1({ type: Boolean })
|
|
3779
3791
|
], KRSelectOption.prototype, "disabled", void 0);
|
|
3780
|
-
KRSelectOption = __decorate$
|
|
3792
|
+
KRSelectOption = __decorate$d([
|
|
3781
3793
|
t$1('kr-select-option')
|
|
3782
3794
|
], KRSelectOption);
|
|
3783
3795
|
|
|
@@ -4825,7 +4837,7 @@ class KRQuery {
|
|
|
4825
4837
|
}
|
|
4826
4838
|
}
|
|
4827
4839
|
|
|
4828
|
-
var __decorate$
|
|
4840
|
+
var __decorate$c = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
4829
4841
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4830
4842
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4831
4843
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -7182,61 +7194,2466 @@ KRTable.styles = [krBaseCSS, i$5 `
|
|
|
7182
7194
|
}
|
|
7183
7195
|
|
|
7184
7196
|
`];
|
|
7185
|
-
__decorate$
|
|
7197
|
+
__decorate$c([
|
|
7186
7198
|
r$1()
|
|
7187
7199
|
], KRTable.prototype, "_data", void 0);
|
|
7188
|
-
__decorate$
|
|
7200
|
+
__decorate$c([
|
|
7189
7201
|
r$1()
|
|
7190
7202
|
], KRTable.prototype, "_dataState", void 0);
|
|
7191
|
-
__decorate$
|
|
7203
|
+
__decorate$c([
|
|
7192
7204
|
r$1()
|
|
7193
7205
|
], KRTable.prototype, "_page", void 0);
|
|
7194
|
-
__decorate$
|
|
7206
|
+
__decorate$c([
|
|
7195
7207
|
r$1()
|
|
7196
7208
|
], KRTable.prototype, "_pageSize", void 0);
|
|
7197
|
-
__decorate$
|
|
7209
|
+
__decorate$c([
|
|
7198
7210
|
r$1()
|
|
7199
7211
|
], KRTable.prototype, "_totalItems", void 0);
|
|
7200
|
-
__decorate$
|
|
7212
|
+
__decorate$c([
|
|
7201
7213
|
r$1()
|
|
7202
7214
|
], KRTable.prototype, "_totalPages", void 0);
|
|
7203
|
-
__decorate$
|
|
7215
|
+
__decorate$c([
|
|
7204
7216
|
r$1()
|
|
7205
7217
|
], KRTable.prototype, "_searchQuery", void 0);
|
|
7206
|
-
__decorate$
|
|
7218
|
+
__decorate$c([
|
|
7207
7219
|
r$1()
|
|
7208
7220
|
], KRTable.prototype, "_canScrollLeft", void 0);
|
|
7209
|
-
__decorate$
|
|
7221
|
+
__decorate$c([
|
|
7210
7222
|
r$1()
|
|
7211
7223
|
], KRTable.prototype, "_canScrollRight", void 0);
|
|
7212
|
-
__decorate$
|
|
7224
|
+
__decorate$c([
|
|
7213
7225
|
r$1()
|
|
7214
7226
|
], KRTable.prototype, "_canScrollHorizontal", void 0);
|
|
7215
|
-
__decorate$
|
|
7227
|
+
__decorate$c([
|
|
7216
7228
|
r$1()
|
|
7217
7229
|
], KRTable.prototype, "_columnPickerOpen", void 0);
|
|
7218
|
-
__decorate$
|
|
7230
|
+
__decorate$c([
|
|
7219
7231
|
r$1()
|
|
7220
7232
|
], KRTable.prototype, "_filterPanelOpened", void 0);
|
|
7221
|
-
__decorate$
|
|
7233
|
+
__decorate$c([
|
|
7222
7234
|
r$1()
|
|
7223
7235
|
], KRTable.prototype, "_filterPanelTab", void 0);
|
|
7224
|
-
__decorate$
|
|
7236
|
+
__decorate$c([
|
|
7225
7237
|
r$1()
|
|
7226
7238
|
], KRTable.prototype, "_buckets", void 0);
|
|
7227
|
-
__decorate$
|
|
7239
|
+
__decorate$c([
|
|
7228
7240
|
r$1()
|
|
7229
7241
|
], KRTable.prototype, "_sorts", void 0);
|
|
7230
|
-
__decorate$
|
|
7242
|
+
__decorate$c([
|
|
7231
7243
|
n$1({ type: Object })
|
|
7232
7244
|
], KRTable.prototype, "def", void 0);
|
|
7233
|
-
__decorate$
|
|
7245
|
+
__decorate$c([
|
|
7234
7246
|
n$1({ type: String, reflect: true })
|
|
7235
7247
|
], KRTable.prototype, "variant", void 0);
|
|
7236
|
-
KRTable = __decorate$
|
|
7248
|
+
KRTable = __decorate$c([
|
|
7237
7249
|
t$1('kr-table')
|
|
7238
7250
|
], KRTable);
|
|
7239
7251
|
|
|
7252
|
+
var __decorate$b = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
7253
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
7254
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
7255
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
7256
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7257
|
+
};
|
|
7258
|
+
/** Internal grid model built from user-provided def. */
|
|
7259
|
+
class KRGridModel {
|
|
7260
|
+
constructor() {
|
|
7261
|
+
this.title = '';
|
|
7262
|
+
this.description = '';
|
|
7263
|
+
this.actions = [];
|
|
7264
|
+
this.columns = [];
|
|
7265
|
+
this.displayedColumns = [];
|
|
7266
|
+
this.data = null;
|
|
7267
|
+
this.dataSource = null;
|
|
7268
|
+
this.refreshInterval = 0;
|
|
7269
|
+
this.pageSize = 0;
|
|
7270
|
+
this.rowClickable = false;
|
|
7271
|
+
this.rowHref = null;
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
let KRGrid = class KRGrid extends i$2 {
|
|
7275
|
+
constructor() {
|
|
7276
|
+
super(...arguments);
|
|
7277
|
+
/**
|
|
7278
|
+
* Internal flag to switch between scroll edge modes:
|
|
7279
|
+
* - 'overlay': Fixed padding with overlay elements that hide content at edges (scrollbar at viewport edge)
|
|
7280
|
+
* - 'edge': Padding scrolls with content, allowing table to reach edges when scrolling
|
|
7281
|
+
*/
|
|
7282
|
+
this._scrollStyle = 'edge';
|
|
7283
|
+
this._data = [];
|
|
7284
|
+
this._dataState = 'idle';
|
|
7285
|
+
this._page = 1;
|
|
7286
|
+
this._pageSize = 50;
|
|
7287
|
+
this._totalItems = 0;
|
|
7288
|
+
this._totalPages = 0;
|
|
7289
|
+
this._searchQuery = '';
|
|
7290
|
+
this._canScrollLeft = false;
|
|
7291
|
+
this._canScrollRight = false;
|
|
7292
|
+
this._canScrollHorizontal = false;
|
|
7293
|
+
this._columnPickerOpen = false;
|
|
7294
|
+
this._filterPanelOpened = null;
|
|
7295
|
+
this._filterPanelTab = 'filter';
|
|
7296
|
+
this._buckets = new Map();
|
|
7297
|
+
this._filterPanelPos = { top: 0, left: 0 };
|
|
7298
|
+
this._sorts = [];
|
|
7299
|
+
this._resizing = null;
|
|
7300
|
+
this._resizeObserver = null;
|
|
7301
|
+
this._searchPositionLocked = false;
|
|
7302
|
+
this._columnWidthsLocked = false;
|
|
7303
|
+
this._model = new KRGridModel();
|
|
7304
|
+
this.def = { columns: [] };
|
|
7305
|
+
/**
|
|
7306
|
+
* Table layout variant.
|
|
7307
|
+
* - 'default': Full-page table that fills parent height with centered search.
|
|
7308
|
+
* - 'card': Embedded table that sizes itself to content, left-aligns search, and
|
|
7309
|
+
* reserves space for pageSize rows to prevent layout shift.
|
|
7310
|
+
*/
|
|
7311
|
+
this.variant = 'default';
|
|
7312
|
+
this._handleClickOutside = (e) => {
|
|
7313
|
+
const path = e.composedPath();
|
|
7314
|
+
if (this._columnPickerOpen) {
|
|
7315
|
+
const picker = this.shadowRoot?.querySelector('.column-picker-wrapper');
|
|
7316
|
+
if (picker && !path.includes(picker)) {
|
|
7317
|
+
this._columnPickerOpen = false;
|
|
7318
|
+
}
|
|
7319
|
+
}
|
|
7320
|
+
if (this._filterPanelOpened) {
|
|
7321
|
+
if (!path.some((el) => el.classList?.contains('filter-panel'))) {
|
|
7322
|
+
this._handleFilterApply();
|
|
7323
|
+
}
|
|
7324
|
+
}
|
|
7325
|
+
};
|
|
7326
|
+
this._handleResizeMove = (e) => {
|
|
7327
|
+
if (!this._resizing)
|
|
7328
|
+
return;
|
|
7329
|
+
const col = this._model.columns.find(c => c.id === this._resizing.columnId);
|
|
7330
|
+
if (col) {
|
|
7331
|
+
const newWidth = this._resizing.startWidth + (e.clientX - this._resizing.startX);
|
|
7332
|
+
col.width = `${Math.min(900, Math.max(50, newWidth))}px`;
|
|
7333
|
+
this.requestUpdate();
|
|
7334
|
+
}
|
|
7335
|
+
};
|
|
7336
|
+
this._handleResizeEnd = () => {
|
|
7337
|
+
this._resizing = null;
|
|
7338
|
+
document.removeEventListener('mousemove', this._handleResizeMove);
|
|
7339
|
+
document.removeEventListener('mouseup', this._handleResizeEnd);
|
|
7340
|
+
};
|
|
7341
|
+
}
|
|
7342
|
+
connectedCallback() {
|
|
7343
|
+
super.connectedCallback();
|
|
7344
|
+
this.classList.toggle('kr-table--scroll-overlay', this._scrollStyle === 'overlay');
|
|
7345
|
+
this.classList.toggle('kr-table--scroll-edge', this._scrollStyle === 'edge');
|
|
7346
|
+
this._fetch();
|
|
7347
|
+
this._initRefresh();
|
|
7348
|
+
document.addEventListener('click', this._handleClickOutside);
|
|
7349
|
+
this._resizeObserver = new ResizeObserver(() => {
|
|
7350
|
+
// Unlock and recalculate on resize since layout changes
|
|
7351
|
+
this._searchPositionLocked = false;
|
|
7352
|
+
this._updateSearchPosition();
|
|
7353
|
+
});
|
|
7354
|
+
this._resizeObserver.observe(this);
|
|
7355
|
+
}
|
|
7356
|
+
disconnectedCallback() {
|
|
7357
|
+
super.disconnectedCallback();
|
|
7358
|
+
clearInterval(this._refreshTimer);
|
|
7359
|
+
document.removeEventListener('click', this._handleClickOutside);
|
|
7360
|
+
this._resizeObserver?.disconnect();
|
|
7361
|
+
}
|
|
7362
|
+
willUpdate(changedProperties) {
|
|
7363
|
+
if (changedProperties.has('def')) {
|
|
7364
|
+
// Build internal model from user-provided def
|
|
7365
|
+
this._columnWidthsLocked = false;
|
|
7366
|
+
this._model = new KRGridModel();
|
|
7367
|
+
if (this.def.title) {
|
|
7368
|
+
this._model.title = this.def.title;
|
|
7369
|
+
}
|
|
7370
|
+
if (this.def.description) {
|
|
7371
|
+
this._model.description = this.def.description;
|
|
7372
|
+
}
|
|
7373
|
+
if (this.def.actions) {
|
|
7374
|
+
this._model.actions = this.def.actions;
|
|
7375
|
+
}
|
|
7376
|
+
if (this.def.data) {
|
|
7377
|
+
this._model.data = this.def.data;
|
|
7378
|
+
}
|
|
7379
|
+
if (this.def.dataSource) {
|
|
7380
|
+
this._model.dataSource = this.def.dataSource;
|
|
7381
|
+
}
|
|
7382
|
+
if (typeof this.def.refreshInterval === 'number') {
|
|
7383
|
+
this._model.refreshInterval = this.def.refreshInterval;
|
|
7384
|
+
}
|
|
7385
|
+
if (typeof this.def.pageSize === 'number') {
|
|
7386
|
+
this._model.pageSize = this.def.pageSize;
|
|
7387
|
+
this._pageSize = this.def.pageSize;
|
|
7388
|
+
}
|
|
7389
|
+
if (this.def.rowClickable) {
|
|
7390
|
+
this._model.rowClickable = this.def.rowClickable;
|
|
7391
|
+
}
|
|
7392
|
+
if (this.def.rowHref) {
|
|
7393
|
+
this._model.rowHref = this.def.rowHref;
|
|
7394
|
+
}
|
|
7395
|
+
this._sorts = [];
|
|
7396
|
+
this._model.columns = this.def.columns.map(col => {
|
|
7397
|
+
const column = {
|
|
7398
|
+
...col,
|
|
7399
|
+
filter: null
|
|
7400
|
+
};
|
|
7401
|
+
if (!column.type) {
|
|
7402
|
+
column.type = 'string';
|
|
7403
|
+
}
|
|
7404
|
+
if (col.sort) {
|
|
7405
|
+
this._sorts.push({
|
|
7406
|
+
sortBy: col.id,
|
|
7407
|
+
sortDirection: col.sort
|
|
7408
|
+
});
|
|
7409
|
+
}
|
|
7410
|
+
if (column.type === 'actions') {
|
|
7411
|
+
column.label = col.label ?? '';
|
|
7412
|
+
column.sticky = 'right';
|
|
7413
|
+
column.resizable = false;
|
|
7414
|
+
return column;
|
|
7415
|
+
}
|
|
7416
|
+
if (col.filterable || col.facetable) {
|
|
7417
|
+
column.filter = new KRQuery();
|
|
7418
|
+
column.filter.field = col.id;
|
|
7419
|
+
column.filter.type = column.type;
|
|
7420
|
+
if (col.filter) {
|
|
7421
|
+
column.filter.setOperator(col.filter.operator);
|
|
7422
|
+
column.filter.setValue(col.filter.value);
|
|
7423
|
+
}
|
|
7424
|
+
else if (col.facetable && !col.filterable) {
|
|
7425
|
+
column.filter.operator = 'in';
|
|
7426
|
+
column.filter.value = [];
|
|
7427
|
+
}
|
|
7428
|
+
else if (column.filter.type === 'string') {
|
|
7429
|
+
column.filter.operator = 'contains';
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
return column;
|
|
7433
|
+
});
|
|
7434
|
+
if (this.def.displayedColumns) {
|
|
7435
|
+
this._model.displayedColumns = this.def.displayedColumns;
|
|
7436
|
+
}
|
|
7437
|
+
else {
|
|
7438
|
+
this._model.displayedColumns = this._model.columns.map(c => c.id);
|
|
7439
|
+
}
|
|
7440
|
+
this._fetch();
|
|
7441
|
+
this._initRefresh();
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
updated(changedProperties) {
|
|
7445
|
+
this.classList.toggle('kr-table--card', this.variant === 'card');
|
|
7446
|
+
this._updateScrollFlags();
|
|
7447
|
+
this._syncSlottedContent();
|
|
7448
|
+
this._lockColumnWidths();
|
|
7449
|
+
}
|
|
7450
|
+
/** Measures header cell widths and locks them to prevent column shift on subsequent data changes. */
|
|
7451
|
+
_lockColumnWidths() {
|
|
7452
|
+
if (this._columnWidthsLocked || this._data.length === 0)
|
|
7453
|
+
return;
|
|
7454
|
+
const headerCells = this.shadowRoot?.querySelectorAll('.header-row > .header-cell');
|
|
7455
|
+
if (!headerCells)
|
|
7456
|
+
return;
|
|
7457
|
+
const cols = this.getDisplayedColumns();
|
|
7458
|
+
headerCells.forEach((cell, i) => {
|
|
7459
|
+
const cellWidth = cell.offsetWidth;
|
|
7460
|
+
if (i < cols.length && !cols[i].width && cols[i].type !== 'actions' && cellWidth > 0) {
|
|
7461
|
+
cols[i].width = `${cellWidth}px`;
|
|
7462
|
+
this._columnWidthsLocked = true;
|
|
7463
|
+
}
|
|
7464
|
+
});
|
|
7465
|
+
}
|
|
7466
|
+
/** Syncs light DOM content for cells with custom render functions */
|
|
7467
|
+
_syncSlottedContent() {
|
|
7468
|
+
const columns = this.getDisplayedColumns().filter(col => col.render);
|
|
7469
|
+
if (!columns.length)
|
|
7470
|
+
return;
|
|
7471
|
+
// Clear old slotted content
|
|
7472
|
+
this.querySelectorAll('[slot^="cell-"]').forEach(el => el.remove());
|
|
7473
|
+
// Create new slotted content
|
|
7474
|
+
this._data.forEach((row, rowIndex) => {
|
|
7475
|
+
columns.forEach(col => {
|
|
7476
|
+
const result = col.render(row);
|
|
7477
|
+
if (!result)
|
|
7478
|
+
return;
|
|
7479
|
+
const el = document.createElement('span');
|
|
7480
|
+
el.slot = `cell-${rowIndex}-${col.id}`;
|
|
7481
|
+
if (col.type === 'actions') {
|
|
7482
|
+
el.style.display = 'flex';
|
|
7483
|
+
el.style.gap = '8px';
|
|
7484
|
+
}
|
|
7485
|
+
if (typeof result === 'string') {
|
|
7486
|
+
el.innerHTML = result;
|
|
7487
|
+
}
|
|
7488
|
+
else {
|
|
7489
|
+
D(result, el);
|
|
7490
|
+
}
|
|
7491
|
+
this.appendChild(el);
|
|
7492
|
+
});
|
|
7493
|
+
});
|
|
7494
|
+
}
|
|
7495
|
+
// ----------------------------------------------------------------------------
|
|
7496
|
+
// Public Interface
|
|
7497
|
+
// ----------------------------------------------------------------------------
|
|
7498
|
+
refresh() {
|
|
7499
|
+
this._fetch();
|
|
7500
|
+
}
|
|
7501
|
+
goToPrevPage() {
|
|
7502
|
+
if (this._page > 1) {
|
|
7503
|
+
this._page--;
|
|
7504
|
+
this._fetch();
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
goToNextPage() {
|
|
7508
|
+
if (this._page < this._totalPages) {
|
|
7509
|
+
this._page++;
|
|
7510
|
+
this._fetch();
|
|
7511
|
+
}
|
|
7512
|
+
}
|
|
7513
|
+
goToPage(page) {
|
|
7514
|
+
if (page >= 1 && page <= this._totalPages) {
|
|
7515
|
+
this._page = page;
|
|
7516
|
+
this._fetch();
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7519
|
+
// ----------------------------------------------------------------------------
|
|
7520
|
+
// Data Fetching
|
|
7521
|
+
// ----------------------------------------------------------------------------
|
|
7522
|
+
_toSolrData() {
|
|
7523
|
+
const request = {
|
|
7524
|
+
page: this._page - 1,
|
|
7525
|
+
size: this._pageSize,
|
|
7526
|
+
sorts: this._sorts,
|
|
7527
|
+
filterFields: [],
|
|
7528
|
+
queryFields: [],
|
|
7529
|
+
facetFields: []
|
|
7530
|
+
};
|
|
7531
|
+
for (const col of this._model.columns) {
|
|
7532
|
+
if (!col.filter || col.filter.isEmpty() || !col.filter.isValid()) {
|
|
7533
|
+
continue;
|
|
7534
|
+
}
|
|
7535
|
+
const filterData = col.filter.toSolrData();
|
|
7536
|
+
if (col.facetable && (col.filter.operator === 'in' || col.filter.operator === 'n_in')) {
|
|
7537
|
+
filterData.tagged = true;
|
|
7538
|
+
}
|
|
7539
|
+
request.filterFields.push(filterData);
|
|
7540
|
+
}
|
|
7541
|
+
for (const col of this._model.columns) {
|
|
7542
|
+
if (!col.facetable) {
|
|
7543
|
+
continue;
|
|
7544
|
+
}
|
|
7545
|
+
request.facetFields.push({
|
|
7546
|
+
name: col.id,
|
|
7547
|
+
type: 'FIELD',
|
|
7548
|
+
limit: 100,
|
|
7549
|
+
sort: 'count',
|
|
7550
|
+
minimumCount: 1
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7553
|
+
if (this._searchQuery?.trim().length) {
|
|
7554
|
+
request.queryFields.push({
|
|
7555
|
+
name: '_text_',
|
|
7556
|
+
operation: 'IS',
|
|
7557
|
+
value: termify(this._searchQuery, false)
|
|
7558
|
+
});
|
|
7559
|
+
}
|
|
7560
|
+
return request;
|
|
7561
|
+
}
|
|
7562
|
+
_toDbParams() {
|
|
7563
|
+
const request = {
|
|
7564
|
+
page: this._page - 1,
|
|
7565
|
+
size: this._pageSize,
|
|
7566
|
+
sorts: this._sorts,
|
|
7567
|
+
filterFields: [],
|
|
7568
|
+
queryFields: [],
|
|
7569
|
+
facetFields: []
|
|
7570
|
+
};
|
|
7571
|
+
for (const col of this._model.columns) {
|
|
7572
|
+
if (!col.filter || col.filter.isEmpty() || !col.filter.isValid()) {
|
|
7573
|
+
continue;
|
|
7574
|
+
}
|
|
7575
|
+
request.filterFields.push(col.filter.toDbParams());
|
|
7576
|
+
}
|
|
7577
|
+
if (this._searchQuery?.trim().length) {
|
|
7578
|
+
this._model.columns.filter(col => col.searchable).forEach(col => {
|
|
7579
|
+
request.queryFields.push({
|
|
7580
|
+
name: col.id,
|
|
7581
|
+
operation: 'CONTAINS',
|
|
7582
|
+
value: this._searchQuery,
|
|
7583
|
+
and: false
|
|
7584
|
+
});
|
|
7585
|
+
});
|
|
7586
|
+
}
|
|
7587
|
+
return request;
|
|
7588
|
+
}
|
|
7589
|
+
/**
|
|
7590
|
+
* Fetches data from the API and updates the table.
|
|
7591
|
+
* Shows a loading spinner while fetching, then displays rows on success
|
|
7592
|
+
* or an error snackbar on failure.
|
|
7593
|
+
* Request/response format depends on dataSource.mode (solr, opensearch, db).
|
|
7594
|
+
*/
|
|
7595
|
+
_fetch() {
|
|
7596
|
+
if (this._model.data) {
|
|
7597
|
+
this._data = this._model.data;
|
|
7598
|
+
this._totalItems = this._model.data.length;
|
|
7599
|
+
this._totalPages = Math.ceil(this._model.data.length / this._pageSize);
|
|
7600
|
+
this._dataState = 'success';
|
|
7601
|
+
return;
|
|
7602
|
+
}
|
|
7603
|
+
if (!this._model.dataSource)
|
|
7604
|
+
return;
|
|
7605
|
+
this._dataState = 'loading';
|
|
7606
|
+
let request;
|
|
7607
|
+
if (this._model.dataSource.mode === 'db') {
|
|
7608
|
+
request = this._toDbParams();
|
|
7609
|
+
}
|
|
7610
|
+
else {
|
|
7611
|
+
request = this._toSolrData();
|
|
7612
|
+
}
|
|
7613
|
+
this._model.dataSource.fetch(request)
|
|
7614
|
+
.then(response => {
|
|
7615
|
+
// Parse response based on mode
|
|
7616
|
+
switch (this._model.dataSource?.mode) {
|
|
7617
|
+
case 'opensearch': {
|
|
7618
|
+
throw Error('Opensearch not supported yet');
|
|
7619
|
+
}
|
|
7620
|
+
case 'db': {
|
|
7621
|
+
const res = response;
|
|
7622
|
+
this._data = res.data.content;
|
|
7623
|
+
this._totalItems = res.data.totalElements;
|
|
7624
|
+
this._totalPages = res.data.totalPages;
|
|
7625
|
+
this._pageSize = res.data.size;
|
|
7626
|
+
break;
|
|
7627
|
+
}
|
|
7628
|
+
default: { // solr
|
|
7629
|
+
const res = response;
|
|
7630
|
+
this._data = res.data.content;
|
|
7631
|
+
this._totalItems = res.data.totalElements;
|
|
7632
|
+
this._totalPages = res.data.totalPages;
|
|
7633
|
+
this._pageSize = res.data.size;
|
|
7634
|
+
this._parseFacetResults(res);
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
this._dataState = 'success';
|
|
7638
|
+
this._updateSearchPosition();
|
|
7639
|
+
})
|
|
7640
|
+
.catch(err => {
|
|
7641
|
+
this._dataState = 'error';
|
|
7642
|
+
KRSnackbar.show({
|
|
7643
|
+
message: err instanceof Error ? err.message : 'Failed to load data',
|
|
7644
|
+
type: 'error'
|
|
7645
|
+
});
|
|
7646
|
+
});
|
|
7647
|
+
}
|
|
7648
|
+
_parseFacetResults(response) {
|
|
7649
|
+
if (!response.data.facetFields) {
|
|
7650
|
+
return;
|
|
7651
|
+
}
|
|
7652
|
+
for (const col of this._model.columns) {
|
|
7653
|
+
if (!col.facetable) {
|
|
7654
|
+
continue;
|
|
7655
|
+
}
|
|
7656
|
+
const rawBuckets = response.data.facetFields[col.id];
|
|
7657
|
+
if (!rawBuckets) {
|
|
7658
|
+
this._buckets.set(col.id, []);
|
|
7659
|
+
continue;
|
|
7660
|
+
}
|
|
7661
|
+
const buckets = [];
|
|
7662
|
+
for (const raw of rawBuckets) {
|
|
7663
|
+
// Solr returns boolean facet values as strings — coerce to actual booleans
|
|
7664
|
+
// so they match the filter values stored by toggle().
|
|
7665
|
+
let val = raw.name;
|
|
7666
|
+
if (col.type === 'boolean' && typeof raw.name === 'string') {
|
|
7667
|
+
if (raw.name === 'true') {
|
|
7668
|
+
val = true;
|
|
7669
|
+
}
|
|
7670
|
+
else if (raw.name === 'false') {
|
|
7671
|
+
val = false;
|
|
7672
|
+
}
|
|
7673
|
+
}
|
|
7674
|
+
if (raw.name === null && raw.count > 0) {
|
|
7675
|
+
buckets.unshift({
|
|
7676
|
+
val: null,
|
|
7677
|
+
count: raw.count
|
|
7678
|
+
});
|
|
7679
|
+
}
|
|
7680
|
+
if (raw.name !== null) {
|
|
7681
|
+
buckets.push({
|
|
7682
|
+
val: val,
|
|
7683
|
+
count: raw.count
|
|
7684
|
+
});
|
|
7685
|
+
}
|
|
7686
|
+
}
|
|
7687
|
+
// Bucket sync: ensure selected values appear even with 0 results
|
|
7688
|
+
if (col.filter && (col.filter.operator === 'in' || col.filter.operator === 'n_in') && Array.isArray(col.filter.value)) {
|
|
7689
|
+
for (const selectedVal of col.filter.value) {
|
|
7690
|
+
if (!buckets.some(b => b.val === selectedVal)) {
|
|
7691
|
+
buckets.push({
|
|
7692
|
+
val: selectedVal,
|
|
7693
|
+
count: 0
|
|
7694
|
+
});
|
|
7695
|
+
}
|
|
7696
|
+
}
|
|
7697
|
+
}
|
|
7698
|
+
this._buckets.set(col.id, buckets);
|
|
7699
|
+
}
|
|
7700
|
+
// Trigger re-render since Map mutation doesn't trigger Lit updates
|
|
7701
|
+
this._buckets = new Map(this._buckets);
|
|
7702
|
+
}
|
|
7703
|
+
/**
|
|
7704
|
+
* Sets up auto-refresh so the table automatically fetches fresh data
|
|
7705
|
+
* at a regular interval (useful for dashboards, monitoring views).
|
|
7706
|
+
* Configured via def.refreshInterval in milliseconds.
|
|
7707
|
+
*/
|
|
7708
|
+
_initRefresh() {
|
|
7709
|
+
clearInterval(this._refreshTimer);
|
|
7710
|
+
if (this._model.refreshInterval && this._model.refreshInterval > 0) {
|
|
7711
|
+
this._refreshTimer = window.setInterval(() => {
|
|
7712
|
+
this._fetch();
|
|
7713
|
+
}, this._model.refreshInterval);
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
_handleSearch(e) {
|
|
7717
|
+
const input = e.target;
|
|
7718
|
+
this._searchQuery = input.value;
|
|
7719
|
+
this._page = 1;
|
|
7720
|
+
this._fetch();
|
|
7721
|
+
}
|
|
7722
|
+
_getGridTemplateColumns() {
|
|
7723
|
+
const cols = this.getDisplayedColumns();
|
|
7724
|
+
return cols.map((col) => {
|
|
7725
|
+
// If column has explicit width, use it
|
|
7726
|
+
if (col.width) {
|
|
7727
|
+
return col.width;
|
|
7728
|
+
}
|
|
7729
|
+
// Actions columns: fit content without minimum
|
|
7730
|
+
if (col.type === 'actions') {
|
|
7731
|
+
return 'max-content';
|
|
7732
|
+
}
|
|
7733
|
+
// No width specified - use content-based sizing with minimum
|
|
7734
|
+
return 'minmax(80px, auto)';
|
|
7735
|
+
}).join(' ');
|
|
7736
|
+
}
|
|
7737
|
+
/**
|
|
7738
|
+
* Updates search position to be centered with equal gaps from title and tools.
|
|
7739
|
+
* On first call: resets to flex centering, measures position, then locks with fixed margin.
|
|
7740
|
+
* Subsequent calls are ignored unless _searchPositionLocked is reset (e.g., on resize).
|
|
7741
|
+
*/
|
|
7742
|
+
_updateSearchPosition() {
|
|
7743
|
+
// Skip if already locked (prevents shifts on pagination changes)
|
|
7744
|
+
if (this._searchPositionLocked)
|
|
7745
|
+
return;
|
|
7746
|
+
// In card mode, search is left-aligned via CSS — no position locking needed
|
|
7747
|
+
if (this.variant === 'card')
|
|
7748
|
+
return;
|
|
7749
|
+
const search = this.shadowRoot?.querySelector('.search');
|
|
7750
|
+
const searchField = search?.querySelector('.search-field');
|
|
7751
|
+
if (!search || !searchField)
|
|
7752
|
+
return;
|
|
7753
|
+
// Reset to flex centering
|
|
7754
|
+
search.style.justifyContent = 'center';
|
|
7755
|
+
searchField.style.marginLeft = '';
|
|
7756
|
+
requestAnimationFrame(() => {
|
|
7757
|
+
const searchRect = search.getBoundingClientRect();
|
|
7758
|
+
const fieldRect = searchField.getBoundingClientRect();
|
|
7759
|
+
// Calculate how far from the left of search container the field currently is
|
|
7760
|
+
const currentOffset = fieldRect.left - searchRect.left;
|
|
7761
|
+
// Lock position: switch to flex-start and use fixed margin
|
|
7762
|
+
search.style.justifyContent = 'flex-start';
|
|
7763
|
+
searchField.style.marginLeft = `${currentOffset}px`;
|
|
7764
|
+
// Mark as locked so pagination changes don't shift the search
|
|
7765
|
+
this._searchPositionLocked = true;
|
|
7766
|
+
});
|
|
7767
|
+
}
|
|
7768
|
+
// ----------------------------------------------------------------------------
|
|
7769
|
+
// Columns
|
|
7770
|
+
// ----------------------------------------------------------------------------
|
|
7771
|
+
_toggleColumnPicker() {
|
|
7772
|
+
this._columnPickerOpen = !this._columnPickerOpen;
|
|
7773
|
+
}
|
|
7774
|
+
_toggleColumn(columnId) {
|
|
7775
|
+
if (this._model.displayedColumns.includes(columnId)) {
|
|
7776
|
+
this._model.displayedColumns = this._model.displayedColumns.filter(id => id !== columnId);
|
|
7777
|
+
}
|
|
7778
|
+
else {
|
|
7779
|
+
this._model.displayedColumns = [...this._model.displayedColumns, columnId];
|
|
7780
|
+
}
|
|
7781
|
+
this.requestUpdate();
|
|
7782
|
+
}
|
|
7783
|
+
// Clear any existing text selection on mousedown so we only detect
|
|
7784
|
+
// selections made during this click gesture, not stale selections from elsewhere
|
|
7785
|
+
_handleRowMouseDown() {
|
|
7786
|
+
if (!this._model.rowClickable && !this._model.rowHref) {
|
|
7787
|
+
return;
|
|
7788
|
+
}
|
|
7789
|
+
window.getSelection()?.removeAllRanges();
|
|
7790
|
+
}
|
|
7791
|
+
_handleRowClick(e, row, rowIndex) {
|
|
7792
|
+
if (!this._model.rowClickable && !this._model.rowHref) {
|
|
7793
|
+
return;
|
|
7794
|
+
}
|
|
7795
|
+
const selection = window.getSelection();
|
|
7796
|
+
if (selection && selection.toString().length > 0) {
|
|
7797
|
+
e.preventDefault();
|
|
7798
|
+
return;
|
|
7799
|
+
}
|
|
7800
|
+
this.dispatchEvent(new CustomEvent('row-click', {
|
|
7801
|
+
detail: { row, rowIndex },
|
|
7802
|
+
bubbles: true,
|
|
7803
|
+
composed: true
|
|
7804
|
+
}));
|
|
7805
|
+
}
|
|
7806
|
+
// When a user toggles a column on via the column picker, it gets appended
|
|
7807
|
+
// to _displayedColumns. By mapping over _displayedColumns (not def.columns),
|
|
7808
|
+
// the new column appears at the right edge of the table instead of jumping
|
|
7809
|
+
// back to its original position in the column definition.
|
|
7810
|
+
// Actions columns are always moved to the end.
|
|
7811
|
+
getDisplayedColumns() {
|
|
7812
|
+
return this._model.displayedColumns
|
|
7813
|
+
.map(id => this._model.columns.find(col => col.id === id))
|
|
7814
|
+
.sort((a, b) => {
|
|
7815
|
+
if (a.type === 'actions' && b.type !== 'actions')
|
|
7816
|
+
return 1;
|
|
7817
|
+
if (a.type !== 'actions' && b.type === 'actions')
|
|
7818
|
+
return -1;
|
|
7819
|
+
return 0;
|
|
7820
|
+
});
|
|
7821
|
+
}
|
|
7822
|
+
// ----------------------------------------------------------------------------
|
|
7823
|
+
// Scrolling
|
|
7824
|
+
// ----------------------------------------------------------------------------
|
|
7825
|
+
/**
|
|
7826
|
+
* Scroll event handler that updates scroll flags in real-time as user scrolls.
|
|
7827
|
+
* Updates shadow indicators to show if more content exists left/right.
|
|
7828
|
+
*/
|
|
7829
|
+
_handleScroll(e) {
|
|
7830
|
+
const container = e.target;
|
|
7831
|
+
this._canScrollLeft = container.scrollLeft > 0;
|
|
7832
|
+
this._canScrollRight = container.scrollLeft < container.scrollWidth - container.clientWidth - 1;
|
|
7833
|
+
}
|
|
7834
|
+
/**
|
|
7835
|
+
* Updates scroll state flags for the table content container.
|
|
7836
|
+
* - _canScrollLeft: true if scrolled right (can scroll back left)
|
|
7837
|
+
* - _canScrollRight: true if more content exists to the right
|
|
7838
|
+
* - _canScrollHorizontal: true if content is wider than container
|
|
7839
|
+
* These flags control scroll shadow indicators and CSS classes.
|
|
7840
|
+
*/
|
|
7841
|
+
_updateScrollFlags() {
|
|
7842
|
+
const container = this.shadowRoot?.querySelector('.content');
|
|
7843
|
+
if (container) {
|
|
7844
|
+
this._canScrollLeft = container.scrollLeft > 0;
|
|
7845
|
+
this._canScrollRight = container.scrollWidth > container.clientWidth && container.scrollLeft < container.scrollWidth - container.clientWidth - 1;
|
|
7846
|
+
this._canScrollHorizontal = container.scrollWidth > container.clientWidth;
|
|
7847
|
+
}
|
|
7848
|
+
this.classList.toggle('kr-table--scroll-left-available', this._canScrollLeft);
|
|
7849
|
+
this.classList.toggle('kr-table--scroll-right-available', this._canScrollRight);
|
|
7850
|
+
this.classList.toggle('kr-table--scroll-horizontal-available', this._canScrollHorizontal);
|
|
7851
|
+
this.classList.toggle('kr-table--sticky-left', this.getDisplayedColumns().some(c => c.sticky === 'left'));
|
|
7852
|
+
this.classList.toggle('kr-table--sticky-right', this.getDisplayedColumns().some(c => c.sticky === 'right'));
|
|
7853
|
+
}
|
|
7854
|
+
// ----------------------------------------------------------------------------
|
|
7855
|
+
// Column Resizing
|
|
7856
|
+
// ----------------------------------------------------------------------------
|
|
7857
|
+
_handleResizeStart(e, columnId) {
|
|
7858
|
+
e.preventDefault();
|
|
7859
|
+
const headerCell = this.shadowRoot?.querySelector(`.header-cell[data-column-id="${columnId}"]`);
|
|
7860
|
+
this._resizing = {
|
|
7861
|
+
columnId,
|
|
7862
|
+
startX: e.clientX,
|
|
7863
|
+
startWidth: headerCell?.offsetWidth || 200
|
|
7864
|
+
};
|
|
7865
|
+
document.addEventListener('mousemove', this._handleResizeMove);
|
|
7866
|
+
document.addEventListener('mouseup', this._handleResizeEnd);
|
|
7867
|
+
}
|
|
7868
|
+
// ----------------------------------------------------------------------------
|
|
7869
|
+
// Sorting
|
|
7870
|
+
// ----------------------------------------------------------------------------
|
|
7871
|
+
_handleSortClick(e, column) {
|
|
7872
|
+
if (e.shiftKey) {
|
|
7873
|
+
// Multi-sort: add or cycle existing
|
|
7874
|
+
const existingIndex = this._sorts.findIndex(s => s.sortBy === column.id);
|
|
7875
|
+
if (existingIndex === -1) {
|
|
7876
|
+
this._sorts.push({ sortBy: column.id, sortDirection: 'asc' });
|
|
7877
|
+
}
|
|
7878
|
+
else {
|
|
7879
|
+
const existing = this._sorts[existingIndex];
|
|
7880
|
+
if (existing.sortDirection === 'asc') {
|
|
7881
|
+
existing.sortDirection = 'desc';
|
|
7882
|
+
}
|
|
7883
|
+
else {
|
|
7884
|
+
// on third click, remove sorting for the column
|
|
7885
|
+
this._sorts.splice(existingIndex, 1);
|
|
7886
|
+
}
|
|
7887
|
+
}
|
|
7888
|
+
this.requestUpdate();
|
|
7889
|
+
}
|
|
7890
|
+
else {
|
|
7891
|
+
// Single sort: replace all
|
|
7892
|
+
let existing = null;
|
|
7893
|
+
if (this._sorts.length === 1) {
|
|
7894
|
+
existing = this._sorts.find(s => s.sortBy === column.id);
|
|
7895
|
+
}
|
|
7896
|
+
if (!existing) {
|
|
7897
|
+
this._sorts = [{ sortBy: column.id, sortDirection: 'asc' }];
|
|
7898
|
+
}
|
|
7899
|
+
else if (existing.sortDirection === 'asc') {
|
|
7900
|
+
this._sorts = [{ sortBy: column.id, sortDirection: 'desc' }];
|
|
7901
|
+
}
|
|
7902
|
+
else {
|
|
7903
|
+
this._sorts = [];
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
7906
|
+
this._page = 1;
|
|
7907
|
+
this._fetch();
|
|
7908
|
+
}
|
|
7909
|
+
_renderSortIndicator(column) {
|
|
7910
|
+
if (!column.sortable) {
|
|
7911
|
+
return A;
|
|
7912
|
+
}
|
|
7913
|
+
const sortIndex = this._sorts.findIndex(s => s.sortBy === column.id);
|
|
7914
|
+
if (sortIndex === -1) {
|
|
7915
|
+
// Ghost arrow: visible only on hover via CSS
|
|
7916
|
+
return b `
|
|
7917
|
+
<span class="header-cell__sort" @click=${(e) => this._handleSortClick(e, column)}>
|
|
7918
|
+
<svg class="header-cell__sort-arrow header-cell__sort-arrow--ghost" viewBox="0 0 24 24" fill="currentColor">
|
|
7919
|
+
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
|
|
7920
|
+
</svg>
|
|
7921
|
+
</span>
|
|
7922
|
+
`;
|
|
7923
|
+
}
|
|
7924
|
+
let arrowStyle = {};
|
|
7925
|
+
if (this._sorts[sortIndex].sortDirection === 'desc') {
|
|
7926
|
+
arrowStyle = { transform: 'rotate(180deg)' };
|
|
7927
|
+
}
|
|
7928
|
+
return b `
|
|
7929
|
+
<span class="header-cell__sort" @click=${(e) => this._handleSortClick(e, column)}>
|
|
7930
|
+
<svg class="header-cell__sort-arrow" viewBox="0 0 24 24" fill="currentColor" style=${o$1(arrowStyle)}>
|
|
7931
|
+
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
|
|
7932
|
+
</svg>
|
|
7933
|
+
${this._sorts.length > 1 ? b `
|
|
7934
|
+
<span class="header-cell__sort-priority">${sortIndex + 1}</span>
|
|
7935
|
+
` : A}
|
|
7936
|
+
</span>
|
|
7937
|
+
`;
|
|
7938
|
+
}
|
|
7939
|
+
// ----------------------------------------------------------------------------
|
|
7940
|
+
// Header
|
|
7941
|
+
// ----------------------------------------------------------------------------
|
|
7942
|
+
_handleAction(action) {
|
|
7943
|
+
if (action.href) {
|
|
7944
|
+
return;
|
|
7945
|
+
}
|
|
7946
|
+
this.dispatchEvent(new CustomEvent('action', {
|
|
7947
|
+
detail: { action: action.id },
|
|
7948
|
+
bubbles: true,
|
|
7949
|
+
composed: true
|
|
7950
|
+
}));
|
|
7951
|
+
}
|
|
7952
|
+
// ----------------------------------------------------------------------------
|
|
7953
|
+
// Filter Handlers
|
|
7954
|
+
// ----------------------------------------------------------------------------
|
|
7955
|
+
_handleKqlChange(e, column) {
|
|
7956
|
+
const kql = e.target.value.trim();
|
|
7957
|
+
if (!kql) {
|
|
7958
|
+
column.filter.clear();
|
|
7959
|
+
this.requestUpdate();
|
|
7960
|
+
}
|
|
7961
|
+
else {
|
|
7962
|
+
column.filter.setKql(kql);
|
|
7963
|
+
this.requestUpdate();
|
|
7964
|
+
if (!column.filter.isValid()) {
|
|
7965
|
+
return;
|
|
7966
|
+
}
|
|
7967
|
+
}
|
|
7968
|
+
this._page = 1;
|
|
7969
|
+
this._fetch();
|
|
7970
|
+
}
|
|
7971
|
+
_handleFilterPanelToggle(e, column) {
|
|
7972
|
+
e.stopPropagation();
|
|
7973
|
+
if (this._filterPanelOpened === column.id) {
|
|
7974
|
+
this._filterPanelOpened = null;
|
|
7975
|
+
}
|
|
7976
|
+
else {
|
|
7977
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
7978
|
+
let left = rect.left;
|
|
7979
|
+
if (left + 328 > window.innerWidth) {
|
|
7980
|
+
left = window.innerWidth - 328;
|
|
7981
|
+
}
|
|
7982
|
+
this._filterPanelPos = {
|
|
7983
|
+
top: rect.bottom + 4,
|
|
7984
|
+
left
|
|
7985
|
+
};
|
|
7986
|
+
this._filterPanelOpened = column.id;
|
|
7987
|
+
if (column.facetable) {
|
|
7988
|
+
this._filterPanelTab = 'counts';
|
|
7989
|
+
}
|
|
7990
|
+
else {
|
|
7991
|
+
this._filterPanelTab = 'filter';
|
|
7992
|
+
}
|
|
7993
|
+
}
|
|
7994
|
+
}
|
|
7995
|
+
_handleKqlClear(column) {
|
|
7996
|
+
column.filter.clear();
|
|
7997
|
+
this._page = 1;
|
|
7998
|
+
this._fetch();
|
|
7999
|
+
}
|
|
8000
|
+
_handleFilterClear() {
|
|
8001
|
+
const column = this._model.columns.find(c => c.id === this._filterPanelOpened);
|
|
8002
|
+
if (column) {
|
|
8003
|
+
column.filter.clear();
|
|
8004
|
+
if (column.facetable && !column.filterable) {
|
|
8005
|
+
column.filter.operator = 'in';
|
|
8006
|
+
column.filter.value = [];
|
|
8007
|
+
}
|
|
8008
|
+
}
|
|
8009
|
+
this._filterPanelOpened = null;
|
|
8010
|
+
this._page = 1;
|
|
8011
|
+
this._fetch();
|
|
8012
|
+
}
|
|
8013
|
+
_handleFilterTextKeydown(e, column) {
|
|
8014
|
+
if (e.key === 'Enter') {
|
|
8015
|
+
e.preventDefault();
|
|
8016
|
+
this._handleFilterApply();
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
_handleOperatorChange(e, column) {
|
|
8020
|
+
column.filter.setOperator(e.target.value);
|
|
8021
|
+
this.requestUpdate();
|
|
8022
|
+
}
|
|
8023
|
+
_handleFilterStringChange(e, column) {
|
|
8024
|
+
column.filter.setValue(e.target.value);
|
|
8025
|
+
this.requestUpdate();
|
|
8026
|
+
}
|
|
8027
|
+
_handleFilterNumberChange(e, column) {
|
|
8028
|
+
column.filter.setValue(Number(e.target.value));
|
|
8029
|
+
this.requestUpdate();
|
|
8030
|
+
}
|
|
8031
|
+
_handleFilterDateChange(e, column) {
|
|
8032
|
+
column.filter.setValue(new Date(e.target.value), 'day');
|
|
8033
|
+
this.requestUpdate();
|
|
8034
|
+
}
|
|
8035
|
+
_handleFilterBooleanChange(e, column) {
|
|
8036
|
+
column.filter.setValue(e.target.value === 'true');
|
|
8037
|
+
this.requestUpdate();
|
|
8038
|
+
}
|
|
8039
|
+
_handleFilterDateStartChange(e, column) {
|
|
8040
|
+
column.filter.setStart(new Date(e.target.value), 'day');
|
|
8041
|
+
this.requestUpdate();
|
|
8042
|
+
}
|
|
8043
|
+
_handleFilterDateEndChange(e, column) {
|
|
8044
|
+
column.filter.setEnd(new Date(e.target.value), 'day');
|
|
8045
|
+
this.requestUpdate();
|
|
8046
|
+
}
|
|
8047
|
+
_handleFilterNumberStartChange(e, column) {
|
|
8048
|
+
column.filter.setStart(Number(e.target.value));
|
|
8049
|
+
this.requestUpdate();
|
|
8050
|
+
}
|
|
8051
|
+
_handleFilterNumberEndChange(e, column) {
|
|
8052
|
+
column.filter.setEnd(Number(e.target.value));
|
|
8053
|
+
this.requestUpdate();
|
|
8054
|
+
}
|
|
8055
|
+
_handleFilterListChange(e, column) {
|
|
8056
|
+
const items = e.target.value.split(',').map((v) => v.trim()).filter((v) => v !== '');
|
|
8057
|
+
if (column.type === 'number') {
|
|
8058
|
+
column.filter.setValue(items.map((v) => Number(v)));
|
|
8059
|
+
}
|
|
8060
|
+
else {
|
|
8061
|
+
column.filter.setValue(items);
|
|
8062
|
+
}
|
|
8063
|
+
this.requestUpdate();
|
|
8064
|
+
}
|
|
8065
|
+
_handleFilterApply() {
|
|
8066
|
+
this._filterPanelOpened = null;
|
|
8067
|
+
this._page = 1;
|
|
8068
|
+
this._fetch();
|
|
8069
|
+
}
|
|
8070
|
+
_handleFilterPanelTabChange(e) {
|
|
8071
|
+
this._filterPanelTab = e.detail.activeTabId;
|
|
8072
|
+
}
|
|
8073
|
+
_handleBucketToggle(e, column, bucket) {
|
|
8074
|
+
column.filter.toggle(bucket.val);
|
|
8075
|
+
this._page = 1;
|
|
8076
|
+
this._fetch();
|
|
8077
|
+
}
|
|
8078
|
+
// ----------------------------------------------------------------------------
|
|
8079
|
+
// Rendering
|
|
8080
|
+
// ----------------------------------------------------------------------------
|
|
8081
|
+
_renderCellContent(column, row, rowIndex) {
|
|
8082
|
+
const value = row[column.id];
|
|
8083
|
+
if (column.render) {
|
|
8084
|
+
// Use slot to project content from light DOM so external styles apply
|
|
8085
|
+
return b `<slot name="cell-${rowIndex}-${column.id}"></slot>`;
|
|
8086
|
+
}
|
|
8087
|
+
if (value === null || value === undefined) {
|
|
8088
|
+
return '';
|
|
8089
|
+
}
|
|
8090
|
+
switch (column.type) {
|
|
8091
|
+
case 'number':
|
|
8092
|
+
if (column.format === 'currency' && typeof value === 'number') {
|
|
8093
|
+
return value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
|
|
8094
|
+
}
|
|
8095
|
+
return String(value);
|
|
8096
|
+
case 'date': {
|
|
8097
|
+
let date;
|
|
8098
|
+
if (value instanceof Date) {
|
|
8099
|
+
date = value;
|
|
8100
|
+
}
|
|
8101
|
+
else if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(value)) {
|
|
8102
|
+
// MySQL datetime format (UTC): "2026-01-28 01:33:44:517"
|
|
8103
|
+
// Replace last colon before ms with dot, append Z for UTC
|
|
8104
|
+
const isoString = value.replace(/(\d{2}:\d{2}:\d{2}):(\d+)$/, '$1.$2').replace(' ', 'T') + 'Z';
|
|
8105
|
+
date = new Date(isoString);
|
|
8106
|
+
}
|
|
8107
|
+
else {
|
|
8108
|
+
date = new Date(value);
|
|
8109
|
+
}
|
|
8110
|
+
// Show date and time for datetime values in UTC
|
|
8111
|
+
return date.toLocaleString(undefined, {
|
|
8112
|
+
year: 'numeric', month: 'short', day: 'numeric',
|
|
8113
|
+
hour: 'numeric', minute: '2-digit',
|
|
8114
|
+
timeZone: 'UTC'
|
|
8115
|
+
});
|
|
8116
|
+
}
|
|
8117
|
+
case 'boolean':
|
|
8118
|
+
if (value === true)
|
|
8119
|
+
return 'Yes';
|
|
8120
|
+
if (value === false)
|
|
8121
|
+
return 'No';
|
|
8122
|
+
return '';
|
|
8123
|
+
default:
|
|
8124
|
+
return String(value);
|
|
8125
|
+
}
|
|
8126
|
+
}
|
|
8127
|
+
/**
|
|
8128
|
+
* Returns CSS classes for a header cell based on column config.
|
|
8129
|
+
*/
|
|
8130
|
+
_getHeaderCellClasses(column, index) {
|
|
8131
|
+
return {
|
|
8132
|
+
'header-cell': true,
|
|
8133
|
+
'header-cell--sortable': !!column.sortable,
|
|
8134
|
+
'header-cell--align-center': column.align === 'center',
|
|
8135
|
+
'header-cell--align-right': column.align === 'right',
|
|
8136
|
+
'header-cell--sticky-left': column.sticky === 'left',
|
|
8137
|
+
'header-cell--sticky-left-last': column.sticky === 'left' &&
|
|
8138
|
+
!this.getDisplayedColumns().slice(index + 1).some(c => c.sticky === 'left'),
|
|
8139
|
+
'header-cell--sticky-right': column.sticky === 'right',
|
|
8140
|
+
'header-cell--sticky-right-first': column.sticky === 'right' &&
|
|
8141
|
+
!this.getDisplayedColumns().slice(0, index).some(c => c.sticky === 'right')
|
|
8142
|
+
};
|
|
8143
|
+
}
|
|
8144
|
+
/**
|
|
8145
|
+
* Returns CSS classes for a table cell based on column config:
|
|
8146
|
+
* - Alignment (center, right)
|
|
8147
|
+
* - Sticky positioning (left, right)
|
|
8148
|
+
* - Border classes for the last left-sticky or first right-sticky column
|
|
8149
|
+
*/
|
|
8150
|
+
_getCellClasses(column, index) {
|
|
8151
|
+
return {
|
|
8152
|
+
'cell': true,
|
|
8153
|
+
'cell--actions': column.type === 'actions',
|
|
8154
|
+
'cell--align-center': column.align === 'center',
|
|
8155
|
+
'cell--align-right': column.align === 'right',
|
|
8156
|
+
'cell--sticky-left': column.sticky === 'left',
|
|
8157
|
+
'cell--sticky-left-last': column.sticky === 'left' &&
|
|
8158
|
+
!this.getDisplayedColumns().slice(index + 1).some(c => c.sticky === 'left'),
|
|
8159
|
+
'cell--sticky-right': column.sticky === 'right',
|
|
8160
|
+
'cell--sticky-right-first': column.sticky === 'right' &&
|
|
8161
|
+
!this.getDisplayedColumns().slice(0, index).some(c => c.sticky === 'right')
|
|
8162
|
+
};
|
|
8163
|
+
}
|
|
8164
|
+
/**
|
|
8165
|
+
* Returns inline styles for a table cell:
|
|
8166
|
+
* - Width (from column config or default 150px)
|
|
8167
|
+
* - Min-width (if specified)
|
|
8168
|
+
* - Left/right offset for sticky columns (calculated from widths of preceding sticky columns)
|
|
8169
|
+
*/
|
|
8170
|
+
_getCellStyle(column, index) {
|
|
8171
|
+
const styles = {};
|
|
8172
|
+
if (column.sticky === 'left') {
|
|
8173
|
+
let leftOffset = 0;
|
|
8174
|
+
for (let i = 0; i < index; i++) {
|
|
8175
|
+
const col = this.getDisplayedColumns()[i];
|
|
8176
|
+
if (col.sticky === 'left') {
|
|
8177
|
+
leftOffset += parseInt(col.width || '0', 10);
|
|
8178
|
+
}
|
|
8179
|
+
}
|
|
8180
|
+
styles.left = `${leftOffset}px`;
|
|
8181
|
+
}
|
|
8182
|
+
if (column.sticky === 'right') {
|
|
8183
|
+
let rightOffset = 0;
|
|
8184
|
+
for (let i = index + 1; i < this.getDisplayedColumns().length; i++) {
|
|
8185
|
+
const col = this.getDisplayedColumns()[i];
|
|
8186
|
+
if (col.sticky === 'right') {
|
|
8187
|
+
rightOffset += parseInt(col.width || '0', 10);
|
|
8188
|
+
}
|
|
8189
|
+
}
|
|
8190
|
+
styles.right = `${rightOffset}px`;
|
|
8191
|
+
}
|
|
8192
|
+
return styles;
|
|
8193
|
+
}
|
|
8194
|
+
/**
|
|
8195
|
+
* Renders the pagination controls:
|
|
8196
|
+
* - Previous page arrow (disabled on first page)
|
|
8197
|
+
* - Range text showing "1-50 of 150" format
|
|
8198
|
+
* - Next page arrow (disabled on last page)
|
|
8199
|
+
*
|
|
8200
|
+
* Hidden when there's no data or all data fits on one page.
|
|
8201
|
+
*/
|
|
8202
|
+
_renderPagination() {
|
|
8203
|
+
const start = (this._page - 1) * this._pageSize + 1;
|
|
8204
|
+
const end = Math.min(this._page * this._pageSize, this._totalItems);
|
|
8205
|
+
return b `
|
|
8206
|
+
<div class="pagination">
|
|
8207
|
+
<span
|
|
8208
|
+
class="pagination-icon ${this._page === 1 ? 'pagination-icon--disabled' : ''}"
|
|
8209
|
+
@click=${this.goToPrevPage}
|
|
8210
|
+
>
|
|
8211
|
+
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>
|
|
8212
|
+
</span>
|
|
8213
|
+
<span class="pagination-info">${start}-${end} of ${this._totalItems}</span>
|
|
8214
|
+
<span
|
|
8215
|
+
class="pagination-icon ${this._page === this._totalPages ? 'pagination-icon--disabled' : ''}"
|
|
8216
|
+
@click=${this.goToNextPage}
|
|
8217
|
+
>
|
|
8218
|
+
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
|
|
8219
|
+
</span>
|
|
8220
|
+
</div>
|
|
8221
|
+
`;
|
|
8222
|
+
}
|
|
8223
|
+
/** Renders the card title block (title + description) above the toolbar in card mode. */
|
|
8224
|
+
_renderCardHeader() {
|
|
8225
|
+
if (this.variant !== 'card')
|
|
8226
|
+
return A;
|
|
8227
|
+
if (!this._model.title && !this._model.description)
|
|
8228
|
+
return A;
|
|
8229
|
+
return b `
|
|
8230
|
+
<div class="card-header">
|
|
8231
|
+
${this._model.title ? b `<h2 class="card-header__title">${this._model.title}</h2>` : A}
|
|
8232
|
+
${this._model.description ? b `<p class="card-header__description">${this._model.description}</p>` : A}
|
|
8233
|
+
</div>
|
|
8234
|
+
`;
|
|
8235
|
+
}
|
|
8236
|
+
/**
|
|
8237
|
+
* Renders the header toolbar containing:
|
|
8238
|
+
* - Title (left, default variant only)
|
|
8239
|
+
* - Search bar with view selector dropdown (center, or left-aligned in card variant)
|
|
8240
|
+
* - Tools (right): page navigation, refresh button, column visibility picker, actions dropdown
|
|
8241
|
+
*
|
|
8242
|
+
* Hidden when there's no title, no actions, and data fits on one page.
|
|
8243
|
+
*/
|
|
8244
|
+
_renderHeader() {
|
|
8245
|
+
if (!this._model.title && !this._model.actions?.length && this._totalPages <= 1) {
|
|
8246
|
+
return A;
|
|
8247
|
+
}
|
|
8248
|
+
return b `
|
|
8249
|
+
<div class="header">
|
|
8250
|
+
${this._model.title && this.variant !== 'card' ? b `<div class="title">${this._model.title}</div>` : A}
|
|
8251
|
+
${this._model.dataSource?.mode === 'db' && !this._model.columns.some(col => col.searchable) ? b `<div class="search"></div>` : b `
|
|
8252
|
+
<div class="search">
|
|
8253
|
+
<!-- TODO: Saved views dropdown
|
|
8254
|
+
<div class="views">
|
|
8255
|
+
<span>Default View</span>
|
|
8256
|
+
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg>
|
|
8257
|
+
</div>
|
|
8258
|
+
-->
|
|
8259
|
+
<div class="search-field">
|
|
8260
|
+
<svg class="search-icon" viewBox="0 -960 960 960" fill="currentColor"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg>
|
|
8261
|
+
<input
|
|
8262
|
+
type="text"
|
|
8263
|
+
class="search-input"
|
|
8264
|
+
placeholder="Search..."
|
|
8265
|
+
.value=${this._searchQuery}
|
|
8266
|
+
@input=${this._handleSearch}
|
|
8267
|
+
/>
|
|
8268
|
+
</div>
|
|
8269
|
+
</div>
|
|
8270
|
+
`}
|
|
8271
|
+
<div class="tools">
|
|
8272
|
+
${this._renderPagination()}
|
|
8273
|
+
<span class="refresh" title="Refresh" @click=${() => this.refresh()}>
|
|
8274
|
+
<svg viewBox="0 -960 960 960" fill="currentColor"><path d="M480-160q-134 0-227-93t-93-227q0-134 93-227t227-93q69 0 132 28.5T720-690v-110h80v280H520v-80h168q-32-56-87.5-88T480-720q-100 0-170 70t-70 170q0 100 70 170t170 70q77 0 139-44t87-116h84q-28 106-114 173t-196 67Z"/></svg>
|
|
8275
|
+
</span>
|
|
8276
|
+
<div class="column-picker-wrapper">
|
|
8277
|
+
<span class="header-icon" title="Columns" @click=${this._toggleColumnPicker}>
|
|
8278
|
+
<svg viewBox="0 -960 960 960" fill="currentColor"><path d="M121-280v-400q0-33 23.5-56.5T201-760h559q33 0 56.5 23.5T840-680v400q0 33-23.5 56.5T760-200H201q-33 0-56.5-23.5T121-280Zm79 0h133v-400H200v400Zm213 0h133v-400H413v400Zm213 0h133v-400H626v400Z"/></svg>
|
|
8279
|
+
</span>
|
|
8280
|
+
<div class="column-picker ${this._columnPickerOpen ? 'open' : ''}">
|
|
8281
|
+
${[...this._model.columns].filter(col => col.type !== 'actions').sort((a, b) => (a.label ?? a.id).localeCompare(b.label ?? b.id)).map(col => b `
|
|
8282
|
+
<div class="column-picker-item" @click=${() => this._toggleColumn(col.id)}>
|
|
8283
|
+
<div class="column-picker-checkbox ${this._model.displayedColumns.includes(col.id) ? 'checked' : ''}">
|
|
8284
|
+
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
|
|
8285
|
+
</div>
|
|
8286
|
+
<span class="column-picker-label">${col.label ?? col.id}</span>
|
|
8287
|
+
</div>
|
|
8288
|
+
`)}
|
|
8289
|
+
</div>
|
|
8290
|
+
</div>
|
|
8291
|
+
${this._model.actions?.length === 1 ? b `
|
|
8292
|
+
<kr-button
|
|
8293
|
+
class="actions"
|
|
8294
|
+
.href=${this._model.actions[0].href}
|
|
8295
|
+
.target=${this._model.actions[0].target}
|
|
8296
|
+
@click=${() => this._handleAction(this._model.actions[0])}
|
|
8297
|
+
>
|
|
8298
|
+
${this._model.actions[0].label}
|
|
8299
|
+
</kr-button>
|
|
8300
|
+
` : this._model.actions?.length ? b `
|
|
8301
|
+
<kr-button
|
|
8302
|
+
class="actions"
|
|
8303
|
+
.options=${this._model.actions.map(a => ({ id: a.id, label: a.label }))}
|
|
8304
|
+
@option-select=${(e) => this._handleAction({ id: e.detail.id, label: e.detail.label })}
|
|
8305
|
+
>
|
|
8306
|
+
Actions
|
|
8307
|
+
</kr-button>
|
|
8308
|
+
` : A}
|
|
8309
|
+
</div>
|
|
8310
|
+
</div>
|
|
8311
|
+
`;
|
|
8312
|
+
}
|
|
8313
|
+
/** Renders status message (loading, error, empty) */
|
|
8314
|
+
_renderStatus() {
|
|
8315
|
+
if (this._dataState === 'loading' && this._data.length === 0) {
|
|
8316
|
+
return b `<div class="status">Loading...</div>`;
|
|
8317
|
+
}
|
|
8318
|
+
if (this._dataState === 'error' && this._data.length === 0) {
|
|
8319
|
+
return b `<div class="status status--error">Error loading data</div>`;
|
|
8320
|
+
}
|
|
8321
|
+
if (this._data.length === 0) {
|
|
8322
|
+
return b `<div class="status">No data available</div>`;
|
|
8323
|
+
}
|
|
8324
|
+
return A;
|
|
8325
|
+
}
|
|
8326
|
+
_renderFilterPanel() {
|
|
8327
|
+
if (!this._filterPanelOpened) {
|
|
8328
|
+
return A;
|
|
8329
|
+
}
|
|
8330
|
+
const column = this._model.columns.find(c => c.id === this._filterPanelOpened);
|
|
8331
|
+
// Build filter content (operator + value input)
|
|
8332
|
+
let valueInput = b ``;
|
|
8333
|
+
if (column.filter.operator === 'empty' || column.filter.operator === 'n_empty') {
|
|
8334
|
+
valueInput = b `
|
|
8335
|
+
<input
|
|
8336
|
+
type="text"
|
|
8337
|
+
class="filter-panel__input"
|
|
8338
|
+
disabled
|
|
8339
|
+
.value=${column.filter.text}
|
|
8340
|
+
/>
|
|
8341
|
+
`;
|
|
8342
|
+
}
|
|
8343
|
+
else if (column.filter.operator === 'between' && column.type === 'date') {
|
|
8344
|
+
valueInput = b `
|
|
8345
|
+
<input
|
|
8346
|
+
type="date"
|
|
8347
|
+
class="filter-panel__input"
|
|
8348
|
+
.valueAsDate=${column.filter.value?.start ?? null}
|
|
8349
|
+
@change=${(e) => this._handleFilterDateStartChange(e, column)}
|
|
8350
|
+
/>
|
|
8351
|
+
<input
|
|
8352
|
+
type="date"
|
|
8353
|
+
class="filter-panel__input"
|
|
8354
|
+
.valueAsDate=${column.filter.value?.end ?? null}
|
|
8355
|
+
@change=${(e) => this._handleFilterDateEndChange(e, column)}
|
|
8356
|
+
/>
|
|
8357
|
+
`;
|
|
8358
|
+
}
|
|
8359
|
+
else if (column.filter.operator === 'between' && column.type === 'number') {
|
|
8360
|
+
valueInput = b `
|
|
8361
|
+
<input
|
|
8362
|
+
type="number"
|
|
8363
|
+
class="filter-panel__input"
|
|
8364
|
+
placeholder="Start"
|
|
8365
|
+
.value=${column.filter.value?.start ?? ''}
|
|
8366
|
+
@input=${(e) => this._handleFilterNumberStartChange(e, column)}
|
|
8367
|
+
@keydown=${(e) => this._handleFilterTextKeydown(e, column)}
|
|
8368
|
+
/>
|
|
8369
|
+
<input
|
|
8370
|
+
type="number"
|
|
8371
|
+
class="filter-panel__input"
|
|
8372
|
+
placeholder="End"
|
|
8373
|
+
.value=${column.filter.value?.end ?? ''}
|
|
8374
|
+
@input=${(e) => this._handleFilterNumberEndChange(e, column)}
|
|
8375
|
+
@keydown=${(e) => this._handleFilterTextKeydown(e, column)}
|
|
8376
|
+
/>
|
|
8377
|
+
`;
|
|
8378
|
+
}
|
|
8379
|
+
else if (column.filter.operator === 'in' || column.filter.operator === 'n_in') {
|
|
8380
|
+
valueInput = b `
|
|
8381
|
+
<textarea
|
|
8382
|
+
class="filter-panel__textarea"
|
|
8383
|
+
rows="3"
|
|
8384
|
+
placeholder="Values (comma-separated)"
|
|
8385
|
+
.value=${column.filter.text}
|
|
8386
|
+
@input=${(e) => this._handleFilterListChange(e, column)}
|
|
8387
|
+
@keydown=${(e) => this._handleFilterTextKeydown(e, column)}
|
|
8388
|
+
></textarea>
|
|
8389
|
+
`;
|
|
8390
|
+
}
|
|
8391
|
+
else if (column.type === 'boolean') {
|
|
8392
|
+
valueInput = b `
|
|
8393
|
+
<kr-select-field
|
|
8394
|
+
placeholder="Value"
|
|
8395
|
+
.value=${String(column.filter.value ?? '')}
|
|
8396
|
+
@change=${(e) => this._handleFilterBooleanChange(e, column)}
|
|
8397
|
+
>
|
|
8398
|
+
<kr-select-option value="true">Yes</kr-select-option>
|
|
8399
|
+
<kr-select-option value="false">No</kr-select-option>
|
|
8400
|
+
</kr-select-field>
|
|
8401
|
+
`;
|
|
8402
|
+
}
|
|
8403
|
+
else if (column.type === 'date') {
|
|
8404
|
+
valueInput = b `
|
|
8405
|
+
<input
|
|
8406
|
+
type="date"
|
|
8407
|
+
class="filter-panel__input"
|
|
8408
|
+
.valueAsDate=${column.filter.value}
|
|
8409
|
+
@change=${(e) => this._handleFilterDateChange(e, column)}
|
|
8410
|
+
/>
|
|
8411
|
+
`;
|
|
8412
|
+
}
|
|
8413
|
+
else if (column.type === 'number') {
|
|
8414
|
+
valueInput = b `
|
|
8415
|
+
<input
|
|
8416
|
+
type="number"
|
|
8417
|
+
class="filter-panel__input"
|
|
8418
|
+
placeholder="Value"
|
|
8419
|
+
min="0"
|
|
8420
|
+
.value=${column.filter.text}
|
|
8421
|
+
@input=${(e) => this._handleFilterNumberChange(e, column)}
|
|
8422
|
+
@keydown=${(e) => this._handleFilterTextKeydown(e, column)}
|
|
8423
|
+
/>
|
|
8424
|
+
`;
|
|
8425
|
+
}
|
|
8426
|
+
else {
|
|
8427
|
+
valueInput = b `
|
|
8428
|
+
<input
|
|
8429
|
+
type="text"
|
|
8430
|
+
class="filter-panel__input"
|
|
8431
|
+
placeholder="Value"
|
|
8432
|
+
.value=${column.filter.text}
|
|
8433
|
+
@input=${(e) => this._handleFilterStringChange(e, column)}
|
|
8434
|
+
@keydown=${(e) => this._handleFilterTextKeydown(e, column)}
|
|
8435
|
+
/>
|
|
8436
|
+
`;
|
|
8437
|
+
}
|
|
8438
|
+
const filterContent = b `
|
|
8439
|
+
<div class="filter-panel__content">
|
|
8440
|
+
<kr-select-field
|
|
8441
|
+
.value=${column.filter.operator}
|
|
8442
|
+
@change=${(e) => this._handleOperatorChange(e, column)}
|
|
8443
|
+
>
|
|
8444
|
+
${getOperatorsForType(column.type).map(op => b `
|
|
8445
|
+
<kr-select-option value=${op.key}>${op.label}</kr-select-option>
|
|
8446
|
+
`)}
|
|
8447
|
+
</kr-select-field>
|
|
8448
|
+
${valueInput}
|
|
8449
|
+
</div>
|
|
8450
|
+
`;
|
|
8451
|
+
// Build bucket list content
|
|
8452
|
+
const buckets = this._buckets.get(column.id) || [];
|
|
8453
|
+
let bucketContent;
|
|
8454
|
+
if (!buckets.length) {
|
|
8455
|
+
bucketContent = b `<div class="bucket-empty">No data</div>`;
|
|
8456
|
+
}
|
|
8457
|
+
else {
|
|
8458
|
+
bucketContent = b `
|
|
8459
|
+
<div class="buckets">
|
|
8460
|
+
${buckets.map(bucket => {
|
|
8461
|
+
let bucketLabel = '(Empty)';
|
|
8462
|
+
if (bucket.val !== null && bucket.val !== undefined) {
|
|
8463
|
+
if (column.type === 'boolean') {
|
|
8464
|
+
if (bucket.val === true || bucket.val === 'true') {
|
|
8465
|
+
bucketLabel = 'Yes';
|
|
8466
|
+
}
|
|
8467
|
+
else {
|
|
8468
|
+
bucketLabel = 'No';
|
|
8469
|
+
}
|
|
8470
|
+
}
|
|
8471
|
+
else {
|
|
8472
|
+
bucketLabel = String(bucket.val);
|
|
8473
|
+
}
|
|
8474
|
+
}
|
|
8475
|
+
// When using n_in, the user sees all buckets checked by default and unchecks
|
|
8476
|
+
// the ones they want to hide. Under the hood, has() returns true for values
|
|
8477
|
+
// in the exclusion list, so we invert the check state for n_in.
|
|
8478
|
+
let checked = column.filter.has(bucket.val);
|
|
8479
|
+
if (column.filter.operator === 'n_in') {
|
|
8480
|
+
checked = !checked;
|
|
8481
|
+
}
|
|
8482
|
+
let checkIcon = A;
|
|
8483
|
+
if (checked) {
|
|
8484
|
+
checkIcon = b `
|
|
8485
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
8486
|
+
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/>
|
|
8487
|
+
</svg>
|
|
8488
|
+
`;
|
|
8489
|
+
}
|
|
8490
|
+
return b `
|
|
8491
|
+
<div
|
|
8492
|
+
class="bucket"
|
|
8493
|
+
@click=${(e) => this._handleBucketToggle(e, column, bucket)}
|
|
8494
|
+
>
|
|
8495
|
+
<div class=${e$1({
|
|
8496
|
+
'bucket__checkbox': true,
|
|
8497
|
+
'bucket__checkbox--checked': checked
|
|
8498
|
+
})}>
|
|
8499
|
+
${checkIcon}
|
|
8500
|
+
</div>
|
|
8501
|
+
<span class="bucket__label">${bucketLabel}</span>
|
|
8502
|
+
<span class="bucket__count">${bucket.count}</span>
|
|
8503
|
+
</div>
|
|
8504
|
+
`;
|
|
8505
|
+
})}
|
|
8506
|
+
</div>
|
|
8507
|
+
`;
|
|
8508
|
+
}
|
|
8509
|
+
// Build panel body — tabs if both filterable+facetable, otherwise just the relevant content
|
|
8510
|
+
let panelBody;
|
|
8511
|
+
if (column.facetable && column.filterable) {
|
|
8512
|
+
panelBody = b `
|
|
8513
|
+
<kr-tab-group
|
|
8514
|
+
size="small"
|
|
8515
|
+
active-tab-id=${this._filterPanelTab}
|
|
8516
|
+
@tab-change=${(e) => this._handleFilterPanelTabChange(e)}
|
|
8517
|
+
>
|
|
8518
|
+
<kr-tab id="filter" label="Filter">
|
|
8519
|
+
${filterContent}
|
|
8520
|
+
</kr-tab>
|
|
8521
|
+
<kr-tab id="counts" label="Counts">
|
|
8522
|
+
${bucketContent}
|
|
8523
|
+
</kr-tab>
|
|
8524
|
+
</kr-tab-group>
|
|
8525
|
+
`;
|
|
8526
|
+
}
|
|
8527
|
+
else if (column.facetable) {
|
|
8528
|
+
panelBody = bucketContent;
|
|
8529
|
+
}
|
|
8530
|
+
else {
|
|
8531
|
+
panelBody = filterContent;
|
|
8532
|
+
}
|
|
8533
|
+
return b `
|
|
8534
|
+
<div
|
|
8535
|
+
class="filter-panel"
|
|
8536
|
+
style=${o$1({
|
|
8537
|
+
top: this._filterPanelPos.top + 'px',
|
|
8538
|
+
left: this._filterPanelPos.left + 'px'
|
|
8539
|
+
})}
|
|
8540
|
+
>
|
|
8541
|
+
${panelBody}
|
|
8542
|
+
<div class="filter-panel__actions">
|
|
8543
|
+
<kr-button variant="outline" color="secondary" size="small" @click=${this._handleFilterClear}>
|
|
8544
|
+
Clear
|
|
8545
|
+
</kr-button>
|
|
8546
|
+
<kr-button size="small" @click=${this._handleFilterApply}>
|
|
8547
|
+
Apply
|
|
8548
|
+
</kr-button>
|
|
8549
|
+
</div>
|
|
8550
|
+
</div>
|
|
8551
|
+
`;
|
|
8552
|
+
}
|
|
8553
|
+
/**
|
|
8554
|
+
* Renders filter row below column headers.
|
|
8555
|
+
* Only displays for columns with filterable: true.
|
|
8556
|
+
*/
|
|
8557
|
+
_renderFilterRow() {
|
|
8558
|
+
const columns = this.getDisplayedColumns();
|
|
8559
|
+
if (!columns.some(col => col.filterable || col.facetable)) {
|
|
8560
|
+
return A;
|
|
8561
|
+
}
|
|
8562
|
+
return b `
|
|
8563
|
+
<div class="filter-row">
|
|
8564
|
+
${columns.map((col, i) => {
|
|
8565
|
+
if (!col.filterable && !col.facetable) {
|
|
8566
|
+
return b `<div
|
|
8567
|
+
class=${e$1({
|
|
8568
|
+
'filter-cell': true,
|
|
8569
|
+
'filter-cell--sticky-left': col.sticky === 'left',
|
|
8570
|
+
'filter-cell--sticky-right': col.sticky === 'right',
|
|
8571
|
+
'filter-cell--sticky-right-first': col.sticky === 'right' &&
|
|
8572
|
+
!columns.slice(0, i).some((c) => c.sticky === 'right')
|
|
8573
|
+
})}
|
|
8574
|
+
style=${o$1(this._getCellStyle(col, i))}
|
|
8575
|
+
></div>`;
|
|
8576
|
+
}
|
|
8577
|
+
return b `
|
|
8578
|
+
<div
|
|
8579
|
+
class=${e$1({
|
|
8580
|
+
'filter-cell': true,
|
|
8581
|
+
'filter-cell--sticky-left': col.sticky === 'left',
|
|
8582
|
+
'filter-cell--sticky-right': col.sticky === 'right',
|
|
8583
|
+
'filter-cell--sticky-right-first': col.sticky === 'right' &&
|
|
8584
|
+
!columns.slice(0, i).some((c) => c.sticky === 'right')
|
|
8585
|
+
})}
|
|
8586
|
+
style=${o$1(this._getCellStyle(col, i))}
|
|
8587
|
+
>
|
|
8588
|
+
<div class="filter-cell__wrapper">
|
|
8589
|
+
<input
|
|
8590
|
+
type="text"
|
|
8591
|
+
class=${e$1({
|
|
8592
|
+
'filter-cell__input': true,
|
|
8593
|
+
'filter-cell__input--invalid': !col.filter.isValid()
|
|
8594
|
+
})}
|
|
8595
|
+
.value=${col.filter.kql}
|
|
8596
|
+
@change=${(e) => this._handleKqlChange(e, col)}
|
|
8597
|
+
/>
|
|
8598
|
+
${col.filter?.kql?.length > 0 ? b `
|
|
8599
|
+
<button
|
|
8600
|
+
class="filter-cell__clear"
|
|
8601
|
+
@click=${() => this._handleKqlClear(col)}
|
|
8602
|
+
>
|
|
8603
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
8604
|
+
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
|
|
8605
|
+
</svg>
|
|
8606
|
+
</button>
|
|
8607
|
+
` : A}
|
|
8608
|
+
<button
|
|
8609
|
+
class=${e$1({
|
|
8610
|
+
'filter-cell__advanced': true,
|
|
8611
|
+
'filter-cell__advanced--opened': this._filterPanelOpened === col.id
|
|
8612
|
+
})}
|
|
8613
|
+
@click=${(e) => this._handleFilterPanelToggle(e, col)}
|
|
8614
|
+
>
|
|
8615
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
8616
|
+
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
|
|
8617
|
+
</svg>
|
|
8618
|
+
</button>
|
|
8619
|
+
</div>
|
|
8620
|
+
</div>
|
|
8621
|
+
`;
|
|
8622
|
+
})}
|
|
8623
|
+
</div>
|
|
8624
|
+
`;
|
|
8625
|
+
}
|
|
8626
|
+
/** Renders the scrollable data grid with column headers and rows. */
|
|
8627
|
+
_renderTable() {
|
|
8628
|
+
return b `
|
|
8629
|
+
<div class="wrapper">
|
|
8630
|
+
<div class="overlay-left"></div>
|
|
8631
|
+
<div class="overlay-right"></div>
|
|
8632
|
+
${this._renderStatus()}
|
|
8633
|
+
<div class="content" @scroll=${this._handleScroll}>
|
|
8634
|
+
<div class="table" style="grid-template-columns: ${this._getGridTemplateColumns()}">
|
|
8635
|
+
<div class="header-row">
|
|
8636
|
+
${this.getDisplayedColumns().map((col, i) => b `
|
|
8637
|
+
<div
|
|
8638
|
+
class=${e$1(this._getHeaderCellClasses(col, i))}
|
|
8639
|
+
style=${o$1(this._getCellStyle(col, i))}
|
|
8640
|
+
data-column-id=${col.id}
|
|
8641
|
+
>
|
|
8642
|
+
<span class="header-cell__label">${col.label ?? col.id}</span>
|
|
8643
|
+
${this._renderSortIndicator(col)}
|
|
8644
|
+
${col.resizable !== false ? b `<div
|
|
8645
|
+
class="header-cell__resize"
|
|
8646
|
+
@mousedown=${(e) => this._handleResizeStart(e, col.id)}
|
|
8647
|
+
></div>` : A}
|
|
8648
|
+
</div>
|
|
8649
|
+
`)}
|
|
8650
|
+
</div>
|
|
8651
|
+
${this._renderFilterRow()}
|
|
8652
|
+
${this._data.map((row, rowIndex) => {
|
|
8653
|
+
const cells = this.getDisplayedColumns().map((col, i) => b `
|
|
8654
|
+
<div
|
|
8655
|
+
class=${e$1(this._getCellClasses(col, i))}
|
|
8656
|
+
style=${o$1(this._getCellStyle(col, i))}
|
|
8657
|
+
data-column-id=${col.id}
|
|
8658
|
+
>
|
|
8659
|
+
${this._renderCellContent(col, row, rowIndex)}
|
|
8660
|
+
</div>
|
|
8661
|
+
`);
|
|
8662
|
+
if (this._model.rowHref) {
|
|
8663
|
+
return b `
|
|
8664
|
+
<a
|
|
8665
|
+
href=${this._model.rowHref(row)}
|
|
8666
|
+
draggable="false"
|
|
8667
|
+
class=${e$1({ 'row': true, 'row--clickable': true, 'row--link': true })}
|
|
8668
|
+
@mousedown=${() => this._handleRowMouseDown()}
|
|
8669
|
+
@click=${(e) => this._handleRowClick(e, row, rowIndex)}
|
|
8670
|
+
>${cells}</a>
|
|
8671
|
+
`;
|
|
8672
|
+
}
|
|
8673
|
+
return b `
|
|
8674
|
+
<div
|
|
8675
|
+
class=${e$1({ 'row': true, 'row--clickable': !!this._model.rowClickable })}
|
|
8676
|
+
@mousedown=${() => this._handleRowMouseDown()}
|
|
8677
|
+
@click=${(e) => this._handleRowClick(e, row, rowIndex)}
|
|
8678
|
+
>${cells}</div>
|
|
8679
|
+
`;
|
|
8680
|
+
})}
|
|
8681
|
+
</div>
|
|
8682
|
+
</div>
|
|
8683
|
+
</div>
|
|
8684
|
+
`;
|
|
8685
|
+
}
|
|
8686
|
+
/**
|
|
8687
|
+
* Renders a data table with:
|
|
8688
|
+
* - Header bar with title, search input with view selector, and tools (pagination, refresh, column visibility, actions dropdown)
|
|
8689
|
+
* - Scrollable grid with sticky header row and optional sticky left/right columns
|
|
8690
|
+
* - Loading, error message, or empty state when no data
|
|
8691
|
+
*/
|
|
8692
|
+
render() {
|
|
8693
|
+
if (!this._model.columns.length) {
|
|
8694
|
+
return b `<slot></slot>`;
|
|
8695
|
+
}
|
|
8696
|
+
return b `
|
|
8697
|
+
${this._renderCardHeader()}
|
|
8698
|
+
${this._renderHeader()}
|
|
8699
|
+
${this._renderTable()}
|
|
8700
|
+
${this._renderFilterPanel()}
|
|
8701
|
+
`;
|
|
8702
|
+
}
|
|
8703
|
+
};
|
|
8704
|
+
KRGrid.styles = [krBaseCSS, i$5 `
|
|
8705
|
+
/* -------------------------------------------------------------------------
|
|
8706
|
+
* Host
|
|
8707
|
+
* ----------------------------------------------------------------------- */
|
|
8708
|
+
:host {
|
|
8709
|
+
display: flex;
|
|
8710
|
+
flex-direction: column;
|
|
8711
|
+
width: 100%;
|
|
8712
|
+
height: 100%;
|
|
8713
|
+
overflow: hidden;
|
|
8714
|
+
container-type: inline-size;
|
|
8715
|
+
}
|
|
8716
|
+
|
|
8717
|
+
/* -------------------------------------------------------------------------
|
|
8718
|
+
* Header
|
|
8719
|
+
* ----------------------------------------------------------------------- */
|
|
8720
|
+
.header {
|
|
8721
|
+
flex-shrink: 0;
|
|
8722
|
+
display: flex;
|
|
8723
|
+
align-items: center;
|
|
8724
|
+
gap: 16px;
|
|
8725
|
+
margin: 0 24px;
|
|
8726
|
+
height: 64px;
|
|
8727
|
+
border-bottom: 1px solid #e5e7eb;
|
|
8728
|
+
background: #fff;
|
|
8729
|
+
}
|
|
8730
|
+
|
|
8731
|
+
:host(.kr-table--scroll-edge) .header {
|
|
8732
|
+
border-bottom: none;
|
|
8733
|
+
}
|
|
8734
|
+
|
|
8735
|
+
.title {
|
|
8736
|
+
font-size: 18px;
|
|
8737
|
+
font-weight: 600;
|
|
8738
|
+
color: #000;
|
|
8739
|
+
}
|
|
8740
|
+
|
|
8741
|
+
/* -------------------------------------------------------------------------
|
|
8742
|
+
* Content
|
|
8743
|
+
* ----------------------------------------------------------------------- */
|
|
8744
|
+
.wrapper {
|
|
8745
|
+
flex: 1;
|
|
8746
|
+
position: relative;
|
|
8747
|
+
overflow: hidden;
|
|
8748
|
+
}
|
|
8749
|
+
|
|
8750
|
+
.content {
|
|
8751
|
+
height: 100%;
|
|
8752
|
+
overflow: auto;
|
|
8753
|
+
}
|
|
8754
|
+
|
|
8755
|
+
/* -------------------------------------------------------------------------
|
|
8756
|
+
* Search
|
|
8757
|
+
* ----------------------------------------------------------------------- */
|
|
8758
|
+
.search {
|
|
8759
|
+
flex: 1;
|
|
8760
|
+
display: flex;
|
|
8761
|
+
align-items: center;
|
|
8762
|
+
justify-content: center;
|
|
8763
|
+
min-width: 0;
|
|
8764
|
+
}
|
|
8765
|
+
|
|
8766
|
+
/* In card mode, align search left instead of center */
|
|
8767
|
+
:host(.kr-table--card) .search {
|
|
8768
|
+
justify-content: flex-start;
|
|
8769
|
+
}
|
|
8770
|
+
|
|
8771
|
+
.search-field {
|
|
8772
|
+
width: 100%;
|
|
8773
|
+
max-width: 400px;
|
|
8774
|
+
position: relative;
|
|
8775
|
+
display: flex;
|
|
8776
|
+
align-items: center;
|
|
8777
|
+
border: 1px solid #00000038;
|
|
8778
|
+
border-radius: 18px;
|
|
8779
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
8780
|
+
}
|
|
8781
|
+
|
|
8782
|
+
.search-field:focus-within {
|
|
8783
|
+
border-color: #163052;
|
|
8784
|
+
box-shadow: 0 0 0 3px rgba(22, 48, 82, 0.1);
|
|
8785
|
+
}
|
|
8786
|
+
|
|
8787
|
+
/* TODO: Uncomment when views dropdown is added
|
|
8788
|
+
.search-field:focus-within .views {
|
|
8789
|
+
border-color: #163052;
|
|
8790
|
+
}
|
|
8791
|
+
*/
|
|
8792
|
+
|
|
8793
|
+
.search-icon {
|
|
8794
|
+
position: absolute;
|
|
8795
|
+
left: 16px;
|
|
8796
|
+
width: 20px;
|
|
8797
|
+
height: 20px;
|
|
8798
|
+
color: #656871;
|
|
8799
|
+
pointer-events: none;
|
|
8800
|
+
}
|
|
8801
|
+
|
|
8802
|
+
.search-input {
|
|
8803
|
+
height: 36px;
|
|
8804
|
+
padding: 0 16px 0 42px;
|
|
8805
|
+
border: none;
|
|
8806
|
+
border-radius: 16px;
|
|
8807
|
+
font-size: 14px;
|
|
8808
|
+
font-weight: 400;
|
|
8809
|
+
font-family: inherit;
|
|
8810
|
+
color: #163052;
|
|
8811
|
+
background: transparent;
|
|
8812
|
+
outline: none;
|
|
8813
|
+
flex: 1;
|
|
8814
|
+
min-width: 0;
|
|
8815
|
+
width: 100%;
|
|
8816
|
+
}
|
|
8817
|
+
|
|
8818
|
+
.search-input::placeholder {
|
|
8819
|
+
color: #656871;
|
|
8820
|
+
font-weight: 400;
|
|
8821
|
+
}
|
|
8822
|
+
|
|
8823
|
+
.search-input:focus {
|
|
8824
|
+
outline: none;
|
|
8825
|
+
}
|
|
8826
|
+
|
|
8827
|
+
@container (max-width: 800px) {
|
|
8828
|
+
.search-field {
|
|
8829
|
+
max-width: 250px;
|
|
8830
|
+
}
|
|
8831
|
+
}
|
|
8832
|
+
|
|
8833
|
+
.views {
|
|
8834
|
+
display: flex;
|
|
8835
|
+
align-items: center;
|
|
8836
|
+
gap: 4px;
|
|
8837
|
+
height: 36px;
|
|
8838
|
+
padding: 0 16px;
|
|
8839
|
+
border: 1px solid #00000038;
|
|
8840
|
+
border-right: none;
|
|
8841
|
+
border-radius: 16px 0 0 16px;
|
|
8842
|
+
font-size: 14px;
|
|
8843
|
+
font-family: inherit;
|
|
8844
|
+
color: #163052;
|
|
8845
|
+
background: transparent;
|
|
8846
|
+
cursor: pointer;
|
|
8847
|
+
white-space: nowrap;
|
|
8848
|
+
transition: border-color 0.2s;
|
|
8849
|
+
}
|
|
8850
|
+
|
|
8851
|
+
.views:hover {
|
|
8852
|
+
background: #e8f0f8;
|
|
8853
|
+
}
|
|
8854
|
+
|
|
8855
|
+
.views svg {
|
|
8856
|
+
width: 16px;
|
|
8857
|
+
height: 16px;
|
|
8858
|
+
color: #163052;
|
|
8859
|
+
}
|
|
8860
|
+
|
|
8861
|
+
/* -------------------------------------------------------------------------
|
|
8862
|
+
* Pagination
|
|
8863
|
+
* ----------------------------------------------------------------------- */
|
|
8864
|
+
.tools {
|
|
8865
|
+
display: flex;
|
|
8866
|
+
align-items: center;
|
|
8867
|
+
gap: 8px;
|
|
8868
|
+
}
|
|
8869
|
+
|
|
8870
|
+
.pagination {
|
|
8871
|
+
display: flex;
|
|
8872
|
+
align-items: center;
|
|
8873
|
+
gap: 2px;
|
|
8874
|
+
}
|
|
8875
|
+
|
|
8876
|
+
.pagination-info {
|
|
8877
|
+
font-size: 13px;
|
|
8878
|
+
color: var(--kr-primary);
|
|
8879
|
+
white-space: nowrap;
|
|
8880
|
+
}
|
|
8881
|
+
|
|
8882
|
+
.pagination-icon {
|
|
8883
|
+
display: flex;
|
|
8884
|
+
color: var(--kr-primary);
|
|
8885
|
+
cursor: pointer;
|
|
8886
|
+
}
|
|
8887
|
+
|
|
8888
|
+
.pagination-icon--disabled {
|
|
8889
|
+
opacity: 0.3;
|
|
8890
|
+
pointer-events: none;
|
|
8891
|
+
}
|
|
8892
|
+
|
|
8893
|
+
.pagination-icon svg {
|
|
8894
|
+
width: 24px;
|
|
8895
|
+
height: 24px;
|
|
8896
|
+
}
|
|
8897
|
+
|
|
8898
|
+
/* -------------------------------------------------------------------------
|
|
8899
|
+
* Header Icons
|
|
8900
|
+
* ----------------------------------------------------------------------- */
|
|
8901
|
+
.refresh,
|
|
8902
|
+
.header-icon {
|
|
8903
|
+
display: flex;
|
|
8904
|
+
align-items: center;
|
|
8905
|
+
justify-content: center;
|
|
8906
|
+
color: var(--kr-primary);
|
|
8907
|
+
background: #EBF1FA;
|
|
8908
|
+
cursor: pointer;
|
|
8909
|
+
padding: 6px;
|
|
8910
|
+
border-radius: 50%;
|
|
8911
|
+
transition: background 0.15s;
|
|
8912
|
+
}
|
|
8913
|
+
|
|
8914
|
+
.refresh:hover,
|
|
8915
|
+
.header-icon:hover {
|
|
8916
|
+
background: #e8f0f8;
|
|
8917
|
+
}
|
|
8918
|
+
|
|
8919
|
+
.refresh svg,
|
|
8920
|
+
.header-icon svg {
|
|
8921
|
+
width: 24px;
|
|
8922
|
+
height: 24px;
|
|
8923
|
+
}
|
|
8924
|
+
|
|
8925
|
+
/* -------------------------------------------------------------------------
|
|
8926
|
+
* Column Picker
|
|
8927
|
+
* ----------------------------------------------------------------------- */
|
|
8928
|
+
.column-picker-wrapper {
|
|
8929
|
+
position: relative;
|
|
8930
|
+
}
|
|
8931
|
+
|
|
8932
|
+
.column-picker {
|
|
8933
|
+
position: absolute;
|
|
8934
|
+
top: 100%;
|
|
8935
|
+
right: 0;
|
|
8936
|
+
margin-top: 4px;
|
|
8937
|
+
min-width: 200px;
|
|
8938
|
+
max-height: calc(100vh - 120px);
|
|
8939
|
+
overflow-y: auto;
|
|
8940
|
+
background: white;
|
|
8941
|
+
border: 1px solid #9ba7b6;
|
|
8942
|
+
border-radius: 8px;
|
|
8943
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
8944
|
+
padding: 8px 0;
|
|
8945
|
+
z-index: 100;
|
|
8946
|
+
display: none;
|
|
8947
|
+
transform-origin: top;
|
|
8948
|
+
}
|
|
8949
|
+
|
|
8950
|
+
.column-picker.open {
|
|
8951
|
+
display: block;
|
|
8952
|
+
animation: column-picker-fade-in 150ms ease-out;
|
|
8953
|
+
}
|
|
8954
|
+
|
|
8955
|
+
@keyframes column-picker-fade-in {
|
|
8956
|
+
from {
|
|
8957
|
+
opacity: 0;
|
|
8958
|
+
transform: translateY(-4px);
|
|
8959
|
+
}
|
|
8960
|
+
to {
|
|
8961
|
+
opacity: 1;
|
|
8962
|
+
transform: translateY(0);
|
|
8963
|
+
}
|
|
8964
|
+
}
|
|
8965
|
+
|
|
8966
|
+
.column-picker-item {
|
|
8967
|
+
display: flex;
|
|
8968
|
+
align-items: center;
|
|
8969
|
+
gap: 10px;
|
|
8970
|
+
padding: 8px 16px;
|
|
8971
|
+
cursor: pointer;
|
|
8972
|
+
white-space: nowrap;
|
|
8973
|
+
}
|
|
8974
|
+
|
|
8975
|
+
.column-picker-item:hover {
|
|
8976
|
+
background: #f3f4f6;
|
|
8977
|
+
}
|
|
8978
|
+
|
|
8979
|
+
.column-picker-checkbox {
|
|
8980
|
+
width: 16px;
|
|
8981
|
+
height: 16px;
|
|
8982
|
+
border: 1.5px solid #9ca3af;
|
|
8983
|
+
border-radius: 3px;
|
|
8984
|
+
display: flex;
|
|
8985
|
+
align-items: center;
|
|
8986
|
+
justify-content: center;
|
|
8987
|
+
flex-shrink: 0;
|
|
8988
|
+
transition: all 0.15s;
|
|
8989
|
+
}
|
|
8990
|
+
|
|
8991
|
+
.column-picker-checkbox.checked {
|
|
8992
|
+
background: var(--kr-primary);
|
|
8993
|
+
border-color: var(--kr-primary);
|
|
8994
|
+
}
|
|
8995
|
+
|
|
8996
|
+
.column-picker-checkbox svg {
|
|
8997
|
+
width: 12px;
|
|
8998
|
+
height: 12px;
|
|
8999
|
+
color: white;
|
|
9000
|
+
opacity: 0;
|
|
9001
|
+
}
|
|
9002
|
+
|
|
9003
|
+
.column-picker-checkbox.checked svg {
|
|
9004
|
+
opacity: 1;
|
|
9005
|
+
}
|
|
9006
|
+
|
|
9007
|
+
.column-picker-label {
|
|
9008
|
+
font-size: 14px;
|
|
9009
|
+
color: #374151;
|
|
9010
|
+
}
|
|
9011
|
+
|
|
9012
|
+
/* -------------------------------------------------------------------------
|
|
9013
|
+
* Table Structure
|
|
9014
|
+
* ----------------------------------------------------------------------- */
|
|
9015
|
+
.table {
|
|
9016
|
+
display: grid;
|
|
9017
|
+
width: max-content;
|
|
9018
|
+
min-width: 100%;
|
|
9019
|
+
font-size: 13px;
|
|
9020
|
+
}
|
|
9021
|
+
|
|
9022
|
+
.row {
|
|
9023
|
+
display: contents;
|
|
9024
|
+
}
|
|
9025
|
+
|
|
9026
|
+
.row:hover .cell {
|
|
9027
|
+
background: #f8f9fa;
|
|
9028
|
+
}
|
|
9029
|
+
|
|
9030
|
+
.row--clickable {
|
|
9031
|
+
cursor: pointer;
|
|
9032
|
+
}
|
|
9033
|
+
|
|
9034
|
+
.row--link {
|
|
9035
|
+
color: inherit;
|
|
9036
|
+
text-decoration: none;
|
|
9037
|
+
}
|
|
9038
|
+
|
|
9039
|
+
.header-row {
|
|
9040
|
+
display: contents;
|
|
9041
|
+
}
|
|
9042
|
+
|
|
9043
|
+
.cell {
|
|
9044
|
+
padding: 8px 12px;
|
|
9045
|
+
display: flex;
|
|
9046
|
+
align-items: center;
|
|
9047
|
+
white-space: nowrap;
|
|
9048
|
+
overflow: hidden;
|
|
9049
|
+
text-overflow: ellipsis;
|
|
9050
|
+
box-sizing: border-box;
|
|
9051
|
+
}
|
|
9052
|
+
|
|
9053
|
+
.cell--actions {
|
|
9054
|
+
gap: 8px;
|
|
9055
|
+
}
|
|
9056
|
+
|
|
9057
|
+
.header-cell {
|
|
9058
|
+
position: sticky;
|
|
9059
|
+
top: 0;
|
|
9060
|
+
padding: 10px 12px;
|
|
9061
|
+
white-space: nowrap;
|
|
9062
|
+
box-sizing: border-box;
|
|
9063
|
+
background: #173153;
|
|
9064
|
+
color: #fff;
|
|
9065
|
+
font-weight: 600;
|
|
9066
|
+
font-size: 12px;
|
|
9067
|
+
text-transform: uppercase;
|
|
9068
|
+
letter-spacing: 0.5px;
|
|
9069
|
+
display: flex;
|
|
9070
|
+
align-items: center;
|
|
9071
|
+
}
|
|
9072
|
+
|
|
9073
|
+
.header-cell__resize {
|
|
9074
|
+
position: absolute;
|
|
9075
|
+
right: -7px;
|
|
9076
|
+
top: 0;
|
|
9077
|
+
bottom: 0;
|
|
9078
|
+
width: 14px;
|
|
9079
|
+
cursor: col-resize;
|
|
9080
|
+
z-index: 10;
|
|
9081
|
+
}
|
|
9082
|
+
|
|
9083
|
+
.header-cell--sortable {
|
|
9084
|
+
user-select: none;
|
|
9085
|
+
}
|
|
9086
|
+
|
|
9087
|
+
.header-cell__label {
|
|
9088
|
+
overflow: hidden;
|
|
9089
|
+
text-overflow: ellipsis;
|
|
9090
|
+
min-width: 0;
|
|
9091
|
+
line-height: 20px;
|
|
9092
|
+
}
|
|
9093
|
+
|
|
9094
|
+
.header-cell__sort {
|
|
9095
|
+
flex-grow: 1;
|
|
9096
|
+
display: flex;
|
|
9097
|
+
align-items: center;
|
|
9098
|
+
height: 100%;
|
|
9099
|
+
margin-left: 6px;
|
|
9100
|
+
cursor: pointer;
|
|
9101
|
+
}
|
|
9102
|
+
|
|
9103
|
+
.header-cell__sort-arrow {
|
|
9104
|
+
width: 16px;
|
|
9105
|
+
height: 16px;
|
|
9106
|
+
color: #fff;
|
|
9107
|
+
stroke: currentColor;
|
|
9108
|
+
stroke-width: 1px;
|
|
9109
|
+
}
|
|
9110
|
+
|
|
9111
|
+
.header-cell__sort-arrow--ghost {
|
|
9112
|
+
opacity: 0;
|
|
9113
|
+
color: rgba(255, 255, 255, 0.6);
|
|
9114
|
+
transition: opacity 0.15s;
|
|
9115
|
+
}
|
|
9116
|
+
|
|
9117
|
+
.header-cell--sortable:hover .header-cell__sort-arrow--ghost {
|
|
9118
|
+
opacity: 0.4;
|
|
9119
|
+
}
|
|
9120
|
+
|
|
9121
|
+
.header-cell__sort-priority {
|
|
9122
|
+
font-size: 10px;
|
|
9123
|
+
font-weight: 600;
|
|
9124
|
+
color: #fff;
|
|
9125
|
+
line-height: 1;
|
|
9126
|
+
}
|
|
9127
|
+
|
|
9128
|
+
.cell {
|
|
9129
|
+
background: #fff;
|
|
9130
|
+
border-bottom: 1px solid rgb(238, 239, 241);
|
|
9131
|
+
color: #1f2937;
|
|
9132
|
+
}
|
|
9133
|
+
|
|
9134
|
+
.cell--align-center {
|
|
9135
|
+
text-align: center;
|
|
9136
|
+
}
|
|
9137
|
+
|
|
9138
|
+
.cell--align-right {
|
|
9139
|
+
text-align: right;
|
|
9140
|
+
}
|
|
9141
|
+
|
|
9142
|
+
.cell--sticky-left,
|
|
9143
|
+
.cell--sticky-right {
|
|
9144
|
+
position: sticky;
|
|
9145
|
+
z-index: 1;
|
|
9146
|
+
}
|
|
9147
|
+
|
|
9148
|
+
.header-cell--sticky-left,
|
|
9149
|
+
.header-cell--sticky-right {
|
|
9150
|
+
position: sticky;
|
|
9151
|
+
z-index: 3;
|
|
9152
|
+
}
|
|
9153
|
+
|
|
9154
|
+
.header-cell--align-center {
|
|
9155
|
+
text-align: center;
|
|
9156
|
+
}
|
|
9157
|
+
|
|
9158
|
+
.header-cell--align-right {
|
|
9159
|
+
text-align: right;
|
|
9160
|
+
}
|
|
9161
|
+
|
|
9162
|
+
.header-cell--sticky-left-last,
|
|
9163
|
+
.cell--sticky-left-last {
|
|
9164
|
+
border-right: 1px solid #d1d5db;
|
|
9165
|
+
}
|
|
9166
|
+
|
|
9167
|
+
.header-cell--sticky-right-first,
|
|
9168
|
+
.cell--sticky-right-first {
|
|
9169
|
+
border-left: 1px solid #d1d5db;
|
|
9170
|
+
}
|
|
9171
|
+
|
|
9172
|
+
/* -------------------------------------------------------------------------
|
|
9173
|
+
* Scroll Mode: Edge
|
|
9174
|
+
* Padding scrolls with content, table can reach edges when scrolling
|
|
9175
|
+
* ----------------------------------------------------------------------- */
|
|
9176
|
+
/* Only add right padding when no horizontal scroll is needed */
|
|
9177
|
+
:host(.kr-table--scroll-edge):not(.kr-table--scroll-horizontal-available) .table {
|
|
9178
|
+
padding-right: 24px;
|
|
9179
|
+
}
|
|
9180
|
+
|
|
9181
|
+
:host(.kr-table--scroll-edge) .header-row .header-cell:first-child,
|
|
9182
|
+
:host(.kr-table--scroll-edge) .row .cell:first-child {
|
|
9183
|
+
padding-left: 24px;
|
|
9184
|
+
}
|
|
9185
|
+
|
|
9186
|
+
:host(.kr-table--scroll-edge) .header-row .header-cell:last-child,
|
|
9187
|
+
:host(.kr-table--scroll-edge) .row .cell:last-child {
|
|
9188
|
+
padding-right: 24px;
|
|
9189
|
+
}
|
|
9190
|
+
|
|
9191
|
+
:host(.kr-table--scroll-edge) .filter-row .filter-cell:first-child .filter-cell__input {
|
|
9192
|
+
padding-left: 24px;
|
|
9193
|
+
}
|
|
9194
|
+
|
|
9195
|
+
:host(.kr-table--scroll-edge) .filter-row .filter-cell:last-child .filter-cell__input {
|
|
9196
|
+
padding-right: 52px;
|
|
9197
|
+
}
|
|
9198
|
+
|
|
9199
|
+
/* -------------------------------------------------------------------------
|
|
9200
|
+
* Scroll Mode: Overlay
|
|
9201
|
+
* Fixed padding with overlay elements that hide content at edges
|
|
9202
|
+
* ----------------------------------------------------------------------- */
|
|
9203
|
+
:host(.kr-table--scroll-overlay) .content {
|
|
9204
|
+
padding-left: 24px;
|
|
9205
|
+
}
|
|
9206
|
+
|
|
9207
|
+
.overlay-left,
|
|
9208
|
+
.overlay-right {
|
|
9209
|
+
display: none;
|
|
9210
|
+
position: absolute;
|
|
9211
|
+
top: 0;
|
|
9212
|
+
bottom: 0;
|
|
9213
|
+
width: 24px;
|
|
9214
|
+
z-index: 5;
|
|
9215
|
+
pointer-events: none;
|
|
9216
|
+
transition: box-shadow 0.15s ease;
|
|
9217
|
+
}
|
|
9218
|
+
|
|
9219
|
+
:host(.kr-table--scroll-overlay) .overlay-left,
|
|
9220
|
+
:host(.kr-table--scroll-overlay) .overlay-right {
|
|
9221
|
+
display: block;
|
|
9222
|
+
}
|
|
9223
|
+
|
|
9224
|
+
.overlay-left {
|
|
9225
|
+
left: 0;
|
|
9226
|
+
background: #fff;
|
|
9227
|
+
}
|
|
9228
|
+
|
|
9229
|
+
.overlay-right {
|
|
9230
|
+
right: 0;
|
|
9231
|
+
background: #fff;
|
|
9232
|
+
}
|
|
9233
|
+
|
|
9234
|
+
:host(.kr-table--scroll-overlay.kr-table--scroll-left-available:not(.kr-table--sticky-left)) .overlay-left {
|
|
9235
|
+
border-right: 1px solid #d1d5db54;
|
|
9236
|
+
}
|
|
9237
|
+
|
|
9238
|
+
:host(.kr-table--scroll-overlay.kr-table--scroll-right-available:not(.kr-table--sticky-right)) .overlay-right {
|
|
9239
|
+
border-left: 1px solid #d1d5db54;
|
|
9240
|
+
}
|
|
9241
|
+
|
|
9242
|
+
/* -------------------------------------------------------------------------
|
|
9243
|
+
* Status (Loading, Error, Empty)
|
|
9244
|
+
* ----------------------------------------------------------------------- */
|
|
9245
|
+
.status {
|
|
9246
|
+
position: absolute;
|
|
9247
|
+
top: 0;
|
|
9248
|
+
left: 0;
|
|
9249
|
+
right: 0;
|
|
9250
|
+
bottom: 0;
|
|
9251
|
+
display: flex;
|
|
9252
|
+
align-items: center;
|
|
9253
|
+
justify-content: center;
|
|
9254
|
+
font-size: 14px;
|
|
9255
|
+
font-weight: 400;
|
|
9256
|
+
color: #5f6368;
|
|
9257
|
+
pointer-events: none;
|
|
9258
|
+
}
|
|
9259
|
+
|
|
9260
|
+
.status--error {
|
|
9261
|
+
color: #dc2626;
|
|
9262
|
+
}
|
|
9263
|
+
|
|
9264
|
+
/* -------------------------------------------------------------------------
|
|
9265
|
+
* Filter Row
|
|
9266
|
+
* ----------------------------------------------------------------------- */
|
|
9267
|
+
.filter-row {
|
|
9268
|
+
display: contents;
|
|
9269
|
+
}
|
|
9270
|
+
|
|
9271
|
+
.filter-cell {
|
|
9272
|
+
position: sticky;
|
|
9273
|
+
top: 40px;
|
|
9274
|
+
z-index: 2;
|
|
9275
|
+
height: 36px;
|
|
9276
|
+
padding: 0;
|
|
9277
|
+
display: flex;
|
|
9278
|
+
align-items: center;
|
|
9279
|
+
background: #fff;
|
|
9280
|
+
border-bottom: 1px solid #d1d5db;
|
|
9281
|
+
border-right: 1px solid #e5e7ebba;
|
|
9282
|
+
box-sizing: border-box;
|
|
9283
|
+
box-shadow: inset 0 0 0 0 #163052;
|
|
9284
|
+
transition: box-shadow 0.15s;
|
|
9285
|
+
}
|
|
9286
|
+
|
|
9287
|
+
.filter-cell:focus-within {
|
|
9288
|
+
box-shadow: inset 0 0 0 1px #163052;
|
|
9289
|
+
}
|
|
9290
|
+
|
|
9291
|
+
|
|
9292
|
+
.filter-cell--sticky-left,
|
|
9293
|
+
.filter-cell--sticky-right {
|
|
9294
|
+
position: sticky;
|
|
9295
|
+
z-index: 3;
|
|
9296
|
+
}
|
|
9297
|
+
|
|
9298
|
+
.filter-cell--sticky-right-first {
|
|
9299
|
+
border-left: 1px solid #d1d5db;
|
|
9300
|
+
}
|
|
9301
|
+
|
|
9302
|
+
.filter-cell__wrapper {
|
|
9303
|
+
position: relative;
|
|
9304
|
+
display: flex;
|
|
9305
|
+
align-items: center;
|
|
9306
|
+
width: 100%;
|
|
9307
|
+
height: 100%;
|
|
9308
|
+
}
|
|
9309
|
+
|
|
9310
|
+
.filter-cell__input {
|
|
9311
|
+
width: 100%;
|
|
9312
|
+
height: 100%;
|
|
9313
|
+
padding: 0 60px 0 16px;
|
|
9314
|
+
border: none;
|
|
9315
|
+
border-radius: 0;
|
|
9316
|
+
font-size: 14px;
|
|
9317
|
+
font-family: inherit;
|
|
9318
|
+
color: #111827;
|
|
9319
|
+
background: transparent;
|
|
9320
|
+
outline: none;
|
|
9321
|
+
}
|
|
9322
|
+
|
|
9323
|
+
.filter-cell__input--invalid {
|
|
9324
|
+
border-color: #dc2626;
|
|
9325
|
+
}
|
|
9326
|
+
|
|
9327
|
+
.filter-cell__input--invalid:focus {
|
|
9328
|
+
border-color: #dc2626;
|
|
9329
|
+
box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.1);
|
|
9330
|
+
}
|
|
9331
|
+
|
|
9332
|
+
.filter-cell__input::placeholder {
|
|
9333
|
+
color: #9ca3af;
|
|
9334
|
+
font-size: 13px;
|
|
9335
|
+
}
|
|
9336
|
+
|
|
9337
|
+
.filter-cell__clear {
|
|
9338
|
+
position: absolute;
|
|
9339
|
+
right: 36px;
|
|
9340
|
+
top: 50%;
|
|
9341
|
+
transform: translateY(-50%);
|
|
9342
|
+
display: flex;
|
|
9343
|
+
align-items: center;
|
|
9344
|
+
justify-content: center;
|
|
9345
|
+
width: 24px;
|
|
9346
|
+
height: 24px;
|
|
9347
|
+
padding: 0;
|
|
9348
|
+
border: none;
|
|
9349
|
+
border-radius: 4px;
|
|
9350
|
+
background: transparent;
|
|
9351
|
+
color: #6b7280;
|
|
9352
|
+
cursor: pointer;
|
|
9353
|
+
transition: background 0.15s, color 0.15s;
|
|
9354
|
+
}
|
|
9355
|
+
|
|
9356
|
+
.filter-cell__clear:hover {
|
|
9357
|
+
background: #e5e7eb;
|
|
9358
|
+
color: #374151;
|
|
9359
|
+
}
|
|
9360
|
+
|
|
9361
|
+
.filter-cell__clear svg {
|
|
9362
|
+
width: 16px;
|
|
9363
|
+
height: 16px;
|
|
9364
|
+
}
|
|
9365
|
+
|
|
9366
|
+
.filter-cell__advanced {
|
|
9367
|
+
position: absolute;
|
|
9368
|
+
right: 12px;
|
|
9369
|
+
top: 50%;
|
|
9370
|
+
transform: translateY(-50%);
|
|
9371
|
+
display: flex;
|
|
9372
|
+
align-items: center;
|
|
9373
|
+
justify-content: center;
|
|
9374
|
+
width: 24px;
|
|
9375
|
+
height: 24px;
|
|
9376
|
+
padding: 0;
|
|
9377
|
+
border: none;
|
|
9378
|
+
border-radius: 4px;
|
|
9379
|
+
background: transparent;
|
|
9380
|
+
color: #163052;
|
|
9381
|
+
cursor: pointer;
|
|
9382
|
+
transition: background 0.15s, color 0.15s;
|
|
9383
|
+
}
|
|
9384
|
+
|
|
9385
|
+
.filter-cell__advanced:hover {
|
|
9386
|
+
background: #e5e7eb;
|
|
9387
|
+
}
|
|
9388
|
+
|
|
9389
|
+
.filter-cell__advanced svg {
|
|
9390
|
+
width: 16px;
|
|
9391
|
+
height: 16px;
|
|
9392
|
+
}
|
|
9393
|
+
|
|
9394
|
+
.filter-cell__advanced--opened {
|
|
9395
|
+
background: #163052;
|
|
9396
|
+
color: #fff;
|
|
9397
|
+
}
|
|
9398
|
+
|
|
9399
|
+
.filter-cell__advanced--opened:hover {
|
|
9400
|
+
background: #1a3a5f;
|
|
9401
|
+
color: #fff;
|
|
9402
|
+
}
|
|
9403
|
+
|
|
9404
|
+
/* -------------------------------------------------------------------------
|
|
9405
|
+
* Filter Panel (Advanced)
|
|
9406
|
+
* ----------------------------------------------------------------------- */
|
|
9407
|
+
.filter-panel {
|
|
9408
|
+
position: fixed;
|
|
9409
|
+
min-width: 320px;
|
|
9410
|
+
background: white;
|
|
9411
|
+
border: 1px solid #9ba7b6;
|
|
9412
|
+
border-radius: 8px;
|
|
9413
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
9414
|
+
z-index: 100;
|
|
9415
|
+
animation: filter-panel-fade-in 150ms ease-out;
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9418
|
+
@keyframes filter-panel-fade-in {
|
|
9419
|
+
from {
|
|
9420
|
+
opacity: 0;
|
|
9421
|
+
transform: translateY(-4px);
|
|
9422
|
+
}
|
|
9423
|
+
to {
|
|
9424
|
+
opacity: 1;
|
|
9425
|
+
transform: translateY(0);
|
|
9426
|
+
}
|
|
9427
|
+
}
|
|
9428
|
+
|
|
9429
|
+
.filter-panel__content {
|
|
9430
|
+
padding: 16px;
|
|
9431
|
+
display: flex;
|
|
9432
|
+
flex-direction: column;
|
|
9433
|
+
gap: 12px;
|
|
9434
|
+
}
|
|
9435
|
+
|
|
9436
|
+
.filter-panel__actions {
|
|
9437
|
+
padding: 12px 16px;
|
|
9438
|
+
border-top: 1px solid #e5e7eb;
|
|
9439
|
+
display: flex;
|
|
9440
|
+
justify-content: flex-end;
|
|
9441
|
+
align-items: center;
|
|
9442
|
+
gap: 12px;
|
|
9443
|
+
}
|
|
9444
|
+
|
|
9445
|
+
|
|
9446
|
+
.filter-panel__input {
|
|
9447
|
+
width: 100%;
|
|
9448
|
+
padding: 10px 12px;
|
|
9449
|
+
border: 1px solid #d1d5db;
|
|
9450
|
+
border-radius: 8px;
|
|
9451
|
+
font-size: 14px;
|
|
9452
|
+
font-family: inherit;
|
|
9453
|
+
color: #111827;
|
|
9454
|
+
background: #fff;
|
|
9455
|
+
outline: none;
|
|
9456
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
9457
|
+
}
|
|
9458
|
+
|
|
9459
|
+
.filter-panel__input:focus {
|
|
9460
|
+
border-color: #163052;
|
|
9461
|
+
box-shadow: 0 0 0 2px rgba(22, 48, 82, 0.1);
|
|
9462
|
+
}
|
|
9463
|
+
|
|
9464
|
+
.filter-panel__input::placeholder {
|
|
9465
|
+
color: #9ca3af;
|
|
9466
|
+
}
|
|
9467
|
+
|
|
9468
|
+
.filter-panel__textarea {
|
|
9469
|
+
width: 100%;
|
|
9470
|
+
padding: 10px 12px;
|
|
9471
|
+
border: 1px solid #d1d5db;
|
|
9472
|
+
border-radius: 8px;
|
|
9473
|
+
font-size: 14px;
|
|
9474
|
+
font-family: inherit;
|
|
9475
|
+
color: #111827;
|
|
9476
|
+
background: #fff;
|
|
9477
|
+
outline: none;
|
|
9478
|
+
resize: vertical;
|
|
9479
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
9480
|
+
}
|
|
9481
|
+
|
|
9482
|
+
.filter-panel__textarea:focus {
|
|
9483
|
+
border-color: #163052;
|
|
9484
|
+
box-shadow: 0 0 0 2px rgba(22, 48, 82, 0.1);
|
|
9485
|
+
}
|
|
9486
|
+
|
|
9487
|
+
.filter-panel__textarea::placeholder {
|
|
9488
|
+
color: #9ca3af;
|
|
9489
|
+
}
|
|
9490
|
+
|
|
9491
|
+
/* -------------------------------------------------------------------------
|
|
9492
|
+
* Bucket List
|
|
9493
|
+
* ----------------------------------------------------------------------- */
|
|
9494
|
+
.buckets {
|
|
9495
|
+
max-height: 280px;
|
|
9496
|
+
overflow-y: auto;
|
|
9497
|
+
padding: 8px 0;
|
|
9498
|
+
}
|
|
9499
|
+
|
|
9500
|
+
.bucket {
|
|
9501
|
+
display: flex;
|
|
9502
|
+
align-items: center;
|
|
9503
|
+
gap: 16px;
|
|
9504
|
+
height: 32px;
|
|
9505
|
+
padding: 0 16px;
|
|
9506
|
+
cursor: pointer;
|
|
9507
|
+
transition: background 0.1s;
|
|
9508
|
+
}
|
|
9509
|
+
|
|
9510
|
+
.bucket:hover {
|
|
9511
|
+
background: #f3f4f6;
|
|
9512
|
+
}
|
|
9513
|
+
|
|
9514
|
+
.bucket__checkbox {
|
|
9515
|
+
width: 16px;
|
|
9516
|
+
height: 16px;
|
|
9517
|
+
border: 1.5px solid #9ca3af;
|
|
9518
|
+
border-radius: 3px;
|
|
9519
|
+
display: flex;
|
|
9520
|
+
align-items: center;
|
|
9521
|
+
justify-content: center;
|
|
9522
|
+
flex-shrink: 0;
|
|
9523
|
+
transition: all 0.15s;
|
|
9524
|
+
}
|
|
9525
|
+
|
|
9526
|
+
.bucket__checkbox--checked {
|
|
9527
|
+
background: var(--kr-primary, #163052);
|
|
9528
|
+
border-color: var(--kr-primary, #163052);
|
|
9529
|
+
}
|
|
9530
|
+
|
|
9531
|
+
.bucket__checkbox svg {
|
|
9532
|
+
width: 12px;
|
|
9533
|
+
height: 12px;
|
|
9534
|
+
color: white;
|
|
9535
|
+
}
|
|
9536
|
+
|
|
9537
|
+
.bucket__label {
|
|
9538
|
+
flex: 1;
|
|
9539
|
+
font-size: 14px;
|
|
9540
|
+
color: #000;
|
|
9541
|
+
overflow: hidden;
|
|
9542
|
+
text-overflow: ellipsis;
|
|
9543
|
+
white-space: nowrap;
|
|
9544
|
+
}
|
|
9545
|
+
|
|
9546
|
+
.bucket__count {
|
|
9547
|
+
font-size: 14px;
|
|
9548
|
+
color: #000;
|
|
9549
|
+
flex-shrink: 0;
|
|
9550
|
+
}
|
|
9551
|
+
|
|
9552
|
+
.bucket-empty {
|
|
9553
|
+
font-size: 14px;
|
|
9554
|
+
color: #000;
|
|
9555
|
+
padding: 16px;
|
|
9556
|
+
}
|
|
9557
|
+
|
|
9558
|
+
/* Card variant — self-contained card with border, auto height, left-aligned search */
|
|
9559
|
+
:host(.kr-table--card) {
|
|
9560
|
+
height: auto;
|
|
9561
|
+
/* overflow: visible; */
|
|
9562
|
+
overflow: hidden;
|
|
9563
|
+
/* border: 1px solid #e5e7eb; */
|
|
9564
|
+
/* border-radius: 8px; */
|
|
9565
|
+
border: 1px solid #c6c6cd;
|
|
9566
|
+
border-radius: 12px;
|
|
9567
|
+
background: #fff;
|
|
9568
|
+
}
|
|
9569
|
+
|
|
9570
|
+
.card-header {
|
|
9571
|
+
padding: 24px 24px 16px;
|
|
9572
|
+
}
|
|
9573
|
+
|
|
9574
|
+
.card-header__title {
|
|
9575
|
+
font-size: 18px;
|
|
9576
|
+
font-weight: 600;
|
|
9577
|
+
color: #1f2937;
|
|
9578
|
+
margin: 0;
|
|
9579
|
+
}
|
|
9580
|
+
|
|
9581
|
+
.card-header__description {
|
|
9582
|
+
font-size: 14px;
|
|
9583
|
+
color: #1f2937;
|
|
9584
|
+
margin: 12px 0 0;
|
|
9585
|
+
}
|
|
9586
|
+
|
|
9587
|
+
:host(.kr-table--card) .header {
|
|
9588
|
+
margin: 0 24px;
|
|
9589
|
+
}
|
|
9590
|
+
|
|
9591
|
+
:host(.kr-table--card) .wrapper {
|
|
9592
|
+
flex: none;
|
|
9593
|
+
overflow: visible;
|
|
9594
|
+
min-height: 200px;
|
|
9595
|
+
}
|
|
9596
|
+
|
|
9597
|
+
:host(.kr-table--card) .content {
|
|
9598
|
+
height: auto;
|
|
9599
|
+
}
|
|
9600
|
+
|
|
9601
|
+
`];
|
|
9602
|
+
__decorate$b([
|
|
9603
|
+
r$1()
|
|
9604
|
+
], KRGrid.prototype, "_data", void 0);
|
|
9605
|
+
__decorate$b([
|
|
9606
|
+
r$1()
|
|
9607
|
+
], KRGrid.prototype, "_dataState", void 0);
|
|
9608
|
+
__decorate$b([
|
|
9609
|
+
r$1()
|
|
9610
|
+
], KRGrid.prototype, "_page", void 0);
|
|
9611
|
+
__decorate$b([
|
|
9612
|
+
r$1()
|
|
9613
|
+
], KRGrid.prototype, "_pageSize", void 0);
|
|
9614
|
+
__decorate$b([
|
|
9615
|
+
r$1()
|
|
9616
|
+
], KRGrid.prototype, "_totalItems", void 0);
|
|
9617
|
+
__decorate$b([
|
|
9618
|
+
r$1()
|
|
9619
|
+
], KRGrid.prototype, "_totalPages", void 0);
|
|
9620
|
+
__decorate$b([
|
|
9621
|
+
r$1()
|
|
9622
|
+
], KRGrid.prototype, "_searchQuery", void 0);
|
|
9623
|
+
__decorate$b([
|
|
9624
|
+
r$1()
|
|
9625
|
+
], KRGrid.prototype, "_canScrollLeft", void 0);
|
|
9626
|
+
__decorate$b([
|
|
9627
|
+
r$1()
|
|
9628
|
+
], KRGrid.prototype, "_canScrollRight", void 0);
|
|
9629
|
+
__decorate$b([
|
|
9630
|
+
r$1()
|
|
9631
|
+
], KRGrid.prototype, "_canScrollHorizontal", void 0);
|
|
9632
|
+
__decorate$b([
|
|
9633
|
+
r$1()
|
|
9634
|
+
], KRGrid.prototype, "_columnPickerOpen", void 0);
|
|
9635
|
+
__decorate$b([
|
|
9636
|
+
r$1()
|
|
9637
|
+
], KRGrid.prototype, "_filterPanelOpened", void 0);
|
|
9638
|
+
__decorate$b([
|
|
9639
|
+
r$1()
|
|
9640
|
+
], KRGrid.prototype, "_filterPanelTab", void 0);
|
|
9641
|
+
__decorate$b([
|
|
9642
|
+
r$1()
|
|
9643
|
+
], KRGrid.prototype, "_buckets", void 0);
|
|
9644
|
+
__decorate$b([
|
|
9645
|
+
r$1()
|
|
9646
|
+
], KRGrid.prototype, "_sorts", void 0);
|
|
9647
|
+
__decorate$b([
|
|
9648
|
+
n$1({ type: Object })
|
|
9649
|
+
], KRGrid.prototype, "def", void 0);
|
|
9650
|
+
__decorate$b([
|
|
9651
|
+
n$1({ type: String, reflect: true })
|
|
9652
|
+
], KRGrid.prototype, "variant", void 0);
|
|
9653
|
+
KRGrid = __decorate$b([
|
|
9654
|
+
t$1('kr-grid')
|
|
9655
|
+
], KRGrid);
|
|
9656
|
+
|
|
7240
9657
|
var __decorate$a = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
7241
9658
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
7242
9659
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -10851,5 +13268,5 @@ KRCheckbox = __decorate([
|
|
|
10851
13268
|
t$1('kr-checkbox')
|
|
10852
13269
|
], KRCheckbox);
|
|
10853
13270
|
|
|
10854
|
-
export { KRAccordion, KRAlert, KRAutoSuggest, KRButton, KRCheckbox, KRCodeDemo, KRComboBox, KRContextMenu, KRDateRangePicker, KRDialog, KRDialogRef, KRFileList, KRFilePreview, KRProgressBar, KRQuery, KRRadioCards, KRSelectField, KRSelectOption, KRSnackbar, KRSpinner, KRTab, KRTabGroup, KRTable, KRTextField, KRTextareaField, KR_OPERATORS, getOperatorsForType, krBaseCSS };
|
|
13271
|
+
export { KRAccordion, KRAlert, KRAutoSuggest, KRButton, KRCheckbox, KRCodeDemo, KRComboBox, KRContextMenu, KRDateRangePicker, KRDialog, KRDialogRef, KRFileList, KRFilePreview, KRGrid, KRProgressBar, KRQuery, KRRadioCards, KRSelectField, KRSelectOption, KRSnackbar, KRSpinner, KRTab, KRTabGroup, KRTable, KRTextField, KRTextareaField, KR_OPERATORS, getOperatorsForType, krBaseCSS };
|
|
10855
13272
|
//# sourceMappingURL=krubble-components.bundled.js.map
|