@kodaris/krubble-components 1.0.55 → 1.0.57
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 +64 -23
- package/dist/krubble-components.bundled.js +168 -30
- package/dist/krubble-components.bundled.js.map +1 -1
- package/dist/krubble-components.bundled.min.js +112 -64
- package/dist/krubble-components.bundled.min.js.map +1 -1
- package/dist/krubble-components.umd.js +168 -30
- package/dist/krubble-components.umd.js.map +1 -1
- package/dist/krubble-components.umd.min.js +163 -115
- package/dist/krubble-components.umd.min.js.map +1 -1
- package/dist/table/query.d.ts +3 -3
- package/dist/table/query.d.ts.map +1 -1
- package/dist/table/query.js +39 -10
- package/dist/table/query.js.map +1 -1
- package/dist/table/table.d.ts +3 -0
- package/dist/table/table.d.ts.map +1 -1
- package/dist/table/table.js +129 -20
- package/dist/table/table.js.map +1 -1
- package/package.json +1 -1
|
@@ -3013,6 +3013,7 @@ const KR_OPERATORS = {
|
|
|
3013
3013
|
greater_than_equal: { key: 'greater_than_equal', type: 'comparison', dataTypes: ['number', 'date'], label: 'Greater than or equal' },
|
|
3014
3014
|
between: { key: 'between', type: 'range', dataTypes: ['number', 'date'], label: 'Between' },
|
|
3015
3015
|
in: { key: 'in', type: 'list', dataTypes: ['string', 'number'], label: 'In' },
|
|
3016
|
+
n_in: { key: 'n_in', type: 'list', dataTypes: ['string', 'number', 'date', 'boolean'], label: 'Not In' },
|
|
3016
3017
|
empty: { key: 'empty', type: 'nil', dataTypes: ['string', 'number', 'date', 'boolean'], label: 'Empty' },
|
|
3017
3018
|
n_empty: { key: 'n_empty', type: 'nil', dataTypes: ['string', 'number', 'date', 'boolean'], label: 'Not empty' },
|
|
3018
3019
|
};
|
|
@@ -3345,6 +3346,14 @@ class KRQuery {
|
|
|
3345
3346
|
};
|
|
3346
3347
|
this.specificity = [getDateSpecificity(rawStart), getDateSpecificity(rawEnd)];
|
|
3347
3348
|
}
|
|
3349
|
+
else if (kql.startsWith('!(') && kql.endsWith(')')) {
|
|
3350
|
+
this.operator = 'n_in';
|
|
3351
|
+
this.text = kql.substring(2, kql.length - 1).trim();
|
|
3352
|
+
this.value = this.text.split(',')
|
|
3353
|
+
.map(v => v.trim())
|
|
3354
|
+
.map(v => this._parse(v));
|
|
3355
|
+
this.specificity = [getDateSpecificity(this.text)];
|
|
3356
|
+
}
|
|
3348
3357
|
else if (kql.startsWith('(') && kql.endsWith(')')) {
|
|
3349
3358
|
this.operator = 'in';
|
|
3350
3359
|
this.text = kql.substring(1, kql.length - 1).trim();
|
|
@@ -3391,7 +3400,7 @@ class KRQuery {
|
|
|
3391
3400
|
this.value = null;
|
|
3392
3401
|
this.text = '';
|
|
3393
3402
|
}
|
|
3394
|
-
else if (this.operator === 'in') {
|
|
3403
|
+
else if (this.operator === 'in' || this.operator === 'n_in') {
|
|
3395
3404
|
this.value = [];
|
|
3396
3405
|
this.text = '';
|
|
3397
3406
|
}
|
|
@@ -3409,7 +3418,7 @@ class KRQuery {
|
|
|
3409
3418
|
this.value = null;
|
|
3410
3419
|
this.text = '';
|
|
3411
3420
|
}
|
|
3412
|
-
else if (this.operator === 'in') {
|
|
3421
|
+
else if (this.operator === 'in' || this.operator === 'n_in') {
|
|
3413
3422
|
this.value = [];
|
|
3414
3423
|
this.text = '';
|
|
3415
3424
|
}
|
|
@@ -3476,14 +3485,14 @@ class KRQuery {
|
|
|
3476
3485
|
if (this.operator === 'between') {
|
|
3477
3486
|
return !this.value?.start && !this.value?.end;
|
|
3478
3487
|
}
|
|
3479
|
-
if (this.operator === 'in') {
|
|
3488
|
+
if (this.operator === 'in' || this.operator === 'n_in') {
|
|
3480
3489
|
return !this.value?.length;
|
|
3481
3490
|
}
|
|
3482
3491
|
return this.value === undefined || this.value === null || this.value === '';
|
|
3483
3492
|
}
|
|
3484
|
-
/** Returns true if the value array contains the given value. Only applies to 'in'
|
|
3493
|
+
/** Returns true if the value array contains the given value. Only applies to 'in' and 'n_in' operators. */
|
|
3485
3494
|
has(val) {
|
|
3486
|
-
if (this.operator !== 'in' || !Array.isArray(this.value)) {
|
|
3495
|
+
if ((this.operator !== 'in' && this.operator !== 'n_in') || !Array.isArray(this.value)) {
|
|
3487
3496
|
return false;
|
|
3488
3497
|
}
|
|
3489
3498
|
// Bucket values from Solr arrive as strings ("true"/"false") but
|
|
@@ -3498,9 +3507,9 @@ class KRQuery {
|
|
|
3498
3507
|
}
|
|
3499
3508
|
return this.value.indexOf(val) >= 0;
|
|
3500
3509
|
}
|
|
3501
|
-
/** Adds or removes a value from the 'in' list and rebuilds text/kql. */
|
|
3510
|
+
/** Adds or removes a value from the 'in' or 'n_in' list and rebuilds text/kql. */
|
|
3502
3511
|
toggle(val) {
|
|
3503
|
-
if (this.operator !== 'in') {
|
|
3512
|
+
if (this.operator !== 'in' && this.operator !== 'n_in') {
|
|
3504
3513
|
this.setOperator('in');
|
|
3505
3514
|
}
|
|
3506
3515
|
// Bucket values from Solr arrive as strings ("true"/"false") —
|
|
@@ -3539,8 +3548,8 @@ class KRQuery {
|
|
|
3539
3548
|
if (this.operator === 'n_empty') {
|
|
3540
3549
|
return true;
|
|
3541
3550
|
}
|
|
3542
|
-
// For 'in' operator, valid as long as there's at least one value (including null for empty buckets)
|
|
3543
|
-
if (this.operator === 'in') {
|
|
3551
|
+
// For 'in'/'n_in' operator, valid as long as there's at least one value (including null for empty buckets)
|
|
3552
|
+
if (this.operator === 'in' || this.operator === 'n_in') {
|
|
3544
3553
|
return Array.isArray(this.value) && this.value.length > 0;
|
|
3545
3554
|
}
|
|
3546
3555
|
if (this.type === 'date') {
|
|
@@ -3684,6 +3693,18 @@ class KRQuery {
|
|
|
3684
3693
|
data.value = termify(this.value, true);
|
|
3685
3694
|
}
|
|
3686
3695
|
break;
|
|
3696
|
+
case 'n_in':
|
|
3697
|
+
if (Array.isArray(this.value) && this.value.length > 0) {
|
|
3698
|
+
data.operation = 'EXPRESSION';
|
|
3699
|
+
data.not = true;
|
|
3700
|
+
data.value = `(${this.value.map((v) => termify(v, true)).join(' OR ')})`;
|
|
3701
|
+
}
|
|
3702
|
+
else {
|
|
3703
|
+
data.operation = 'EXPRESSION';
|
|
3704
|
+
data.not = true;
|
|
3705
|
+
data.value = termify(this.value, true);
|
|
3706
|
+
}
|
|
3707
|
+
break;
|
|
3687
3708
|
default:
|
|
3688
3709
|
data.operation = 'EXPRESSION';
|
|
3689
3710
|
data.value = termify(this.value, true);
|
|
@@ -3778,6 +3799,11 @@ class KRQuery {
|
|
|
3778
3799
|
params.operation = 'IN';
|
|
3779
3800
|
params.values = this.value ?? [];
|
|
3780
3801
|
break;
|
|
3802
|
+
case 'n_in':
|
|
3803
|
+
params.operation = 'IN';
|
|
3804
|
+
params.not = true;
|
|
3805
|
+
params.values = this.value ?? [];
|
|
3806
|
+
break;
|
|
3781
3807
|
default:
|
|
3782
3808
|
throw Error(`${this.operator} operator not supported by db params.`);
|
|
3783
3809
|
}
|
|
@@ -3794,7 +3820,7 @@ class KRQuery {
|
|
|
3794
3820
|
if (this.operator === 'between') {
|
|
3795
3821
|
this.text = `${this._format(this.value?.start)} - ${this._format(this.value?.end)}`;
|
|
3796
3822
|
}
|
|
3797
|
-
else if (this.operator === 'in') {
|
|
3823
|
+
else if (this.operator === 'in' || this.operator === 'n_in') {
|
|
3798
3824
|
this.text = this.value.map((v) => this._format(v)).join(',');
|
|
3799
3825
|
}
|
|
3800
3826
|
else {
|
|
@@ -4008,6 +4034,9 @@ class KRQuery {
|
|
|
4008
4034
|
case 'in':
|
|
4009
4035
|
this.kql = `(${this.value.map((v) => this._format(v)).join(',')})`;
|
|
4010
4036
|
break;
|
|
4037
|
+
case 'n_in':
|
|
4038
|
+
this.kql = `!(${this.value.map((v) => this._format(v)).join(',')})`;
|
|
4039
|
+
break;
|
|
4011
4040
|
default:
|
|
4012
4041
|
throw Error(`Unknown operator ${this.operator}`);
|
|
4013
4042
|
}
|
|
@@ -4059,6 +4088,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4059
4088
|
this._filterPanelTab = 'filter';
|
|
4060
4089
|
this._buckets = new Map();
|
|
4061
4090
|
this._filterPanelPos = { top: 0, left: 0 };
|
|
4091
|
+
this._sorts = [];
|
|
4062
4092
|
this._resizing = null;
|
|
4063
4093
|
this._resizeObserver = null;
|
|
4064
4094
|
this._searchPositionLocked = false;
|
|
@@ -4248,7 +4278,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4248
4278
|
const request = {
|
|
4249
4279
|
page: this._page - 1,
|
|
4250
4280
|
size: this._pageSize,
|
|
4251
|
-
sorts:
|
|
4281
|
+
sorts: this._sorts,
|
|
4252
4282
|
filterFields: [],
|
|
4253
4283
|
queryFields: [],
|
|
4254
4284
|
facetFields: []
|
|
@@ -4258,7 +4288,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4258
4288
|
continue;
|
|
4259
4289
|
}
|
|
4260
4290
|
const filterData = col.filter.toSolrData();
|
|
4261
|
-
if (col.facetable && col.filter.operator === 'in') {
|
|
4291
|
+
if (col.facetable && (col.filter.operator === 'in' || col.filter.operator === 'n_in')) {
|
|
4262
4292
|
filterData.tagged = true;
|
|
4263
4293
|
}
|
|
4264
4294
|
request.filterFields.push(filterData);
|
|
@@ -4288,7 +4318,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4288
4318
|
const request = {
|
|
4289
4319
|
page: this._page - 1,
|
|
4290
4320
|
size: this._pageSize,
|
|
4291
|
-
sorts:
|
|
4321
|
+
sorts: this._sorts,
|
|
4292
4322
|
filterFields: [],
|
|
4293
4323
|
queryFields: [],
|
|
4294
4324
|
facetFields: []
|
|
@@ -4410,7 +4440,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4410
4440
|
}
|
|
4411
4441
|
}
|
|
4412
4442
|
// Bucket sync: ensure selected values appear even with 0 results
|
|
4413
|
-
if (col.filter && col.filter.operator === 'in' && Array.isArray(col.filter.value)) {
|
|
4443
|
+
if (col.filter && (col.filter.operator === 'in' || col.filter.operator === 'n_in') && Array.isArray(col.filter.value)) {
|
|
4414
4444
|
for (const selectedVal of col.filter.value) {
|
|
4415
4445
|
if (!buckets.some(b => b.val === selectedVal)) {
|
|
4416
4446
|
buckets.push({
|
|
@@ -4587,6 +4617,77 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4587
4617
|
document.addEventListener('mouseup', this._handleResizeEnd);
|
|
4588
4618
|
}
|
|
4589
4619
|
// ----------------------------------------------------------------------------
|
|
4620
|
+
// Sorting
|
|
4621
|
+
// ----------------------------------------------------------------------------
|
|
4622
|
+
_handleSortClick(e, column) {
|
|
4623
|
+
if (e.shiftKey) {
|
|
4624
|
+
// Multi-sort: add or cycle existing
|
|
4625
|
+
const existingIndex = this._sorts.findIndex(s => s.sortBy === column.id);
|
|
4626
|
+
if (existingIndex === -1) {
|
|
4627
|
+
this._sorts.push({ sortBy: column.id, sortDirection: 'asc' });
|
|
4628
|
+
}
|
|
4629
|
+
else {
|
|
4630
|
+
const existing = this._sorts[existingIndex];
|
|
4631
|
+
if (existing.sortDirection === 'asc') {
|
|
4632
|
+
existing.sortDirection = 'desc';
|
|
4633
|
+
}
|
|
4634
|
+
else {
|
|
4635
|
+
// on third click, remove sorting for the column
|
|
4636
|
+
this._sorts.splice(existingIndex, 1);
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
this.requestUpdate();
|
|
4640
|
+
}
|
|
4641
|
+
else {
|
|
4642
|
+
// Single sort: replace all
|
|
4643
|
+
let existing = null;
|
|
4644
|
+
if (this._sorts.length === 1) {
|
|
4645
|
+
existing = this._sorts.find(s => s.sortBy === column.id);
|
|
4646
|
+
}
|
|
4647
|
+
if (!existing) {
|
|
4648
|
+
this._sorts = [{ sortBy: column.id, sortDirection: 'asc' }];
|
|
4649
|
+
}
|
|
4650
|
+
else if (existing.sortDirection === 'asc') {
|
|
4651
|
+
this._sorts = [{ sortBy: column.id, sortDirection: 'desc' }];
|
|
4652
|
+
}
|
|
4653
|
+
else {
|
|
4654
|
+
this._sorts = [];
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
this._page = 1;
|
|
4658
|
+
this._fetch();
|
|
4659
|
+
}
|
|
4660
|
+
_renderSortIndicator(column) {
|
|
4661
|
+
if (!column.sortable) {
|
|
4662
|
+
return A;
|
|
4663
|
+
}
|
|
4664
|
+
const sortIndex = this._sorts.findIndex(s => s.sortBy === column.id);
|
|
4665
|
+
if (sortIndex === -1) {
|
|
4666
|
+
// Ghost arrow: visible only on hover via CSS
|
|
4667
|
+
return b `
|
|
4668
|
+
<span class="header-cell__sort" @click=${(e) => this._handleSortClick(e, column)}>
|
|
4669
|
+
<svg class="header-cell__sort-arrow header-cell__sort-arrow--ghost" viewBox="0 0 24 24" fill="currentColor">
|
|
4670
|
+
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
|
|
4671
|
+
</svg>
|
|
4672
|
+
</span>
|
|
4673
|
+
`;
|
|
4674
|
+
}
|
|
4675
|
+
let arrowStyle = {};
|
|
4676
|
+
if (this._sorts[sortIndex].sortDirection === 'desc') {
|
|
4677
|
+
arrowStyle = { transform: 'rotate(180deg)' };
|
|
4678
|
+
}
|
|
4679
|
+
return b `
|
|
4680
|
+
<span class="header-cell__sort" @click=${(e) => this._handleSortClick(e, column)}>
|
|
4681
|
+
<svg class="header-cell__sort-arrow" viewBox="0 0 24 24" fill="currentColor" style=${o$1(arrowStyle)}>
|
|
4682
|
+
<path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
|
|
4683
|
+
</svg>
|
|
4684
|
+
${this._sorts.length > 1 ? b `
|
|
4685
|
+
<span class="header-cell__sort-priority">${sortIndex + 1}</span>
|
|
4686
|
+
` : A}
|
|
4687
|
+
</span>
|
|
4688
|
+
`;
|
|
4689
|
+
}
|
|
4690
|
+
// ----------------------------------------------------------------------------
|
|
4590
4691
|
// Header
|
|
4591
4692
|
// ----------------------------------------------------------------------------
|
|
4592
4693
|
_handleAction(action) {
|
|
@@ -4780,6 +4881,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
4780
4881
|
_getHeaderCellClasses(column, index) {
|
|
4781
4882
|
return {
|
|
4782
4883
|
'header-cell': true,
|
|
4884
|
+
'header-cell--sortable': !!column.sortable,
|
|
4783
4885
|
'header-cell--align-center': column.align === 'center',
|
|
4784
4886
|
'header-cell--align-right': column.align === 'right',
|
|
4785
4887
|
'header-cell--sticky-left': column.sticky === 'left',
|
|
@@ -5012,7 +5114,7 @@ let KRTable = class KRTable extends i$2 {
|
|
|
5012
5114
|
/>
|
|
5013
5115
|
`;
|
|
5014
5116
|
}
|
|
5015
|
-
else if (column.filter.operator === 'in') {
|
|
5117
|
+
else if (column.filter.operator === 'in' || column.filter.operator === 'n_in') {
|
|
5016
5118
|
valueInput = b `
|
|
5017
5119
|
<textarea
|
|
5018
5120
|
class="filter-panel__textarea"
|
|
@@ -5267,10 +5369,14 @@ let KRTable = class KRTable extends i$2 {
|
|
|
5267
5369
|
class=${e$1(this._getHeaderCellClasses(col, i))}
|
|
5268
5370
|
style=${o$1(this._getCellStyle(col, i))}
|
|
5269
5371
|
data-column-id=${col.id}
|
|
5270
|
-
|
|
5372
|
+
>
|
|
5373
|
+
<span class="header-cell__label">${col.label ?? col.id}</span>
|
|
5374
|
+
${this._renderSortIndicator(col)}
|
|
5375
|
+
${col.resizable !== false ? b `<div
|
|
5271
5376
|
class="header-cell__resize"
|
|
5272
5377
|
@mousedown=${(e) => this._handleResizeStart(e, col.id)}
|
|
5273
|
-
></div>` : A}
|
|
5378
|
+
></div>` : A}
|
|
5379
|
+
</div>
|
|
5274
5380
|
`)}
|
|
5275
5381
|
</div>
|
|
5276
5382
|
${this._renderFilterRow()}
|
|
@@ -5679,9 +5785,7 @@ KRTable.styles = [krBaseCSS, i$5 `
|
|
|
5679
5785
|
.header-cell {
|
|
5680
5786
|
position: sticky;
|
|
5681
5787
|
top: 0;
|
|
5682
|
-
z-index: 2;
|
|
5683
5788
|
height: 48px;
|
|
5684
|
-
line-height: 48px;
|
|
5685
5789
|
padding: 0 16px;
|
|
5686
5790
|
white-space: nowrap;
|
|
5687
5791
|
box-sizing: border-box;
|
|
@@ -5691,8 +5795,8 @@ KRTable.styles = [krBaseCSS, i$5 `
|
|
|
5691
5795
|
border-right: 1px solid #e5e7ebba;
|
|
5692
5796
|
font-weight: 600;
|
|
5693
5797
|
color: #374151;
|
|
5694
|
-
|
|
5695
|
-
|
|
5798
|
+
display: flex;
|
|
5799
|
+
align-items: center;
|
|
5696
5800
|
}
|
|
5697
5801
|
|
|
5698
5802
|
.header-cell__resize {
|
|
@@ -5702,21 +5806,52 @@ KRTable.styles = [krBaseCSS, i$5 `
|
|
|
5702
5806
|
bottom: 0;
|
|
5703
5807
|
width: 14px;
|
|
5704
5808
|
cursor: col-resize;
|
|
5809
|
+
z-index: 10;
|
|
5810
|
+
}
|
|
5811
|
+
|
|
5812
|
+
.header-cell--sortable {
|
|
5813
|
+
user-select: none;
|
|
5814
|
+
}
|
|
5815
|
+
|
|
5816
|
+
.header-cell__label {
|
|
5817
|
+
overflow: hidden;
|
|
5818
|
+
text-overflow: ellipsis;
|
|
5819
|
+
min-width: 0;
|
|
5820
|
+
line-height: 48px;
|
|
5821
|
+
}
|
|
5822
|
+
|
|
5823
|
+
.header-cell__sort {
|
|
5824
|
+
flex-grow: 1;
|
|
5705
5825
|
display: flex;
|
|
5706
5826
|
align-items: center;
|
|
5707
|
-
|
|
5708
|
-
|
|
5827
|
+
height: 100%;
|
|
5828
|
+
margin-left: 6px;
|
|
5829
|
+
cursor: pointer;
|
|
5709
5830
|
}
|
|
5710
5831
|
|
|
5711
|
-
.header-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5832
|
+
.header-cell__sort-arrow {
|
|
5833
|
+
width: 16px;
|
|
5834
|
+
height: 16px;
|
|
5835
|
+
color: #374151;
|
|
5836
|
+
stroke: currentColor;
|
|
5837
|
+
stroke-width: 1px;
|
|
5716
5838
|
}
|
|
5717
5839
|
|
|
5718
|
-
.header-
|
|
5719
|
-
|
|
5840
|
+
.header-cell__sort-arrow--ghost {
|
|
5841
|
+
opacity: 0;
|
|
5842
|
+
color: #374151;
|
|
5843
|
+
transition: opacity 0.15s;
|
|
5844
|
+
}
|
|
5845
|
+
|
|
5846
|
+
.header-cell--sortable:hover .header-cell__sort-arrow--ghost {
|
|
5847
|
+
opacity: 0.4;
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5850
|
+
.header-cell__sort-priority {
|
|
5851
|
+
font-size: 10px;
|
|
5852
|
+
font-weight: 600;
|
|
5853
|
+
color: #374151;
|
|
5854
|
+
line-height: 1;
|
|
5720
5855
|
}
|
|
5721
5856
|
|
|
5722
5857
|
.cell {
|
|
@@ -6182,6 +6317,9 @@ __decorate$9([
|
|
|
6182
6317
|
__decorate$9([
|
|
6183
6318
|
r$1()
|
|
6184
6319
|
], KRTable.prototype, "_buckets", void 0);
|
|
6320
|
+
__decorate$9([
|
|
6321
|
+
r$1()
|
|
6322
|
+
], KRTable.prototype, "_sorts", void 0);
|
|
6185
6323
|
__decorate$9([
|
|
6186
6324
|
n$1({ type: Object })
|
|
6187
6325
|
], KRTable.prototype, "def", void 0);
|