@mantine-vue/hooks 3.4.0 → 3.6.0
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/cjs/index.cjs +97 -46
- package/cjs/index.cjs.map +1 -1
- package/esm/index.mjs +97 -46
- package/esm/index.mjs.map +1 -1
- package/lib/use-click-outside/use-click-outside.d.ts +1 -1
- package/lib/use-collapse/use-collapse.d.ts +1 -0
- package/package.json +1 -1
package/cjs/index.cjs
CHANGED
|
@@ -118,9 +118,10 @@ function useDebouncedCallback(callback, waitOrOptions) {
|
|
|
118
118
|
}
|
|
119
119
|
//#endregion
|
|
120
120
|
//#region src/use-click-outside/use-click-outside.ts
|
|
121
|
-
function useClickOutside(callback, events = ["mousedown", "touchstart"], nodes, enabled = true) {
|
|
121
|
+
function useClickOutside(callback, events = ["mousedown", "touchstart"], nodes, enabled = true, capture = false) {
|
|
122
122
|
const element = (0, vue.ref)(null);
|
|
123
123
|
let activeEvents = [];
|
|
124
|
+
let activeCapture = false;
|
|
124
125
|
const listener = (event) => {
|
|
125
126
|
const target = event.target;
|
|
126
127
|
if (!target || !document.body.contains(target) && target.tagName !== "HTML") return;
|
|
@@ -131,17 +132,22 @@ function useClickOutside(callback, events = ["mousedown", "touchstart"], nodes,
|
|
|
131
132
|
} else if (element.value && !path.includes(element.value)) callback(event);
|
|
132
133
|
};
|
|
133
134
|
const cleanup = () => {
|
|
134
|
-
activeEvents.forEach((event) => document.removeEventListener(event, listener));
|
|
135
|
+
activeEvents.forEach((event) => document.removeEventListener(event, listener, activeCapture));
|
|
135
136
|
activeEvents = [];
|
|
136
137
|
};
|
|
137
138
|
const bind = () => {
|
|
138
139
|
cleanup();
|
|
139
140
|
if (!(0, vue.toValue)(enabled)) return;
|
|
140
141
|
activeEvents = (0, vue.toValue)(events) || ["mousedown", "touchstart"];
|
|
141
|
-
|
|
142
|
+
activeCapture = (0, vue.toValue)(capture);
|
|
143
|
+
activeEvents.forEach((event) => document.addEventListener(event, listener, activeCapture));
|
|
142
144
|
};
|
|
143
145
|
(0, vue.onMounted)(bind);
|
|
144
|
-
(0, vue.watch)([
|
|
146
|
+
(0, vue.watch)([
|
|
147
|
+
() => (0, vue.toValue)(events)?.join(","),
|
|
148
|
+
() => (0, vue.toValue)(enabled),
|
|
149
|
+
() => (0, vue.toValue)(capture)
|
|
150
|
+
], bind);
|
|
145
151
|
(0, vue.onBeforeUnmount)(cleanup);
|
|
146
152
|
return element;
|
|
147
153
|
}
|
|
@@ -185,7 +191,11 @@ function useClipboard({ timeout = 2e3 } = {}) {
|
|
|
185
191
|
//#region src/use-media-query/use-media-query.ts
|
|
186
192
|
function getInitialMediaQueryValue(query, initialValue) {
|
|
187
193
|
if (typeof initialValue === "boolean") return initialValue;
|
|
188
|
-
if (typeof window !== "undefined" && typeof window.matchMedia === "function")
|
|
194
|
+
if (typeof window !== "undefined" && typeof window.matchMedia === "function") try {
|
|
195
|
+
return window.matchMedia(query).matches;
|
|
196
|
+
} catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
189
199
|
return false;
|
|
190
200
|
}
|
|
191
201
|
function useMediaQuery(query, initialValue = false, options = { getInitialValueInEffect: true }) {
|
|
@@ -255,6 +265,10 @@ function useDebouncedState(initialValue, wait, options = {}) {
|
|
|
255
265
|
if (options.leading && !leadingCalled) {
|
|
256
266
|
value.value = next;
|
|
257
267
|
leadingCalled = true;
|
|
268
|
+
clear();
|
|
269
|
+
timeout = setTimeout(() => {
|
|
270
|
+
leadingCalled = false;
|
|
271
|
+
}, wait);
|
|
258
272
|
} else {
|
|
259
273
|
clear();
|
|
260
274
|
timeout = setTimeout(() => {
|
|
@@ -1026,7 +1040,7 @@ function usePagination({ total, siblings = 1, boundaries = 1, page, initialPage,
|
|
|
1026
1040
|
const leftSiblingIndex = Math.max(active.value - siblings, start.value + boundaries - 1);
|
|
1027
1041
|
const rightSiblingIndex = Math.min(active.value + siblings, end.value - boundaries);
|
|
1028
1042
|
const shouldShowLeftDots = leftSiblingIndex > start.value + boundaries + 1;
|
|
1029
|
-
const shouldShowRightDots = rightSiblingIndex < end.value - boundaries;
|
|
1043
|
+
const shouldShowRightDots = rightSiblingIndex < end.value - (boundaries + 1);
|
|
1030
1044
|
if (!shouldShowLeftDots && shouldShowRightDots) {
|
|
1031
1045
|
const leftItemCount = siblings * 2 + boundaries + 2;
|
|
1032
1046
|
return [
|
|
@@ -1432,8 +1446,8 @@ function useIntersection(options) {
|
|
|
1432
1446
|
entry.value = null;
|
|
1433
1447
|
return;
|
|
1434
1448
|
}
|
|
1435
|
-
observer = new IntersectionObserver((
|
|
1436
|
-
entry.value =
|
|
1449
|
+
observer = new IntersectionObserver((entries) => {
|
|
1450
|
+
entry.value = entries[entries.length - 1];
|
|
1437
1451
|
}, options);
|
|
1438
1452
|
observer.observe(node);
|
|
1439
1453
|
}, { immediate: true });
|
|
@@ -1536,12 +1550,10 @@ function getHotkeyMatcher(hotkey, usePhysicalKeys) {
|
|
|
1536
1550
|
}
|
|
1537
1551
|
function getHotkeyHandler(hotkeys) {
|
|
1538
1552
|
return (event) => {
|
|
1539
|
-
hotkeys.forEach(([hotkey, handler, options
|
|
1540
|
-
preventDefault
|
|
1541
|
-
usePhysicalKeys
|
|
1542
|
-
|
|
1543
|
-
if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event)) {
|
|
1544
|
-
if (options.preventDefault) event.preventDefault();
|
|
1553
|
+
hotkeys.forEach(([hotkey, handler, options]) => {
|
|
1554
|
+
const { preventDefault = true, usePhysicalKeys = false } = options || {};
|
|
1555
|
+
if (getHotkeyMatcher(hotkey, usePhysicalKeys)(event)) {
|
|
1556
|
+
if (preventDefault) event.preventDefault();
|
|
1545
1557
|
handler(event);
|
|
1546
1558
|
}
|
|
1547
1559
|
});
|
|
@@ -1572,16 +1584,14 @@ function useHotkeys(hotkeys, tagsToIgnore = [
|
|
|
1572
1584
|
"select"
|
|
1573
1585
|
], triggerOnContentEditable = false) {
|
|
1574
1586
|
const handleKeydown = (event) => {
|
|
1575
|
-
(0, vue.toValue)(hotkeys).forEach(([hotkey, handler, options
|
|
1576
|
-
preventDefault
|
|
1577
|
-
usePhysicalKeys
|
|
1578
|
-
}]) => {
|
|
1579
|
-
if (getHotkeyMatcher(hotkey, options.usePhysicalKeys)(event) && shouldFireEvent(event, (0, vue.toValue)(tagsToIgnore) ?? [
|
|
1587
|
+
(0, vue.toValue)(hotkeys).forEach(([hotkey, handler, options]) => {
|
|
1588
|
+
const { preventDefault = true, usePhysicalKeys = false } = options || {};
|
|
1589
|
+
if (getHotkeyMatcher(hotkey, usePhysicalKeys)(event) && shouldFireEvent(event, (0, vue.toValue)(tagsToIgnore) ?? [
|
|
1580
1590
|
"input",
|
|
1581
1591
|
"textarea",
|
|
1582
1592
|
"select"
|
|
1583
1593
|
], (0, vue.toValue)(triggerOnContentEditable))) {
|
|
1584
|
-
if (
|
|
1594
|
+
if (preventDefault) event.preventDefault();
|
|
1585
1595
|
handler(event);
|
|
1586
1596
|
}
|
|
1587
1597
|
});
|
|
@@ -2279,7 +2289,13 @@ function useThrottledCallbackWithClearTimeout(callback, wait) {
|
|
|
2279
2289
|
let latestOutArgs = null;
|
|
2280
2290
|
let active = true;
|
|
2281
2291
|
let timeoutId = -1;
|
|
2282
|
-
const clear = () =>
|
|
2292
|
+
const clear = () => {
|
|
2293
|
+
window.clearTimeout(timeoutId);
|
|
2294
|
+
timeoutId = -1;
|
|
2295
|
+
active = true;
|
|
2296
|
+
latestInArgs = null;
|
|
2297
|
+
latestOutArgs = null;
|
|
2298
|
+
};
|
|
2283
2299
|
const callThrottledCallback = (...args) => {
|
|
2284
2300
|
callback(...args);
|
|
2285
2301
|
latestInArgs = args;
|
|
@@ -2521,6 +2537,10 @@ function useRadialMove(onChange, { step = .01, onChangeEnd, onScrubStart, onScru
|
|
|
2521
2537
|
//#endregion
|
|
2522
2538
|
//#region src/use-scroll-spy/use-scroll-spy.ts
|
|
2523
2539
|
var scrollSpyId = 0;
|
|
2540
|
+
function resolveHeadingNode(heading, selector, index) {
|
|
2541
|
+
if (heading.isConnected) return heading;
|
|
2542
|
+
return (heading.id ? document.getElementById(heading.id) : null) ?? document.querySelectorAll(selector)[index] ?? heading;
|
|
2543
|
+
}
|
|
2524
2544
|
function getActiveElement(rects, offset = 0) {
|
|
2525
2545
|
if (rects.length === 0) return -1;
|
|
2526
2546
|
return rects.reduce((closest, rect, index) => Math.abs(closest.position - offset) < Math.abs(rect.y - offset) ? closest : {
|
|
@@ -2543,11 +2563,12 @@ function useScrollSpy(options = {}) {
|
|
|
2543
2563
|
if (typeof document === "undefined") return;
|
|
2544
2564
|
const getDepth = options.getDepth ?? ((element) => Number(element.tagName[1]));
|
|
2545
2565
|
const getValue = options.getValue ?? ((element) => element.textContent || "");
|
|
2546
|
-
|
|
2566
|
+
const selector = (0, vue.toValue)(options.selector) ?? "h1, h2, h3, h4, h5, h6";
|
|
2567
|
+
data.value = Array.from(document.querySelectorAll(selector)).map((heading, index) => ({
|
|
2547
2568
|
depth: getDepth(heading),
|
|
2548
2569
|
value: getValue(heading),
|
|
2549
2570
|
id: heading.id || `mantine-scroll-spy-${++scrollSpyId}`,
|
|
2550
|
-
getNode: () => heading
|
|
2571
|
+
getNode: () => resolveHeadingNode(heading, selector, index)
|
|
2551
2572
|
}));
|
|
2552
2573
|
initialized.value = true;
|
|
2553
2574
|
updateActive();
|
|
@@ -3041,6 +3062,9 @@ function getElementContentSize(element, dimension) {
|
|
|
3041
3062
|
function getCssSize(size) {
|
|
3042
3063
|
return typeof size === "number" ? `${size}px` : size;
|
|
3043
3064
|
}
|
|
3065
|
+
function isMeasured(size) {
|
|
3066
|
+
return typeof size === "number" && size > 0;
|
|
3067
|
+
}
|
|
3044
3068
|
function createCollapse({ dimension, getElementSize, expanded, transitionDuration, transitionTimingFunction = "ease", onTransitionEnd, onTransitionStart, keepMounted }) {
|
|
3045
3069
|
const isExpanded = () => (0, vue.toValue)(expanded);
|
|
3046
3070
|
const getTransitionDuration = () => (0, vue.toValue)(transitionDuration);
|
|
@@ -3054,17 +3078,24 @@ function createCollapse({ dimension, getElementSize, expanded, transitionDuratio
|
|
|
3054
3078
|
const styles = (0, vue.ref)(isExpanded() ? {} : collapsedStyles);
|
|
3055
3079
|
const state = (0, vue.ref)(isExpanded() ? "entered" : "exited");
|
|
3056
3080
|
const raf = typeof window === "undefined" ? (callback) => callback(0) : window.requestAnimationFrame;
|
|
3081
|
+
let transitionId = 0;
|
|
3057
3082
|
const mergeStyles = (nextStyles) => {
|
|
3058
3083
|
styles.value = {
|
|
3059
3084
|
...styles.value,
|
|
3060
3085
|
...nextStyles
|
|
3061
3086
|
};
|
|
3062
3087
|
};
|
|
3063
|
-
const measureExpandedSize = (attempt = 0) => {
|
|
3064
|
-
if (!isExpanded()) return;
|
|
3088
|
+
const measureExpandedSize = (currentTransitionId, attempt = 0) => {
|
|
3089
|
+
if (transitionId !== currentTransitionId || !isExpanded() || !elementRef.value) return;
|
|
3065
3090
|
const size = getElementSize(elementRef.value);
|
|
3066
3091
|
if (size === 0 && elementRef.value?.children.length && attempt < 5) {
|
|
3067
|
-
raf(() => measureExpandedSize(attempt + 1));
|
|
3092
|
+
raf(() => measureExpandedSize(currentTransitionId, attempt + 1));
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
if (!isMeasured(size)) {
|
|
3096
|
+
styles.value = {};
|
|
3097
|
+
state.value = "entered";
|
|
3098
|
+
onTransitionEnd?.();
|
|
3068
3099
|
return;
|
|
3069
3100
|
}
|
|
3070
3101
|
mergeStyles({
|
|
@@ -3078,8 +3109,12 @@ function createCollapse({ dimension, getElementSize, expanded, transitionDuratio
|
|
|
3078
3109
|
};
|
|
3079
3110
|
(0, vue.watch)(() => isExpanded(), (value, oldValue) => {
|
|
3080
3111
|
if (value === oldValue) return;
|
|
3112
|
+
transitionId += 1;
|
|
3113
|
+
const currentTransitionId = transitionId;
|
|
3114
|
+
const isCurrentTransition = () => transitionId === currentTransitionId && elementRef.value !== null;
|
|
3081
3115
|
if (getTransitionDuration() !== 0) onTransitionStart?.();
|
|
3082
3116
|
if (value) raf(() => {
|
|
3117
|
+
if (!isCurrentTransition()) return;
|
|
3083
3118
|
state.value = "entering";
|
|
3084
3119
|
mergeStyles({
|
|
3085
3120
|
willChange: dimension,
|
|
@@ -3088,24 +3123,37 @@ function createCollapse({ dimension, getElementSize, expanded, transitionDuratio
|
|
|
3088
3123
|
});
|
|
3089
3124
|
(0, vue.nextTick)(() => {
|
|
3090
3125
|
raf(() => {
|
|
3091
|
-
|
|
3126
|
+
if (!isCurrentTransition()) return;
|
|
3127
|
+
raf(() => measureExpandedSize(currentTransitionId));
|
|
3092
3128
|
});
|
|
3093
3129
|
});
|
|
3094
3130
|
});
|
|
3095
3131
|
else raf(() => {
|
|
3132
|
+
if (!isCurrentTransition()) return;
|
|
3096
3133
|
state.value = "exiting";
|
|
3097
3134
|
const size = getElementSize(elementRef.value);
|
|
3135
|
+
if (!isMeasured(size)) {
|
|
3136
|
+
styles.value = collapsedStyles;
|
|
3137
|
+
state.value = "exited";
|
|
3138
|
+
onTransitionEnd?.();
|
|
3139
|
+
return;
|
|
3140
|
+
}
|
|
3098
3141
|
mergeStyles({
|
|
3099
3142
|
...getTransitionStyles(size),
|
|
3100
3143
|
willChange: dimension,
|
|
3101
3144
|
[dimension]: getCssSize(size)
|
|
3102
3145
|
});
|
|
3103
|
-
raf(() =>
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3146
|
+
raf(() => {
|
|
3147
|
+
if (isCurrentTransition()) mergeStyles({
|
|
3148
|
+
[dimension]: 0,
|
|
3149
|
+
overflow: "hidden"
|
|
3150
|
+
});
|
|
3151
|
+
});
|
|
3107
3152
|
});
|
|
3108
3153
|
}, { flush: "post" });
|
|
3154
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
3155
|
+
transitionId += 1;
|
|
3156
|
+
});
|
|
3109
3157
|
const handleTransitionEnd = (event) => {
|
|
3110
3158
|
if (event.target !== elementRef.value || event.propertyName !== dimension) return;
|
|
3111
3159
|
if (isExpanded()) {
|
|
@@ -3269,7 +3317,7 @@ function findPrevTokenIndex(slots, from) {
|
|
|
3269
3317
|
for (let i = from; i >= 0; i--) if (slots[i].type === "token") return i;
|
|
3270
3318
|
return -1;
|
|
3271
3319
|
}
|
|
3272
|
-
function processInput(inputValue, slots, _slotCharOption) {
|
|
3320
|
+
function processInput(inputValue, slots, _slotCharOption, transform) {
|
|
3273
3321
|
let result = "";
|
|
3274
3322
|
let inputIndex = 0;
|
|
3275
3323
|
for (let slotIndex = 0; slotIndex < slots.length && inputIndex <= inputValue.length; slotIndex++) {
|
|
@@ -3281,7 +3329,7 @@ function processInput(inputValue, slots, _slotCharOption) {
|
|
|
3281
3329
|
}
|
|
3282
3330
|
if (inputIndex >= inputValue.length) break;
|
|
3283
3331
|
while (inputIndex < inputValue.length) {
|
|
3284
|
-
const ch = inputValue[inputIndex];
|
|
3332
|
+
const ch = transform ? transform(inputValue[inputIndex]) : inputValue[inputIndex];
|
|
3285
3333
|
inputIndex++;
|
|
3286
3334
|
if (slot.pattern.test(ch)) {
|
|
3287
3335
|
result += ch;
|
|
@@ -3402,9 +3450,11 @@ function useMask(options) {
|
|
|
3402
3450
|
};
|
|
3403
3451
|
const initializeInputValue = (inputNode) => {
|
|
3404
3452
|
if (!inputNode.value) return false;
|
|
3405
|
-
const
|
|
3406
|
-
const { slots:
|
|
3407
|
-
const
|
|
3453
|
+
const isOwnValue = inputNode.value === display;
|
|
3454
|
+
const { slots: initialSlots, slotChar: initialSlotChar, transform } = getResolvedOptions(options, "");
|
|
3455
|
+
const parse = (slots, slotChar) => isOwnValue ? applyMaskToRaw(rawInternal, slots, slotChar, options.transform) : processInput(inputNode.value, slots, slotChar, transform);
|
|
3456
|
+
const { slots: resolvedSlots, slotChar } = getResolvedOptions(options, extractRaw(parse(initialSlots, initialSlotChar), initialSlots));
|
|
3457
|
+
const reprocessed = parse(resolvedSlots, slotChar);
|
|
3408
3458
|
const newRaw = extractRaw(reprocessed, resolvedSlots);
|
|
3409
3459
|
const showSlots = options.alwaysShowMask || isFocused;
|
|
3410
3460
|
const showOnFocus = options.showMaskOnFocus !== false;
|
|
@@ -3747,6 +3797,13 @@ function findLastEnabled(total, isItemDisabled) {
|
|
|
3747
3797
|
for (let i = total - 1; i >= 0; i -= 1) if (!isItemDisabled(i)) return i;
|
|
3748
3798
|
return 0;
|
|
3749
3799
|
}
|
|
3800
|
+
function findEnabledInRow(row, startCol, step, columns, total, isItemDisabled) {
|
|
3801
|
+
for (let col = startCol; col >= 0 && col < columns; col += step) {
|
|
3802
|
+
const candidate = row * columns + col;
|
|
3803
|
+
if (candidate < total && !isItemDisabled(candidate)) return candidate;
|
|
3804
|
+
}
|
|
3805
|
+
return null;
|
|
3806
|
+
}
|
|
3750
3807
|
var defaultIsItemDisabled = () => false;
|
|
3751
3808
|
function useRovingIndex(input) {
|
|
3752
3809
|
const { total, orientation = "horizontal", loop = true, dir = "ltr", activateOnFocus = false, columns, focusedIndex, initialIndex, onFocusChange, isItemDisabled = defaultIsItemDisabled } = input;
|
|
@@ -3785,19 +3842,13 @@ function useRovingIndex(input) {
|
|
|
3785
3842
|
const isRtl = dir === "rtl";
|
|
3786
3843
|
switch (event.key) {
|
|
3787
3844
|
case "ArrowRight": {
|
|
3788
|
-
const
|
|
3789
|
-
|
|
3790
|
-
const candidate = row * cols + targetCol;
|
|
3791
|
-
if (!isItemDisabled(candidate)) nextIndex = candidate;
|
|
3792
|
-
}
|
|
3845
|
+
const step = isRtl ? -1 : 1;
|
|
3846
|
+
nextIndex = findEnabledInRow(row, col + step, step, cols, total_, isItemDisabled);
|
|
3793
3847
|
break;
|
|
3794
3848
|
}
|
|
3795
3849
|
case "ArrowLeft": {
|
|
3796
|
-
const
|
|
3797
|
-
|
|
3798
|
-
const candidate = row * cols + targetCol;
|
|
3799
|
-
if (!isItemDisabled(candidate)) nextIndex = candidate;
|
|
3800
|
-
}
|
|
3850
|
+
const step = isRtl ? 1 : -1;
|
|
3851
|
+
nextIndex = findEnabledInRow(row, col + step, step, cols, total_, isItemDisabled);
|
|
3801
3852
|
break;
|
|
3802
3853
|
}
|
|
3803
3854
|
case "ArrowDown":
|