ropav 0.1.5 → 0.1.7
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 +10 -0
- package/dist/accordion.css +17 -17
- package/dist/accordion.js +125 -154
- package/dist/alert.css +18 -18
- package/dist/alert.js +20 -20
- package/dist/aria.js +14 -0
- package/dist/aspect-ratio.js +1 -1
- package/dist/attributes.js +9 -0
- package/dist/attributes2.js +29 -0
- package/dist/avatar.css +19 -19
- package/dist/avatar.js +10 -18
- package/dist/badge.css +16 -16
- package/dist/badge.js +6 -6
- package/dist/base.css +18 -13
- package/dist/button-group.js +1 -1
- package/dist/button-link.js +13 -14
- package/dist/button.css +32 -27
- package/dist/button.js +13 -14
- package/dist/{useButtonColor.js → button.scss_vue_type_style_index_0_src_true_lang.js} +3 -2
- package/dist/card.js +1 -1
- package/dist/checkbox.css +32 -32
- package/dist/checkbox.js +23 -29
- package/dist/collapse.css +6 -6
- package/dist/collapse.js +8 -7
- package/dist/collectionNavigation.js +2 -99
- package/dist/color-input.css +19 -19
- package/dist/color-input.js +15 -14
- package/dist/color-picker.css +40 -40
- package/dist/color-picker.js +222 -202
- package/dist/color-picker2.js +1 -9
- package/dist/color-swatch.css +4 -4
- package/dist/color-swatch.js +7 -9
- package/dist/color.js +5 -10
- package/dist/componentColors.js +165 -84
- package/dist/componentRef.js +26 -0
- package/dist/components/accordion/accordionContext.d.ts +3 -0
- package/dist/components/accordion/accordionModel.d.ts +14 -0
- package/dist/components/accordion/index.d.ts +2 -1
- package/dist/components/accordion/index.js +1 -1
- package/dist/components/accordion/types.d.ts +1 -2
- package/dist/components/accordion/useAccordion.d.ts +2 -2
- package/dist/components/accordion/useAccordionItem.d.ts +2 -0
- package/dist/components/checkbox/useCheckbox.d.ts +2 -3
- package/dist/components/color-input/color-input.d.ts +2 -2
- package/dist/components/color-input/useColorInput.d.ts +1 -1
- package/dist/components/color-picker/index.js +2 -2
- package/dist/components/color-picker/types.d.ts +2 -2
- package/dist/components/color-picker/useColorPickerSaturation.d.ts +22 -0
- package/dist/components/color-picker/useColorPickerSlider.d.ts +20 -0
- package/dist/components/color-picker/useColorPickerValue.d.ts +1 -1
- package/dist/components/dialog/{dialog-core.d.ts → dialogContext.d.ts} +2 -6
- package/dist/components/dialog/useDialogContentInteractions.d.ts +18 -0
- package/dist/components/dialog/useDialogRootState.d.ts +19 -0
- package/dist/components/dropdown-menu/dropdown-menu-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu-item-row.d.ts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu-items.d.ts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu-model.d.ts +8 -0
- package/dist/components/dropdown-menu/dropdown-menu-root.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu-sub-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu-sub-trigger.d.ts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu-sub.d.ts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +3 -3
- package/dist/components/dropdown-menu/{dropdown-menu-primitive-core.d.ts → dropdownMenuContext.d.ts} +17 -19
- package/dist/components/dropdown-menu/dropdownMenuDataModel.d.ts +20 -0
- package/dist/components/dropdown-menu/dropdownMenuInteraction.d.ts +3 -0
- package/dist/components/dropdown-menu/dropdownMenuInteractionNavigation.d.ts +24 -0
- package/dist/components/dropdown-menu/dropdownMenuInteractionRegistry.d.ts +42 -0
- package/dist/components/dropdown-menu/dropdownMenuInteractionTypes.d.ts +85 -0
- package/dist/components/dropdown-menu/useDropdownMenu.d.ts +11 -11
- package/dist/components/dropdown-menu/useDropdownMenuContextTrigger.d.ts +9 -0
- package/dist/components/dropdown-menu/useDropdownMenuDataController.d.ts +34 -0
- package/dist/components/dropdown-menu/useDropdownMenuDataRegistration.d.ts +22 -0
- package/dist/components/dropdown-menu/useDropdownMenuHoverIntent.d.ts +6 -5
- package/dist/components/dropdown-menu/useDropdownMenuInteractionDismissal.d.ts +17 -0
- package/dist/components/dropdown-menu/useDropdownMenuInteractionKeyboard.d.ts +19 -0
- package/dist/components/dropdown-menu/useDropdownMenuPortalPosition.d.ts +0 -1
- package/dist/components/dropdown-menu/useDropdownMenuPresentation.d.ts +29 -0
- package/dist/components/dropdown-menu/useDropdownMenuPrimitiveContent.d.ts +2 -2
- package/dist/components/dropdown-menu/useDropdownMenuRenderItems.d.ts +1 -1
- package/dist/components/dropdown-menu/useDropdownMenuTargetBindings.d.ts +19 -0
- package/dist/components/floating/hoverDisclosureInteractionModel.d.ts +42 -0
- package/dist/components/floating/index.js +1 -1
- package/dist/components/floating/useFloatingPosition.d.ts +0 -1
- package/dist/components/floating/useHoverDisclosureInteractions.d.ts +32 -0
- package/dist/components/floating/useHoverDisclosureOpenState.d.ts +25 -0
- package/dist/components/floating/useHoverDisclosureTargetBinding.d.ts +27 -0
- package/dist/components/input/useInput.d.ts +1 -1
- package/dist/components/number-input/numberInputModel.d.ts +15 -0
- package/dist/components/number-input/useNumberInput.d.ts +4 -18
- package/dist/components/pagination/index.d.ts +1 -1
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/pagination/paginationModel.d.ts +4 -0
- package/dist/components/pagination/types.d.ts +15 -0
- package/dist/components/pagination/usePagination.d.ts +3 -19
- package/dist/components/popover/usePopoverBindings.d.ts +16 -0
- package/dist/components/progress/progressModel.d.ts +8 -0
- package/dist/components/progress/useProgress.d.ts +1 -7
- package/dist/components/radio/useRadio.d.ts +3 -4
- package/dist/components/scroll-area/scroll-area.d.ts +1 -1
- package/dist/components/scroll-area/scrollAreaModel.d.ts +64 -0
- package/dist/components/scroll-area/types.d.ts +4 -0
- package/dist/components/scroll-area/useScrollArea.d.ts +70 -52
- package/dist/components/scroll-area/{useScrollAreaPresentation.d.ts → useScrollAreaAttributes.d.ts} +37 -14
- package/dist/components/scroll-area/useScrollAreaDerivedState.d.ts +8 -0
- package/dist/components/scroll-area/useScrollAreaMeasurement.d.ts +35 -0
- package/dist/components/scroll-area/useScrollAreaPointer.d.ts +10 -8
- package/dist/components/scroll-area/useScrollAreaVisibility.d.ts +15 -20
- package/dist/components/select/useSelect.d.ts +2 -1
- package/dist/components/select/useSelectNativeValue.d.ts +1 -7
- package/dist/components/slider/rangeSliderModel.d.ts +41 -0
- package/dist/components/slider/{sliderCore.d.ts → sliderModel.d.ts} +2 -2
- package/dist/components/slider/useRangeSlider.d.ts +9 -17
- package/dist/components/slider/useRangeSliderValueState.d.ts +40 -0
- package/dist/components/slider/useSlider.d.ts +8 -14
- package/dist/components/slider/useSliderPointerPreview.d.ts +22 -0
- package/dist/components/slider/useSliderTooltipState.d.ts +40 -0
- package/dist/components/slider/useSliderValueState.d.ts +33 -0
- package/dist/components/switch/useSwitch.d.ts +1 -1
- package/dist/components/teleport-provider/index.js +1 -1
- package/dist/components/teleport-provider/useTeleportTarget.d.ts +1 -2
- package/dist/components/textarea/useTextarea.d.ts +1 -1
- package/dist/components/toast/useToastLifecycle.d.ts +19 -0
- package/dist/components/tooltip/useTooltip.d.ts +1 -2
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.js +2 -0
- package/dist/composables/useControllableValue.d.ts +14 -0
- package/dist/css.js +12 -0
- package/dist/dialog.js +227 -216
- package/dist/dropdown-menu.js +1493 -1118
- package/dist/events.js +59 -0
- package/dist/field.css +8 -8
- package/dist/field.js +13 -25
- package/dist/floating.js +553 -312
- package/dist/floatingOffset.js +11 -0
- package/dist/focus-trap.js +7 -5
- package/dist/focusNavigation.js +37 -0
- package/dist/icon-button.css +12 -173
- package/dist/icon-button.js +8 -7
- package/dist/index.d.ts +5 -4
- package/dist/index.js +13 -11
- package/dist/input.css +24 -24
- package/dist/input.js +20 -32
- package/dist/interactive.js +18 -0
- package/dist/modal.js +11 -7
- package/dist/number-input.css +18 -18
- package/dist/number-input.js +15 -13
- package/dist/number.js +22 -0
- package/dist/overlay.js +3 -2
- package/dist/pagination.css +28 -28
- package/dist/pagination.js +67 -65
- package/dist/pointer.js +9 -0
- package/dist/popover.css +34 -34
- package/dist/popover.js +93 -91
- package/dist/progress.css +29 -21
- package/dist/progress.js +25 -21
- package/dist/query.js +40 -0
- package/dist/radio.css +18 -18
- package/dist/radio.js +31 -37
- package/dist/rafScheduler.js +34 -0
- package/dist/scroll-area.css +35 -26
- package/dist/scroll-area.js +553 -500
- package/dist/select.css +45 -45
- package/dist/select.js +70 -56
- package/dist/slider.css +191 -191
- package/dist/slider.js +695 -628
- package/dist/styles-api.d.ts +0 -1
- package/dist/styles-api.js +1 -4
- package/dist/switch.css +17 -17
- package/dist/switch.js +15 -16
- package/dist/tabs.css +46 -46
- package/dist/tabs.js +51 -68
- package/dist/text.js +17 -0
- package/dist/textarea.css +26 -26
- package/dist/textarea.js +22 -33
- package/dist/toast.css +26 -26
- package/dist/toast.js +157 -129
- package/dist/tooltip.css +12 -12
- package/dist/tooltip.js +46 -47
- package/dist/useCollapse.js +19 -17
- package/dist/useControlState.js +4 -7
- package/dist/useControllableValue.js +8 -2
- package/dist/useFloatingPosition.js +122 -1128
- package/dist/useFormControl.js +3 -2
- package/dist/useOverlayZIndex.js +2 -6
- package/dist/useRequiredInject.js +1 -1
- package/dist/useTeleportTarget.js +3 -14
- package/dist/useTypeahead.js +94 -0
- package/dist/utils/aria.d.ts +3 -0
- package/dist/utils/attributes.d.ts +2 -0
- package/dist/utils/bem.d.ts +3 -0
- package/dist/utils/collectionNavigation.d.ts +2 -0
- package/dist/utils/color.d.ts +7 -0
- package/dist/{components/color-picker/color-picker-utils.d.ts → utils/colorPicker.d.ts} +5 -4
- package/dist/utils/componentColors.d.ts +7 -0
- package/dist/utils/css.d.ts +3 -0
- package/dist/utils/dom/ancestry.d.ts +7 -0
- package/dist/utils/dom/attributes.d.ts +16 -0
- package/dist/utils/dom/componentRef.d.ts +4 -0
- package/dist/utils/dom/events.d.ts +5 -0
- package/dist/utils/dom/focusNavigation.d.ts +7 -0
- package/dist/utils/dom/interactive.d.ts +2 -0
- package/dist/utils/dom/pointer.d.ts +2 -0
- package/dist/utils/dom/query.d.ts +4 -0
- package/dist/utils/dom/scroll.d.ts +23 -0
- package/dist/utils/floatingOffset.d.ts +10 -0
- package/dist/utils/geometry.d.ts +14 -0
- package/dist/utils/indexPath.d.ts +6 -0
- package/dist/utils/number.d.ts +4 -0
- package/dist/utils/rafScheduler.d.ts +4 -0
- package/dist/utils/text.d.ts +2 -0
- package/docs/code-architecture.md +118 -0
- package/docs/public-composables-api.md +52 -0
- package/docs/public-floating-api.md +6 -5
- package/package.json +54 -46
- package/src/styles/_mixins.scss +4 -0
- package/src/styles/_tokens.scss +12 -12
- package/src/styles/_variables.scss +1 -1
- package/dist/button-link.css +0 -167
- package/dist/components/dropdown-menu/dropdown-menu-outside.d.ts +0 -3
- package/dist/components/dropdown-menu/dropdown-menu-utils.d.ts +0 -21
- package/dist/components/dropdown-menu/useDropdownMenuDisclosure.d.ts +0 -37
- package/dist/components/dropdown-menu/useDropdownMenuDom.d.ts +0 -29
- package/dist/components/dropdown-menu/useDropdownMenuInteractions.d.ts +0 -52
- package/dist/components/dropdown-menu/useDropdownMenuNavigation.d.ts +0 -17
- package/dist/components/dropdown-menu/useDropdownSubmenus.d.ts +0 -18
- package/dist/components/scroll-area/scrollAreaCore.d.ts +0 -25
- package/dist/components/scroll-area/useScrollAreaControls.d.ts +0 -25
- package/dist/components/scroll-area/useScrollAreaMetrics.d.ts +0 -35
- /package/dist/components/alert/{useAlertColor.d.ts → alertColor.d.ts} +0 -0
- /package/dist/components/avatar/{useAvatarColor.d.ts → avatarColor.d.ts} +0 -0
- /package/dist/components/badge/{useBadgeColor.d.ts → badgeColor.d.ts} +0 -0
- /package/dist/components/button/{useButtonColor.d.ts → buttonColor.d.ts} +0 -0
- /package/dist/components/color-swatch/{useColorSwatchColor.d.ts → colorSwatchColor.d.ts} +0 -0
- /package/dist/components/toast/{useToastColor.d.ts → toastColor.d.ts} +0 -0
- /package/dist/{composables → internal/composables}/useOverlayLayer.d.ts +0 -0
package/dist/dropdown-menu.js
CHANGED
|
@@ -1,40 +1,49 @@
|
|
|
1
1
|
import './dropdown-menu.css';
|
|
2
|
+
import { t as useControllableValue } from "./useControllableValue.js";
|
|
3
|
+
import { t as useStylesApi } from "./styles-api.js";
|
|
4
|
+
import { n as toPresenceAttribute, t as toOptionalAttribute } from "./attributes.js";
|
|
2
5
|
import { t as bem } from "./bem.js";
|
|
3
|
-
import {
|
|
6
|
+
import { t as isElement } from "./query.js";
|
|
4
7
|
import { t as useRequiredInject } from "./useRequiredInject.js";
|
|
8
|
+
import { t as clamp } from "./number.js";
|
|
9
|
+
import { a as snapshotAttributes, i as restoreAttributes } from "./attributes2.js";
|
|
10
|
+
import { t as resolveHTMLElementRef } from "./componentRef.js";
|
|
11
|
+
import { n as isEventWithinElement, r as isEventWithinTargets, t as createCancelableCustomEvent } from "./events.js";
|
|
5
12
|
import { n as useOverlayZIndex, r as useOverlayLayer } from "./useOverlayZIndex.js";
|
|
6
|
-
import { n as
|
|
7
|
-
import { n as
|
|
8
|
-
import {
|
|
13
|
+
import { n as useFloatingTarget, t as useFloatingPosition } from "./useFloatingPosition.js";
|
|
14
|
+
import { n as useTeleportTarget, t as provideTeleportTarget } from "./useTeleportTarget.js";
|
|
15
|
+
import { t as useTypeahead } from "./useTypeahead.js";
|
|
9
16
|
import { t as chevron_right_default } from "./chevron-right.js";
|
|
10
|
-
import { VaporTeleport, VaporTransition, child, computed, createComponent, createComponentWithFallback, createDynamicComponent, createFor, createIf, createSlot, createTemplateRefSetter, defineVaporComponent, extend, isRef, mergeProps, nextTick, onBeforeUnmount, onMounted, onUnmounted, provide, ref, renderEffect, resolveComponent, setAttr, setDynamicProps, setInsertionState,
|
|
11
|
-
//#region src/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function optionalAttr(value) {
|
|
18
|
-
return value || void 0;
|
|
17
|
+
import { VaporTeleport, VaporTransition, child, computed, createComponent, createComponentWithFallback, createDynamicComponent, createFor, createIf, createSlot, createTemplateRefSetter, defineVaporComponent, extend, isRef, mergeProps, nextTick, onBeforeUnmount, onMounted, onUnmounted, provide, ref, renderEffect, resolveComponent, setAttr, setDynamicProps, setInsertionState, setStyle, setTemplateRefBinding, setText, shallowRef, template, toDisplayString, txt, unref, useAttrs, useId, watch } from "vue";
|
|
18
|
+
//#region src/utils/geometry.ts
|
|
19
|
+
function getClientPoint(event) {
|
|
20
|
+
return {
|
|
21
|
+
x: event.clientX,
|
|
22
|
+
y: event.clientY
|
|
23
|
+
};
|
|
19
24
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
function hasMeasuredRect(rect) {
|
|
26
|
+
return rect.width > 0 || rect.height > 0;
|
|
27
|
+
}
|
|
28
|
+
function isPointInRect(point, rect, padding = 0) {
|
|
29
|
+
return point.x >= rect.left - padding && point.x <= rect.right + padding && point.y >= rect.top - padding && point.y <= rect.bottom + padding;
|
|
23
30
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
function getTriangleArea(a, b, c) {
|
|
32
|
+
return Math.abs((a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2);
|
|
33
|
+
}
|
|
34
|
+
function isPointInTriangle(point, triangle, tolerance = .5) {
|
|
35
|
+
const [a, b, c] = triangle;
|
|
36
|
+
const area = getTriangleArea(a, b, c);
|
|
37
|
+
const area1 = getTriangleArea(point, b, c);
|
|
38
|
+
const area2 = getTriangleArea(a, point, c);
|
|
39
|
+
const area3 = getTriangleArea(a, b, point);
|
|
40
|
+
return Math.abs(area - (area1 + area2 + area3)) < tolerance;
|
|
32
41
|
}
|
|
33
|
-
function
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
function clampPointToRect(point, rect) {
|
|
43
|
+
return {
|
|
44
|
+
x: clamp(point.x, rect.left, rect.right),
|
|
45
|
+
y: clamp(point.y, rect.top, rect.bottom)
|
|
46
|
+
};
|
|
38
47
|
}
|
|
39
48
|
function createPointRect(point) {
|
|
40
49
|
return {
|
|
@@ -49,202 +58,72 @@ function createPointRect(point) {
|
|
|
49
58
|
toJSON: () => ({})
|
|
50
59
|
};
|
|
51
60
|
}
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/components/dropdown-menu/dropdownMenuContext.ts
|
|
63
|
+
var rootKey = Symbol("dropdown-menu-root");
|
|
64
|
+
var menuKey = Symbol("dropdown-menu-content");
|
|
65
|
+
var subKey = Symbol("dropdown-menu-sub");
|
|
66
|
+
var radioGroupKey = Symbol("dropdown-menu-radio-group");
|
|
67
|
+
var checkedKey = Symbol("dropdown-menu-checked");
|
|
52
68
|
function createVirtualAnchor(point) {
|
|
53
69
|
return { getBoundingClientRect: () => createPointRect(point) };
|
|
54
70
|
}
|
|
55
|
-
function createCustomEvent(type, detail, originalEvent) {
|
|
56
|
-
const target = originalEvent.target;
|
|
57
|
-
return new (((target instanceof Node ? target.ownerDocument?.defaultView : null)?.CustomEvent) ?? CustomEvent)(type, {
|
|
58
|
-
bubbles: false,
|
|
59
|
-
cancelable: true,
|
|
60
|
-
detail
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
71
|
function createSelectEvent(originalEvent, value) {
|
|
64
|
-
return
|
|
72
|
+
return createCancelableCustomEvent("dropdown-menu-select", {
|
|
65
73
|
originalEvent,
|
|
66
74
|
value
|
|
67
75
|
}, originalEvent);
|
|
68
76
|
}
|
|
69
|
-
function createOutsideEvent(originalEvent) {
|
|
70
|
-
return createCustomEvent("dropdown-menu-interact-outside", { originalEvent }, originalEvent);
|
|
71
|
-
}
|
|
72
|
-
function sortItems(items) {
|
|
73
|
-
return [...items].sort((left, right) => {
|
|
74
|
-
const leftElement = left.element();
|
|
75
|
-
const rightElement = right.element();
|
|
76
|
-
if (!leftElement || !rightElement || leftElement === rightElement) return 0;
|
|
77
|
-
const position = leftElement.compareDocumentPosition(rightElement);
|
|
78
|
-
if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
|
|
79
|
-
if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
|
80
|
-
return 0;
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function getPlacementSide(placement) {
|
|
84
|
-
return placement.split("-")[0];
|
|
85
|
-
}
|
|
86
|
-
function getOpenDirection(sub) {
|
|
87
|
-
return getPlacementSide(sub.actualPlacement.value) === "left" ? "ArrowLeft" : "ArrowRight";
|
|
88
|
-
}
|
|
89
|
-
function getCloseDirection(menu) {
|
|
90
|
-
return getPlacementSide(menu.actualPlacement.value) === "left" ? "ArrowRight" : "ArrowLeft";
|
|
91
|
-
}
|
|
92
|
-
function blockDocumentClick(event) {
|
|
93
|
-
if (event.cancelable) event.preventDefault();
|
|
94
|
-
event.stopPropagation();
|
|
95
|
-
document.removeEventListener("click", blockDocumentClick, true);
|
|
96
|
-
}
|
|
97
|
-
function blockNextDocumentClick() {
|
|
98
|
-
if (typeof document === "undefined") return;
|
|
99
|
-
document.addEventListener("click", blockDocumentClick, true);
|
|
100
|
-
window.setTimeout(() => document.removeEventListener("click", blockDocumentClick, true), 1e3);
|
|
101
|
-
}
|
|
102
77
|
function createMenuContext(options) {
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
item.element()?.scrollIntoView?.({ block: "nearest" });
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function unregisterItem(id) {
|
|
120
|
-
items.value = items.value.filter((item) => item.id !== id);
|
|
121
|
-
if (activeId.value === id) activeId.value = null;
|
|
122
|
-
}
|
|
123
|
-
function registerSub(sub) {
|
|
124
|
-
submenus.add(sub);
|
|
125
|
-
}
|
|
126
|
-
function unregisterSub(sub) {
|
|
127
|
-
submenus.delete(sub);
|
|
128
|
-
}
|
|
129
|
-
function closeSubmenus(except) {
|
|
130
|
-
for (const submenu of submenus) if (submenu !== except) submenu.close(false);
|
|
131
|
-
}
|
|
132
|
-
function setActive(id) {
|
|
133
|
-
const item = items.value.find((current) => current.id === id);
|
|
134
|
-
if (!item || item.disabled()) return;
|
|
135
|
-
activeId.value = id;
|
|
136
|
-
nextTick(() => item.element()?.scrollIntoView?.({ block: "nearest" }));
|
|
137
|
-
}
|
|
138
|
-
function focus(target = "first") {
|
|
139
|
-
const enabledItems = getEnabledItems();
|
|
140
|
-
const item = target === "last" ? enabledItems[enabledItems.length - 1] : enabledItems[0];
|
|
141
|
-
if (!item) {
|
|
142
|
-
activeId.value = null;
|
|
143
|
-
options.element.value?.focus();
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
activeId.value = item.id;
|
|
147
|
-
options.element.value?.focus();
|
|
148
|
-
item.element()?.scrollIntoView?.({ block: "nearest" });
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
function focusElement() {
|
|
152
|
-
options.element.value?.focus();
|
|
153
|
-
}
|
|
154
|
-
function move(direction) {
|
|
155
|
-
const enabledItems = getEnabledItems();
|
|
156
|
-
if (enabledItems.length === 0) return;
|
|
157
|
-
const currentIndex = enabledItems.findIndex((item) => item.id === activeId.value);
|
|
158
|
-
const item = enabledItems[((currentIndex < 0 ? direction === 1 ? -1 : 0 : currentIndex) + direction + enabledItems.length) % enabledItems.length];
|
|
159
|
-
if (item) setActive(item.id);
|
|
160
|
-
}
|
|
161
|
-
const typeahead = useTypeahead({
|
|
162
|
-
items: () => sortItems(items.value),
|
|
163
|
-
activeIndex: () => sortItems(items.value).findIndex((item) => item.id === activeId.value),
|
|
164
|
-
getKey: (item) => item.id,
|
|
165
|
-
getTextValue: (item) => item.textValue(),
|
|
166
|
-
isDisabled: (item) => item.disabled(),
|
|
167
|
-
onMatch: (item) => setActive(item.id)
|
|
78
|
+
const id = options.parentSub?.menuId ?? options.root.interaction.rootMenuId;
|
|
79
|
+
const interaction = options.root.interaction;
|
|
80
|
+
const activeId = interaction.getActiveId(id);
|
|
81
|
+
const cleanupMenu = interaction.registerMenu({
|
|
82
|
+
id,
|
|
83
|
+
parentItemId: () => options.parentSub?.trigger.value?.id,
|
|
84
|
+
element: () => options.element.value,
|
|
85
|
+
placement: () => options.actualPlacement.value,
|
|
86
|
+
isOpen: () => options.parentSub?.isOpen.value ?? options.root.isOpen.value,
|
|
87
|
+
setOpen: options.parentSub?.setOpen,
|
|
88
|
+
stopKeyPropagation: true,
|
|
89
|
+
onEscape: options.onEscape
|
|
168
90
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
function onKeydown(event) {
|
|
185
|
-
if (typeahead.handleKey(event)) {
|
|
186
|
-
event.stopPropagation();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const active = items.value.find((item) => item.id === activeId.value);
|
|
190
|
-
switch (event.key) {
|
|
191
|
-
case "ArrowDown":
|
|
192
|
-
event.preventDefault();
|
|
193
|
-
event.stopPropagation();
|
|
194
|
-
move(1);
|
|
195
|
-
break;
|
|
196
|
-
case "ArrowUp":
|
|
197
|
-
event.preventDefault();
|
|
198
|
-
event.stopPropagation();
|
|
199
|
-
move(-1);
|
|
200
|
-
break;
|
|
201
|
-
case "Home":
|
|
202
|
-
event.preventDefault();
|
|
203
|
-
event.stopPropagation();
|
|
204
|
-
focus("first");
|
|
205
|
-
break;
|
|
206
|
-
case "End":
|
|
207
|
-
event.preventDefault();
|
|
208
|
-
event.stopPropagation();
|
|
209
|
-
focus("last");
|
|
210
|
-
break;
|
|
211
|
-
case "ArrowRight":
|
|
212
|
-
case "ArrowLeft":
|
|
213
|
-
onHorizontalKeydown(event, active);
|
|
214
|
-
break;
|
|
215
|
-
case "Enter":
|
|
216
|
-
case " ":
|
|
217
|
-
event.preventDefault();
|
|
218
|
-
event.stopPropagation();
|
|
219
|
-
active?.activate(event);
|
|
220
|
-
break;
|
|
221
|
-
case "Escape":
|
|
222
|
-
event.preventDefault();
|
|
223
|
-
event.stopPropagation();
|
|
224
|
-
options.onEscape(event);
|
|
225
|
-
break;
|
|
226
|
-
case "Tab":
|
|
227
|
-
options.root.close({ returnFocus: false });
|
|
228
|
-
break;
|
|
229
|
-
}
|
|
91
|
+
function registerItem(item) {
|
|
92
|
+
interaction.registerItem({
|
|
93
|
+
get id() {
|
|
94
|
+
return item.id;
|
|
95
|
+
},
|
|
96
|
+
menuId: id,
|
|
97
|
+
element: item.element,
|
|
98
|
+
textValue: item.textValue,
|
|
99
|
+
disabled: item.disabled,
|
|
100
|
+
submenuId: () => item.submenu?.menuId,
|
|
101
|
+
submenuDirection: () => item.submenu?.actualPlacement.value.startsWith("left") ? "left" : "right",
|
|
102
|
+
select: item.activate,
|
|
103
|
+
closeOnSelect: item.closeOnSelect
|
|
104
|
+
});
|
|
230
105
|
}
|
|
231
106
|
const context = {
|
|
232
107
|
root: options.root,
|
|
108
|
+
id,
|
|
233
109
|
element: options.element,
|
|
234
110
|
activeId,
|
|
235
111
|
actualPlacement: options.actualPlacement,
|
|
236
112
|
parentSub: options.parentSub,
|
|
237
113
|
registerItem,
|
|
238
|
-
unregisterItem,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
isActive:
|
|
244
|
-
focus,
|
|
245
|
-
focusElement,
|
|
246
|
-
|
|
114
|
+
unregisterItem: interaction.unregisterItem,
|
|
115
|
+
closeSubmenus: (except) => interaction.closeSubmenus(id, except?.menuId),
|
|
116
|
+
setActive: (itemId) => {
|
|
117
|
+
interaction.setActive(itemId);
|
|
118
|
+
},
|
|
119
|
+
isActive: interaction.isActive,
|
|
120
|
+
focus: (target = "first") => interaction.focusMenu(id, target),
|
|
121
|
+
focusElement: () => interaction.focusMenuElement(id),
|
|
122
|
+
activate: interaction.activateItem,
|
|
123
|
+
hover: interaction.hoverItem,
|
|
124
|
+
onKeydown: (event) => interaction.onMenuKeydown(id, event)
|
|
247
125
|
};
|
|
126
|
+
onBeforeUnmount(cleanupMenu);
|
|
248
127
|
return context;
|
|
249
128
|
}
|
|
250
129
|
function usePrimitiveItem(componentName, props, emitSelect, options) {
|
|
@@ -254,12 +133,12 @@ function usePrimitiveItem(componentName, props, emitSelect, options) {
|
|
|
254
133
|
const element = ref(null);
|
|
255
134
|
const isDisabled = computed(() => Boolean(menu.root.disabled.value || props.disabled));
|
|
256
135
|
const focused = computed(() => menu.isActive(id.value));
|
|
257
|
-
function
|
|
258
|
-
if (isDisabled.value) return;
|
|
136
|
+
function emitSelection(originalEvent) {
|
|
137
|
+
if (isDisabled.value) return void 0;
|
|
259
138
|
const selectEvent = createSelectEvent(originalEvent, props.value);
|
|
260
139
|
emitSelect(selectEvent);
|
|
261
140
|
options.afterSelect?.();
|
|
262
|
-
|
|
141
|
+
return selectEvent;
|
|
263
142
|
}
|
|
264
143
|
const registration = {
|
|
265
144
|
get id() {
|
|
@@ -268,27 +147,33 @@ function usePrimitiveItem(componentName, props, emitSelect, options) {
|
|
|
268
147
|
element: () => element.value,
|
|
269
148
|
textValue: () => props.textValue ?? element.value?.textContent?.trim() ?? "",
|
|
270
149
|
disabled: () => isDisabled.value,
|
|
271
|
-
activate
|
|
150
|
+
activate: emitSelection,
|
|
151
|
+
closeOnSelect: () => props.closeOnSelect ?? options.defaultCloseOnSelect
|
|
272
152
|
};
|
|
273
153
|
menu.registerItem(registration);
|
|
274
154
|
watch(id, (nextId, previousId) => {
|
|
155
|
+
const wasActive = menu.activeId.value === previousId;
|
|
275
156
|
menu.unregisterItem(previousId);
|
|
276
157
|
menu.registerItem(registration);
|
|
277
|
-
if (
|
|
278
|
-
});
|
|
158
|
+
if (wasActive) menu.setActive(nextId);
|
|
159
|
+
}, { flush: "sync" });
|
|
160
|
+
watch(isDisabled, () => menu.root.interaction.reconcile(menu.id));
|
|
279
161
|
onBeforeUnmount(() => menu.unregisterItem(id.value));
|
|
280
162
|
function setElement(value) {
|
|
281
163
|
resolveHTMLElementRef(value, id.value, (resolved) => {
|
|
282
164
|
element.value = resolved;
|
|
165
|
+
menu.root.interaction.reconcile(menu.id);
|
|
283
166
|
});
|
|
284
167
|
}
|
|
168
|
+
function activate(originalEvent) {
|
|
169
|
+
menu.activate(id.value, originalEvent);
|
|
170
|
+
}
|
|
285
171
|
function onPointerenter() {
|
|
286
172
|
if (isDisabled.value) return;
|
|
287
|
-
menu.
|
|
288
|
-
menu.setActive(id.value);
|
|
173
|
+
menu.hover(id.value);
|
|
289
174
|
}
|
|
290
175
|
function select() {
|
|
291
|
-
activate(new Event("select"));
|
|
176
|
+
menu.activate(id.value, new Event("select"));
|
|
292
177
|
}
|
|
293
178
|
return {
|
|
294
179
|
menu,
|
|
@@ -339,14 +224,17 @@ var dropdown_menu_checkbox_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
339
224
|
const props = __props;
|
|
340
225
|
const emit = __emit;
|
|
341
226
|
const attrs = useAttrs();
|
|
342
|
-
const
|
|
343
|
-
|
|
227
|
+
const controllable = useControllableValue({
|
|
228
|
+
modelValue: () => props.modelValue,
|
|
229
|
+
defaultValue: () => props.defaultValue,
|
|
230
|
+
onChange: (value) => emit("update:modelValue", value)
|
|
231
|
+
});
|
|
232
|
+
const value = controllable.value;
|
|
344
233
|
const checked = computed(() => value.value === "indeterminate" ? "mixed" : value.value);
|
|
345
234
|
const state = computed(() => value.value === "indeterminate" ? "indeterminate" : value.value ? "checked" : "unchecked");
|
|
346
235
|
function toggleChecked() {
|
|
347
236
|
const nextValue = value.value === "indeterminate" ? true : !value.value;
|
|
348
|
-
|
|
349
|
-
emit("update:modelValue", nextValue);
|
|
237
|
+
controllable.setValue(nextValue);
|
|
350
238
|
}
|
|
351
239
|
provide(checkedKey, {
|
|
352
240
|
state,
|
|
@@ -365,12 +253,12 @@ var dropdown_menu_checkbox_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
365
253
|
type: props.as === "button" ? "button" : void 0,
|
|
366
254
|
role: "menuitemcheckbox",
|
|
367
255
|
tabindex: -1,
|
|
368
|
-
disabled: props.as === "button" ?
|
|
369
|
-
"aria-disabled":
|
|
256
|
+
disabled: props.as === "button" ? toOptionalAttribute(isDisabled.value) : void 0,
|
|
257
|
+
"aria-disabled": toOptionalAttribute(isDisabled.value),
|
|
370
258
|
"aria-checked": checked.value,
|
|
371
|
-
"data-disabled":
|
|
372
|
-
"data-focused":
|
|
373
|
-
"data-highlighted":
|
|
259
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
260
|
+
"data-focused": toOptionalAttribute(focused.value),
|
|
261
|
+
"data-highlighted": toOptionalAttribute(focused.value),
|
|
374
262
|
"data-state": state.value,
|
|
375
263
|
class: bem("rp-dropdown-menu__item", {
|
|
376
264
|
focused: focused.value,
|
|
@@ -392,31 +280,6 @@ var dropdown_menu_checkbox_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
392
280
|
}
|
|
393
281
|
});
|
|
394
282
|
//#endregion
|
|
395
|
-
//#region src/components/dropdown-menu/dropdown-menu-outside.ts
|
|
396
|
-
function isNode(value) {
|
|
397
|
-
return typeof value === "object" && value !== null && "nodeType" in value;
|
|
398
|
-
}
|
|
399
|
-
function isEventWithinElement(event, element) {
|
|
400
|
-
const path = event.composedPath();
|
|
401
|
-
if (path.length > 0) return path.some((entry) => entry === element || isNode(entry) && element.contains(entry));
|
|
402
|
-
return isNode(event.target) && element.contains(event.target);
|
|
403
|
-
}
|
|
404
|
-
function isEventWithinTargets(event, targets) {
|
|
405
|
-
for (const source of targets) {
|
|
406
|
-
const target = isRef(source) ? source.value : source;
|
|
407
|
-
if (!target) continue;
|
|
408
|
-
if (typeof target === "string") {
|
|
409
|
-
if (typeof document === "undefined") continue;
|
|
410
|
-
try {
|
|
411
|
-
if ([...document.querySelectorAll(target)].some((element) => isEventWithinElement(event, element))) return true;
|
|
412
|
-
} catch {}
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (isEventWithinElement(event, target)) return true;
|
|
416
|
-
}
|
|
417
|
-
return false;
|
|
418
|
-
}
|
|
419
|
-
//#endregion
|
|
420
283
|
//#region src/components/dropdown-menu/useDropdownMenuPrimitiveContent.ts
|
|
421
284
|
function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
422
285
|
const componentName = submenu ? "RpDropdownMenuSubContent" : "RpDropdownMenuContent";
|
|
@@ -430,20 +293,23 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
|
430
293
|
const actualPlacement = ref(props.placement ?? defaultPlacement);
|
|
431
294
|
const isOpen = computed(() => sub ? sub.isOpen.value : root.isOpen.value);
|
|
432
295
|
const reference = computed(() => sub ? sub.trigger.value : root.reference.value);
|
|
433
|
-
const teleportPositioningKey = useTeleportPositioningKey();
|
|
434
296
|
const menu = createMenuContext({
|
|
435
297
|
root,
|
|
436
298
|
element,
|
|
437
299
|
actualPlacement,
|
|
438
300
|
parentSub: sub,
|
|
439
301
|
onEscape(event) {
|
|
440
|
-
const customEvent =
|
|
302
|
+
const customEvent = createCancelableCustomEvent("dropdown-menu-escape-key-down", { originalEvent: event }, event);
|
|
441
303
|
events.escapeKeyDown(customEvent);
|
|
442
|
-
|
|
443
|
-
if (sub) sub.close(true);
|
|
444
|
-
else root.close({ returnFocus: true });
|
|
304
|
+
return !customEvent.defaultPrevented;
|
|
445
305
|
}
|
|
446
306
|
});
|
|
307
|
+
const cleanupDismissal = submenu ? void 0 : root.interaction.registerDismissal({
|
|
308
|
+
ignoredTargets: () => props.ignore ?? [],
|
|
309
|
+
pointerDownOutside: events.pointerDownOutside,
|
|
310
|
+
focusOutside: events.focusOutside,
|
|
311
|
+
interactOutside: events.interactOutside
|
|
312
|
+
});
|
|
447
313
|
const floating = useFloatingPosition({
|
|
448
314
|
reference,
|
|
449
315
|
floating: element,
|
|
@@ -456,8 +322,7 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
|
456
322
|
flipOptions: () => props.flipOptions,
|
|
457
323
|
shift: () => props.shift !== false,
|
|
458
324
|
collisionPadding: () => props.collisionPadding ?? 8,
|
|
459
|
-
autoUpdateOptions: () => props.autoUpdateOptions
|
|
460
|
-
restartKey: teleportPositioningKey
|
|
325
|
+
autoUpdateOptions: () => props.autoUpdateOptions
|
|
461
326
|
});
|
|
462
327
|
watch(floating.actualPlacement, (value) => {
|
|
463
328
|
actualPlacement.value = value;
|
|
@@ -478,44 +343,9 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
|
478
343
|
else if (resolved) layerBranchCleanup = root.layer.registerBranch(resolved);
|
|
479
344
|
});
|
|
480
345
|
}
|
|
481
|
-
function emitOutside(type, originalEvent) {
|
|
482
|
-
const outsideEvent = createOutsideEvent(originalEvent);
|
|
483
|
-
if (type === "pointer") events.pointerDownOutside(outsideEvent);
|
|
484
|
-
else events.focusOutside(outsideEvent);
|
|
485
|
-
events.interactOutside(outsideEvent);
|
|
486
|
-
return outsideEvent;
|
|
487
|
-
}
|
|
488
|
-
function onDocumentPointer(event) {
|
|
489
|
-
if (!root.layer.isTopLayer() || root.isInside(event) || isEventWithinTargets(event, props.ignore ?? [])) return;
|
|
490
|
-
const outsideEvent = emitOutside("pointer", event);
|
|
491
|
-
if (root.modal.value) {
|
|
492
|
-
if (event.cancelable) event.preventDefault();
|
|
493
|
-
event.stopPropagation();
|
|
494
|
-
if (event.type === "pointerdown") blockNextDocumentClick();
|
|
495
|
-
}
|
|
496
|
-
if (!outsideEvent.defaultPrevented) root.close({ returnFocus: root.modal.value });
|
|
497
|
-
}
|
|
498
|
-
function onDocumentFocus(event) {
|
|
499
|
-
if (!root.layer.isTopLayer() || root.isInside(event) || isEventWithinTargets(event, props.ignore ?? [])) return;
|
|
500
|
-
const outsideEvent = emitOutside("focus", event);
|
|
501
|
-
if (root.modal.value) {
|
|
502
|
-
if (event.cancelable) event.preventDefault();
|
|
503
|
-
event.stopPropagation();
|
|
504
|
-
}
|
|
505
|
-
if (!outsideEvent.defaultPrevented) root.close({ returnFocus: root.modal.value });
|
|
506
|
-
else if (root.modal.value) nextTick(menu.focusElement);
|
|
507
|
-
}
|
|
508
|
-
function setDocumentListeners(active) {
|
|
509
|
-
if (submenu || typeof document === "undefined") return;
|
|
510
|
-
const method = active ? "addEventListener" : "removeEventListener";
|
|
511
|
-
document[method]("pointerdown", onDocumentPointer, true);
|
|
512
|
-
document[method]("focusin", onDocumentFocus, true);
|
|
513
|
-
}
|
|
514
346
|
watch(isOpen, (open) => {
|
|
515
|
-
setDocumentListeners(open);
|
|
516
347
|
if (!open) {
|
|
517
|
-
menu.
|
|
518
|
-
menu.closeSubmenus();
|
|
348
|
+
if (sub) root.interaction.closeMenu(menu.id, false);
|
|
519
349
|
return;
|
|
520
350
|
}
|
|
521
351
|
nextTick(() => {
|
|
@@ -532,7 +362,7 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
|
532
362
|
if (isOpen.value) menu.focus((sub ? sub.pendingFocus.value : root.pendingFocus.value) || "first");
|
|
533
363
|
});
|
|
534
364
|
onBeforeUnmount(() => {
|
|
535
|
-
|
|
365
|
+
cleanupDismissal?.();
|
|
536
366
|
layerBranchCleanup?.();
|
|
537
367
|
if (element.value) root.unregisterInside(element.value);
|
|
538
368
|
if (!sub && root.layer.element.value === element.value) root.layer.element.value = null;
|
|
@@ -545,7 +375,7 @@ function useDropdownMenuPrimitiveContent(props, attrs, events, submenu) {
|
|
|
545
375
|
id: id.value,
|
|
546
376
|
role: "menu",
|
|
547
377
|
tabindex: -1,
|
|
548
|
-
hidden:
|
|
378
|
+
hidden: toOptionalAttribute(!isOpen.value),
|
|
549
379
|
class: submenu ? bem("rp-dropdown-menu__submenu", {
|
|
550
380
|
compound: true,
|
|
551
381
|
open: isOpen.value
|
|
@@ -640,15 +470,16 @@ var dropdown_menu_content_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
640
470
|
focusOutside: (event) => emit("focusOutside", event),
|
|
641
471
|
interactOutside: (event) => emit("interactOutside", event)
|
|
642
472
|
}, false);
|
|
473
|
+
const templateRefs = { arrow: arrowElement };
|
|
643
474
|
const _setTemplateRef = createTemplateRefSetter();
|
|
644
475
|
return createIf(() => unref(shouldRender), () => {
|
|
645
476
|
const n6 = createDynamicComponent(() => __props.as, { $: [() => unref(rootAttrs)] }, extend(() => {
|
|
646
477
|
return [createIf(() => __props.arrow, () => {
|
|
647
478
|
const n4 = t0$2();
|
|
648
|
-
_setTemplateRef(n4, arrowElement, null, "arrowElement");
|
|
649
479
|
renderEffect(() => {
|
|
650
480
|
setAttr(n4, "data-side", unref(placementSide));
|
|
651
481
|
setStyle(n4, unref(floating).arrowStyle.value);
|
|
482
|
+
_setTemplateRef(n4, templateRefs.arrow);
|
|
652
483
|
});
|
|
653
484
|
return n4;
|
|
654
485
|
}, null, 129), createSlot("default", {
|
|
@@ -663,6 +494,117 @@ var dropdown_menu_content_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
663
494
|
}
|
|
664
495
|
});
|
|
665
496
|
//#endregion
|
|
497
|
+
//#region src/components/dropdown-menu/useDropdownMenuContextTrigger.ts
|
|
498
|
+
function useDropdownMenuContextTrigger(props) {
|
|
499
|
+
const attrs = useAttrs();
|
|
500
|
+
const root = useRequiredInject(rootKey, "RpDropdownMenuContextTrigger");
|
|
501
|
+
const generatedId = useId();
|
|
502
|
+
const id = computed(() => props.id ?? `${generatedId}-context-trigger`);
|
|
503
|
+
const element = ref(null);
|
|
504
|
+
const isDisabled = computed(() => root.disabled.value || props.disabled);
|
|
505
|
+
let timer;
|
|
506
|
+
let pointerId;
|
|
507
|
+
let startPoint;
|
|
508
|
+
let longPressOpened = false;
|
|
509
|
+
let suppressUntil = 0;
|
|
510
|
+
function setElement(value) {
|
|
511
|
+
resolveHTMLElementRef(value, id.value, (resolved) => {
|
|
512
|
+
const previous = element.value;
|
|
513
|
+
if (previous) root.unregisterInside(previous);
|
|
514
|
+
element.value = resolved;
|
|
515
|
+
if (resolved) root.registerInside(resolved);
|
|
516
|
+
if (!root.triggerId.value) root.triggerId.value = id.value;
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function clearLongPress() {
|
|
520
|
+
if (timer) clearTimeout(timer);
|
|
521
|
+
timer = void 0;
|
|
522
|
+
pointerId = void 0;
|
|
523
|
+
startPoint = void 0;
|
|
524
|
+
element.value?.ownerDocument.defaultView?.removeEventListener("scroll", clearLongPress, true);
|
|
525
|
+
}
|
|
526
|
+
function openAt(point) {
|
|
527
|
+
root.setReturnFocus(element.value);
|
|
528
|
+
root.openAt(point);
|
|
529
|
+
}
|
|
530
|
+
function onContextmenu(event) {
|
|
531
|
+
if (isDisabled.value) return;
|
|
532
|
+
event.preventDefault();
|
|
533
|
+
if (Date.now() < suppressUntil) return;
|
|
534
|
+
openAt({
|
|
535
|
+
x: event.clientX,
|
|
536
|
+
y: event.clientY
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
function onKeydown(event) {
|
|
540
|
+
if (isDisabled.value) return;
|
|
541
|
+
if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
|
|
542
|
+
event.preventDefault();
|
|
543
|
+
const rect = element.value?.getBoundingClientRect();
|
|
544
|
+
openAt({
|
|
545
|
+
x: rect?.left ?? 0,
|
|
546
|
+
y: rect?.bottom ?? 0
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
function onPointerdown(event) {
|
|
550
|
+
if (isDisabled.value || event.pointerType !== "touch" && event.pointerType !== "pen") return;
|
|
551
|
+
clearLongPress();
|
|
552
|
+
pointerId = event.pointerId;
|
|
553
|
+
startPoint = {
|
|
554
|
+
x: event.clientX,
|
|
555
|
+
y: event.clientY
|
|
556
|
+
};
|
|
557
|
+
longPressOpened = false;
|
|
558
|
+
(element.value?.ownerDocument.defaultView)?.addEventListener("scroll", clearLongPress, true);
|
|
559
|
+
timer = setTimeout(() => {
|
|
560
|
+
if (!startPoint) return;
|
|
561
|
+
longPressOpened = true;
|
|
562
|
+
suppressUntil = Date.now() + 1e3;
|
|
563
|
+
openAt(startPoint);
|
|
564
|
+
timer = void 0;
|
|
565
|
+
}, props.longPressDelay);
|
|
566
|
+
}
|
|
567
|
+
function onPointermove(event) {
|
|
568
|
+
if (event.pointerId !== pointerId || !startPoint) return;
|
|
569
|
+
if (Math.hypot(event.clientX - startPoint.x, event.clientY - startPoint.y) > (props.longPressTolerance ?? 0)) clearLongPress();
|
|
570
|
+
}
|
|
571
|
+
function finishPointer(event) {
|
|
572
|
+
if (event.pointerId !== pointerId) return;
|
|
573
|
+
if (longPressOpened) event.preventDefault();
|
|
574
|
+
clearLongPress();
|
|
575
|
+
}
|
|
576
|
+
function onClick(event) {
|
|
577
|
+
if (Date.now() >= suppressUntil) return;
|
|
578
|
+
event.preventDefault();
|
|
579
|
+
event.stopPropagation();
|
|
580
|
+
}
|
|
581
|
+
const rootAttrs = computed(() => mergeProps(attrs, {
|
|
582
|
+
id: id.value,
|
|
583
|
+
"aria-controls": root.contentId.value,
|
|
584
|
+
"aria-haspopup": "menu",
|
|
585
|
+
"aria-disabled": toOptionalAttribute(isDisabled.value),
|
|
586
|
+
"data-state": root.isOpen.value ? "open" : "closed",
|
|
587
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
588
|
+
onClick,
|
|
589
|
+
onContextmenu,
|
|
590
|
+
onKeydown,
|
|
591
|
+
onPointerdown,
|
|
592
|
+
onPointermove,
|
|
593
|
+
onPointerup: finishPointer,
|
|
594
|
+
onPointercancel: finishPointer
|
|
595
|
+
}));
|
|
596
|
+
onBeforeUnmount(() => {
|
|
597
|
+
clearLongPress();
|
|
598
|
+
if (element.value) root.unregisterInside(element.value);
|
|
599
|
+
if (root.triggerId.value === id.value) root.triggerId.value = void 0;
|
|
600
|
+
});
|
|
601
|
+
return {
|
|
602
|
+
isOpen: root.isOpen,
|
|
603
|
+
rootAttrs,
|
|
604
|
+
setElement
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
//#endregion
|
|
666
608
|
//#region src/components/dropdown-menu/dropdown-menu-context-trigger.vue
|
|
667
609
|
var dropdown_menu_context_trigger_default = /* @__PURE__ */ defineVaporComponent({
|
|
668
610
|
name: "RpDropdownMenuContextTrigger",
|
|
@@ -679,114 +621,11 @@ var dropdown_menu_context_trigger_default = /* @__PURE__ */ defineVaporComponent
|
|
|
679
621
|
longPressTolerance: { default: 10 }
|
|
680
622
|
},
|
|
681
623
|
setup(__props) {
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
const generatedId = useId();
|
|
686
|
-
const id = computed(() => props.id ?? `${generatedId}-context-trigger`);
|
|
687
|
-
const element = ref(null);
|
|
688
|
-
const isDisabled = computed(() => root.disabled.value || props.disabled);
|
|
689
|
-
let timer;
|
|
690
|
-
let pointerId;
|
|
691
|
-
let startPoint;
|
|
692
|
-
let longPressOpened = false;
|
|
693
|
-
let suppressUntil = 0;
|
|
694
|
-
function setElement(value) {
|
|
695
|
-
resolveHTMLElementRef(value, id.value, (resolved) => {
|
|
696
|
-
const previous = element.value;
|
|
697
|
-
if (previous) root.unregisterInside(previous);
|
|
698
|
-
element.value = resolved;
|
|
699
|
-
if (resolved) root.registerInside(resolved);
|
|
700
|
-
if (!root.triggerId.value) root.triggerId.value = id.value;
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
function clearLongPress() {
|
|
704
|
-
if (timer) clearTimeout(timer);
|
|
705
|
-
timer = void 0;
|
|
706
|
-
pointerId = void 0;
|
|
707
|
-
startPoint = void 0;
|
|
708
|
-
element.value?.ownerDocument.defaultView?.removeEventListener("scroll", clearLongPress, true);
|
|
709
|
-
}
|
|
710
|
-
function openAt(point) {
|
|
711
|
-
root.setReturnFocus(element.value);
|
|
712
|
-
root.openAt(point);
|
|
713
|
-
}
|
|
714
|
-
function onContextmenu(event) {
|
|
715
|
-
if (isDisabled.value) return;
|
|
716
|
-
event.preventDefault();
|
|
717
|
-
if (Date.now() < suppressUntil) return;
|
|
718
|
-
openAt({
|
|
719
|
-
x: event.clientX,
|
|
720
|
-
y: event.clientY
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
function onKeydown(event) {
|
|
724
|
-
if (isDisabled.value) return;
|
|
725
|
-
if (event.key !== "ContextMenu" && !(event.shiftKey && event.key === "F10")) return;
|
|
726
|
-
event.preventDefault();
|
|
727
|
-
const rect = element.value?.getBoundingClientRect();
|
|
728
|
-
openAt({
|
|
729
|
-
x: rect?.left ?? 0,
|
|
730
|
-
y: rect?.bottom ?? 0
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
function onPointerdown(event) {
|
|
734
|
-
if (isDisabled.value || event.pointerType !== "touch" && event.pointerType !== "pen") return;
|
|
735
|
-
clearLongPress();
|
|
736
|
-
pointerId = event.pointerId;
|
|
737
|
-
startPoint = {
|
|
738
|
-
x: event.clientX,
|
|
739
|
-
y: event.clientY
|
|
740
|
-
};
|
|
741
|
-
longPressOpened = false;
|
|
742
|
-
(element.value?.ownerDocument.defaultView)?.addEventListener("scroll", clearLongPress, true);
|
|
743
|
-
timer = setTimeout(() => {
|
|
744
|
-
if (!startPoint) return;
|
|
745
|
-
longPressOpened = true;
|
|
746
|
-
suppressUntil = Date.now() + 1e3;
|
|
747
|
-
openAt(startPoint);
|
|
748
|
-
timer = void 0;
|
|
749
|
-
}, props.longPressDelay);
|
|
750
|
-
}
|
|
751
|
-
function onPointermove(event) {
|
|
752
|
-
if (event.pointerId !== pointerId || !startPoint) return;
|
|
753
|
-
if (Math.hypot(event.clientX - startPoint.x, event.clientY - startPoint.y) > props.longPressTolerance) clearLongPress();
|
|
754
|
-
}
|
|
755
|
-
function finishPointer(event) {
|
|
756
|
-
if (event.pointerId !== pointerId) return;
|
|
757
|
-
if (longPressOpened) event.preventDefault();
|
|
758
|
-
clearLongPress();
|
|
759
|
-
}
|
|
760
|
-
function onClick(event) {
|
|
761
|
-
if (Date.now() >= suppressUntil) return;
|
|
762
|
-
event.preventDefault();
|
|
763
|
-
event.stopPropagation();
|
|
764
|
-
}
|
|
765
|
-
const rootAttrs = computed(() => mergeProps(attrs, {
|
|
766
|
-
id: id.value,
|
|
767
|
-
"aria-controls": root.contentId.value,
|
|
768
|
-
"aria-expanded": root.isOpen.value,
|
|
769
|
-
"aria-haspopup": "menu",
|
|
770
|
-
"aria-disabled": optionalAttr(isDisabled.value),
|
|
771
|
-
"data-state": root.isOpen.value ? "open" : "closed",
|
|
772
|
-
"data-disabled": optionalAttr(isDisabled.value),
|
|
773
|
-
onClick,
|
|
774
|
-
onContextmenu,
|
|
775
|
-
onKeydown,
|
|
776
|
-
onPointerdown,
|
|
777
|
-
onPointermove,
|
|
778
|
-
onPointerup: finishPointer,
|
|
779
|
-
onPointercancel: finishPointer
|
|
780
|
-
}));
|
|
781
|
-
onBeforeUnmount(() => {
|
|
782
|
-
clearLongPress();
|
|
783
|
-
if (element.value) root.unregisterInside(element.value);
|
|
784
|
-
if (root.triggerId.value === id.value) root.triggerId.value = void 0;
|
|
785
|
-
});
|
|
786
|
-
const n1 = createDynamicComponent(() => __props.as, { $: [() => rootAttrs.value] }, extend(() => {
|
|
787
|
-
return createSlot("default", { isOpen: () => unref(root).isOpen.value });
|
|
624
|
+
const { isOpen, rootAttrs, setElement } = useDropdownMenuContextTrigger(__props);
|
|
625
|
+
const n1 = createDynamicComponent(() => __props.as, { $: [() => unref(rootAttrs)] }, extend(() => {
|
|
626
|
+
return createSlot("default", { isOpen: () => unref(isOpen) });
|
|
788
627
|
}, { _: 8 }), 1);
|
|
789
|
-
setTemplateRefBinding(n1, () => setElement);
|
|
628
|
+
setTemplateRefBinding(n1, () => setElement, void 0, void 0, "setElement");
|
|
790
629
|
return n1;
|
|
791
630
|
}
|
|
792
631
|
});
|
|
@@ -828,11 +667,11 @@ var dropdown_menu_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
828
667
|
type: props.as === "button" ? "button" : void 0,
|
|
829
668
|
role: "menuitem",
|
|
830
669
|
tabindex: -1,
|
|
831
|
-
disabled: props.as === "button" ?
|
|
832
|
-
"aria-disabled":
|
|
833
|
-
"data-disabled":
|
|
834
|
-
"data-focused":
|
|
835
|
-
"data-highlighted":
|
|
670
|
+
disabled: props.as === "button" ? toOptionalAttribute(isDisabled.value) : void 0,
|
|
671
|
+
"aria-disabled": toOptionalAttribute(isDisabled.value),
|
|
672
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
673
|
+
"data-focused": toOptionalAttribute(focused.value),
|
|
674
|
+
"data-highlighted": toOptionalAttribute(focused.value),
|
|
836
675
|
class: bem("rp-dropdown-menu__item", {
|
|
837
676
|
focused: focused.value,
|
|
838
677
|
disabled: isDisabled.value,
|
|
@@ -928,7 +767,7 @@ var dropdown_menu_portal_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
928
767
|
const props = __props;
|
|
929
768
|
const teleportTo = provideTeleportTarget({ get teleportTo() {
|
|
930
769
|
return props.to ?? props.teleportTo;
|
|
931
|
-
} }
|
|
770
|
+
} });
|
|
932
771
|
return createComponent(VaporTeleport, {
|
|
933
772
|
to: () => unref(teleportTo),
|
|
934
773
|
disabled: () => __props.disabled || !__props.teleport
|
|
@@ -957,12 +796,17 @@ var dropdown_menu_radio_group_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
957
796
|
const emit = __emit;
|
|
958
797
|
const attrs = useAttrs();
|
|
959
798
|
useRequiredInject(menuKey, "RpDropdownMenuRadioGroup");
|
|
960
|
-
const
|
|
961
|
-
|
|
799
|
+
const controllable = useControllableValue({
|
|
800
|
+
modelValue: () => props.modelValue,
|
|
801
|
+
defaultValue: () => props.defaultValue,
|
|
802
|
+
onChange: (value) => {
|
|
803
|
+
if (value !== null) emit("update:modelValue", value);
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
const value = controllable.value;
|
|
962
807
|
function select(nextValue) {
|
|
963
808
|
if (value.value === nextValue) return;
|
|
964
|
-
|
|
965
|
-
emit("update:modelValue", nextValue);
|
|
809
|
+
controllable.setValue(nextValue);
|
|
966
810
|
}
|
|
967
811
|
provide(radioGroupKey, {
|
|
968
812
|
value,
|
|
@@ -976,7 +820,7 @@ var dropdown_menu_radio_group_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
976
820
|
"aria-labelledby": props.ariaLabelledby
|
|
977
821
|
}));
|
|
978
822
|
return createDynamicComponent(() => __props.as, { $: [() => rootAttrs.value] }, extend(() => {
|
|
979
|
-
return createSlot("default", { value: () => value
|
|
823
|
+
return createSlot("default", { value: () => unref(value) });
|
|
980
824
|
}, { _: 8 }), 1);
|
|
981
825
|
}
|
|
982
826
|
});
|
|
@@ -1030,12 +874,12 @@ var dropdown_menu_radio_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1030
874
|
type: props.as === "button" ? "button" : void 0,
|
|
1031
875
|
role: "menuitemradio",
|
|
1032
876
|
tabindex: -1,
|
|
1033
|
-
disabled: props.as === "button" ?
|
|
1034
|
-
"aria-disabled":
|
|
877
|
+
disabled: props.as === "button" ? toOptionalAttribute(isDisabled.value) : void 0,
|
|
878
|
+
"aria-disabled": toOptionalAttribute(isDisabled.value),
|
|
1035
879
|
"aria-checked": checked.value,
|
|
1036
|
-
"data-disabled":
|
|
1037
|
-
"data-focused":
|
|
1038
|
-
"data-highlighted":
|
|
880
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
881
|
+
"data-focused": toOptionalAttribute(focused.value),
|
|
882
|
+
"data-highlighted": toOptionalAttribute(focused.value),
|
|
1039
883
|
"data-state": state.value,
|
|
1040
884
|
class: bem("rp-dropdown-menu__item", {
|
|
1041
885
|
focused: focused.value,
|
|
@@ -1057,19 +901,655 @@ var dropdown_menu_radio_item_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1057
901
|
}
|
|
1058
902
|
});
|
|
1059
903
|
//#endregion
|
|
1060
|
-
//#region src/components/dropdown-menu/
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
904
|
+
//#region src/components/dropdown-menu/dropdownMenuInteractionNavigation.ts
|
|
905
|
+
function createDropdownMenuInteractionNavigation({ host, registry, closeRoot }) {
|
|
906
|
+
const state = registry.state;
|
|
907
|
+
function closeMenu(menuId, focusParent = false) {
|
|
908
|
+
const menu = registry.getMenu(menuId);
|
|
909
|
+
const menuState = state.getMenuState(menuId);
|
|
910
|
+
if (!menu && !menuState || menuId === host.rootMenuId) return false;
|
|
911
|
+
const wasOpen = registry.isMenuOpen(menuId);
|
|
912
|
+
closeSubmenus(menuId);
|
|
913
|
+
const shouldRestoreParent = focusParent || registry.activeMenuId.value === menuId;
|
|
914
|
+
if (wasOpen) state.setMenuOpen(menuId, false);
|
|
915
|
+
state.clearPendingMenuFocus(menuId);
|
|
916
|
+
state.clearMenuState(menuId);
|
|
917
|
+
if (shouldRestoreParent) {
|
|
918
|
+
const parentItem = state.getParentItem(menuId);
|
|
919
|
+
if (!parentItem || !registry.setActive(parentItem.id, focusParent)) {
|
|
920
|
+
const parentMenuId = parentItem?.menuId ?? host.rootMenuId;
|
|
921
|
+
registry.activeMenuId.value = parentMenuId;
|
|
922
|
+
registry.activeItemId.value = state.getActiveIdValue(parentMenuId);
|
|
923
|
+
if (focusParent) registry.focusMenuElement(parentMenuId);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return wasOpen;
|
|
927
|
+
}
|
|
928
|
+
function closeSubmenus(menuId, exceptMenuId) {
|
|
929
|
+
for (const item of state.getItems(menuId)) {
|
|
930
|
+
const submenuId = item.submenuId?.();
|
|
931
|
+
if (!submenuId || submenuId === exceptMenuId) continue;
|
|
932
|
+
closeMenu(submenuId, false);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
function closeAllSubmenus() {
|
|
936
|
+
closeSubmenus(host.rootMenuId);
|
|
937
|
+
for (const menuId of state.getMenuIds()) if (menuId !== host.rootMenuId && registry.isMenuOpen(menuId)) closeMenu(menuId, false);
|
|
938
|
+
}
|
|
939
|
+
function focusMenu(menuId, target = "first") {
|
|
940
|
+
const enabledItems = state.getEnabledItems(menuId);
|
|
941
|
+
const item = target === "last" ? enabledItems.at(-1) : enabledItems[0];
|
|
942
|
+
registry.focusMenuElement(menuId);
|
|
943
|
+
if (!item) {
|
|
944
|
+
state.clearMenuState(menuId);
|
|
945
|
+
registry.activeMenuId.value = menuId;
|
|
946
|
+
const parentItem = state.getParentItem(menuId);
|
|
947
|
+
if (parentItem) registry.activeItemId.value = parentItem.id;
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
return registry.setActive(item.id);
|
|
951
|
+
}
|
|
952
|
+
function openMenu(menuId, focus = "first") {
|
|
953
|
+
const menu = registry.getMenu(menuId);
|
|
954
|
+
const menuState = state.getMenuState(menuId);
|
|
955
|
+
if (!menu && !menuState || menuId === host.rootMenuId) return false;
|
|
956
|
+
const parentItem = state.getParentItem(menuId);
|
|
957
|
+
if (!parentItem || parentItem.disabled()) return false;
|
|
958
|
+
closeSubmenus(parentItem.menuId, menuId);
|
|
959
|
+
state.setPendingMenuFocus(menuId, focus);
|
|
960
|
+
state.setMenuOpen(menuId, true);
|
|
961
|
+
if (focus && menu) focusMenu(menuId, focus);
|
|
962
|
+
return true;
|
|
963
|
+
}
|
|
964
|
+
function selectItem(id, originalEvent = new Event("select")) {
|
|
965
|
+
const item = registry.getItem(id);
|
|
966
|
+
if (!item || item.disabled()) return;
|
|
967
|
+
const selectEvent = item.select?.(originalEvent);
|
|
968
|
+
if (selectEvent && !selectEvent.defaultPrevented && (item.closeOnSelect?.() ?? true)) closeRoot({ focusTrigger: true });
|
|
969
|
+
}
|
|
970
|
+
function activateItem(id, originalEvent = new Event("select")) {
|
|
971
|
+
const item = registry.getItem(id);
|
|
972
|
+
if (!item || item.disabled()) return;
|
|
973
|
+
const submenuId = item.submenuId?.();
|
|
974
|
+
if (submenuId) {
|
|
975
|
+
openMenu(submenuId, "first");
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
selectItem(id, originalEvent);
|
|
979
|
+
}
|
|
980
|
+
function hoverItem(id, openSubmenu = false) {
|
|
981
|
+
const item = registry.getItem(id);
|
|
982
|
+
if (!item || item.disabled()) return;
|
|
983
|
+
registry.setActive(id);
|
|
984
|
+
const submenuId = item.submenuId?.();
|
|
985
|
+
if (openSubmenu && submenuId) openMenu(submenuId, false);
|
|
986
|
+
else closeSubmenus(item.menuId, submenuId && registry.isMenuOpen(submenuId) ? submenuId : void 0);
|
|
987
|
+
}
|
|
988
|
+
function reconcileOpenSubmenus() {
|
|
989
|
+
for (const menuId of state.getMenuIds()) {
|
|
990
|
+
if (menuId === host.rootMenuId || !registry.isMenuOpen(menuId)) continue;
|
|
991
|
+
const parentItem = state.getParentItem(menuId);
|
|
992
|
+
if (!parentItem || parentItem.disabled()) closeMenu(menuId, false);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
function reconcile(menuId) {
|
|
996
|
+
const menuIds = menuId ? [menuId] : state.getRegisteredMenuIds();
|
|
997
|
+
for (const id of menuIds) {
|
|
998
|
+
const activeId = state.getActiveIdValue(id);
|
|
999
|
+
if (!activeId) continue;
|
|
1000
|
+
const currentItems = state.getItems(id);
|
|
1001
|
+
const activeIndex = currentItems.findIndex((item) => item.id === activeId);
|
|
1002
|
+
const activeItem = currentItems[activeIndex];
|
|
1003
|
+
if (activeItem && !activeItem.disabled()) continue;
|
|
1004
|
+
state.chooseNeighbor(id, Math.max(0, activeIndex));
|
|
1005
|
+
}
|
|
1006
|
+
reconcileOpenSubmenus();
|
|
1007
|
+
}
|
|
1008
|
+
return {
|
|
1009
|
+
closeMenu,
|
|
1010
|
+
closeSubmenus,
|
|
1011
|
+
closeAllSubmenus,
|
|
1012
|
+
focusMenu,
|
|
1013
|
+
openMenu,
|
|
1014
|
+
selectItem,
|
|
1015
|
+
activateItem,
|
|
1016
|
+
hoverItem,
|
|
1017
|
+
reconcile,
|
|
1018
|
+
reconcileOpenSubmenus
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
//#endregion
|
|
1022
|
+
//#region src/components/dropdown-menu/dropdownMenuInteractionRegistry.ts
|
|
1023
|
+
function compareItems(left, right) {
|
|
1024
|
+
const leftElement = left.element();
|
|
1025
|
+
const rightElement = right.element();
|
|
1026
|
+
if (leftElement && rightElement && leftElement !== rightElement && typeof Node !== "undefined") {
|
|
1027
|
+
const position = leftElement.compareDocumentPosition(rightElement);
|
|
1028
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
|
|
1029
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
|
1030
|
+
}
|
|
1031
|
+
return (left.order?.() ?? 0) - (right.order?.() ?? 0);
|
|
1032
|
+
}
|
|
1033
|
+
function scrollItemIntoView(item) {
|
|
1034
|
+
nextTick(() => item.element()?.scrollIntoView?.({ block: "nearest" }));
|
|
1035
|
+
}
|
|
1036
|
+
function createDropdownMenuInteractionRegistry(host, navigation) {
|
|
1037
|
+
const menus = /* @__PURE__ */ new Map();
|
|
1038
|
+
const menuStates = /* @__PURE__ */ new Map();
|
|
1039
|
+
const items = /* @__PURE__ */ new Map();
|
|
1040
|
+
const activeIds = ref(/* @__PURE__ */ new Map());
|
|
1041
|
+
const activeItemId = ref(null);
|
|
1042
|
+
const activeMenuId = ref(host.rootMenuId);
|
|
1043
|
+
const pendingRootFocus = ref("first");
|
|
1044
|
+
const pendingMenuFocus = /* @__PURE__ */ new Map();
|
|
1045
|
+
function getMenu(id) {
|
|
1046
|
+
return menus.get(id);
|
|
1047
|
+
}
|
|
1048
|
+
function getMenuState(id) {
|
|
1049
|
+
return menuStates.get(id);
|
|
1050
|
+
}
|
|
1051
|
+
function getItem(id) {
|
|
1052
|
+
return items.get(id);
|
|
1053
|
+
}
|
|
1054
|
+
function getItems(menuId) {
|
|
1055
|
+
return [...items.values()].filter((item) => item.menuId === menuId).sort(compareItems);
|
|
1056
|
+
}
|
|
1057
|
+
function getEnabledItems(menuId) {
|
|
1058
|
+
return getItems(menuId).filter((item) => !item.disabled());
|
|
1059
|
+
}
|
|
1060
|
+
function getActiveIdValue(menuId) {
|
|
1061
|
+
return activeIds.value.get(menuId) ?? null;
|
|
1062
|
+
}
|
|
1063
|
+
function setActiveId(menuId, id) {
|
|
1064
|
+
const next = new Map(activeIds.value);
|
|
1065
|
+
if (id) next.set(menuId, id);
|
|
1066
|
+
else next.delete(menuId);
|
|
1067
|
+
activeIds.value = next;
|
|
1068
|
+
}
|
|
1069
|
+
function getActiveId(menuId) {
|
|
1070
|
+
return computed(() => getActiveIdValue(menuId));
|
|
1071
|
+
}
|
|
1072
|
+
function isMenuOpen(menuId) {
|
|
1073
|
+
if (menuId === host.rootMenuId) return host.isOpen.value;
|
|
1074
|
+
return menuStates.get(menuId)?.isOpen() ?? menus.get(menuId)?.isOpen() ?? false;
|
|
1075
|
+
}
|
|
1076
|
+
function focusMenuElement(menuId) {
|
|
1077
|
+
nextTick(() => {
|
|
1078
|
+
const menu = menus.get(menuId);
|
|
1079
|
+
(menu?.focusTarget?.() ?? menu?.element())?.focus();
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
function clearMenuState(menuId) {
|
|
1083
|
+
const activeId = getActiveIdValue(menuId);
|
|
1084
|
+
if (activeId && activeItemId.value === activeId) activeItemId.value = null;
|
|
1085
|
+
setActiveId(menuId, null);
|
|
1086
|
+
}
|
|
1087
|
+
function setActive(id, focusElement = false) {
|
|
1088
|
+
if (id === null) {
|
|
1089
|
+
clearMenuState(activeMenuId.value);
|
|
1090
|
+
activeItemId.value = null;
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
const item = items.get(id);
|
|
1094
|
+
if (!item || item.disabled()) return false;
|
|
1095
|
+
setActiveId(item.menuId, item.id);
|
|
1096
|
+
activeItemId.value = item.id;
|
|
1097
|
+
activeMenuId.value = item.menuId;
|
|
1098
|
+
pendingMenuFocus.delete(item.menuId);
|
|
1099
|
+
if (focusElement) focusMenuElement(item.menuId);
|
|
1100
|
+
scrollItemIntoView(item);
|
|
1101
|
+
return true;
|
|
1102
|
+
}
|
|
1103
|
+
function isActive(id) {
|
|
1104
|
+
return getActiveIdValue(items.get(id)?.menuId ?? "") === id;
|
|
1105
|
+
}
|
|
1106
|
+
function getParentItem(menuId) {
|
|
1107
|
+
const parentItemId = menus.get(menuId)?.parentItemId?.();
|
|
1108
|
+
if (parentItemId) {
|
|
1109
|
+
const parentItem = items.get(parentItemId);
|
|
1110
|
+
if (parentItem) return parentItem;
|
|
1111
|
+
}
|
|
1112
|
+
return [...items.values()].find((item) => item.submenuId?.() === menuId);
|
|
1113
|
+
}
|
|
1114
|
+
function setMenuOpen(menuId, open) {
|
|
1115
|
+
const state = menuStates.get(menuId);
|
|
1116
|
+
if (state) state.setOpen(open);
|
|
1117
|
+
else menus.get(menuId)?.setOpen?.(open);
|
|
1118
|
+
}
|
|
1119
|
+
function chooseNeighbor(menuId, previousIndex) {
|
|
1120
|
+
const currentItems = getItems(menuId);
|
|
1121
|
+
const nextCandidates = currentItems.slice(Math.max(0, previousIndex));
|
|
1122
|
+
const previousCandidates = [];
|
|
1123
|
+
for (let index = Math.max(0, previousIndex) - 1; index >= 0; index -= 1) {
|
|
1124
|
+
const item = currentItems[index];
|
|
1125
|
+
if (item) previousCandidates.push(item);
|
|
1126
|
+
}
|
|
1127
|
+
const next = [...nextCandidates, ...previousCandidates].find((item) => !item.disabled());
|
|
1128
|
+
if (next) setActive(next.id);
|
|
1129
|
+
else {
|
|
1130
|
+
clearMenuState(menuId);
|
|
1131
|
+
focusMenuElement(menuId);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
function unregisterItem(id) {
|
|
1135
|
+
const item = items.get(id);
|
|
1136
|
+
if (!item) return;
|
|
1137
|
+
const previousIndex = getItems(item.menuId).findIndex((current) => current.id === id);
|
|
1138
|
+
const submenuId = item.submenuId?.();
|
|
1139
|
+
if (submenuId) navigation.closeMenu(submenuId, false);
|
|
1140
|
+
items.delete(id);
|
|
1141
|
+
if (getActiveIdValue(item.menuId) === id) chooseNeighbor(item.menuId, previousIndex);
|
|
1142
|
+
navigation.reconcileOpenSubmenus();
|
|
1143
|
+
}
|
|
1144
|
+
function registerItem(registration) {
|
|
1145
|
+
const previous = items.get(registration.id);
|
|
1146
|
+
if (previous && previous.menuId !== registration.menuId && getActiveIdValue(previous.menuId) === previous.id) clearMenuState(previous.menuId);
|
|
1147
|
+
items.set(registration.id, registration);
|
|
1148
|
+
if (isMenuOpen(registration.menuId) && !getActiveIdValue(registration.menuId) && !registration.disabled()) {
|
|
1149
|
+
const enabledItems = getEnabledItems(registration.menuId);
|
|
1150
|
+
const candidate = pendingMenuFocus.get(registration.menuId) === "last" ? enabledItems.at(-1) : enabledItems[0];
|
|
1151
|
+
if (candidate) setActive(candidate.id);
|
|
1152
|
+
} else navigation.reconcile(registration.menuId);
|
|
1153
|
+
return () => {
|
|
1154
|
+
if (items.get(registration.id) === registration) unregisterItem(registration.id);
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
function unregisterMenu(id) {
|
|
1158
|
+
if (!menus.get(id)) return;
|
|
1159
|
+
navigation.closeSubmenus(id);
|
|
1160
|
+
if (id !== host.rootMenuId) navigation.closeMenu(id, false);
|
|
1161
|
+
clearMenuState(id);
|
|
1162
|
+
menus.delete(id);
|
|
1163
|
+
}
|
|
1164
|
+
function registerMenu(registration) {
|
|
1165
|
+
menus.set(registration.id, registration);
|
|
1166
|
+
const pending = pendingMenuFocus.get(registration.id);
|
|
1167
|
+
if (registration.isOpen() && pending) nextTick(() => navigation.focusMenu(registration.id, pending));
|
|
1168
|
+
return () => {
|
|
1169
|
+
if (menus.get(registration.id) === registration) unregisterMenu(registration.id);
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
function registerMenuState(registration) {
|
|
1173
|
+
menuStates.set(registration.id, registration);
|
|
1174
|
+
return () => {
|
|
1175
|
+
if (menuStates.get(registration.id) !== registration) return;
|
|
1176
|
+
menuStates.delete(registration.id);
|
|
1177
|
+
pendingMenuFocus.delete(registration.id);
|
|
1178
|
+
if (!menus.has(registration.id)) clearMenuState(registration.id);
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
activeItemId,
|
|
1183
|
+
activeMenuId,
|
|
1184
|
+
pendingRootFocus,
|
|
1185
|
+
registerMenu,
|
|
1186
|
+
unregisterMenu,
|
|
1187
|
+
registerMenuState,
|
|
1188
|
+
registerItem,
|
|
1189
|
+
unregisterItem,
|
|
1190
|
+
getActiveId,
|
|
1191
|
+
getItem,
|
|
1192
|
+
getMenu,
|
|
1193
|
+
isActive,
|
|
1194
|
+
isMenuOpen,
|
|
1195
|
+
setActive,
|
|
1196
|
+
focusMenuElement,
|
|
1197
|
+
state: {
|
|
1198
|
+
getMenuState,
|
|
1199
|
+
getItems,
|
|
1200
|
+
getEnabledItems,
|
|
1201
|
+
getActiveIdValue,
|
|
1202
|
+
clearMenuState,
|
|
1203
|
+
getParentItem,
|
|
1204
|
+
setMenuOpen,
|
|
1205
|
+
chooseNeighbor,
|
|
1206
|
+
getMenuIds: () => /* @__PURE__ */ new Set([...menus.keys(), ...menuStates.keys()]),
|
|
1207
|
+
getRegisteredMenuIds: () => [...menus.keys()],
|
|
1208
|
+
getPendingMenuFocus: (menuId) => pendingMenuFocus.get(menuId),
|
|
1209
|
+
setPendingMenuFocus: (menuId, focus) => pendingMenuFocus.set(menuId, focus),
|
|
1210
|
+
clearPendingMenuFocus: (menuId) => pendingMenuFocus.delete(menuId)
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
//#endregion
|
|
1215
|
+
//#region src/components/dropdown-menu/useDropdownMenuInteractionDismissal.ts
|
|
1216
|
+
function createOutsideEvent(originalEvent) {
|
|
1217
|
+
return createCancelableCustomEvent("dropdown-menu-interact-outside", { originalEvent }, originalEvent);
|
|
1218
|
+
}
|
|
1219
|
+
function blockDocumentClick(event) {
|
|
1220
|
+
if (event.cancelable) event.preventDefault();
|
|
1221
|
+
event.stopPropagation();
|
|
1222
|
+
document.removeEventListener("click", blockDocumentClick, true);
|
|
1223
|
+
}
|
|
1224
|
+
function blockNextDocumentClick() {
|
|
1225
|
+
if (typeof document === "undefined") return;
|
|
1226
|
+
document.addEventListener("click", blockDocumentClick, true);
|
|
1227
|
+
window.setTimeout(() => document.removeEventListener("click", blockDocumentClick, true), 1e3);
|
|
1228
|
+
}
|
|
1229
|
+
function useDropdownMenuInteractionDismissal({ host, registry, closeRoot }) {
|
|
1230
|
+
const inside = /* @__PURE__ */ new Set();
|
|
1231
|
+
let dismissal;
|
|
1232
|
+
let isListening = false;
|
|
1233
|
+
function registerInside(element) {
|
|
1234
|
+
inside.add(element);
|
|
1235
|
+
}
|
|
1236
|
+
function unregisterInside(element) {
|
|
1237
|
+
inside.delete(element);
|
|
1238
|
+
}
|
|
1239
|
+
function isInside(event) {
|
|
1240
|
+
return [...inside].some((element) => isEventWithinElement(event, element));
|
|
1241
|
+
}
|
|
1242
|
+
function emitOutside(type, originalEvent) {
|
|
1243
|
+
const outsideEvent = createOutsideEvent(originalEvent);
|
|
1244
|
+
if (type === "pointer") dismissal?.pointerDownOutside?.(outsideEvent);
|
|
1245
|
+
else dismissal?.focusOutside?.(outsideEvent);
|
|
1246
|
+
dismissal?.interactOutside?.(outsideEvent);
|
|
1247
|
+
return outsideEvent;
|
|
1248
|
+
}
|
|
1249
|
+
function blockModalInteraction(event) {
|
|
1250
|
+
if (!host.modal.value) return;
|
|
1251
|
+
if (event.cancelable) event.preventDefault();
|
|
1252
|
+
event.stopPropagation();
|
|
1253
|
+
if (event.type === "pointerdown") blockNextDocumentClick();
|
|
1254
|
+
}
|
|
1255
|
+
function shouldIgnoreOutside(event) {
|
|
1256
|
+
const ignoredTargets = (dismissal?.ignoredTargets() ?? []).map((target) => isRef(target) ? target.value : target);
|
|
1257
|
+
return isInside(event) || isEventWithinTargets(event, ignoredTargets);
|
|
1258
|
+
}
|
|
1259
|
+
function onDocumentPointer(event) {
|
|
1260
|
+
if (!host.isTopLayer() || shouldIgnoreOutside(event)) return;
|
|
1261
|
+
const outsideEvent = emitOutside("pointer", event);
|
|
1262
|
+
blockModalInteraction(event);
|
|
1263
|
+
if (!outsideEvent.defaultPrevented) closeRoot({ focusTrigger: host.modal.value });
|
|
1264
|
+
}
|
|
1265
|
+
function onDocumentFocus(event) {
|
|
1266
|
+
if (!host.isTopLayer() || shouldIgnoreOutside(event)) return;
|
|
1267
|
+
const outsideEvent = emitOutside("focus", event);
|
|
1268
|
+
blockModalInteraction(event);
|
|
1269
|
+
if (!outsideEvent.defaultPrevented) closeRoot({ focusTrigger: host.modal.value });
|
|
1270
|
+
else if (host.modal.value) registry.focusMenuElement(registry.activeMenuId.value);
|
|
1271
|
+
}
|
|
1272
|
+
function setDocumentListeners(active) {
|
|
1273
|
+
if (typeof document === "undefined" || active === isListening) return;
|
|
1274
|
+
isListening = active;
|
|
1275
|
+
const method = active ? "addEventListener" : "removeEventListener";
|
|
1276
|
+
document[method]("pointerdown", onDocumentPointer, true);
|
|
1277
|
+
document[method]("focusin", onDocumentFocus, true);
|
|
1278
|
+
}
|
|
1279
|
+
function registerDismissal(registration) {
|
|
1280
|
+
dismissal = registration;
|
|
1281
|
+
setDocumentListeners(host.isOpen.value);
|
|
1282
|
+
return () => {
|
|
1283
|
+
if (dismissal !== registration) return;
|
|
1284
|
+
dismissal = void 0;
|
|
1285
|
+
setDocumentListeners(false);
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
watch(host.isOpen, (open) => setDocumentListeners(open && Boolean(dismissal)));
|
|
1289
|
+
onBeforeUnmount(() => setDocumentListeners(false));
|
|
1290
|
+
return {
|
|
1291
|
+
registerInside,
|
|
1292
|
+
unregisterInside,
|
|
1293
|
+
registerDismissal
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
//#endregion
|
|
1297
|
+
//#region src/components/dropdown-menu/useDropdownMenuInteractionKeyboard.ts
|
|
1298
|
+
function getPlacementSide(placement) {
|
|
1299
|
+
return placement.split("-")[0];
|
|
1300
|
+
}
|
|
1301
|
+
function useDropdownMenuInteractionKeyboard({ host, registry, navigation, openRoot, closeRoot }) {
|
|
1302
|
+
const state = registry.state;
|
|
1303
|
+
const typeaheadMenuId = ref(host.rootMenuId);
|
|
1304
|
+
const typeahead = useTypeahead({
|
|
1305
|
+
items: () => state.getItems(typeaheadMenuId.value),
|
|
1306
|
+
activeIndex: () => state.getItems(typeaheadMenuId.value).findIndex((item) => item.id === state.getActiveIdValue(typeaheadMenuId.value)),
|
|
1307
|
+
getKey: (item) => item.id,
|
|
1308
|
+
getTextValue: (item) => item.textValue(),
|
|
1309
|
+
isDisabled: (item) => item.disabled(),
|
|
1310
|
+
scopeKey: () => typeaheadMenuId.value,
|
|
1311
|
+
onMatch(item) {
|
|
1312
|
+
registry.setActive(item.id);
|
|
1313
|
+
navigation.closeSubmenus(item.menuId);
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
function move(menuId, direction) {
|
|
1317
|
+
const enabledItems = state.getEnabledItems(menuId);
|
|
1318
|
+
if (enabledItems.length === 0) {
|
|
1319
|
+
state.clearMenuState(menuId);
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
const currentIndex = enabledItems.findIndex((item) => item.id === state.getActiveIdValue(menuId));
|
|
1323
|
+
const item = enabledItems[((currentIndex < 0 ? direction === 1 ? -1 : 0 : currentIndex) + direction + enabledItems.length) % enabledItems.length];
|
|
1324
|
+
if (item) {
|
|
1325
|
+
registry.setActive(item.id);
|
|
1326
|
+
navigation.closeSubmenus(menuId);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
function handleHorizontalKey(menuId, event, activeItem) {
|
|
1330
|
+
const menu = registry.getMenu(menuId);
|
|
1331
|
+
const isRight = event.key === "ArrowRight";
|
|
1332
|
+
if (menuId !== host.rootMenuId && menu) {
|
|
1333
|
+
if (isRight === (getPlacementSide(menu.placement()) === "left")) {
|
|
1334
|
+
event.preventDefault();
|
|
1335
|
+
if (menu.stopKeyPropagation) event.stopPropagation();
|
|
1336
|
+
navigation.closeMenu(menuId, true);
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
const submenuId = activeItem?.submenuId?.();
|
|
1341
|
+
if (!activeItem || activeItem.disabled() || !submenuId) return;
|
|
1342
|
+
const submenu = registry.getMenu(submenuId);
|
|
1343
|
+
if (isRight !== (activeItem.submenuDirection?.() !== "left" && (!submenu || getPlacementSide(submenu.placement()) !== "left"))) return;
|
|
1344
|
+
event.preventDefault();
|
|
1345
|
+
if (menu?.stopKeyPropagation) event.stopPropagation();
|
|
1346
|
+
navigation.openMenu(submenuId, "first");
|
|
1347
|
+
}
|
|
1348
|
+
function onMenuKeydown(menuId, event) {
|
|
1349
|
+
const menu = registry.getMenu(menuId);
|
|
1350
|
+
typeaheadMenuId.value = menuId;
|
|
1351
|
+
if (typeahead.handleKey(event)) {
|
|
1352
|
+
if (menu?.stopKeyPropagation) event.stopPropagation();
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const activeId = state.getActiveIdValue(menuId);
|
|
1356
|
+
const activeItem = activeId ? registry.getItem(activeId) : void 0;
|
|
1357
|
+
const stop = () => {
|
|
1358
|
+
if (menu?.stopKeyPropagation) event.stopPropagation();
|
|
1359
|
+
};
|
|
1360
|
+
switch (event.key) {
|
|
1361
|
+
case "ArrowDown":
|
|
1362
|
+
event.preventDefault();
|
|
1363
|
+
stop();
|
|
1364
|
+
move(menuId, 1);
|
|
1365
|
+
break;
|
|
1366
|
+
case "ArrowUp":
|
|
1367
|
+
event.preventDefault();
|
|
1368
|
+
stop();
|
|
1369
|
+
move(menuId, -1);
|
|
1370
|
+
break;
|
|
1371
|
+
case "Home":
|
|
1372
|
+
event.preventDefault();
|
|
1373
|
+
stop();
|
|
1374
|
+
navigation.focusMenu(menuId, "first");
|
|
1375
|
+
navigation.closeSubmenus(menuId);
|
|
1376
|
+
break;
|
|
1377
|
+
case "End":
|
|
1378
|
+
event.preventDefault();
|
|
1379
|
+
stop();
|
|
1380
|
+
navigation.focusMenu(menuId, "last");
|
|
1381
|
+
navigation.closeSubmenus(menuId);
|
|
1382
|
+
break;
|
|
1383
|
+
case "ArrowRight":
|
|
1384
|
+
case "ArrowLeft":
|
|
1385
|
+
handleHorizontalKey(menuId, event, activeItem);
|
|
1386
|
+
break;
|
|
1387
|
+
case "Enter":
|
|
1388
|
+
case " ":
|
|
1389
|
+
event.preventDefault();
|
|
1390
|
+
stop();
|
|
1391
|
+
if (activeItem) navigation.activateItem(activeItem.id, event);
|
|
1392
|
+
break;
|
|
1393
|
+
case "Escape":
|
|
1394
|
+
event.preventDefault();
|
|
1395
|
+
stop();
|
|
1396
|
+
if (menu?.onEscape && !menu.onEscape(event)) return;
|
|
1397
|
+
if (!navigation.closeMenu(menuId, true)) closeRoot({ focusTrigger: true });
|
|
1398
|
+
break;
|
|
1399
|
+
case "Tab":
|
|
1400
|
+
closeRoot();
|
|
1401
|
+
break;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function onTriggerKeydown(event, beforeOpen) {
|
|
1405
|
+
if (host.disabled.value) return;
|
|
1406
|
+
switch (event.key) {
|
|
1407
|
+
case "Enter":
|
|
1408
|
+
case " ":
|
|
1409
|
+
case "ArrowDown":
|
|
1410
|
+
event.preventDefault();
|
|
1411
|
+
beforeOpen?.();
|
|
1412
|
+
openRoot("first");
|
|
1413
|
+
break;
|
|
1414
|
+
case "ArrowUp":
|
|
1415
|
+
event.preventDefault();
|
|
1416
|
+
beforeOpen?.();
|
|
1417
|
+
openRoot("last");
|
|
1418
|
+
break;
|
|
1419
|
+
case "Escape":
|
|
1420
|
+
closeRoot({ focusTrigger: true });
|
|
1421
|
+
break;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
return {
|
|
1425
|
+
onMenuKeydown,
|
|
1426
|
+
onTriggerKeydown,
|
|
1427
|
+
resetTypeahead: typeahead.reset
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
//#endregion
|
|
1431
|
+
//#region src/components/dropdown-menu/dropdownMenuInteraction.ts
|
|
1432
|
+
function resolveOpenFocusTarget(options) {
|
|
1433
|
+
if (typeof options === "string") return options;
|
|
1434
|
+
return options?.focus ?? "first";
|
|
1435
|
+
}
|
|
1436
|
+
function useDropdownMenuInteraction(host) {
|
|
1437
|
+
let navigation;
|
|
1438
|
+
const registry = createDropdownMenuInteractionRegistry(host, {
|
|
1439
|
+
closeMenu: (menuId, focusParent) => navigation.closeMenu(menuId, focusParent),
|
|
1440
|
+
closeSubmenus: (menuId, exceptMenuId) => navigation.closeSubmenus(menuId, exceptMenuId),
|
|
1441
|
+
focusMenu: (menuId, target) => navigation.focusMenu(menuId, target),
|
|
1442
|
+
reconcile: (menuId) => navigation.reconcile(menuId),
|
|
1443
|
+
reconcileOpenSubmenus: () => navigation.reconcileOpenSubmenus()
|
|
1444
|
+
});
|
|
1445
|
+
function open(options) {
|
|
1446
|
+
if (host.disabled.value) return;
|
|
1447
|
+
host.beforeOpen?.();
|
|
1448
|
+
registry.pendingRootFocus.value = resolveOpenFocusTarget(options);
|
|
1449
|
+
host.setOpen(true);
|
|
1450
|
+
navigation.focusMenu(host.rootMenuId, registry.pendingRootFocus.value);
|
|
1451
|
+
}
|
|
1452
|
+
function close(options = {}) {
|
|
1453
|
+
host.beforeClose?.();
|
|
1454
|
+
host.setOpen(false);
|
|
1455
|
+
registry.pendingRootFocus.value = false;
|
|
1456
|
+
navigation.closeAllSubmenus();
|
|
1457
|
+
registry.state.clearMenuState(host.rootMenuId);
|
|
1458
|
+
registry.activeItemId.value = null;
|
|
1459
|
+
registry.activeMenuId.value = host.rootMenuId;
|
|
1460
|
+
keyboard.resetTypeahead();
|
|
1461
|
+
if (options.focusTrigger || options.returnFocus) host.focusTrigger();
|
|
1462
|
+
}
|
|
1463
|
+
function toggle() {
|
|
1464
|
+
if (host.isOpen.value) close({ returnFocus: true });
|
|
1465
|
+
else open();
|
|
1466
|
+
}
|
|
1467
|
+
function onTriggerClick(beforeToggle) {
|
|
1468
|
+
beforeToggle?.();
|
|
1469
|
+
toggle();
|
|
1470
|
+
}
|
|
1471
|
+
navigation = createDropdownMenuInteractionNavigation({
|
|
1472
|
+
host,
|
|
1473
|
+
registry,
|
|
1474
|
+
closeRoot: close
|
|
1475
|
+
});
|
|
1476
|
+
const keyboard = useDropdownMenuInteractionKeyboard({
|
|
1477
|
+
host,
|
|
1478
|
+
registry,
|
|
1479
|
+
navigation,
|
|
1480
|
+
openRoot: open,
|
|
1481
|
+
closeRoot: close
|
|
1482
|
+
});
|
|
1483
|
+
const dismissal = useDropdownMenuInteractionDismissal({
|
|
1484
|
+
host,
|
|
1485
|
+
registry,
|
|
1486
|
+
closeRoot: close
|
|
1487
|
+
});
|
|
1488
|
+
watch(host.disabled, (disabled) => {
|
|
1489
|
+
if (disabled) close();
|
|
1490
|
+
});
|
|
1491
|
+
watch(host.isOpen, (isOpen) => {
|
|
1492
|
+
if (!isOpen) {
|
|
1493
|
+
navigation.closeAllSubmenus();
|
|
1494
|
+
registry.state.clearMenuState(host.rootMenuId);
|
|
1495
|
+
registry.activeItemId.value = null;
|
|
1496
|
+
registry.activeMenuId.value = host.rootMenuId;
|
|
1497
|
+
keyboard.resetTypeahead();
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
const focus = registry.pendingRootFocus.value || "first";
|
|
1501
|
+
navigation.focusMenu(host.rootMenuId, focus);
|
|
1502
|
+
}, { immediate: true });
|
|
1503
|
+
return {
|
|
1504
|
+
rootMenuId: host.rootMenuId,
|
|
1505
|
+
activeItemId: registry.activeItemId,
|
|
1506
|
+
activeMenuId: registry.activeMenuId,
|
|
1507
|
+
pendingRootFocus: registry.pendingRootFocus,
|
|
1508
|
+
registerMenu: registry.registerMenu,
|
|
1509
|
+
unregisterMenu: registry.unregisterMenu,
|
|
1510
|
+
registerMenuState: registry.registerMenuState,
|
|
1511
|
+
registerItem: registry.registerItem,
|
|
1512
|
+
unregisterItem: registry.unregisterItem,
|
|
1513
|
+
registerInside: dismissal.registerInside,
|
|
1514
|
+
unregisterInside: dismissal.unregisterInside,
|
|
1515
|
+
registerDismissal: dismissal.registerDismissal,
|
|
1516
|
+
getActiveId: registry.getActiveId,
|
|
1517
|
+
getItem: registry.getItem,
|
|
1518
|
+
getMenu: registry.getMenu,
|
|
1519
|
+
isActive: registry.isActive,
|
|
1520
|
+
isMenuOpen: registry.isMenuOpen,
|
|
1521
|
+
setActive: registry.setActive,
|
|
1522
|
+
focusMenu: navigation.focusMenu,
|
|
1523
|
+
focusMenuElement: registry.focusMenuElement,
|
|
1524
|
+
open,
|
|
1525
|
+
close,
|
|
1526
|
+
toggle,
|
|
1527
|
+
openMenu: navigation.openMenu,
|
|
1528
|
+
closeMenu: navigation.closeMenu,
|
|
1529
|
+
closeSubmenus: navigation.closeSubmenus,
|
|
1530
|
+
selectItem: navigation.selectItem,
|
|
1531
|
+
activateItem: navigation.activateItem,
|
|
1532
|
+
hoverItem: navigation.hoverItem,
|
|
1533
|
+
reconcile: navigation.reconcile,
|
|
1534
|
+
onTriggerClick,
|
|
1535
|
+
onTriggerKeydown: keyboard.onTriggerKeydown,
|
|
1536
|
+
onMenuKeydown: keyboard.onMenuKeydown
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
//#endregion
|
|
1540
|
+
//#region src/components/dropdown-menu/dropdown-menu-root.vue
|
|
1541
|
+
var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
1542
|
+
name: "RpDropdownMenuRoot",
|
|
1543
|
+
__name: "dropdown-menu-root",
|
|
1544
|
+
props: {
|
|
1545
|
+
id: {},
|
|
1546
|
+
open: {
|
|
1547
|
+
type: Boolean,
|
|
1548
|
+
default: void 0
|
|
1549
|
+
},
|
|
1550
|
+
defaultOpen: {
|
|
1551
|
+
type: Boolean,
|
|
1552
|
+
default: false
|
|
1073
1553
|
},
|
|
1074
1554
|
baseZIndex: {},
|
|
1075
1555
|
disabled: {
|
|
@@ -1089,8 +1569,12 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1089
1569
|
const emit = __emit;
|
|
1090
1570
|
const generatedId = useId();
|
|
1091
1571
|
const id = computed(() => props.id ?? `${generatedId}-dropdown-menu`);
|
|
1092
|
-
const
|
|
1093
|
-
|
|
1572
|
+
const controllableOpen = useControllableValue({
|
|
1573
|
+
modelValue: () => props.open,
|
|
1574
|
+
defaultValue: () => props.defaultOpen,
|
|
1575
|
+
onChange: (nextOpen) => emit("update:open", nextOpen)
|
|
1576
|
+
});
|
|
1577
|
+
const isOpen = controllableOpen.value;
|
|
1094
1578
|
const disabled = computed(() => props.disabled);
|
|
1095
1579
|
const modal = computed(() => props.modal);
|
|
1096
1580
|
const trigger = ref(null);
|
|
@@ -1099,9 +1583,7 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1099
1583
|
const activeReference = shallowRef(null);
|
|
1100
1584
|
const { reference: configuredReference } = useFloatingTarget(() => props.target ?? props.virtualAnchor, trigger);
|
|
1101
1585
|
const reference = computed(() => activeReference.value ?? configuredReference.value);
|
|
1102
|
-
const pendingFocus = ref("first");
|
|
1103
1586
|
const contentElement = ref(null);
|
|
1104
|
-
const inside = /* @__PURE__ */ new Set();
|
|
1105
1587
|
let returnFocusElement = null;
|
|
1106
1588
|
const baseZIndex = useOverlayZIndex({
|
|
1107
1589
|
baseZIndex: () => props.baseZIndex,
|
|
@@ -1115,43 +1597,37 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1115
1597
|
});
|
|
1116
1598
|
function setOpen(value) {
|
|
1117
1599
|
if (value && disabled.value) return;
|
|
1118
|
-
|
|
1119
|
-
if (props.open === void 0) uncontrolledOpen.value = value;
|
|
1120
|
-
if (previous !== value) emit("update:open", value);
|
|
1600
|
+
if (isOpen.value !== value) controllableOpen.setValue(value);
|
|
1121
1601
|
}
|
|
1122
1602
|
function rememberFocus() {
|
|
1123
1603
|
if (typeof document === "undefined" || returnFocusElement) return;
|
|
1124
1604
|
const activeElement = document.activeElement;
|
|
1125
1605
|
if (activeElement instanceof HTMLElement) returnFocusElement = activeElement;
|
|
1126
1606
|
}
|
|
1127
|
-
function open(options) {
|
|
1128
|
-
if (disabled.value) return;
|
|
1129
|
-
rememberFocus();
|
|
1130
|
-
pendingFocus.value = getFocusTarget(options);
|
|
1131
|
-
setOpen(true);
|
|
1132
|
-
}
|
|
1133
1607
|
function focusReturnTarget() {
|
|
1134
1608
|
const target = returnFocusElement ?? trigger.value;
|
|
1135
1609
|
nextTick(() => target?.focus());
|
|
1136
1610
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1611
|
+
const interaction = useDropdownMenuInteraction({
|
|
1612
|
+
rootMenuId: `${generatedId}-interaction-root`,
|
|
1613
|
+
isOpen,
|
|
1614
|
+
disabled,
|
|
1615
|
+
modal,
|
|
1616
|
+
setOpen,
|
|
1617
|
+
isTopLayer: layer.isTopLayer,
|
|
1618
|
+
focusTrigger: focusReturnTarget,
|
|
1619
|
+
beforeOpen: rememberFocus
|
|
1620
|
+
});
|
|
1621
|
+
const { pendingRootFocus: pendingFocus, open, close, toggle } = interaction;
|
|
1146
1622
|
function openAt(point, options) {
|
|
1147
1623
|
activeReference.value = createVirtualAnchor(point);
|
|
1148
1624
|
open(options);
|
|
1149
1625
|
}
|
|
1150
1626
|
function setTrigger(element, nextId) {
|
|
1151
|
-
if (trigger.value && trigger.value !== element)
|
|
1627
|
+
if (trigger.value && trigger.value !== element) interaction.unregisterInside(trigger.value);
|
|
1152
1628
|
trigger.value = element;
|
|
1153
1629
|
triggerId.value = nextId;
|
|
1154
|
-
if (element)
|
|
1630
|
+
if (element) interaction.registerInside(element);
|
|
1155
1631
|
}
|
|
1156
1632
|
const context = {
|
|
1157
1633
|
id,
|
|
@@ -1164,6 +1640,7 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1164
1640
|
reference,
|
|
1165
1641
|
pendingFocus,
|
|
1166
1642
|
layer,
|
|
1643
|
+
interaction,
|
|
1167
1644
|
open,
|
|
1168
1645
|
close,
|
|
1169
1646
|
toggle,
|
|
@@ -1176,13 +1653,10 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1176
1653
|
returnFocusElement = element;
|
|
1177
1654
|
},
|
|
1178
1655
|
registerInside(element) {
|
|
1179
|
-
|
|
1656
|
+
interaction.registerInside(element);
|
|
1180
1657
|
},
|
|
1181
1658
|
unregisterInside(element) {
|
|
1182
|
-
|
|
1183
|
-
},
|
|
1184
|
-
isInside(event) {
|
|
1185
|
-
return [...inside].some((element) => isEventWithinElement(event, element));
|
|
1659
|
+
interaction.unregisterInside(element);
|
|
1186
1660
|
}
|
|
1187
1661
|
};
|
|
1188
1662
|
const slotProps = computed(() => ({
|
|
@@ -1192,9 +1666,6 @@ var dropdown_menu_root_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1192
1666
|
toggle,
|
|
1193
1667
|
openAt
|
|
1194
1668
|
}));
|
|
1195
|
-
watch(disabled, (value) => {
|
|
1196
|
-
if (value) close();
|
|
1197
|
-
});
|
|
1198
1669
|
watch(isOpen, (value) => {
|
|
1199
1670
|
if (!value) activeReference.value = null;
|
|
1200
1671
|
}, { flush: "sync" });
|
|
@@ -1253,48 +1724,47 @@ var dropdown_menu_sub_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1253
1724
|
const props = __props;
|
|
1254
1725
|
const emit = __emit;
|
|
1255
1726
|
const parentMenu = useRequiredInject(menuKey, "RpDropdownMenuSub");
|
|
1256
|
-
const
|
|
1257
|
-
const
|
|
1727
|
+
const menuId = `${useId()}-interaction-menu`;
|
|
1728
|
+
const controllableOpen = useControllableValue({
|
|
1729
|
+
modelValue: () => props.open,
|
|
1730
|
+
defaultValue: () => props.defaultOpen,
|
|
1731
|
+
onChange: (open) => emit("update:open", open)
|
|
1732
|
+
});
|
|
1733
|
+
const isOpen = controllableOpen.value;
|
|
1258
1734
|
const trigger = ref(null);
|
|
1259
1735
|
const contentId = ref();
|
|
1260
1736
|
const actualPlacement = ref("right-start");
|
|
1261
1737
|
const pendingFocus = ref(false);
|
|
1262
1738
|
function setOpen(value) {
|
|
1263
|
-
|
|
1264
|
-
if (props.open === void 0) uncontrolled.value = value;
|
|
1265
|
-
if (previous !== value) emit("update:open", value);
|
|
1739
|
+
if (isOpen.value !== value) controllableOpen.setValue(value);
|
|
1266
1740
|
}
|
|
1741
|
+
const cleanupMenuState = parentMenu.root.interaction.registerMenuState({
|
|
1742
|
+
id: menuId,
|
|
1743
|
+
isOpen: () => isOpen.value,
|
|
1744
|
+
setOpen
|
|
1745
|
+
});
|
|
1267
1746
|
const context = {
|
|
1747
|
+
menuId,
|
|
1268
1748
|
isOpen,
|
|
1269
1749
|
trigger,
|
|
1270
1750
|
contentId,
|
|
1271
1751
|
actualPlacement,
|
|
1272
1752
|
pendingFocus,
|
|
1273
1753
|
menu: null,
|
|
1754
|
+
setOpen,
|
|
1274
1755
|
open(focus = "first") {
|
|
1275
|
-
parentMenu.closeSubmenus(context);
|
|
1276
1756
|
pendingFocus.value = focus;
|
|
1277
|
-
setOpen(true);
|
|
1278
|
-
if (focus) nextTick(() => context.menu?.focus(focus));
|
|
1757
|
+
if (!parentMenu.root.interaction.openMenu(menuId, focus)) setOpen(true);
|
|
1279
1758
|
},
|
|
1280
1759
|
close(focusParent = false) {
|
|
1281
|
-
setOpen(false);
|
|
1282
1760
|
pendingFocus.value = false;
|
|
1283
|
-
|
|
1284
|
-
if (focusParent) {
|
|
1285
|
-
parentMenu.setActive(trigger.value?.id ?? "");
|
|
1286
|
-
parentMenu.focusElement();
|
|
1287
|
-
}
|
|
1761
|
+
if (!parentMenu.root.interaction.closeMenu(menuId, focusParent)) setOpen(false);
|
|
1288
1762
|
}
|
|
1289
1763
|
};
|
|
1290
|
-
parentMenu.registerSub(context);
|
|
1291
1764
|
provide(subKey, context);
|
|
1292
|
-
|
|
1293
|
-
if (!open) context.close(false);
|
|
1294
|
-
});
|
|
1295
|
-
onBeforeUnmount(() => parentMenu.unregisterSub(context));
|
|
1765
|
+
onBeforeUnmount(cleanupMenuState);
|
|
1296
1766
|
return createSlot("default", {
|
|
1297
|
-
isOpen: () => isOpen
|
|
1767
|
+
isOpen: () => unref(isOpen),
|
|
1298
1768
|
open: () => context.open,
|
|
1299
1769
|
close: () => context.close
|
|
1300
1770
|
});
|
|
@@ -1390,10 +1860,17 @@ var dropdown_menu_sub_trigger_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1390
1860
|
element: () => sub.trigger.value,
|
|
1391
1861
|
textValue: () => props.textValue ?? sub.trigger.value?.textContent?.trim() ?? "",
|
|
1392
1862
|
disabled: () => isDisabled.value,
|
|
1393
|
-
activate: () =>
|
|
1863
|
+
activate: () => void 0,
|
|
1394
1864
|
submenu: sub
|
|
1395
1865
|
};
|
|
1396
1866
|
menu.registerItem(registration);
|
|
1867
|
+
watch(id, (nextId, previousId) => {
|
|
1868
|
+
const wasActive = menu.activeId.value === previousId;
|
|
1869
|
+
menu.unregisterItem(previousId);
|
|
1870
|
+
menu.registerItem(registration);
|
|
1871
|
+
if (wasActive) menu.setActive(nextId);
|
|
1872
|
+
}, { flush: "sync" });
|
|
1873
|
+
watch(isDisabled, () => menu.root.interaction.reconcile(menu.id));
|
|
1397
1874
|
onBeforeUnmount(() => menu.unregisterItem(id.value));
|
|
1398
1875
|
function setElement(value) {
|
|
1399
1876
|
resolveHTMLElementRef(value, id.value, (resolved) => {
|
|
@@ -1402,25 +1879,24 @@ var dropdown_menu_sub_trigger_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1402
1879
|
}
|
|
1403
1880
|
function onMouseenter() {
|
|
1404
1881
|
if (isDisabled.value) return;
|
|
1405
|
-
menu.
|
|
1406
|
-
sub.open(false);
|
|
1882
|
+
menu.hover(id.value, true);
|
|
1407
1883
|
}
|
|
1408
1884
|
function onClick(event) {
|
|
1409
|
-
if (!event.defaultPrevented && !isDisabled.value)
|
|
1885
|
+
if (!event.defaultPrevented && !isDisabled.value) menu.activate(id.value, event);
|
|
1410
1886
|
}
|
|
1411
1887
|
const rootAttrs = computed(() => mergeProps(attrs, {
|
|
1412
1888
|
id: id.value,
|
|
1413
1889
|
type: props.as === "button" ? "button" : void 0,
|
|
1414
1890
|
role: "menuitem",
|
|
1415
1891
|
tabindex: -1,
|
|
1416
|
-
disabled: props.as === "button" ?
|
|
1417
|
-
"aria-disabled":
|
|
1892
|
+
disabled: props.as === "button" ? toOptionalAttribute(isDisabled.value) : void 0,
|
|
1893
|
+
"aria-disabled": toOptionalAttribute(isDisabled.value),
|
|
1418
1894
|
"aria-haspopup": "menu",
|
|
1419
1895
|
"aria-expanded": sub.isOpen.value,
|
|
1420
1896
|
"aria-controls": sub.contentId.value,
|
|
1421
|
-
"data-disabled":
|
|
1422
|
-
"data-focused":
|
|
1423
|
-
"data-highlighted":
|
|
1897
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
1898
|
+
"data-focused": toOptionalAttribute(focused.value),
|
|
1899
|
+
"data-highlighted": toOptionalAttribute(focused.value),
|
|
1424
1900
|
"data-state": sub.isOpen.value ? "open" : "closed",
|
|
1425
1901
|
class: bem("rp-dropdown-menu__item", {
|
|
1426
1902
|
focused: focused.value,
|
|
@@ -1472,41 +1948,28 @@ var dropdown_menu_trigger_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1472
1948
|
root.setTrigger(resolved, id.value);
|
|
1473
1949
|
});
|
|
1474
1950
|
}
|
|
1475
|
-
function
|
|
1951
|
+
function prepareReference() {
|
|
1476
1952
|
root.setReference(element.value);
|
|
1477
1953
|
root.setReturnFocus(element.value);
|
|
1478
|
-
root.open({ focus });
|
|
1479
1954
|
}
|
|
1480
1955
|
function onClick(event) {
|
|
1481
1956
|
if (event.defaultPrevented || isDisabled.value) return;
|
|
1482
|
-
root.
|
|
1483
|
-
root.setReturnFocus(element.value);
|
|
1484
|
-
root.toggle();
|
|
1957
|
+
root.interaction.onTriggerClick(prepareReference);
|
|
1485
1958
|
}
|
|
1486
1959
|
function onKeydown(event) {
|
|
1487
1960
|
if (isDisabled.value) return;
|
|
1488
|
-
|
|
1489
|
-
event.preventDefault();
|
|
1490
|
-
openWithReference("last");
|
|
1491
|
-
} else if ([
|
|
1492
|
-
"Enter",
|
|
1493
|
-
" ",
|
|
1494
|
-
"ArrowDown"
|
|
1495
|
-
].includes(event.key)) {
|
|
1496
|
-
event.preventDefault();
|
|
1497
|
-
openWithReference("first");
|
|
1498
|
-
} else if (event.key === "Escape") root.close({ focusTrigger: true });
|
|
1961
|
+
root.interaction.onTriggerKeydown(event, prepareReference);
|
|
1499
1962
|
}
|
|
1500
1963
|
const rootAttrs = computed(() => mergeProps(attrs, {
|
|
1501
1964
|
id: id.value,
|
|
1502
1965
|
type: props.as === "button" ? "button" : void 0,
|
|
1503
|
-
disabled: props.as === "button" ?
|
|
1966
|
+
disabled: props.as === "button" ? toOptionalAttribute(isDisabled.value) : void 0,
|
|
1504
1967
|
"aria-controls": root.contentId.value,
|
|
1505
1968
|
"aria-expanded": root.isOpen.value,
|
|
1506
1969
|
"aria-haspopup": "menu",
|
|
1507
|
-
"aria-disabled": props.as === "button" ? void 0 :
|
|
1970
|
+
"aria-disabled": props.as === "button" ? void 0 : toOptionalAttribute(isDisabled.value),
|
|
1508
1971
|
"data-state": root.isOpen.value ? "open" : "closed",
|
|
1509
|
-
"data-disabled":
|
|
1972
|
+
"data-disabled": toOptionalAttribute(isDisabled.value),
|
|
1510
1973
|
onClick,
|
|
1511
1974
|
onKeydown
|
|
1512
1975
|
}));
|
|
@@ -1518,31 +1981,10 @@ var dropdown_menu_trigger_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1518
1981
|
return n1;
|
|
1519
1982
|
}
|
|
1520
1983
|
});
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
return
|
|
1525
|
-
}
|
|
1526
|
-
function getItemClass(item, focused, disabled, hasSubmenu, submenuOpen) {
|
|
1527
|
-
return bem("rp-dropdown-menu__item", {
|
|
1528
|
-
focused,
|
|
1529
|
-
disabled,
|
|
1530
|
-
destructive: item.destructive,
|
|
1531
|
-
submenu: hasSubmenu,
|
|
1532
|
-
open: submenuOpen
|
|
1533
|
-
});
|
|
1534
|
-
}
|
|
1535
|
-
function hasItemSubmenu(item) {
|
|
1536
|
-
return (item.children?.length ?? 0) > 0;
|
|
1537
|
-
}
|
|
1538
|
-
function hasNestedItems(items) {
|
|
1539
|
-
return items.some(hasItemSubmenu);
|
|
1540
|
-
}
|
|
1541
|
-
function getPathKey(path) {
|
|
1542
|
-
return path.length === 0 ? "root" : path.join("-");
|
|
1543
|
-
}
|
|
1544
|
-
function getParentPath(path) {
|
|
1545
|
-
return path.slice(0, -1);
|
|
1984
|
+
//#endregion
|
|
1985
|
+
//#region src/utils/indexPath.ts
|
|
1986
|
+
function getPathKey(path) {
|
|
1987
|
+
return path.length === 0 ? "root" : path.join("-");
|
|
1546
1988
|
}
|
|
1547
1989
|
function arePathsEqual(a, b) {
|
|
1548
1990
|
return a.length === b.length && a.every((part, index) => part === b[index]);
|
|
@@ -1553,17 +1995,21 @@ function isPathPrefix(prefix, path) {
|
|
|
1553
1995
|
function normalizePath(indexOrPath) {
|
|
1554
1996
|
return Array.isArray(indexOrPath) ? indexOrPath : [indexOrPath];
|
|
1555
1997
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1998
|
+
var DEFAULT_FOCUS_TARGET = "first";
|
|
1999
|
+
function getItemClass(item, focused, disabled, hasSubmenu, submenuOpen) {
|
|
2000
|
+
return bem("rp-dropdown-menu__item", {
|
|
2001
|
+
focused,
|
|
2002
|
+
disabled,
|
|
2003
|
+
destructive: item.destructive,
|
|
2004
|
+
submenu: hasSubmenu,
|
|
2005
|
+
open: submenuOpen
|
|
2006
|
+
});
|
|
1561
2007
|
}
|
|
1562
|
-
function
|
|
1563
|
-
return
|
|
2008
|
+
function hasItemSubmenu(item) {
|
|
2009
|
+
return (item.children?.length ?? 0) > 0;
|
|
1564
2010
|
}
|
|
1565
|
-
function
|
|
1566
|
-
return
|
|
2011
|
+
function hasNestedItems(items) {
|
|
2012
|
+
return items.some(hasItemSubmenu);
|
|
1567
2013
|
}
|
|
1568
2014
|
//#endregion
|
|
1569
2015
|
//#region src/components/dropdown-menu/dropdown-menu-item-row.vue?vue&type=script&setup=true&vapor=true&lang.ts
|
|
@@ -1595,6 +2041,10 @@ var dropdown_menu_item_row_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1595
2041
|
const slotProps = computed(() => props.context.getItemSlotProps(props.item, path.value, focused.value, disabled.value, submenuOpen.value));
|
|
1596
2042
|
const itemElement = ref(null);
|
|
1597
2043
|
const submenuElement = ref(null);
|
|
2044
|
+
const templateRefs = {
|
|
2045
|
+
item: itemElement,
|
|
2046
|
+
submenu: submenuElement
|
|
2047
|
+
};
|
|
1598
2048
|
const { actualPlacement, floatingStyle } = useFloatingPosition({
|
|
1599
2049
|
reference: itemElement,
|
|
1600
2050
|
floating: submenuElement,
|
|
@@ -1620,14 +2070,13 @@ var dropdown_menu_item_row_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1620
2070
|
function getChildKey(index, child) {
|
|
1621
2071
|
return `${getPathKey([...path.value, index])}:${String(child.value)}`;
|
|
1622
2072
|
}
|
|
1623
|
-
const _setTemplateRef = createTemplateRefSetter();
|
|
1624
2073
|
const _component_DropdownMenuItemRow__self = resolveComponent("DropdownMenuItemRow", true);
|
|
1625
2074
|
const n10 = t1$1();
|
|
1626
2075
|
const n1 = child(n10);
|
|
1627
2076
|
renderEffect(() => setDynamicProps(n1, [publicItemProps.value]));
|
|
1628
2077
|
setInsertionState(n1, null, 0);
|
|
1629
2078
|
createSlot("item", { $: [() => slotProps.value] });
|
|
1630
|
-
|
|
2079
|
+
setTemplateRefBinding(n1, () => templateRefs.item);
|
|
1631
2080
|
setInsertionState(n10, null, 1);
|
|
1632
2081
|
createIf(() => hasSubmenu.value && submenuOpen.value, () => {
|
|
1633
2082
|
const n9 = t0$1();
|
|
@@ -1647,7 +2096,7 @@ var dropdown_menu_item_row_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1647
2096
|
return createSlot("item", { $: [() => childSlotProps] });
|
|
1648
2097
|
}, { _: 8 }) });
|
|
1649
2098
|
}, (child, childIndex) => getChildKey(childIndex, child), 3);
|
|
1650
|
-
|
|
2099
|
+
setTemplateRefBinding(n9, () => templateRefs.submenu);
|
|
1651
2100
|
return n9;
|
|
1652
2101
|
});
|
|
1653
2102
|
return n10;
|
|
@@ -1681,153 +2130,167 @@ var dropdown_menu_items_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
1681
2130
|
}
|
|
1682
2131
|
});
|
|
1683
2132
|
//#endregion
|
|
1684
|
-
//#region src/components/dropdown-menu/
|
|
1685
|
-
function
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
else emit.focusOutside?.(outsideEvent);
|
|
1727
|
-
emit.interactOutside?.(outsideEvent);
|
|
1728
|
-
return outsideEvent;
|
|
1729
|
-
}
|
|
1730
|
-
function isInside(event) {
|
|
1731
|
-
return isEventWithinTargets(event, [
|
|
1732
|
-
rootRef,
|
|
1733
|
-
menuRef,
|
|
1734
|
-
targetRef,
|
|
1735
|
-
...props.ignore ?? []
|
|
1736
|
-
]);
|
|
1737
|
-
}
|
|
1738
|
-
function blockModalInteraction(event) {
|
|
1739
|
-
if (!props.modal) return;
|
|
1740
|
-
if (event.cancelable) event.preventDefault();
|
|
1741
|
-
event.stopPropagation();
|
|
1742
|
-
if (event.type === "pointerdown") blockNextDocumentClick();
|
|
1743
|
-
}
|
|
1744
|
-
function onDocumentPointerdown(event) {
|
|
1745
|
-
if (!layer.isTopLayer()) return;
|
|
1746
|
-
if (isInside(event)) return;
|
|
1747
|
-
const outsideEvent = emitOutside("pointer", event);
|
|
1748
|
-
blockModalInteraction(event);
|
|
1749
|
-
if (!outsideEvent.defaultPrevented) close({ focusTrigger: Boolean(props.modal) });
|
|
1750
|
-
}
|
|
1751
|
-
function onDocumentFocus(event) {
|
|
1752
|
-
if (!layer.isTopLayer()) return;
|
|
1753
|
-
if (isInside(event)) return;
|
|
1754
|
-
const outsideEvent = emitOutside("focus", event);
|
|
1755
|
-
blockModalInteraction(event);
|
|
1756
|
-
if (!outsideEvent.defaultPrevented) close({ focusTrigger: Boolean(props.modal) });
|
|
1757
|
-
else if (props.modal) focusMenu();
|
|
1758
|
-
}
|
|
1759
|
-
let isListening = false;
|
|
1760
|
-
function setDocumentListeners(active) {
|
|
1761
|
-
if (typeof document === "undefined" || active === isListening) return;
|
|
1762
|
-
isListening = active;
|
|
1763
|
-
const method = active ? "addEventListener" : "removeEventListener";
|
|
1764
|
-
document[method]("pointerdown", onDocumentPointerdown, true);
|
|
1765
|
-
document[method]("focusin", onDocumentFocus, true);
|
|
2133
|
+
//#region src/components/dropdown-menu/dropdownMenuDataModel.ts
|
|
2134
|
+
function createDataIndexState(rootMenuId) {
|
|
2135
|
+
return {
|
|
2136
|
+
entries: [],
|
|
2137
|
+
itemIdByPath: /* @__PURE__ */ new Map(),
|
|
2138
|
+
pathByItemId: /* @__PURE__ */ new Map(),
|
|
2139
|
+
menuIdByPath: /* @__PURE__ */ new Map([["root", rootMenuId]]),
|
|
2140
|
+
pathByMenuId: /* @__PURE__ */ new Map([[rootMenuId, []]]),
|
|
2141
|
+
primaryItemId: /* @__PURE__ */ new WeakMap(),
|
|
2142
|
+
occurrences: /* @__PURE__ */ new Map()
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
function getOccurrenceItemId(item, state, getStableItemId) {
|
|
2146
|
+
const occurrence = state.occurrences.get(item) ?? 0;
|
|
2147
|
+
state.occurrences.set(item, occurrence + 1);
|
|
2148
|
+
const stableItemId = getStableItemId(item);
|
|
2149
|
+
return {
|
|
2150
|
+
occurrence,
|
|
2151
|
+
itemId: occurrence === 0 ? stableItemId : `${stableItemId}-copy-${occurrence}`
|
|
2152
|
+
};
|
|
2153
|
+
}
|
|
2154
|
+
function indexItems(items, parentPath, ownerMenuId, state, getStableItemId) {
|
|
2155
|
+
for (const [order, item] of items.entries()) {
|
|
2156
|
+
const path = [...parentPath, order];
|
|
2157
|
+
const pathKey = getPathKey(path);
|
|
2158
|
+
const { itemId, occurrence } = getOccurrenceItemId(item, state, getStableItemId);
|
|
2159
|
+
const submenuMenuId = hasItemSubmenu(item) ? `${itemId}-menu` : void 0;
|
|
2160
|
+
state.entries.push({
|
|
2161
|
+
item,
|
|
2162
|
+
path,
|
|
2163
|
+
itemId,
|
|
2164
|
+
ownerMenuId,
|
|
2165
|
+
order,
|
|
2166
|
+
submenuMenuId
|
|
2167
|
+
});
|
|
2168
|
+
state.itemIdByPath.set(pathKey, itemId);
|
|
2169
|
+
state.pathByItemId.set(itemId, path);
|
|
2170
|
+
if (occurrence === 0) state.primaryItemId.set(item, itemId);
|
|
2171
|
+
if (!submenuMenuId) continue;
|
|
2172
|
+
state.menuIdByPath.set(pathKey, submenuMenuId);
|
|
2173
|
+
state.pathByMenuId.set(submenuMenuId, path);
|
|
2174
|
+
indexItems(item.children ?? [], path, submenuMenuId, state, getStableItemId);
|
|
1766
2175
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
2176
|
+
}
|
|
2177
|
+
function buildDropdownMenuDataIndex(items, rootMenuId, getStableItemId) {
|
|
2178
|
+
const state = createDataIndexState(rootMenuId);
|
|
2179
|
+
indexItems(items, [], rootMenuId, state, getStableItemId);
|
|
1769
2180
|
return {
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
2181
|
+
entries: state.entries,
|
|
2182
|
+
itemIdByPath: state.itemIdByPath,
|
|
2183
|
+
pathByItemId: state.pathByItemId,
|
|
2184
|
+
menuIdByPath: state.menuIdByPath,
|
|
2185
|
+
pathByMenuId: state.pathByMenuId,
|
|
2186
|
+
primaryItemId: state.primaryItemId
|
|
1774
2187
|
};
|
|
1775
2188
|
}
|
|
2189
|
+
function getDropdownMenuDataCollectionState(items) {
|
|
2190
|
+
const state = [];
|
|
2191
|
+
function collect(currentItems) {
|
|
2192
|
+
state.push(currentItems.length);
|
|
2193
|
+
for (const item of currentItems) {
|
|
2194
|
+
const children = item.children;
|
|
2195
|
+
state.push(item, Boolean(item.disabled), children);
|
|
2196
|
+
if (children) collect(children);
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
collect(items);
|
|
2200
|
+
return state;
|
|
2201
|
+
}
|
|
1776
2202
|
//#endregion
|
|
1777
|
-
//#region src/components/dropdown-menu/
|
|
1778
|
-
function
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
2203
|
+
//#region src/components/dropdown-menu/useDropdownMenuDataRegistration.ts
|
|
2204
|
+
function getCurrentPath(index, entry) {
|
|
2205
|
+
return index.pathByItemId.get(entry.itemId) ?? entry.path;
|
|
2206
|
+
}
|
|
2207
|
+
function useDropdownMenuDataRegistration({ props, items, rootMenuId, interaction, menuRef, getItemElement, getSubmenuElement, isSubmenuOpeningLeft, onSelect }) {
|
|
2208
|
+
const openMenuIds = ref(/* @__PURE__ */ new Set());
|
|
2209
|
+
const itemIdentity = /* @__PURE__ */ new WeakMap();
|
|
2210
|
+
let nextItemIdentity = 0;
|
|
2211
|
+
let registeredItemIds = /* @__PURE__ */ new Set();
|
|
2212
|
+
let registeredMenuIds = /* @__PURE__ */ new Set();
|
|
2213
|
+
function getStableItemId(item) {
|
|
2214
|
+
const existing = itemIdentity.get(item);
|
|
2215
|
+
if (existing) return existing;
|
|
2216
|
+
nextItemIdentity += 1;
|
|
2217
|
+
const id = `${rootMenuId}-item-${nextItemIdentity}`;
|
|
2218
|
+
itemIdentity.set(item, id);
|
|
2219
|
+
return id;
|
|
2220
|
+
}
|
|
2221
|
+
const registrationIndex = shallowRef(buildDropdownMenuDataIndex([], rootMenuId, getStableItemId));
|
|
2222
|
+
const collectionState = computed(() => getDropdownMenuDataCollectionState(items.value));
|
|
2223
|
+
function setMenuOpen(id, open) {
|
|
2224
|
+
const next = new Set(openMenuIds.value);
|
|
2225
|
+
if (open) next.add(id);
|
|
2226
|
+
else next.delete(id);
|
|
2227
|
+
openMenuIds.value = next;
|
|
2228
|
+
}
|
|
2229
|
+
function createMenuRegistration(index, entry) {
|
|
2230
|
+
const submenuMenuId = entry.submenuMenuId;
|
|
2231
|
+
if (!submenuMenuId) return void 0;
|
|
2232
|
+
return {
|
|
2233
|
+
id: submenuMenuId,
|
|
2234
|
+
parentItemId: () => entry.itemId,
|
|
2235
|
+
element: () => getSubmenuElement(getCurrentPath(index, entry)),
|
|
2236
|
+
focusTarget: () => menuRef.value,
|
|
2237
|
+
placement: () => {
|
|
2238
|
+
return getSubmenuElement(getCurrentPath(index, entry))?.dataset.placement ?? "right-start";
|
|
2239
|
+
},
|
|
2240
|
+
isOpen: () => openMenuIds.value.has(submenuMenuId),
|
|
2241
|
+
setOpen: (open) => setMenuOpen(submenuMenuId, open)
|
|
2242
|
+
};
|
|
1782
2243
|
}
|
|
1783
|
-
function
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
2244
|
+
function createSelectEvent(entry, originalEvent) {
|
|
2245
|
+
const event = new CustomEvent("dropdown-menu-select", {
|
|
2246
|
+
cancelable: true,
|
|
2247
|
+
detail: {
|
|
2248
|
+
originalEvent,
|
|
2249
|
+
value: entry.item.value
|
|
1788
2250
|
}
|
|
1789
|
-
|
|
2251
|
+
});
|
|
2252
|
+
onSelect?.(entry.item, event);
|
|
2253
|
+
return event;
|
|
2254
|
+
}
|
|
2255
|
+
function registerEntry(index, entry) {
|
|
2256
|
+
const menuRegistration = createMenuRegistration(index, entry);
|
|
2257
|
+
if (menuRegistration) interaction.registerMenu(menuRegistration);
|
|
2258
|
+
interaction.registerItem({
|
|
2259
|
+
id: entry.itemId,
|
|
2260
|
+
menuId: entry.ownerMenuId,
|
|
2261
|
+
element: () => getItemElement(getCurrentPath(index, entry)),
|
|
2262
|
+
textValue: () => entry.item.label,
|
|
2263
|
+
disabled: () => Boolean(entry.item.disabled || props.disabled),
|
|
2264
|
+
order: () => entry.order,
|
|
2265
|
+
submenuId: () => entry.submenuMenuId,
|
|
2266
|
+
submenuDirection: () => isSubmenuOpeningLeft(getCurrentPath(index, entry)) ? "left" : "right",
|
|
2267
|
+
select: (originalEvent) => createSelectEvent(entry, originalEvent),
|
|
2268
|
+
closeOnSelect: () => props.closeOnSelect !== false
|
|
1790
2269
|
});
|
|
1791
2270
|
}
|
|
1792
|
-
function
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
return document.getElementById(getItemId(path));
|
|
1800
|
-
}
|
|
1801
|
-
function getSubmenuElement(path) {
|
|
1802
|
-
return document.getElementById(getSubmenuId(path));
|
|
1803
|
-
}
|
|
1804
|
-
function isSubmenuOpeningLeft(path) {
|
|
1805
|
-
const submenuRect = getSubmenuElement(path)?.getBoundingClientRect();
|
|
1806
|
-
const itemRect = getItemElement(path)?.getBoundingClientRect();
|
|
1807
|
-
if (submenuRect && itemRect && hasMeasuredRect(submenuRect) && hasMeasuredRect(itemRect)) return submenuRect.right <= itemRect.left;
|
|
1808
|
-
return placement.value.endsWith("end");
|
|
1809
|
-
}
|
|
1810
|
-
function getMenuActiveDescendant(menuPath) {
|
|
1811
|
-
return arePathsEqual(getParentPath(focusedPath.value), menuPath) ? getItemId(focusedPath.value) : void 0;
|
|
2271
|
+
function unregisterStaleEntries(nextRegisteredItemIds, nextRegisteredMenuIds) {
|
|
2272
|
+
for (const id of registeredItemIds) if (!nextRegisteredItemIds.has(id)) interaction.unregisterItem(id);
|
|
2273
|
+
for (const id of registeredMenuIds) {
|
|
2274
|
+
if (nextRegisteredMenuIds.has(id)) continue;
|
|
2275
|
+
interaction.unregisterMenu(id);
|
|
2276
|
+
setMenuOpen(id, false);
|
|
2277
|
+
}
|
|
1812
2278
|
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
const
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
2279
|
+
function registerItems() {
|
|
2280
|
+
const nextIndex = buildDropdownMenuDataIndex(items.value, rootMenuId, getStableItemId);
|
|
2281
|
+
const nextRegisteredItemIds = new Set(nextIndex.entries.map((entry) => entry.itemId));
|
|
2282
|
+
const nextRegisteredMenuIds = new Set(nextIndex.entries.flatMap((entry) => entry.submenuMenuId ? [entry.submenuMenuId] : []));
|
|
2283
|
+
for (const entry of nextIndex.entries) registerEntry(nextIndex, entry);
|
|
2284
|
+
unregisterStaleEntries(nextRegisteredItemIds, nextRegisteredMenuIds);
|
|
2285
|
+
registeredItemIds = nextRegisteredItemIds;
|
|
2286
|
+
registeredMenuIds = nextRegisteredMenuIds;
|
|
2287
|
+
registrationIndex.value = nextIndex;
|
|
2288
|
+
interaction.reconcile();
|
|
2289
|
+
}
|
|
2290
|
+
watch(collectionState, registerItems, { immediate: true });
|
|
1821
2291
|
return {
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
focusTrigger,
|
|
1825
|
-
getItemId,
|
|
1826
|
-
getSubmenuId,
|
|
1827
|
-
getItemElement,
|
|
1828
|
-
getSubmenuElement,
|
|
1829
|
-
isSubmenuOpeningLeft,
|
|
1830
|
-
getMenuActiveDescendant
|
|
2292
|
+
openMenuIds,
|
|
2293
|
+
registrationIndex
|
|
1831
2294
|
};
|
|
1832
2295
|
}
|
|
1833
2296
|
//#endregion
|
|
@@ -1835,26 +2298,6 @@ function useDropdownMenuDom({ menuId, rootRef, menuRef, targetRef, placement, fo
|
|
|
1835
2298
|
var SAFE_TRIANGLE_PADDING = 2;
|
|
1836
2299
|
var SAFE_TRIANGLE_ORIGIN_OFFSET = 2;
|
|
1837
2300
|
var SAFE_TRIANGLE_TIMEOUT = 400;
|
|
1838
|
-
function getTriangleArea(a, b, c) {
|
|
1839
|
-
return Math.abs((a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y)) / 2);
|
|
1840
|
-
}
|
|
1841
|
-
function isPointInTriangle(point, triangle) {
|
|
1842
|
-
const [a, b, c] = triangle;
|
|
1843
|
-
const area = getTriangleArea(a, b, c);
|
|
1844
|
-
const area1 = getTriangleArea(point, b, c);
|
|
1845
|
-
const area2 = getTriangleArea(a, point, c);
|
|
1846
|
-
const area3 = getTriangleArea(a, b, point);
|
|
1847
|
-
return Math.abs(area - (area1 + area2 + area3)) < .5;
|
|
1848
|
-
}
|
|
1849
|
-
function clamp(value, min, max) {
|
|
1850
|
-
return Math.min(Math.max(value, min), max);
|
|
1851
|
-
}
|
|
1852
|
-
function clampPointToRect(point, rect) {
|
|
1853
|
-
return {
|
|
1854
|
-
x: clamp(point.x, rect.left, rect.right),
|
|
1855
|
-
y: clamp(point.y, rect.top, rect.bottom)
|
|
1856
|
-
};
|
|
1857
|
-
}
|
|
1858
2301
|
function getDropdownMenuSafeTriangle({ itemRect, submenuRect, origin }) {
|
|
1859
2302
|
const measuredItemRect = itemRect && hasMeasuredRect(itemRect) ? itemRect : null;
|
|
1860
2303
|
const opensRight = !measuredItemRect || submenuRect.left >= measuredItemRect.right;
|
|
@@ -1951,7 +2394,7 @@ function useDropdownMenuHoverIntent({ openSubmenuPath, getItemElement, getSubmen
|
|
|
1951
2394
|
}, SAFE_TRIANGLE_TIMEOUT);
|
|
1952
2395
|
}
|
|
1953
2396
|
function handleItemHover(item, path, event, commit) {
|
|
1954
|
-
const point = event ?
|
|
2397
|
+
const point = event ? getClientPoint(event) : void 0;
|
|
1955
2398
|
latestPointerPoint = point ?? latestPointerPoint;
|
|
1956
2399
|
if (point && shouldDelayHover(path, point)) {
|
|
1957
2400
|
delayHoveredItem(item, path, commit);
|
|
@@ -1960,7 +2403,7 @@ function useDropdownMenuHoverIntent({ openSubmenuPath, getItemElement, getSubmen
|
|
|
1960
2403
|
commit(item, path, point);
|
|
1961
2404
|
}
|
|
1962
2405
|
function handleMenuMousemove(event, commit) {
|
|
1963
|
-
const point =
|
|
2406
|
+
const point = getClientPoint(event);
|
|
1964
2407
|
latestPointerPoint = point;
|
|
1965
2408
|
updateSafeTriangleOrigin(point);
|
|
1966
2409
|
if (!pendingHover) return;
|
|
@@ -1978,221 +2421,131 @@ function useDropdownMenuHoverIntent({ openSubmenuPath, getItemElement, getSubmen
|
|
|
1978
2421
|
};
|
|
1979
2422
|
}
|
|
1980
2423
|
//#endregion
|
|
1981
|
-
//#region src/components/dropdown-menu/
|
|
1982
|
-
function
|
|
1983
|
-
function
|
|
1984
|
-
|
|
1985
|
-
if (hasItemSubmenu(item)) {
|
|
1986
|
-
openSubmenu(path, DEFAULT_FOCUS_TARGET, event instanceof MouseEvent ? getEventPoint(event) : void 0);
|
|
1987
|
-
return;
|
|
1988
|
-
}
|
|
1989
|
-
selectItem(item, event);
|
|
2424
|
+
//#region src/components/dropdown-menu/useDropdownMenuDataController.ts
|
|
2425
|
+
function useDropdownMenuDataController({ props, items, rootMenuId, menuId, menuRef, actualPlacement, interaction, onSelect }) {
|
|
2426
|
+
function getItemId(path) {
|
|
2427
|
+
return `${menuId.value}-item-${getPathKey(path)}`;
|
|
1990
2428
|
}
|
|
1991
|
-
function
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2429
|
+
function getSubmenuId(path) {
|
|
2430
|
+
return `${menuId.value}-submenu-${getPathKey(path)}`;
|
|
2431
|
+
}
|
|
2432
|
+
function getItemElement(path) {
|
|
2433
|
+
return typeof document === "undefined" ? null : document.getElementById(getItemId(path));
|
|
2434
|
+
}
|
|
2435
|
+
function getSubmenuElement(path) {
|
|
2436
|
+
return typeof document === "undefined" ? null : document.getElementById(getSubmenuId(path));
|
|
2437
|
+
}
|
|
2438
|
+
function isSubmenuOpeningLeft(path) {
|
|
2439
|
+
const submenuRect = getSubmenuElement(path)?.getBoundingClientRect();
|
|
2440
|
+
const itemRect = getItemElement(path)?.getBoundingClientRect();
|
|
2441
|
+
if (submenuRect && itemRect && hasMeasuredRect(submenuRect) && hasMeasuredRect(itemRect)) return submenuRect.right <= itemRect.left;
|
|
2442
|
+
return actualPlacement.value.endsWith("end");
|
|
2443
|
+
}
|
|
2444
|
+
const { openMenuIds, registrationIndex } = useDropdownMenuDataRegistration({
|
|
2445
|
+
props,
|
|
2446
|
+
items,
|
|
2447
|
+
rootMenuId,
|
|
2448
|
+
interaction,
|
|
2449
|
+
menuRef,
|
|
2450
|
+
getItemElement,
|
|
2451
|
+
getSubmenuElement,
|
|
2452
|
+
isSubmenuOpeningLeft,
|
|
2453
|
+
onSelect
|
|
2454
|
+
});
|
|
2455
|
+
function getDataItemId(path) {
|
|
2456
|
+
return registrationIndex.value.itemIdByPath.get(getPathKey(path));
|
|
2002
2457
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2458
|
+
const focusedPath = computed({
|
|
2459
|
+
get() {
|
|
2460
|
+
const id = interaction.activeItemId.value;
|
|
2461
|
+
return id ? [...registrationIndex.value.pathByItemId.get(id) ?? []] : [];
|
|
2462
|
+
},
|
|
2463
|
+
set(path) {
|
|
2464
|
+
interaction.setActive(path.length > 0 ? getDataItemId(path) ?? null : null);
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
const focusedIndex = computed(() => focusedPath.value[0] ?? -1);
|
|
2468
|
+
const activeDescendantId = computed(() => focusedPath.value.length === 0 ? void 0 : getItemId(focusedPath.value));
|
|
2469
|
+
const openSubmenuPath = computed(() => {
|
|
2470
|
+
let deepest = [];
|
|
2471
|
+
for (const id of openMenuIds.value) {
|
|
2472
|
+
const path = registrationIndex.value.pathByMenuId.get(id);
|
|
2473
|
+
if (path && path.length > deepest.length) deepest = path;
|
|
2474
|
+
}
|
|
2475
|
+
return [...deepest];
|
|
2476
|
+
});
|
|
2477
|
+
function isItemFocused(indexOrPath) {
|
|
2478
|
+
const id = getDataItemId(normalizePath(indexOrPath));
|
|
2479
|
+
return Boolean(id && interaction.activeItemId.value === id);
|
|
2480
|
+
}
|
|
2481
|
+
function isSubmenuOpen(path) {
|
|
2482
|
+
const itemId = getDataItemId(path);
|
|
2483
|
+
const submenuId = itemId ? interaction.getItem(itemId)?.submenuId?.() : void 0;
|
|
2484
|
+
return Boolean(submenuId && interaction.isMenuOpen(submenuId));
|
|
2006
2485
|
}
|
|
2007
2486
|
function openSubmenu(path, focus = DEFAULT_FOCUS_TARGET, point) {
|
|
2008
|
-
const
|
|
2009
|
-
|
|
2010
|
-
return
|
|
2487
|
+
const itemId = getDataItemId(path);
|
|
2488
|
+
const submenuId = itemId ? interaction.getItem(itemId)?.submenuId?.() : void 0;
|
|
2489
|
+
if (!submenuId || !interaction.openMenu(submenuId, focus)) return false;
|
|
2490
|
+
hoverIntent.trackSubmenuOpen(path, point);
|
|
2491
|
+
return true;
|
|
2011
2492
|
}
|
|
2012
2493
|
function closeSubmenu(path) {
|
|
2013
|
-
const
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
}
|
|
2017
|
-
function closeCurrentSubmenu() {
|
|
2018
|
-
const closed = submenus.closeCurrentSubmenu();
|
|
2494
|
+
const itemId = getDataItemId(path);
|
|
2495
|
+
const submenuId = itemId ? interaction.getItem(itemId)?.submenuId?.() : void 0;
|
|
2496
|
+
const closed = submenuId ? interaction.closeMenu(submenuId, false) : false;
|
|
2019
2497
|
if (closed) hoverIntent.resetHoverIntent();
|
|
2020
2498
|
return closed;
|
|
2021
2499
|
}
|
|
2022
2500
|
function commitHoveredItem(item, path, point) {
|
|
2501
|
+
const itemId = getDataItemId(path);
|
|
2502
|
+
const itemRegistration = itemId ? interaction.getItem(itemId) : void 0;
|
|
2503
|
+
if (!itemRegistration) return;
|
|
2023
2504
|
hoverIntent.clearPendingHover();
|
|
2024
|
-
|
|
2505
|
+
interaction.setActive(itemRegistration.id);
|
|
2025
2506
|
if (hasItemSubmenu(item)) openSubmenu(path, false, point);
|
|
2026
|
-
else
|
|
2507
|
+
else interaction.closeSubmenus(itemRegistration.menuId);
|
|
2027
2508
|
}
|
|
2509
|
+
const hoverIntent = useDropdownMenuHoverIntent({
|
|
2510
|
+
openSubmenuPath,
|
|
2511
|
+
getItemElement,
|
|
2512
|
+
getSubmenuElement
|
|
2513
|
+
});
|
|
2028
2514
|
function focusHoveredItem(item, indexOrPath, event) {
|
|
2029
2515
|
if (item.disabled) return;
|
|
2030
|
-
|
|
2031
|
-
hoverIntent.handleItemHover(item, path, event, commitHoveredItem);
|
|
2032
|
-
}
|
|
2033
|
-
function selectFocusedItem(event) {
|
|
2034
|
-
const item = getItemAtPath(focusedPath.value);
|
|
2035
|
-
if (!item) return;
|
|
2036
|
-
activateItem(item, focusedPath.value, event);
|
|
2037
|
-
}
|
|
2038
|
-
function moveFocusedItem(direction) {
|
|
2039
|
-
const menuPath = moveFocus(direction);
|
|
2040
|
-
if (menuPath) closeSubmenusAfter(menuPath);
|
|
2041
|
-
}
|
|
2042
|
-
function onTriggerClick() {
|
|
2043
|
-
disclosure.toggle();
|
|
2044
|
-
}
|
|
2045
|
-
function onTriggerKeydown(event) {
|
|
2046
|
-
if (isDisabled.value) return;
|
|
2047
|
-
switch (event.key) {
|
|
2048
|
-
case "Enter":
|
|
2049
|
-
case " ":
|
|
2050
|
-
case "ArrowDown":
|
|
2051
|
-
event.preventDefault();
|
|
2052
|
-
disclosure.open();
|
|
2053
|
-
break;
|
|
2054
|
-
case "ArrowUp":
|
|
2055
|
-
event.preventDefault();
|
|
2056
|
-
disclosure.open({ focus: "last" });
|
|
2057
|
-
break;
|
|
2058
|
-
case "Escape":
|
|
2059
|
-
disclosure.close({ focusTrigger: true });
|
|
2060
|
-
break;
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
function onMenuKeydown(event) {
|
|
2064
|
-
hoverIntent.resetHoverIntent();
|
|
2065
|
-
if (handleTypeahead(event)) return;
|
|
2066
|
-
switch (event.key) {
|
|
2067
|
-
case "ArrowDown":
|
|
2068
|
-
event.preventDefault();
|
|
2069
|
-
moveFocusedItem(1);
|
|
2070
|
-
break;
|
|
2071
|
-
case "ArrowUp":
|
|
2072
|
-
event.preventDefault();
|
|
2073
|
-
moveFocusedItem(-1);
|
|
2074
|
-
break;
|
|
2075
|
-
case "Home":
|
|
2076
|
-
event.preventDefault();
|
|
2077
|
-
focusItem("first", getParentPath(focusedPath.value));
|
|
2078
|
-
break;
|
|
2079
|
-
case "End":
|
|
2080
|
-
event.preventDefault();
|
|
2081
|
-
focusItem("last", getParentPath(focusedPath.value));
|
|
2082
|
-
break;
|
|
2083
|
-
case "ArrowRight":
|
|
2084
|
-
case "ArrowLeft":
|
|
2085
|
-
onMenuHorizontalKeydown(event);
|
|
2086
|
-
break;
|
|
2087
|
-
case "Enter":
|
|
2088
|
-
case " ":
|
|
2089
|
-
event.preventDefault();
|
|
2090
|
-
selectFocusedItem(event);
|
|
2091
|
-
break;
|
|
2092
|
-
case "Escape":
|
|
2093
|
-
event.preventDefault();
|
|
2094
|
-
if (!closeCurrentSubmenu()) disclosure.close({ focusTrigger: true });
|
|
2095
|
-
break;
|
|
2096
|
-
case "Tab":
|
|
2097
|
-
disclosure.close();
|
|
2098
|
-
break;
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
function onMenuHorizontalKeydown(event) {
|
|
2102
|
-
const isRight = event.key === "ArrowRight";
|
|
2103
|
-
const currentMenuPath = getParentPath(focusedPath.value);
|
|
2104
|
-
const closePath = focusedPath.value.length > 1 ? currentMenuPath : arePathsEqual(focusedPath.value, openSubmenuPath.value) ? focusedPath.value : void 0;
|
|
2105
|
-
if (closePath && isRight === isSubmenuOpeningLeft(closePath)) {
|
|
2106
|
-
event.preventDefault();
|
|
2107
|
-
closeSubmenu(closePath);
|
|
2108
|
-
return;
|
|
2109
|
-
}
|
|
2110
|
-
const item = getItemAtPath(focusedPath.value);
|
|
2111
|
-
if (!item || item.disabled || !hasItemSubmenu(item)) return;
|
|
2112
|
-
if (isRight === isSubmenuOpeningLeft(focusedPath.value)) return;
|
|
2113
|
-
event.preventDefault();
|
|
2114
|
-
openSubmenu(focusedPath.value);
|
|
2115
|
-
}
|
|
2116
|
-
function onMenuMousemove(event) {
|
|
2117
|
-
hoverIntent.handleMenuMousemove(event, commitHoveredItem);
|
|
2118
|
-
}
|
|
2119
|
-
function onMenuMouseleave() {
|
|
2120
|
-
hoverIntent.resetHoverIntent();
|
|
2121
|
-
}
|
|
2122
|
-
return {
|
|
2123
|
-
activateItem,
|
|
2124
|
-
selectItem,
|
|
2125
|
-
openSubmenu,
|
|
2126
|
-
closeSubmenu,
|
|
2127
|
-
focusHoveredItem,
|
|
2128
|
-
onTriggerClick,
|
|
2129
|
-
onTriggerKeydown,
|
|
2130
|
-
onMenuKeydown,
|
|
2131
|
-
onMenuMousemove,
|
|
2132
|
-
onMenuMouseleave
|
|
2133
|
-
};
|
|
2134
|
-
}
|
|
2135
|
-
//#endregion
|
|
2136
|
-
//#region src/components/dropdown-menu/useDropdownMenuNavigation.ts
|
|
2137
|
-
function useDropdownMenuNavigation(items) {
|
|
2138
|
-
const focusedPath = ref([]);
|
|
2139
|
-
const focusedIndex = computed(() => focusedPath.value[0] ?? -1);
|
|
2140
|
-
function getItemsAtPath(path) {
|
|
2141
|
-
let currentItems = items.value;
|
|
2142
|
-
for (const index of path) {
|
|
2143
|
-
const item = currentItems[index];
|
|
2144
|
-
if (!item) return [];
|
|
2145
|
-
currentItems = item.children ?? [];
|
|
2146
|
-
}
|
|
2147
|
-
return currentItems;
|
|
2516
|
+
hoverIntent.handleItemHover(item, normalizePath(indexOrPath), event, commitHoveredItem);
|
|
2148
2517
|
}
|
|
2149
|
-
function
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
}
|
|
2153
|
-
function focusItem(target, menuPath = []) {
|
|
2154
|
-
const enabledIndexes = getEnabledIndexes(getItemsAtPath(menuPath), (item) => Boolean(item.disabled));
|
|
2155
|
-
const index = target === "last" ? enabledIndexes[enabledIndexes.length - 1] : enabledIndexes[0];
|
|
2156
|
-
if (index === void 0) {
|
|
2157
|
-
if (menuPath.length === 0) focusedPath.value = [];
|
|
2158
|
-
return false;
|
|
2159
|
-
}
|
|
2160
|
-
focusedPath.value = [...menuPath, index];
|
|
2161
|
-
return true;
|
|
2518
|
+
function selectItem(item, originalEvent = new Event("select")) {
|
|
2519
|
+
const id = registrationIndex.value.primaryItemId.get(item);
|
|
2520
|
+
if (id) interaction.selectItem(id, originalEvent);
|
|
2162
2521
|
}
|
|
2163
|
-
function
|
|
2164
|
-
|
|
2522
|
+
function activateItem(_item, path, event) {
|
|
2523
|
+
const id = getDataItemId(path);
|
|
2524
|
+
if (id) interaction.activateItem(id, event);
|
|
2165
2525
|
}
|
|
2166
|
-
function
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
return
|
|
2171
|
-
}
|
|
2172
|
-
function isItemFocused(indexOrPath) {
|
|
2173
|
-
return arePathsEqual(normalizePath(indexOrPath), focusedPath.value);
|
|
2174
|
-
}
|
|
2175
|
-
function moveFocus(direction) {
|
|
2176
|
-
const menuPath = getParentPath(focusedPath.value);
|
|
2177
|
-
const itemsAtPath = getItemsAtPath(menuPath);
|
|
2178
|
-
const nextIndex = getNextEnabledIndex(itemsAtPath, focusedPath.value.length === 0 ? direction === 1 ? -1 : itemsAtPath.length : focusedPath.value[focusedPath.value.length - 1], direction, (item) => Boolean(item.disabled));
|
|
2179
|
-
if (nextIndex === void 0) {
|
|
2180
|
-
focusedPath.value = [];
|
|
2181
|
-
return;
|
|
2182
|
-
}
|
|
2183
|
-
focusedPath.value = [...menuPath, nextIndex];
|
|
2184
|
-
return menuPath;
|
|
2526
|
+
function getMenuActiveDescendant(path) {
|
|
2527
|
+
const pathKey = getPathKey(path);
|
|
2528
|
+
const activeId = interaction.getActiveId(registrationIndex.value.menuIdByPath.get(pathKey) ?? rootMenuId).value;
|
|
2529
|
+
const activePath = activeId ? registrationIndex.value.pathByItemId.get(activeId) : void 0;
|
|
2530
|
+
return activePath ? getItemId(activePath) : void 0;
|
|
2185
2531
|
}
|
|
2186
2532
|
return {
|
|
2187
2533
|
focusedPath,
|
|
2188
2534
|
focusedIndex,
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2535
|
+
activeDescendantId,
|
|
2536
|
+
getItemId,
|
|
2537
|
+
getSubmenuId,
|
|
2538
|
+
getItemElement,
|
|
2539
|
+
getMenuActiveDescendant,
|
|
2194
2540
|
isItemFocused,
|
|
2195
|
-
|
|
2541
|
+
isSubmenuOpen,
|
|
2542
|
+
openSubmenu,
|
|
2543
|
+
closeSubmenu,
|
|
2544
|
+
focusHoveredItem,
|
|
2545
|
+
onMenuMousemove: (event) => hoverIntent.handleMenuMousemove(event, commitHoveredItem),
|
|
2546
|
+
resetHoverIntent: hoverIntent.resetHoverIntent,
|
|
2547
|
+
selectItem,
|
|
2548
|
+
activateItem
|
|
2196
2549
|
};
|
|
2197
2550
|
}
|
|
2198
2551
|
//#endregion
|
|
@@ -2210,8 +2563,7 @@ function useDropdownMenuPortalPosition(options) {
|
|
|
2210
2563
|
flipOptions: () => options.props.flipOptions,
|
|
2211
2564
|
shift: () => options.props.shift !== false,
|
|
2212
2565
|
collisionPadding: () => options.props.collisionPadding ?? 8,
|
|
2213
|
-
autoUpdateOptions: () => options.props.autoUpdateOptions
|
|
2214
|
-
restartKey: options.restartKey
|
|
2566
|
+
autoUpdateOptions: () => options.props.autoUpdateOptions
|
|
2215
2567
|
});
|
|
2216
2568
|
return {
|
|
2217
2569
|
actualPlacement: floating.actualPlacement,
|
|
@@ -2220,6 +2572,67 @@ function useDropdownMenuPortalPosition(options) {
|
|
|
2220
2572
|
};
|
|
2221
2573
|
}
|
|
2222
2574
|
//#endregion
|
|
2575
|
+
//#region src/components/dropdown-menu/useDropdownMenuPresentation.ts
|
|
2576
|
+
function useDropdownMenuPresentation({ props, rootMenuId, menuId, isDisabled, isVisible, isExplicitTarget, actualPlacement, contentHasSubmenu, activeDescendantId, interaction, resetHoverIntent, onMenuMousemove, open, close, toggle }) {
|
|
2577
|
+
const rootClass = computed(() => bem("rp-dropdown-menu", {
|
|
2578
|
+
[`placement-${actualPlacement.value}`]: true,
|
|
2579
|
+
target: isExplicitTarget.value,
|
|
2580
|
+
open: isVisible.value,
|
|
2581
|
+
disabled: isDisabled.value
|
|
2582
|
+
}));
|
|
2583
|
+
const contentClass = computed(() => bem("rp-dropdown-menu__content", { "has-submenu": contentHasSubmenu.value }));
|
|
2584
|
+
const triggerProps = computed(() => ({
|
|
2585
|
+
"aria-controls": isDisabled.value ? void 0 : menuId.value,
|
|
2586
|
+
"aria-expanded": isDisabled.value ? void 0 : isVisible.value,
|
|
2587
|
+
"aria-haspopup": "menu",
|
|
2588
|
+
disabled: isDisabled.value || void 0,
|
|
2589
|
+
onClick: () => interaction.onTriggerClick(),
|
|
2590
|
+
onKeydown: (event) => interaction.onTriggerKeydown(event)
|
|
2591
|
+
}));
|
|
2592
|
+
function getKeyboardMenuId(event) {
|
|
2593
|
+
const activeItem = interaction.activeItemId.value ? interaction.getItem(interaction.activeItemId.value) : void 0;
|
|
2594
|
+
const openSubmenuId = activeItem?.submenuId?.();
|
|
2595
|
+
if (openSubmenuId && interaction.isMenuOpen(openSubmenuId)) {
|
|
2596
|
+
if (event.key === "Escape") return openSubmenuId;
|
|
2597
|
+
const opensLeft = activeItem?.submenuDirection?.() === "left" || interaction.getMenu(openSubmenuId)?.placement().startsWith("left");
|
|
2598
|
+
if (event.key === (opensLeft ? "ArrowRight" : "ArrowLeft")) return openSubmenuId;
|
|
2599
|
+
}
|
|
2600
|
+
if ([
|
|
2601
|
+
"ArrowLeft",
|
|
2602
|
+
"ArrowRight",
|
|
2603
|
+
"Escape"
|
|
2604
|
+
].includes(event.key) && interaction.activeMenuId.value !== rootMenuId) return interaction.activeMenuId.value;
|
|
2605
|
+
return activeItem?.menuId ?? interaction.activeMenuId.value;
|
|
2606
|
+
}
|
|
2607
|
+
function onMenuKeydown(event) {
|
|
2608
|
+
resetHoverIntent();
|
|
2609
|
+
interaction.onMenuKeydown(getKeyboardMenuId(event), event);
|
|
2610
|
+
}
|
|
2611
|
+
return {
|
|
2612
|
+
rootClass,
|
|
2613
|
+
contentClass,
|
|
2614
|
+
triggerProps,
|
|
2615
|
+
contentProps: computed(() => ({
|
|
2616
|
+
id: menuId.value,
|
|
2617
|
+
role: "menu",
|
|
2618
|
+
tabindex: -1,
|
|
2619
|
+
"aria-label": props.ariaLabel || void 0,
|
|
2620
|
+
"aria-activedescendant": activeDescendantId.value,
|
|
2621
|
+
onKeydown: onMenuKeydown,
|
|
2622
|
+
onMousemove: onMenuMousemove,
|
|
2623
|
+
onMouseleave: resetHoverIntent
|
|
2624
|
+
})),
|
|
2625
|
+
slotProps: computed(() => ({
|
|
2626
|
+
triggerProps: triggerProps.value,
|
|
2627
|
+
isOpen: isVisible.value,
|
|
2628
|
+
open,
|
|
2629
|
+
close,
|
|
2630
|
+
toggle
|
|
2631
|
+
})),
|
|
2632
|
+
onMenuKeydown
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
//#endregion
|
|
2223
2636
|
//#region src/components/dropdown-menu/useDropdownMenuRenderItems.ts
|
|
2224
2637
|
function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId, getSubmenuId, getMenuActiveDescendant, getItemElement, isItemFocused, isSubmenuOpen, activateItem, focusHoveredItem, selectItem, openSubmenu, closeSubmenu, close }) {
|
|
2225
2638
|
const renderedItems = computed(() => getRenderedItems(items.value));
|
|
@@ -2262,9 +2675,9 @@ function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId,
|
|
|
2262
2675
|
"aria-expanded": hasSubmenu ? resolvedSubmenuOpen : void 0,
|
|
2263
2676
|
"aria-haspopup": hasSubmenu ? "menu" : void 0,
|
|
2264
2677
|
"aria-disabled": disabled || void 0,
|
|
2265
|
-
"data-disabled": disabled
|
|
2266
|
-
"data-highlighted": focused
|
|
2267
|
-
"data-submenu": hasSubmenu
|
|
2678
|
+
"data-disabled": toPresenceAttribute(disabled),
|
|
2679
|
+
"data-highlighted": toPresenceAttribute(focused),
|
|
2680
|
+
"data-submenu": toPresenceAttribute(hasSubmenu),
|
|
2268
2681
|
onClick: (event) => activateItem(item, path, event),
|
|
2269
2682
|
onMouseenter: (event) => focusHoveredItem(item, path, event)
|
|
2270
2683
|
};
|
|
@@ -2322,45 +2735,66 @@ function useDropdownMenuRenderItems({ props, actualPlacement, items, getItemId,
|
|
|
2322
2735
|
};
|
|
2323
2736
|
}
|
|
2324
2737
|
//#endregion
|
|
2325
|
-
//#region src/components/dropdown-menu/
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2738
|
+
//#region src/components/dropdown-menu/useDropdownMenuTargetBindings.ts
|
|
2739
|
+
var TARGET_ATTRIBUTES = [
|
|
2740
|
+
"aria-controls",
|
|
2741
|
+
"aria-expanded",
|
|
2742
|
+
"aria-haspopup",
|
|
2743
|
+
"aria-disabled"
|
|
2744
|
+
];
|
|
2745
|
+
function syncTargetAttributes(target, id, visible, disabled) {
|
|
2746
|
+
if (disabled) {
|
|
2747
|
+
target.removeAttribute("aria-controls");
|
|
2748
|
+
target.removeAttribute("aria-expanded");
|
|
2749
|
+
target.removeAttribute("aria-haspopup");
|
|
2750
|
+
target.setAttribute("aria-disabled", "true");
|
|
2751
|
+
return;
|
|
2752
|
+
}
|
|
2753
|
+
target.setAttribute("aria-controls", id);
|
|
2754
|
+
target.setAttribute("aria-expanded", String(visible));
|
|
2755
|
+
target.setAttribute("aria-haspopup", "menu");
|
|
2756
|
+
target.removeAttribute("aria-disabled");
|
|
2757
|
+
}
|
|
2758
|
+
function useDropdownMenuTargetBindings({ interaction, rootRef, menuRef, targetElement, isExplicitTarget, menuId, isVisible, isDisabled, ignoredTargets, pointerDownOutside, focusOutside, interactOutside }) {
|
|
2759
|
+
function watchInside(source) {
|
|
2760
|
+
watch(source, (element, previous) => {
|
|
2761
|
+
if (previous) interaction.unregisterInside(previous);
|
|
2762
|
+
if (element) interaction.registerInside(element);
|
|
2763
|
+
}, { immediate: true });
|
|
2764
|
+
}
|
|
2765
|
+
watchInside(rootRef);
|
|
2766
|
+
watchInside(menuRef);
|
|
2767
|
+
watchInside(targetElement);
|
|
2768
|
+
const cleanupDismissal = interaction.registerDismissal({
|
|
2769
|
+
ignoredTargets,
|
|
2770
|
+
pointerDownOutside,
|
|
2771
|
+
focusOutside,
|
|
2772
|
+
interactOutside
|
|
2773
|
+
});
|
|
2774
|
+
watch([isExplicitTarget, targetElement], ([explicit, target], _previous, onCleanup) => {
|
|
2775
|
+
if (!explicit || !target) return;
|
|
2776
|
+
const onClick = () => interaction.onTriggerClick();
|
|
2777
|
+
const onKeydown = (event) => interaction.onTriggerKeydown(event);
|
|
2778
|
+
target.addEventListener("click", onClick);
|
|
2779
|
+
target.addEventListener("keydown", onKeydown);
|
|
2780
|
+
onCleanup(() => {
|
|
2781
|
+
target.removeEventListener("click", onClick);
|
|
2782
|
+
target.removeEventListener("keydown", onKeydown);
|
|
2783
|
+
});
|
|
2784
|
+
}, { flush: "sync" });
|
|
2785
|
+
watch([
|
|
2786
|
+
isExplicitTarget,
|
|
2787
|
+
targetElement,
|
|
2788
|
+
menuId,
|
|
2789
|
+
isVisible,
|
|
2790
|
+
isDisabled
|
|
2791
|
+
], ([explicit, target, id, visible, disabled], _previous, onCleanup) => {
|
|
2792
|
+
if (!explicit || !target) return;
|
|
2793
|
+
const snapshot = snapshotAttributes(target, TARGET_ATTRIBUTES);
|
|
2794
|
+
syncTargetAttributes(target, id, visible, disabled);
|
|
2795
|
+
onCleanup(() => restoreAttributes(target, snapshot));
|
|
2796
|
+
}, { flush: "sync" });
|
|
2797
|
+
onBeforeUnmount(cleanupDismissal);
|
|
2364
2798
|
}
|
|
2365
2799
|
//#endregion
|
|
2366
2800
|
//#region src/components/dropdown-menu/useDropdownMenu.ts
|
|
@@ -2368,18 +2802,23 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
2368
2802
|
const rootRef = ref(null);
|
|
2369
2803
|
const menuRef = ref(null);
|
|
2370
2804
|
const arrowRef = ref(null);
|
|
2371
|
-
const uncontrolledOpen = ref(false);
|
|
2372
2805
|
const generatedId = useId();
|
|
2806
|
+
const interactionRootMenuId = `${generatedId}-interaction-root`;
|
|
2807
|
+
const controllableOpen = useControllableValue({
|
|
2808
|
+
modelValue: () => props.open,
|
|
2809
|
+
defaultValue: () => false,
|
|
2810
|
+
onChange: (open) => emit.openChange?.(open)
|
|
2811
|
+
});
|
|
2373
2812
|
const menuId = computed(() => props.id ?? `${generatedId}-menu`);
|
|
2374
2813
|
const placement = computed(() => props.placement ?? "bottom-start");
|
|
2375
2814
|
const teleportTo = useTeleportTarget(() => props.teleportTo);
|
|
2376
|
-
const teleportPositioningKey = useTeleportPositioningKey();
|
|
2377
2815
|
const shouldTeleport = computed(() => props.teleport !== false);
|
|
2378
2816
|
const { isExplicitTarget, reference, resolvedTarget } = useFloatingTarget(() => props.target, rootRef);
|
|
2379
|
-
const targetElement = computed(() =>
|
|
2817
|
+
const targetElement = computed(() => isElement(resolvedTarget.value) ? resolvedTarget.value : null);
|
|
2380
2818
|
const visibleItems = computed(() => props.items ?? []);
|
|
2381
2819
|
const isDisabled = computed(() => Boolean(props.disabled));
|
|
2382
|
-
const
|
|
2820
|
+
const modal = computed(() => Boolean(props.modal));
|
|
2821
|
+
const isOpen = controllableOpen.value;
|
|
2383
2822
|
const isVisible = computed(() => isOpen.value && !isDisabled.value);
|
|
2384
2823
|
const layer = useOverlayLayer({
|
|
2385
2824
|
active: isVisible,
|
|
@@ -2398,173 +2837,107 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
2398
2837
|
menuRef,
|
|
2399
2838
|
arrowRef,
|
|
2400
2839
|
isVisible,
|
|
2401
|
-
placement
|
|
2402
|
-
restartKey: () => [
|
|
2403
|
-
shouldTeleport.value,
|
|
2404
|
-
teleportTo.value,
|
|
2405
|
-
teleportPositioningKey.value
|
|
2406
|
-
]
|
|
2840
|
+
placement
|
|
2407
2841
|
});
|
|
2408
2842
|
const placementSide = computed(() => actualPlacement.value.split("-")[0]);
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2843
|
+
function focusTrigger() {
|
|
2844
|
+
nextTick(() => {
|
|
2845
|
+
if (targetElement.value instanceof HTMLElement) {
|
|
2846
|
+
targetElement.value.focus();
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
rootRef.value?.querySelector("[aria-haspopup=\"menu\"]")?.focus();
|
|
2850
|
+
});
|
|
2851
|
+
}
|
|
2852
|
+
function setOpen(nextOpen) {
|
|
2853
|
+
if (nextOpen && isDisabled.value) return;
|
|
2854
|
+
if (isOpen.value !== nextOpen) controllableOpen.setValue(nextOpen);
|
|
2855
|
+
}
|
|
2856
|
+
let resetHoverIntent;
|
|
2857
|
+
const interaction = useDropdownMenuInteraction({
|
|
2858
|
+
rootMenuId: interactionRootMenuId,
|
|
2859
|
+
isOpen: isVisible,
|
|
2860
|
+
disabled: isDisabled,
|
|
2861
|
+
modal,
|
|
2862
|
+
setOpen,
|
|
2863
|
+
isTopLayer: layer.isTopLayer,
|
|
2864
|
+
focusTrigger,
|
|
2865
|
+
beforeOpen: () => resetHoverIntent(),
|
|
2866
|
+
beforeClose: () => resetHoverIntent()
|
|
2414
2867
|
});
|
|
2415
|
-
const
|
|
2416
|
-
const
|
|
2417
|
-
const
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
scopeKey: () => activeMenuPath.value.join("/"),
|
|
2424
|
-
onMatch(_item, index) {
|
|
2425
|
-
const menuPath = activeMenuPath.value;
|
|
2426
|
-
if (setFocusedIndex(index, menuPath)) submenus.closeSubmenusAfter(menuPath);
|
|
2427
|
-
}
|
|
2868
|
+
const open = interaction.open;
|
|
2869
|
+
const close = (options = {}) => interaction.close(options);
|
|
2870
|
+
const toggle = interaction.toggle;
|
|
2871
|
+
const cleanupRootMenu = interaction.registerMenu({
|
|
2872
|
+
id: interactionRootMenuId,
|
|
2873
|
+
element: () => menuRef.value,
|
|
2874
|
+
placement: () => actualPlacement.value,
|
|
2875
|
+
isOpen: () => isVisible.value
|
|
2428
2876
|
});
|
|
2429
|
-
const
|
|
2877
|
+
const dataController = useDropdownMenuDataController({
|
|
2878
|
+
props,
|
|
2879
|
+
items: visibleItems,
|
|
2880
|
+
rootMenuId: interactionRootMenuId,
|
|
2430
2881
|
menuId,
|
|
2431
|
-
rootRef,
|
|
2432
2882
|
menuRef,
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
});
|
|
2437
|
-
const hoverIntent = useDropdownMenuHoverIntent({
|
|
2438
|
-
openSubmenuPath,
|
|
2439
|
-
getItemElement,
|
|
2440
|
-
getSubmenuElement
|
|
2883
|
+
actualPlacement,
|
|
2884
|
+
interaction,
|
|
2885
|
+
onSelect: (item, event) => emit.select?.(item, event)
|
|
2441
2886
|
});
|
|
2442
|
-
|
|
2887
|
+
resetHoverIntent = dataController.resetHoverIntent;
|
|
2888
|
+
const { renderedItems, renderContext, getItemProps, getItemSlotProps } = useDropdownMenuRenderItems({
|
|
2443
2889
|
props,
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
focusTrigger,
|
|
2459
|
-
layer
|
|
2890
|
+
actualPlacement,
|
|
2891
|
+
items: visibleItems,
|
|
2892
|
+
getItemId: dataController.getItemId,
|
|
2893
|
+
getSubmenuId: dataController.getSubmenuId,
|
|
2894
|
+
getMenuActiveDescendant: dataController.getMenuActiveDescendant,
|
|
2895
|
+
getItemElement: dataController.getItemElement,
|
|
2896
|
+
isItemFocused: dataController.isItemFocused,
|
|
2897
|
+
isSubmenuOpen: dataController.isSubmenuOpen,
|
|
2898
|
+
activateItem: dataController.activateItem,
|
|
2899
|
+
focusHoveredItem: dataController.focusHoveredItem,
|
|
2900
|
+
selectItem: dataController.selectItem,
|
|
2901
|
+
openSubmenu: dataController.openSubmenu,
|
|
2902
|
+
closeSubmenu: dataController.closeSubmenu,
|
|
2903
|
+
close
|
|
2460
2904
|
});
|
|
2461
|
-
const
|
|
2462
|
-
const { activateItem, selectItem, openSubmenu, closeSubmenu, focusHoveredItem, onTriggerClick, onTriggerKeydown, onMenuKeydown, onMenuMousemove, onMenuMouseleave } = useDropdownMenuInteractions({
|
|
2905
|
+
const presentation = useDropdownMenuPresentation({
|
|
2463
2906
|
props,
|
|
2464
|
-
|
|
2907
|
+
rootMenuId: interactionRootMenuId,
|
|
2908
|
+
menuId,
|
|
2465
2909
|
isDisabled,
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
disclosure,
|
|
2475
|
-
isSubmenuOpeningLeft
|
|
2476
|
-
});
|
|
2477
|
-
const rootClass = computed(() => bem("rp-dropdown-menu", {
|
|
2478
|
-
[`placement-${actualPlacement.value}`]: true,
|
|
2479
|
-
target: isExplicitTarget.value,
|
|
2480
|
-
open: isVisible.value,
|
|
2481
|
-
disabled: isDisabled.value
|
|
2482
|
-
}));
|
|
2483
|
-
const contentClass = computed(() => bem("rp-dropdown-menu__content", { "has-submenu": contentHasSubmenu.value }));
|
|
2484
|
-
const triggerProps = computed(() => ({
|
|
2485
|
-
"aria-controls": isDisabled.value ? void 0 : menuId.value,
|
|
2486
|
-
"aria-expanded": isDisabled.value ? void 0 : isVisible.value,
|
|
2487
|
-
"aria-haspopup": "menu",
|
|
2488
|
-
disabled: isDisabled.value || void 0,
|
|
2489
|
-
onClick: onTriggerClick,
|
|
2490
|
-
onKeydown: onTriggerKeydown
|
|
2491
|
-
}));
|
|
2492
|
-
const contentProps = computed(() => ({
|
|
2493
|
-
id: menuId.value,
|
|
2494
|
-
role: "menu",
|
|
2495
|
-
tabindex: -1,
|
|
2496
|
-
"aria-label": props.ariaLabel || void 0,
|
|
2497
|
-
"aria-activedescendant": activeDescendantId.value,
|
|
2498
|
-
onKeydown: onMenuKeydown,
|
|
2499
|
-
onMousemove: onMenuMousemove,
|
|
2500
|
-
onMouseleave: onMenuMouseleave
|
|
2501
|
-
}));
|
|
2502
|
-
const slotProps = computed(() => ({
|
|
2503
|
-
triggerProps: triggerProps.value,
|
|
2504
|
-
isOpen: isVisible.value,
|
|
2910
|
+
isVisible,
|
|
2911
|
+
isExplicitTarget,
|
|
2912
|
+
actualPlacement,
|
|
2913
|
+
contentHasSubmenu,
|
|
2914
|
+
activeDescendantId: dataController.activeDescendantId,
|
|
2915
|
+
interaction,
|
|
2916
|
+
resetHoverIntent,
|
|
2917
|
+
onMenuMousemove: dataController.onMenuMousemove,
|
|
2505
2918
|
open,
|
|
2506
2919
|
close,
|
|
2507
2920
|
toggle
|
|
2508
|
-
}));
|
|
2509
|
-
const { renderedItems, renderContext, getItemProps, getItemSlotProps } = useDropdownMenuRenderItems({
|
|
2510
|
-
props,
|
|
2511
|
-
actualPlacement,
|
|
2512
|
-
items: visibleItems,
|
|
2513
|
-
getItemId,
|
|
2514
|
-
getSubmenuId,
|
|
2515
|
-
getMenuActiveDescendant,
|
|
2516
|
-
getItemElement,
|
|
2517
|
-
isItemFocused,
|
|
2518
|
-
isSubmenuOpen,
|
|
2519
|
-
activateItem,
|
|
2520
|
-
focusHoveredItem,
|
|
2521
|
-
selectItem,
|
|
2522
|
-
openSubmenu,
|
|
2523
|
-
closeSubmenu,
|
|
2524
|
-
close
|
|
2525
2921
|
});
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
onCleanup(() => {
|
|
2531
|
-
target.removeEventListener("click", onTriggerClick);
|
|
2532
|
-
target.removeEventListener("keydown", onTriggerKeydown);
|
|
2533
|
-
});
|
|
2534
|
-
}, { flush: "sync" });
|
|
2535
|
-
watch(isVisible, (visible) => {
|
|
2536
|
-
if (!visible) typeahead.reset();
|
|
2537
|
-
}, { flush: "sync" });
|
|
2538
|
-
watch([
|
|
2539
|
-
isExplicitTarget,
|
|
2922
|
+
useDropdownMenuTargetBindings({
|
|
2923
|
+
interaction,
|
|
2924
|
+
rootRef,
|
|
2925
|
+
menuRef,
|
|
2540
2926
|
targetElement,
|
|
2927
|
+
isExplicitTarget,
|
|
2541
2928
|
menuId,
|
|
2542
2929
|
isVisible,
|
|
2543
|
-
isDisabled
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
target.removeAttribute("aria-expanded");
|
|
2555
|
-
target.removeAttribute("aria-haspopup");
|
|
2556
|
-
target.setAttribute("aria-disabled", "true");
|
|
2557
|
-
} else {
|
|
2558
|
-
target.setAttribute("aria-controls", id);
|
|
2559
|
-
target.setAttribute("aria-expanded", String(visible));
|
|
2560
|
-
target.setAttribute("aria-haspopup", "menu");
|
|
2561
|
-
target.removeAttribute("aria-disabled");
|
|
2562
|
-
}
|
|
2563
|
-
onCleanup(() => {
|
|
2564
|
-
for (const [attribute, value] of snapshot) if (value == null) target.removeAttribute(attribute);
|
|
2565
|
-
else target.setAttribute(attribute, value);
|
|
2566
|
-
});
|
|
2567
|
-
}, { flush: "sync" });
|
|
2930
|
+
isDisabled,
|
|
2931
|
+
ignoredTargets: () => props.ignore ?? [],
|
|
2932
|
+
pointerDownOutside: emit.pointerDownOutside,
|
|
2933
|
+
focusOutside: emit.focusOutside,
|
|
2934
|
+
interactOutside: emit.interactOutside
|
|
2935
|
+
});
|
|
2936
|
+
const layeredContentStyle = computed(() => ({
|
|
2937
|
+
...contentStyle.value,
|
|
2938
|
+
zIndex: layer.zIndex.value
|
|
2939
|
+
}));
|
|
2940
|
+
onBeforeUnmount(cleanupRootMenu);
|
|
2568
2941
|
return {
|
|
2569
2942
|
rootRef,
|
|
2570
2943
|
menuRef,
|
|
@@ -2575,33 +2948,30 @@ function useDropdownMenu(props, emit = {}) {
|
|
|
2575
2948
|
visibleItems,
|
|
2576
2949
|
renderedItems,
|
|
2577
2950
|
renderContext,
|
|
2578
|
-
focusedIndex,
|
|
2579
|
-
focusedPath,
|
|
2580
|
-
activeDescendantId,
|
|
2581
|
-
rootClass,
|
|
2582
|
-
contentClass,
|
|
2583
|
-
contentStyle:
|
|
2584
|
-
...contentStyle.value,
|
|
2585
|
-
zIndex: layer.zIndex.value
|
|
2586
|
-
})),
|
|
2951
|
+
focusedIndex: dataController.focusedIndex,
|
|
2952
|
+
focusedPath: dataController.focusedPath,
|
|
2953
|
+
activeDescendantId: dataController.activeDescendantId,
|
|
2954
|
+
rootClass: presentation.rootClass,
|
|
2955
|
+
contentClass: presentation.contentClass,
|
|
2956
|
+
contentStyle: layeredContentStyle,
|
|
2587
2957
|
arrowStyle,
|
|
2588
2958
|
actualPlacement,
|
|
2589
2959
|
placementSide,
|
|
2590
2960
|
isTargetMode: isExplicitTarget,
|
|
2591
2961
|
teleportTo,
|
|
2592
2962
|
shouldTeleport,
|
|
2593
|
-
triggerProps,
|
|
2594
|
-
contentProps,
|
|
2595
|
-
slotProps,
|
|
2963
|
+
triggerProps: presentation.triggerProps,
|
|
2964
|
+
contentProps: presentation.contentProps,
|
|
2965
|
+
slotProps: presentation.slotProps,
|
|
2596
2966
|
open,
|
|
2597
2967
|
close,
|
|
2598
2968
|
toggle,
|
|
2599
|
-
selectItem,
|
|
2600
|
-
openSubmenu,
|
|
2601
|
-
closeSubmenu,
|
|
2602
|
-
onItemMouseenter: focusHoveredItem,
|
|
2603
|
-
onTriggerKeydown,
|
|
2604
|
-
onMenuKeydown,
|
|
2969
|
+
selectItem: dataController.selectItem,
|
|
2970
|
+
openSubmenu: dataController.openSubmenu,
|
|
2971
|
+
closeSubmenu: dataController.closeSubmenu,
|
|
2972
|
+
onItemMouseenter: dataController.focusHoveredItem,
|
|
2973
|
+
onTriggerKeydown: (event) => interaction.onTriggerKeydown(event),
|
|
2974
|
+
onMenuKeydown: presentation.onMenuKeydown,
|
|
2605
2975
|
getItemProps,
|
|
2606
2976
|
getItemSlotProps
|
|
2607
2977
|
};
|
|
@@ -2687,12 +3057,17 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
2687
3057
|
focusOutside: (event) => emit("focusOutside", event),
|
|
2688
3058
|
interactOutside: (event) => emit("interactOutside", event)
|
|
2689
3059
|
});
|
|
3060
|
+
const templateRefs = {
|
|
3061
|
+
root: rootRef,
|
|
3062
|
+
menu: menuRef,
|
|
3063
|
+
arrow: arrowRef
|
|
3064
|
+
};
|
|
2690
3065
|
const { getPartAttrs, getRootAttrs } = useStylesApi(props, "root");
|
|
2691
3066
|
const state = computed(() => isVisible.value ? "open" : "closed");
|
|
2692
3067
|
const rootAttrs = computed(() => getRootAttrs({
|
|
2693
3068
|
class: rootClass.value,
|
|
2694
3069
|
"data-state": state.value,
|
|
2695
|
-
"data-disabled":
|
|
3070
|
+
"data-disabled": toPresenceAttribute(props.disabled)
|
|
2696
3071
|
}));
|
|
2697
3072
|
const publicSlotProps = computed(() => {
|
|
2698
3073
|
const partAttrs = getPartAttrs("trigger");
|
|
@@ -2703,7 +3078,7 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
2703
3078
|
...props.classNames?.trigger !== void 0 ? { class: partAttrs.class } : {},
|
|
2704
3079
|
...props.styles?.trigger !== void 0 ? { style: partAttrs.style } : {},
|
|
2705
3080
|
"data-state": state.value,
|
|
2706
|
-
"data-disabled":
|
|
3081
|
+
"data-disabled": toPresenceAttribute(props.disabled)
|
|
2707
3082
|
}
|
|
2708
3083
|
};
|
|
2709
3084
|
});
|
|
@@ -2739,10 +3114,10 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
2739
3114
|
setInsertionState(n26, null, 0);
|
|
2740
3115
|
createIf(() => __props.arrow, () => {
|
|
2741
3116
|
const n7 = t0();
|
|
2742
|
-
_setTemplateRef(n7, arrowRef, null, "arrowRef");
|
|
2743
3117
|
renderEffect(() => {
|
|
2744
3118
|
setAttr(n7, "data-side", unref(placementSide));
|
|
2745
3119
|
setStyle(n7, unref(arrowStyle));
|
|
3120
|
+
_setTemplateRef(n7, templateRefs.arrow);
|
|
2746
3121
|
});
|
|
2747
3122
|
return n7;
|
|
2748
3123
|
});
|
|
@@ -2785,12 +3160,12 @@ var dropdown_menu_default = /* @__PURE__ */ defineVaporComponent({
|
|
|
2785
3160
|
return n23;
|
|
2786
3161
|
}, null, 129)];
|
|
2787
3162
|
}, { _: 8 }) });
|
|
2788
|
-
|
|
3163
|
+
setTemplateRefBinding(n26, () => templateRefs.menu, _setTemplateRef);
|
|
2789
3164
|
return n26;
|
|
2790
3165
|
}, null, 129);
|
|
2791
3166
|
}, { _: 8 }));
|
|
2792
3167
|
});
|
|
2793
|
-
|
|
3168
|
+
setTemplateRefBinding(n29, () => templateRefs.root);
|
|
2794
3169
|
return n29;
|
|
2795
3170
|
}
|
|
2796
3171
|
});
|