@lavalogic/scoria 0.37.32 → 0.37.33

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.
@@ -90,8 +90,6 @@ export function attachDropdownPortal(options) {
90
90
  /* nothing wired up */
91
91
  };
92
92
  }
93
- let originalParent = null;
94
- let originalNextSibling = null;
95
93
  let isPortalled = false;
96
94
  const reposition = () => {
97
95
  if (!isPortalled) {
@@ -140,68 +138,36 @@ export function attachDropdownPortal(options) {
140
138
  const handleResize = () => {
141
139
  throttled.schedule();
142
140
  };
143
- /**
144
- * Direct mousedown listener attached to the portaled dropdown that
145
- * calls `preventDefault()` to keep focus on the Svelecte input while
146
- * the user clicks an option.
147
- *
148
- * Svelecte already attaches `onmousedown={preventDefault}` to the
149
- * `.sv_dropdown` element in template, but Svelte 5 wires inline
150
- * event handlers through its delegated-event chain rooted at the
151
- * original mount point. Once we `appendChild` the dropdown to
152
- * `document.body` (or to a `<dialog>` ancestor) the delegated chain
153
- * no longer finds this element, the inline handler never fires,
154
- * the browser's default mousedown shifts focus to the option (or to
155
- * `body`), Svelecte's `on_blur` runs `updateDropdownState(false)`
156
- * which closes the dropdown, this helper's MutationObserver moves
157
- * the dropdown back into place, and the `mouseup` / `click` events
158
- * never reach an option element. The visible symptom: keyboard
159
- * selection (Enter) works, mouse click does not.
160
- *
161
- * Adding a *direct* `addEventListener` on the dropdown bypasses
162
- * Svelte's delegation entirely. The listener is reset every
163
- * `portalOut` / `portalIn` cycle.
164
- */
165
- const preventFocusShiftOnMousedown = (e) => {
166
- // Same intent as Svelecte's own `on_mouse_down`. Keep focus on
167
- // the input so `on_blur` does not collapse the dropdown before
168
- // the click event reaches its selection handler.
169
- e.preventDefault();
170
- };
171
141
  const portalOut = () => {
172
142
  if (isPortalled) {
173
143
  return;
174
144
  }
175
- originalParent = dropdown.parentNode;
176
- originalNextSibling = dropdown.nextSibling;
177
- // Clear any `display: none` left over from a previous portalIn
178
- // (see the defensive hide there) so the dropdown is visible
179
- // once teleported into the new host.
145
+ // PREVIOUSLY: this helper moved the dropdown to `document.body`
146
+ // (or to the open `<dialog>` ancestor) via `appendChild` so it
147
+ // would escape ancestor `overflow: hidden` / `z-index` clipping.
148
+ // That hop broke Svelte 5's per-component event delegation:
149
+ // inline `onmousedown` / `onclick` handlers in Svelecte's
150
+ // template (specifically the `.sv_dropdown` element) are wired
151
+ // through a delegated dispatch rooted at the component's
152
+ // original mount point, and the dispatch's parent-chain walk
153
+ // never reaches the moved element. The visible symptom: mouse
154
+ // clicks on dropdown options did not select (keyboard Enter
155
+ // did, because that path bypasses the dropdown's click
156
+ // handler).
157
+ //
158
+ // We now leave the dropdown in its original DOM location and
159
+ // only flip it to `position: fixed`. `position: fixed` escapes
160
+ // ancestor `overflow` clipping (the original motivation for
161
+ // portaling) without removing the element from its component
162
+ // tree, so Svelte's delegated dispatch continues to find it.
163
+ // The reposition logic below tracks the trigger via
164
+ // `getBoundingClientRect` exactly as before.
180
165
  dropdown.style.display = '';
181
- // Append the dropdown to the nearest open native `<dialog>` ancestor
182
- // when one exists, otherwise to `document.body`. A `<dialog>` opened
183
- // via `showModal()` renders in the browser's top layer, which sits
184
- // above every z-indexed element in the regular stacking context.
185
- // Without this hop the dropdown's `z-index: 10000` was still painted
186
- // behind the dialog backdrop and its content (the symptom that
187
- // surfaced as "select options disappear behind the allocate modal").
188
- const dialogHost = trigger.closest('dialog');
189
- const portalTarget = dialogHost && dialogHost.open ? dialogHost : document.body;
190
- portalTarget.appendChild(dropdown);
191
- // Tag the teleported dropdown so any "click outside the
192
- // panel" / "click outside the trigger" handler elsewhere in
193
- // the codebase can recognise the dropdown as a logical
194
- // extension of its trigger and ignore clicks landing inside
195
- // it. The `TableSidebar` side-panel uses this marker (along
196
- // with `closest('.sv_dropdown')`) so clicking an option in a
197
- // teleported filter-row dropdown does not close the
198
- // side-panel under it. Components that want to ignore
199
- // portal clicks should check
200
- // `el.closest('[data-scoria-portal-dropdown]')`.
166
+ // Marker preserved for any consumer that still uses it (e.g.
167
+ // the TableSidebar "click-outside" handler). The dropdown is
168
+ // no longer literally portaled, but the marker means "treat
169
+ // clicks landing here as part of the trigger".
201
170
  dropdown.setAttribute('data-scoria-portal-dropdown', '');
202
- // Restore the focus-preserving mousedown handler that Svelte's
203
- // delegated event chain no longer reaches after the move.
204
- dropdown.addEventListener('mousedown', preventFocusShiftOnMousedown);
205
171
  isPortalled = true;
206
172
  // First-frame measurement: lay out, then reposition again on
207
173
  // the next frame so we measure the dropdown's real
@@ -220,7 +186,6 @@ export function attachDropdownPortal(options) {
220
186
  return;
221
187
  }
222
188
  throttled.cancel();
223
- dropdown.removeEventListener('mousedown', preventFocusShiftOnMousedown);
224
189
  window.removeEventListener('scroll', handleScroll, { capture: true });
225
190
  window.removeEventListener('resize', handleResize);
226
191
  // Strip the inline overrides so Svelecte's next open starts
@@ -240,24 +205,14 @@ export function attachDropdownPortal(options) {
240
205
  // `display: none` (e.g. on certain transition-cancel race paths
241
206
  // the open/close class flip and the inline style update arrive
242
207
  // out of order), the dropdown would now be `position: static;
243
- // display: block` in `document.body` and contribute its option
244
- // list's height to the body scroll size - which is what surfaces
245
- // as a stray page-level vertical scrollbar after toggling a
246
- // select. Force `display: none` here; Svelecte will restore the
247
- // inline style on next open via its own class-driven render.
208
+ // display: block` and contribute its option list's height to
209
+ // the page scroll size, which is what surfaces as a stray
210
+ // page-level vertical scrollbar after toggling a select. Force
211
+ // `display: none` here; Svelecte will restore the inline style
212
+ // on next open via its own class-driven render.
248
213
  if (!dropdown.classList.contains('is-open')) {
249
214
  dropdown.style.display = 'none';
250
215
  }
251
- if (originalParent != null) {
252
- if (originalNextSibling != null && originalNextSibling.parentNode === originalParent) {
253
- originalParent.insertBefore(dropdown, originalNextSibling);
254
- }
255
- else {
256
- originalParent.appendChild(dropdown);
257
- }
258
- }
259
- originalParent = null;
260
- originalNextSibling = null;
261
216
  isPortalled = false;
262
217
  };
263
218
  // Apply / unapply the portal whenever Svelecte toggles the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lavalogic/scoria",
3
3
  "description": "Svelte components used for the FloWMS Web Frontend",
4
- "version": "0.37.32",
4
+ "version": "0.37.33",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },