@coreui/data-grid 0.1.0-rc.0 → 0.3.0-rc.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/README.md +9 -6
- package/dist/css/data-grid.css +156 -38
- package/dist/css/data-grid.css.map +1 -1
- package/dist/css/data-grid.min.css +2 -2
- package/dist/css/data-grid.min.css.map +1 -1
- package/dist/css/data-grid.standalone.css +1066 -0
- package/dist/css/data-grid.standalone.css.map +1 -0
- package/dist/css/data-grid.standalone.min.css +5 -0
- package/dist/css/data-grid.standalone.min.css.map +1 -0
- package/dist/js/clipboard.cjs +56 -0
- package/dist/js/clipboard.cjs.map +1 -0
- package/dist/js/clipboard.mjs +54 -0
- package/dist/js/clipboard.mjs.map +1 -0
- package/dist/js/csv.cjs +36 -59
- package/dist/js/csv.cjs.map +1 -1
- package/dist/js/csv.mjs +35 -55
- package/dist/js/csv.mjs.map +1 -1
- package/dist/js/data-grid.esm.js +14108 -9331
- package/dist/js/data-grid.esm.js.map +1 -1
- package/dist/js/data-grid.esm.min.js +6 -6
- package/dist/js/data-grid.esm.min.js.map +1 -1
- package/dist/js/data-grid.js +14408 -9634
- package/dist/js/data-grid.js.map +1 -1
- package/dist/js/data-grid.lite.esm.js +10507 -0
- package/dist/js/data-grid.lite.esm.js.map +1 -0
- package/dist/js/data-grid.lite.esm.min.js +8 -0
- package/dist/js/data-grid.lite.esm.min.js.map +1 -0
- package/dist/js/data-grid.lite.js +10520 -0
- package/dist/js/data-grid.lite.js.map +1 -0
- package/dist/js/data-grid.lite.min.js +8 -0
- package/dist/js/data-grid.lite.min.js.map +1 -0
- package/dist/js/data-grid.lite.mjs +10507 -0
- package/dist/js/data-grid.lite.mjs.map +1 -0
- package/dist/js/data-grid.min.js +6 -6
- package/dist/js/data-grid.min.js.map +1 -1
- package/dist/js/data-grid.mjs +14108 -9331
- package/dist/js/data-grid.mjs.map +1 -1
- package/dist/js/direction.cjs +26 -0
- package/dist/js/direction.cjs.map +1 -0
- package/dist/js/direction.mjs +24 -0
- package/dist/js/direction.mjs.map +1 -0
- package/dist/js/drag.cjs +467 -0
- package/dist/js/drag.cjs.map +1 -0
- package/dist/js/drag.mjs +464 -0
- package/dist/js/drag.mjs.map +1 -0
- package/dist/js/export-table-BdabEbJG.mjs +26 -0
- package/dist/js/export-table-BdabEbJG.mjs.map +1 -0
- package/dist/js/export-table-D762wrZ1.cjs +55 -0
- package/dist/js/export-table-D762wrZ1.cjs.map +1 -0
- package/dist/js/filters.cjs +89 -132
- package/dist/js/filters.cjs.map +1 -1
- package/dist/js/filters.mjs +88 -128
- package/dist/js/filters.mjs.map +1 -1
- package/dist/js/labels.cjs +65 -70
- package/dist/js/labels.cjs.map +1 -1
- package/dist/js/labels.mjs +64 -66
- package/dist/js/labels.mjs.map +1 -1
- package/dist/js/print.cjs +66 -0
- package/dist/js/print.cjs.map +1 -0
- package/dist/js/print.mjs +64 -0
- package/dist/js/print.mjs.map +1 -0
- package/dist/js/validate.cjs +43 -0
- package/dist/js/validate.cjs.map +1 -0
- package/dist/js/validate.mjs +42 -0
- package/dist/js/validate.mjs.map +1 -0
- package/dist/js/xlsx.cjs +240 -0
- package/dist/js/xlsx.cjs.map +1 -0
- package/dist/js/xlsx.mjs +238 -0
- package/dist/js/xlsx.mjs.map +1 -0
- package/dist/types/base-component.d.ts +28 -18
- package/dist/types/data-grid.d.ts +26 -13
- package/dist/types/dom/data.d.ts +15 -0
- package/dist/types/dom/event-handler.d.ts +21 -10
- package/dist/types/dom/manipulator.d.ts +15 -8
- package/dist/types/engine/active-cell.d.ts +1 -0
- package/dist/types/engine/data-source.d.ts +1 -1
- package/dist/types/engine/features-lite.d.ts +25 -0
- package/dist/types/engine/features.d.ts +35 -0
- package/dist/types/engine/table.d.ts +3 -3
- package/dist/types/engine/validate.d.mts +1 -0
- package/dist/types/engine/validate.d.ts +20 -0
- package/dist/types/engine/virtualizer.d.ts +2 -0
- package/dist/types/icons.d.ts +6 -4
- package/dist/types/index-lite.d.mts +1 -0
- package/dist/types/index-lite.d.ts +19 -0
- package/dist/types/index.d.ts +11 -2
- package/dist/types/types.d.ts +53 -31
- package/dist/types/ui/body.d.ts +6 -3
- package/dist/types/ui/header.d.ts +3 -2
- package/dist/types/ui/loading.d.ts +1 -1
- package/dist/types/ui/pinning.d.ts +1 -1
- package/dist/types/ui/toolbar.d.ts +10 -2
- package/dist/types/util/clipboard.d.mts +1 -0
- package/dist/types/util/clipboard.d.ts +29 -0
- package/dist/types/util/config.d.ts +27 -10
- package/dist/types/util/csv.d.ts +5 -5
- package/dist/types/util/direction.d.mts +1 -0
- package/dist/types/util/direction.d.ts +17 -0
- package/dist/types/util/drag.d.mts +1 -0
- package/dist/types/util/drag.d.ts +48 -0
- package/dist/types/util/export-table.d.ts +47 -0
- package/dist/types/util/index.d.ts +66 -10
- package/dist/types/util/print.d.mts +1 -0
- package/dist/types/util/print.d.ts +32 -0
- package/dist/types/util/sanitizer.d.ts +15 -11
- package/dist/types/util/xlsx.d.mts +1 -0
- package/dist/types/util/xlsx.d.ts +17 -0
- package/dist/types/util/zip.d.ts +11 -0
- package/package.json +101 -10
- package/scss/_base.scss +13 -0
- package/scss/_config.scss +14 -0
- package/scss/_functions.scss +1 -0
- package/scss/_mixins.scss +1 -0
- package/scss/base/_buttons.scss +113 -0
- package/scss/base/_forms.scss +157 -0
- package/scss/base/_helpers.scss +24 -0
- package/scss/base/_pagination.scss +100 -0
- package/scss/base/_reboot.scss +93 -0
- package/scss/base/_root.scss +85 -0
- package/scss/base/_spinner.scss +45 -0
- package/scss/base/_table.scss +78 -0
- package/scss/components/_data-grid.scss +807 -0
- package/scss/data-grid.scss +7 -555
- package/scss/data-grid.standalone.scss +16 -0
- package/scss/functions/_defaults.scss +25 -0
- package/scss/mixins/_tokens.scss +12 -0
- package/src/{base-component.js → base-component.ts} +21 -17
- package/src/data-grid.ts +523 -201
- package/src/dom/{data.js → data.ts} +13 -10
- package/src/dom/event-handler.ts +380 -0
- package/src/dom/{manipulator.js → manipulator.ts} +11 -11
- package/src/engine/active-cell.ts +10 -3
- package/src/engine/data-source.ts +7 -3
- package/src/engine/features-lite.ts +47 -0
- package/src/engine/features.ts +68 -0
- package/src/engine/table.ts +86 -45
- package/src/engine/validate.ts +64 -0
- package/src/engine/virtualizer.ts +17 -1
- package/src/icons.ts +11 -5
- package/src/index-lite.ts +85 -0
- package/src/index.ts +30 -2
- package/src/labels.ts +6 -4
- package/src/types.ts +87 -32
- package/src/ui/body.ts +73 -17
- package/src/ui/header.ts +51 -26
- package/src/ui/loading.ts +2 -2
- package/src/ui/pinning.ts +16 -16
- package/src/ui/toolbar.ts +27 -3
- package/src/util/clipboard.ts +112 -0
- package/src/util/{config.js → config.ts} +25 -11
- package/src/util/csv.ts +11 -30
- package/src/util/direction.ts +37 -0
- package/src/util/drag.ts +832 -0
- package/src/util/export-table.ts +86 -0
- package/src/util/{index.js → index.ts} +55 -35
- package/src/util/print.ts +125 -0
- package/src/util/{sanitizer.js → sanitizer.ts} +17 -13
- package/src/util/xlsx.ts +183 -0
- package/src/util/zip.ts +170 -0
- package/src/base-component.d.ts +0 -19
- package/src/dom/event-handler.d.ts +0 -11
- package/src/dom/event-handler.js +0 -331
- package/src/dom/manipulator.d.ts +0 -9
- package/src/util/config.d.ts +0 -11
- package/src/util/index.d.ts +0 -10
- package/src/util/sanitizer.d.ts +0 -11
package/dist/js/drag.mjs
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* CoreUI PRO data-grid v0.3.0-rc.0 (https://coreui.io)
|
|
3
|
+
* Copyright 2026 The CoreUI Team (https://github.com/orgs/coreui/people)
|
|
4
|
+
* License (https://coreui.io/pro/license/)
|
|
5
|
+
*/
|
|
6
|
+
//#region src/util/drag.ts
|
|
7
|
+
/**
|
|
8
|
+
* --------------------------------------------------------------------------
|
|
9
|
+
* CoreUI PRO data-grid util/drag.ts
|
|
10
|
+
* License (https://coreui.io/pro/license/)
|
|
11
|
+
* --------------------------------------------------------------------------
|
|
12
|
+
*/
|
|
13
|
+
const CLASS_NAME_GHOST = "data-grid-drag-ghost";
|
|
14
|
+
const CLASS_NAME_INDICATOR = "data-grid-drop-indicator";
|
|
15
|
+
const CLASS_NAME_DRAGGING = "data-grid-dragging";
|
|
16
|
+
const CLASS_NAME_DRAG_ACTIVE = "data-grid-drag-active";
|
|
17
|
+
const CLASS_NAME_PREVIEW = "data-grid-drag-preview";
|
|
18
|
+
const CLASS_NAME_GHOST_SETTLE = "data-grid-drag-ghost-settle";
|
|
19
|
+
const DRAG_THRESHOLD = 4;
|
|
20
|
+
const DRAG_HYSTERESIS = 3;
|
|
21
|
+
const EDGE_SIZE = 48;
|
|
22
|
+
const EDGE_MAX_SPEED = 18;
|
|
23
|
+
const GHOST_OFFSET = 12;
|
|
24
|
+
const GHOST_SETTLE_FALLBACK_MS = 400;
|
|
25
|
+
const collapse = (text) => text.replace(/\s+/g, " ").trim();
|
|
26
|
+
const destinationIndex = (from, target, after) => target > from ? after ? target : target - 1 : after ? target + 1 : target;
|
|
27
|
+
const swallowClick = (event) => {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
event.stopPropagation();
|
|
30
|
+
};
|
|
31
|
+
const disarmSwallowClick = () => {
|
|
32
|
+
document.removeEventListener("click", swallowClick, { capture: true });
|
|
33
|
+
};
|
|
34
|
+
const INERT_CONTROLLER = { dispose() {} };
|
|
35
|
+
const createDragController = (options) => {
|
|
36
|
+
if (typeof document === "undefined") return INERT_CONTROLLER;
|
|
37
|
+
const { axis, root } = options;
|
|
38
|
+
const horizontal = axis === "x";
|
|
39
|
+
let sourceHit = null;
|
|
40
|
+
let dragging = false;
|
|
41
|
+
let axisSign = 1;
|
|
42
|
+
let origin = {
|
|
43
|
+
x: 0,
|
|
44
|
+
y: 0
|
|
45
|
+
};
|
|
46
|
+
let pointer = {
|
|
47
|
+
x: 0,
|
|
48
|
+
y: 0
|
|
49
|
+
};
|
|
50
|
+
let drop = null;
|
|
51
|
+
let ghost = null;
|
|
52
|
+
let indicator = null;
|
|
53
|
+
let scrollFrame = 0;
|
|
54
|
+
let pointerId = -1;
|
|
55
|
+
let previewKey = "";
|
|
56
|
+
let sticky = null;
|
|
57
|
+
const previewDeltas = /* @__PURE__ */ new Map();
|
|
58
|
+
const previewClassed = /* @__PURE__ */ new Set();
|
|
59
|
+
const contentStarts = /* @__PURE__ */ new Map();
|
|
60
|
+
const contentSizes = /* @__PURE__ */ new Map();
|
|
61
|
+
const logicalStart = (rect) => {
|
|
62
|
+
if (!horizontal) return rect.top;
|
|
63
|
+
return axisSign === 1 ? rect.left : -rect.right;
|
|
64
|
+
};
|
|
65
|
+
const logicalPointer = () => horizontal ? pointer.x * axisSign : pointer.y;
|
|
66
|
+
const stopAutoScroll = () => {
|
|
67
|
+
if (scrollFrame) {
|
|
68
|
+
cancelAnimationFrame(scrollFrame);
|
|
69
|
+
scrollFrame = 0;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const autoScroll = () => {
|
|
73
|
+
scrollFrame = 0;
|
|
74
|
+
const scrollElement = options.getScrollElement();
|
|
75
|
+
if (!scrollElement || !dragging) return;
|
|
76
|
+
const rect = scrollElement.getBoundingClientRect();
|
|
77
|
+
const position = horizontal ? pointer.x : pointer.y;
|
|
78
|
+
const start = horizontal ? rect.left : rect.top;
|
|
79
|
+
const end = horizontal ? rect.right : rect.bottom;
|
|
80
|
+
let delta = 0;
|
|
81
|
+
if (position < start + EDGE_SIZE) delta = -18 * Math.min(1, (start + EDGE_SIZE - position) / EDGE_SIZE);
|
|
82
|
+
else if (position > end - EDGE_SIZE) delta = EDGE_MAX_SPEED * Math.min(1, (position - (end - EDGE_SIZE)) / EDGE_SIZE);
|
|
83
|
+
if (delta !== 0) {
|
|
84
|
+
if (horizontal) scrollElement.scrollLeft += delta;
|
|
85
|
+
else scrollElement.scrollTop += delta;
|
|
86
|
+
updateTarget();
|
|
87
|
+
scrollFrame = requestAnimationFrame(autoScroll);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const moveGhost = () => {
|
|
91
|
+
if (ghost) ghost.style.transform = `translate(${pointer.x + GHOST_OFFSET}px, ${pointer.y + GHOST_OFFSET}px)`;
|
|
92
|
+
};
|
|
93
|
+
const hideIndicator = () => {
|
|
94
|
+
if (indicator) indicator.hidden = true;
|
|
95
|
+
};
|
|
96
|
+
const showIndicator = (target, after) => {
|
|
97
|
+
if (!indicator) return;
|
|
98
|
+
const rect = target.getBoundingClientRect();
|
|
99
|
+
const rootRect = root.getBoundingClientRect();
|
|
100
|
+
indicator.hidden = false;
|
|
101
|
+
if (horizontal) {
|
|
102
|
+
const trailing = after === (axisSign === 1);
|
|
103
|
+
indicator.style.left = `${trailing ? rect.right : rect.left}px`;
|
|
104
|
+
indicator.style.top = `${rootRect.top}px`;
|
|
105
|
+
indicator.style.height = `${rootRect.height}px`;
|
|
106
|
+
} else {
|
|
107
|
+
indicator.style.left = `${rootRect.left}px`;
|
|
108
|
+
indicator.style.top = `${after ? rect.bottom : rect.top}px`;
|
|
109
|
+
indicator.style.width = `${rootRect.width}px`;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const startDrag = () => {
|
|
113
|
+
dragging = true;
|
|
114
|
+
axisSign = horizontal && getComputedStyle(root).direction === "rtl" ? -1 : 1;
|
|
115
|
+
const active = document.activeElement;
|
|
116
|
+
if (active instanceof HTMLElement && root.contains(active)) active.blur();
|
|
117
|
+
root.classList.add(CLASS_NAME_DRAG_ACTIVE);
|
|
118
|
+
sourceHit.element.classList.add(CLASS_NAME_DRAGGING);
|
|
119
|
+
const rect = sourceHit.element.getBoundingClientRect();
|
|
120
|
+
ghost = document.createElement("div");
|
|
121
|
+
ghost.className = CLASS_NAME_GHOST;
|
|
122
|
+
ghost.setAttribute("aria-hidden", "true");
|
|
123
|
+
ghost.style.width = `${rect.width}px`;
|
|
124
|
+
ghost.style.height = `${rect.height}px`;
|
|
125
|
+
ghost.textContent = options.ghostLabel ? options.ghostLabel(sourceHit) : collapse(sourceHit.element.textContent ?? "");
|
|
126
|
+
if (!options.preview) {
|
|
127
|
+
indicator = document.createElement("div");
|
|
128
|
+
indicator.className = `${CLASS_NAME_INDICATOR} ${CLASS_NAME_INDICATOR}-${axis}`;
|
|
129
|
+
indicator.setAttribute("aria-hidden", "true");
|
|
130
|
+
indicator.hidden = true;
|
|
131
|
+
root.append(indicator);
|
|
132
|
+
}
|
|
133
|
+
root.append(ghost);
|
|
134
|
+
moveGhost();
|
|
135
|
+
captureLayout();
|
|
136
|
+
};
|
|
137
|
+
const contentOrigin = () => {
|
|
138
|
+
const scrollElement = options.getScrollElement();
|
|
139
|
+
if (!scrollElement) return 0;
|
|
140
|
+
const rect = scrollElement.getBoundingClientRect();
|
|
141
|
+
return horizontal ? logicalStart(rect) - axisSign * scrollElement.scrollLeft : rect.top - scrollElement.scrollTop;
|
|
142
|
+
};
|
|
143
|
+
const captureItem = (id, origin) => {
|
|
144
|
+
const element = options.items.getElements(id)[0];
|
|
145
|
+
if (!element) return false;
|
|
146
|
+
const rect = element.getBoundingClientRect();
|
|
147
|
+
const start = logicalStart(rect) - (previewDeltas.get(id) ?? 0);
|
|
148
|
+
contentStarts.set(id, start - origin);
|
|
149
|
+
contentSizes.set(id, horizontal ? rect.width : rect.height);
|
|
150
|
+
return true;
|
|
151
|
+
};
|
|
152
|
+
const captureLayout = () => {
|
|
153
|
+
contentStarts.clear();
|
|
154
|
+
contentSizes.clear();
|
|
155
|
+
const origin = contentOrigin();
|
|
156
|
+
for (const id of options.items.getOrderedIds()) captureItem(id, origin);
|
|
157
|
+
};
|
|
158
|
+
const updateTarget = () => {
|
|
159
|
+
const position = logicalPointer();
|
|
160
|
+
const origin = contentOrigin();
|
|
161
|
+
const zones = [];
|
|
162
|
+
for (const id of options.items.getOrderedIds()) {
|
|
163
|
+
if (!contentStarts.has(id) && !captureItem(id, origin)) continue;
|
|
164
|
+
zones.push({
|
|
165
|
+
id,
|
|
166
|
+
start: origin + contentStarts.get(id),
|
|
167
|
+
size: contentSizes.get(id)
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
let hit = null;
|
|
171
|
+
const lastZone = zones[zones.length - 1];
|
|
172
|
+
const fromIndex = zones.findIndex((zone) => zone.id === sourceHit.id);
|
|
173
|
+
if (lastZone && position > lastZone.start + lastZone.size) {
|
|
174
|
+
sticky = null;
|
|
175
|
+
for (let index = zones.length - 1; index >= 0; index--) if (options.canDrop(sourceHit.id, zones[index].id)) {
|
|
176
|
+
hit = {
|
|
177
|
+
id: zones[index].id,
|
|
178
|
+
after: true
|
|
179
|
+
};
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
} else if (lastZone && position < zones[0].start) {
|
|
183
|
+
sticky = null;
|
|
184
|
+
for (const zone of zones) if (options.canDrop(sourceHit.id, zone.id)) {
|
|
185
|
+
hit = {
|
|
186
|
+
id: zone.id,
|
|
187
|
+
after: false
|
|
188
|
+
};
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
} else if (drop && sticky && position >= sticky.lo - DRAG_HYSTERESIS && position <= sticky.hi + DRAG_HYSTERESIS) hit = drop;
|
|
192
|
+
else for (let index = 0; index < zones.length; index++) {
|
|
193
|
+
const zone = zones[index];
|
|
194
|
+
const previous = zones[index - 1];
|
|
195
|
+
const following = zones[index + 1];
|
|
196
|
+
const lo = previous ? (previous.start + previous.size + zone.start) / 2 : zone.start;
|
|
197
|
+
const hi = following ? (zone.start + zone.size + following.start) / 2 : zone.start + zone.size;
|
|
198
|
+
if (position < lo || position > hi) continue;
|
|
199
|
+
if (options.canDrop(sourceHit.id, zone.id)) {
|
|
200
|
+
hit = {
|
|
201
|
+
id: zone.id,
|
|
202
|
+
after: fromIndex === -1 ? position > zone.start + zone.size / 2 : index > fromIndex
|
|
203
|
+
};
|
|
204
|
+
sticky = {
|
|
205
|
+
lo,
|
|
206
|
+
hi
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
if (!hit) {
|
|
212
|
+
drop = null;
|
|
213
|
+
sticky = null;
|
|
214
|
+
hideIndicator();
|
|
215
|
+
applyPreview();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
drop = hit;
|
|
219
|
+
showIndicator(options.items.getElements(hit.id)[0], hit.after);
|
|
220
|
+
applyPreview();
|
|
221
|
+
};
|
|
222
|
+
const clearPreview = () => {
|
|
223
|
+
for (const id of previewClassed) for (const element of options.items.getElements(id)) {
|
|
224
|
+
element.style.transform = "";
|
|
225
|
+
element.classList.remove(CLASS_NAME_PREVIEW);
|
|
226
|
+
}
|
|
227
|
+
previewKey = "";
|
|
228
|
+
previewDeltas.clear();
|
|
229
|
+
previewClassed.clear();
|
|
230
|
+
};
|
|
231
|
+
const clearLayout = () => {
|
|
232
|
+
contentStarts.clear();
|
|
233
|
+
contentSizes.clear();
|
|
234
|
+
};
|
|
235
|
+
const applyPreview = () => {
|
|
236
|
+
if (!options.preview || !sourceHit) return;
|
|
237
|
+
const ids = options.items.getOrderedIds();
|
|
238
|
+
const from = ids.indexOf(sourceHit.id);
|
|
239
|
+
const target = drop ? ids.indexOf(drop.id) : -1;
|
|
240
|
+
const to = from === -1 || target === -1 ? from : destinationIndex(from, target, drop.after);
|
|
241
|
+
const key = String(to);
|
|
242
|
+
if (key === previewKey) return;
|
|
243
|
+
previewKey = key;
|
|
244
|
+
const next = /* @__PURE__ */ new Map();
|
|
245
|
+
if (from !== -1 && to !== from) {
|
|
246
|
+
const sizeOf = (index) => contentSizes.get(ids[index]) ?? 0;
|
|
247
|
+
const forward = to > from;
|
|
248
|
+
const first = forward ? from + 1 : to;
|
|
249
|
+
const last = forward ? to : from - 1;
|
|
250
|
+
const sourceSize = sizeOf(from);
|
|
251
|
+
let travelled = 0;
|
|
252
|
+
for (let index = first; index <= last; index++) {
|
|
253
|
+
travelled += sizeOf(index);
|
|
254
|
+
next.set(ids[index], forward ? -sourceSize : sourceSize);
|
|
255
|
+
}
|
|
256
|
+
next.set(ids[from], forward ? travelled : -travelled);
|
|
257
|
+
}
|
|
258
|
+
for (const id of previewDeltas.keys()) if (!next.has(id)) for (const element of options.items.getElements(id)) element.style.transform = "";
|
|
259
|
+
for (const [id, delta] of next) {
|
|
260
|
+
if (previewDeltas.get(id) === delta) continue;
|
|
261
|
+
for (const element of options.items.getElements(id)) {
|
|
262
|
+
element.style.transform = horizontal ? `translateX(${axisSign * delta}px)` : `translateY(${delta}px)`;
|
|
263
|
+
element.classList.add(CLASS_NAME_PREVIEW);
|
|
264
|
+
}
|
|
265
|
+
previewClassed.add(id);
|
|
266
|
+
}
|
|
267
|
+
previewDeltas.clear();
|
|
268
|
+
for (const [id, delta] of next) previewDeltas.set(id, delta);
|
|
269
|
+
};
|
|
270
|
+
const settleGhost = (x, y) => {
|
|
271
|
+
if (!ghost) return;
|
|
272
|
+
const element = ghost;
|
|
273
|
+
ghost = null;
|
|
274
|
+
element.classList.add(CLASS_NAME_GHOST_SETTLE);
|
|
275
|
+
element.style.transform = `translate(${x}px, ${y}px)`;
|
|
276
|
+
element.style.opacity = "0";
|
|
277
|
+
let settled = false;
|
|
278
|
+
const finish = () => {
|
|
279
|
+
if (!settled) {
|
|
280
|
+
settled = true;
|
|
281
|
+
element.remove();
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
element.addEventListener("transitionend", finish);
|
|
285
|
+
setTimeout(finish, GHOST_SETTLE_FALLBACK_MS);
|
|
286
|
+
};
|
|
287
|
+
const settleTarget = (committed) => {
|
|
288
|
+
if (!sourceHit) return null;
|
|
289
|
+
const rect = sourceHit.element.getBoundingClientRect();
|
|
290
|
+
if (committed) return {
|
|
291
|
+
x: rect.left,
|
|
292
|
+
y: rect.top
|
|
293
|
+
};
|
|
294
|
+
const delta = previewDeltas.get(sourceHit.id) ?? 0;
|
|
295
|
+
return horizontal ? {
|
|
296
|
+
x: rect.left - axisSign * delta,
|
|
297
|
+
y: rect.top
|
|
298
|
+
} : {
|
|
299
|
+
x: rect.left,
|
|
300
|
+
y: rect.top - delta
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
const cleanup = () => {
|
|
304
|
+
clearPreview();
|
|
305
|
+
clearLayout();
|
|
306
|
+
stopAutoScroll();
|
|
307
|
+
root.classList.remove(CLASS_NAME_DRAG_ACTIVE);
|
|
308
|
+
sourceHit?.element.classList.remove(CLASS_NAME_DRAGGING);
|
|
309
|
+
ghost?.remove();
|
|
310
|
+
indicator?.remove();
|
|
311
|
+
ghost = null;
|
|
312
|
+
indicator = null;
|
|
313
|
+
sourceHit = null;
|
|
314
|
+
dragging = false;
|
|
315
|
+
drop = null;
|
|
316
|
+
sticky = null;
|
|
317
|
+
pointerId = -1;
|
|
318
|
+
document.removeEventListener("pointermove", onPointerMove);
|
|
319
|
+
document.removeEventListener("pointerup", onPointerUp);
|
|
320
|
+
document.removeEventListener("pointercancel", cancel);
|
|
321
|
+
document.removeEventListener("keydown", onKeydown);
|
|
322
|
+
};
|
|
323
|
+
function cancel() {
|
|
324
|
+
if (dragging) {
|
|
325
|
+
const home = settleTarget(false);
|
|
326
|
+
if (home) settleGhost(home.x, home.y);
|
|
327
|
+
}
|
|
328
|
+
cleanup();
|
|
329
|
+
}
|
|
330
|
+
function onKeydown(event) {
|
|
331
|
+
if (event.key === "Escape") {
|
|
332
|
+
event.preventDefault();
|
|
333
|
+
cancel();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
function onPointerMove(event) {
|
|
337
|
+
if (event.pointerId !== pointerId || !sourceHit) return;
|
|
338
|
+
pointer = {
|
|
339
|
+
x: event.clientX,
|
|
340
|
+
y: event.clientY
|
|
341
|
+
};
|
|
342
|
+
if (!dragging) {
|
|
343
|
+
if (Math.max(Math.abs(pointer.x - origin.x), Math.abs(pointer.y - origin.y)) < DRAG_THRESHOLD) return;
|
|
344
|
+
startDrag();
|
|
345
|
+
}
|
|
346
|
+
event.preventDefault();
|
|
347
|
+
moveGhost();
|
|
348
|
+
updateTarget();
|
|
349
|
+
if (!scrollFrame) scrollFrame = requestAnimationFrame(autoScroll);
|
|
350
|
+
}
|
|
351
|
+
function onPointerUp(event) {
|
|
352
|
+
if (event.pointerId !== pointerId) return;
|
|
353
|
+
const sourceId = sourceHit?.id;
|
|
354
|
+
const source = sourceHit?.element;
|
|
355
|
+
const pending = drop;
|
|
356
|
+
const wasDragging = dragging;
|
|
357
|
+
if (wasDragging) {
|
|
358
|
+
const committed = Boolean(pending && pending.id !== sourceId);
|
|
359
|
+
const landing = settleTarget(committed);
|
|
360
|
+
if (landing) settleGhost(landing.x, landing.y);
|
|
361
|
+
}
|
|
362
|
+
cleanup();
|
|
363
|
+
if (!wasDragging) return;
|
|
364
|
+
if (source?.contains(event.target)) {
|
|
365
|
+
document.addEventListener("click", swallowClick, {
|
|
366
|
+
capture: true,
|
|
367
|
+
once: true
|
|
368
|
+
});
|
|
369
|
+
setTimeout(disarmSwallowClick, 0);
|
|
370
|
+
}
|
|
371
|
+
if (sourceId && pending && pending.id !== sourceId) options.onDrop(sourceId, pending);
|
|
372
|
+
}
|
|
373
|
+
const onPointerDown = (event) => {
|
|
374
|
+
if (!event.isPrimary || event.pointerType === "mouse" && event.button !== 0 || sourceHit) return;
|
|
375
|
+
const element = event.target?.closest(options.handle);
|
|
376
|
+
if (!element) return;
|
|
377
|
+
const hit = options.resolveSource(element, event.target);
|
|
378
|
+
if (!hit) return;
|
|
379
|
+
sourceHit = hit;
|
|
380
|
+
pointerId = event.pointerId;
|
|
381
|
+
origin = {
|
|
382
|
+
x: event.clientX,
|
|
383
|
+
y: event.clientY
|
|
384
|
+
};
|
|
385
|
+
pointer = origin;
|
|
386
|
+
document.addEventListener("pointermove", onPointerMove);
|
|
387
|
+
document.addEventListener("pointerup", onPointerUp);
|
|
388
|
+
document.addEventListener("pointercancel", cancel);
|
|
389
|
+
document.addEventListener("keydown", onKeydown);
|
|
390
|
+
};
|
|
391
|
+
root.addEventListener("pointerdown", onPointerDown);
|
|
392
|
+
return { dispose() {
|
|
393
|
+
root.removeEventListener("pointerdown", onPointerDown);
|
|
394
|
+
disarmSwallowClick();
|
|
395
|
+
cleanup();
|
|
396
|
+
} };
|
|
397
|
+
};
|
|
398
|
+
const SELECTOR_DRAGGABLE_COLUMN = "th[data-coreui-draggable]";
|
|
399
|
+
const SELECTOR_RESIZER = "[data-coreui-resizer]";
|
|
400
|
+
const SELECTOR_PREVIEW_ROWS = "thead tr, tbody tr:not(.data-grid-spacer):not(.data-grid-empty)";
|
|
401
|
+
const columnItems = (root) => ({
|
|
402
|
+
getOrderedIds: () => [...root.querySelectorAll("thead tr:first-child th[data-coreui-column]")].map((cell) => cell.dataset.coreuiColumn ?? ""),
|
|
403
|
+
getElements(id) {
|
|
404
|
+
const header = root.querySelector(`thead th[data-coreui-column="${id}"]`);
|
|
405
|
+
if (!header) return [];
|
|
406
|
+
const { cellIndex } = header;
|
|
407
|
+
const elements = [];
|
|
408
|
+
for (const row of root.querySelectorAll(SELECTOR_PREVIEW_ROWS)) {
|
|
409
|
+
const cell = row.children[cellIndex];
|
|
410
|
+
if (cell) elements.push(cell);
|
|
411
|
+
}
|
|
412
|
+
return elements;
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
const createColumnDragController = (options) => createDragController({
|
|
416
|
+
axis: "x",
|
|
417
|
+
root: options.root,
|
|
418
|
+
handle: SELECTOR_DRAGGABLE_COLUMN,
|
|
419
|
+
getScrollElement: options.getScrollElement,
|
|
420
|
+
resolveSource(element, target) {
|
|
421
|
+
if (target.closest(SELECTOR_RESIZER)) return null;
|
|
422
|
+
const id = element.dataset.coreuiColumn;
|
|
423
|
+
return id ? {
|
|
424
|
+
id,
|
|
425
|
+
element
|
|
426
|
+
} : null;
|
|
427
|
+
},
|
|
428
|
+
items: columnItems(options.root),
|
|
429
|
+
canDrop: (sourceId, targetId) => sourceId !== targetId && Boolean(options.root.querySelector(`th[data-coreui-column="${targetId}"][data-coreui-draggable]`)) && options.canDrop(sourceId, targetId),
|
|
430
|
+
preview: true,
|
|
431
|
+
onDrop: (sourceKey, drop) => options.onReorder(sourceKey, drop.id, drop.after)
|
|
432
|
+
});
|
|
433
|
+
const SELECTOR_ROW_HANDLE = "[data-coreui-row-handle]";
|
|
434
|
+
const SELECTOR_ROW = "tr[data-coreui-index]";
|
|
435
|
+
const rowItems = (root) => ({
|
|
436
|
+
getOrderedIds: () => [...root.querySelectorAll(`tbody ${SELECTOR_ROW}`)].map((row) => row.dataset.coreuiIndex ?? ""),
|
|
437
|
+
getElements(id) {
|
|
438
|
+
const row = root.querySelector(`tbody tr[data-coreui-index="${id}"]`);
|
|
439
|
+
return row ? [row] : [];
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
const createRowDragController = (options) => createDragController({
|
|
443
|
+
axis: "y",
|
|
444
|
+
root: options.root,
|
|
445
|
+
handle: SELECTOR_ROW_HANDLE,
|
|
446
|
+
getScrollElement: options.getScrollElement,
|
|
447
|
+
resolveSource(handle) {
|
|
448
|
+
const row = handle.closest(SELECTOR_ROW);
|
|
449
|
+
const id = row?.dataset.coreuiIndex;
|
|
450
|
+
return row && id ? {
|
|
451
|
+
id,
|
|
452
|
+
element: row
|
|
453
|
+
} : null;
|
|
454
|
+
},
|
|
455
|
+
items: rowItems(options.root),
|
|
456
|
+
canDrop: (sourceId, targetId) => sourceId !== targetId,
|
|
457
|
+
ghostLabel: (source) => collapse(source.element.querySelector("td:not(.data-grid-row-handle-cell):not(.data-grid-select-cell)")?.textContent ?? ""),
|
|
458
|
+
preview: true,
|
|
459
|
+
onDrop: (sourceId, drop) => options.onReorder(Number(sourceId), Number(drop.id), drop.after)
|
|
460
|
+
});
|
|
461
|
+
//#endregion
|
|
462
|
+
export { createColumnDragController, createDragController, createRowDragController };
|
|
463
|
+
|
|
464
|
+
//# sourceMappingURL=drag.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drag.mjs","names":[],"sources":["../../src/util/drag.ts"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * CoreUI PRO data-grid util/drag.ts\n * License (https://coreui.io/pro/license/)\n * --------------------------------------------------------------------------\n */\n\n// The one drag implementation behind every reorder in the grid: column drag\n// (axis 'x', over the header) and row drag (axis 'y', over the body). It is\n// headless in the sense that matters — it never reads the table, only what the\n// consumer resolves for it — and pointer-based rather than HTML5 drag events,\n// which cannot render a drop indicator, cannot auto-scroll, and behave\n// differently on touch.\n//\n// The invariant that keeps it cheap: pointermove writes to the DOM directly.\n// Nothing here goes through component state, change detection or a signal, so\n// a drag costs no re-renders in any of the four editions.\n\nconst CLASS_NAME_GHOST = 'data-grid-drag-ghost'\nconst CLASS_NAME_INDICATOR = 'data-grid-drop-indicator'\nconst CLASS_NAME_DRAGGING = 'data-grid-dragging'\nconst CLASS_NAME_DRAG_ACTIVE = 'data-grid-drag-active'\nconst CLASS_NAME_PREVIEW = 'data-grid-drag-preview'\nconst CLASS_NAME_GHOST_SETTLE = 'data-grid-drag-ghost-settle'\n\n// A press has to travel this far before it becomes a drag — otherwise a click\n// on a sortable header would never sort.\nconst DRAG_THRESHOLD = 4\n// How far past a zone boundary the pointer must travel before the slot flips.\n// Swaps fire on ENTRY into a neighbour's zone, and without this band a hand\n// tremor exactly on the boundary would re-animate back and forth.\nconst DRAG_HYSTERESIS = 3\n// How close to the scroll element's edge the pointer starts auto-scrolling,\n// and the fastest it scrolls when pinned to that edge.\nconst EDGE_SIZE = 48\nconst EDGE_MAX_SPEED = 18\n// The ghost trails the pointer by this much, in px.\nconst GHOST_OFFSET = 12\n// Removal fallback for the settling ghost — a context where the transition\n// never runs (reduced motion, a hidden tab) must not leak the element.\nconst GHOST_SETTLE_FALLBACK_MS = 400\n\nexport type DragAxis = 'x' | 'y'\n\nexport interface DragHit {\n id: string\n element: HTMLElement\n}\n\nexport interface DragDrop {\n id: string\n // The source lands after the target rather than before it — which side of\n // the target's midpoint the pointer was released on.\n after: boolean\n}\n\nexport interface DragControllerOptions {\n axis: DragAxis\n root: HTMLElement\n // Delegation selector for the element a drag may start from.\n handle: string\n // Called with the handle and the element actually pressed. Returning null\n // vetoes the drag: a press on a resize handle, a column the author marked\n // immovable, a grid whose reordering is off.\n resolveSource: (handle: HTMLElement, target: HTMLElement) => DragHit | null\n items: DragItems\n // Vetoes a slot: the source itself, or an item the reorder may not cross\n // (a column in another pinned region).\n canDrop: (sourceId: string, targetId: string) => boolean\n getScrollElement: () => HTMLElement | null\n // The ghost's caption. Defaults to the source's collapsed text, which is the\n // label for a header cell but every cell run together for a row.\n ghostLabel?: (source: DragHit) => string\n // The live preview: the items between the source and the drop slot slide\n // aside and the source slides into the gap, so the grid shows the layout the\n // drop will produce instead of only pointing at it. Transforms only, so\n // nothing reflows and the real order still changes once, on drop. Replaces\n // the drop-indicator line, which only renders when this is off.\n preview?: boolean\n onDrop: (sourceId: string, drop: DragDrop) => void\n}\n\n// The reorderable items, in display order along the drag's axis. This is both\n// what the pointer is hit-tested against and what the live preview slides.\nexport interface DragItems {\n getOrderedIds: () => string[]\n // Every element that travels with that id: a column's header and body cells,\n // or simply the row.\n getElements: (id: string) => HTMLElement[]\n}\n\nexport interface DragController {\n dispose: () => void\n}\n\nconst collapse = (text: string): string => text.replace(/\\s+/g, ' ').trim()\n\n// Which slot the source lands in, expressed in the CURRENT order — the same\n// arithmetic the drop itself does, so the preview cannot disagree with it.\nconst destinationIndex = (from: number, target: number, after: boolean): number =>\n (target > from ? (after ? target : target - 1) : (after ? target + 1 : target))\n\nconst swallowClick = (event: Event) => {\n event.preventDefault()\n event.stopPropagation()\n}\n\nconst disarmSwallowClick = () => {\n document.removeEventListener('click', swallowClick, { capture: true })\n}\n\n// Server-side rendering reaches here through Angular, whose ngAfterViewInit and\n// ngOnDestroy both run during prerender. There is no pointer to track without a\n// document, so hand back an inert controller instead of touching one.\nconst INERT_CONTROLLER: DragController = { dispose() {} }\n\nexport const createDragController = (options: DragControllerOptions): DragController => {\n if (typeof document === 'undefined') {\n return INERT_CONTROLLER\n }\n\n const { axis, root } = options\n const horizontal = axis === 'x'\n\n let sourceHit: DragHit | null = null\n let dragging = false\n // +1 while the axis runs the way the coordinates do, -1 under RTL, where the\n // logical column order runs against increasing x. Negating the axis keeps\n // every comparison below — the zone tiling, the hysteresis band, both edge\n // clamps, `index > fromIndex` — written once, for one direction. Only the\n // three places that touch pixels again convert back: the indicator's side,\n // the preview transform and the settling ghost.\n //\n // Read from the grid's own computed direction rather than the document's: a\n // grid can sit in an RTL subtree of an LTR page, which is exactly the case\n // the vendored isRTL() cannot see.\n let axisSign = 1\n let origin = { x: 0, y: 0 }\n let pointer = { x: 0, y: 0 }\n let drop: DragDrop | null = null\n let ghost: HTMLElement | null = null\n let indicator: HTMLElement | null = null\n let scrollFrame = 0\n let pointerId = -1\n let previewKey = ''\n // The zone that produced the current drop, padded by the hysteresis band.\n let sticky: { lo: number; hi: number } | null = null\n // The transform currently applied to each item — the preview diffs against\n // it, and a layout captured mid-preview (a row revealed by auto-scroll) is\n // corrected back through it.\n const previewDeltas = new Map<string, number>()\n // Every id that still carries the transition class. Mid-drag un-shifts keep\n // the class so the slide BACK animates too; it only comes off at the end.\n const previewClassed = new Set<string>()\n // Each item's start in the scroll container's CONTENT coordinates — a space\n // no transform and no scroll can move. Captured at drag start, when nothing\n // is transformed yet, so the values are exact.\n const contentStarts = new Map<string, number>()\n const contentSizes = new Map<string, number>()\n\n // A rect's logical start: its leading edge along the axis, in the negated\n // space when the axis is negated, so the span stays [start, start + size].\n const logicalStart = (rect: DOMRect): number => {\n if (!horizontal) {\n return rect.top\n }\n\n return axisSign === 1 ? rect.left : -rect.right\n }\n\n const logicalPointer = (): number => (horizontal ? pointer.x * axisSign : pointer.y)\n\n const stopAutoScroll = () => {\n if (scrollFrame) {\n cancelAnimationFrame(scrollFrame)\n scrollFrame = 0\n }\n }\n\n const autoScroll = () => {\n scrollFrame = 0\n const scrollElement = options.getScrollElement()\n if (!scrollElement || !dragging) {\n return\n }\n\n const rect = scrollElement.getBoundingClientRect()\n const position = horizontal ? pointer.x : pointer.y\n const start = horizontal ? rect.left : rect.top\n const end = horizontal ? rect.right : rect.bottom\n\n // Speed ramps with how far into the edge zone the pointer sits, so the\n // list creeps at the boundary and races when pinned to the edge.\n let delta = 0\n if (position < start + EDGE_SIZE) {\n delta = -EDGE_MAX_SPEED * Math.min(1, (start + EDGE_SIZE - position) / EDGE_SIZE)\n } else if (position > end - EDGE_SIZE) {\n delta = EDGE_MAX_SPEED * Math.min(1, (position - (end - EDGE_SIZE)) / EDGE_SIZE)\n }\n\n if (delta !== 0) {\n if (horizontal) {\n scrollElement.scrollLeft += delta\n } else {\n scrollElement.scrollTop += delta\n }\n\n // Scrolling moved the content under a stationary pointer, and no\n // pointermove will fire to say so.\n updateTarget()\n scrollFrame = requestAnimationFrame(autoScroll)\n }\n }\n\n // The ghost trails the pointer instead of sitting under it, so the cell the\n // hit test resolves stays visible.\n const moveGhost = () => {\n if (ghost) {\n ghost.style.transform = `translate(${pointer.x + GHOST_OFFSET}px, ${pointer.y + GHOST_OFFSET}px)`\n }\n }\n\n const hideIndicator = () => {\n if (indicator) {\n indicator.hidden = true\n }\n }\n\n const showIndicator = (target: HTMLElement, after: boolean) => {\n if (!indicator) {\n return\n }\n\n const rect = target.getBoundingClientRect()\n const rootRect = root.getBoundingClientRect()\n indicator.hidden = false\n if (horizontal) {\n // `after` is logical; which pixel edge that is flips with the axis.\n const trailing = after === (axisSign === 1)\n indicator.style.left = `${trailing ? rect.right : rect.left}px`\n indicator.style.top = `${rootRect.top}px`\n indicator.style.height = `${rootRect.height}px`\n } else {\n indicator.style.left = `${rootRect.left}px`\n indicator.style.top = `${after ? rect.bottom : rect.top}px`\n indicator.style.width = `${rootRect.width}px`\n }\n }\n\n const startDrag = () => {\n dragging = true\n axisSign = horizontal && getComputedStyle(root).direction === 'rtl' ? -1 : 1\n // Chrome focuses a button on mousedown (a press on a header lands on the\n // sort button), and tearing a FOCUSED element out of the DOM — which the\n // drop's header re-append does — makes the browser reset the scroller it\n // lived in: releasing a drag with the viewport scrolled right snapped it\n // back to the left. A drag has no use for focus; drop it the moment the\n // press becomes one. Sub-threshold presses never get here, so click-to-\n // sort keeps its focus behavior.\n const active = document.activeElement\n if (active instanceof HTMLElement && root.contains(active)) {\n active.blur()\n }\n\n root.classList.add(CLASS_NAME_DRAG_ACTIVE)\n sourceHit!.element.classList.add(CLASS_NAME_DRAGGING)\n\n const rect = sourceHit!.element.getBoundingClientRect()\n ghost = document.createElement('div')\n ghost.className = CLASS_NAME_GHOST\n ghost.setAttribute('aria-hidden', 'true')\n ghost.style.width = `${rect.width}px`\n ghost.style.height = `${rect.height}px`\n ghost.textContent = options.ghostLabel ?\n options.ghostLabel(sourceHit!) :\n collapse(sourceHit!.element.textContent ?? '')\n\n // With the live preview on, the sliding items ARE the drop indicator; a\n // line has no stable place to stand, because it would be measured against\n // cells that are themselves mid-transition. The line only exists for\n // consumers that turned the preview off.\n if (!options.preview) {\n indicator = document.createElement('div')\n indicator.className = `${CLASS_NAME_INDICATOR} ${CLASS_NAME_INDICATOR}-${axis}`\n indicator.setAttribute('aria-hidden', 'true')\n indicator.hidden = true\n root.append(indicator)\n }\n\n root.append(ghost)\n moveGhost()\n captureLayout()\n }\n\n // Where the container's content coordinate 0 currently sits on screen. The\n // one live measurement the hit test needs — everything else is arithmetic on\n // the snapshot, so mid-transition rects can never feed back into the slot.\n //\n // This is the whole reason the hit test is neither document.elementFromPoint\n // nor rect-minus-delta reconstruction: the preview MOVES the cells under the\n // pointer, and a rect measured mid-transition contains only part of its\n // delta, so both models handed back zones shifted by the unfinished\n // remainder of the animation. Dragging with the direction of travel, that\n // shifted zone swallowed the next item's first half and the slot flipped\n // back and forth until the transition settled.\n const contentOrigin = (): number => {\n const scrollElement = options.getScrollElement()\n if (!scrollElement) {\n return 0\n }\n\n const rect = scrollElement.getBoundingClientRect()\n // scrollLeft stays a physical axis in every engine (RTL just runs it\n // negative), so it enters the negated space through the sign.\n return horizontal ?\n logicalStart(rect) - (axisSign * scrollElement.scrollLeft) :\n rect.top - scrollElement.scrollTop\n }\n\n const captureItem = (id: string, origin: number): boolean => {\n const element = options.items.getElements(id)[0]\n if (!element) {\n return false\n }\n\n const rect = element.getBoundingClientRect()\n // Corrected by the applied delta for items first seen mid-preview (a row\n // revealed by auto-scroll); at drag start every delta is zero.\n const start = logicalStart(rect) - (previewDeltas.get(id) ?? 0)\n contentStarts.set(id, start - origin)\n contentSizes.set(id, horizontal ? rect.width : rect.height)\n return true\n }\n\n const captureLayout = () => {\n contentStarts.clear()\n contentSizes.clear()\n const origin = contentOrigin()\n for (const id of options.items.getOrderedIds()) {\n captureItem(id, origin)\n }\n }\n\n const updateTarget = () => {\n const position = logicalPointer()\n const origin = contentOrigin()\n\n const zones: Array<{ id: string; start: number; size: number }> = []\n for (const id of options.items.getOrderedIds()) {\n if (!contentStarts.has(id) && !captureItem(id, origin)) {\n continue\n }\n\n zones.push({ id, start: origin + contentStarts.get(id)!, size: contentSizes.get(id)! })\n }\n\n let hit: { id: string; after: boolean } | null = null\n const lastZone = zones[zones.length - 1]\n const fromIndex = zones.findIndex(zone => zone.id === sourceHit!.id)\n\n if (lastZone && position > lastZone.start + lastZone.size) {\n // Past the end there is no zone to be inside, but the intent could not\n // be clearer: after the last item the source may land on. Same at the\n // start edge below.\n sticky = null\n for (let index = zones.length - 1; index >= 0; index--) {\n if (options.canDrop(sourceHit!.id, zones[index].id)) {\n hit = { id: zones[index].id, after: true }\n break\n }\n }\n } else if (lastZone && position < zones[0].start) {\n sticky = null\n for (const zone of zones) {\n if (options.canDrop(sourceHit!.id, zone.id)) {\n hit = { id: zone.id, after: false }\n break\n }\n }\n } else if (drop && sticky && position >= sticky.lo - DRAG_HYSTERESIS && position <= sticky.hi + DRAG_HYSTERESIS) {\n // Still inside (or barely past) the zone that produced the current\n // drop — keep it, so boundary jitter cannot re-animate.\n hit = drop\n } else {\n for (let index = 0; index < zones.length; index++) {\n const zone = zones[index]\n const previous = zones[index - 1]\n const following = zones[index + 1]\n // Zones TILE the axis: real tables have collapsed borders between the\n // cells, and those few pixels belong to no rect. A pointer crossing\n // such a gap used to hit nothing, which cleared the preview and\n // re-applied it on the far side — replaying the slide right at the\n // boundary. Each gap is split down its middle instead.\n const lo = previous ? (previous.start + previous.size + zone.start) / 2 : zone.start\n const hi = following ? (zone.start + zone.size + following.start) / 2 : zone.start + zone.size\n if (position < lo || position > hi) {\n continue\n }\n\n if (options.canDrop(sourceHit!.id, zone.id)) {\n // Entering a neighbour's zone displaces it AT ONCE — the swap fires\n // at the boundary, not at the neighbour's midpoint, which is the\n // feel MUI and AG have and what a drag reads as: \"I am past it, so\n // it moves\". The release then just commits whatever the preview\n // shows.\n hit = {\n id: zone.id,\n after: fromIndex === -1 ? position > zone.start + (zone.size / 2) : index > fromIndex\n }\n sticky = { lo, hi }\n }\n\n break\n }\n }\n\n if (!hit) {\n drop = null\n sticky = null\n hideIndicator()\n applyPreview()\n return\n }\n\n drop = hit\n showIndicator(options.items.getElements(hit.id)[0], hit.after)\n applyPreview()\n }\n\n const clearPreview = () => {\n for (const id of previewClassed) {\n for (const element of options.items.getElements(id)) {\n element.style.transform = ''\n element.classList.remove(CLASS_NAME_PREVIEW)\n }\n }\n\n previewKey = ''\n previewDeltas.clear()\n previewClassed.clear()\n }\n\n const clearLayout = () => {\n contentStarts.clear()\n contentSizes.clear()\n }\n\n const applyPreview = () => {\n if (!options.preview || !sourceHit) {\n return\n }\n\n const ids = options.items.getOrderedIds()\n const from = ids.indexOf(sourceHit.id)\n const target = drop ? ids.indexOf(drop.id) : -1\n const to = from === -1 || target === -1 ? from : destinationIndex(from, target, drop!.after)\n\n // Keyed on the DESTINATION SLOT, not on the hit: two hits that resolve to\n // the same slot (the clamp past the end vs the last zone, jitter inside\n // the hysteresis band) must not rewrite anything. A clear-and-reapply of\n // identical transforms next to a forced layout read restarts the running\n // transition from zero — the mid-drag replay this file has already paid\n // for once.\n const key = String(to)\n if (key === previewKey) {\n return\n }\n\n previewKey = key\n\n const next = new Map<string, number>()\n if (from !== -1 && to !== from) {\n // Sizes come from the drag-start snapshot: no DOM reads may happen in\n // here, or they would flush layout between the transform writes below.\n const sizeOf = (index: number): number => contentSizes.get(ids[index]) ?? 0\n const forward = to > from\n const first = forward ? from + 1 : to\n const last = forward ? to : from - 1\n const sourceSize = sizeOf(from)\n let travelled = 0\n\n for (let index = first; index <= last; index++) {\n travelled += sizeOf(index)\n next.set(ids[index], forward ? -sourceSize : sourceSize)\n }\n\n // The source moves by the combined size of everything it passed, so no\n // gap opens anywhere and the axis keeps its total extent.\n next.set(ids[from], forward ? travelled : -travelled)\n }\n\n // Only elements whose delta actually changed are touched; everything else\n // keeps its running transition undisturbed. An un-shift keeps the\n // transition class, so sliding back home animates exactly like sliding\n // aside did — the class only comes off when the drag ends.\n for (const id of previewDeltas.keys()) {\n if (!next.has(id)) {\n for (const element of options.items.getElements(id)) {\n element.style.transform = ''\n }\n }\n }\n\n for (const [id, delta] of next) {\n if (previewDeltas.get(id) === delta) {\n continue\n }\n\n for (const element of options.items.getElements(id)) {\n element.style.transform = horizontal ?\n `translateX(${axisSign * delta}px)` :\n `translateY(${delta}px)`\n element.classList.add(CLASS_NAME_PREVIEW)\n }\n\n previewClassed.add(id)\n }\n\n previewDeltas.clear()\n for (const [id, delta] of next) {\n previewDeltas.set(id, delta)\n }\n }\n\n // The gesture's closing beat: instead of vanishing at the pointer, the\n // ghost flies to where the item landed (or back home on cancel) and fades\n // out there. Purely cosmetic — the commit below never waits for it.\n const settleGhost = (x: number, y: number) => {\n if (!ghost) {\n return\n }\n\n const element = ghost\n // Taken out of cleanup's hands; it removes itself when the flight ends.\n ghost = null\n element.classList.add(CLASS_NAME_GHOST_SETTLE)\n element.style.transform = `translate(${x}px, ${y}px)`\n element.style.opacity = '0'\n\n let settled = false\n const finish = () => {\n if (!settled) {\n settled = true\n element.remove()\n }\n }\n\n element.addEventListener('transitionend', finish)\n setTimeout(finish, GHOST_SETTLE_FALLBACK_MS)\n }\n\n // Where the ghost should land: the source's current visual position for a\n // commit (the preview already put it in its slot), its untransformed home\n // for a cancel (the preview is about to slide everything back there).\n const settleTarget = (committed: boolean): { x: number; y: number } | null => {\n if (!sourceHit) {\n return null\n }\n\n const rect = sourceHit.element.getBoundingClientRect()\n if (committed) {\n return { x: rect.left, y: rect.top }\n }\n\n const delta = previewDeltas.get(sourceHit.id) ?? 0\n return horizontal ?\n { x: rect.left - (axisSign * delta), y: rect.top } :\n { x: rect.left, y: rect.top - delta }\n }\n\n const cleanup = () => {\n clearPreview()\n clearLayout()\n stopAutoScroll()\n root.classList.remove(CLASS_NAME_DRAG_ACTIVE)\n sourceHit?.element.classList.remove(CLASS_NAME_DRAGGING)\n ghost?.remove()\n indicator?.remove()\n ghost = null\n indicator = null\n sourceHit = null\n dragging = false\n drop = null\n sticky = null\n pointerId = -1\n document.removeEventListener('pointermove', onPointerMove)\n document.removeEventListener('pointerup', onPointerUp)\n document.removeEventListener('pointercancel', cancel)\n document.removeEventListener('keydown', onKeydown)\n }\n\n function cancel() {\n if (dragging) {\n const home = settleTarget(false)\n if (home) {\n settleGhost(home.x, home.y)\n }\n }\n\n cleanup()\n }\n\n function onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n event.preventDefault()\n cancel()\n }\n }\n\n function onPointerMove(event: PointerEvent) {\n if (event.pointerId !== pointerId || !sourceHit) {\n return\n }\n\n pointer = { x: event.clientX, y: event.clientY }\n\n if (!dragging) {\n const travelled = Math.max(Math.abs(pointer.x - origin.x), Math.abs(pointer.y - origin.y))\n if (travelled < DRAG_THRESHOLD) {\n return\n }\n\n startDrag()\n }\n\n // Suppresses the text selection a pointer drag would otherwise paint\n // across the header or the rows.\n event.preventDefault()\n moveGhost()\n updateTarget()\n\n if (!scrollFrame) {\n scrollFrame = requestAnimationFrame(autoScroll)\n }\n }\n\n function onPointerUp(event: PointerEvent) {\n if (event.pointerId !== pointerId) {\n return\n }\n\n const sourceId = sourceHit?.id\n const source = sourceHit?.element\n const pending = drop\n const wasDragging = dragging\n if (wasDragging) {\n const committed = Boolean(pending && pending.id !== sourceId)\n const landing = settleTarget(committed)\n if (landing) {\n settleGhost(landing.x, landing.y)\n }\n }\n\n cleanup()\n\n if (!wasDragging) {\n return\n }\n\n // A drag that ends on the element it started from is still followed by a\n // click there — which on a header cell would toggle the sort. Swallow\n // exactly that one. Releasing anywhere else fires the click on the common\n // ancestor instead (never the sort button), so arming there would only\n // risk eating an unrelated click; the 0 ms disarm covers the rest.\n if (source?.contains(event.target as Node)) {\n document.addEventListener('click', swallowClick, { capture: true, once: true })\n setTimeout(disarmSwallowClick, 0)\n }\n\n if (sourceId && pending && pending.id !== sourceId) {\n options.onDrop(sourceId, pending)\n }\n }\n\n const onPointerDown = (event: PointerEvent) => {\n // Primary button / single touch only — a right-click or a second finger\n // must not start a reorder.\n if (!event.isPrimary || (event.pointerType === 'mouse' && event.button !== 0) || sourceHit) {\n return\n }\n\n const element = (event.target as HTMLElement | null)?.closest<HTMLElement>(options.handle)\n if (!element) {\n return\n }\n\n const hit = options.resolveSource(element, event.target as HTMLElement)\n if (!hit) {\n return\n }\n\n sourceHit = hit\n pointerId = event.pointerId\n origin = { x: event.clientX, y: event.clientY }\n pointer = origin\n\n document.addEventListener('pointermove', onPointerMove)\n document.addEventListener('pointerup', onPointerUp)\n document.addEventListener('pointercancel', cancel)\n document.addEventListener('keydown', onKeydown)\n }\n\n root.addEventListener('pointerdown', onPointerDown)\n\n return {\n dispose() {\n root.removeEventListener('pointerdown', onPointerDown)\n disarmSwallowClick()\n cleanup()\n }\n }\n}\n\nconst SELECTOR_DRAGGABLE_COLUMN = 'th[data-coreui-draggable]'\nconst SELECTOR_RESIZER = '[data-coreui-resizer]'\n// Spacer and empty rows have a single colSpan cell, so a positional lookup\n// would land on the wrong thing.\nconst SELECTOR_PREVIEW_ROWS = 'thead tr, tbody tr:not(.data-grid-spacer):not(.data-grid-empty)'\n\n// A column's cells are found by POSITION, not by a data attribute: the body\n// only marks `data-coreui-column` when cellNavigation is on, while the header\n// always does — so the header cell's index is the reliable way in, and it\n// already accounts for the leading handle and select columns.\nconst columnItems = (root: HTMLElement): DragItems => ({\n getOrderedIds: () =>\n [...root.querySelectorAll<HTMLTableCellElement>('thead tr:first-child th[data-coreui-column]')]\n .map(cell => cell.dataset.coreuiColumn ?? ''),\n getElements(id) {\n const header = root.querySelector<HTMLTableCellElement>(`thead th[data-coreui-column=\"${id}\"]`)\n if (!header) {\n return []\n }\n\n const { cellIndex } = header\n const elements: HTMLElement[] = []\n for (const row of root.querySelectorAll<HTMLTableRowElement>(SELECTOR_PREVIEW_ROWS)) {\n const cell = row.children[cellIndex] as HTMLElement | undefined\n if (cell) {\n elements.push(cell)\n }\n }\n\n return elements\n }\n})\n\nexport interface ColumnDragOptions {\n root: HTMLElement\n getScrollElement: () => HTMLElement | null\n // Vetoes a target: the source itself, or a column in another pinned region —\n // reordering never crosses a pinning boundary.\n canDrop: (sourceKey: string, targetKey: string) => boolean\n onReorder: (sourceKey: string, targetKey: string, after: boolean) => void\n}\n\n// The column half of the wiring, shared so each edition's adapter is the four\n// lines that resolve its own table rather than a copy of the drag setup.\nexport const createColumnDragController = (options: ColumnDragOptions): DragController =>\n createDragController({\n axis: 'x',\n root: options.root,\n handle: SELECTOR_DRAGGABLE_COLUMN,\n getScrollElement: options.getScrollElement,\n resolveSource(element, target) {\n // A press on the resize handle is a resize, not a reorder.\n if (target.closest(SELECTOR_RESIZER)) {\n return null\n }\n\n const id = element.dataset.coreuiColumn\n return id ? { id, element } : null\n },\n items: columnItems(options.root),\n // Only a column the header marks as draggable is a slot, on top of the\n // consumer's own veto — an immovable column is not somewhere to land.\n canDrop: (sourceId, targetId) =>\n sourceId !== targetId &&\n Boolean(options.root.querySelector(`th[data-coreui-column=\"${targetId}\"][data-coreui-draggable]`)) &&\n options.canDrop(sourceId, targetId),\n preview: true,\n onDrop: (sourceKey, drop) => options.onReorder(sourceKey, drop.id, drop.after)\n })\n\nconst SELECTOR_ROW_HANDLE = '[data-coreui-row-handle]'\nconst SELECTOR_ROW = 'tr[data-coreui-index]'\n\nconst rowItems = (root: HTMLElement): DragItems => ({\n getOrderedIds: () =>\n [...root.querySelectorAll<HTMLElement>(`tbody ${SELECTOR_ROW}`)].map(row => row.dataset.coreuiIndex ?? ''),\n getElements(id) {\n const row = root.querySelector<HTMLElement>(`tbody tr[data-coreui-index=\"${id}\"]`)\n return row ? [row] : []\n }\n})\n\nexport interface RowDragOptions {\n root: HTMLElement\n getScrollElement: () => HTMLElement | null\n onReorder: (sourceIndex: number, targetIndex: number, after: boolean) => void\n}\n\n// The row half. Unlike columns, the whole row travels but only the grip cell\n// starts the drag — a row is covered in interactive content (checkboxes,\n// editors, custom cells) that a whole-row handle would swallow.\nexport const createRowDragController = (options: RowDragOptions): DragController =>\n createDragController({\n axis: 'y',\n root: options.root,\n handle: SELECTOR_ROW_HANDLE,\n getScrollElement: options.getScrollElement,\n resolveSource(handle) {\n const row = handle.closest<HTMLElement>(SELECTOR_ROW)\n const id = row?.dataset.coreuiIndex\n return row && id ? { id, element: row } : null\n },\n items: rowItems(options.root),\n canDrop: (sourceId, targetId) => sourceId !== targetId,\n // The row's own text is every cell run together; the first data cell reads\n // as the row's name in practice.\n // The row's own text is every cell run together, so the ghost carries the\n // first DATA cell instead — found by skipping the leading handle and\n // select cells rather than by data-coreui-column, which the body only\n // carries when cellNavigation is on (without it the ghost came up empty).\n ghostLabel: source =>\n collapse(\n source.element.querySelector(\n 'td:not(.data-grid-row-handle-cell):not(.data-grid-select-cell)'\n )?.textContent ?? ''\n ),\n preview: true,\n onDrop: (sourceId, drop) => options.onReorder(Number(sourceId), Number(drop.id), drop.after)\n })\n"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* CoreUI PRO data-grid v0.3.0-rc.0 (https://coreui.io)
|
|
3
|
+
* Copyright 2026 The CoreUI Team (https://github.com/orgs/coreui/people)
|
|
4
|
+
* License (https://coreui.io/pro/license/)
|
|
5
|
+
*/
|
|
6
|
+
//#region src/util/export-table.ts
|
|
7
|
+
const rowsFor = (table, scope) => {
|
|
8
|
+
if (scope === "all") return table.getCoreRowModel().rows;
|
|
9
|
+
if (scope === "selected") return table.getSelectedRowModel?.().rows ?? [];
|
|
10
|
+
return (table.getSortedRowModel ?? table.getFilteredRowModel ?? table.getCoreRowModel)().rows;
|
|
11
|
+
};
|
|
12
|
+
const columnsFor = (table) => {
|
|
13
|
+
if (table.getCenterVisibleLeafColumns) return [
|
|
14
|
+
...table.getStartVisibleLeafColumns?.() ?? [],
|
|
15
|
+
...table.getCenterVisibleLeafColumns(),
|
|
16
|
+
...table.getEndVisibleLeafColumns?.() ?? []
|
|
17
|
+
];
|
|
18
|
+
return table.getVisibleLeafColumns?.() ?? table.getAllLeafColumns();
|
|
19
|
+
};
|
|
20
|
+
const headerFor = (column) => String(column.columnDef.meta?.label ?? column.id);
|
|
21
|
+
const formatterFor = (column) => column.columnDef.meta?.formatter;
|
|
22
|
+
const widthFor = (column) => column.columnDef.meta?.width;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { widthFor as a, rowsFor as i, formatterFor as n, headerFor as r, columnsFor as t };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=export-table-BdabEbJG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-table-BdabEbJG.mjs","names":[],"sources":["../../src/util/export-table.ts"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * CoreUI PRO data-grid util/export-table.ts\n * License (https://coreui.io/pro/license/)\n * --------------------------------------------------------------------------\n */\n\nimport type { DataGridItem } from '../types'\n\n// Typed structurally, not as one edition's table: TFeatures is invariant in v9,\n// so the vanilla grid and each framework binding (whose adapter registers its\n// own reactivity feature) have mutually incompatible Table types even though\n// they expose the same row/column surface an export needs. Everything beyond\n// the core row model is optional - a reduced feature set exports whatever\n// layout/scope its features can express and falls back to core for the rest.\n\nexport interface ExportColumnMeta {\n label?: string\n formatter?: (value: unknown, item: DataGridItem) => string\n width?: number\n}\n\nexport interface ExportColumn {\n id: string\n columnDef: { meta?: unknown }\n}\n\nexport interface ExportRow {\n original: DataGridItem\n getValue: (columnId: string) => unknown\n}\n\nexport interface ExportTable {\n getAllLeafColumns: () => ExportColumn[]\n getCenterVisibleLeafColumns?: () => ExportColumn[]\n getCoreRowModel: () => { rows: ExportRow[] }\n getEndVisibleLeafColumns?: () => ExportColumn[]\n getFilteredRowModel?: () => { rows: ExportRow[] }\n getSelectedRowModel?: () => { rows: ExportRow[] }\n getSortedRowModel?: () => { rows: ExportRow[] }\n getStartVisibleLeafColumns?: () => ExportColumn[]\n getVisibleLeafColumns?: () => ExportColumn[]\n}\n\nexport type ExportScope = 'filtered' | 'all' | 'selected'\n\nexport const rowsFor = (table: ExportTable, scope: ExportScope | undefined): ExportRow[] => {\n if (scope === 'all') {\n return table.getCoreRowModel().rows\n }\n\n if (scope === 'selected') {\n return table.getSelectedRowModel?.().rows ?? []\n }\n\n return (table.getSortedRowModel ?? table.getFilteredRowModel ?? table.getCoreRowModel)().rows\n}\n\n// Exports follow the rendered layout: pinning, column order and visibility -\n// as far as the registered features track them.\nexport const columnsFor = (table: ExportTable): ExportColumn[] => {\n if (table.getCenterVisibleLeafColumns) {\n return [\n ...(table.getStartVisibleLeafColumns?.() ?? []),\n ...table.getCenterVisibleLeafColumns(),\n ...(table.getEndVisibleLeafColumns?.() ?? [])\n ]\n }\n\n return table.getVisibleLeafColumns?.() ?? table.getAllLeafColumns()\n}\n\nexport const headerFor = (column: ExportColumn): string =>\n String((column.columnDef.meta as ExportColumnMeta)?.label ?? column.id)\n\n// A column formatter is author intent and matches what the grid renders, so\n// exports honor it - which also means a formatted number leaves as text.\nexport const formatterFor = (column: ExportColumn): ExportColumnMeta['formatter'] =>\n (column.columnDef.meta as ExportColumnMeta)?.formatter\n\n// The author's declared column width in px. Deliberately NOT column.getSize():\n// that returns table-core's 150 px default whenever the grid does not track\n// sizing, which would force an arbitrary width on every exported column. A\n// consequence is that an interactive resize is not carried into the export.\nexport const widthFor = (column: ExportColumn): number | undefined =>\n (column.columnDef.meta as ExportColumnMeta)?.width\n"],"mappings":";;;;;;AA8CA,MAAa,WAAW,OAAoB,UAAgD;CAC1F,IAAI,UAAU,OACZ,OAAO,MAAM,gBAAgB,CAAC,CAAC;CAGjC,IAAI,UAAU,YACZ,OAAO,MAAM,sBAAsB,CAAC,CAAC,QAAQ,CAAC;CAGhD,QAAQ,MAAM,qBAAqB,MAAM,uBAAuB,MAAM,gBAAA,CAAiB,CAAC,CAAC;AAC3F;AAIA,MAAa,cAAc,UAAuC;CAChE,IAAI,MAAM,6BACR,OAAO;EACL,GAAI,MAAM,6BAA6B,KAAK,CAAC;EAC7C,GAAG,MAAM,4BAA4B;EACrC,GAAI,MAAM,2BAA2B,KAAK,CAAC;CAC7C;CAGF,OAAO,MAAM,wBAAwB,KAAK,MAAM,kBAAkB;AACpE;AAEA,MAAa,aAAa,WACxB,OAAQ,OAAO,UAAU,MAA2B,SAAS,OAAO,EAAE;AAIxE,MAAa,gBAAgB,WAC1B,OAAO,UAAU,MAA2B;AAM/C,MAAa,YAAY,WACtB,OAAO,UAAU,MAA2B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* CoreUI PRO data-grid v0.3.0-rc.0 (https://coreui.io)
|
|
3
|
+
* Copyright 2026 The CoreUI Team (https://github.com/orgs/coreui/people)
|
|
4
|
+
* License (https://coreui.io/pro/license/)
|
|
5
|
+
*/
|
|
6
|
+
//#region src/util/export-table.ts
|
|
7
|
+
const rowsFor = (table, scope) => {
|
|
8
|
+
if (scope === "all") return table.getCoreRowModel().rows;
|
|
9
|
+
if (scope === "selected") return table.getSelectedRowModel?.().rows ?? [];
|
|
10
|
+
return (table.getSortedRowModel ?? table.getFilteredRowModel ?? table.getCoreRowModel)().rows;
|
|
11
|
+
};
|
|
12
|
+
const columnsFor = (table) => {
|
|
13
|
+
if (table.getCenterVisibleLeafColumns) return [
|
|
14
|
+
...table.getStartVisibleLeafColumns?.() ?? [],
|
|
15
|
+
...table.getCenterVisibleLeafColumns(),
|
|
16
|
+
...table.getEndVisibleLeafColumns?.() ?? []
|
|
17
|
+
];
|
|
18
|
+
return table.getVisibleLeafColumns?.() ?? table.getAllLeafColumns();
|
|
19
|
+
};
|
|
20
|
+
const headerFor = (column) => String(column.columnDef.meta?.label ?? column.id);
|
|
21
|
+
const formatterFor = (column) => column.columnDef.meta?.formatter;
|
|
22
|
+
const widthFor = (column) => column.columnDef.meta?.width;
|
|
23
|
+
//#endregion
|
|
24
|
+
Object.defineProperty(exports, "columnsFor", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function() {
|
|
27
|
+
return columnsFor;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "formatterFor", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function() {
|
|
33
|
+
return formatterFor;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "headerFor", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function() {
|
|
39
|
+
return headerFor;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "rowsFor", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function() {
|
|
45
|
+
return rowsFor;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "widthFor", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function() {
|
|
51
|
+
return widthFor;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=export-table-D762wrZ1.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-table-D762wrZ1.cjs","names":[],"sources":["../../src/util/export-table.ts"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * CoreUI PRO data-grid util/export-table.ts\n * License (https://coreui.io/pro/license/)\n * --------------------------------------------------------------------------\n */\n\nimport type { DataGridItem } from '../types'\n\n// Typed structurally, not as one edition's table: TFeatures is invariant in v9,\n// so the vanilla grid and each framework binding (whose adapter registers its\n// own reactivity feature) have mutually incompatible Table types even though\n// they expose the same row/column surface an export needs. Everything beyond\n// the core row model is optional - a reduced feature set exports whatever\n// layout/scope its features can express and falls back to core for the rest.\n\nexport interface ExportColumnMeta {\n label?: string\n formatter?: (value: unknown, item: DataGridItem) => string\n width?: number\n}\n\nexport interface ExportColumn {\n id: string\n columnDef: { meta?: unknown }\n}\n\nexport interface ExportRow {\n original: DataGridItem\n getValue: (columnId: string) => unknown\n}\n\nexport interface ExportTable {\n getAllLeafColumns: () => ExportColumn[]\n getCenterVisibleLeafColumns?: () => ExportColumn[]\n getCoreRowModel: () => { rows: ExportRow[] }\n getEndVisibleLeafColumns?: () => ExportColumn[]\n getFilteredRowModel?: () => { rows: ExportRow[] }\n getSelectedRowModel?: () => { rows: ExportRow[] }\n getSortedRowModel?: () => { rows: ExportRow[] }\n getStartVisibleLeafColumns?: () => ExportColumn[]\n getVisibleLeafColumns?: () => ExportColumn[]\n}\n\nexport type ExportScope = 'filtered' | 'all' | 'selected'\n\nexport const rowsFor = (table: ExportTable, scope: ExportScope | undefined): ExportRow[] => {\n if (scope === 'all') {\n return table.getCoreRowModel().rows\n }\n\n if (scope === 'selected') {\n return table.getSelectedRowModel?.().rows ?? []\n }\n\n return (table.getSortedRowModel ?? table.getFilteredRowModel ?? table.getCoreRowModel)().rows\n}\n\n// Exports follow the rendered layout: pinning, column order and visibility -\n// as far as the registered features track them.\nexport const columnsFor = (table: ExportTable): ExportColumn[] => {\n if (table.getCenterVisibleLeafColumns) {\n return [\n ...(table.getStartVisibleLeafColumns?.() ?? []),\n ...table.getCenterVisibleLeafColumns(),\n ...(table.getEndVisibleLeafColumns?.() ?? [])\n ]\n }\n\n return table.getVisibleLeafColumns?.() ?? table.getAllLeafColumns()\n}\n\nexport const headerFor = (column: ExportColumn): string =>\n String((column.columnDef.meta as ExportColumnMeta)?.label ?? column.id)\n\n// A column formatter is author intent and matches what the grid renders, so\n// exports honor it - which also means a formatted number leaves as text.\nexport const formatterFor = (column: ExportColumn): ExportColumnMeta['formatter'] =>\n (column.columnDef.meta as ExportColumnMeta)?.formatter\n\n// The author's declared column width in px. Deliberately NOT column.getSize():\n// that returns table-core's 150 px default whenever the grid does not track\n// sizing, which would force an arbitrary width on every exported column. A\n// consequence is that an interactive resize is not carried into the export.\nexport const widthFor = (column: ExportColumn): number | undefined =>\n (column.columnDef.meta as ExportColumnMeta)?.width\n"],"mappings":";;;;;;AA8CA,MAAa,WAAW,OAAoB,UAAgD;CAC1F,IAAI,UAAU,OACZ,OAAO,MAAM,gBAAgB,CAAC,CAAC;CAGjC,IAAI,UAAU,YACZ,OAAO,MAAM,sBAAsB,CAAC,CAAC,QAAQ,CAAC;CAGhD,QAAQ,MAAM,qBAAqB,MAAM,uBAAuB,MAAM,gBAAA,CAAiB,CAAC,CAAC;AAC3F;AAIA,MAAa,cAAc,UAAuC;CAChE,IAAI,MAAM,6BACR,OAAO;EACL,GAAI,MAAM,6BAA6B,KAAK,CAAC;EAC7C,GAAG,MAAM,4BAA4B;EACrC,GAAI,MAAM,2BAA2B,KAAK,CAAC;CAC7C;CAGF,OAAO,MAAM,wBAAwB,KAAK,MAAM,kBAAkB;AACpE;AAEA,MAAa,aAAa,WACxB,OAAQ,OAAO,UAAU,MAA2B,SAAS,OAAO,EAAE;AAIxE,MAAa,gBAAgB,WAC1B,OAAO,UAAU,MAA2B;AAM/C,MAAa,YAAY,WACtB,OAAO,UAAU,MAA2B"}
|