Skip to content

Commit a9a1aa2

Browse files
committed
Merge branch 'master' into next
| Conflicts: | packages/vuetify/src/components/VSnackbar/VSnackbar.tsx
2 parents 1371aba + ed74c54 commit a9a1aa2

File tree

6 files changed

+70
-23
lines changed

6 files changed

+70
-23
lines changed

packages/api-generator/src/locale/en/VSnackbar.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"props": {
33
"app": "Respects boundaries of—and will not overlap with—other `app` components like `v-app-bar`, `v-navigation-drawer`, and `v-footer`.",
44
"centered": "Positions the snackbar in the center of the screen, (x and y axis).",
5-
"multiLine": "Gives the snackbar a larger minimum height.",
5+
"multiLine": "Deprecated, use `min-height` instead. Increases minimum height.",
66
"timer": "Display a progress bar that counts down until the snackbar closes. Pass a string to set a custom color, otherwise uses `info`.",
77
"timeout": "Time (in milliseconds) to wait until snackbar is automatically hidden. Use `-1` to keep open indefinitely (`0` in version < 2.3 ). It is recommended for this number to be between `4000` and `10000`. Changes to this property will reset the timeout.",
88
"vertical": "Stacks snackbar content on top of the actions (button)."

packages/vuetify/src/components/VOverlay/locationStrategies.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ function connectedLocationStrategy (data: LocationStrategyData, props: StrategyP
279279

280280
const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value)
281281
const scrollParents = getScrollParents(data.contentEl.value)
282-
const viewportMargin = 12
282+
const viewportMargin = props.stickToTarget ? 0 : 12 // TOOD: prop.viewportMargin
283283

284284
if (!scrollParents.length) {
285285
scrollParents.push(document.documentElement)
@@ -302,10 +302,18 @@ function connectedLocationStrategy (data: LocationStrategyData, props: StrategyP
302302
}
303303
return scrollBox
304304
}, undefined!)
305-
viewport.x += viewportMargin
306-
viewport.y += viewportMargin
307-
viewport.width -= viewportMargin * 2
308-
viewport.height -= viewportMargin * 2
305+
306+
if (props.stickToTarget) {
307+
viewport.x += Math.min(0, targetBox.x)
308+
viewport.y += Math.min(0, targetBox.y)
309+
viewport.width = Math.max(viewport.width, targetBox.x + targetBox.width)
310+
viewport.height = Math.max(viewport.height, targetBox.y + targetBox.height)
311+
} else {
312+
viewport.x += viewportMargin
313+
viewport.y += viewportMargin
314+
viewport.width -= viewportMargin * 2
315+
viewport.height -= viewportMargin * 2
316+
}
309317

310318
let placement = {
311319
anchor: preferredAnchor.value,
@@ -397,19 +405,19 @@ function connectedLocationStrategy (data: LocationStrategyData, props: StrategyP
397405

398406
// shift
399407
if (overflows.x.before) {
400-
if (!props.stickToTarget) x += overflows.x.before
408+
x += overflows.x.before
401409
contentBox.x += overflows.x.before
402410
}
403411
if (overflows.x.after) {
404-
if (!props.stickToTarget) x -= overflows.x.after
412+
x -= overflows.x.after
405413
contentBox.x -= overflows.x.after
406414
}
407415
if (overflows.y.before) {
408-
if (!props.stickToTarget) y += overflows.y.before
416+
y += overflows.y.before
409417
contentBox.y += overflows.y.before
410418
}
411419
if (overflows.y.after) {
412-
if (!props.stickToTarget) y -= overflows.y.after
420+
y -= overflows.y.after
413421
contentBox.y -= overflows.y.after
414422
}
415423

@@ -419,9 +427,9 @@ function connectedLocationStrategy (data: LocationStrategyData, props: StrategyP
419427
available.x = viewport.width - overflows.x.before - overflows.x.after
420428
available.y = viewport.height - overflows.y.before - overflows.y.after
421429

422-
if (!props.stickToTarget) x += overflows.x.before
430+
x += overflows.x.before
423431
contentBox.x += overflows.x.before
424-
if (!props.stickToTarget) y += overflows.y.before
432+
y += overflows.y.before
425433
contentBox.y += overflows.y.before
426434
}
427435

packages/vuetify/src/components/VOverlay/useActivator.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ export function useActivator (
114114
isActive.value = !isActive.value
115115
},
116116
onMouseenter: (e: MouseEvent) => {
117-
if (e.sourceCapabilities?.firesTouchEvents) return
118-
119117
isHovered = true
120118
activatorEl.value = (e.currentTarget || e.target) as HTMLElement
121119
runOpenDelay()

packages/vuetify/src/composables/nested/nested.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
leafSingleSelectStrategy,
3232
trunkSelectStrategy,
3333
} from './selectStrategies'
34-
import { consoleError, getCurrentInstance, propsFactory } from '@/util'
34+
import { consoleError, getCurrentInstance, propsFactory, throttle } from '@/util'
3535

3636
// Types
3737
import type { InjectionKey, MaybeRefOrGetter, PropType, Ref } from 'vue'
@@ -220,6 +220,11 @@ export const useNested = (props: NestedProps) => {
220220

221221
const nodeIds = new Set<unknown>()
222222

223+
const itemsUpdatePropagation = throttle(() => {
224+
children.value = new Map(children.value)
225+
parents.value = new Map(parents.value)
226+
}, 100)
227+
223228
const nested: NestedProvide = {
224229
id: shallowRef(),
225230
root: {
@@ -255,6 +260,7 @@ export const useNested = (props: NestedProps) => {
255260
if (parentId != null) {
256261
children.value.set(parentId, [...children.value.get(parentId) || [], id])
257262
}
263+
itemsUpdatePropagation()
258264
},
259265
unregister: id => {
260266
if (isUnmounted) return
@@ -268,6 +274,7 @@ export const useNested = (props: NestedProps) => {
268274
children.value.set(parent, list.filter(child => child !== id))
269275
}
270276
parents.value.delete(id)
277+
itemsUpdatePropagation()
271278
},
272279
open: (id, value, event) => {
273280
vm.emit('click:open', { id, value, path: getPath(id), event })

packages/vuetify/src/labs/VPie/VPie.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ export const VPie = genericComponent<VPieSlots>()({
293293

294294
const tooltipDefaults = {
295295
VAvatar: {
296-
size: typeof props.tooltip === 'object' ? props.tooltip.avatarSize : 28,
296+
size: typeof props.tooltip === 'object' ? (props.tooltip.avatarSize ?? 28) : 28,
297297
},
298298
}
299299

packages/vuetify/src/util/helpers.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
unref,
1212
watchEffect,
1313
} from 'vue'
14+
import { consoleError } from '@/util/console'
1415
import { IN_BROWSER } from '@/util/globals'
1516

1617
// Types
@@ -419,15 +420,39 @@ export function debounce (fn: Function, delay: MaybeRef<number>) {
419420
return wrap
420421
}
421422

422-
export function throttle<T extends (...args: any[]) => any> (fn: T, limit: number) {
423+
export function throttle<T extends (...args: any[]) => any> (
424+
fn: T,
425+
delay: number,
426+
options = { leading: true, trailing: true },
427+
) {
428+
let timeoutId = 0
429+
let lastExec = 0
423430
let throttling = false
424-
return (...args: Parameters<T>): void | ReturnType<T> => {
425-
if (!throttling) {
426-
throttling = true
427-
setTimeout(() => throttling = false, limit)
428-
return fn(...args)
431+
432+
const wrap = (...args: Parameters<T>): void | ReturnType<T> => {
433+
clearTimeout(timeoutId)
434+
const now = Date.now()
435+
const elapsed = now - lastExec
436+
437+
if (!throttling || elapsed >= delay) {
438+
lastExec = now
429439
}
440+
if ((!throttling && options.leading) || elapsed >= delay) {
441+
window.setTimeout(() => fn(...args)) // ignore 'fn' executin errors
442+
}
443+
444+
throttling = true
445+
timeoutId = window.setTimeout(() => {
446+
throttling = false
447+
if (options.trailing) {
448+
fn(...args)
449+
}
450+
}, delay)
430451
}
452+
453+
wrap.clear = () => clearTimeout(timeoutId)
454+
wrap.immediate = fn
455+
return wrap
431456
}
432457

433458
export function clamp (value: number, min = 0, max = 1) {
@@ -666,7 +691,16 @@ export function focusableChildren (el: Element, filterByTabIndex = true) {
666691
]
667692
.map(s => `${s}${filterByTabIndex ? ':not([tabindex="-1"])' : ''}:not([disabled], [inert])`)
668693
.join(', ')
669-
return ([...el.querySelectorAll(targets)] as HTMLElement[])
694+
695+
let elements
696+
try {
697+
elements = [...el.querySelectorAll(targets)] as HTMLElement[]
698+
} catch (err) {
699+
consoleError(String(err))
700+
return []
701+
}
702+
703+
return elements
670704
.filter(x => !x.closest('[inert]')) // does not have inert parent
671705
.filter(x => !!x.offsetParent || x.getClientRects().length > 0) // is rendered
672706
.filter(x => !x.parentElement?.closest('details:not([open])') ||

0 commit comments

Comments
 (0)