@r2digisolutions/ui 0.24.4 → 0.24.7

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.
@@ -124,22 +124,19 @@
124
124
  ) {
125
125
  e.preventDefault();
126
126
  const columnIndex = columnId ? manager.state.visibleColumns.indexOf(columnId) : null;
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 {
127
+ // Reset menu state and set new coordinates
128
+ rightMenu = { open: false, x: 0, y: 0 };
129
+ tick().then(() => {
133
130
  rightMenu = { open: true, x: e.clientX, y: e.clientY };
134
- }
135
- rightClickContext = {
136
- row,
137
- rowIndex,
138
- columnId,
139
- columnIndex,
140
- event: e,
141
- column: columnId ? manager.getColumn(columnId) : null
142
- } as TDataTableCellContext<T>;
131
+ rightClickContext = {
132
+ row,
133
+ rowIndex,
134
+ columnId,
135
+ columnIndex,
136
+ event: e,
137
+ column: columnId ? manager.getColumn(columnId) : null
138
+ } as TDataTableCellContext<T>;
139
+ });
143
140
  }
144
141
 
145
142
  function selectedRows(): T[] {
@@ -5,14 +5,19 @@
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
- if (!node.parentNode) return { destroy: () => {} };
9
- node.parentNode.insertBefore(placeholder, node);
8
+ if (node.parentNode) {
9
+ node.parentNode.insertBefore(placeholder, node);
10
+ }
11
+ // Remove any existing menu instances
12
+ const existingMenus = document.querySelectorAll('.context-menu-portal');
13
+ existingMenus.forEach((menu) => menu.remove());
14
+ // Add class for identification
15
+ node.classList.add('context-menu-portal');
10
16
  tgt.appendChild(node);
11
17
  return {
12
18
  destroy() {
13
19
  if (node.isConnected) node.remove();
14
20
  if (placeholder.isConnected && placeholder.parentNode) {
15
- placeholder.parentNode.insertBefore(node, placeholder);
16
21
  placeholder.remove();
17
22
  }
18
23
  }
@@ -65,6 +70,12 @@
65
70
  q = '';
66
71
  x = 0;
67
72
  y = 0;
73
+ if (menuEl) {
74
+ menuEl.style.left = '0px';
75
+ menuEl.style.top = '0px';
76
+ menuEl.remove();
77
+ menuEl = null;
78
+ }
68
79
  }
69
80
 
70
81
  function hasChildren(it: TContextMenuEntry) {
@@ -170,40 +181,21 @@
170
181
  };
171
182
  });
172
183
 
173
- // Clamp de posición tras abrir o cambiar coords
184
+ // Aplicar posición tras abrir o cambiar coords
174
185
  $effect(() => {
175
186
  if (!open || !menuEl) return;
176
- requestAnimationFrame(() => {
177
- if (!menuEl) return;
178
- const rect = menuEl.getBoundingClientRect();
179
- const { x: nx, y: ny } = clampToViewport(x, y, rect.width, rect.height, 8);
180
- if (nx !== x || ny !== y) {
181
- x = nx;
182
- y = ny;
183
- }
184
- });
187
+ const rect = menuEl.getBoundingClientRect();
188
+ const { x: nx, y: ny } = clampToViewport(x, y, rect.width, rect.height, 8);
189
+ menuEl.style.left = `${nx}px`;
190
+ menuEl.style.top = `${ny}px`;
185
191
  });
186
192
  </script>
187
193
 
188
194
  {#if open}
189
- <!-- BACKDROP -->
190
- <div
191
- use:portal={portalTarget}
192
- role="dialog"
193
- class="fixed inset-0 z-[2147483646]"
194
- onclick={() => close()}
195
- oncontextmenu={(e) => e.preventDefault()}
196
- aria-modal="true"
197
- tabindex="0"
198
- style="pointer-events:auto"
199
- />
200
-
201
- <!-- MENÚ -->
202
195
  <div
203
196
  bind:this={menuEl}
204
197
  use:portal={portalTarget}
205
- class="fixed z-[2147483647] w-72 rounded-2xl bg-white p-2 shadow-xl ring-1 ring-black/5 dark:bg-gray-900"
206
- style={`left:${x}px; top:${y}px`}
198
+ class="context-menu-portal fixed z-[2147483647] w-72 rounded-2xl bg-white p-2 shadow-xl ring-1 ring-black/5 dark:bg-gray-900"
207
199
  oncontextmenu={(e) => e.preventDefault()}
208
200
  >
209
201
  <div class="flex items-center gap-1 px-1 py-1">
@@ -241,42 +233,46 @@
241
233
  <div
242
234
  class="max-h-72 overflow-auto rounded-xl border border-gray-200 p-1 dark:border-gray-800 dark:bg-gray-950"
243
235
  >
244
- {#each filtered as it}
245
- {#if it.kind === 'divider'}
246
- <div class="my-1 border-t border-gray-200 dark:border-gray-800"></div>
247
- {:else if it.kind === 'label'}
248
- <div class="px-3 py-1 text-[11px] tracking-wide uppercase opacity-60">{it.label}</div>
249
- {:else}
250
- <button
251
- class="flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-gray-100 disabled:opacity-50 dark:hover:bg-gray-800"
252
- role="dialog"
253
- disabled={it.disabled}
254
- onclick={() => clickItem(it)}
255
- >
256
- <span class="truncate">{it.label}</span>
257
- <span class="flex items-center gap-2">
258
- {#if it.shortcut}
259
- <kbd class="rounded bg-gray-100 px-1 text-[10px] dark:bg-gray-800"
260
- >{it.shortcut}</kbd
261
- >
262
- {/if}
263
- {#if hasChildren(it)}
264
- <svg
265
- width="14"
266
- height="14"
267
- viewBox="0 0 24 24"
268
- class="opacity-60"
269
- fill="none"
270
- stroke="currentColor"
271
- stroke-width="2"
272
- stroke-linecap="round"
273
- stroke-linejoin="round"><polyline points="9 18 15 12 9 6" /></svg
274
- >
275
- {/if}
276
- </span>
277
- </button>
278
- {/if}
279
- {/each}
236
+ {#if filtered.length}
237
+ {#each filtered as it}
238
+ {#if it.kind === 'divider'}
239
+ <div class="my-1 border-t border-gray-200 dark:border-gray-800"></div>
240
+ {:else if it.kind === 'label'}
241
+ <div class="px-3 py-1 text-[11px] tracking-wide uppercase opacity-60">{it.label}</div>
242
+ {:else}
243
+ <button
244
+ class="flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-gray-100 disabled:opacity-50 dark:hover:bg-gray-800"
245
+ role="dialog"
246
+ disabled={it.disabled}
247
+ onclick={() => clickItem(it)}
248
+ >
249
+ <span class="truncate">{it.label}</span>
250
+ <span class="flex items-center gap-2">
251
+ {#if it.shortcut}
252
+ <kbd class="rounded bg-gray-100 px-1 text-[10px] dark:bg-gray-800"
253
+ >{it.shortcut}</kbd
254
+ >
255
+ {/if}
256
+ {#if hasChildren(it)}
257
+ <svg
258
+ width="14"
259
+ height="14"
260
+ viewBox="0 0 24 24"
261
+ class="opacity-60"
262
+ fill="none"
263
+ stroke="currentColor"
264
+ stroke-width="2"
265
+ stroke-linecap="round"
266
+ stroke-linejoin="round"><polyline points="9 18 15 12 9 6" /></svg
267
+ >
268
+ {/if}
269
+ </span>
270
+ </button>
271
+ {/if}
272
+ {/each}
273
+ {:else}
274
+ <div class="my-1 border-t border-gray-200 dark:border-gray-800">No hay resultados</div>
275
+ {/if}
280
276
  </div>
281
277
  </div>
282
278
  {/if}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/ui",
3
- "version": "0.24.4",
3
+ "version": "0.24.7",
4
4
  "private": false,
5
5
  "packageManager": "bun@1.2.23",
6
6
  "publishConfig": {