ropav 0.1.7 → 0.1.8
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 +1 -1
- package/dist/ancestry.js +136 -0
- package/dist/calendar.css +173 -0
- package/dist/calendar.js +714 -0
- package/dist/calendar2.js +37 -0
- package/dist/chevron-left.js +12 -0
- package/dist/color-picker.js +38 -88
- package/dist/combobox.css +251 -0
- package/dist/combobox.js +410 -0
- package/dist/components/calendar/calendar.d.ts +30 -0
- package/dist/components/calendar/calendarBehavior.d.ts +49 -0
- package/dist/components/calendar/index.d.ts +3 -0
- package/dist/components/calendar/index.js +3 -0
- package/dist/components/calendar/types.d.ts +53 -0
- package/dist/components/calendar/useCalendar.d.ts +24 -0
- package/dist/components/color-picker/useColorPickerDrag.d.ts +1 -1
- package/dist/components/color-picker/useColorPickerSaturation.d.ts +1 -1
- package/dist/components/color-picker/useColorPickerSlider.d.ts +1 -1
- package/dist/components/combobox/combobox.d.ts +29 -0
- package/dist/components/combobox/comboboxModel.d.ts +4 -0
- package/dist/components/combobox/index.d.ts +3 -0
- package/dist/components/combobox/index.js +2 -0
- package/dist/components/combobox/types.d.ts +43 -0
- package/dist/components/combobox/useCombobox.d.ts +45 -0
- package/dist/components/date-picker/date-picker.d.ts +33 -0
- package/dist/components/date-picker/datePickerModel.d.ts +10 -0
- package/dist/components/date-picker/index.d.ts +4 -0
- package/dist/components/date-picker/index.js +2 -0
- package/dist/components/date-picker/types.d.ts +57 -0
- package/dist/components/date-picker/useDatePicker.d.ts +29 -0
- package/dist/components/date-picker/useDatePickerValueState.d.ts +21 -0
- package/dist/components/dropdown-menu/dropdown-menu-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu-sub-content.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +2 -2
- package/dist/components/dropdown-menu/dropdownMenuContext.d.ts +7 -18
- package/dist/components/dropdown-menu/dropdownMenuInteraction.d.ts +3 -3
- package/dist/components/dropdown-menu/dropdownMenuInteractionTypes.d.ts +58 -29
- package/dist/components/dropdown-menu/useDropdownMenuDataController.d.ts +4 -3
- package/dist/components/dropdown-menu/useDropdownMenuDataRegistration.d.ts +6 -4
- package/dist/components/dropdown-menu/useDropdownMenuPresentation.d.ts +3 -4
- package/dist/components/dropdown-menu/useDropdownMenuTargetBindings.d.ts +5 -5
- package/dist/components/dropzone/dropzone.d.ts +31 -0
- package/dist/components/dropzone/dropzoneModel.d.ts +16 -0
- package/dist/components/dropzone/index.d.ts +3 -0
- package/dist/components/dropzone/index.js +2 -0
- package/dist/components/dropzone/types.d.ts +56 -0
- package/dist/components/dropzone/useDropzone.d.ts +25 -0
- package/dist/components/file-input/file-input.d.ts +29 -0
- package/dist/components/file-input/index.d.ts +3 -0
- package/dist/components/file-input/index.js +2 -0
- package/dist/components/file-input/types.d.ts +37 -0
- package/dist/components/file-input/useFileInput.d.ts +15 -0
- package/dist/components/floating/index.js +1 -1
- package/dist/components/floating/useFloatingPosition.d.ts +1 -13
- package/dist/components/floating/useFloatingTargetLifecycle.d.ts +32 -0
- package/dist/components/floating/useHoverDisclosure.d.ts +10 -0
- package/dist/components/hover-card/hover-card.d.ts +25 -0
- package/dist/components/hover-card/index.d.ts +3 -0
- package/dist/components/hover-card/index.js +2 -0
- package/dist/components/hover-card/types.d.ts +45 -0
- package/dist/components/hover-card/useHoverCard.d.ts +22 -0
- package/dist/components/hover-card/useHoverCardDisclosure.d.ts +19 -0
- package/dist/components/multi-select/index.d.ts +3 -0
- package/dist/components/multi-select/index.js +2 -0
- package/dist/components/multi-select/multi-select.d.ts +30 -0
- package/dist/components/multi-select/multiSelectModel.d.ts +3 -0
- package/dist/components/multi-select/types.d.ts +49 -0
- package/dist/components/multi-select/useMultiSelect.d.ts +46 -0
- package/dist/components/number-input/useNumberInput.d.ts +1 -3
- package/dist/components/popover/usePopoverBindings.d.ts +3 -6
- package/dist/components/scroll-area/useScrollArea.d.ts +4 -4
- package/dist/components/scroll-area/useScrollAreaAttributes.d.ts +3 -3
- package/dist/components/scroll-area/useScrollAreaPointer.d.ts +1 -1
- package/dist/components/segmented-control/index.d.ts +3 -0
- package/dist/components/segmented-control/index.js +2 -0
- package/dist/components/segmented-control/segmented-control.d.ts +26 -0
- package/dist/components/segmented-control/types.d.ts +47 -0
- package/dist/components/segmented-control/useSegmentedControl.d.ts +15 -0
- package/dist/components/select/useSelect.d.ts +31 -19
- package/dist/components/slider/useRangeSlider.d.ts +1 -1
- package/dist/components/slider/useRangeSliderPointer.d.ts +1 -1
- package/dist/components/tags-input/index.d.ts +3 -0
- package/dist/components/tags-input/index.js +2 -0
- package/dist/components/tags-input/tags-input.d.ts +27 -0
- package/dist/components/tags-input/tagsInputModel.d.ts +12 -0
- package/dist/components/tags-input/types.d.ts +37 -0
- package/dist/components/tags-input/useTagsInput.d.ts +23 -0
- package/dist/components/tooltip/useTooltipTargetBindings.d.ts +12 -0
- package/dist/date-picker.css +49 -0
- package/dist/date-picker.js +809 -0
- package/dist/dialog.js +9 -20
- package/dist/direction.js +6 -0
- package/dist/dropdown-menu.css +21 -3
- package/dist/dropdown-menu.js +341 -261
- package/dist/dropzone.css +135 -0
- package/dist/dropzone.js +431 -0
- package/dist/file-input.css +135 -0
- package/dist/file-input.js +198 -0
- package/dist/hover-card.css +80 -0
- package/dist/hover-card.js +402 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +14 -3
- package/dist/internal/composables/useOverlayLayer.d.ts +12 -0
- package/dist/modal.js +1 -1
- package/dist/multi-select.css +316 -0
- package/dist/multi-select.js +481 -0
- package/dist/nativeChoice.js +169 -0
- package/dist/number-input.css +18 -18
- package/dist/number-input.js +36 -38
- package/dist/pagination.js +1 -10
- package/dist/pointerSession.js +130 -0
- package/dist/popover.css +21 -3
- package/dist/popover.js +37 -62
- package/dist/scroll-area.js +52 -62
- package/dist/segmented-control.css +176 -0
- package/dist/segmented-control.js +382 -0
- package/dist/select.css +50 -48
- package/dist/select.js +121 -271
- package/dist/slider.js +70 -129
- package/dist/tags-input.css +197 -0
- package/dist/tags-input.js +380 -0
- package/dist/tooltip.js +35 -30
- package/dist/useEditableOptionList.js +216 -0
- package/dist/useFlatOptionCollection.js +134 -0
- package/dist/useFloatingPosition.js +4 -160
- package/dist/useFloatingTargetLifecycle.js +127 -0
- package/dist/useFormControl.js +1 -0
- package/dist/{floating.js → useHoverDisclosure.js} +338 -421
- package/dist/useNativeChoiceTransaction.js +46 -0
- package/dist/useNativeFileSelection.js +86 -0
- package/dist/useOverlayZIndex.js +246 -15
- package/dist/utils/date.d.ts +13 -0
- package/dist/utils/dateAvailability.d.ts +7 -0
- package/dist/utils/dom/ancestry.d.ts +1 -0
- package/dist/utils/dom/direction.d.ts +2 -0
- package/dist/utils/dom/files.d.ts +3 -0
- package/dist/utils/dom/nativeChoice.d.ts +17 -0
- package/dist/utils/dom/pointerSession.d.ts +20 -0
- package/dist/utils/dom/scroll.d.ts +2 -1
- package/dist/utils/optionFilter.d.ts +5 -0
- package/docs/public-floating-api.md +7 -4
- package/docs/public-styles-api.md +25 -12
- package/package.json +39 -3
- package/src/styles/_mixins.scss +26 -0
- package/src/styles/styles-manifest.json +1 -2
- package/dist/components/floating/hoverDisclosureInteractionModel.d.ts +0 -42
- package/dist/components/floating/useHoverDisclosureInteractions.d.ts +0 -32
- package/dist/components/floating/useHoverDisclosureOpenState.d.ts +0 -25
- package/dist/components/floating/useHoverDisclosureTargetBinding.d.ts +0 -27
- package/dist/components/select/useSelectNativeControl.d.ts +0 -9
- package/dist/components/select/useSelectNativeValue.d.ts +0 -9
- package/dist/pointer.js +0 -9
- package/dist/utils/dom/pointer.d.ts +0 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { t as useControllableValue } from "./useControllableValue.js";
|
|
2
|
+
import { i as useFormControl } from "./useFormControl.js";
|
|
3
|
+
import { nextTick, watchEffect } from "vue";
|
|
4
|
+
//#region src/internal/composables/useNativeChoiceTransaction.ts
|
|
5
|
+
function useNativeChoiceTransaction(options) {
|
|
6
|
+
const controllable = useControllableValue(options.value);
|
|
7
|
+
function syncNativeValue(value) {
|
|
8
|
+
options.adapter.syncValue(value, controllable.initialValue);
|
|
9
|
+
}
|
|
10
|
+
function restoreControlledValue() {
|
|
11
|
+
if (!controllable.isControlled.value) return;
|
|
12
|
+
queueMicrotask(() => syncNativeValue(controllable.value.value));
|
|
13
|
+
}
|
|
14
|
+
function requestValueUpdate(value) {
|
|
15
|
+
options.adapter.commitValue(value, controllable.initialValue, () => controllable.setValue(value));
|
|
16
|
+
restoreControlledValue();
|
|
17
|
+
}
|
|
18
|
+
useFormControl({
|
|
19
|
+
elements: options.adapter.controls,
|
|
20
|
+
isControlled: () => controllable.isControlled.value,
|
|
21
|
+
validationMessage: options.adapter.validationMessage,
|
|
22
|
+
readResetValue(controls) {
|
|
23
|
+
controllable.resetValue(options.adapter.readResetValue(controls, controllable.initialValue));
|
|
24
|
+
syncNativeValue(controllable.value.value);
|
|
25
|
+
options.onFormReset?.();
|
|
26
|
+
},
|
|
27
|
+
syncControlledValue() {
|
|
28
|
+
syncNativeValue(controllable.value.value);
|
|
29
|
+
options.onFormReset?.();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
watchEffect(() => {
|
|
33
|
+
const currentValue = controllable.value.value;
|
|
34
|
+
const reconciledValue = options.adapter.reconcileValue?.(currentValue, controllable.initialValue, controllable.isControlled.value) ?? currentValue;
|
|
35
|
+
if (!controllable.isControlled.value && !Object.is(reconciledValue, currentValue)) controllable.resetValue(reconciledValue);
|
|
36
|
+
syncNativeValue(controllable.value.value);
|
|
37
|
+
nextTick(() => syncNativeValue(controllable.value.value));
|
|
38
|
+
}, { flush: "post" });
|
|
39
|
+
return {
|
|
40
|
+
isControlled: controllable.isControlled,
|
|
41
|
+
requestValueUpdate,
|
|
42
|
+
value: controllable.value
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { useNativeChoiceTransaction as t };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { t as useControllableValue } from "./useControllableValue.js";
|
|
2
|
+
import { i as useFormControl } from "./useFormControl.js";
|
|
3
|
+
import { computed, nextTick, ref, watchEffect } from "vue";
|
|
4
|
+
//#region src/utils/dom/files.ts
|
|
5
|
+
function normalizeSelectedFiles(files, multiple) {
|
|
6
|
+
const selectedFiles = Array.from(files);
|
|
7
|
+
return multiple ? selectedFiles : selectedFiles.slice(0, 1);
|
|
8
|
+
}
|
|
9
|
+
function haveSameFiles(fileList, files) {
|
|
10
|
+
if (!fileList || fileList.length !== files.length) return false;
|
|
11
|
+
return files.every((file, index) => fileList.item(index) === file);
|
|
12
|
+
}
|
|
13
|
+
function replaceInputFiles(input, files) {
|
|
14
|
+
if (haveSameFiles(input.files, files)) return true;
|
|
15
|
+
if (files.length === 0) {
|
|
16
|
+
input.value = "";
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
const DataTransferConstructor = input.ownerDocument.defaultView?.DataTransfer;
|
|
20
|
+
if (!DataTransferConstructor) return false;
|
|
21
|
+
const transfer = new DataTransferConstructor();
|
|
22
|
+
for (const file of files) transfer.items.add(file);
|
|
23
|
+
try {
|
|
24
|
+
input.files = transfer.files;
|
|
25
|
+
return true;
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/internal/composables/useNativeFileSelection.ts
|
|
32
|
+
function useNativeFileSelection(options) {
|
|
33
|
+
const inputRef = ref(null);
|
|
34
|
+
const controllable = useControllableValue({
|
|
35
|
+
modelValue: options.modelValue,
|
|
36
|
+
defaultValue: () => [],
|
|
37
|
+
onChange: options.onChange
|
|
38
|
+
});
|
|
39
|
+
const files = computed(() => normalizeSelectedFiles(controllable.value.value, options.multiple()));
|
|
40
|
+
function syncNativeFiles(nextFiles = files.value) {
|
|
41
|
+
const input = inputRef.value;
|
|
42
|
+
if (input) replaceInputFiles(input, nextFiles);
|
|
43
|
+
}
|
|
44
|
+
function settleSelection(outcome) {
|
|
45
|
+
if (outcome.status === "accepted") {
|
|
46
|
+
const nextFiles = normalizeSelectedFiles(outcome.files, options.multiple());
|
|
47
|
+
syncNativeFiles(nextFiles);
|
|
48
|
+
controllable.setValue(nextFiles);
|
|
49
|
+
} else syncNativeFiles();
|
|
50
|
+
nextTick(() => syncNativeFiles());
|
|
51
|
+
}
|
|
52
|
+
function clear() {
|
|
53
|
+
settleSelection({
|
|
54
|
+
status: "accepted",
|
|
55
|
+
files: []
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function focus(focusOptions) {
|
|
59
|
+
inputRef.value?.focus(focusOptions);
|
|
60
|
+
}
|
|
61
|
+
function open() {
|
|
62
|
+
if (options.disabled()) return;
|
|
63
|
+
inputRef.value?.click();
|
|
64
|
+
}
|
|
65
|
+
watchEffect(() => syncNativeFiles(files.value), { flush: "post" });
|
|
66
|
+
useFormControl({
|
|
67
|
+
elements: () => [inputRef.value],
|
|
68
|
+
isControlled: () => controllable.isControlled.value,
|
|
69
|
+
validationMessage: options.validationMessage,
|
|
70
|
+
readResetValue() {
|
|
71
|
+
controllable.resetValue([]);
|
|
72
|
+
settleSelection({ status: "rejected" });
|
|
73
|
+
},
|
|
74
|
+
syncControlledValue: () => settleSelection({ status: "rejected" })
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
inputRef,
|
|
78
|
+
files,
|
|
79
|
+
settleSelection,
|
|
80
|
+
clear,
|
|
81
|
+
focus,
|
|
82
|
+
open
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { useNativeFileSelection as t };
|
package/dist/useOverlayZIndex.js
CHANGED
|
@@ -1,13 +1,40 @@
|
|
|
1
1
|
import { n as isEventWithinElement } from "./events.js";
|
|
2
|
+
import { n as observeComposedAncestry } from "./ancestry.js";
|
|
2
3
|
import { computed, inject, onBeforeUnmount, provide, readonly, ref, shallowRef, toValue, watch } from "vue";
|
|
3
4
|
//#region src/internal/composables/useOverlayLayer.ts
|
|
4
5
|
var overlayLayerKey = Symbol("overlay-layer");
|
|
5
6
|
var documentStates = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
var activeInteractionLayers = [];
|
|
8
|
+
var interactionListenerDefinitions = {
|
|
9
|
+
escapeKeyDown: {
|
|
10
|
+
capture: false,
|
|
11
|
+
eventName: "keydown",
|
|
12
|
+
outside: false,
|
|
13
|
+
matches: (event) => event.key === "Escape"
|
|
14
|
+
},
|
|
15
|
+
pointerDownOutside: {
|
|
16
|
+
capture: true,
|
|
17
|
+
eventName: "pointerdown",
|
|
18
|
+
outside: true
|
|
19
|
+
},
|
|
20
|
+
focusOutside: {
|
|
21
|
+
capture: true,
|
|
22
|
+
eventName: "focusin",
|
|
23
|
+
outside: true
|
|
24
|
+
},
|
|
25
|
+
clickOutside: {
|
|
26
|
+
capture: true,
|
|
27
|
+
eventName: "click",
|
|
28
|
+
outside: true
|
|
29
|
+
}
|
|
30
|
+
};
|
|
6
31
|
var layerMetadata = /* @__PURE__ */ new WeakMap();
|
|
7
32
|
function createState() {
|
|
8
33
|
return {
|
|
9
34
|
layers: [],
|
|
35
|
+
interactionLayers: [],
|
|
10
36
|
inertSnapshots: /* @__PURE__ */ new Map(),
|
|
37
|
+
interactionListeners: {},
|
|
11
38
|
originalBodyOverflow: "",
|
|
12
39
|
scrollLocked: false,
|
|
13
40
|
observer: null,
|
|
@@ -29,6 +56,24 @@ function isDescendantLayer(layer, ancestor) {
|
|
|
29
56
|
}
|
|
30
57
|
return false;
|
|
31
58
|
}
|
|
59
|
+
function insertLayer(layers, layer) {
|
|
60
|
+
const currentIndex = layers.indexOf(layer);
|
|
61
|
+
if (currentIndex >= 0) layers.splice(currentIndex, 1);
|
|
62
|
+
const descendantIndex = layers.findIndex((candidate) => isDescendantLayer(candidate, layer));
|
|
63
|
+
if (descendantIndex >= 0) layers.splice(descendantIndex, 0, layer);
|
|
64
|
+
else layers.push(layer);
|
|
65
|
+
}
|
|
66
|
+
function insertPhysicalLayer(layers, layer) {
|
|
67
|
+
removeLayerFromStack(layers, layer);
|
|
68
|
+
const layerIndex = activeInteractionLayers.indexOf(layer);
|
|
69
|
+
const nextIndex = layers.findIndex((candidate) => activeInteractionLayers.indexOf(candidate) > layerIndex);
|
|
70
|
+
if (nextIndex >= 0) layers.splice(nextIndex, 0, layer);
|
|
71
|
+
else layers.push(layer);
|
|
72
|
+
}
|
|
73
|
+
function removeLayerFromStack(layers, layer) {
|
|
74
|
+
const index = layers.indexOf(layer);
|
|
75
|
+
if (index >= 0) layers.splice(index, 1);
|
|
76
|
+
}
|
|
32
77
|
function syncLayerZIndices(state) {
|
|
33
78
|
let highestZIndex = Number.NEGATIVE_INFINITY;
|
|
34
79
|
for (const layer of state.layers) {
|
|
@@ -39,6 +84,65 @@ function syncLayerZIndices(state) {
|
|
|
39
84
|
highestZIndex = zIndex;
|
|
40
85
|
}
|
|
41
86
|
}
|
|
87
|
+
function syncDocumentInteractionLayers(document) {
|
|
88
|
+
const state = getState(document);
|
|
89
|
+
state.interactionLayers = activeInteractionLayers.filter((layer) => layerMetadata.get(layer)?.interactionDocuments.has(document));
|
|
90
|
+
syncInteractionListeners(document, state);
|
|
91
|
+
}
|
|
92
|
+
function reconcileInteractionDocuments(layer) {
|
|
93
|
+
const affectedDocuments = /* @__PURE__ */ new Set();
|
|
94
|
+
const layers = activeInteractionLayers.filter((candidate) => candidate === layer || isDescendantLayer(candidate, layer));
|
|
95
|
+
if (!layers.includes(layer)) layers.unshift(layer);
|
|
96
|
+
for (const candidate of layers) {
|
|
97
|
+
const metadata = layerMetadata.get(candidate);
|
|
98
|
+
if (!metadata) continue;
|
|
99
|
+
for (const document of metadata.interactionDocuments) affectedDocuments.add(document);
|
|
100
|
+
const nextDocuments = metadata.registered ? new Set(metadata.ownInteractionDocuments) : /* @__PURE__ */ new Set();
|
|
101
|
+
const parentDocuments = metadata.parent ? layerMetadata.get(metadata.parent)?.interactionDocuments : void 0;
|
|
102
|
+
if (metadata.registered && parentDocuments) for (const document of parentDocuments) nextDocuments.add(document);
|
|
103
|
+
metadata.interactionDocuments = nextDocuments;
|
|
104
|
+
for (const document of nextDocuments) affectedDocuments.add(document);
|
|
105
|
+
}
|
|
106
|
+
for (const document of affectedDocuments) syncDocumentInteractionLayers(document);
|
|
107
|
+
}
|
|
108
|
+
function hasInteractionHandler(state, name) {
|
|
109
|
+
return state.interactionLayers.some((layer) => [...layerMetadata.get(layer)?.interactions ?? []].some((interaction) => typeof interaction[name] === "function"));
|
|
110
|
+
}
|
|
111
|
+
function routeLayerInteraction(state, name, event) {
|
|
112
|
+
const layer = state.interactionLayers[state.interactionLayers.length - 1];
|
|
113
|
+
if (!layer) return;
|
|
114
|
+
const definition = interactionListenerDefinitions[name];
|
|
115
|
+
if (definition.matches && !definition.matches(event)) return;
|
|
116
|
+
const interactions = [...layerMetadata.get(layer)?.interactions ?? []];
|
|
117
|
+
for (const interaction of interactions) {
|
|
118
|
+
const handler = interaction[name];
|
|
119
|
+
if (!handler) continue;
|
|
120
|
+
const additionalInside = interaction.inside ? toValue(interaction.inside) : [];
|
|
121
|
+
if (definition.outside && layer.isInside(event, additionalInside)) continue;
|
|
122
|
+
handler(event);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function syncInteractionListeners(document, state) {
|
|
126
|
+
for (const name of Object.keys(interactionListenerDefinitions)) {
|
|
127
|
+
const existing = state.interactionListeners[name];
|
|
128
|
+
if (!hasInteractionHandler(state, name)) {
|
|
129
|
+
if (existing) {
|
|
130
|
+
document.removeEventListener(existing.eventName, existing.listener, existing.capture);
|
|
131
|
+
delete state.interactionListeners[name];
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (existing) continue;
|
|
136
|
+
const definition = interactionListenerDefinitions[name];
|
|
137
|
+
const listener = (event) => routeLayerInteraction(state, name, event);
|
|
138
|
+
document.addEventListener(definition.eventName, listener, definition.capture);
|
|
139
|
+
state.interactionListeners[name] = {
|
|
140
|
+
capture: definition.capture,
|
|
141
|
+
eventName: definition.eventName,
|
|
142
|
+
listener
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
42
146
|
function restoreInertBackground(state) {
|
|
43
147
|
for (const [element, snapshot] of state.inertSnapshots) {
|
|
44
148
|
element.inert = snapshot.inert;
|
|
@@ -123,11 +227,41 @@ function syncModalEffects(document, state) {
|
|
|
123
227
|
}
|
|
124
228
|
}
|
|
125
229
|
function removeLayer(layer, document, state) {
|
|
126
|
-
|
|
127
|
-
if (index >= 0) state.layers.splice(index, 1);
|
|
230
|
+
removeLayerFromStack(state.layers, layer);
|
|
128
231
|
syncLayerZIndices(state);
|
|
129
232
|
syncModalEffects(document, state);
|
|
130
233
|
}
|
|
234
|
+
function createOverlayLayerAncestryObserver(options) {
|
|
235
|
+
let cleanups = [];
|
|
236
|
+
let disposed = false;
|
|
237
|
+
function stop() {
|
|
238
|
+
for (const cleanup of cleanups) cleanup();
|
|
239
|
+
cleanups = [];
|
|
240
|
+
}
|
|
241
|
+
function reset() {
|
|
242
|
+
stop();
|
|
243
|
+
if (disposed || !options.active.value) return;
|
|
244
|
+
const content = options.element.value;
|
|
245
|
+
if (content) cleanups.push(observeComposedAncestry(() => [content], options.onContentChange, { deferWhileDisconnected: true }));
|
|
246
|
+
const auxiliaryElements = new Set(options.branches);
|
|
247
|
+
for (const interaction of options.interactions) {
|
|
248
|
+
if (!interaction.inside) continue;
|
|
249
|
+
for (const element of toValue(interaction.inside)) if (element) auxiliaryElements.add(element);
|
|
250
|
+
}
|
|
251
|
+
if (content) auxiliaryElements.delete(content);
|
|
252
|
+
for (const element of auxiliaryElements) cleanups.push(observeComposedAncestry(() => [element], options.onAuxiliaryChange, {
|
|
253
|
+
deferWhileDisconnected: true,
|
|
254
|
+
notifyOnDisconnect: true
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
reset,
|
|
259
|
+
dispose() {
|
|
260
|
+
disposed = true;
|
|
261
|
+
stop();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
131
265
|
function useOverlayLayer(options) {
|
|
132
266
|
const parent = inject(overlayLayerKey, null);
|
|
133
267
|
const active = computed(() => Boolean(toValue(options.active)));
|
|
@@ -138,14 +272,26 @@ function useOverlayLayer(options) {
|
|
|
138
272
|
const branchSet = /* @__PURE__ */ new Set();
|
|
139
273
|
const focusBranchSet = /* @__PURE__ */ new Set();
|
|
140
274
|
const insideBranchSet = /* @__PURE__ */ new Set();
|
|
275
|
+
const interactions = /* @__PURE__ */ new Set();
|
|
276
|
+
const interactionSetRevision = ref(0);
|
|
141
277
|
const baseZIndex = computed(() => toValue(options.baseZIndex ?? 100));
|
|
142
278
|
const zIndex = ref(baseZIndex.value);
|
|
143
279
|
let registeredDocument = null;
|
|
144
280
|
let registeredElement = null;
|
|
145
281
|
let parentBranchCleanup;
|
|
282
|
+
const ancestryObserver = createOverlayLayerAncestryObserver({
|
|
283
|
+
active,
|
|
284
|
+
element: options.element,
|
|
285
|
+
branches: branchSet,
|
|
286
|
+
interactions,
|
|
287
|
+
onContentChange: syncObservedAncestry,
|
|
288
|
+
onAuxiliaryChange: syncObservedAuxiliaryAncestry
|
|
289
|
+
});
|
|
146
290
|
function syncBranches() {
|
|
147
291
|
branches.value = [...branchSet];
|
|
148
292
|
focusBranches.value = [...focusBranchSet];
|
|
293
|
+
syncOwnInteractionDocuments();
|
|
294
|
+
ancestryObserver.reset();
|
|
149
295
|
if (registeredDocument) syncModalEffects(registeredDocument, getState(registeredDocument));
|
|
150
296
|
}
|
|
151
297
|
function registerBranch(element, branchOptions = {}) {
|
|
@@ -166,6 +312,36 @@ function useOverlayLayer(options) {
|
|
|
166
312
|
parentBranchCleanup?.();
|
|
167
313
|
parentBranchCleanup = element ? parent?.registerBranch(element) : void 0;
|
|
168
314
|
}
|
|
315
|
+
function connectInteraction(interaction) {
|
|
316
|
+
interactions.add(interaction);
|
|
317
|
+
interactionSetRevision.value += 1;
|
|
318
|
+
let connected = true;
|
|
319
|
+
return Object.assign(() => {
|
|
320
|
+
if (!connected) return;
|
|
321
|
+
connected = false;
|
|
322
|
+
interactions.delete(interaction);
|
|
323
|
+
interactionSetRevision.value += 1;
|
|
324
|
+
}, { refresh() {
|
|
325
|
+
if (!connected) return;
|
|
326
|
+
syncOwnInteractionDocuments();
|
|
327
|
+
ancestryObserver.reset();
|
|
328
|
+
} });
|
|
329
|
+
}
|
|
330
|
+
function readOwnInteractionDocuments() {
|
|
331
|
+
const documents = /* @__PURE__ */ new Set();
|
|
332
|
+
if (registeredElement) documents.add(registeredElement.ownerDocument);
|
|
333
|
+
for (const branch of branchSet) if (branch.isConnected) documents.add(branch.ownerDocument);
|
|
334
|
+
for (const interaction of interactions) if (interaction.inside) {
|
|
335
|
+
for (const element of toValue(interaction.inside)) if (element?.isConnected) documents.add(element.ownerDocument);
|
|
336
|
+
}
|
|
337
|
+
return [...documents];
|
|
338
|
+
}
|
|
339
|
+
function syncOwnInteractionDocuments(documents = readOwnInteractionDocuments()) {
|
|
340
|
+
const metadata = layerMetadata.get(context);
|
|
341
|
+
if (!metadata) return;
|
|
342
|
+
metadata.ownInteractionDocuments = new Set(documents);
|
|
343
|
+
reconcileInteractionDocuments(context);
|
|
344
|
+
}
|
|
169
345
|
const context = {
|
|
170
346
|
id: Symbol("overlay-layer"),
|
|
171
347
|
element: options.element,
|
|
@@ -188,49 +364,100 @@ function useOverlayLayer(options) {
|
|
|
188
364
|
...additional
|
|
189
365
|
].some((element) => element != null && isEventWithinElement(event, element));
|
|
190
366
|
},
|
|
191
|
-
registerBranch
|
|
367
|
+
registerBranch,
|
|
368
|
+
connectInteraction
|
|
192
369
|
};
|
|
193
370
|
layerMetadata.set(context, {
|
|
194
371
|
baseZIndex,
|
|
372
|
+
interactions,
|
|
373
|
+
interactionDocuments: /* @__PURE__ */ new Set(),
|
|
374
|
+
ownInteractionDocuments: /* @__PURE__ */ new Set(),
|
|
195
375
|
parent,
|
|
376
|
+
registered: false,
|
|
196
377
|
setZIndex(value) {
|
|
197
378
|
zIndex.value = value;
|
|
198
379
|
}
|
|
199
380
|
});
|
|
381
|
+
watch(() => {
|
|
382
|
+
interactionSetRevision.value;
|
|
383
|
+
return readOwnInteractionDocuments();
|
|
384
|
+
}, (documents) => {
|
|
385
|
+
syncOwnInteractionDocuments(documents);
|
|
386
|
+
ancestryObserver.reset();
|
|
387
|
+
}, {
|
|
388
|
+
flush: "sync",
|
|
389
|
+
immediate: true
|
|
390
|
+
});
|
|
200
391
|
function unregister() {
|
|
201
|
-
replaceParentBranch(null);
|
|
202
392
|
if (!registeredDocument) return;
|
|
203
393
|
const document = registeredDocument;
|
|
204
394
|
registeredDocument = null;
|
|
205
395
|
registeredElement = null;
|
|
396
|
+
const metadata = layerMetadata.get(context);
|
|
397
|
+
if (metadata) metadata.registered = false;
|
|
398
|
+
removeLayerFromStack(activeInteractionLayers, context);
|
|
399
|
+
syncOwnInteractionDocuments();
|
|
400
|
+
replaceParentBranch(null);
|
|
206
401
|
removeLayer(context, document, getState(document));
|
|
207
402
|
}
|
|
403
|
+
function moveRegistration(element) {
|
|
404
|
+
const previousDocument = registeredDocument;
|
|
405
|
+
if (!previousDocument) return;
|
|
406
|
+
registeredDocument = element.ownerDocument;
|
|
407
|
+
registeredElement = element;
|
|
408
|
+
removeLayer(context, previousDocument, getState(previousDocument));
|
|
409
|
+
const state = getState(registeredDocument);
|
|
410
|
+
insertPhysicalLayer(state.layers, context);
|
|
411
|
+
syncOwnInteractionDocuments();
|
|
412
|
+
replaceParentBranch(element);
|
|
413
|
+
syncLayerZIndices(state);
|
|
414
|
+
syncModalEffects(registeredDocument, state);
|
|
415
|
+
}
|
|
208
416
|
function register(element) {
|
|
209
417
|
const document = element.ownerDocument;
|
|
210
418
|
if (registeredDocument === document) {
|
|
211
419
|
if (registeredElement !== element) {
|
|
212
|
-
replaceParentBranch(element);
|
|
213
420
|
registeredElement = element;
|
|
421
|
+
syncOwnInteractionDocuments();
|
|
422
|
+
replaceParentBranch(element);
|
|
214
423
|
syncModalEffects(document, getState(document));
|
|
215
424
|
}
|
|
216
425
|
return;
|
|
217
426
|
}
|
|
218
|
-
|
|
427
|
+
if (registeredDocument) {
|
|
428
|
+
moveRegistration(element);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
219
431
|
const state = getState(document);
|
|
220
|
-
const currentIndex = state.layers.indexOf(context);
|
|
221
|
-
if (currentIndex >= 0) state.layers.splice(currentIndex, 1);
|
|
222
|
-
const descendantIndex = state.layers.findIndex((layer) => isDescendantLayer(layer, context));
|
|
223
|
-
if (descendantIndex >= 0) state.layers.splice(descendantIndex, 0, context);
|
|
224
|
-
else state.layers.push(context);
|
|
225
432
|
registeredDocument = document;
|
|
226
433
|
registeredElement = element;
|
|
434
|
+
const metadata = layerMetadata.get(context);
|
|
435
|
+
if (metadata) metadata.registered = true;
|
|
436
|
+
insertLayer(activeInteractionLayers, context);
|
|
437
|
+
insertPhysicalLayer(state.layers, context);
|
|
438
|
+
syncOwnInteractionDocuments();
|
|
227
439
|
replaceParentBranch(element);
|
|
228
440
|
syncLayerZIndices(state);
|
|
229
441
|
syncModalEffects(document, state);
|
|
230
442
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
443
|
+
function syncRegistration() {
|
|
444
|
+
const element = options.element.value;
|
|
445
|
+
if (active.value && element?.isConnected) {
|
|
446
|
+
register(element);
|
|
447
|
+
syncOwnInteractionDocuments();
|
|
448
|
+
} else unregister();
|
|
449
|
+
}
|
|
450
|
+
function syncObservedAncestry() {
|
|
451
|
+
syncRegistration();
|
|
452
|
+
if (registeredDocument) syncModalEffects(registeredDocument, getState(registeredDocument));
|
|
453
|
+
}
|
|
454
|
+
function syncObservedAuxiliaryAncestry() {
|
|
455
|
+
syncOwnInteractionDocuments();
|
|
456
|
+
if (registeredDocument) syncModalEffects(registeredDocument, getState(registeredDocument));
|
|
457
|
+
}
|
|
458
|
+
watch([active, options.element], () => {
|
|
459
|
+
syncRegistration();
|
|
460
|
+
ancestryObserver.reset();
|
|
234
461
|
}, {
|
|
235
462
|
flush: "post",
|
|
236
463
|
immediate: true
|
|
@@ -242,7 +469,11 @@ function useOverlayLayer(options) {
|
|
|
242
469
|
if (registeredDocument) syncLayerZIndices(getState(registeredDocument));
|
|
243
470
|
else zIndex.value = value;
|
|
244
471
|
});
|
|
245
|
-
onBeforeUnmount(
|
|
472
|
+
onBeforeUnmount(() => {
|
|
473
|
+
ancestryObserver.dispose();
|
|
474
|
+
unregister();
|
|
475
|
+
interactions.clear();
|
|
476
|
+
});
|
|
246
477
|
provide(overlayLayerKey, context);
|
|
247
478
|
return context;
|
|
248
479
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function isValidDate(value: unknown): value is Date;
|
|
2
|
+
export declare function toLocalDate(value: Date): Date;
|
|
3
|
+
export declare function normalizeDate(value: Date | null | undefined): Date | null;
|
|
4
|
+
export declare function toDateKey(value: Date): string;
|
|
5
|
+
export declare function parseDateKey(value: string): Date | null;
|
|
6
|
+
export declare function compareDates(left: Date, right: Date): number;
|
|
7
|
+
export declare function isSameDate(left: Date | null | undefined, right: Date | null | undefined): boolean;
|
|
8
|
+
export declare function isSameMonth(left: Date, right: Date): boolean;
|
|
9
|
+
export declare function startOfMonth(value: Date): Date;
|
|
10
|
+
export declare function endOfMonth(value: Date): Date;
|
|
11
|
+
export declare function addCalendarDays(value: Date, amount: number): Date;
|
|
12
|
+
export declare function addCalendarMonths(value: Date, amount: number): Date;
|
|
13
|
+
export declare function addCalendarYears(value: Date, amount: number): Date;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type DisabledDateRule = readonly Date[] | ((date: Date) => boolean);
|
|
2
|
+
export interface DateAvailabilityOptions {
|
|
3
|
+
min?: Date;
|
|
4
|
+
max?: Date;
|
|
5
|
+
disabledDates?: DisabledDateRule;
|
|
6
|
+
}
|
|
7
|
+
export declare function isDateUnavailable(date: Date, options: DateAvailabilityOptions): boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface ObserveComposedAncestryOptions {
|
|
2
2
|
deferWhileDisconnected?: boolean;
|
|
3
|
+
notifyOnDisconnect?: boolean;
|
|
3
4
|
}
|
|
4
5
|
export declare function getComposedParent(node: Node): Node | null;
|
|
5
6
|
export declare function getComposedAncestry(node: Node | null | undefined): Node[];
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function normalizeSelectedFiles(files: Iterable<File>, multiple: boolean): File[];
|
|
2
|
+
export declare function haveSameFiles(fileList: FileList | null, files: readonly File[]): boolean;
|
|
3
|
+
export declare function replaceInputFiles(input: HTMLInputElement, files: readonly File[]): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface NativeChoiceOption<Value> {
|
|
2
|
+
value: Value;
|
|
3
|
+
}
|
|
4
|
+
export interface NativeSelectChoiceAdapter<Value> {
|
|
5
|
+
commit: (select: HTMLSelectElement, value: Value, defaultValue: Value, applyValue: () => void) => void;
|
|
6
|
+
read: (select: HTMLSelectElement) => Value;
|
|
7
|
+
resolveResetValue: (select: HTMLSelectElement, initialValue: Value) => Value;
|
|
8
|
+
sync: (select: HTMLSelectElement, value: Value, defaultValue: Value) => void;
|
|
9
|
+
}
|
|
10
|
+
interface SingleNativeChoiceAdapterOptions<Value> {
|
|
11
|
+
emptyValue: Value;
|
|
12
|
+
options: () => readonly NativeChoiceOption<Value>[] | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function createSingleNativeChoiceAdapter<Value>(options: SingleNativeChoiceAdapterOptions<Value>): NativeSelectChoiceAdapter<Value>;
|
|
15
|
+
export declare function createMultipleNativeChoiceAdapter<Value>(options: () => readonly NativeChoiceOption<Value>[] | undefined): NativeSelectChoiceAdapter<Value[]>;
|
|
16
|
+
export declare function createStringListNativeChoiceAdapter(): NativeSelectChoiceAdapter<string[]>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type PointerSessionEndUpdate = 'event' | 'none' | 'pending-pointerup';
|
|
2
|
+
type PointerSessionUpdateMode = 'animation-frame' | 'immediate';
|
|
3
|
+
interface PointerSessionAdapter<TState> {
|
|
4
|
+
endUpdate?: PointerSessionEndUpdate;
|
|
5
|
+
onStart?: (event: PointerEvent, state: TState) => void;
|
|
6
|
+
onStop?: (state: TState) => void;
|
|
7
|
+
onUpdate: (event: PointerEvent, state: TState) => void;
|
|
8
|
+
refreshGeometry?: (state: TState) => boolean;
|
|
9
|
+
updateMode?: PointerSessionUpdateMode;
|
|
10
|
+
}
|
|
11
|
+
interface PointerSessionStart<TState> {
|
|
12
|
+
geometryDirty?: boolean;
|
|
13
|
+
state: TState;
|
|
14
|
+
target: HTMLElement;
|
|
15
|
+
}
|
|
16
|
+
export declare function createPointerSession<TState>(adapter: PointerSessionAdapter<TState>): {
|
|
17
|
+
start: (event: PointerEvent, initialize: () => PointerSessionStart<TState> | undefined) => boolean;
|
|
18
|
+
stop: () => void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ElementDirection } from './direction.js';
|
|
1
2
|
export type ScrollAxis = 'x' | 'y';
|
|
2
|
-
export type ScrollDirection =
|
|
3
|
+
export type ScrollDirection = ElementDirection;
|
|
3
4
|
export interface KeyboardScrollPositionOptions {
|
|
4
5
|
axis: ScrollAxis;
|
|
5
6
|
key: string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export interface LabeledOption {
|
|
2
|
+
label: string;
|
|
3
|
+
}
|
|
4
|
+
export type OptionFilter<Option> = (option: Option, searchValue: string) => boolean;
|
|
5
|
+
export declare function filterOptions<Option extends LabeledOption>(options: readonly Option[] | undefined, searchValue: string, filter: OptionFilter<Option> | false | undefined): Option[];
|
|
@@ -68,10 +68,10 @@ Use `autoUpdateOptions.animationFrame` sparingly. It checks the reference positi
|
|
|
68
68
|
frame and is intended for references moving with CSS transforms or nested floating elements outside
|
|
69
69
|
their ancestor's scrolling context. The animation-frame loop only runs while positioning is open.
|
|
70
70
|
|
|
71
|
-
`Popover`, `Tooltip`, `DropdownMenu`, `DropdownMenuContent` and
|
|
72
|
-
same `flipOptions` and `autoUpdateOptions` objects. On the
|
|
73
|
-
also apply to its open submenus. Each open floating element
|
|
74
|
-
animation-frame loop.
|
|
71
|
+
`HoverCard`, `Popover`, `Tooltip`, `DropdownMenu`, `DropdownMenuContent` and
|
|
72
|
+
`DropdownMenuSubContent` accept the same `flipOptions` and `autoUpdateOptions` objects. On the
|
|
73
|
+
data-driven `DropdownMenu`, the options also apply to its open submenus. Each open floating element
|
|
74
|
+
using `animationFrame: true` runs its own animation-frame loop.
|
|
75
75
|
|
|
76
76
|
The return value contains readonly `actualPlacement`, `floatingStyle`, `arrowStyle` and
|
|
77
77
|
`isPositioned` refs, plus an async `update()` method for content-driven layout changes.
|
|
@@ -92,6 +92,9 @@ for keyboard handling, focus management, roles, labels, outside interaction and
|
|
|
92
92
|
coordinates the trigger and floating content, so a close delay started when the pointer leaves the
|
|
93
93
|
trigger is cancelled when the pointer enters the content.
|
|
94
94
|
|
|
95
|
+
`HoverCard` composes this behavior with positioning, Teleport and styled content. Use the composable
|
|
96
|
+
directly when custom markup or a different visual treatment is required.
|
|
97
|
+
|
|
95
98
|
```vue
|
|
96
99
|
<template>
|
|
97
100
|
<a ref="reference" href="/people/ada" v-bind="triggerProps">Ada Lovelace</a>
|