ropav 0.0.10 → 0.0.11
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/README.md +6 -0
- package/dist/accordion.css +115 -111
- package/dist/accordion.js +60 -16
- package/dist/alert.css +110 -108
- package/dist/alert.js +48 -26
- package/dist/aspect-ratio.css +17 -15
- package/dist/aspect-ratio.js +20 -6
- package/dist/avatar.css +98 -96
- package/dist/avatar.js +27 -16
- package/dist/badge.css +95 -93
- package/dist/badge.js +29 -16
- package/dist/base.css +672 -671
- package/dist/button-group.css +39 -37
- package/dist/button-group.js +23 -12
- package/dist/button-link.css +160 -158
- package/dist/button-link.js +43 -24
- package/dist/button.css +160 -158
- package/dist/button.js +37 -19
- package/dist/card.css +109 -107
- package/dist/card.js +42 -17
- package/dist/checkbox.css +139 -137
- package/dist/checkbox.js +79 -28
- package/dist/collapse.css +29 -27
- package/dist/collapse.js +44 -10
- package/dist/color-input.css +137 -107
- package/dist/color-input.js +86 -17
- package/dist/color-picker.css +309 -303
- package/dist/color-picker.js +147 -54
- package/dist/color-picker2.js +9 -1
- package/dist/color-swatch.css +48 -46
- package/dist/color-swatch.js +15 -11
- package/dist/color-swatch2.js +4 -0
- package/dist/components/accordion/accordion-item.d.ts +13 -1
- package/dist/components/accordion/index.d.ts +2 -1
- package/dist/components/accordion/index.js +2 -2
- package/dist/components/accordion/types.d.ts +9 -4
- package/dist/components/alert/alert.d.ts +2 -2
- package/dist/components/alert/index.d.ts +2 -2
- package/dist/components/alert/index.js +2 -2
- package/dist/components/alert/types.d.ts +4 -1
- package/dist/components/aspect-ratio/index.d.ts +2 -1
- package/dist/components/aspect-ratio/index.js +2 -2
- package/dist/components/aspect-ratio/types.d.ts +4 -1
- package/dist/components/avatar/index.d.ts +2 -2
- package/dist/components/avatar/index.js +2 -2
- package/dist/components/avatar/types.d.ts +4 -1
- package/dist/components/badge/index.d.ts +2 -2
- package/dist/components/badge/index.js +2 -2
- package/dist/components/badge/types.d.ts +4 -1
- package/dist/components/button/index.d.ts +2 -1
- package/dist/components/button/index.js +2 -2
- package/dist/components/button/types.d.ts +4 -1
- package/dist/components/button-group/index.d.ts +2 -1
- package/dist/components/button-group/index.js +2 -2
- package/dist/components/button-group/types.d.ts +4 -1
- package/dist/components/button-link/index.d.ts +2 -1
- package/dist/components/button-link/index.js +2 -2
- package/dist/components/button-link/types.d.ts +4 -1
- package/dist/components/card/index.d.ts +2 -1
- package/dist/components/card/index.js +2 -2
- package/dist/components/card/types.d.ts +5 -1
- package/dist/components/checkbox/checkbox.d.ts +4 -1
- package/dist/components/checkbox/index.d.ts +2 -1
- package/dist/components/checkbox/index.js +2 -2
- package/dist/components/checkbox/types.d.ts +6 -1
- package/dist/components/checkbox/useCheckbox.d.ts +2 -0
- package/dist/components/collapse/collapse.d.ts +2 -2
- package/dist/components/collapse/index.d.ts +2 -1
- package/dist/components/collapse/index.js +2 -2
- package/dist/components/collapse/types.d.ts +9 -2
- package/dist/components/color-input/index.d.ts +2 -1
- package/dist/components/color-input/index.js +2 -2
- package/dist/components/color-input/types.d.ts +4 -1
- package/dist/components/color-picker/index.d.ts +2 -2
- package/dist/components/color-picker/index.js +2 -2
- package/dist/components/color-picker/types.d.ts +13 -1
- package/dist/components/color-swatch/index.d.ts +2 -1
- package/dist/components/color-swatch/index.js +2 -1
- package/dist/components/color-swatch/types.d.ts +4 -1
- package/dist/components/dropdown-menu/dropdown-menu-primitives.d.ts +724 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +3 -3
- package/dist/components/dropdown-menu/index.d.ts +53 -1
- package/dist/components/dropdown-menu/index.js +2 -2
- package/dist/components/dropdown-menu/types.d.ts +142 -6
- package/dist/components/dropdown-menu/useDropdownMenu.d.ts +11 -3
- package/dist/components/dropdown-menu/useDropdownMenuDisclosure.d.ts +5 -3
- package/dist/components/dropdown-menu/useDropdownMenuDom.d.ts +2 -1
- package/dist/components/dropdown-menu/useDropdownMenuInteractions.d.ts +4 -4
- package/dist/components/dropdown-menu/useDropdownMenuPortalPosition.d.ts +19 -0
- package/dist/components/dropdown-menu/useDropdownMenuRenderItems.d.ts +14 -2
- package/dist/components/field/index.d.ts +2 -1
- package/dist/components/field/index.js +2 -2
- package/dist/components/field/types.d.ts +4 -1
- package/dist/components/floating/index.d.ts +1 -0
- package/dist/components/floating/index.js +0 -0
- package/dist/components/floating/types.d.ts +31 -0
- package/dist/components/floating/useFloatingPosition.d.ts +38 -0
- package/dist/components/focus-trap/focus-trap.d.ts +31 -0
- package/dist/components/focus-trap/index.d.ts +4 -0
- package/dist/components/focus-trap/index.js +3 -0
- package/dist/components/focus-trap/types.d.ts +41 -0
- package/dist/components/focus-trap/useFocusTrap.d.ts +2 -0
- package/dist/components/icon-button/index.d.ts +2 -1
- package/dist/components/icon-button/index.js +2 -1
- package/dist/components/icon-button/types.d.ts +4 -1
- package/dist/components/input/index.d.ts +2 -1
- package/dist/components/input/index.js +2 -1
- package/dist/components/input/types.d.ts +4 -1
- package/dist/components/modal/index.d.ts +2 -1
- package/dist/components/modal/index.js +2 -2
- package/dist/components/modal/types.d.ts +8 -1
- package/dist/components/number-input/index.d.ts +2 -1
- package/dist/components/number-input/index.js +2 -2
- package/dist/components/number-input/types.d.ts +4 -1
- package/dist/components/overlay/index.d.ts +2 -1
- package/dist/components/overlay/index.js +2 -1
- package/dist/components/overlay/types.d.ts +4 -1
- package/dist/components/popover/index.d.ts +2 -2
- package/dist/components/popover/index.js +2 -2
- package/dist/components/popover/popover.d.ts +2 -2
- package/dist/components/popover/types.d.ts +20 -11
- package/dist/components/popover/usePopover.d.ts +9 -1
- package/dist/components/progress/index.d.ts +2 -2
- package/dist/components/progress/index.js +2 -2
- package/dist/components/progress/types.d.ts +4 -1
- package/dist/components/radio/index.d.ts +2 -1
- package/dist/components/radio/index.js +2 -2
- package/dist/components/radio/radio.d.ts +8 -3
- package/dist/components/radio/types.d.ts +20 -3
- package/dist/components/radio/useRadio.d.ts +9 -4
- package/dist/components/select/index.d.ts +2 -1
- package/dist/components/select/index.js +2 -2
- package/dist/components/select/types.d.ts +4 -1
- package/dist/components/select/useSelect.d.ts +2 -1
- package/dist/components/slider/index.d.ts +2 -2
- package/dist/components/slider/index.js +2 -2
- package/dist/components/slider/range-slider-tooltip.d.ts +3 -0
- package/dist/components/slider/range-slider.d.ts +4 -1
- package/dist/components/slider/slider.d.ts +4 -1
- package/dist/components/slider/sliderCore.d.ts +4 -4
- package/dist/components/slider/types.d.ts +12 -2
- package/dist/components/slider/useRangeSlider.d.ts +1 -1
- package/dist/components/slider/useSlider.d.ts +1 -1
- package/dist/components/switch/index.d.ts +2 -1
- package/dist/components/switch/index.js +2 -2
- package/dist/components/switch/switch.d.ts +4 -1
- package/dist/components/switch/types.d.ts +6 -1
- package/dist/components/switch/useSwitch.d.ts +2 -0
- package/dist/components/tabs/index.d.ts +2 -1
- package/dist/components/tabs/index.js +2 -2
- package/dist/components/tabs/types.d.ts +13 -4
- package/dist/components/teleport-provider/index.d.ts +2 -0
- package/dist/components/teleport-provider/index.js +2 -0
- package/dist/components/teleport-provider/teleport-provider.d.ts +21 -0
- package/dist/components/teleport-provider/types.d.ts +4 -0
- package/dist/components/teleport-provider/useTeleportTarget.d.ts +5 -0
- package/dist/components/textarea/index.d.ts +2 -1
- package/dist/components/textarea/index.js +2 -2
- package/dist/components/textarea/textarea.d.ts +4 -1
- package/dist/components/textarea/types.d.ts +6 -1
- package/dist/components/textarea/useTextarea.d.ts +1 -0
- package/dist/components/toast/index.d.ts +2 -2
- package/dist/components/toast/index.js +2 -2
- package/dist/components/toast/toast.d.ts +2 -2
- package/dist/components/toast/types.d.ts +10 -6
- package/dist/components/tooltip/index.d.ts +2 -1
- package/dist/components/tooltip/index.js +2 -1
- package/dist/components/tooltip/tooltip.d.ts +2 -2
- package/dist/components/tooltip/types.d.ts +13 -12
- package/dist/components/tooltip/useTooltip.d.ts +13 -3
- package/dist/dropdown-menu.css +191 -107
- package/dist/dropdown-menu.js +1582 -81
- package/dist/field.css +41 -39
- package/dist/field.js +40 -16
- package/dist/focus-trap.js +80 -0
- package/dist/icon-button.css +193 -189
- package/dist/icon-button.js +23 -18
- package/dist/icon-button2.js +8 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +36 -32
- package/dist/input.css +122 -120
- package/dist/input.js +47 -34
- package/dist/input2.js +9 -0
- package/dist/legacy-unlayered.css +5461 -0
- package/dist/modal.css +129 -127
- package/dist/modal.js +160 -200
- package/dist/number-input.css +87 -85
- package/dist/number-input.js +61 -17
- package/dist/overlay.css +26 -24
- package/dist/overlay.js +17 -9
- package/dist/overlay2.js +4 -0
- package/dist/popover.css +140 -107
- package/dist/popover.js +288 -193
- package/dist/popover2.js +6 -1
- package/dist/progress.css +101 -99
- package/dist/progress.js +50 -28
- package/dist/radio.css +114 -105
- package/dist/radio.js +154 -56
- package/dist/select.css +244 -242
- package/dist/select.js +92 -47
- package/dist/slider.css +1109 -1031
- package/dist/slider.js +330 -163
- package/dist/styles-api.d.ts +22 -0
- package/dist/styles-api.js +49 -0
- package/dist/switch.css +120 -108
- package/dist/switch.js +89 -33
- package/dist/tabs.css +286 -278
- package/dist/tabs.js +60 -21
- package/dist/teleport-provider.js +15 -0
- package/dist/textarea.css +132 -130
- package/dist/textarea.js +69 -27
- package/dist/toast.css +229 -225
- package/dist/toast.js +102 -42
- package/dist/tooltip.css +137 -107
- package/dist/tooltip.js +180 -228
- package/dist/tooltip2.js +8 -0
- package/dist/useClickOutside.js +1 -1
- package/dist/useFloatingPosition.js +1284 -0
- package/dist/useFocusTrap.js +130 -0
- package/dist/useTeleportTarget.js +29 -0
- package/docs/public-styles-api.md +133 -0
- package/docs/public-tokens.md +545 -0
- package/package.json +29 -5
- package/src/styles/_tokens.scss +33 -28
- package/src/styles/_utilities.scss +11 -9
- package/src/styles/styles-manifest.json +4125 -0
- package/dist/rafScheduler.js +0 -34
package/dist/dropdown-menu.js
CHANGED
|
@@ -1,7 +1,1251 @@
|
|
|
1
1
|
import './dropdown-menu.css';
|
|
2
2
|
import { t as bem } from "./bem.js";
|
|
3
|
+
import { n as useStylesApi, t as presence } from "./styles-api.js";
|
|
4
|
+
import { t as useRequiredInject } from "./useRequiredInject.js";
|
|
5
|
+
import { n as useFloatingPosition, r as useFloatingTarget, t as isElementReference } from "./useFloatingPosition.js";
|
|
6
|
+
import { n as useTeleportTarget, t as provideTeleportTarget } from "./useTeleportTarget.js";
|
|
3
7
|
import { t as useClickOutside } from "./useClickOutside.js";
|
|
4
|
-
import { VaporTransition, computed, createComponent, createIf, createSlot, createTemplateRefSetter, defineComponent, defineVaporComponent, extend, h, markRaw, nextTick, onUnmounted, ref, renderEffect,
|
|
8
|
+
import { Teleport, VaporTeleport, VaporTransition, computed, createComponent, createIf, createSlot, createTemplateRefSetter, defineComponent, defineVaporComponent, extend, h, markRaw, mergeProps, nextTick, onBeforeUnmount, onMounted, onUnmounted, provide, ref, renderEffect, setAttr, setDynamicProps, setInsertionState, setStaticTemplateRef, setStyle, setText, shallowRef, template, toDisplayString, txt, unref, useId, watch } from "vue";
|
|
9
|
+
//#region src/components/dropdown-menu/dropdown-menu-primitives.ts
|
|
10
|
+
var rootKey = Symbol("dropdown-menu-root");
|
|
11
|
+
var menuKey = Symbol("dropdown-menu-content");
|
|
12
|
+
var subKey = Symbol("dropdown-menu-sub");
|
|
13
|
+
var radioGroupKey = Symbol("dropdown-menu-radio-group");
|
|
14
|
+
var checkedKey = Symbol("dropdown-menu-checked");
|
|
15
|
+
var openLayers = [];
|
|
16
|
+
function optionalAttr(value) {
|
|
17
|
+
return value || void 0;
|
|
18
|
+
}
|
|
19
|
+
function getFocusTarget(options) {
|
|
20
|
+
if (typeof options === "string") return options;
|
|
21
|
+
return options?.focus ?? "first";
|
|
22
|
+
}
|
|
23
|
+
function toHTMLElement(value) {
|
|
24
|
+
if (typeof HTMLElement !== "undefined" && value instanceof HTMLElement) return value;
|
|
25
|
+
const element = value?.$el;
|
|
26
|
+
return typeof HTMLElement !== "undefined" && element instanceof HTMLElement ? element : null;
|
|
27
|
+
}
|
|
28
|
+
function createPointRect(point) {
|
|
29
|
+
return {
|
|
30
|
+
x: point.x,
|
|
31
|
+
y: point.y,
|
|
32
|
+
left: point.x,
|
|
33
|
+
right: point.x,
|
|
34
|
+
top: point.y,
|
|
35
|
+
bottom: point.y,
|
|
36
|
+
width: 0,
|
|
37
|
+
height: 0,
|
|
38
|
+
toJSON: () => ({})
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function createVirtualAnchor(point) {
|
|
42
|
+
return { getBoundingClientRect: () => createPointRect(point) };
|
|
43
|
+
}
|
|
44
|
+
function createCustomEvent(type, detail, originalEvent) {
|
|
45
|
+
const target = originalEvent.target;
|
|
46
|
+
return new (((target instanceof Node ? target.ownerDocument?.defaultView : null)?.CustomEvent) ?? CustomEvent)(type, {
|
|
47
|
+
bubbles: false,
|
|
48
|
+
cancelable: true,
|
|
49
|
+
detail
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function createSelectEvent(originalEvent, value) {
|
|
53
|
+
return createCustomEvent("dropdown-menu-select", {
|
|
54
|
+
originalEvent,
|
|
55
|
+
value
|
|
56
|
+
}, originalEvent);
|
|
57
|
+
}
|
|
58
|
+
function createOutsideEvent(originalEvent) {
|
|
59
|
+
return createCustomEvent("dropdown-menu-interact-outside", { originalEvent }, originalEvent);
|
|
60
|
+
}
|
|
61
|
+
function sortItems(items) {
|
|
62
|
+
return [...items].sort((left, right) => {
|
|
63
|
+
const leftElement = left.element();
|
|
64
|
+
const rightElement = right.element();
|
|
65
|
+
if (!leftElement || !rightElement || leftElement === rightElement) return 0;
|
|
66
|
+
const position = leftElement.compareDocumentPosition(rightElement);
|
|
67
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
|
|
68
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
|
69
|
+
return 0;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function getPlacementSide(placement) {
|
|
73
|
+
return placement.split("-")[0];
|
|
74
|
+
}
|
|
75
|
+
function getOpenDirection(sub) {
|
|
76
|
+
return getPlacementSide(sub.actualPlacement.value) === "left" ? "ArrowLeft" : "ArrowRight";
|
|
77
|
+
}
|
|
78
|
+
function getCloseDirection(menu) {
|
|
79
|
+
return getPlacementSide(menu.actualPlacement.value) === "left" ? "ArrowRight" : "ArrowLeft";
|
|
80
|
+
}
|
|
81
|
+
function addOpenLayer(root) {
|
|
82
|
+
const index = openLayers.indexOf(root);
|
|
83
|
+
if (index >= 0) openLayers.splice(index, 1);
|
|
84
|
+
openLayers.push(root);
|
|
85
|
+
}
|
|
86
|
+
function removeOpenLayer(root) {
|
|
87
|
+
const index = openLayers.indexOf(root);
|
|
88
|
+
if (index >= 0) openLayers.splice(index, 1);
|
|
89
|
+
}
|
|
90
|
+
function isTopLayer(root) {
|
|
91
|
+
return openLayers[openLayers.length - 1] === root;
|
|
92
|
+
}
|
|
93
|
+
function blockDocumentClick(event) {
|
|
94
|
+
if (event.cancelable) event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
document.removeEventListener("click", blockDocumentClick, true);
|
|
97
|
+
}
|
|
98
|
+
function blockNextDocumentClick() {
|
|
99
|
+
if (typeof document === "undefined") return;
|
|
100
|
+
document.addEventListener("click", blockDocumentClick, true);
|
|
101
|
+
window.setTimeout(() => document.removeEventListener("click", blockDocumentClick, true), 1e3);
|
|
102
|
+
}
|
|
103
|
+
function createMenuContext(options) {
|
|
104
|
+
const items = shallowRef([]);
|
|
105
|
+
const activeId = ref(null);
|
|
106
|
+
const submenus = /* @__PURE__ */ new Set();
|
|
107
|
+
function getEnabledItems() {
|
|
108
|
+
return sortItems(items.value).filter((item) => !item.disabled());
|
|
109
|
+
}
|
|
110
|
+
function registerItem(item) {
|
|
111
|
+
items.value = [...items.value.filter((current) => current.id !== item.id), item];
|
|
112
|
+
if ((options.parentSub?.isOpen.value ?? options.root.isOpen.value) && activeId.value == null && !item.disabled()) {
|
|
113
|
+
activeId.value = item.id;
|
|
114
|
+
nextTick(() => {
|
|
115
|
+
options.element.value?.focus();
|
|
116
|
+
item.element()?.scrollIntoView?.({ block: "nearest" });
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function unregisterItem(id) {
|
|
121
|
+
items.value = items.value.filter((item) => item.id !== id);
|
|
122
|
+
if (activeId.value === id) activeId.value = null;
|
|
123
|
+
}
|
|
124
|
+
function registerSub(sub) {
|
|
125
|
+
submenus.add(sub);
|
|
126
|
+
}
|
|
127
|
+
function unregisterSub(sub) {
|
|
128
|
+
submenus.delete(sub);
|
|
129
|
+
}
|
|
130
|
+
function closeSubmenus(except) {
|
|
131
|
+
for (const submenu of submenus) if (submenu !== except) submenu.close(false);
|
|
132
|
+
}
|
|
133
|
+
function setActive(id) {
|
|
134
|
+
const item = items.value.find((current) => current.id === id);
|
|
135
|
+
if (!item || item.disabled()) return;
|
|
136
|
+
activeId.value = id;
|
|
137
|
+
nextTick(() => item.element()?.scrollIntoView?.({ block: "nearest" }));
|
|
138
|
+
}
|
|
139
|
+
function focus(target = "first") {
|
|
140
|
+
const enabledItems = getEnabledItems();
|
|
141
|
+
const item = target === "last" ? enabledItems[enabledItems.length - 1] : enabledItems[0];
|
|
142
|
+
if (!item) {
|
|
143
|
+
activeId.value = null;
|
|
144
|
+
options.element.value?.focus();
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
activeId.value = item.id;
|
|
148
|
+
options.element.value?.focus();
|
|
149
|
+
item.element()?.scrollIntoView?.({ block: "nearest" });
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
function focusElement() {
|
|
153
|
+
options.element.value?.focus();
|
|
154
|
+
}
|
|
155
|
+
function move(direction) {
|
|
156
|
+
const enabledItems = getEnabledItems();
|
|
157
|
+
if (enabledItems.length === 0) return;
|
|
158
|
+
const currentIndex = enabledItems.findIndex((item) => item.id === activeId.value);
|
|
159
|
+
const item = enabledItems[((currentIndex < 0 ? direction === 1 ? -1 : 0 : currentIndex) + direction + enabledItems.length) % enabledItems.length];
|
|
160
|
+
if (item) setActive(item.id);
|
|
161
|
+
}
|
|
162
|
+
function onHorizontalKeydown(event, active) {
|
|
163
|
+
if (options.parentSub && event.key === getCloseDirection(context)) {
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
event.stopPropagation();
|
|
166
|
+
options.parentSub.close(true);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (!active?.submenu || event.key !== getOpenDirection(active.submenu)) return;
|
|
170
|
+
event.preventDefault();
|
|
171
|
+
event.stopPropagation();
|
|
172
|
+
active.submenu.open("first");
|
|
173
|
+
}
|
|
174
|
+
function onKeydown(event) {
|
|
175
|
+
const active = items.value.find((item) => item.id === activeId.value);
|
|
176
|
+
switch (event.key) {
|
|
177
|
+
case "ArrowDown":
|
|
178
|
+
event.preventDefault();
|
|
179
|
+
event.stopPropagation();
|
|
180
|
+
move(1);
|
|
181
|
+
break;
|
|
182
|
+
case "ArrowUp":
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
event.stopPropagation();
|
|
185
|
+
move(-1);
|
|
186
|
+
break;
|
|
187
|
+
case "Home":
|
|
188
|
+
event.preventDefault();
|
|
189
|
+
event.stopPropagation();
|
|
190
|
+
focus("first");
|
|
191
|
+
break;
|
|
192
|
+
case "End":
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
event.stopPropagation();
|
|
195
|
+
focus("last");
|
|
196
|
+
break;
|
|
197
|
+
case "ArrowRight":
|
|
198
|
+
case "ArrowLeft":
|
|
199
|
+
onHorizontalKeydown(event, active);
|
|
200
|
+
break;
|
|
201
|
+
case "Enter":
|
|
202
|
+
case " ":
|
|
203
|
+
event.preventDefault();
|
|
204
|
+
event.stopPropagation();
|
|
205
|
+
active?.activate(event);
|
|
206
|
+
break;
|
|
207
|
+
case "Escape":
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
event.stopPropagation();
|
|
210
|
+
options.onEscape(event);
|
|
211
|
+
break;
|
|
212
|
+
case "Tab":
|
|
213
|
+
options.root.close({ returnFocus: false });
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const context = {
|
|
218
|
+
root: options.root,
|
|
219
|
+
element: options.element,
|
|
220
|
+
activeId,
|
|
221
|
+
actualPlacement: options.actualPlacement,
|
|
222
|
+
parentSub: options.parentSub,
|
|
223
|
+
registerItem,
|
|
224
|
+
unregisterItem,
|
|
225
|
+
registerSub,
|
|
226
|
+
unregisterSub,
|
|
227
|
+
closeSubmenus,
|
|
228
|
+
setActive,
|
|
229
|
+
isActive: (id) => activeId.value === id,
|
|
230
|
+
focus,
|
|
231
|
+
focusElement,
|
|
232
|
+
onKeydown
|
|
233
|
+
};
|
|
234
|
+
return context;
|
|
235
|
+
}
|
|
236
|
+
function primitiveAsProp(defaultValue) {
|
|
237
|
+
return {
|
|
238
|
+
type: [
|
|
239
|
+
String,
|
|
240
|
+
Object,
|
|
241
|
+
Function
|
|
242
|
+
],
|
|
243
|
+
default: defaultValue
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
var DropdownMenuRoot = defineComponent({
|
|
247
|
+
name: "RpDropdownMenuRoot",
|
|
248
|
+
props: {
|
|
249
|
+
id: String,
|
|
250
|
+
open: {
|
|
251
|
+
type: Boolean,
|
|
252
|
+
default: void 0
|
|
253
|
+
},
|
|
254
|
+
defaultOpen: {
|
|
255
|
+
type: Boolean,
|
|
256
|
+
default: false
|
|
257
|
+
},
|
|
258
|
+
disabled: {
|
|
259
|
+
type: Boolean,
|
|
260
|
+
default: false
|
|
261
|
+
},
|
|
262
|
+
modal: {
|
|
263
|
+
type: Boolean,
|
|
264
|
+
default: true
|
|
265
|
+
},
|
|
266
|
+
target: {
|
|
267
|
+
type: [String, Object],
|
|
268
|
+
default: null
|
|
269
|
+
},
|
|
270
|
+
virtualAnchor: {
|
|
271
|
+
type: Object,
|
|
272
|
+
default: null
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
emits: ["update:open"],
|
|
276
|
+
setup(props, { emit, expose, slots }) {
|
|
277
|
+
const generatedId = useId();
|
|
278
|
+
const id = computed(() => props.id ?? `${generatedId}-dropdown-menu`);
|
|
279
|
+
const uncontrolledOpen = ref(props.defaultOpen);
|
|
280
|
+
const isOpen = computed(() => props.open ?? uncontrolledOpen.value);
|
|
281
|
+
const disabled = computed(() => props.disabled);
|
|
282
|
+
const modal = computed(() => props.modal);
|
|
283
|
+
const trigger = ref(null);
|
|
284
|
+
const triggerId = ref();
|
|
285
|
+
const contentId = ref();
|
|
286
|
+
const activeReference = shallowRef(null);
|
|
287
|
+
const { reference: configuredReference } = useFloatingTarget(() => props.target ?? props.virtualAnchor, trigger);
|
|
288
|
+
const reference = computed(() => activeReference.value ?? configuredReference.value);
|
|
289
|
+
const pendingFocus = ref("first");
|
|
290
|
+
const inside = /* @__PURE__ */ new Set();
|
|
291
|
+
let returnFocusElement = null;
|
|
292
|
+
function setOpen(value) {
|
|
293
|
+
if (value && disabled.value) return;
|
|
294
|
+
const previous = isOpen.value;
|
|
295
|
+
if (props.open === void 0) uncontrolledOpen.value = value;
|
|
296
|
+
if (previous !== value) emit("update:open", value);
|
|
297
|
+
}
|
|
298
|
+
function rememberFocus() {
|
|
299
|
+
if (typeof document === "undefined" || returnFocusElement) return;
|
|
300
|
+
const activeElement = document.activeElement;
|
|
301
|
+
if (activeElement instanceof HTMLElement) returnFocusElement = activeElement;
|
|
302
|
+
}
|
|
303
|
+
function open(options) {
|
|
304
|
+
if (disabled.value) return;
|
|
305
|
+
rememberFocus();
|
|
306
|
+
pendingFocus.value = getFocusTarget(options);
|
|
307
|
+
setOpen(true);
|
|
308
|
+
}
|
|
309
|
+
function focusReturnTarget() {
|
|
310
|
+
const target = returnFocusElement ?? trigger.value;
|
|
311
|
+
nextTick(() => target?.focus());
|
|
312
|
+
}
|
|
313
|
+
function close(options = {}) {
|
|
314
|
+
setOpen(false);
|
|
315
|
+
pendingFocus.value = false;
|
|
316
|
+
if (options.focusTrigger || options.returnFocus) focusReturnTarget();
|
|
317
|
+
}
|
|
318
|
+
function toggle() {
|
|
319
|
+
if (isOpen.value) close({ returnFocus: true });
|
|
320
|
+
else open();
|
|
321
|
+
}
|
|
322
|
+
function openAt(point, options) {
|
|
323
|
+
activeReference.value = createVirtualAnchor(point);
|
|
324
|
+
open(options);
|
|
325
|
+
}
|
|
326
|
+
function setTrigger(element, nextId) {
|
|
327
|
+
if (trigger.value && trigger.value !== element) inside.delete(trigger.value);
|
|
328
|
+
trigger.value = element;
|
|
329
|
+
triggerId.value = nextId;
|
|
330
|
+
if (element) inside.add(element);
|
|
331
|
+
}
|
|
332
|
+
const context = {
|
|
333
|
+
id,
|
|
334
|
+
isOpen,
|
|
335
|
+
disabled,
|
|
336
|
+
modal,
|
|
337
|
+
trigger,
|
|
338
|
+
triggerId,
|
|
339
|
+
contentId,
|
|
340
|
+
reference,
|
|
341
|
+
pendingFocus,
|
|
342
|
+
open,
|
|
343
|
+
close,
|
|
344
|
+
toggle,
|
|
345
|
+
openAt,
|
|
346
|
+
setTrigger,
|
|
347
|
+
setReference(nextReference) {
|
|
348
|
+
activeReference.value = nextReference;
|
|
349
|
+
},
|
|
350
|
+
setReturnFocus(element) {
|
|
351
|
+
returnFocusElement = element;
|
|
352
|
+
},
|
|
353
|
+
registerInside(element) {
|
|
354
|
+
inside.add(element);
|
|
355
|
+
},
|
|
356
|
+
unregisterInside(element) {
|
|
357
|
+
inside.delete(element);
|
|
358
|
+
},
|
|
359
|
+
isInside(target) {
|
|
360
|
+
return target instanceof Node && [...inside].some((element) => element.contains(target));
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
const slotProps = computed(() => ({
|
|
364
|
+
isOpen: isOpen.value,
|
|
365
|
+
open,
|
|
366
|
+
close,
|
|
367
|
+
toggle,
|
|
368
|
+
openAt
|
|
369
|
+
}));
|
|
370
|
+
watch(disabled, (value) => {
|
|
371
|
+
if (value) close();
|
|
372
|
+
});
|
|
373
|
+
watch(isOpen, (value) => {
|
|
374
|
+
if (value) addOpenLayer(context);
|
|
375
|
+
else removeOpenLayer(context);
|
|
376
|
+
}, { immediate: true });
|
|
377
|
+
onBeforeUnmount(() => removeOpenLayer(context));
|
|
378
|
+
provide(rootKey, context);
|
|
379
|
+
expose({
|
|
380
|
+
open,
|
|
381
|
+
close,
|
|
382
|
+
toggle,
|
|
383
|
+
openAt
|
|
384
|
+
});
|
|
385
|
+
return () => slots.default?.(slotProps.value);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
var DropdownMenuTrigger = defineComponent({
|
|
389
|
+
name: "RpDropdownMenuTrigger",
|
|
390
|
+
inheritAttrs: false,
|
|
391
|
+
props: {
|
|
392
|
+
id: String,
|
|
393
|
+
as: primitiveAsProp("button"),
|
|
394
|
+
disabled: {
|
|
395
|
+
type: Boolean,
|
|
396
|
+
default: false
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
setup(props, { attrs, slots }) {
|
|
400
|
+
const root = useRequiredInject(rootKey, "RpDropdownMenuTrigger");
|
|
401
|
+
const generatedId = useId();
|
|
402
|
+
const id = computed(() => props.id ?? `${generatedId}-trigger`);
|
|
403
|
+
const element = ref(null);
|
|
404
|
+
const isDisabled = computed(() => root.disabled.value || props.disabled);
|
|
405
|
+
function setElement(value) {
|
|
406
|
+
element.value = toHTMLElement(value);
|
|
407
|
+
root.setTrigger(element.value, id.value);
|
|
408
|
+
}
|
|
409
|
+
function openWithReference(focus = "first") {
|
|
410
|
+
root.setReference(element.value);
|
|
411
|
+
root.setReturnFocus(element.value);
|
|
412
|
+
root.open({ focus });
|
|
413
|
+
}
|
|
414
|
+
function onClick(event) {
|
|
415
|
+
if (event.defaultPrevented || isDisabled.value) return;
|
|
416
|
+
root.setReference(element.value);
|
|
417
|
+
root.setReturnFocus(element.value);
|
|
418
|
+
root.toggle();
|
|
419
|
+
}
|
|
420
|
+
function onKeydown(event) {
|
|
421
|
+
if (isDisabled.value) return;
|
|
422
|
+
if (event.key === "ArrowUp") {
|
|
423
|
+
event.preventDefault();
|
|
424
|
+
openWithReference("last");
|
|
425
|
+
} else if ([
|
|
426
|
+
"Enter",
|
|
427
|
+
" ",
|
|
428
|
+
"ArrowDown"
|
|
429
|
+
].includes(event.key)) {
|
|
430
|
+
event.preventDefault();
|
|
431
|
+
openWithReference("first");
|
|
432
|
+
} else if (event.key === "Escape") root.close({ focusTrigger: true });
|
|
433
|
+
}
|
|
434
|
+
onBeforeUnmount(() => root.setTrigger(null));
|
|
435
|
+
return () => {
|
|
436
|
+
const as = props.as ?? "button";
|
|
437
|
+
return h(as, mergeProps(attrs, {
|
|
438
|
+
id: id.value,
|
|
439
|
+
ref: setElement,
|
|
440
|
+
type: as === "button" ? "button" : void 0,
|
|
441
|
+
disabled: as === "button" ? optionalAttr(isDisabled.value) : void 0,
|
|
442
|
+
"aria-controls": root.contentId.value,
|
|
443
|
+
"aria-expanded": root.isOpen.value,
|
|
444
|
+
"aria-haspopup": "menu",
|
|
445
|
+
"aria-disabled": as === "button" ? void 0 : optionalAttr(isDisabled.value),
|
|
446
|
+
"data-state": root.isOpen.value ? "open" : "closed",
|
|
447
|
+
"data-disabled": optionalAttr(isDisabled.value),
|
|
448
|
+
onClick,
|
|
449
|
+
onKeydown
|
|
450
|
+
}), slots.default?.({ isOpen: root.isOpen.value }));
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
var DropdownMenuContextTrigger = defineComponent({
|
|
455
|
+
name: "RpDropdownMenuContextTrigger",
|
|
456
|
+
inheritAttrs: false,
|
|
457
|
+
props: {
|
|
458
|
+
id: String,
|
|
459
|
+
as: primitiveAsProp("span"),
|
|
460
|
+
disabled: {
|
|
461
|
+
type: Boolean,
|
|
462
|
+
default: false
|
|
463
|
+
},
|
|
464
|
+
longPressDelay: {
|
|
465
|
+
type: Number,
|
|
466
|
+
default: 700
|
|
467
|
+
},
|
|
468
|
+
longPressTolerance: {
|
|
469
|
+
type: Number,
|
|
470
|
+
default: 10
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
setup(props, { attrs, slots }) {
|
|
474
|
+
const root = useRequiredInject(rootKey, "RpDropdownMenuContextTrigger");
|
|
475
|
+
const generatedId = useId();
|
|
476
|
+
const id = computed(() => props.id ?? `${generatedId}-context-trigger`);
|
|
477
|
+
const element = ref(null);
|
|
478
|
+
const isDisabled = computed(() => root.disabled.value || props.disabled);
|
|
479
|
+
let timer;
|
|
480
|
+
let pointerId;
|
|
481
|
+
let startPoint;
|
|
482
|
+
let longPressOpened = false;
|
|
483
|
+
let suppressUntil = 0;
|
|
484
|
+
function setElement(value) {
|
|
485
|
+
const previous = element.value;
|
|
486
|
+
if (previous) root.unregisterInside(previous);
|
|
487
|
+
element.value = toHTMLElement(value);
|
|
488
|
+
if (element.value) root.registerInside(element.value);
|
|
489
|
+
if (!root.triggerId.value) root.triggerId.value = id.value;
|
|
490
|
+
}
|
|
491
|
+
function clearLongPress() {
|
|
492
|
+
if (timer) clearTimeout(timer);
|
|
493
|
+
timer = void 0;
|
|
494
|
+
pointerId = void 0;
|
|
495
|
+
startPoint = void 0;
|
|
496
|
+
element.value?.ownerDocument.defaultView?.removeEventListener("scroll", clearLongPress, true);
|
|
497
|
+
}
|
|
498
|
+
function openAt(point) {
|
|
499
|
+
root.setReturnFocus(element.value);
|
|
500
|
+
root.openAt(point);
|
|
501
|
+
}
|
|
502
|
+
function onContextmenu(event) {
|
|
503
|
+
if (isDisabled.value) return;
|
|
504
|
+
event.preventDefault();
|
|
505
|
+
if (Date.now() < suppressUntil) return;
|
|
506
|
+
openAt({
|
|
507
|
+
x: event.clientX,
|
|
508
|
+
y: event.clientY
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
function onKeydown(event) {
|
|
512
|
+
if (isDisabled.value) return;
|
|
513
|
+
if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
|
|
514
|
+
event.preventDefault();
|
|
515
|
+
const rect = element.value?.getBoundingClientRect();
|
|
516
|
+
openAt({
|
|
517
|
+
x: rect?.left ?? 0,
|
|
518
|
+
y: rect?.bottom ?? 0
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
function onPointerdown(event) {
|
|
522
|
+
if (isDisabled.value || event.pointerType !== "touch" && event.pointerType !== "pen") return;
|
|
523
|
+
clearLongPress();
|
|
524
|
+
pointerId = event.pointerId;
|
|
525
|
+
startPoint = {
|
|
526
|
+
x: event.clientX,
|
|
527
|
+
y: event.clientY
|
|
528
|
+
};
|
|
529
|
+
longPressOpened = false;
|
|
530
|
+
(element.value?.ownerDocument.defaultView)?.addEventListener("scroll", clearLongPress, true);
|
|
531
|
+
timer = setTimeout(() => {
|
|
532
|
+
if (!startPoint) return;
|
|
533
|
+
longPressOpened = true;
|
|
534
|
+
suppressUntil = Date.now() + 1e3;
|
|
535
|
+
openAt(startPoint);
|
|
536
|
+
timer = void 0;
|
|
537
|
+
}, props.longPressDelay);
|
|
538
|
+
}
|
|
539
|
+
function onPointermove(event) {
|
|
540
|
+
if (event.pointerId !== pointerId || !startPoint) return;
|
|
541
|
+
if (Math.hypot(event.clientX - startPoint.x, event.clientY - startPoint.y) > props.longPressTolerance) clearLongPress();
|
|
542
|
+
}
|
|
543
|
+
function finishPointer(event) {
|
|
544
|
+
if (event.pointerId !== pointerId) return;
|
|
545
|
+
if (longPressOpened) event.preventDefault();
|
|
546
|
+
clearLongPress();
|
|
547
|
+
}
|
|
548
|
+
function onClick(event) {
|
|
549
|
+
if (Date.now() >= suppressUntil) return;
|
|
550
|
+
event.preventDefault();
|
|
551
|
+
event.stopPropagation();
|
|
552
|
+
}
|
|
553
|
+
onBeforeUnmount(() => {
|
|
554
|
+
clearLongPress();
|
|
555
|
+
if (element.value) root.unregisterInside(element.value);
|
|
556
|
+
if (root.triggerId.value === id.value) root.triggerId.value = void 0;
|
|
557
|
+
});
|
|
558
|
+
return () => h(props.as ?? "span", mergeProps(attrs, {
|
|
559
|
+
id: id.value,
|
|
560
|
+
ref: setElement,
|
|
561
|
+
"aria-controls": root.contentId.value,
|
|
562
|
+
"aria-expanded": root.isOpen.value,
|
|
563
|
+
"aria-haspopup": "menu",
|
|
564
|
+
"aria-disabled": optionalAttr(isDisabled.value),
|
|
565
|
+
"data-state": root.isOpen.value ? "open" : "closed",
|
|
566
|
+
"data-disabled": optionalAttr(isDisabled.value),
|
|
567
|
+
onClick,
|
|
568
|
+
onContextmenu,
|
|
569
|
+
onKeydown,
|
|
570
|
+
onPointerdown,
|
|
571
|
+
onPointermove,
|
|
572
|
+
onPointerup: finishPointer,
|
|
573
|
+
onPointercancel: finishPointer
|
|
574
|
+
}), slots.default?.({ isOpen: root.isOpen.value }));
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
var DropdownMenuPortal = defineComponent({
|
|
578
|
+
name: "RpDropdownMenuPortal",
|
|
579
|
+
props: {
|
|
580
|
+
to: {
|
|
581
|
+
type: [String, Object],
|
|
582
|
+
default: void 0
|
|
583
|
+
},
|
|
584
|
+
teleportTo: {
|
|
585
|
+
type: [String, Object],
|
|
586
|
+
default: void 0
|
|
587
|
+
},
|
|
588
|
+
teleport: {
|
|
589
|
+
type: Boolean,
|
|
590
|
+
default: true
|
|
591
|
+
},
|
|
592
|
+
disabled: {
|
|
593
|
+
type: Boolean,
|
|
594
|
+
default: false
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
setup(props, { slots }) {
|
|
598
|
+
const teleportTo = provideTeleportTarget({ get teleportTo() {
|
|
599
|
+
return props.to ?? props.teleportTo;
|
|
600
|
+
} });
|
|
601
|
+
return () => h(Teleport, {
|
|
602
|
+
to: teleportTo.value,
|
|
603
|
+
disabled: props.disabled || !props.teleport
|
|
604
|
+
}, slots.default?.());
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
function createContentComponent(submenu) {
|
|
608
|
+
return defineComponent({
|
|
609
|
+
name: submenu ? "RpDropdownMenuSubContent" : "RpDropdownMenuContent",
|
|
610
|
+
inheritAttrs: false,
|
|
611
|
+
props: {
|
|
612
|
+
id: String,
|
|
613
|
+
as: primitiveAsProp("div"),
|
|
614
|
+
placement: {
|
|
615
|
+
type: String,
|
|
616
|
+
default: submenu ? "right-start" : "bottom-start"
|
|
617
|
+
},
|
|
618
|
+
offset: {
|
|
619
|
+
type: [Number, Object],
|
|
620
|
+
default: void 0
|
|
621
|
+
},
|
|
622
|
+
strategy: {
|
|
623
|
+
type: String,
|
|
624
|
+
default: "absolute"
|
|
625
|
+
},
|
|
626
|
+
flip: {
|
|
627
|
+
type: Boolean,
|
|
628
|
+
default: true
|
|
629
|
+
},
|
|
630
|
+
shift: {
|
|
631
|
+
type: Boolean,
|
|
632
|
+
default: true
|
|
633
|
+
},
|
|
634
|
+
collisionPadding: {
|
|
635
|
+
type: [Number, Object],
|
|
636
|
+
default: 8
|
|
637
|
+
},
|
|
638
|
+
arrow: {
|
|
639
|
+
type: Boolean,
|
|
640
|
+
default: false
|
|
641
|
+
},
|
|
642
|
+
avoidCollisions: {
|
|
643
|
+
type: Boolean,
|
|
644
|
+
default: true
|
|
645
|
+
},
|
|
646
|
+
forceMount: {
|
|
647
|
+
type: Boolean,
|
|
648
|
+
default: false
|
|
649
|
+
},
|
|
650
|
+
ariaLabel: String,
|
|
651
|
+
ariaLabelledby: String,
|
|
652
|
+
ariaDescribedby: String
|
|
653
|
+
},
|
|
654
|
+
emits: [
|
|
655
|
+
"escapeKeyDown",
|
|
656
|
+
"pointerDownOutside",
|
|
657
|
+
"focusOutside",
|
|
658
|
+
"interactOutside"
|
|
659
|
+
],
|
|
660
|
+
setup(props, { attrs, emit, slots }) {
|
|
661
|
+
const root = useRequiredInject(rootKey, submenu ? "RpDropdownMenuSubContent" : "RpDropdownMenuContent");
|
|
662
|
+
const sub = submenu ? useRequiredInject(subKey, "RpDropdownMenuSubContent") : void 0;
|
|
663
|
+
const generatedId = useId();
|
|
664
|
+
const id = computed(() => props.id ?? `${generatedId}-${submenu ? "submenu" : "menu"}`);
|
|
665
|
+
const element = ref(null);
|
|
666
|
+
const arrowElement = ref(null);
|
|
667
|
+
const actualPlacement = ref(props.placement);
|
|
668
|
+
const isOpen = computed(() => sub ? sub.isOpen.value : root.isOpen.value);
|
|
669
|
+
const reference = computed(() => sub ? sub.trigger.value : root.reference.value);
|
|
670
|
+
const teleportTo = useTeleportTarget(() => void 0);
|
|
671
|
+
const menu = createMenuContext({
|
|
672
|
+
root,
|
|
673
|
+
element,
|
|
674
|
+
actualPlacement,
|
|
675
|
+
parentSub: sub,
|
|
676
|
+
onEscape(event) {
|
|
677
|
+
const customEvent = createCustomEvent("dropdown-menu-escape-key-down", { originalEvent: event }, event);
|
|
678
|
+
emit("escapeKeyDown", customEvent);
|
|
679
|
+
if (customEvent.defaultPrevented) return;
|
|
680
|
+
if (sub) sub.close(true);
|
|
681
|
+
else root.close({ returnFocus: true });
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
const floating = useFloatingPosition({
|
|
685
|
+
reference,
|
|
686
|
+
floating: element,
|
|
687
|
+
arrow: arrowElement,
|
|
688
|
+
open: isOpen,
|
|
689
|
+
placement: () => props.placement,
|
|
690
|
+
strategy: () => props.strategy,
|
|
691
|
+
offset: () => props.offset,
|
|
692
|
+
flip: () => props.avoidCollisions !== false && props.flip,
|
|
693
|
+
shift: () => props.avoidCollisions !== false && props.shift,
|
|
694
|
+
collisionPadding: () => props.collisionPadding,
|
|
695
|
+
arrowEnabled: () => !submenu && props.arrow,
|
|
696
|
+
restartKey: () => teleportTo.value
|
|
697
|
+
});
|
|
698
|
+
watch(floating.actualPlacement, (value) => {
|
|
699
|
+
actualPlacement.value = value;
|
|
700
|
+
}, { immediate: true });
|
|
701
|
+
const shouldRender = computed(() => props.forceMount || isOpen.value);
|
|
702
|
+
provide(menuKey, menu);
|
|
703
|
+
if (sub) sub.menu = menu;
|
|
704
|
+
function setElement(value) {
|
|
705
|
+
const previous = element.value;
|
|
706
|
+
if (previous) root.unregisterInside(previous);
|
|
707
|
+
element.value = toHTMLElement(value);
|
|
708
|
+
if (element.value) root.registerInside(element.value);
|
|
709
|
+
}
|
|
710
|
+
function emitOutside(type, originalEvent) {
|
|
711
|
+
const outsideEvent = createOutsideEvent(originalEvent);
|
|
712
|
+
if (type === "pointer") emit("pointerDownOutside", outsideEvent);
|
|
713
|
+
else emit("focusOutside", outsideEvent);
|
|
714
|
+
emit("interactOutside", outsideEvent);
|
|
715
|
+
return outsideEvent;
|
|
716
|
+
}
|
|
717
|
+
function onDocumentPointer(event) {
|
|
718
|
+
if (!isTopLayer(root) || root.isInside(event.target)) return;
|
|
719
|
+
const outsideEvent = emitOutside("pointer", event);
|
|
720
|
+
if (root.modal.value) {
|
|
721
|
+
if (event.cancelable) event.preventDefault();
|
|
722
|
+
event.stopPropagation();
|
|
723
|
+
if (event.type === "pointerdown") blockNextDocumentClick();
|
|
724
|
+
}
|
|
725
|
+
if (!outsideEvent.defaultPrevented) root.close({ returnFocus: root.modal.value });
|
|
726
|
+
}
|
|
727
|
+
function onDocumentFocus(event) {
|
|
728
|
+
if (!isTopLayer(root) || root.isInside(event.target)) return;
|
|
729
|
+
const outsideEvent = emitOutside("focus", event);
|
|
730
|
+
if (root.modal.value) {
|
|
731
|
+
if (event.cancelable) event.preventDefault();
|
|
732
|
+
event.stopPropagation();
|
|
733
|
+
}
|
|
734
|
+
if (!outsideEvent.defaultPrevented) root.close({ returnFocus: root.modal.value });
|
|
735
|
+
else if (root.modal.value) nextTick(menu.focusElement);
|
|
736
|
+
}
|
|
737
|
+
function setDocumentListeners(active) {
|
|
738
|
+
if (submenu || typeof document === "undefined") return;
|
|
739
|
+
const method = active ? "addEventListener" : "removeEventListener";
|
|
740
|
+
document[method]("pointerdown", onDocumentPointer, true);
|
|
741
|
+
document[method]("click", onDocumentPointer, true);
|
|
742
|
+
document[method]("focusin", onDocumentFocus, true);
|
|
743
|
+
}
|
|
744
|
+
watch(isOpen, (open) => {
|
|
745
|
+
setDocumentListeners(open);
|
|
746
|
+
if (!open) {
|
|
747
|
+
menu.activeId.value = null;
|
|
748
|
+
menu.closeSubmenus();
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
nextTick(() => {
|
|
752
|
+
const focus = sub ? sub.pendingFocus.value : root.pendingFocus.value;
|
|
753
|
+
menu.focus(focus || "first");
|
|
754
|
+
});
|
|
755
|
+
}, {
|
|
756
|
+
flush: "post",
|
|
757
|
+
immediate: true
|
|
758
|
+
});
|
|
759
|
+
onMounted(() => {
|
|
760
|
+
if (sub) sub.contentId.value = id.value;
|
|
761
|
+
else root.contentId.value = id.value;
|
|
762
|
+
if (isOpen.value) menu.focus((sub ? sub.pendingFocus.value : root.pendingFocus.value) || "first");
|
|
763
|
+
});
|
|
764
|
+
onBeforeUnmount(() => {
|
|
765
|
+
setDocumentListeners(false);
|
|
766
|
+
if (element.value) root.unregisterInside(element.value);
|
|
767
|
+
if (sub) sub.menu = null;
|
|
768
|
+
else if (root.contentId.value === id.value) root.contentId.value = void 0;
|
|
769
|
+
});
|
|
770
|
+
return () => {
|
|
771
|
+
if (!shouldRender.value) return null;
|
|
772
|
+
const placement = floating.actualPlacement.value.split("-");
|
|
773
|
+
const className = submenu ? bem("rp-dropdown-menu__submenu", {
|
|
774
|
+
compound: true,
|
|
775
|
+
open: isOpen.value
|
|
776
|
+
}) : bem("rp-dropdown-menu__content", {
|
|
777
|
+
compound: true,
|
|
778
|
+
open: isOpen.value
|
|
779
|
+
});
|
|
780
|
+
return h(props.as ?? "div", mergeProps(attrs, {
|
|
781
|
+
id: id.value,
|
|
782
|
+
ref: setElement,
|
|
783
|
+
role: "menu",
|
|
784
|
+
tabindex: -1,
|
|
785
|
+
hidden: optionalAttr(!isOpen.value),
|
|
786
|
+
class: className,
|
|
787
|
+
style: [floating.floatingStyle.value, !isOpen.value ? { display: "none" } : void 0],
|
|
788
|
+
"aria-label": props.ariaLabel,
|
|
789
|
+
"aria-labelledby": props.ariaLabelledby ?? (submenu ? void 0 : root.triggerId.value),
|
|
790
|
+
"aria-describedby": props.ariaDescribedby,
|
|
791
|
+
"aria-activedescendant": menu.activeId.value ?? void 0,
|
|
792
|
+
"data-state": isOpen.value ? "open" : "closed",
|
|
793
|
+
"data-placement": floating.actualPlacement.value,
|
|
794
|
+
"data-side": placement[0],
|
|
795
|
+
"data-align": placement[1] ?? "center",
|
|
796
|
+
onKeydown: menu.onKeydown
|
|
797
|
+
}), [!submenu && props.arrow ? h("span", {
|
|
798
|
+
ref: arrowElement,
|
|
799
|
+
class: "rp-dropdown-menu__arrow",
|
|
800
|
+
"data-side": placement[0],
|
|
801
|
+
style: floating.arrowStyle.value,
|
|
802
|
+
"aria-hidden": "true"
|
|
803
|
+
}) : null, slots.default?.({
|
|
804
|
+
isOpen: isOpen.value,
|
|
805
|
+
placement: floating.actualPlacement.value,
|
|
806
|
+
close: () => sub ? sub.close(true) : root.close({ returnFocus: true })
|
|
807
|
+
})]);
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
var DropdownMenuContent = createContentComponent(false);
|
|
813
|
+
var DropdownMenuSubContent = createContentComponent(true);
|
|
814
|
+
function usePrimitiveItem(componentName, props, emit, options) {
|
|
815
|
+
const menu = useRequiredInject(menuKey, componentName);
|
|
816
|
+
const generatedId = useId();
|
|
817
|
+
const id = computed(() => props.id ?? `${generatedId}-item`);
|
|
818
|
+
const element = ref(null);
|
|
819
|
+
const isDisabled = computed(() => Boolean(menu.root.disabled.value || props.disabled));
|
|
820
|
+
const focused = computed(() => menu.isActive(id.value));
|
|
821
|
+
function activate(originalEvent) {
|
|
822
|
+
if (isDisabled.value) return;
|
|
823
|
+
const selectEvent = createSelectEvent(originalEvent, props.value);
|
|
824
|
+
emit("select", selectEvent);
|
|
825
|
+
options.afterSelect?.();
|
|
826
|
+
if (!selectEvent.defaultPrevented && (props.closeOnSelect ?? options.defaultCloseOnSelect)) menu.root.close({ returnFocus: true });
|
|
827
|
+
}
|
|
828
|
+
const registration = {
|
|
829
|
+
get id() {
|
|
830
|
+
return id.value;
|
|
831
|
+
},
|
|
832
|
+
element: () => element.value,
|
|
833
|
+
disabled: () => isDisabled.value,
|
|
834
|
+
activate
|
|
835
|
+
};
|
|
836
|
+
menu.registerItem(registration);
|
|
837
|
+
watch(id, (nextId, previousId) => {
|
|
838
|
+
menu.unregisterItem(previousId);
|
|
839
|
+
menu.registerItem(registration);
|
|
840
|
+
if (menu.activeId.value === previousId) menu.activeId.value = nextId;
|
|
841
|
+
});
|
|
842
|
+
onBeforeUnmount(() => menu.unregisterItem(id.value));
|
|
843
|
+
function setElement(value) {
|
|
844
|
+
element.value = toHTMLElement(value);
|
|
845
|
+
}
|
|
846
|
+
function onPointerenter() {
|
|
847
|
+
if (isDisabled.value) return;
|
|
848
|
+
menu.closeSubmenus();
|
|
849
|
+
menu.setActive(id.value);
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
menu,
|
|
853
|
+
id,
|
|
854
|
+
element,
|
|
855
|
+
isDisabled,
|
|
856
|
+
focused,
|
|
857
|
+
activate,
|
|
858
|
+
setElement,
|
|
859
|
+
render(attrs, slots) {
|
|
860
|
+
const as = props.as ?? "button";
|
|
861
|
+
return h(as, mergeProps(attrs, {
|
|
862
|
+
id: id.value,
|
|
863
|
+
ref: setElement,
|
|
864
|
+
type: as === "button" ? "button" : void 0,
|
|
865
|
+
role: options.role ?? "menuitem",
|
|
866
|
+
tabindex: -1,
|
|
867
|
+
disabled: as === "button" ? optionalAttr(isDisabled.value) : void 0,
|
|
868
|
+
"aria-disabled": optionalAttr(isDisabled.value),
|
|
869
|
+
"aria-checked": options.checked?.value,
|
|
870
|
+
"data-disabled": optionalAttr(isDisabled.value),
|
|
871
|
+
"data-focused": optionalAttr(focused.value),
|
|
872
|
+
"data-highlighted": optionalAttr(focused.value),
|
|
873
|
+
"data-state": options.checked ? options.checked.value === "mixed" ? "indeterminate" : options.checked.value ? "checked" : "unchecked" : void 0,
|
|
874
|
+
class: bem("rp-dropdown-menu__item", {
|
|
875
|
+
focused: focused.value,
|
|
876
|
+
disabled: isDisabled.value,
|
|
877
|
+
destructive: props.destructive
|
|
878
|
+
}),
|
|
879
|
+
onClick: (event) => {
|
|
880
|
+
if (!event.defaultPrevented) activate(event);
|
|
881
|
+
},
|
|
882
|
+
onMouseenter: onPointerenter
|
|
883
|
+
}), slots.default?.({
|
|
884
|
+
focused: focused.value,
|
|
885
|
+
disabled: isDisabled.value,
|
|
886
|
+
select: () => activate(new Event("select"))
|
|
887
|
+
}));
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
var DropdownMenuItem$1 = defineComponent({
|
|
892
|
+
name: "RpDropdownMenuItem",
|
|
893
|
+
inheritAttrs: false,
|
|
894
|
+
props: {
|
|
895
|
+
id: String,
|
|
896
|
+
as: primitiveAsProp("button"),
|
|
897
|
+
value: [String, Number],
|
|
898
|
+
disabled: {
|
|
899
|
+
type: Boolean,
|
|
900
|
+
default: false
|
|
901
|
+
},
|
|
902
|
+
destructive: {
|
|
903
|
+
type: Boolean,
|
|
904
|
+
default: false
|
|
905
|
+
},
|
|
906
|
+
closeOnSelect: {
|
|
907
|
+
type: Boolean,
|
|
908
|
+
default: true
|
|
909
|
+
}
|
|
910
|
+
},
|
|
911
|
+
emits: ["select"],
|
|
912
|
+
setup(props, { attrs, emit, slots }) {
|
|
913
|
+
const item = usePrimitiveItem("RpDropdownMenuItem", props, emit, { defaultCloseOnSelect: true });
|
|
914
|
+
return () => item.render(attrs, slots);
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
var DropdownMenuSeparator = defineComponent({
|
|
918
|
+
name: "RpDropdownMenuSeparator",
|
|
919
|
+
inheritAttrs: false,
|
|
920
|
+
props: {
|
|
921
|
+
id: String,
|
|
922
|
+
as: primitiveAsProp("div"),
|
|
923
|
+
orientation: {
|
|
924
|
+
type: String,
|
|
925
|
+
default: "horizontal"
|
|
926
|
+
}
|
|
927
|
+
},
|
|
928
|
+
setup(props, { attrs }) {
|
|
929
|
+
useRequiredInject(menuKey, "RpDropdownMenuSeparator");
|
|
930
|
+
return () => h(props.as ?? "div", mergeProps(attrs, {
|
|
931
|
+
id: props.id,
|
|
932
|
+
role: "separator",
|
|
933
|
+
"aria-orientation": props.orientation,
|
|
934
|
+
class: "rp-dropdown-menu__separator",
|
|
935
|
+
"data-orientation": props.orientation
|
|
936
|
+
}));
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
var DropdownMenuLabel = defineComponent({
|
|
940
|
+
name: "RpDropdownMenuLabel",
|
|
941
|
+
inheritAttrs: false,
|
|
942
|
+
props: {
|
|
943
|
+
id: String,
|
|
944
|
+
as: primitiveAsProp("div")
|
|
945
|
+
},
|
|
946
|
+
setup(props, { attrs, slots }) {
|
|
947
|
+
useRequiredInject(menuKey, "RpDropdownMenuLabel");
|
|
948
|
+
return () => h(props.as ?? "div", mergeProps(attrs, {
|
|
949
|
+
id: props.id,
|
|
950
|
+
role: "presentation",
|
|
951
|
+
class: "rp-dropdown-menu__group-label"
|
|
952
|
+
}), slots.default?.());
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
var DropdownMenuCheckboxItem = defineComponent({
|
|
956
|
+
name: "RpDropdownMenuCheckboxItem",
|
|
957
|
+
inheritAttrs: false,
|
|
958
|
+
props: {
|
|
959
|
+
id: String,
|
|
960
|
+
as: primitiveAsProp("button"),
|
|
961
|
+
modelValue: {
|
|
962
|
+
type: [Boolean, String],
|
|
963
|
+
default: void 0
|
|
964
|
+
},
|
|
965
|
+
defaultValue: {
|
|
966
|
+
type: [Boolean, String],
|
|
967
|
+
default: false
|
|
968
|
+
},
|
|
969
|
+
disabled: {
|
|
970
|
+
type: Boolean,
|
|
971
|
+
default: false
|
|
972
|
+
},
|
|
973
|
+
destructive: {
|
|
974
|
+
type: Boolean,
|
|
975
|
+
default: false
|
|
976
|
+
},
|
|
977
|
+
closeOnSelect: {
|
|
978
|
+
type: Boolean,
|
|
979
|
+
default: false
|
|
980
|
+
}
|
|
981
|
+
},
|
|
982
|
+
emits: ["select", "update:modelValue"],
|
|
983
|
+
setup(props, { attrs, emit, slots }) {
|
|
984
|
+
const uncontrolled = ref(props.defaultValue);
|
|
985
|
+
const value = computed(() => props.modelValue ?? uncontrolled.value);
|
|
986
|
+
const checked = computed(() => value.value === "indeterminate" ? "mixed" : value.value);
|
|
987
|
+
const state = computed(() => value.value === "indeterminate" ? "indeterminate" : value.value ? "checked" : "unchecked");
|
|
988
|
+
function toggleChecked() {
|
|
989
|
+
const nextValue = value.value === "indeterminate" ? true : !value.value;
|
|
990
|
+
if (props.modelValue === void 0) uncontrolled.value = nextValue;
|
|
991
|
+
emit("update:modelValue", nextValue);
|
|
992
|
+
}
|
|
993
|
+
provide(checkedKey, {
|
|
994
|
+
state,
|
|
995
|
+
checked: computed(() => value.value !== false)
|
|
996
|
+
});
|
|
997
|
+
const item = usePrimitiveItem("RpDropdownMenuCheckboxItem", props, emit, {
|
|
998
|
+
role: "menuitemcheckbox",
|
|
999
|
+
checked,
|
|
1000
|
+
defaultCloseOnSelect: false,
|
|
1001
|
+
afterSelect: toggleChecked
|
|
1002
|
+
});
|
|
1003
|
+
return () => item.render(attrs, slots);
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
var DropdownMenuRadioGroup = defineComponent({
|
|
1007
|
+
name: "RpDropdownMenuRadioGroup",
|
|
1008
|
+
inheritAttrs: false,
|
|
1009
|
+
props: {
|
|
1010
|
+
id: String,
|
|
1011
|
+
as: primitiveAsProp("div"),
|
|
1012
|
+
modelValue: {
|
|
1013
|
+
type: [String, Number],
|
|
1014
|
+
default: void 0
|
|
1015
|
+
},
|
|
1016
|
+
defaultValue: {
|
|
1017
|
+
type: [String, Number],
|
|
1018
|
+
default: null
|
|
1019
|
+
},
|
|
1020
|
+
ariaLabel: String,
|
|
1021
|
+
ariaLabelledby: String
|
|
1022
|
+
},
|
|
1023
|
+
emits: ["update:modelValue"],
|
|
1024
|
+
setup(props, { attrs, emit, slots }) {
|
|
1025
|
+
useRequiredInject(menuKey, "RpDropdownMenuRadioGroup");
|
|
1026
|
+
const uncontrolled = ref(props.defaultValue);
|
|
1027
|
+
const value = computed(() => props.modelValue === void 0 ? uncontrolled.value : props.modelValue);
|
|
1028
|
+
function select(nextValue) {
|
|
1029
|
+
if (value.value === nextValue) return;
|
|
1030
|
+
if (props.modelValue === void 0) uncontrolled.value = nextValue;
|
|
1031
|
+
emit("update:modelValue", nextValue);
|
|
1032
|
+
}
|
|
1033
|
+
provide(radioGroupKey, {
|
|
1034
|
+
value,
|
|
1035
|
+
select
|
|
1036
|
+
});
|
|
1037
|
+
return () => h(props.as ?? "div", mergeProps(attrs, {
|
|
1038
|
+
id: props.id,
|
|
1039
|
+
role: "group",
|
|
1040
|
+
class: "rp-dropdown-menu__radio-group",
|
|
1041
|
+
"aria-label": props.ariaLabel,
|
|
1042
|
+
"aria-labelledby": props.ariaLabelledby
|
|
1043
|
+
}), slots.default?.({ value: value.value }));
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
var DropdownMenuRadioItem = defineComponent({
|
|
1047
|
+
name: "RpDropdownMenuRadioItem",
|
|
1048
|
+
inheritAttrs: false,
|
|
1049
|
+
props: {
|
|
1050
|
+
id: String,
|
|
1051
|
+
as: primitiveAsProp("button"),
|
|
1052
|
+
value: {
|
|
1053
|
+
type: [String, Number],
|
|
1054
|
+
required: true
|
|
1055
|
+
},
|
|
1056
|
+
disabled: {
|
|
1057
|
+
type: Boolean,
|
|
1058
|
+
default: false
|
|
1059
|
+
},
|
|
1060
|
+
destructive: {
|
|
1061
|
+
type: Boolean,
|
|
1062
|
+
default: false
|
|
1063
|
+
},
|
|
1064
|
+
closeOnSelect: {
|
|
1065
|
+
type: Boolean,
|
|
1066
|
+
default: false
|
|
1067
|
+
}
|
|
1068
|
+
},
|
|
1069
|
+
emits: ["select"],
|
|
1070
|
+
setup(props, { attrs, emit, slots }) {
|
|
1071
|
+
const group = useRequiredInject(radioGroupKey, "RpDropdownMenuRadioItem");
|
|
1072
|
+
const isChecked = computed(() => group.value.value === props.value);
|
|
1073
|
+
const checked = computed(() => isChecked.value);
|
|
1074
|
+
provide(checkedKey, {
|
|
1075
|
+
state: computed(() => isChecked.value ? "checked" : "unchecked"),
|
|
1076
|
+
checked: isChecked
|
|
1077
|
+
});
|
|
1078
|
+
const item = usePrimitiveItem("RpDropdownMenuRadioItem", props, emit, {
|
|
1079
|
+
role: "menuitemradio",
|
|
1080
|
+
checked,
|
|
1081
|
+
defaultCloseOnSelect: false,
|
|
1082
|
+
afterSelect: () => group.select(props.value)
|
|
1083
|
+
});
|
|
1084
|
+
return () => item.render(attrs, slots);
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
var DropdownMenuItemIndicator = defineComponent({
|
|
1088
|
+
name: "RpDropdownMenuItemIndicator",
|
|
1089
|
+
inheritAttrs: false,
|
|
1090
|
+
props: {
|
|
1091
|
+
as: primitiveAsProp("span"),
|
|
1092
|
+
forceMount: {
|
|
1093
|
+
type: Boolean,
|
|
1094
|
+
default: false
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
setup(props, { attrs, slots }) {
|
|
1098
|
+
const context = useRequiredInject(checkedKey, "RpDropdownMenuItemIndicator");
|
|
1099
|
+
return () => {
|
|
1100
|
+
if (!props.forceMount && !context.checked.value) return null;
|
|
1101
|
+
return h(props.as ?? "span", mergeProps(attrs, {
|
|
1102
|
+
class: "rp-dropdown-menu__indicator",
|
|
1103
|
+
"data-state": context.state.value,
|
|
1104
|
+
"aria-hidden": true
|
|
1105
|
+
}), slots.default?.({
|
|
1106
|
+
state: context.state.value,
|
|
1107
|
+
checked: context.checked.value
|
|
1108
|
+
}));
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
var DropdownMenuSub = defineComponent({
|
|
1113
|
+
name: "RpDropdownMenuSub",
|
|
1114
|
+
props: {
|
|
1115
|
+
open: {
|
|
1116
|
+
type: Boolean,
|
|
1117
|
+
default: void 0
|
|
1118
|
+
},
|
|
1119
|
+
defaultOpen: {
|
|
1120
|
+
type: Boolean,
|
|
1121
|
+
default: false
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
emits: ["update:open"],
|
|
1125
|
+
setup(props, { emit, slots }) {
|
|
1126
|
+
const parentMenu = useRequiredInject(menuKey, "RpDropdownMenuSub");
|
|
1127
|
+
const uncontrolled = ref(props.defaultOpen);
|
|
1128
|
+
const isOpen = computed(() => props.open ?? uncontrolled.value);
|
|
1129
|
+
const trigger = ref(null);
|
|
1130
|
+
const contentId = ref();
|
|
1131
|
+
const actualPlacement = ref("right-start");
|
|
1132
|
+
const pendingFocus = ref(false);
|
|
1133
|
+
function setOpen(value) {
|
|
1134
|
+
const previous = isOpen.value;
|
|
1135
|
+
if (props.open === void 0) uncontrolled.value = value;
|
|
1136
|
+
if (previous !== value) emit("update:open", value);
|
|
1137
|
+
}
|
|
1138
|
+
const context = {
|
|
1139
|
+
isOpen,
|
|
1140
|
+
trigger,
|
|
1141
|
+
contentId,
|
|
1142
|
+
actualPlacement,
|
|
1143
|
+
pendingFocus,
|
|
1144
|
+
menu: null,
|
|
1145
|
+
open(focus = "first") {
|
|
1146
|
+
parentMenu.closeSubmenus(context);
|
|
1147
|
+
pendingFocus.value = focus;
|
|
1148
|
+
setOpen(true);
|
|
1149
|
+
if (focus) nextTick(() => context.menu?.focus(focus));
|
|
1150
|
+
},
|
|
1151
|
+
close(focusParent = false) {
|
|
1152
|
+
setOpen(false);
|
|
1153
|
+
pendingFocus.value = false;
|
|
1154
|
+
context.menu?.closeSubmenus();
|
|
1155
|
+
if (focusParent) {
|
|
1156
|
+
parentMenu.setActive(trigger.value?.id ?? "");
|
|
1157
|
+
parentMenu.focusElement();
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
parentMenu.registerSub(context);
|
|
1162
|
+
provide(subKey, context);
|
|
1163
|
+
watch(parentMenu.root.isOpen, (open) => {
|
|
1164
|
+
if (!open) context.close(false);
|
|
1165
|
+
});
|
|
1166
|
+
onBeforeUnmount(() => parentMenu.unregisterSub(context));
|
|
1167
|
+
return () => slots.default?.({
|
|
1168
|
+
isOpen: isOpen.value,
|
|
1169
|
+
open: context.open,
|
|
1170
|
+
close: context.close
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
});
|
|
1174
|
+
var DropdownMenuSubTrigger = defineComponent({
|
|
1175
|
+
name: "RpDropdownMenuSubTrigger",
|
|
1176
|
+
inheritAttrs: false,
|
|
1177
|
+
props: {
|
|
1178
|
+
id: String,
|
|
1179
|
+
as: primitiveAsProp("button"),
|
|
1180
|
+
disabled: {
|
|
1181
|
+
type: Boolean,
|
|
1182
|
+
default: false
|
|
1183
|
+
}
|
|
1184
|
+
},
|
|
1185
|
+
setup(props, { attrs, slots }) {
|
|
1186
|
+
const menu = useRequiredInject(menuKey, "RpDropdownMenuSubTrigger");
|
|
1187
|
+
const sub = useRequiredInject(subKey, "RpDropdownMenuSubTrigger");
|
|
1188
|
+
const generatedId = useId();
|
|
1189
|
+
const id = computed(() => props.id ?? `${generatedId}-sub-trigger`);
|
|
1190
|
+
const isDisabled = computed(() => menu.root.disabled.value || props.disabled);
|
|
1191
|
+
const focused = computed(() => menu.isActive(id.value));
|
|
1192
|
+
const registration = {
|
|
1193
|
+
get id() {
|
|
1194
|
+
return id.value;
|
|
1195
|
+
},
|
|
1196
|
+
element: () => sub.trigger.value,
|
|
1197
|
+
disabled: () => isDisabled.value,
|
|
1198
|
+
activate: () => sub.open("first"),
|
|
1199
|
+
submenu: sub
|
|
1200
|
+
};
|
|
1201
|
+
menu.registerItem(registration);
|
|
1202
|
+
onBeforeUnmount(() => menu.unregisterItem(id.value));
|
|
1203
|
+
function setElement(value) {
|
|
1204
|
+
sub.trigger.value = toHTMLElement(value);
|
|
1205
|
+
}
|
|
1206
|
+
function onMouseenter() {
|
|
1207
|
+
if (isDisabled.value) return;
|
|
1208
|
+
menu.setActive(id.value);
|
|
1209
|
+
sub.open(false);
|
|
1210
|
+
}
|
|
1211
|
+
return () => {
|
|
1212
|
+
const as = props.as ?? "button";
|
|
1213
|
+
return h(as, mergeProps(attrs, {
|
|
1214
|
+
id: id.value,
|
|
1215
|
+
ref: setElement,
|
|
1216
|
+
type: as === "button" ? "button" : void 0,
|
|
1217
|
+
role: "menuitem",
|
|
1218
|
+
tabindex: -1,
|
|
1219
|
+
disabled: as === "button" ? optionalAttr(isDisabled.value) : void 0,
|
|
1220
|
+
"aria-disabled": optionalAttr(isDisabled.value),
|
|
1221
|
+
"aria-haspopup": "menu",
|
|
1222
|
+
"aria-expanded": sub.isOpen.value,
|
|
1223
|
+
"aria-controls": sub.contentId.value,
|
|
1224
|
+
"data-disabled": optionalAttr(isDisabled.value),
|
|
1225
|
+
"data-focused": optionalAttr(focused.value),
|
|
1226
|
+
"data-highlighted": optionalAttr(focused.value),
|
|
1227
|
+
"data-state": sub.isOpen.value ? "open" : "closed",
|
|
1228
|
+
class: bem("rp-dropdown-menu__item", {
|
|
1229
|
+
focused: focused.value,
|
|
1230
|
+
disabled: isDisabled.value,
|
|
1231
|
+
submenu: true,
|
|
1232
|
+
open: sub.isOpen.value
|
|
1233
|
+
}),
|
|
1234
|
+
onClick: (event) => {
|
|
1235
|
+
if (!event.defaultPrevented && !isDisabled.value) sub.open("first");
|
|
1236
|
+
},
|
|
1237
|
+
onMouseenter
|
|
1238
|
+
}), slots.default?.({
|
|
1239
|
+
focused: focused.value,
|
|
1240
|
+
disabled: isDisabled.value,
|
|
1241
|
+
isOpen: sub.isOpen.value,
|
|
1242
|
+
open: sub.open,
|
|
1243
|
+
close: sub.close
|
|
1244
|
+
}));
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
});
|
|
1248
|
+
//#endregion
|
|
5
1249
|
//#region ~icons/lucide/chevron-right
|
|
6
1250
|
var t0$1 = template("<svg viewBox=\"0 0 24 24\"width=1.2em height=1.2em><path fill=none stroke=currentColor stroke-linecap=round stroke-linejoin=round stroke-width=2 d=\"m9 18l6-6l-6-6\">", 3, 1);
|
|
7
1251
|
function render(_ctx) {
|
|
@@ -116,7 +1360,11 @@ var DropdownMenuItemRow = defineComponent({
|
|
|
116
1360
|
return () => {
|
|
117
1361
|
const currentPath = path.value;
|
|
118
1362
|
const hasSubmenu = hasItemSubmenu(props.item);
|
|
119
|
-
const
|
|
1363
|
+
const itemProps = props.context.getItemProps(props.item, currentPath, props.focused, props.disabled, props.submenuOpen);
|
|
1364
|
+
const children = [h("button", {
|
|
1365
|
+
...itemProps,
|
|
1366
|
+
...props.context.getPublicPartAttrs?.("item", { class: itemProps.class })
|
|
1367
|
+
}, props.renderItem(props.context.getItemSlotProps(props.item, currentPath, props.focused, props.disabled, props.submenuOpen)))];
|
|
120
1368
|
if (hasSubmenu && props.submenuOpen) children.push(h(DropdownMenuSubmenu, {
|
|
121
1369
|
context: props.context,
|
|
122
1370
|
item: props.item,
|
|
@@ -177,12 +1425,38 @@ var DropdownMenuSubmenu = defineComponent({
|
|
|
177
1425
|
renderItem: renderItemProp
|
|
178
1426
|
},
|
|
179
1427
|
setup(props) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1428
|
+
const element = ref(null);
|
|
1429
|
+
const floating = useFloatingPosition({
|
|
1430
|
+
reference: computed(() => props.context.getItemElement(props.path)),
|
|
1431
|
+
floating: element,
|
|
1432
|
+
open: computed(() => props.context.isSubmenuOpen(props.path)),
|
|
1433
|
+
placement: props.context.getSubmenuPlacement,
|
|
1434
|
+
strategy: props.context.getStrategy,
|
|
1435
|
+
offset: () => 4,
|
|
1436
|
+
flip: props.context.getFlip,
|
|
1437
|
+
shift: props.context.getShift,
|
|
1438
|
+
collisionPadding: props.context.getCollisionPadding,
|
|
1439
|
+
arrowEnabled: () => false
|
|
1440
|
+
});
|
|
1441
|
+
return () => {
|
|
1442
|
+
const submenuProps = props.context.getSubmenuProps(props.item, props.path, true);
|
|
1443
|
+
return h("div", {
|
|
1444
|
+
...submenuProps,
|
|
1445
|
+
...props.context.getPublicPartAttrs?.("submenu", {
|
|
1446
|
+
class: submenuProps.class,
|
|
1447
|
+
style: floating.floatingStyle.value
|
|
1448
|
+
}),
|
|
1449
|
+
ref: element,
|
|
1450
|
+
"data-state": "open",
|
|
1451
|
+
"data-placement": floating.actualPlacement.value.split("-")[0],
|
|
1452
|
+
"data-side": floating.actualPlacement.value.split("-")[0]
|
|
1453
|
+
}, [h(DropdownMenuItemsList, {
|
|
1454
|
+
context: props.context,
|
|
1455
|
+
items: props.item.children ?? [],
|
|
1456
|
+
parentPath: props.path,
|
|
1457
|
+
renderItem: props.renderItem
|
|
1458
|
+
})]);
|
|
1459
|
+
};
|
|
186
1460
|
}
|
|
187
1461
|
});
|
|
188
1462
|
var dropdown_menu_items_default = defineComponent({
|
|
@@ -205,7 +1479,7 @@ var dropdown_menu_items_default = defineComponent({
|
|
|
205
1479
|
});
|
|
206
1480
|
//#endregion
|
|
207
1481
|
//#region src/components/dropdown-menu/useDropdownMenuDisclosure.ts
|
|
208
|
-
function useDropdownMenuDisclosure({ props, emit, rootRef, uncontrolledOpen, isDisabled, isOpen, isVisible, focusedPath, resetFocus, resetSubmenus, resetHoverIntent, focusItem, focusMenu, focusTrigger }) {
|
|
1482
|
+
function useDropdownMenuDisclosure({ props, emit, rootRef, menuRef, targetRef, uncontrolledOpen, isDisabled, isOpen, isVisible, focusedPath, resetFocus, resetSubmenus, resetHoverIntent, focusItem, focusMenu, focusTrigger }) {
|
|
209
1483
|
function setOpen(nextOpen) {
|
|
210
1484
|
if (nextOpen && isDisabled.value) return;
|
|
211
1485
|
const previousOpen = isOpen.value;
|
|
@@ -243,7 +1517,17 @@ function useDropdownMenuDisclosure({ props, emit, rootRef, uncontrolledOpen, isD
|
|
|
243
1517
|
focusMenu();
|
|
244
1518
|
} else resetMenuFocus();
|
|
245
1519
|
});
|
|
246
|
-
useClickOutside(
|
|
1520
|
+
useClickOutside([
|
|
1521
|
+
rootRef,
|
|
1522
|
+
menuRef,
|
|
1523
|
+
targetRef
|
|
1524
|
+
], isVisible, (event) => {
|
|
1525
|
+
if (props.modal) {
|
|
1526
|
+
event.preventDefault();
|
|
1527
|
+
event.stopPropagation();
|
|
1528
|
+
}
|
|
1529
|
+
close({ focusTrigger: Boolean(props.modal) });
|
|
1530
|
+
});
|
|
247
1531
|
return {
|
|
248
1532
|
open,
|
|
249
1533
|
close,
|
|
@@ -253,13 +1537,17 @@ function useDropdownMenuDisclosure({ props, emit, rootRef, uncontrolledOpen, isD
|
|
|
253
1537
|
}
|
|
254
1538
|
//#endregion
|
|
255
1539
|
//#region src/components/dropdown-menu/useDropdownMenuDom.ts
|
|
256
|
-
function useDropdownMenuDom({ menuId, rootRef, menuRef, placement, focusedPath }) {
|
|
1540
|
+
function useDropdownMenuDom({ menuId, rootRef, menuRef, targetRef, placement, focusedPath }) {
|
|
257
1541
|
const activeDescendantId = computed(() => focusedPath.value.length === 0 ? void 0 : getItemId(focusedPath.value));
|
|
258
1542
|
function focusMenu() {
|
|
259
1543
|
nextTick(() => menuRef.value?.focus());
|
|
260
1544
|
}
|
|
261
1545
|
function focusTrigger() {
|
|
262
1546
|
nextTick(() => {
|
|
1547
|
+
if (targetRef.value instanceof HTMLElement) {
|
|
1548
|
+
targetRef.value.focus();
|
|
1549
|
+
return;
|
|
1550
|
+
}
|
|
263
1551
|
(rootRef.value?.querySelector("[aria-haspopup=\"menu\"]"))?.focus();
|
|
264
1552
|
});
|
|
265
1553
|
}
|
|
@@ -457,15 +1745,22 @@ function useDropdownMenuInteractions({ props, emit, isDisabled, focusedPath, ope
|
|
|
457
1745
|
function activateItem(item, path, event) {
|
|
458
1746
|
if (item.disabled) return;
|
|
459
1747
|
if (hasItemSubmenu(item)) {
|
|
460
|
-
openSubmenu(path, DEFAULT_FOCUS_TARGET, event ? getEventPoint(event) : void 0);
|
|
1748
|
+
openSubmenu(path, DEFAULT_FOCUS_TARGET, event instanceof MouseEvent ? getEventPoint(event) : void 0);
|
|
461
1749
|
return;
|
|
462
1750
|
}
|
|
463
|
-
selectItem(item);
|
|
1751
|
+
selectItem(item, event);
|
|
464
1752
|
}
|
|
465
|
-
function selectItem(item) {
|
|
1753
|
+
function selectItem(item, originalEvent = new Event("select")) {
|
|
466
1754
|
if (item.disabled) return;
|
|
467
|
-
|
|
468
|
-
|
|
1755
|
+
const event = new CustomEvent("dropdown-menu-select", {
|
|
1756
|
+
cancelable: true,
|
|
1757
|
+
detail: {
|
|
1758
|
+
originalEvent,
|
|
1759
|
+
value: item.value
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
emit.select?.(item, event);
|
|
1763
|
+
if (!event.defaultPrevented && props.closeOnSelect !== false) disclosure.close({ focusTrigger: true });
|
|
469
1764
|
}
|
|
470
1765
|
function closeSubmenusAfter(menuPath) {
|
|
471
1766
|
submenus.closeSubmenusAfter(menuPath);
|
|
@@ -497,10 +1792,10 @@ function useDropdownMenuInteractions({ props, emit, isDisabled, focusedPath, ope
|
|
|
497
1792
|
const path = normalizePath(indexOrPath);
|
|
498
1793
|
hoverIntent.handleItemHover(item, path, event, commitHoveredItem);
|
|
499
1794
|
}
|
|
500
|
-
function selectFocusedItem() {
|
|
1795
|
+
function selectFocusedItem(event) {
|
|
501
1796
|
const item = getItemAtPath(focusedPath.value);
|
|
502
1797
|
if (!item) return;
|
|
503
|
-
activateItem(item, focusedPath.value);
|
|
1798
|
+
activateItem(item, focusedPath.value, event);
|
|
504
1799
|
}
|
|
505
1800
|
function moveFocusedItem(direction) {
|
|
506
1801
|
const menuPath = moveFocus(direction);
|
|
@@ -553,7 +1848,7 @@ function useDropdownMenuInteractions({ props, emit, isDisabled, focusedPath, ope
|
|
|
553
1848
|
case "Enter":
|
|
554
1849
|
case " ":
|
|
555
1850
|
event.preventDefault();
|
|
556
|
-
selectFocusedItem();
|
|
1851
|
+
selectFocusedItem(event);
|
|
557
1852
|
break;
|
|
558
1853
|
case "Escape":
|
|
559
1854
|
event.preventDefault();
|
|
@@ -655,8 +1950,31 @@ function useDropdownMenuNavigation(items) {
|
|
|
655
1950
|
};
|
|
656
1951
|
}
|
|
657
1952
|
//#endregion
|
|
1953
|
+
//#region src/components/dropdown-menu/useDropdownMenuPortalPosition.ts
|
|
1954
|
+
function useDropdownMenuPortalPosition(options) {
|
|
1955
|
+
const floating = useFloatingPosition({
|
|
1956
|
+
reference: options.reference,
|
|
1957
|
+
floating: options.menuRef,
|
|
1958
|
+
arrow: options.arrowRef,
|
|
1959
|
+
open: options.isVisible,
|
|
1960
|
+
placement: () => options.placement.value,
|
|
1961
|
+
strategy: () => options.props.strategy ?? "absolute",
|
|
1962
|
+
offset: () => options.props.offset,
|
|
1963
|
+
flip: () => options.props.flip !== false,
|
|
1964
|
+
shift: () => options.props.shift !== false,
|
|
1965
|
+
collisionPadding: () => options.props.collisionPadding ?? 8,
|
|
1966
|
+
arrowEnabled: () => Boolean(options.props.arrow),
|
|
1967
|
+
restartKey: options.restartKey
|
|
1968
|
+
});
|
|
1969
|
+
return {
|
|
1970
|
+
actualPlacement: floating.actualPlacement,
|
|
1971
|
+
arrowStyle: floating.arrowStyle,
|
|
1972
|
+
contentStyle: floating.floatingStyle
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
//#endregion
|
|
658
1976
|
//#region src/components/dropdown-menu/useDropdownMenuRenderItems.ts
|
|
659
|
-
function useDropdownMenuRenderItems({ items, getItemId, getSubmenuId, getMenuActiveDescendant, isItemFocused, isSubmenuOpen, activateItem, focusHoveredItem, selectItem, openSubmenu, closeSubmenu, close }) {
|
|
1977
|
+
function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId, getSubmenuId, getMenuActiveDescendant, getItemElement, isItemFocused, isSubmenuOpen, activateItem, focusHoveredItem, selectItem, openSubmenu, closeSubmenu, close }) {
|
|
660
1978
|
const renderedItems = computed(() => getRenderedItems(items.value));
|
|
661
1979
|
function getRenderedItems(dropdownItems, parentPath = []) {
|
|
662
1980
|
return dropdownItems.map((item, index) => {
|
|
@@ -697,9 +2015,9 @@ function useDropdownMenuRenderItems({ items, getItemId, getSubmenuId, getMenuAct
|
|
|
697
2015
|
"aria-expanded": hasSubmenu ? resolvedSubmenuOpen : void 0,
|
|
698
2016
|
"aria-haspopup": hasSubmenu ? "menu" : void 0,
|
|
699
2017
|
"aria-disabled": disabled || void 0,
|
|
700
|
-
"data-disabled": disabled
|
|
701
|
-
"data-
|
|
702
|
-
"data-submenu": hasSubmenu
|
|
2018
|
+
"data-disabled": disabled ? "" : void 0,
|
|
2019
|
+
"data-highlighted": focused ? "" : void 0,
|
|
2020
|
+
"data-submenu": hasSubmenu ? "" : void 0,
|
|
703
2021
|
onClick: (event) => activateItem(item, path, event),
|
|
704
2022
|
onMouseenter: (event) => focusHoveredItem(item, path, event)
|
|
705
2023
|
};
|
|
@@ -742,7 +2060,13 @@ function useDropdownMenuRenderItems({ items, getItemId, getSubmenuId, getMenuAct
|
|
|
742
2060
|
isSubmenuOpen,
|
|
743
2061
|
getItemProps,
|
|
744
2062
|
getSubmenuProps,
|
|
745
|
-
getItemSlotProps
|
|
2063
|
+
getItemSlotProps,
|
|
2064
|
+
getItemElement,
|
|
2065
|
+
getSubmenuPlacement: () => actualPlacement.value.endsWith("end") ? "left-start" : "right-start",
|
|
2066
|
+
getStrategy: () => props.strategy ?? "absolute",
|
|
2067
|
+
getFlip: () => props.flip !== false,
|
|
2068
|
+
getShift: () => props.shift !== false,
|
|
2069
|
+
getCollisionPadding: () => props.collisionPadding ?? 8
|
|
746
2070
|
},
|
|
747
2071
|
getItemProps,
|
|
748
2072
|
getItemSlotProps
|
|
@@ -794,16 +2118,32 @@ function useDropdownSubmenus({ focusedPath, getItemAtPath, focusItem }) {
|
|
|
794
2118
|
function useDropdownMenu(props, emit = {}) {
|
|
795
2119
|
const rootRef = ref(null);
|
|
796
2120
|
const menuRef = ref(null);
|
|
2121
|
+
const arrowRef = ref(null);
|
|
797
2122
|
const uncontrolledOpen = ref(false);
|
|
798
2123
|
const generatedId = useId();
|
|
799
2124
|
const menuId = computed(() => props.id ?? `${generatedId}-menu`);
|
|
800
2125
|
const placement = computed(() => props.placement ?? "bottom-start");
|
|
2126
|
+
const requestedTeleportTarget = computed(() => props.portalTo ?? props.teleportTo);
|
|
2127
|
+
const teleportTo = useTeleportTarget(() => requestedTeleportTarget.value);
|
|
2128
|
+
const shouldTeleport = computed(() => props.portal ?? props.teleport !== false);
|
|
2129
|
+
const { isExplicitTarget, reference, resolvedTarget } = useFloatingTarget(() => props.target, rootRef);
|
|
2130
|
+
const targetElement = computed(() => isElementReference(resolvedTarget.value) ? resolvedTarget.value : null);
|
|
801
2131
|
const visibleItems = computed(() => props.items ?? []);
|
|
802
2132
|
const isDisabled = computed(() => Boolean(props.disabled));
|
|
803
2133
|
const isOpen = computed(() => props.open ?? uncontrolledOpen.value);
|
|
804
2134
|
const isVisible = computed(() => isOpen.value && !isDisabled.value);
|
|
805
2135
|
const contentHasSubmenu = computed(() => hasNestedItems(visibleItems.value));
|
|
806
2136
|
const isEmpty = computed(() => visibleItems.value.length === 0);
|
|
2137
|
+
const { actualPlacement, arrowStyle, contentStyle } = useDropdownMenuPortalPosition({
|
|
2138
|
+
props,
|
|
2139
|
+
reference,
|
|
2140
|
+
menuRef,
|
|
2141
|
+
arrowRef,
|
|
2142
|
+
isVisible,
|
|
2143
|
+
placement,
|
|
2144
|
+
restartKey: () => [shouldTeleport.value, teleportTo.value]
|
|
2145
|
+
});
|
|
2146
|
+
const placementSide = computed(() => actualPlacement.value.split("-")[0]);
|
|
807
2147
|
const { focusedPath, focusedIndex, getItemAtPath, focusItem, resetFocus, isItemFocused, moveFocus } = useDropdownMenuNavigation(visibleItems);
|
|
808
2148
|
const submenus = useDropdownSubmenus({
|
|
809
2149
|
focusedPath,
|
|
@@ -815,7 +2155,8 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
815
2155
|
menuId,
|
|
816
2156
|
rootRef,
|
|
817
2157
|
menuRef,
|
|
818
|
-
|
|
2158
|
+
targetRef: targetElement,
|
|
2159
|
+
placement: actualPlacement,
|
|
819
2160
|
focusedPath
|
|
820
2161
|
});
|
|
821
2162
|
const hoverIntent = useDropdownMenuHoverIntent({
|
|
@@ -827,6 +2168,8 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
827
2168
|
props,
|
|
828
2169
|
emit,
|
|
829
2170
|
rootRef,
|
|
2171
|
+
menuRef,
|
|
2172
|
+
targetRef: targetElement,
|
|
830
2173
|
uncontrolledOpen,
|
|
831
2174
|
isDisabled,
|
|
832
2175
|
isOpen,
|
|
@@ -855,7 +2198,8 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
855
2198
|
isSubmenuOpeningLeft
|
|
856
2199
|
});
|
|
857
2200
|
const rootClass = computed(() => bem("rp-dropdown-menu", {
|
|
858
|
-
[`placement-${
|
|
2201
|
+
[`placement-${actualPlacement.value}`]: true,
|
|
2202
|
+
target: isExplicitTarget.value,
|
|
859
2203
|
open: isVisible.value,
|
|
860
2204
|
disabled: isDisabled.value
|
|
861
2205
|
}));
|
|
@@ -886,10 +2230,13 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
886
2230
|
toggle
|
|
887
2231
|
}));
|
|
888
2232
|
const { renderedItems, renderContext, getItemProps, getItemSlotProps } = useDropdownMenuRenderItems({
|
|
2233
|
+
props,
|
|
2234
|
+
actualPlacement,
|
|
889
2235
|
items: visibleItems,
|
|
890
2236
|
getItemId,
|
|
891
2237
|
getSubmenuId,
|
|
892
2238
|
getMenuActiveDescendant,
|
|
2239
|
+
getItemElement,
|
|
893
2240
|
isItemFocused,
|
|
894
2241
|
isSubmenuOpen,
|
|
895
2242
|
activateItem,
|
|
@@ -899,9 +2246,49 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
899
2246
|
closeSubmenu,
|
|
900
2247
|
close
|
|
901
2248
|
});
|
|
2249
|
+
watch([isExplicitTarget, targetElement], ([explicit, target], _previous, onCleanup) => {
|
|
2250
|
+
if (!explicit || !target) return;
|
|
2251
|
+
target.addEventListener("click", onTriggerClick);
|
|
2252
|
+
target.addEventListener("keydown", onTriggerKeydown);
|
|
2253
|
+
onCleanup(() => {
|
|
2254
|
+
target.removeEventListener("click", onTriggerClick);
|
|
2255
|
+
target.removeEventListener("keydown", onTriggerKeydown);
|
|
2256
|
+
});
|
|
2257
|
+
}, { flush: "sync" });
|
|
2258
|
+
watch([
|
|
2259
|
+
isExplicitTarget,
|
|
2260
|
+
targetElement,
|
|
2261
|
+
menuId,
|
|
2262
|
+
isVisible,
|
|
2263
|
+
isDisabled
|
|
2264
|
+
], ([explicit, target, id, visible, disabled], _previous, onCleanup) => {
|
|
2265
|
+
if (!explicit || !target) return;
|
|
2266
|
+
const snapshot = new Map([
|
|
2267
|
+
"aria-controls",
|
|
2268
|
+
"aria-expanded",
|
|
2269
|
+
"aria-haspopup",
|
|
2270
|
+
"aria-disabled"
|
|
2271
|
+
].map((attribute) => [attribute, target.getAttribute(attribute)]));
|
|
2272
|
+
if (disabled) {
|
|
2273
|
+
target.removeAttribute("aria-controls");
|
|
2274
|
+
target.removeAttribute("aria-expanded");
|
|
2275
|
+
target.removeAttribute("aria-haspopup");
|
|
2276
|
+
target.setAttribute("aria-disabled", "true");
|
|
2277
|
+
} else {
|
|
2278
|
+
target.setAttribute("aria-controls", id);
|
|
2279
|
+
target.setAttribute("aria-expanded", String(visible));
|
|
2280
|
+
target.setAttribute("aria-haspopup", "menu");
|
|
2281
|
+
target.removeAttribute("aria-disabled");
|
|
2282
|
+
}
|
|
2283
|
+
onCleanup(() => {
|
|
2284
|
+
for (const [attribute, value] of snapshot) if (value == null) target.removeAttribute(attribute);
|
|
2285
|
+
else target.setAttribute(attribute, value);
|
|
2286
|
+
});
|
|
2287
|
+
}, { flush: "sync" });
|
|
902
2288
|
return {
|
|
903
2289
|
rootRef,
|
|
904
2290
|
menuRef,
|
|
2291
|
+
arrowRef,
|
|
905
2292
|
menuId,
|
|
906
2293
|
isVisible,
|
|
907
2294
|
isEmpty,
|
|
@@ -913,6 +2300,13 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
913
2300
|
activeDescendantId,
|
|
914
2301
|
rootClass,
|
|
915
2302
|
contentClass,
|
|
2303
|
+
contentStyle,
|
|
2304
|
+
arrowStyle,
|
|
2305
|
+
actualPlacement,
|
|
2306
|
+
placementSide,
|
|
2307
|
+
isTargetMode: isExplicitTarget,
|
|
2308
|
+
teleportTo,
|
|
2309
|
+
shouldTeleport,
|
|
916
2310
|
triggerProps,
|
|
917
2311
|
contentProps,
|
|
918
2312
|
slotProps,
|
|
@@ -931,22 +2325,22 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
931
2325
|
}
|
|
932
2326
|
//#endregion
|
|
933
2327
|
//#region src/components/dropdown-menu/dropdown-menu.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
934
|
-
var t0 = template("
|
|
935
|
-
var t1 = template("
|
|
936
|
-
var t2 = template("<
|
|
937
|
-
var t3 = template("<
|
|
938
|
-
var t4 = template("<
|
|
939
|
-
var t5 = template("<
|
|
2328
|
+
var t0 = template("<span class=rp-dropdown-menu__arrow aria-hidden=true>");
|
|
2329
|
+
var t1 = template("No actions", 2);
|
|
2330
|
+
var t2 = template("<div>");
|
|
2331
|
+
var t3 = template("<span> </span>");
|
|
2332
|
+
var t4 = template("<kbd> ");
|
|
2333
|
+
var t5 = template("<span>");
|
|
940
2334
|
var t6 = template("<span>", 1);
|
|
941
2335
|
//#endregion
|
|
942
2336
|
//#region src/components/dropdown-menu/dropdown-menu.vue
|
|
943
2337
|
var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
944
2338
|
name: "RpDropdownMenu",
|
|
2339
|
+
inheritAttrs: false,
|
|
945
2340
|
__name: "dropdown-menu",
|
|
946
2341
|
props: {
|
|
947
2342
|
id: {},
|
|
948
2343
|
items: { default: () => [] },
|
|
949
|
-
placement: { default: "bottom-start" },
|
|
950
2344
|
open: {
|
|
951
2345
|
type: Boolean,
|
|
952
2346
|
default: void 0
|
|
@@ -959,64 +2353,171 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
959
2353
|
type: Boolean,
|
|
960
2354
|
default: true
|
|
961
2355
|
},
|
|
962
|
-
ariaLabel: {}
|
|
2356
|
+
ariaLabel: {},
|
|
2357
|
+
modal: {
|
|
2358
|
+
type: Boolean,
|
|
2359
|
+
default: false
|
|
2360
|
+
},
|
|
2361
|
+
portal: {
|
|
2362
|
+
type: Boolean,
|
|
2363
|
+
default: void 0
|
|
2364
|
+
},
|
|
2365
|
+
portalTo: {},
|
|
2366
|
+
target: {},
|
|
2367
|
+
placement: { default: "bottom-start" },
|
|
2368
|
+
strategy: { default: "absolute" },
|
|
2369
|
+
offset: {},
|
|
2370
|
+
flip: {
|
|
2371
|
+
type: Boolean,
|
|
2372
|
+
default: true
|
|
2373
|
+
},
|
|
2374
|
+
shift: {
|
|
2375
|
+
type: Boolean,
|
|
2376
|
+
default: true
|
|
2377
|
+
},
|
|
2378
|
+
collisionPadding: { default: 8 },
|
|
2379
|
+
arrow: {
|
|
2380
|
+
type: Boolean,
|
|
2381
|
+
default: false
|
|
2382
|
+
},
|
|
2383
|
+
teleport: {
|
|
2384
|
+
type: Boolean,
|
|
2385
|
+
default: true
|
|
2386
|
+
},
|
|
2387
|
+
teleportTo: {},
|
|
2388
|
+
classNames: {},
|
|
2389
|
+
styles: {}
|
|
963
2390
|
},
|
|
964
2391
|
emits: ["update:open", "select"],
|
|
965
2392
|
setup(__props, { emit: __emit }) {
|
|
966
2393
|
const props = __props;
|
|
967
2394
|
const emit = __emit;
|
|
968
|
-
const { rootRef, menuRef, isVisible, isEmpty, visibleItems, renderContext, rootClass, contentClass, contentProps, slotProps } = useDropdownMenu(props, {
|
|
2395
|
+
const { rootRef, menuRef, arrowRef, isVisible, isEmpty, visibleItems, renderContext, rootClass, contentClass, contentStyle, arrowStyle, placementSide, isTargetMode, teleportTo, shouldTeleport, contentProps, slotProps } = useDropdownMenu(props, {
|
|
969
2396
|
openChange: (open) => emit("update:open", open),
|
|
970
|
-
select: (item) => emit("select", item)
|
|
2397
|
+
select: (item, event) => emit("select", item, event)
|
|
2398
|
+
});
|
|
2399
|
+
const { getPartAttrs, getRootAttrs } = useStylesApi(props, "root");
|
|
2400
|
+
const state = computed(() => isVisible.value ? "open" : "closed");
|
|
2401
|
+
const rootAttrs = computed(() => getRootAttrs({
|
|
2402
|
+
class: rootClass.value,
|
|
2403
|
+
"data-state": state.value,
|
|
2404
|
+
"data-disabled": presence(props.disabled)
|
|
2405
|
+
}));
|
|
2406
|
+
const publicSlotProps = computed(() => {
|
|
2407
|
+
const partAttrs = getPartAttrs("trigger");
|
|
2408
|
+
return {
|
|
2409
|
+
...slotProps.value,
|
|
2410
|
+
triggerProps: {
|
|
2411
|
+
...slotProps.value.triggerProps,
|
|
2412
|
+
...props.classNames?.trigger !== void 0 ? { class: partAttrs.class } : {},
|
|
2413
|
+
...props.styles?.trigger !== void 0 ? { style: partAttrs.style } : {},
|
|
2414
|
+
"data-state": state.value,
|
|
2415
|
+
"data-disabled": presence(props.disabled)
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
971
2418
|
});
|
|
2419
|
+
const publicContentProps = computed(() => ({
|
|
2420
|
+
...contentProps.value,
|
|
2421
|
+
...getPartAttrs("content", {
|
|
2422
|
+
class: contentClass.value,
|
|
2423
|
+
style: contentStyle.value
|
|
2424
|
+
}),
|
|
2425
|
+
"data-state": state.value,
|
|
2426
|
+
"data-placement": placementSide.value
|
|
2427
|
+
}));
|
|
2428
|
+
const publicRenderContext = computed(() => ({
|
|
2429
|
+
...renderContext,
|
|
2430
|
+
getPublicPartAttrs: getPartAttrs
|
|
2431
|
+
}));
|
|
972
2432
|
const _setTemplateRef = createTemplateRefSetter();
|
|
973
|
-
const
|
|
974
|
-
renderEffect(() =>
|
|
975
|
-
setInsertionState(
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
2433
|
+
const n29 = t6();
|
|
2434
|
+
renderEffect(() => setDynamicProps(n29, [rootAttrs.value]));
|
|
2435
|
+
setInsertionState(n29, null, 0);
|
|
2436
|
+
createIf(() => !unref(isTargetMode), () => {
|
|
2437
|
+
return createSlot("default", { $: [() => publicSlotProps.value] });
|
|
2438
|
+
});
|
|
2439
|
+
setInsertionState(n29, null, 1);
|
|
2440
|
+
createComponent(VaporTeleport, {
|
|
2441
|
+
to: () => unref(teleportTo),
|
|
2442
|
+
disabled: () => !unref(shouldTeleport)
|
|
2443
|
+
}, () => {
|
|
2444
|
+
return createComponent(VaporTransition, { name: "rp-dropdown-menu-content" }, extend(() => {
|
|
2445
|
+
return createIf(() => unref(isVisible), () => {
|
|
2446
|
+
const n26 = t2();
|
|
2447
|
+
renderEffect(() => setDynamicProps(n26, [publicContentProps.value, { "data-side": unref(placementSide) }]));
|
|
2448
|
+
setInsertionState(n26, null, 0);
|
|
2449
|
+
createIf(() => __props.arrow, () => {
|
|
2450
|
+
const n7 = t0();
|
|
2451
|
+
_setTemplateRef(n7, arrowRef, null, "arrowRef");
|
|
2452
|
+
renderEffect(() => {
|
|
2453
|
+
setAttr(n7, "data-side", unref(placementSide));
|
|
2454
|
+
setStyle(n7, unref(arrowStyle));
|
|
2455
|
+
});
|
|
2456
|
+
return n7;
|
|
988
2457
|
});
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
2458
|
+
setInsertionState(n26, null, 1);
|
|
2459
|
+
createIf(() => unref(isEmpty), () => {
|
|
2460
|
+
const n13 = t2();
|
|
2461
|
+
renderEffect(() => setDynamicProps(n13, [unref(getPartAttrs)("empty", { class: "rp-dropdown-menu__empty" })]));
|
|
2462
|
+
setInsertionState(n13, null, 0);
|
|
2463
|
+
createSlot("empty", null, () => {
|
|
2464
|
+
return t1();
|
|
2465
|
+
});
|
|
2466
|
+
return n13;
|
|
2467
|
+
});
|
|
2468
|
+
setInsertionState(n26, null, 2);
|
|
2469
|
+
createComponent(unref(dropdown_menu_items_default), {
|
|
2470
|
+
items: () => unref(visibleItems),
|
|
2471
|
+
context: () => publicRenderContext.value
|
|
2472
|
+
}, { "item": extend((itemSlotProps) => {
|
|
2473
|
+
return [createSlot("item", { $: [() => itemSlotProps] }, () => {
|
|
2474
|
+
const n16 = t3();
|
|
2475
|
+
const x16 = txt(n16);
|
|
2476
|
+
renderEffect(() => {
|
|
2477
|
+
setDynamicProps(n16, [unref(getPartAttrs)("label", { class: "rp-dropdown-menu__label" })]);
|
|
2478
|
+
setText(x16, toDisplayString(itemSlotProps.item.label));
|
|
2479
|
+
});
|
|
2480
|
+
return [n16, createIf(() => itemSlotProps.item.shortcut, () => {
|
|
2481
|
+
const n19 = t4();
|
|
2482
|
+
const x19 = txt(n19);
|
|
2483
|
+
renderEffect(() => {
|
|
2484
|
+
setDynamicProps(n19, [unref(getPartAttrs)("shortcut", { class: "rp-dropdown-menu__shortcut" })]);
|
|
2485
|
+
setText(x19, toDisplayString(itemSlotProps.item.shortcut));
|
|
2486
|
+
});
|
|
2487
|
+
return n19;
|
|
2488
|
+
}, null, 129)];
|
|
2489
|
+
}), createIf(() => itemSlotProps.hasSubmenu, () => {
|
|
2490
|
+
const n23 = t5();
|
|
2491
|
+
renderEffect(() => setDynamicProps(n23, [unref(getPartAttrs)("submenuIndicator", { class: "rp-dropdown-menu__submenu-icon" }), { "aria-hidden": "true" }]));
|
|
2492
|
+
setInsertionState(n23, null, 0);
|
|
2493
|
+
createComponent(unref(chevron_right_default));
|
|
2494
|
+
return n23;
|
|
1005
2495
|
}, null, 129)];
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
return n21;
|
|
1015
|
-
}, null, 129);
|
|
1016
|
-
}, { _: 8 }));
|
|
1017
|
-
setStaticTemplateRef(n23, rootRef, null, "rootRef");
|
|
1018
|
-
return n23;
|
|
2496
|
+
}, { _: 8 }) });
|
|
2497
|
+
_setTemplateRef(n26, menuRef, null, "menuRef");
|
|
2498
|
+
return n26;
|
|
2499
|
+
}, null, 129);
|
|
2500
|
+
}, { _: 8 }));
|
|
2501
|
+
});
|
|
2502
|
+
setStaticTemplateRef(n29, rootRef, null, "rootRef");
|
|
2503
|
+
return n29;
|
|
1019
2504
|
}
|
|
1020
2505
|
});
|
|
1021
2506
|
//#endregion
|
|
1022
|
-
|
|
2507
|
+
//#region src/components/dropdown-menu/types.ts
|
|
2508
|
+
var dropdownMenuParts = [
|
|
2509
|
+
"root",
|
|
2510
|
+
"trigger",
|
|
2511
|
+
"content",
|
|
2512
|
+
"item",
|
|
2513
|
+
"label",
|
|
2514
|
+
"shortcut",
|
|
2515
|
+
"submenu",
|
|
2516
|
+
"submenuIndicator",
|
|
2517
|
+
"empty"
|
|
2518
|
+
];
|
|
2519
|
+
//#endregion
|
|
2520
|
+
//#region src/components/dropdown-menu/index.ts
|
|
2521
|
+
var DropdownMenuItem = DropdownMenuItem$1;
|
|
2522
|
+
//#endregion
|
|
2523
|
+
export { DropdownMenuSubTrigger as _, DropdownMenuCheckboxItem as a, DropdownMenuItemIndicator as c, DropdownMenuRadioGroup as d, DropdownMenuRadioItem as f, DropdownMenuSubContent as g, DropdownMenuSub as h, useDropdownMenu as i, DropdownMenuLabel as l, DropdownMenuSeparator as m, dropdownMenuParts as n, DropdownMenuContent as o, DropdownMenuRoot as p, dropdown_menu_default as r, DropdownMenuContextTrigger as s, DropdownMenuItem as t, DropdownMenuPortal as u, DropdownMenuTrigger as v };
|