mnfst 0.5.181 → 0.5.182

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.
@@ -173,6 +173,7 @@ function initializeDropdownPlugin() {
173
173
 
174
174
  // Re-point the shared menu at whichever trigger opens it (multi-trigger)
175
175
  const pointMenuHere = () => {
176
+ menu.__mnfstTrigger = el;
176
177
  const a = el.style.getPropertyValue('--trigger-anchor');
177
178
  if (a) menu.style.setProperty('position-anchor', a);
178
179
  };
@@ -295,14 +296,54 @@ function initializeDropdownPlugin() {
295
296
  document.addEventListener('keydown', (e) => {
296
297
  if (e.key === 'Escape' && menu.matches(':popover-open')) { closeContext(); el.focus(); }
297
298
  }, { signal });
298
-
299
- // Close after clicking a menu item
300
- menu.addEventListener('click', (e) => {
301
- if (e.target.closest('li, a, button')) closeContext();
302
- }, { signal });
303
299
  }
304
300
  }
305
301
 
302
+ // Auto-close on selection: `close` per item, .close for every row
303
+ // that isn't an embedded control, `keep-open` to opt back out.
304
+ // Context menus auto-close by nature, so .close is implied.
305
+ if (modifiers.includes('close') || modifiers.includes('context')) menu.__mnfstAutoClose = true;
306
+
307
+ if (!menu.__mnfstCloseBound) {
308
+ menu.__mnfstCloseBound = true;
309
+
310
+ const ROW = 'li, a, button, label, [role=menuitem], [role=option]';
311
+ const CONTROL = 'input, select, textarea, [contenteditable]:not([contenteditable=false]), [role=switch], .combobox, [x-dropdown], [popovertarget], [keep-open]';
312
+
313
+ // Close the item's menu plus any menus it was nested in
314
+ const closeFrom = (node) => {
315
+ let m = node.closest('menu[popover]');
316
+ while (m) {
317
+ if (m.matches(':popover-open')) m.hidePopover();
318
+ m = m.parentElement?.closest('menu[popover]');
319
+ }
320
+ if (lastInputModality === 'keyboard') (menu.__mnfstTrigger || el).focus?.();
321
+ };
322
+
323
+ menu.addEventListener('click', (e) => {
324
+ // Explicit opt-in wins over every exclusion below
325
+ const opted = e.target.closest('[close]');
326
+ if (opted && menu.contains(opted)) return closeFrom(opted);
327
+ if (!menu.__mnfstAutoClose) return;
328
+
329
+ // Outermost row between the click target and the menu
330
+ let row = null;
331
+ for (let n = e.target; n && n !== menu; n = n.parentElement) {
332
+ if (n.matches?.(ROW)) row = n;
333
+ }
334
+ if (!row) return;
335
+
336
+ // A control that *is* the row is a menu item; one nested
337
+ // inside it is embedded UI, so leave the menu open
338
+ const hit = e.target.closest(CONTROL);
339
+ if (hit && hit !== row && row.contains(hit)) return;
340
+ if (row.querySelector(CONTROL)) return;
341
+ if (row.matches('[role=switch], [x-dropdown], [popovertarget], [keep-open]')) return;
342
+
343
+ closeFrom(row);
344
+ });
345
+ }
346
+
306
347
  // Add keyboard navigation handling
307
348
  menu.addEventListener('keydown', (e) => {
308
349
  // Get all navigable elements (traditional focusable + li elements)
@@ -356,11 +397,8 @@ function initializeDropdownPlugin() {
356
397
  } else if (e.key === 'Enter' || e.key === ' ') {
357
398
  // Allow Enter/Space to activate li elements or follow links
358
399
  if (e.target.tagName === 'LI') {
359
- const link = e.target.querySelector('a');
360
- if (link) {
361
- e.preventDefault();
362
- link.click();
363
- }
400
+ e.preventDefault();
401
+ (e.target.querySelector('a') || e.target).click();
364
402
  }
365
403
  }
366
404
  });
@@ -11,7 +11,7 @@
11
11
  "manifest.components.js": "sha384-eZDib+RFdwd9mOUdi6o53eNS0LBlEEkZPDegxtkAcE+GrGIFxsuB4O0ymfixGNfM",
12
12
  "manifest.data.js": "sha384-3lLvGnqcQr4Ium80MdaQTr8RytjVbs5rnxd0q41BF3ppcoQccMFAcvgFSyZP/0sl",
13
13
  "manifest.datepicker.js": "sha384-52BBZdlLN+EATiUorwTEQOWGJZiSNu0voy9q+WQxxWpUeYsGGkuS0QPPXGx2akxG",
14
- "manifest.dropdowns.js": "sha384-7DtzNNGKAFzsXLO73x0qifvHxd/o+QSLoENOJA03rBRTDKHvHbXsRoMn1WJvX6VG",
14
+ "manifest.dropdowns.js": "sha384-UWKzv3CquY1lwl5SpuGLQ9xfGgMsNEfKUmx8HcMTp6B7IrPf+zaye1rYncTMPLkh",
15
15
  "manifest.export.js": "sha384-NkqOydcrdQ6qFEcpBKc80JCbeSCuybASrTUGajuTMBrHMzt1OIe8b3ndNn9VfqSh",
16
16
  "manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
17
17
  "manifest.localization.js": "sha384-MUetuW8PllIM+9JDMw/tx+qGem8t+ZUN5WZpycsTDKtz+LaX4DJehsfh/YZt9J7L",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst",
3
- "version": "0.5.181",
3
+ "version": "0.5.182",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "templates/starter",