@r2digisolutions/ui 0.24.2 → 0.24.4
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.
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
manager.setReservedWidth(reserved);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
//
|
|
74
|
+
// Reflow ancho
|
|
75
75
|
$effect(() => {
|
|
76
76
|
if (!container) return;
|
|
77
77
|
const ro = new ResizeObserver((entries) => {
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
return () => ro.disconnect();
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
//
|
|
85
|
+
// Medir DOM
|
|
86
86
|
const SAMPLE_ROWS = 10;
|
|
87
87
|
async function measureColumns() {
|
|
88
88
|
await tick();
|
|
@@ -124,7 +124,14 @@
|
|
|
124
124
|
) {
|
|
125
125
|
e.preventDefault();
|
|
126
126
|
const columnIndex = columnId ? manager.state.visibleColumns.indexOf(columnId) : null;
|
|
127
|
-
rightMenu
|
|
127
|
+
if (rightMenu.open) {
|
|
128
|
+
rightMenu = { open: false, x: 0, y: 0 };
|
|
129
|
+
setTimeout(() => {
|
|
130
|
+
rightMenu = { open: true, x: e.clientX, y: e.clientY };
|
|
131
|
+
}, 0);
|
|
132
|
+
} else {
|
|
133
|
+
rightMenu = { open: true, x: e.clientX, y: e.clientY };
|
|
134
|
+
}
|
|
128
135
|
rightClickContext = {
|
|
129
136
|
row,
|
|
130
137
|
rowIndex,
|
|
@@ -140,13 +147,13 @@
|
|
|
140
147
|
return manager.state.items.filter((r) => ids.has(rowId(r)));
|
|
141
148
|
}
|
|
142
149
|
|
|
143
|
-
// tracks
|
|
144
150
|
function colTrack(cId: string, measuring: boolean) {
|
|
145
151
|
if (measuring) return 'max-content';
|
|
146
152
|
const c = manager.getColumn(cId);
|
|
147
153
|
const w = manager.measured[cId] ?? c.width ?? c.minWidth ?? 160;
|
|
148
154
|
return `${Math.max(40, Math.ceil(Number(w)))}px`;
|
|
149
155
|
}
|
|
156
|
+
|
|
150
157
|
function headerTemplateCols(visible: string[], endExtras: boolean) {
|
|
151
158
|
const tracks = [
|
|
152
159
|
`${CHECK_W}px`,
|
|
@@ -282,7 +289,7 @@
|
|
|
282
289
|
data-dt-cell="1"
|
|
283
290
|
data-col-id={cid}
|
|
284
291
|
data-row-index={i}
|
|
285
|
-
class="px-3"
|
|
292
|
+
class="flex h-full w-full items-center px-3"
|
|
286
293
|
onclick={() => onRowClick?.(row)}
|
|
287
294
|
oncontextmenu={(e) => onCellContext(e, row, cid, i)}
|
|
288
295
|
>
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { TContextMenuEntry } from '../core/types.js';
|
|
3
3
|
|
|
4
|
-
// --- Action portal
|
|
4
|
+
// --- Action portal ---
|
|
5
5
|
function portal(node: HTMLElement, target: HTMLElement | null = null) {
|
|
6
6
|
const tgt = target ?? document.body;
|
|
7
7
|
const placeholder = document.createComment('portal-placeholder');
|
|
8
|
-
node.parentNode
|
|
8
|
+
if (!node.parentNode) return { destroy: () => {} };
|
|
9
|
+
node.parentNode.insertBefore(placeholder, node);
|
|
9
10
|
tgt.appendChild(node);
|
|
10
11
|
return {
|
|
11
12
|
destroy() {
|
|
12
|
-
node.remove();
|
|
13
|
-
placeholder.
|
|
14
|
-
|
|
13
|
+
if (node.isConnected) node.remove();
|
|
14
|
+
if (placeholder.isConnected && placeholder.parentNode) {
|
|
15
|
+
placeholder.parentNode.insertBefore(node, placeholder);
|
|
16
|
+
placeholder.remove();
|
|
17
|
+
}
|
|
15
18
|
}
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
// --- Util para clamping a viewport
|
|
22
|
+
// --- Util para clamping a viewport ---
|
|
20
23
|
function clampToViewport(x: number, y: number, menuW: number, menuH: number, padding = 8) {
|
|
21
24
|
const vw = document.documentElement.clientWidth;
|
|
22
25
|
const vh = document.documentElement.clientHeight;
|
|
@@ -54,12 +57,14 @@
|
|
|
54
57
|
let q = $state('');
|
|
55
58
|
const current = $derived(stack.length ? stack[stack.length - 1] : { label: title, items });
|
|
56
59
|
|
|
60
|
+
let menuEl: HTMLDivElement | null = $state(null);
|
|
61
|
+
|
|
57
62
|
function close() {
|
|
58
63
|
open = false;
|
|
59
64
|
stack = [];
|
|
60
65
|
q = '';
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
x = 0;
|
|
67
|
+
y = 0;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
function hasChildren(it: TContextMenuEntry) {
|
|
@@ -91,8 +96,6 @@
|
|
|
91
96
|
const list = current.items ?? [];
|
|
92
97
|
const query = q.trim().toLowerCase();
|
|
93
98
|
let arr = query ? list.filter((it) => matches(it, query)) : list.slice();
|
|
94
|
-
|
|
95
|
-
// limpiar divisores consecutivos y extremos
|
|
96
99
|
const out: TContextMenuEntry[] = [];
|
|
97
100
|
let prevDiv = false;
|
|
98
101
|
for (const it of arr) {
|
|
@@ -125,9 +128,6 @@
|
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
// --- Ref al elemento del menú para detectar click-fuera ---
|
|
129
|
-
let menuEl: HTMLDivElement | null = $state(null);
|
|
130
|
-
|
|
131
131
|
// Teclado (Escape / Backspace)
|
|
132
132
|
$effect(() => {
|
|
133
133
|
if (!open) return;
|
|
@@ -136,30 +136,34 @@
|
|
|
136
136
|
return () => document.removeEventListener('keydown', handler);
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
// Cierres robustos: click-fuera
|
|
139
|
+
// Cierres robustos: click-fuera, scroll/resize, y bloqueo de menú nativo
|
|
140
140
|
$effect(() => {
|
|
141
|
-
if (!open) return;
|
|
141
|
+
if (!open || !menuEl) return;
|
|
142
142
|
|
|
143
|
-
const
|
|
144
|
-
if (!menuEl) return;
|
|
145
|
-
|
|
146
|
-
close();
|
|
147
|
-
}
|
|
143
|
+
const onPointerDown = (ev: PointerEvent) => {
|
|
144
|
+
if (!menuEl || menuEl.contains(ev.target as Node)) return;
|
|
145
|
+
close();
|
|
148
146
|
};
|
|
149
147
|
|
|
150
148
|
const onNativeCtx = (ev: MouseEvent) => {
|
|
149
|
+
if (!menuEl || menuEl.contains(ev.target as Node)) return;
|
|
151
150
|
ev.preventDefault();
|
|
152
151
|
};
|
|
153
152
|
|
|
154
|
-
|
|
153
|
+
let timeout: NodeJS.Timeout;
|
|
154
|
+
const onScrollOrResize = () => {
|
|
155
|
+
clearTimeout(timeout);
|
|
156
|
+
timeout = setTimeout(() => close(), 100);
|
|
157
|
+
};
|
|
155
158
|
|
|
156
|
-
document.addEventListener('pointerdown',
|
|
159
|
+
document.addEventListener('pointerdown', onPointerDown);
|
|
157
160
|
document.addEventListener('contextmenu', onNativeCtx);
|
|
158
161
|
window.addEventListener('scroll', onScrollOrResize, true);
|
|
159
162
|
window.addEventListener('resize', onScrollOrResize, true);
|
|
160
163
|
|
|
161
164
|
return () => {
|
|
162
|
-
|
|
165
|
+
clearTimeout(timeout);
|
|
166
|
+
document.removeEventListener('pointerdown', onPointerDown);
|
|
163
167
|
document.removeEventListener('contextmenu', onNativeCtx);
|
|
164
168
|
window.removeEventListener('scroll', onScrollOrResize, true);
|
|
165
169
|
window.removeEventListener('resize', onScrollOrResize, true);
|
|
@@ -182,7 +186,7 @@
|
|
|
182
186
|
</script>
|
|
183
187
|
|
|
184
188
|
{#if open}
|
|
185
|
-
<!-- BACKDROP
|
|
189
|
+
<!-- BACKDROP -->
|
|
186
190
|
<div
|
|
187
191
|
use:portal={portalTarget}
|
|
188
192
|
role="dialog"
|
|
@@ -194,7 +198,7 @@
|
|
|
194
198
|
style="pointer-events:auto"
|
|
195
199
|
/>
|
|
196
200
|
|
|
197
|
-
<!-- MENÚ
|
|
201
|
+
<!-- MENÚ -->
|
|
198
202
|
<div
|
|
199
203
|
bind:this={menuEl}
|
|
200
204
|
use:portal={portalTarget}
|