@payloadcms/ui 4.0.0-beta.4 → 4.0.0-beta.5
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/dist/elements/Popup/SubmenuScope.d.ts +3 -5
- package/dist/elements/Popup/SubmenuScope.d.ts.map +1 -1
- package/dist/elements/Popup/SubmenuScope.js +10 -54
- package/dist/elements/Popup/SubmenuScope.js.map +1 -1
- package/dist/elements/Popup/index.css +15 -0
- package/dist/elements/Popup/index.d.ts.map +1 -1
- package/dist/elements/Popup/index.js +69 -30
- package/dist/elements/Popup/index.js.map +1 -1
- package/dist/elements/Popup/useSubmenuPointerIntent.d.ts +16 -4
- package/dist/elements/Popup/useSubmenuPointerIntent.d.ts.map +1 -1
- package/dist/elements/Popup/useSubmenuPointerIntent.js +68 -27
- package/dist/elements/Popup/useSubmenuPointerIntent.js.map +1 -1
- package/dist/exports/client/index.js +15 -15
- package/dist/exports/client/index.js.map +4 -4
- package/dist/hooks/usePointerSafeArea.d.ts +29 -0
- package/dist/hooks/usePointerSafeArea.d.ts.map +1 -0
- package/dist/hooks/usePointerSafeArea.js +232 -0
- package/dist/hooks/usePointerSafeArea.js.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +4 -4
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
export type SubmenuNode = {
|
|
2
2
|
closeBranch: () => void;
|
|
3
3
|
id: string;
|
|
4
|
+
isPointerProtected?: () => boolean;
|
|
4
5
|
open: (viaKeyboard: boolean) => void;
|
|
5
6
|
};
|
|
6
7
|
export type SubmenuScope = {
|
|
7
8
|
activeChildId: null | string;
|
|
8
|
-
cancelPending: (id?: string) => void;
|
|
9
9
|
closeActiveBranch: () => void;
|
|
10
10
|
register: (node: SubmenuNode) => () => void;
|
|
11
11
|
release: (id: string) => void;
|
|
12
12
|
requestOpen: (args: {
|
|
13
|
-
delay: boolean;
|
|
14
13
|
id: string;
|
|
15
14
|
viaKeyboard?: boolean;
|
|
15
|
+
viaPointer?: boolean;
|
|
16
16
|
}) => void;
|
|
17
17
|
};
|
|
18
|
-
export declare const createSubmenuScope: (
|
|
19
|
-
hoverDelay?: number;
|
|
20
|
-
}) => SubmenuScope;
|
|
18
|
+
export declare const createSubmenuScope: () => SubmenuScope;
|
|
21
19
|
//# sourceMappingURL=SubmenuScope.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubmenuScope.d.ts","sourceRoot":"","sources":["../../../src/elements/Popup/SubmenuScope.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,EAAE,IAAI,GAAG,MAAM,CAAA;IAC5B,
|
|
1
|
+
{"version":3,"file":"SubmenuScope.d.ts","sourceRoot":"","sources":["../../../src/elements/Popup/SubmenuScope.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAA;IAClC,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,aAAa,EAAE,IAAI,GAAG,MAAM,CAAA;IAC5B,iBAAiB,EAAE,MAAM,IAAI,CAAA;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,IAAI,CAAA;IAC3C,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;CACzF,CAAA;AAED,eAAO,MAAM,kBAAkB,QAAO,YAyCrC,CAAA"}
|
|
@@ -1,50 +1,17 @@
|
|
|
1
|
-
const
|
|
2
|
-
export const createSubmenuScope = ({
|
|
3
|
-
hoverDelay = DEFAULT_HOVER_DELAY
|
|
4
|
-
} = {}) => {
|
|
1
|
+
export const createSubmenuScope = () => {
|
|
5
2
|
const nodes = new Map();
|
|
6
3
|
let activeChildId = null;
|
|
7
|
-
let pendingChildId = null;
|
|
8
|
-
let pendingTimer;
|
|
9
|
-
const cancelPending = id => {
|
|
10
|
-
if (id && pendingChildId !== id) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
if (pendingTimer) {
|
|
14
|
-
clearTimeout(pendingTimer);
|
|
15
|
-
}
|
|
16
|
-
pendingTimer = undefined;
|
|
17
|
-
pendingChildId = null;
|
|
18
|
-
};
|
|
19
|
-
const activate = ({
|
|
20
|
-
id,
|
|
21
|
-
viaKeyboard = false
|
|
22
|
-
}) => {
|
|
23
|
-
cancelPending();
|
|
24
|
-
const node = nodes.get(id);
|
|
25
|
-
if (!node) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (activeChildId !== id) {
|
|
29
|
-
nodes.get(activeChildId ?? '')?.closeBranch();
|
|
30
|
-
activeChildId = id;
|
|
31
|
-
}
|
|
32
|
-
node.open(viaKeyboard);
|
|
33
|
-
};
|
|
34
4
|
return {
|
|
35
5
|
get activeChildId() {
|
|
36
6
|
return activeChildId;
|
|
37
7
|
},
|
|
38
|
-
cancelPending,
|
|
39
8
|
closeActiveBranch: () => {
|
|
40
|
-
cancelPending();
|
|
41
9
|
nodes.get(activeChildId ?? '')?.closeBranch();
|
|
42
10
|
activeChildId = null;
|
|
43
11
|
},
|
|
44
12
|
register: node => {
|
|
45
13
|
nodes.set(node.id, node);
|
|
46
14
|
return () => {
|
|
47
|
-
cancelPending(node.id);
|
|
48
15
|
if (activeChildId === node.id) {
|
|
49
16
|
activeChildId = null;
|
|
50
17
|
}
|
|
@@ -52,37 +19,26 @@ export const createSubmenuScope = ({
|
|
|
52
19
|
};
|
|
53
20
|
},
|
|
54
21
|
release: id => {
|
|
55
|
-
cancelPending(id);
|
|
56
22
|
if (activeChildId === id) {
|
|
57
23
|
activeChildId = null;
|
|
58
24
|
}
|
|
59
25
|
},
|
|
60
26
|
requestOpen: ({
|
|
61
27
|
id,
|
|
62
|
-
|
|
63
|
-
|
|
28
|
+
viaKeyboard = false,
|
|
29
|
+
viaPointer = false
|
|
64
30
|
}) => {
|
|
65
|
-
if (
|
|
66
|
-
activate({
|
|
67
|
-
id,
|
|
68
|
-
viaKeyboard
|
|
69
|
-
});
|
|
31
|
+
if (activeChildId === id) {
|
|
70
32
|
return;
|
|
71
33
|
}
|
|
72
|
-
|
|
73
|
-
|
|
34
|
+
const node = nodes.get(id);
|
|
35
|
+
const activeNode = nodes.get(activeChildId ?? '');
|
|
36
|
+
if (!node || viaPointer && activeNode?.isPointerProtected?.()) {
|
|
74
37
|
return;
|
|
75
38
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
pendingTimer = undefined;
|
|
80
|
-
pendingChildId = null;
|
|
81
|
-
activate({
|
|
82
|
-
id,
|
|
83
|
-
viaKeyboard
|
|
84
|
-
});
|
|
85
|
-
}, hoverDelay);
|
|
39
|
+
activeNode?.closeBranch();
|
|
40
|
+
activeChildId = id;
|
|
41
|
+
node.open(viaKeyboard);
|
|
86
42
|
}
|
|
87
43
|
};
|
|
88
44
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubmenuScope.js","names":["
|
|
1
|
+
{"version":3,"file":"SubmenuScope.js","names":["createSubmenuScope","nodes","Map","activeChildId","closeActiveBranch","get","closeBranch","register","node","set","id","delete","release","requestOpen","viaKeyboard","viaPointer","activeNode","isPointerProtected","open"],"sources":["../../../src/elements/Popup/SubmenuScope.ts"],"sourcesContent":["export type SubmenuNode = {\n closeBranch: () => void\n id: string\n isPointerProtected?: () => boolean\n open: (viaKeyboard: boolean) => void\n}\n\nexport type SubmenuScope = {\n activeChildId: null | string\n closeActiveBranch: () => void\n register: (node: SubmenuNode) => () => void\n release: (id: string) => void\n requestOpen: (args: { id: string; viaKeyboard?: boolean; viaPointer?: boolean }) => void\n}\n\nexport const createSubmenuScope = (): SubmenuScope => {\n const nodes = new Map<string, SubmenuNode>()\n let activeChildId: null | string = null\n\n return {\n get activeChildId() {\n return activeChildId\n },\n closeActiveBranch: () => {\n nodes.get(activeChildId ?? '')?.closeBranch()\n activeChildId = null\n },\n register: (node) => {\n nodes.set(node.id, node)\n return () => {\n if (activeChildId === node.id) {\n activeChildId = null\n }\n nodes.delete(node.id)\n }\n },\n release: (id) => {\n if (activeChildId === id) {\n activeChildId = null\n }\n },\n requestOpen: ({ id, viaKeyboard = false, viaPointer = false }) => {\n if (activeChildId === id) {\n return\n }\n const node = nodes.get(id)\n const activeNode = nodes.get(activeChildId ?? '')\n\n if (!node || (viaPointer && activeNode?.isPointerProtected?.())) {\n return\n }\n activeNode?.closeBranch()\n activeChildId = id\n node.open(viaKeyboard)\n },\n }\n}\n"],"mappings":"AAeA,OAAO,MAAMA,kBAAA,GAAqBA,CAAA;EAChC,MAAMC,KAAA,GAAQ,IAAIC,GAAA;EAClB,IAAIC,aAAA,GAA+B;EAEnC,OAAO;IACL,IAAIA,cAAA,EAAgB;MAClB,OAAOA,aAAA;IACT;IACAC,iBAAA,EAAmBA,CAAA;MACjBH,KAAA,CAAMI,GAAG,CAACF,aAAA,IAAiB,KAAKG,WAAA;MAChCH,aAAA,GAAgB;IAClB;IACAI,QAAA,EAAWC,IAAA;MACTP,KAAA,CAAMQ,GAAG,CAACD,IAAA,CAAKE,EAAE,EAAEF,IAAA;MACnB,OAAO;QACL,IAAIL,aAAA,KAAkBK,IAAA,CAAKE,EAAE,EAAE;UAC7BP,aAAA,GAAgB;QAClB;QACAF,KAAA,CAAMU,MAAM,CAACH,IAAA,CAAKE,EAAE;MACtB;IACF;IACAE,OAAA,EAAUF,EAAA;MACR,IAAIP,aAAA,KAAkBO,EAAA,EAAI;QACxBP,aAAA,GAAgB;MAClB;IACF;IACAU,WAAA,EAAaA,CAAC;MAAEH,EAAE;MAAEI,WAAA,GAAc,KAAK;MAAEC,UAAA,GAAa;IAAK,CAAE;MAC3D,IAAIZ,aAAA,KAAkBO,EAAA,EAAI;QACxB;MACF;MACA,MAAMF,IAAA,GAAOP,KAAA,CAAMI,GAAG,CAACK,EAAA;MACvB,MAAMM,UAAA,GAAaf,KAAA,CAAMI,GAAG,CAACF,aAAA,IAAiB;MAE9C,IAAI,CAACK,IAAA,IAASO,UAAA,IAAcC,UAAA,EAAYC,kBAAA,MAAyB;QAC/D;MACF;MACAD,UAAA,EAAYV,WAAA;MACZH,aAAA,GAAgBO,EAAA;MAChBF,IAAA,CAAKU,IAAI,CAACJ,WAAA;IACZ;EACF;AACF","ignoreList":[]}
|
|
@@ -49,6 +49,21 @@
|
|
|
49
49
|
color: var(--popup-text, var(--color-text-ontooltip));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
.popup__content[data-submenu-safe-area] {
|
|
53
|
+
overflow: visible;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.popup__content[data-submenu-safe-area]::before {
|
|
57
|
+
/* Debug safe area: uncomment to show the protected path.
|
|
58
|
+
background-color: color-mix(in srgb, var(--color-bg-assistive) 35%, transparent);
|
|
59
|
+
*/
|
|
60
|
+
content: '';
|
|
61
|
+
position: fixed;
|
|
62
|
+
inset: 0;
|
|
63
|
+
clip-path: var(--popup-safe-area);
|
|
64
|
+
pointer-events: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
.popup__content.popup--size-small {
|
|
53
68
|
min-width: 80px;
|
|
54
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/Popup/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAY,aAAa,EAAE,MAAM,OAAO,CAAA;AAEpE,OAAO,KAAK,SAAS,MAAM,4BAA4B,CAAA;AAEvD,OAAO,KASN,MAAM,OAAO,CAAA;AAKd,OAAO,aAAa,CAAA;AACpB,OAAO,EAAE,KAAK,sBAAsB,EAAgB,MAAM,yBAAyB,CAAA;AAyCnF,MAAM,MAAM,UAAU,GAAG;IACvB,eAAe,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC/B,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;IACjC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAA;IACzD;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,KAAK,CAAC,SAAS,CAAA;IACjE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,GAAG,OAAO,CAAA;IACxC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IACjC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CACjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/Popup/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAY,aAAa,EAAE,MAAM,OAAO,CAAA;AAEpE,OAAO,KAAK,SAAS,MAAM,4BAA4B,CAAA;AAEvD,OAAO,KASN,MAAM,OAAO,CAAA;AAKd,OAAO,aAAa,CAAA;AACpB,OAAO,EAAE,KAAK,sBAAsB,EAAgB,MAAM,yBAAyB,CAAA;AAyCnF,MAAM,MAAM,UAAU,GAAG;IACvB,eAAe,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC/B,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;IACjC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAA;IACzD;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,KAAK,CAAC,SAAS,CAAA;IACjE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,GAAG,OAAO,CAAA;IACxC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IACjC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;CACjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA0rBtC,CAAA"}
|
|
@@ -94,7 +94,6 @@ export const Popup = props => {
|
|
|
94
94
|
if (coordinateParent && isSubmenu) {
|
|
95
95
|
parentPopup.submenuScope.requestOpen({
|
|
96
96
|
id: contentId,
|
|
97
|
-
delay: false,
|
|
98
97
|
viaKeyboard
|
|
99
98
|
});
|
|
100
99
|
return;
|
|
@@ -128,27 +127,67 @@ export const Popup = props => {
|
|
|
128
127
|
closePopup(options);
|
|
129
128
|
}, [closePopup, parentPopup]);
|
|
130
129
|
const openFromParent = useCallback(viaKeyboard_0 => setActive(true, viaKeyboard_0, false), [setActive]);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
id: contentId,
|
|
137
|
-
closeBranch: () => closePopup({
|
|
138
|
-
restoreFocus: false
|
|
139
|
-
}),
|
|
140
|
-
open: openFromParent
|
|
130
|
+
const closeFromPointer = useCallback(() => {
|
|
131
|
+
const hasFocus = popupRef.current?.contains(document.activeElement);
|
|
132
|
+
const trigger_0 = triggerRef.current?.querySelector('[aria-haspopup="menu"]');
|
|
133
|
+
closePopup({
|
|
134
|
+
restoreFocus: false
|
|
141
135
|
});
|
|
142
|
-
|
|
136
|
+
if (hasFocus) {
|
|
137
|
+
trigger_0?.focus();
|
|
138
|
+
}
|
|
139
|
+
}, [closePopup]);
|
|
143
140
|
const pointerIntent = useSubmenuPointerIntent({
|
|
141
|
+
active,
|
|
144
142
|
contentRef: popupRef,
|
|
145
143
|
enabled: isSubmenu && hoverSubmenu,
|
|
146
|
-
onClose:
|
|
144
|
+
onClose: closeFromPointer,
|
|
147
145
|
onOpen: () => parentPopup?.submenuScope.requestOpen({
|
|
148
146
|
id: contentId,
|
|
149
|
-
|
|
150
|
-
})
|
|
147
|
+
viaPointer: true
|
|
148
|
+
}),
|
|
149
|
+
onSafeAreaExpire: ({
|
|
150
|
+
x,
|
|
151
|
+
y
|
|
152
|
+
}) => {
|
|
153
|
+
const target = document.elementFromPoint(x, y);
|
|
154
|
+
const parentContent = parentPopup?.popupRef.current;
|
|
155
|
+
if (parentContent && target?.closest(POPUP_CONTENT_SELECTOR) === parentContent) {
|
|
156
|
+
const trigger_1 = target.closest('.popup__submenu-hover-watch')?.querySelector('[aria-haspopup="menu"][aria-controls]');
|
|
157
|
+
const siblingId = trigger_1?.getAttribute('aria-controls');
|
|
158
|
+
if (siblingId && trigger_1?.getAttribute('aria-disabled') !== 'true') {
|
|
159
|
+
parentPopup?.submenuScope.requestOpen({
|
|
160
|
+
id: siblingId
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
closeFromPointer();
|
|
166
|
+
},
|
|
167
|
+
triggerRef
|
|
151
168
|
});
|
|
169
|
+
const submenuCallbacks = useRef({
|
|
170
|
+
closeFromPointer,
|
|
171
|
+
openFromParent
|
|
172
|
+
});
|
|
173
|
+
const parentSubmenuScope = parentPopup?.submenuScope;
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
submenuCallbacks.current = {
|
|
176
|
+
closeFromPointer,
|
|
177
|
+
openFromParent
|
|
178
|
+
};
|
|
179
|
+
}, [closeFromPointer, openFromParent]);
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (!isSubmenu || !parentSubmenuScope) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
return parentSubmenuScope.register({
|
|
185
|
+
id: contentId,
|
|
186
|
+
closeBranch: () => submenuCallbacks.current.closeFromPointer(),
|
|
187
|
+
isPointerProtected: pointerIntent.isProtected,
|
|
188
|
+
open: viaKeyboard_1 => submenuCallbacks.current.openFromParent(viaKeyboard_1)
|
|
189
|
+
});
|
|
190
|
+
}, [contentId, isSubmenu, parentSubmenuScope, pointerIntent.isProtected]);
|
|
152
191
|
// /////////////////////////////////////
|
|
153
192
|
// Position Calculation
|
|
154
193
|
//
|
|
@@ -157,12 +196,12 @@ export const Popup = props => {
|
|
|
157
196
|
// styles if the calculated position differs from current position.
|
|
158
197
|
// /////////////////////////////////////
|
|
159
198
|
const updatePosition = useEffectEvent(() => {
|
|
160
|
-
const
|
|
199
|
+
const trigger_2 = triggerRef.current;
|
|
161
200
|
const popup = popupRef.current;
|
|
162
|
-
if (!
|
|
201
|
+
if (!trigger_2 || !popup) {
|
|
163
202
|
return;
|
|
164
203
|
}
|
|
165
|
-
const triggerRect =
|
|
204
|
+
const triggerRect = trigger_2.getBoundingClientRect();
|
|
166
205
|
const popupRect = popup.getBoundingClientRect();
|
|
167
206
|
// Gap between the popup and the trigger/viewport edges (in pixels)
|
|
168
207
|
const offset = 8;
|
|
@@ -275,6 +314,7 @@ export const Popup = props => {
|
|
|
275
314
|
if (popup.style.getPropertyValue('--caret-left') !== newCaretLeft) {
|
|
276
315
|
popup.style.setProperty('--caret-left', newCaretLeft);
|
|
277
316
|
}
|
|
317
|
+
pointerIntent.updateSafeArea();
|
|
278
318
|
});
|
|
279
319
|
// /////////////////////////////////////
|
|
280
320
|
// Click Outside Handler
|
|
@@ -284,11 +324,11 @@ export const Popup = props => {
|
|
|
284
324
|
// - Click in parent popup: child closes
|
|
285
325
|
// /////////////////////////////////////
|
|
286
326
|
const handleClickOutside = useEffectEvent(e => {
|
|
287
|
-
const
|
|
288
|
-
const isOutsidePopup = !popupRef.current?.contains(
|
|
289
|
-
const isOutsideTrigger = !triggerRef.current?.contains(
|
|
327
|
+
const target_0 = e.target;
|
|
328
|
+
const isOutsidePopup = !popupRef.current?.contains(target_0);
|
|
329
|
+
const isOutsideTrigger = !triggerRef.current?.contains(target_0);
|
|
290
330
|
// Check if click is inside a popup portal
|
|
291
|
-
const clickedPopupContent =
|
|
331
|
+
const clickedPopupContent = target_0.closest?.('.popup__content');
|
|
292
332
|
// If the clicked popup contains this popup's trigger, it's a parent popup
|
|
293
333
|
// and we should close. If it doesn't contain our trigger, it's a child popup
|
|
294
334
|
// and we should stay open to avoid closing parent when interacting with child.
|
|
@@ -321,8 +361,8 @@ export const Popup = props => {
|
|
|
321
361
|
return;
|
|
322
362
|
}
|
|
323
363
|
if (e_0.key === 'ArrowRight' && popupRole === 'menu') {
|
|
324
|
-
const
|
|
325
|
-
const nestedTrigger =
|
|
364
|
+
const trigger_3 = document.activeElement?.closest(`.${baseClass}__trigger-wrap`);
|
|
365
|
+
const nestedTrigger = trigger_3?.querySelector('button, [role="menuitem"]');
|
|
326
366
|
if (nestedTrigger) {
|
|
327
367
|
e_0.preventDefault();
|
|
328
368
|
nestedTrigger.dispatchEvent(new KeyboardEvent('keydown', {
|
|
@@ -383,13 +423,13 @@ export const Popup = props => {
|
|
|
383
423
|
// Closes popup when buttons/links inside are clicked (includes Enter/Space activation).
|
|
384
424
|
// /////////////////////////////////////
|
|
385
425
|
const handleActionableClick = useEffectEvent(e_1 => {
|
|
386
|
-
const
|
|
426
|
+
const target_1 = e_1.target;
|
|
387
427
|
// Allow opting out with data-popup-prevent-close attribute on element or ancestor
|
|
388
|
-
if (
|
|
428
|
+
if (target_1.closest('[data-popup-prevent-close]')) {
|
|
389
429
|
return;
|
|
390
430
|
}
|
|
391
431
|
// Check if the clicked element or any ancestor is an actionable element
|
|
392
|
-
const actionable =
|
|
432
|
+
const actionable = target_1.closest('button, a[href], [role="button"], [role="menuitem"]');
|
|
393
433
|
if (actionable && popupRef.current?.contains(actionable)) {
|
|
394
434
|
if (actionable.closest(`.${baseClass}__content`) !== popupRef.current) {
|
|
395
435
|
return;
|
|
@@ -520,7 +560,7 @@ export const Popup = props => {
|
|
|
520
560
|
tabIndex: 0,
|
|
521
561
|
children: Trigger
|
|
522
562
|
}) : hoverSubmenu && isSubmenu ? /*#__PURE__*/_jsx("div", {
|
|
523
|
-
...pointerIntent,
|
|
563
|
+
...pointerIntent.triggerProps,
|
|
524
564
|
className: `${baseClass}__submenu-hover-watch`,
|
|
525
565
|
children: Trigger
|
|
526
566
|
}) : Trigger
|
|
@@ -532,6 +572,7 @@ export const Popup = props => {
|
|
|
532
572
|
submenuScope
|
|
533
573
|
},
|
|
534
574
|
children: /*#__PURE__*/_jsxs("div", {
|
|
575
|
+
...pointerIntent.contentProps,
|
|
535
576
|
"aria-label": popupAriaLabel,
|
|
536
577
|
className: active ? [`${baseClass}__content`, `${baseClass}--size-${size}`, resolvedSide ? `${baseClass}--side-${resolvedSide}` : isOnTop ? `${baseClass}--v-top` : `${baseClass}--v-bottom`, portalClassName].filter(Boolean).join(' ') :
|
|
537
578
|
// tests do not accidentally target inactive popups.
|
|
@@ -539,8 +580,6 @@ export const Popup = props => {
|
|
|
539
580
|
"data-popup-id": id || undefined,
|
|
540
581
|
"data-theme": theme === 'auto' ? undefined : theme,
|
|
541
582
|
id: contentId,
|
|
542
|
-
onMouseEnter: pointerIntent.onMouseEnter,
|
|
543
|
-
onMouseLeave: pointerIntent.onMouseLeave,
|
|
544
583
|
popover: "manual",
|
|
545
584
|
ref: popupRef,
|
|
546
585
|
role: popupRole,
|