@design.estate/dees-catalog 3.61.2 → 3.63.0
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/dist_bundle/bundle.js +677 -128
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-dataview/dees-table/data.d.ts +8 -2
- package/dist_ts_web/elements/00group-dataview/dees-table/data.js +40 -22
- package/dist_ts_web/elements/00group-dataview/dees-table/dees-table.d.ts +110 -6
- package/dist_ts_web/elements/00group-dataview/dees-table/dees-table.demo.js +39 -1
- package/dist_ts_web/elements/00group-dataview/dees-table/dees-table.js +629 -114
- package/dist_ts_web/elements/00group-dataview/dees-table/styles.js +72 -18
- package/dist_ts_web/elements/00group-dataview/dees-table/types.d.ts +8 -0
- package/dist_watch/bundle.js +675 -126
- package/dist_watch/bundle.js.map +3 -3
- package/package.json +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-dataview/dees-table/data.ts +33 -17
- package/ts_web/elements/00group-dataview/dees-table/dees-table.demo.ts +38 -0
- package/ts_web/elements/00group-dataview/dees-table/dees-table.ts +656 -92
- package/ts_web/elements/00group-dataview/dees-table/styles.ts +71 -17
- package/ts_web/elements/00group-dataview/dees-table/types.ts +9 -0
package/dist_bundle/bundle.js
CHANGED
|
@@ -163645,6 +163645,44 @@ var demoFunc29 = /* @__PURE__ */ __name(() => b2`
|
|
|
163645
163645
|
></dees-table>
|
|
163646
163646
|
</div>
|
|
163647
163647
|
|
|
163648
|
+
<div class="demo-section">
|
|
163649
|
+
<h2 class="demo-title">Multi-Column Sort</h2>
|
|
163650
|
+
<p class="demo-description">
|
|
163651
|
+
Click any column header for a single-column sort. Hold Shift while clicking to add the
|
|
163652
|
+
column to a multi-sort cascade (or cycle its direction). Right-click any sortable header
|
|
163653
|
+
to open a menu where you can pin a column to a specific priority slot, remove it, or
|
|
163654
|
+
clear the cascade.
|
|
163655
|
+
</p>
|
|
163656
|
+
<dees-table
|
|
163657
|
+
heading1="People Directory"
|
|
163658
|
+
heading2="Pre-seeded with department ▲ 1, name ▲ 2"
|
|
163659
|
+
.sortBy=${[
|
|
163660
|
+
{ key: "department", dir: "asc" },
|
|
163661
|
+
{ key: "name", dir: "asc" }
|
|
163662
|
+
]}
|
|
163663
|
+
.columns=${[
|
|
163664
|
+
{ key: "department", header: "Department", sortable: true },
|
|
163665
|
+
{ key: "name", header: "Name", sortable: true },
|
|
163666
|
+
{ key: "role", header: "Role", sortable: true },
|
|
163667
|
+
{ key: "createdAt", header: "Created", sortable: true },
|
|
163668
|
+
{ key: "location", header: "Location", sortable: true },
|
|
163669
|
+
{ key: "status", header: "Status", sortable: true }
|
|
163670
|
+
]}
|
|
163671
|
+
.data=${[
|
|
163672
|
+
{ department: "R&D", name: "Alice Johnson", role: "Engineer", createdAt: "2023-01-12", location: "Berlin", status: "Active" },
|
|
163673
|
+
{ department: "R&D", name: "Diana Martinez", role: "Engineer", createdAt: "2020-06-30", location: "Madrid", status: "Active" },
|
|
163674
|
+
{ department: "R&D", name: "Mark Lee", role: "Engineer", createdAt: "2024-03-04", location: "Berlin", status: "Active" },
|
|
163675
|
+
{ department: "Design", name: "Bob Smith", role: "Designer", createdAt: "2022-11-05", location: "Paris", status: "Active" },
|
|
163676
|
+
{ department: "Design", name: "Sara Kim", role: "Designer", createdAt: "2021-08-19", location: "Paris", status: "On Leave" },
|
|
163677
|
+
{ department: "Ops", name: "Charlie Davis", role: "Manager", createdAt: "2021-04-21", location: "London", status: "On Leave" },
|
|
163678
|
+
{ department: "Ops", name: "Helena Voss", role: "SRE", createdAt: "2023-07-22", location: "London", status: "Active" },
|
|
163679
|
+
{ department: "QA", name: "Fiona Clark", role: "QA", createdAt: "2022-03-14", location: "Vienna", status: "Active" },
|
|
163680
|
+
{ department: "QA", name: "Tom\xE1s Rivera", role: "QA", createdAt: "2024-01-09", location: "Madrid", status: "Active" },
|
|
163681
|
+
{ department: "CS", name: "Ethan Brown", role: "Support", createdAt: "2019-09-18", location: "Rome", status: "Inactive" }
|
|
163682
|
+
]}
|
|
163683
|
+
></dees-table>
|
|
163684
|
+
</div>
|
|
163685
|
+
|
|
163648
163686
|
<div class="demo-section">
|
|
163649
163687
|
<h2 class="demo-title">Wide Properties + Many Actions</h2>
|
|
163650
163688
|
<p class="demo-description">A table with many columns and rich actions to stress test layout and sticky Actions.</p>
|
|
@@ -163876,29 +163914,48 @@ var tableStyles = [
|
|
|
163876
163914
|
border-bottom-width: 0px;
|
|
163877
163915
|
}
|
|
163878
163916
|
|
|
163917
|
+
/* Default mode (Mode B, page sticky): horizontal scroll lives on
|
|
163918
|
+
.tableScroll (so wide tables don't get clipped by an ancestor
|
|
163919
|
+
overflow:hidden such as dees-tile). Vertical sticky is handled by
|
|
163920
|
+
a JS-managed floating header (.floatingHeader, position:fixed),
|
|
163921
|
+
which is unaffected by ancestor overflow. */
|
|
163879
163922
|
.tableScroll {
|
|
163880
|
-
|
|
163923
|
+
position: relative;
|
|
163881
163924
|
overflow-x: auto;
|
|
163882
|
-
|
|
163883
|
-
|
|
163884
|
-
|
|
163925
|
+
overflow-y: visible;
|
|
163926
|
+
scrollbar-gutter: stable;
|
|
163927
|
+
}
|
|
163928
|
+
/* Mode A, internal scroll: opt-in via fixed-height attribute.
|
|
163929
|
+
The table scrolls inside its own box and the header sticks via plain CSS sticky. */
|
|
163930
|
+
:host([fixed-height]) .tableScroll {
|
|
163931
|
+
max-height: var(--table-max-height, 360px);
|
|
163932
|
+
overflow: auto;
|
|
163885
163933
|
scrollbar-gutter: stable both-edges;
|
|
163886
163934
|
}
|
|
163887
|
-
|
|
163888
|
-
|
|
163889
|
-
|
|
163890
|
-
|
|
163935
|
+
:host([fixed-height]) .tableScroll::-webkit-scrollbar:horizontal {
|
|
163936
|
+
height: 0px;
|
|
163937
|
+
}
|
|
163938
|
+
|
|
163939
|
+
/* Floating header overlay (Mode B). Position is managed by JS so it
|
|
163940
|
+
escapes any ancestor overflow:hidden (position:fixed is not clipped
|
|
163941
|
+
by overflow ancestors). */
|
|
163942
|
+
.floatingHeader {
|
|
163943
|
+
position: fixed;
|
|
163944
|
+
top: 0;
|
|
163945
|
+
left: 0;
|
|
163946
|
+
z-index: 100;
|
|
163947
|
+
visibility: hidden;
|
|
163948
|
+
overflow: hidden;
|
|
163949
|
+
pointer-events: none;
|
|
163891
163950
|
}
|
|
163892
|
-
|
|
163893
|
-
|
|
163951
|
+
.floatingHeader.active {
|
|
163952
|
+
visibility: visible;
|
|
163894
163953
|
}
|
|
163895
|
-
|
|
163896
|
-
|
|
163897
|
-
height: 0px;
|
|
163954
|
+
.floatingHeader table {
|
|
163955
|
+
margin: 0;
|
|
163898
163956
|
}
|
|
163899
|
-
|
|
163900
|
-
|
|
163901
|
-
overflow: auto;
|
|
163957
|
+
.floatingHeader th {
|
|
163958
|
+
pointer-events: auto;
|
|
163902
163959
|
}
|
|
163903
163960
|
|
|
163904
163961
|
table {
|
|
@@ -163921,11 +163978,20 @@ var tableStyles = [
|
|
|
163921
163978
|
background: ${cssManager.bdTheme("hsl(210 40% 96.1%)", "hsl(0 0% 9%)")};
|
|
163922
163979
|
border-bottom: 1px solid var(--dees-color-border-strong);
|
|
163923
163980
|
}
|
|
163924
|
-
|
|
163981
|
+
/* th needs its own background so sticky cells paint over scrolled rows
|
|
163982
|
+
(browsers don't paint the <thead> box behind a sticky <th>). */
|
|
163983
|
+
th {
|
|
163984
|
+
background: ${cssManager.bdTheme("hsl(210 40% 96.1%)", "hsl(0 0% 9%)")};
|
|
163985
|
+
}
|
|
163986
|
+
/* Mode A — internal scroll sticky */
|
|
163987
|
+
:host([fixed-height]) thead th {
|
|
163925
163988
|
position: sticky;
|
|
163926
163989
|
top: 0;
|
|
163927
163990
|
z-index: 2;
|
|
163928
163991
|
}
|
|
163992
|
+
:host([fixed-height]) thead tr.filtersRow th {
|
|
163993
|
+
top: 36px; /* matches th { height: 36px } below */
|
|
163994
|
+
}
|
|
163929
163995
|
|
|
163930
163996
|
tbody tr {
|
|
163931
163997
|
transition: background-color 0.15s ease;
|
|
@@ -164038,6 +164104,32 @@ var tableStyles = [
|
|
|
164038
164104
|
color: ${cssManager.bdTheme("hsl(215.4 16.3% 46.9%)", "hsl(215 20.2% 65.1%)")};
|
|
164039
164105
|
letter-spacing: -0.01em;
|
|
164040
164106
|
}
|
|
164107
|
+
|
|
164108
|
+
th[role='columnheader']:hover {
|
|
164109
|
+
color: var(--dees-color-text-primary);
|
|
164110
|
+
}
|
|
164111
|
+
|
|
164112
|
+
th .sortArrow {
|
|
164113
|
+
display: inline-block;
|
|
164114
|
+
margin-left: 6px;
|
|
164115
|
+
font-size: 10px;
|
|
164116
|
+
line-height: 1;
|
|
164117
|
+
opacity: 0.7;
|
|
164118
|
+
vertical-align: middle;
|
|
164119
|
+
}
|
|
164120
|
+
|
|
164121
|
+
th .sortBadge {
|
|
164122
|
+
display: inline-block;
|
|
164123
|
+
margin-left: 3px;
|
|
164124
|
+
padding: 1px 5px;
|
|
164125
|
+
font-size: 10px;
|
|
164126
|
+
font-weight: 600;
|
|
164127
|
+
line-height: 1;
|
|
164128
|
+
color: ${cssManager.bdTheme("hsl(222.2 47.4% 30%)", "hsl(217.2 91.2% 75%)")};
|
|
164129
|
+
background: ${cssManager.bdTheme("hsl(222.2 47.4% 51.2% / 0.12)", "hsl(217.2 91.2% 59.8% / 0.18)")};
|
|
164130
|
+
border-radius: 999px;
|
|
164131
|
+
vertical-align: middle;
|
|
164132
|
+
}
|
|
164041
164133
|
|
|
164042
164134
|
:host([show-vertical-lines]) th {
|
|
164043
164135
|
border-right: 1px solid var(--dees-color-border-default);
|
|
@@ -164229,7 +164321,23 @@ function getCellValue(row, col, displayFunction) {
|
|
|
164229
164321
|
return col.value ? col.value(row) : row[col.key];
|
|
164230
164322
|
}
|
|
164231
164323
|
__name(getCellValue, "getCellValue");
|
|
164232
|
-
function
|
|
164324
|
+
function compareCellValues(va, vb) {
|
|
164325
|
+
if (va == null && vb == null) return 0;
|
|
164326
|
+
if (va == null) return -1;
|
|
164327
|
+
if (vb == null) return 1;
|
|
164328
|
+
if (typeof va === "number" && typeof vb === "number") {
|
|
164329
|
+
if (va < vb) return -1;
|
|
164330
|
+
if (va > vb) return 1;
|
|
164331
|
+
return 0;
|
|
164332
|
+
}
|
|
164333
|
+
const sa = String(va).toLowerCase();
|
|
164334
|
+
const sb = String(vb).toLowerCase();
|
|
164335
|
+
if (sa < sb) return -1;
|
|
164336
|
+
if (sa > sb) return 1;
|
|
164337
|
+
return 0;
|
|
164338
|
+
}
|
|
164339
|
+
__name(compareCellValues, "compareCellValues");
|
|
164340
|
+
function getViewData(data, effectiveColumns, sortBy, filterText, columnFilters, filterMode = "table", lucenePredicate) {
|
|
164233
164341
|
let arr = data.slice();
|
|
164234
164342
|
const ft = (filterText || "").trim().toLowerCase();
|
|
164235
164343
|
const cf = columnFilters || {};
|
|
@@ -164243,9 +164351,9 @@ function getViewData(data, effectiveColumns, sortKey, sortDir, filterText, colum
|
|
|
164243
164351
|
const needle = String(cf[k4]).toLowerCase();
|
|
164244
164352
|
if (!s10.includes(needle)) return false;
|
|
164245
164353
|
} else {
|
|
164246
|
-
const
|
|
164247
|
-
if (!
|
|
164248
|
-
const val = getCellValue(row,
|
|
164354
|
+
const col = effectiveColumns.find((c11) => String(c11.key) === k4);
|
|
164355
|
+
if (!col || col.hidden || col.filterable === false) continue;
|
|
164356
|
+
const val = getCellValue(row, col);
|
|
164249
164357
|
const s10 = String(val ?? "").toLowerCase();
|
|
164250
164358
|
const needle = String(cf[k4]).toLowerCase();
|
|
164251
164359
|
if (!s10.includes(needle)) return false;
|
|
@@ -164266,9 +164374,9 @@ function getViewData(data, effectiveColumns, sortKey, sortDir, filterText, colum
|
|
|
164266
164374
|
}
|
|
164267
164375
|
}
|
|
164268
164376
|
} else {
|
|
164269
|
-
for (const
|
|
164270
|
-
if (
|
|
164271
|
-
const val = getCellValue(row,
|
|
164377
|
+
for (const col of effectiveColumns) {
|
|
164378
|
+
if (col.hidden) continue;
|
|
164379
|
+
const val = getCellValue(row, col);
|
|
164272
164380
|
const s10 = String(val ?? "").toLowerCase();
|
|
164273
164381
|
if (s10.includes(ft)) {
|
|
164274
164382
|
any = true;
|
|
@@ -164281,21 +164389,14 @@ function getViewData(data, effectiveColumns, sortKey, sortDir, filterText, colum
|
|
|
164281
164389
|
return true;
|
|
164282
164390
|
});
|
|
164283
164391
|
}
|
|
164284
|
-
if (!
|
|
164285
|
-
const
|
|
164286
|
-
if (
|
|
164287
|
-
const dir = sortDir === "asc" ? 1 : -1;
|
|
164392
|
+
if (!sortBy || sortBy.length === 0) return arr;
|
|
164393
|
+
const resolved2 = sortBy.map((desc) => ({ desc, col: effectiveColumns.find((c11) => String(c11.key) === desc.key) })).filter((entry) => !!entry.col);
|
|
164394
|
+
if (resolved2.length === 0) return arr;
|
|
164288
164395
|
arr.sort((a5, b5) => {
|
|
164289
|
-
const
|
|
164290
|
-
|
|
164291
|
-
|
|
164292
|
-
|
|
164293
|
-
if (vb == null) return 1 * dir;
|
|
164294
|
-
if (typeof va === "number" && typeof vb === "number") return (va - vb) * dir;
|
|
164295
|
-
const sa = String(va).toLowerCase();
|
|
164296
|
-
const sb = String(vb).toLowerCase();
|
|
164297
|
-
if (sa < sb) return -1 * dir;
|
|
164298
|
-
if (sa > sb) return 1 * dir;
|
|
164396
|
+
for (const { desc, col } of resolved2) {
|
|
164397
|
+
const cmp2 = compareCellValues(getCellValue(a5, col), getCellValue(b5, col));
|
|
164398
|
+
if (cmp2 !== 0) return desc.dir === "asc" ? cmp2 : -cmp2;
|
|
164399
|
+
}
|
|
164299
164400
|
return 0;
|
|
164300
164401
|
});
|
|
164301
164402
|
return arr;
|
|
@@ -164448,7 +164549,13 @@ __name(compileLucenePredicate, "compileLucenePredicate");
|
|
|
164448
164549
|
init_dist_ts30();
|
|
164449
164550
|
init_dist_ts29();
|
|
164450
164551
|
init_theme();
|
|
164451
|
-
var _selectedIds_dec, _selectionMode_dec, _searchMode_dec,
|
|
164552
|
+
var _selectedIds_dec, _selectionMode_dec, _searchMode_dec, _fixedHeight_dec, _showColumnFilters_dec, _columnFilters_dec, _filterText_dec, _sortBy_dec, _showGrid_dec, _showHorizontalLines_dec, _showVerticalLines_dec, _editableFields_dec, _selectedDataRow_dec, _reverseDisplayFunction_dec, _displayFunction_dec, _augmentFromDisplayFunction_dec, _rowKey_dec, _columns_dec, _dataActions_dec, _searchable_dec, _dataName_dec, _required_dec3, _disabled_dec3, _label_dec3, _key_dec2, _data_dec, _heading2_dec, _heading1_dec, _a42, _DeesTable_decorators, _init39, _heading1, _heading22, _data, _key2, _label3, _disabled3, _required3, _dataName, _searchable, _dataActions, _columns, _rowKey, _augmentFromDisplayFunction, _displayFunction, _reverseDisplayFunction, _selectedDataRow, _editableFields, _showVerticalLines, _showHorizontalLines, _showGrid, _sortBy, _filterText, _columnFilters, _showColumnFilters, _fixedHeight, _searchMode, _selectionMode, _selectedIds;
|
|
164553
|
+
function ordinalLabel(n12) {
|
|
164554
|
+
const s10 = ["th", "st", "nd", "rd"];
|
|
164555
|
+
const v5 = n12 % 100;
|
|
164556
|
+
return n12 + (s10[(v5 - 20) % 10] || s10[v5] || s10[0]);
|
|
164557
|
+
}
|
|
164558
|
+
__name(ordinalLabel, "ordinalLabel");
|
|
164452
164559
|
_DeesTable_decorators = [customElement("dees-table")];
|
|
164453
164560
|
var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [n5({
|
|
164454
164561
|
type: String
|
|
@@ -164491,7 +164598,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164491
164598
|
type: Boolean,
|
|
164492
164599
|
reflect: true,
|
|
164493
164600
|
attribute: "show-grid"
|
|
164494
|
-
})],
|
|
164601
|
+
})], _sortBy_dec = [n5({ attribute: false })], _filterText_dec = [n5({ type: String })], _columnFilters_dec = [n5({ attribute: false })], _showColumnFilters_dec = [n5({ type: Boolean, attribute: "show-column-filters" })], _fixedHeight_dec = [n5({ type: Boolean, reflect: true, attribute: "fixed-height" })], _searchMode_dec = [n5({ type: String })], _selectionMode_dec = [n5({ type: String })], _selectedIds_dec = [n5({ attribute: false })], _a42) {
|
|
164495
164602
|
constructor() {
|
|
164496
164603
|
super();
|
|
164497
164604
|
__privateAdd(this, _heading1, __runInitializers(_init39, 8, this, "heading 1")), __runInitializers(_init39, 11, this);
|
|
@@ -164518,19 +164625,23 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164518
164625
|
__publicField(this, "files", []);
|
|
164519
164626
|
__publicField(this, "fileWeakMap", /* @__PURE__ */ new WeakMap());
|
|
164520
164627
|
__publicField(this, "dataChangeSubject", new domtools_pluginexports_exports.smartrx.rxjs.Subject());
|
|
164521
|
-
__privateAdd(this,
|
|
164522
|
-
__privateAdd(this,
|
|
164523
|
-
__privateAdd(this,
|
|
164524
|
-
__privateAdd(this,
|
|
164525
|
-
__privateAdd(this,
|
|
164526
|
-
__privateAdd(this,
|
|
164527
|
-
__privateAdd(this, _searchMode, __runInitializers(_init39, 112, this, "table")), __runInitializers(_init39, 115, this);
|
|
164628
|
+
__privateAdd(this, _sortBy, __runInitializers(_init39, 88, this, [])), __runInitializers(_init39, 91, this);
|
|
164629
|
+
__privateAdd(this, _filterText, __runInitializers(_init39, 92, this, "")), __runInitializers(_init39, 95, this);
|
|
164630
|
+
__privateAdd(this, _columnFilters, __runInitializers(_init39, 96, this, {})), __runInitializers(_init39, 99, this);
|
|
164631
|
+
__privateAdd(this, _showColumnFilters, __runInitializers(_init39, 100, this, false)), __runInitializers(_init39, 103, this);
|
|
164632
|
+
__privateAdd(this, _fixedHeight, __runInitializers(_init39, 104, this, false)), __runInitializers(_init39, 107, this);
|
|
164633
|
+
__privateAdd(this, _searchMode, __runInitializers(_init39, 108, this, "table")), __runInitializers(_init39, 111, this);
|
|
164528
164634
|
__publicField(this, "__searchTextSub");
|
|
164529
164635
|
__publicField(this, "__searchModeSub");
|
|
164530
|
-
__privateAdd(this, _selectionMode, __runInitializers(_init39,
|
|
164531
|
-
__privateAdd(this, _selectedIds, __runInitializers(_init39,
|
|
164636
|
+
__privateAdd(this, _selectionMode, __runInitializers(_init39, 112, this, "none")), __runInitializers(_init39, 115, this);
|
|
164637
|
+
__privateAdd(this, _selectedIds, __runInitializers(_init39, 116, this, /* @__PURE__ */ new Set())), __runInitializers(_init39, 119, this);
|
|
164532
164638
|
__publicField(this, "_rowIdMap", /* @__PURE__ */ new WeakMap());
|
|
164533
164639
|
__publicField(this, "_rowIdCounter", 0);
|
|
164640
|
+
// ─── Floating header (page-sticky) lifecycle ─────────────────────────
|
|
164641
|
+
__publicField(this, "__floatingResizeObserver");
|
|
164642
|
+
__publicField(this, "__floatingScrollHandler");
|
|
164643
|
+
__publicField(this, "__floatingActive", false);
|
|
164644
|
+
__publicField(this, "__scrollAncestors", []);
|
|
164534
164645
|
__publicField(this, "__debounceTimer");
|
|
164535
164646
|
}
|
|
164536
164647
|
get value() {
|
|
@@ -164549,8 +164660,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164549
164660
|
const viewData = getViewData(
|
|
164550
164661
|
this.data,
|
|
164551
164662
|
effectiveColumns,
|
|
164552
|
-
this.
|
|
164553
|
-
this.sortDir,
|
|
164663
|
+
this.sortBy,
|
|
164554
164664
|
this.filterText,
|
|
164555
164665
|
this.columnFilters,
|
|
164556
164666
|
this.searchMode === "data" ? "data" : "table",
|
|
@@ -164622,57 +164732,7 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164622
164732
|
<div class="tableScroll">
|
|
164623
164733
|
<table>
|
|
164624
164734
|
<thead>
|
|
164625
|
-
|
|
164626
|
-
${this.selectionMode !== "none" ? b2`
|
|
164627
|
-
<th style="width:42px; text-align:center;">
|
|
164628
|
-
${this.selectionMode === "multi" ? b2`
|
|
164629
|
-
<dees-input-checkbox
|
|
164630
|
-
.value=${this.areAllVisibleSelected()}
|
|
164631
|
-
.indeterminate=${this.isVisibleSelectionIndeterminate()}
|
|
164632
|
-
@newValue=${(e11) => {
|
|
164633
|
-
e11.stopPropagation();
|
|
164634
|
-
this.setSelectVisible(e11.detail === true);
|
|
164635
|
-
}}
|
|
164636
|
-
></dees-input-checkbox>
|
|
164637
|
-
` : b2``}
|
|
164638
|
-
</th>
|
|
164639
|
-
` : b2``}
|
|
164640
|
-
${effectiveColumns.filter((c11) => !c11.hidden).map((col) => {
|
|
164641
|
-
const isSortable = !!col.sortable;
|
|
164642
|
-
const ariaSort = this.getAriaSort(col);
|
|
164643
|
-
return b2`
|
|
164644
|
-
<th
|
|
164645
|
-
role="columnheader"
|
|
164646
|
-
aria-sort=${ariaSort}
|
|
164647
|
-
style="${isSortable ? "cursor: pointer;" : ""}"
|
|
164648
|
-
@click=${() => isSortable ? this.toggleSort(col) : null}
|
|
164649
|
-
>
|
|
164650
|
-
${col.header ?? col.key}
|
|
164651
|
-
${this.renderSortIndicator(col)}
|
|
164652
|
-
</th>`;
|
|
164653
|
-
})}
|
|
164654
|
-
${(() => {
|
|
164655
|
-
if (this.dataActions && this.dataActions.length > 0) {
|
|
164656
|
-
return b2` <th class="actionsCol">Actions</th> `;
|
|
164657
|
-
}
|
|
164658
|
-
})()}
|
|
164659
|
-
</tr>
|
|
164660
|
-
${this.showColumnFilters ? b2`<tr class="filtersRow">
|
|
164661
|
-
${this.selectionMode !== "none" ? b2`<th style="width:42px;"></th>` : b2``}
|
|
164662
|
-
${effectiveColumns.filter((c11) => !c11.hidden).map((col) => {
|
|
164663
|
-
const key2 = String(col.key);
|
|
164664
|
-
if (col.filterable === false) return b2`<th></th>`;
|
|
164665
|
-
return b2`<th>
|
|
164666
|
-
<input type="text" placeholder="Filter..." .value=${this.columnFilters[key2] || ""}
|
|
164667
|
-
@input=${(e11) => this.setColumnFilter(key2, e11.target.value)} />
|
|
164668
|
-
</th>`;
|
|
164669
|
-
})}
|
|
164670
|
-
${(() => {
|
|
164671
|
-
if (this.dataActions && this.dataActions.length > 0) {
|
|
164672
|
-
return b2` <th></th> `;
|
|
164673
|
-
}
|
|
164674
|
-
})()}
|
|
164675
|
-
</tr>` : b2``}
|
|
164735
|
+
${this.renderHeaderRows(effectiveColumns)}
|
|
164676
164736
|
</thead>
|
|
164677
164737
|
<tbody>
|
|
164678
164738
|
${viewData.map((itemArg, rowIndex) => {
|
|
@@ -164806,6 +164866,13 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164806
164866
|
</tbody>
|
|
164807
164867
|
</table>
|
|
164808
164868
|
</div>
|
|
164869
|
+
<div class="floatingHeader" aria-hidden="true">
|
|
164870
|
+
<table>
|
|
164871
|
+
<thead>
|
|
164872
|
+
${this.renderHeaderRows(effectiveColumns)}
|
|
164873
|
+
</thead>
|
|
164874
|
+
</table>
|
|
164875
|
+
</div>
|
|
164809
164876
|
` : b2` <div class="noDataSet">No data set!</div> `}
|
|
164810
164877
|
<div slot="footer" class="footer">
|
|
164811
164878
|
<div class="tableStatistics">
|
|
@@ -164840,11 +164907,226 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164840
164907
|
</dees-tile>
|
|
164841
164908
|
`;
|
|
164842
164909
|
}
|
|
164910
|
+
/**
|
|
164911
|
+
* Renders the header rows. Used twice per render: once inside the real
|
|
164912
|
+
* `<thead>` and once inside the floating-header clone, so sort indicators
|
|
164913
|
+
* and filter inputs stay in sync automatically.
|
|
164914
|
+
*/
|
|
164915
|
+
renderHeaderRows(effectiveColumns) {
|
|
164916
|
+
return b2`
|
|
164917
|
+
<tr>
|
|
164918
|
+
${this.selectionMode !== "none" ? b2`
|
|
164919
|
+
<th style="width:42px; text-align:center;">
|
|
164920
|
+
${this.selectionMode === "multi" ? b2`
|
|
164921
|
+
<dees-input-checkbox
|
|
164922
|
+
.value=${this.areAllVisibleSelected()}
|
|
164923
|
+
.indeterminate=${this.isVisibleSelectionIndeterminate()}
|
|
164924
|
+
@newValue=${(e11) => {
|
|
164925
|
+
e11.stopPropagation();
|
|
164926
|
+
this.setSelectVisible(e11.detail === true);
|
|
164927
|
+
}}
|
|
164928
|
+
></dees-input-checkbox>
|
|
164929
|
+
` : b2``}
|
|
164930
|
+
</th>
|
|
164931
|
+
` : b2``}
|
|
164932
|
+
${effectiveColumns.filter((c11) => !c11.hidden).map((col) => {
|
|
164933
|
+
const isSortable = !!col.sortable;
|
|
164934
|
+
const ariaSort = this.getAriaSort(col);
|
|
164935
|
+
return b2`
|
|
164936
|
+
<th
|
|
164937
|
+
role="columnheader"
|
|
164938
|
+
aria-sort=${ariaSort}
|
|
164939
|
+
style="${isSortable ? "cursor: pointer;" : ""}"
|
|
164940
|
+
@click=${(eventArg) => isSortable ? this.handleHeaderClick(eventArg, col, effectiveColumns) : null}
|
|
164941
|
+
@contextmenu=${(eventArg) => isSortable ? this.openHeaderContextMenu(eventArg, col, effectiveColumns) : null}
|
|
164942
|
+
>
|
|
164943
|
+
${col.header ?? col.key}
|
|
164944
|
+
${this.renderSortIndicator(col)}
|
|
164945
|
+
</th>`;
|
|
164946
|
+
})}
|
|
164947
|
+
${this.dataActions && this.dataActions.length > 0 ? b2`<th class="actionsCol">Actions</th>` : b2``}
|
|
164948
|
+
</tr>
|
|
164949
|
+
${this.showColumnFilters ? b2`<tr class="filtersRow">
|
|
164950
|
+
${this.selectionMode !== "none" ? b2`<th style="width:42px;"></th>` : b2``}
|
|
164951
|
+
${effectiveColumns.filter((c11) => !c11.hidden).map((col) => {
|
|
164952
|
+
const key2 = String(col.key);
|
|
164953
|
+
if (col.filterable === false) return b2`<th></th>`;
|
|
164954
|
+
return b2`<th>
|
|
164955
|
+
<input type="text" placeholder="Filter..." .value=${this.columnFilters[key2] || ""}
|
|
164956
|
+
@input=${(e11) => this.setColumnFilter(key2, e11.target.value)} />
|
|
164957
|
+
</th>`;
|
|
164958
|
+
})}
|
|
164959
|
+
${this.dataActions && this.dataActions.length > 0 ? b2`<th></th>` : b2``}
|
|
164960
|
+
</tr>` : b2``}
|
|
164961
|
+
`;
|
|
164962
|
+
}
|
|
164963
|
+
get __floatingHeaderEl() {
|
|
164964
|
+
return this.shadowRoot?.querySelector(".floatingHeader") ?? null;
|
|
164965
|
+
}
|
|
164966
|
+
get __realTableEl() {
|
|
164967
|
+
return this.shadowRoot?.querySelector(".tableScroll > table") ?? null;
|
|
164968
|
+
}
|
|
164969
|
+
get __floatingTableEl() {
|
|
164970
|
+
return this.shadowRoot?.querySelector(".floatingHeader > table") ?? null;
|
|
164971
|
+
}
|
|
164972
|
+
/**
|
|
164973
|
+
* Walks up the DOM (and through shadow roots) collecting every ancestor
|
|
164974
|
+
* element whose computed `overflow-y` makes it a scroll container, plus
|
|
164975
|
+
* `window` at the end. We listen for scroll on all of them so the floating
|
|
164976
|
+
* header reacts whether the user scrolls the page or any nested container.
|
|
164977
|
+
*/
|
|
164978
|
+
__collectScrollAncestors() {
|
|
164979
|
+
const result = [];
|
|
164980
|
+
let node2 = this;
|
|
164981
|
+
const scrollish = /* @__PURE__ */ __name((v5) => v5 === "auto" || v5 === "scroll" || v5 === "overlay", "scrollish");
|
|
164982
|
+
while (node2) {
|
|
164983
|
+
if (node2 instanceof Element) {
|
|
164984
|
+
const style2 = getComputedStyle(node2);
|
|
164985
|
+
const sy = scrollish(style2.overflowY);
|
|
164986
|
+
const sx = scrollish(style2.overflowX);
|
|
164987
|
+
if (sy || sx) {
|
|
164988
|
+
result.push({ target: node2, scrollsY: sy, scrollsX: sx });
|
|
164989
|
+
}
|
|
164990
|
+
}
|
|
164991
|
+
const parent = node2.assignedSlot ? node2.assignedSlot : node2.parentNode;
|
|
164992
|
+
if (parent) {
|
|
164993
|
+
node2 = parent;
|
|
164994
|
+
} else if (node2.host) {
|
|
164995
|
+
node2 = node2.host;
|
|
164996
|
+
} else {
|
|
164997
|
+
node2 = null;
|
|
164998
|
+
}
|
|
164999
|
+
}
|
|
165000
|
+
result.push({ target: window, scrollsY: true, scrollsX: true });
|
|
165001
|
+
return result;
|
|
165002
|
+
}
|
|
165003
|
+
/**
|
|
165004
|
+
* Returns the "stick line" — the y-coordinate (in viewport space) at which
|
|
165005
|
+
* the floating header should appear. Defaults to 0 (page top), but if the
|
|
165006
|
+
* table is inside a scroll container we use that container's content-box
|
|
165007
|
+
* top so the header sits inside the container's border/padding instead of
|
|
165008
|
+
* floating over it.
|
|
165009
|
+
*/
|
|
165010
|
+
__getStickContext() {
|
|
165011
|
+
let top = 0;
|
|
165012
|
+
let left = 0;
|
|
165013
|
+
let right = window.innerWidth;
|
|
165014
|
+
for (const a5 of this.__scrollAncestors) {
|
|
165015
|
+
if (a5.target === window) continue;
|
|
165016
|
+
const el = a5.target;
|
|
165017
|
+
const r11 = el.getBoundingClientRect();
|
|
165018
|
+
const cs = getComputedStyle(el);
|
|
165019
|
+
if (a5.scrollsY) {
|
|
165020
|
+
const bt = parseFloat(cs.borderTopWidth) || 0;
|
|
165021
|
+
top = Math.max(top, r11.top + bt);
|
|
165022
|
+
}
|
|
165023
|
+
if (a5.scrollsX) {
|
|
165024
|
+
const bl = parseFloat(cs.borderLeftWidth) || 0;
|
|
165025
|
+
const br = parseFloat(cs.borderRightWidth) || 0;
|
|
165026
|
+
left = Math.max(left, r11.left + bl);
|
|
165027
|
+
right = Math.min(right, r11.right - br);
|
|
165028
|
+
}
|
|
165029
|
+
}
|
|
165030
|
+
return { top, left, right };
|
|
165031
|
+
}
|
|
165032
|
+
setupFloatingHeader() {
|
|
165033
|
+
this.teardownFloatingHeader();
|
|
165034
|
+
if (this.fixedHeight) return;
|
|
165035
|
+
const realTable = this.__realTableEl;
|
|
165036
|
+
if (!realTable) return;
|
|
165037
|
+
this.__scrollAncestors = this.__collectScrollAncestors();
|
|
165038
|
+
const tableScrollEl = this.shadowRoot?.querySelector(".tableScroll");
|
|
165039
|
+
if (tableScrollEl) {
|
|
165040
|
+
this.__scrollAncestors.unshift({ target: tableScrollEl, scrollsY: false, scrollsX: true });
|
|
165041
|
+
}
|
|
165042
|
+
this.__floatingResizeObserver = new ResizeObserver(() => {
|
|
165043
|
+
this.__syncFloatingHeader();
|
|
165044
|
+
});
|
|
165045
|
+
this.__floatingResizeObserver.observe(realTable);
|
|
165046
|
+
this.__floatingScrollHandler = () => this.__syncFloatingHeader();
|
|
165047
|
+
for (const a5 of this.__scrollAncestors) {
|
|
165048
|
+
a5.target.addEventListener("scroll", this.__floatingScrollHandler, { passive: true });
|
|
165049
|
+
}
|
|
165050
|
+
window.addEventListener("resize", this.__floatingScrollHandler, { passive: true });
|
|
165051
|
+
this.__syncFloatingHeader();
|
|
165052
|
+
}
|
|
165053
|
+
teardownFloatingHeader() {
|
|
165054
|
+
this.__floatingResizeObserver?.disconnect();
|
|
165055
|
+
this.__floatingResizeObserver = void 0;
|
|
165056
|
+
if (this.__floatingScrollHandler) {
|
|
165057
|
+
for (const a5 of this.__scrollAncestors) {
|
|
165058
|
+
a5.target.removeEventListener("scroll", this.__floatingScrollHandler);
|
|
165059
|
+
}
|
|
165060
|
+
window.removeEventListener("resize", this.__floatingScrollHandler);
|
|
165061
|
+
this.__floatingScrollHandler = void 0;
|
|
165062
|
+
}
|
|
165063
|
+
this.__scrollAncestors = [];
|
|
165064
|
+
this.__floatingActive = false;
|
|
165065
|
+
const fh = this.__floatingHeaderEl;
|
|
165066
|
+
if (fh) fh.classList.remove("active");
|
|
165067
|
+
}
|
|
165068
|
+
/**
|
|
165069
|
+
* Single function that drives both activation and geometry of the floating
|
|
165070
|
+
* header. Called on scroll, resize, table-resize, and after each render.
|
|
165071
|
+
*/
|
|
165072
|
+
__syncFloatingHeader() {
|
|
165073
|
+
const fh = this.__floatingHeaderEl;
|
|
165074
|
+
const realTable = this.__realTableEl;
|
|
165075
|
+
const floatTable = this.__floatingTableEl;
|
|
165076
|
+
if (!fh || !realTable || !floatTable) return;
|
|
165077
|
+
const tableRect = realTable.getBoundingClientRect();
|
|
165078
|
+
const stick = this.__getStickContext();
|
|
165079
|
+
floatTable.style.tableLayout = realTable.style.tableLayout || "auto";
|
|
165080
|
+
const realHeadRows = realTable.tHead?.rows;
|
|
165081
|
+
const floatHeadRows = floatTable.tHead?.rows;
|
|
165082
|
+
let headerHeight = 0;
|
|
165083
|
+
if (realHeadRows && floatHeadRows) {
|
|
165084
|
+
for (let r11 = 0; r11 < realHeadRows.length && r11 < floatHeadRows.length; r11++) {
|
|
165085
|
+
headerHeight += realHeadRows[r11].getBoundingClientRect().height;
|
|
165086
|
+
const realCells = realHeadRows[r11].cells;
|
|
165087
|
+
const floatCells = floatHeadRows[r11].cells;
|
|
165088
|
+
for (let c11 = 0; c11 < realCells.length && c11 < floatCells.length; c11++) {
|
|
165089
|
+
const w4 = realCells[c11].getBoundingClientRect().width;
|
|
165090
|
+
floatCells[c11].style.width = `${w4}px`;
|
|
165091
|
+
floatCells[c11].style.minWidth = `${w4}px`;
|
|
165092
|
+
floatCells[c11].style.maxWidth = `${w4}px`;
|
|
165093
|
+
}
|
|
165094
|
+
}
|
|
165095
|
+
}
|
|
165096
|
+
const shouldBeActive = tableRect.top < stick.top && tableRect.bottom > stick.top + Math.min(headerHeight, 1);
|
|
165097
|
+
if (shouldBeActive !== this.__floatingActive) {
|
|
165098
|
+
this.__floatingActive = shouldBeActive;
|
|
165099
|
+
fh.classList.toggle("active", shouldBeActive);
|
|
165100
|
+
}
|
|
165101
|
+
if (!shouldBeActive) return;
|
|
165102
|
+
const clipLeft = Math.max(tableRect.left, stick.left);
|
|
165103
|
+
const clipRight = Math.min(tableRect.right, stick.right);
|
|
165104
|
+
const clipWidth = Math.max(0, clipRight - clipLeft);
|
|
165105
|
+
fh.style.top = `${stick.top}px`;
|
|
165106
|
+
fh.style.left = `${clipLeft}px`;
|
|
165107
|
+
fh.style.width = `${clipWidth}px`;
|
|
165108
|
+
floatTable.style.width = `${tableRect.width}px`;
|
|
165109
|
+
floatTable.style.marginLeft = `${tableRect.left - clipLeft}px`;
|
|
165110
|
+
}
|
|
165111
|
+
async disconnectedCallback() {
|
|
165112
|
+
super.disconnectedCallback();
|
|
165113
|
+
this.teardownFloatingHeader();
|
|
165114
|
+
}
|
|
164843
165115
|
async firstUpdated() {
|
|
164844
165116
|
}
|
|
164845
165117
|
async updated(changedProperties) {
|
|
164846
165118
|
super.updated(changedProperties);
|
|
164847
165119
|
this.determineColumnWidths();
|
|
165120
|
+
if (changedProperties.has("fixedHeight") || changedProperties.has("data") || changedProperties.has("columns") || !this.__floatingScrollHandler) {
|
|
165121
|
+
if (!this.fixedHeight && this.data.length > 0) {
|
|
165122
|
+
this.setupFloatingHeader();
|
|
165123
|
+
} else {
|
|
165124
|
+
this.teardownFloatingHeader();
|
|
165125
|
+
}
|
|
165126
|
+
}
|
|
165127
|
+
if (!this.fixedHeight && this.data.length > 0) {
|
|
165128
|
+
this.__syncFloatingHeader();
|
|
165129
|
+
}
|
|
164848
165130
|
if (this.searchable) {
|
|
164849
165131
|
const existing = this.dataActions.find((actionArg) => actionArg.type?.includes("header") && actionArg.name === "Search");
|
|
164850
165132
|
if (!existing) {
|
|
@@ -164941,33 +165223,302 @@ var _DeesTable = class _DeesTable extends (_a42 = DeesElement, _heading1_dec = [
|
|
|
164941
165223
|
table2.style.tableLayout = "fixed";
|
|
164942
165224
|
}
|
|
164943
165225
|
// compute helpers moved to ./data.ts
|
|
164944
|
-
|
|
164945
|
-
|
|
164946
|
-
|
|
164947
|
-
|
|
164948
|
-
|
|
164949
|
-
|
|
164950
|
-
|
|
164951
|
-
|
|
164952
|
-
|
|
164953
|
-
|
|
164954
|
-
|
|
164955
|
-
}
|
|
165226
|
+
// ─── sort: public API ────────────────────────────────────────────────
|
|
165227
|
+
/** Returns the descriptor for `key` if the column is currently in the cascade. */
|
|
165228
|
+
getSortDescriptor(key2) {
|
|
165229
|
+
return this.sortBy.find((d6) => d6.key === key2);
|
|
165230
|
+
}
|
|
165231
|
+
/** Returns the 0-based priority of `key` in the cascade, or -1 if not present. */
|
|
165232
|
+
getSortPriority(key2) {
|
|
165233
|
+
return this.sortBy.findIndex((d6) => d6.key === key2);
|
|
165234
|
+
}
|
|
165235
|
+
/** Replaces the cascade with a single sort entry. */
|
|
165236
|
+
setSort(key2, dir) {
|
|
165237
|
+
this.sortBy = [{ key: key2, dir }];
|
|
165238
|
+
this.emitSortChange();
|
|
165239
|
+
this.requestUpdate();
|
|
165240
|
+
}
|
|
165241
|
+
/**
|
|
165242
|
+
* Inserts (or moves) `key` to a 0-based position in the cascade. If the key is
|
|
165243
|
+
* already present elsewhere, its previous entry is removed before insertion so
|
|
165244
|
+
* a column appears at most once.
|
|
165245
|
+
*/
|
|
165246
|
+
addSortAt(key2, position3, dir) {
|
|
165247
|
+
const next2 = this.sortBy.filter((d6) => d6.key !== key2);
|
|
165248
|
+
const clamped = Math.max(0, Math.min(position3, next2.length));
|
|
165249
|
+
next2.splice(clamped, 0, { key: key2, dir });
|
|
165250
|
+
this.sortBy = next2;
|
|
165251
|
+
this.emitSortChange();
|
|
165252
|
+
this.requestUpdate();
|
|
165253
|
+
}
|
|
165254
|
+
/** Appends `key` to the end of the cascade (or moves it there if already present). */
|
|
165255
|
+
appendSort(key2, dir) {
|
|
165256
|
+
const next2 = this.sortBy.filter((d6) => d6.key !== key2);
|
|
165257
|
+
next2.push({ key: key2, dir });
|
|
165258
|
+
this.sortBy = next2;
|
|
165259
|
+
this.emitSortChange();
|
|
165260
|
+
this.requestUpdate();
|
|
165261
|
+
}
|
|
165262
|
+
/** Removes `key` from the cascade. No-op if not present. */
|
|
165263
|
+
removeSort(key2) {
|
|
165264
|
+
if (!this.sortBy.some((d6) => d6.key === key2)) return;
|
|
165265
|
+
this.sortBy = this.sortBy.filter((d6) => d6.key !== key2);
|
|
165266
|
+
this.emitSortChange();
|
|
165267
|
+
this.requestUpdate();
|
|
165268
|
+
}
|
|
165269
|
+
/** Empties the cascade. */
|
|
165270
|
+
clearSorts() {
|
|
165271
|
+
if (this.sortBy.length === 0) return;
|
|
165272
|
+
this.sortBy = [];
|
|
165273
|
+
this.emitSortChange();
|
|
165274
|
+
this.requestUpdate();
|
|
165275
|
+
}
|
|
165276
|
+
emitSortChange() {
|
|
164956
165277
|
this.dispatchEvent(
|
|
164957
165278
|
new CustomEvent("sortChange", {
|
|
164958
|
-
detail: {
|
|
165279
|
+
detail: { sortBy: this.sortBy.map((d6) => ({ ...d6 })) },
|
|
164959
165280
|
bubbles: true
|
|
164960
165281
|
})
|
|
164961
165282
|
);
|
|
164962
|
-
this.requestUpdate();
|
|
164963
165283
|
}
|
|
165284
|
+
// ─── sort: header interaction handlers ───────────────────────────────
|
|
165285
|
+
/**
|
|
165286
|
+
* Plain left-click on a sortable header. Cycles `none → asc → desc → none`
|
|
165287
|
+
* collapsing the cascade to a single column. If a multi-column cascade is
|
|
165288
|
+
* active, asks the user to confirm the destructive replacement first. A
|
|
165289
|
+
* Shift+click bypasses the modal and routes through the multi-sort cycle.
|
|
165290
|
+
*/
|
|
165291
|
+
async handleHeaderClick(eventArg, col, _effectiveColumns) {
|
|
165292
|
+
if (eventArg.shiftKey) {
|
|
165293
|
+
this.handleHeaderShiftClick(col);
|
|
165294
|
+
return;
|
|
165295
|
+
}
|
|
165296
|
+
const proceed = await this.confirmReplaceCascade(col);
|
|
165297
|
+
if (!proceed) return;
|
|
165298
|
+
this.cycleSingleSort(col);
|
|
165299
|
+
}
|
|
165300
|
+
/**
|
|
165301
|
+
* Cycles a single column through `none → asc → desc → none`, collapsing the
|
|
165302
|
+
* cascade. Used by both plain click and the menu's "Sort Ascending/Descending"
|
|
165303
|
+
* shortcuts (after confirmation).
|
|
165304
|
+
*/
|
|
165305
|
+
cycleSingleSort(col) {
|
|
165306
|
+
const key2 = String(col.key);
|
|
165307
|
+
const current = this.sortBy.length === 1 && this.sortBy[0].key === key2 ? this.sortBy[0].dir : null;
|
|
165308
|
+
if (current === "asc") this.setSort(key2, "desc");
|
|
165309
|
+
else if (current === "desc") this.clearSorts();
|
|
165310
|
+
else this.setSort(key2, "asc");
|
|
165311
|
+
}
|
|
165312
|
+
/**
|
|
165313
|
+
* Shift+click cycle on a sortable header. Edits the cascade in place without
|
|
165314
|
+
* destroying other sort keys: append → flip dir → remove.
|
|
165315
|
+
*/
|
|
165316
|
+
handleHeaderShiftClick(col) {
|
|
165317
|
+
const key2 = String(col.key);
|
|
165318
|
+
const existing = this.getSortDescriptor(key2);
|
|
165319
|
+
if (!existing) {
|
|
165320
|
+
this.appendSort(key2, "asc");
|
|
165321
|
+
} else if (existing.dir === "asc") {
|
|
165322
|
+
this.sortBy = this.sortBy.map((d6) => d6.key === key2 ? { key: key2, dir: "desc" } : d6);
|
|
165323
|
+
this.emitSortChange();
|
|
165324
|
+
this.requestUpdate();
|
|
165325
|
+
} else {
|
|
165326
|
+
this.removeSort(key2);
|
|
165327
|
+
}
|
|
165328
|
+
}
|
|
165329
|
+
/**
|
|
165330
|
+
* Opens a confirmation modal when the cascade has more than one entry and the
|
|
165331
|
+
* user attempts a destructive single-sort replacement. Resolves to `true` if
|
|
165332
|
+
* the user accepts, `false` if they cancel. If the cascade has 0 or 1 entries
|
|
165333
|
+
* the modal is skipped and we resolve to `true` immediately.
|
|
165334
|
+
*/
|
|
165335
|
+
confirmReplaceCascade(targetCol) {
|
|
165336
|
+
if (this.sortBy.length <= 1) return Promise.resolve(true);
|
|
165337
|
+
return new Promise((resolve2) => {
|
|
165338
|
+
let settled = false;
|
|
165339
|
+
const settle = /* @__PURE__ */ __name((result) => {
|
|
165340
|
+
if (settled) return;
|
|
165341
|
+
settled = true;
|
|
165342
|
+
resolve2(result);
|
|
165343
|
+
}, "settle");
|
|
165344
|
+
const summary = this.sortBy.map((d6, i11) => {
|
|
165345
|
+
const c11 = this._lookupColumnByKey?.(d6.key);
|
|
165346
|
+
const label = c11?.header ?? d6.key;
|
|
165347
|
+
return b2`<li>${i11 + 1}. ${label} ${d6.dir === "asc" ? "\u25B2" : "\u25BC"}</li>`;
|
|
165348
|
+
});
|
|
165349
|
+
DeesModal.createAndShow({
|
|
165350
|
+
heading: "Replace multi-column sort?",
|
|
165351
|
+
width: "small",
|
|
165352
|
+
showCloseButton: true,
|
|
165353
|
+
content: b2`
|
|
165354
|
+
<div style="font-size:13px; line-height:1.55;">
|
|
165355
|
+
<p style="margin:0 0 8px;">
|
|
165356
|
+
You currently have a ${this.sortBy.length}-column sort active:
|
|
165357
|
+
</p>
|
|
165358
|
+
<ul style="margin:0 0 12px; padding-left:18px;">${summary}</ul>
|
|
165359
|
+
<p style="margin:0;">
|
|
165360
|
+
Continuing will discard the cascade and replace it with a single sort on
|
|
165361
|
+
<strong>${targetCol.header ?? String(targetCol.key)}</strong>.
|
|
165362
|
+
</p>
|
|
165363
|
+
</div>
|
|
165364
|
+
`,
|
|
165365
|
+
menuOptions: [
|
|
165366
|
+
{
|
|
165367
|
+
name: "Cancel",
|
|
165368
|
+
iconName: "lucide:x",
|
|
165369
|
+
action: /* @__PURE__ */ __name(async (modal) => {
|
|
165370
|
+
settle(false);
|
|
165371
|
+
await modal.destroy();
|
|
165372
|
+
return null;
|
|
165373
|
+
}, "action")
|
|
165374
|
+
},
|
|
165375
|
+
{
|
|
165376
|
+
name: "Replace",
|
|
165377
|
+
iconName: "lucide:check",
|
|
165378
|
+
action: /* @__PURE__ */ __name(async (modal) => {
|
|
165379
|
+
settle(true);
|
|
165380
|
+
await modal.destroy();
|
|
165381
|
+
return null;
|
|
165382
|
+
}, "action")
|
|
165383
|
+
}
|
|
165384
|
+
]
|
|
165385
|
+
});
|
|
165386
|
+
});
|
|
165387
|
+
}
|
|
165388
|
+
/**
|
|
165389
|
+
* Looks up a column by its string key in the currently effective column set.
|
|
165390
|
+
* Used by the modal helper to render human-friendly labels.
|
|
165391
|
+
*/
|
|
165392
|
+
_lookupColumnByKey(key2) {
|
|
165393
|
+
const usingColumns = Array.isArray(this.columns) && this.columns.length > 0;
|
|
165394
|
+
const effective = usingColumns ? computeEffectiveColumns(this.columns, this.augmentFromDisplayFunction, this.displayFunction, this.data) : computeColumnsFromDisplayFunction(this.displayFunction, this.data);
|
|
165395
|
+
return effective.find((c11) => String(c11.key) === key2);
|
|
165396
|
+
}
|
|
165397
|
+
/**
|
|
165398
|
+
* Opens the header context menu for explicit multi-sort priority control.
|
|
165399
|
+
*/
|
|
165400
|
+
openHeaderContextMenu(eventArg, col, effectiveColumns) {
|
|
165401
|
+
const items = this.buildHeaderMenuItems(col, effectiveColumns);
|
|
165402
|
+
DeesContextmenu.openContextMenuWithOptions(eventArg, items);
|
|
165403
|
+
}
|
|
165404
|
+
/**
|
|
165405
|
+
* Builds the dynamic context-menu structure for a single column header.
|
|
165406
|
+
*/
|
|
165407
|
+
buildHeaderMenuItems(col, effectiveColumns) {
|
|
165408
|
+
const key2 = String(col.key);
|
|
165409
|
+
const existing = this.getSortDescriptor(key2);
|
|
165410
|
+
const cascadeLen = this.sortBy.length;
|
|
165411
|
+
const sortableColumnCount = effectiveColumns.filter((c11) => !!c11.sortable).length;
|
|
165412
|
+
const maxSlot = Math.min(
|
|
165413
|
+
Math.max(cascadeLen + (existing ? 0 : 1), 1),
|
|
165414
|
+
Math.max(sortableColumnCount, 1)
|
|
165415
|
+
);
|
|
165416
|
+
const items = [];
|
|
165417
|
+
items.push({
|
|
165418
|
+
name: "Sort Ascending",
|
|
165419
|
+
iconName: cascadeLen === 1 && existing?.dir === "asc" ? "lucide:check" : "lucide:arrowUp",
|
|
165420
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165421
|
+
if (await this.confirmReplaceCascade(col)) this.setSort(key2, "asc");
|
|
165422
|
+
return null;
|
|
165423
|
+
}, "action")
|
|
165424
|
+
});
|
|
165425
|
+
items.push({
|
|
165426
|
+
name: "Sort Descending",
|
|
165427
|
+
iconName: cascadeLen === 1 && existing?.dir === "desc" ? "lucide:check" : "lucide:arrowDown",
|
|
165428
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165429
|
+
if (await this.confirmReplaceCascade(col)) this.setSort(key2, "desc");
|
|
165430
|
+
return null;
|
|
165431
|
+
}, "action")
|
|
165432
|
+
});
|
|
165433
|
+
items.push({ divider: true });
|
|
165434
|
+
for (let slot = 1; slot <= maxSlot; slot++) {
|
|
165435
|
+
const ordinal = ordinalLabel(slot);
|
|
165436
|
+
const isCurrentSlot = existing && this.getSortPriority(key2) === slot - 1;
|
|
165437
|
+
items.push({
|
|
165438
|
+
name: `Set as ${ordinal} sort`,
|
|
165439
|
+
iconName: isCurrentSlot ? "lucide:check" : "lucide:listOrdered",
|
|
165440
|
+
submenu: [
|
|
165441
|
+
{
|
|
165442
|
+
name: "Ascending",
|
|
165443
|
+
iconName: "lucide:arrowUp",
|
|
165444
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165445
|
+
this.addSortAt(key2, slot - 1, "asc");
|
|
165446
|
+
return null;
|
|
165447
|
+
}, "action")
|
|
165448
|
+
},
|
|
165449
|
+
{
|
|
165450
|
+
name: "Descending",
|
|
165451
|
+
iconName: "lucide:arrowDown",
|
|
165452
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165453
|
+
this.addSortAt(key2, slot - 1, "desc");
|
|
165454
|
+
return null;
|
|
165455
|
+
}, "action")
|
|
165456
|
+
}
|
|
165457
|
+
]
|
|
165458
|
+
});
|
|
165459
|
+
}
|
|
165460
|
+
items.push({ divider: true });
|
|
165461
|
+
items.push({
|
|
165462
|
+
name: "Append to sort",
|
|
165463
|
+
iconName: "lucide:plus",
|
|
165464
|
+
submenu: [
|
|
165465
|
+
{
|
|
165466
|
+
name: "Ascending",
|
|
165467
|
+
iconName: "lucide:arrowUp",
|
|
165468
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165469
|
+
this.appendSort(key2, "asc");
|
|
165470
|
+
return null;
|
|
165471
|
+
}, "action")
|
|
165472
|
+
},
|
|
165473
|
+
{
|
|
165474
|
+
name: "Descending",
|
|
165475
|
+
iconName: "lucide:arrowDown",
|
|
165476
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165477
|
+
this.appendSort(key2, "desc");
|
|
165478
|
+
return null;
|
|
165479
|
+
}, "action")
|
|
165480
|
+
}
|
|
165481
|
+
]
|
|
165482
|
+
});
|
|
165483
|
+
if (existing) {
|
|
165484
|
+
items.push({ divider: true });
|
|
165485
|
+
items.push({
|
|
165486
|
+
name: "Remove from sort",
|
|
165487
|
+
iconName: "lucide:minus",
|
|
165488
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165489
|
+
this.removeSort(key2);
|
|
165490
|
+
return null;
|
|
165491
|
+
}, "action")
|
|
165492
|
+
});
|
|
165493
|
+
}
|
|
165494
|
+
if (cascadeLen > 0) {
|
|
165495
|
+
if (!existing) items.push({ divider: true });
|
|
165496
|
+
items.push({
|
|
165497
|
+
name: "Clear all sorts",
|
|
165498
|
+
iconName: "lucide:trash",
|
|
165499
|
+
action: /* @__PURE__ */ __name(async () => {
|
|
165500
|
+
this.clearSorts();
|
|
165501
|
+
return null;
|
|
165502
|
+
}, "action")
|
|
165503
|
+
});
|
|
165504
|
+
}
|
|
165505
|
+
return items;
|
|
165506
|
+
}
|
|
165507
|
+
// ─── sort: indicator + ARIA ──────────────────────────────────────────
|
|
164964
165508
|
getAriaSort(col) {
|
|
164965
|
-
|
|
164966
|
-
|
|
165509
|
+
const primary = this.sortBy[0];
|
|
165510
|
+
if (!primary || primary.key !== String(col.key)) return "none";
|
|
165511
|
+
return primary.dir === "asc" ? "ascending" : "descending";
|
|
164967
165512
|
}
|
|
164968
165513
|
renderSortIndicator(col) {
|
|
164969
|
-
|
|
164970
|
-
|
|
165514
|
+
const idx = this.getSortPriority(String(col.key));
|
|
165515
|
+
if (idx < 0) return b2``;
|
|
165516
|
+
const desc = this.sortBy[idx];
|
|
165517
|
+
const arrow2 = desc.dir === "asc" ? "\u25B2" : "\u25BC";
|
|
165518
|
+
if (this.sortBy.length === 1) {
|
|
165519
|
+
return b2`<span class="sortArrow">${arrow2}</span>`;
|
|
165520
|
+
}
|
|
165521
|
+
return b2`<span class="sortArrow">${arrow2}</span><span class="sortBadge">${idx + 1}</span>`;
|
|
164971
165522
|
}
|
|
164972
165523
|
// filtering helpers
|
|
164973
165524
|
setFilterText(value2) {
|
|
@@ -165132,12 +165683,11 @@ _editableFields = new WeakMap();
|
|
|
165132
165683
|
_showVerticalLines = new WeakMap();
|
|
165133
165684
|
_showHorizontalLines = new WeakMap();
|
|
165134
165685
|
_showGrid = new WeakMap();
|
|
165135
|
-
|
|
165136
|
-
_sortDir = new WeakMap();
|
|
165686
|
+
_sortBy = new WeakMap();
|
|
165137
165687
|
_filterText = new WeakMap();
|
|
165138
165688
|
_columnFilters = new WeakMap();
|
|
165139
165689
|
_showColumnFilters = new WeakMap();
|
|
165140
|
-
|
|
165690
|
+
_fixedHeight = new WeakMap();
|
|
165141
165691
|
_searchMode = new WeakMap();
|
|
165142
165692
|
_selectionMode = new WeakMap();
|
|
165143
165693
|
_selectedIds = new WeakMap();
|
|
@@ -165161,12 +165711,11 @@ __decorateElement(_init39, 4, "editableFields", _editableFields_dec, _DeesTable,
|
|
|
165161
165711
|
__decorateElement(_init39, 4, "showVerticalLines", _showVerticalLines_dec, _DeesTable, _showVerticalLines);
|
|
165162
165712
|
__decorateElement(_init39, 4, "showHorizontalLines", _showHorizontalLines_dec, _DeesTable, _showHorizontalLines);
|
|
165163
165713
|
__decorateElement(_init39, 4, "showGrid", _showGrid_dec, _DeesTable, _showGrid);
|
|
165164
|
-
__decorateElement(_init39, 4, "
|
|
165165
|
-
__decorateElement(_init39, 4, "sortDir", _sortDir_dec, _DeesTable, _sortDir);
|
|
165714
|
+
__decorateElement(_init39, 4, "sortBy", _sortBy_dec, _DeesTable, _sortBy);
|
|
165166
165715
|
__decorateElement(_init39, 4, "filterText", _filterText_dec, _DeesTable, _filterText);
|
|
165167
165716
|
__decorateElement(_init39, 4, "columnFilters", _columnFilters_dec, _DeesTable, _columnFilters);
|
|
165168
165717
|
__decorateElement(_init39, 4, "showColumnFilters", _showColumnFilters_dec, _DeesTable, _showColumnFilters);
|
|
165169
|
-
__decorateElement(_init39, 4, "
|
|
165718
|
+
__decorateElement(_init39, 4, "fixedHeight", _fixedHeight_dec, _DeesTable, _fixedHeight);
|
|
165170
165719
|
__decorateElement(_init39, 4, "searchMode", _searchMode_dec, _DeesTable, _searchMode);
|
|
165171
165720
|
__decorateElement(_init39, 4, "selectionMode", _selectionMode_dec, _DeesTable, _selectionMode);
|
|
165172
165721
|
__decorateElement(_init39, 4, "selectedIds", _selectedIds_dec, _DeesTable, _selectedIds);
|
|
@@ -199016,7 +199565,7 @@ init_group_runtime();
|
|
|
199016
199565
|
// ts_web/00_commitinfo_data.ts
|
|
199017
199566
|
var commitinfo = {
|
|
199018
199567
|
name: "@design.estate/dees-catalog",
|
|
199019
|
-
version: "3.
|
|
199568
|
+
version: "3.63.0",
|
|
199020
199569
|
description: "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript."
|
|
199021
199570
|
};
|
|
199022
199571
|
export {
|
|
@@ -200989,4 +201538,4 @@ ibantools/jsnext/ibantools.js:
|
|
|
200989
201538
|
* @preferred
|
|
200990
201539
|
*)
|
|
200991
201540
|
*/
|
|
200992
|
-
//# sourceMappingURL=bundle-
|
|
201541
|
+
//# sourceMappingURL=bundle-1775570157836.js.map
|