@muten/shadcn 0.2.16 → 0.2.18
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/package.json +1 -1
- package/registry/modal-behavior.js +15 -5
package/package.json
CHANGED
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
// MODALS STACK (a receipt opened over a cita): Back, Esc and the focus trap belong to the TOP one only, and the page's
|
|
6
6
|
// scroll is unlocked when the last one closes. Each modal used to listen to every Back: closing the receipt went back
|
|
7
7
|
// in history and that Back also closed the cita under it, leaving the agenda without its buttons (21-10-2026).
|
|
8
|
-
|
|
8
|
+
// ONE CLOSES AS THE NEXT OPENS («Añadir» → the link's editor): the closing one's history.back() lands after the new one's
|
|
9
|
+
// pushState, and Chrome counts that Back from where it was asked, so it stepped over the new entry. The new modal then
|
|
10
|
+
// closed with a Back that was not its own and took the page one screen back (/shop/import, 31-10-2026). So a modal that
|
|
11
|
+
// opens while a closing Back is still on its way pushes its entry once that Back has landed (`after`).
|
|
12
|
+
const stack = (globalThis.__cxModals ||= { list: [], skip: 0, after: [], wired: false });
|
|
13
|
+
stack.after ||= [];
|
|
9
14
|
if (!stack.wired) {
|
|
10
15
|
stack.wired = true;
|
|
11
16
|
addEventListener('popstate', () => {
|
|
12
17
|
// the history.back() a modal makes when it closes itself is its own, not a Back for the one under it
|
|
13
|
-
if (stack.skip > 0) { stack.skip -= 1; return; }
|
|
18
|
+
if (stack.skip > 0) { stack.skip -= 1; if (stack.skip === 0) stack.after.splice(0).forEach((push) => push()); return; }
|
|
14
19
|
stack.list.at(-1)?.onPop();
|
|
15
20
|
});
|
|
16
21
|
}
|
|
@@ -24,7 +29,8 @@ export function mount(el, inputs, on) {
|
|
|
24
29
|
// the auto mode is resolved NOW (and again when the width crosses the phone line while closed), never at the moment
|
|
25
30
|
// of opening: a dialog that only learns it is a dialog as it opens animates its centring from the corner
|
|
26
31
|
const resolve = () => { if (auto && !isOpen) mdl.dataset.mode = phone.matches ? 'drawer' : 'dialog'; };
|
|
27
|
-
|
|
32
|
+
// pushedAt: the address when this modal added its step; a page that moves the address to close it took that step's place
|
|
33
|
+
let isOpen = false, pushed = false, pushedAt = '', lastFocus = null;
|
|
28
34
|
const me = { onPop: () => { if (isOpen) { pushed = false; close(); } } };
|
|
29
35
|
queueMicrotask(() => resolve()); phone.addEventListener('change', resolve);
|
|
30
36
|
// the footer sticks under the scrolling body, not inside it
|
|
@@ -59,7 +65,8 @@ export function mount(el, inputs, on) {
|
|
|
59
65
|
document.documentElement.classList.add('cx-locked');
|
|
60
66
|
// on the phone, focusing a field would throw the keyboard over the sheet: focus the sheet itself
|
|
61
67
|
requestAnimationFrame(() => { ((mdl.dataset.mode === 'dialog' && focusables().find((x) => x.matches('input, textarea'))) || mdl).focus({ preventScroll: true }); });
|
|
62
|
-
history.pushState({ cxModal: 1 }, ''); pushed = true;
|
|
68
|
+
const push = () => { if (!isOpen || pushed) return; history.pushState({ cxModal: 1 }, ''); pushed = true; pushedAt = location.href; };
|
|
69
|
+
if (stack.skip > 0) stack.after.push(push); else push();
|
|
63
70
|
};
|
|
64
71
|
const shut = () => {
|
|
65
72
|
if (!isOpen) return; isOpen = false;
|
|
@@ -67,7 +74,10 @@ export function mount(el, inputs, on) {
|
|
|
67
74
|
stack.list = stack.list.filter((one) => one !== me);
|
|
68
75
|
if (stack.list.length === 0) document.documentElement.classList.remove('cx-locked');
|
|
69
76
|
lastFocus?.focus?.({ preventScroll: true });
|
|
70
|
-
|
|
77
|
+
// A PAGE THAT CLOSES IT BY MOVING THE ADDRESS (a sheet kept in ?sheet=, closed with url.set): its new step already
|
|
78
|
+
// stands where the modal's was, and going back from it lands on the address that opened the sheet, which opened it
|
|
79
|
+
// again (Platform's «Avisar» never closed, 1 Nov 2026). The modal goes back only from its own step.
|
|
80
|
+
if (pushed) { pushed = false; if (location.href === pushedAt) { stack.skip += 1; history.back(); } }
|
|
71
81
|
};
|
|
72
82
|
mdl.tabIndex = -1;
|
|
73
83
|
// A link inside (a menu in a drawer): close first, then go. Closing undoes the history entry the modal pushed, and
|