Socket
Socket
Sign inDemoInstall

@vaadin/component-base

Package Overview
Dependencies
5
Maintainers
12
Versions
344
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 24.4.0-alpha2 to 24.4.0-alpha20

4

package.json
{
"name": "@vaadin/component-base",
"version": "24.4.0-alpha2",
"version": "24.4.0-alpha20",
"publishConfig": {

@@ -45,3 +45,3 @@ "access": "public"

},
"gitHead": "f303ead58d27e15d81a55db0559611fb77c0e421"
"gitHead": "9d2eacc494eb27658ba9298be6656815912637be"
}

@@ -12,3 +12,3 @@ /**

get() {
return '24.4.0-alpha2';
return '24.4.0-alpha20';
},

@@ -15,0 +15,0 @@ });

@@ -8,5 +8,9 @@ /**

/**
* Check if two paths can be resolved as URLs
* with the same origin and pathname.
* Checks if two paths match based on their origin, pathname, and query parameters.
*
* The function matches an actual URL against an expected URL to see if they share
* the same base origin (like https://example.com), the same path (like /path/to/page),
* and if the actual URL contains at least all the query parameters with the same values
* from the expected URL.
*/
export declare function matchPaths(path1: string, path2: string): boolean;
export declare function matchPaths(actual: string, expected: string): boolean;

@@ -8,13 +8,35 @@ /**

/**
* Check if two paths can be resolved as URLs
* with the same origin and pathname.
* Checks if one set of URL parameters contains all the parameters
* with the same values from another set.
*
* @param {string} path1
* @param {string} path2
* @param {URLSearchParams} actual
* @param {URLSearchParams} expected
*/
export function matchPaths(path1, path2) {
function containsQueryParams(actual, expected) {
return [...expected.entries()].every(([key, value]) => {
return actual.getAll(key).includes(value);
});
}
/**
* Checks if two paths match based on their origin, pathname, and query parameters.
*
* The function matches an actual URL against an expected URL to see if they share
* the same base origin (like https://example.com), the same path (like /path/to/page),
* and if the actual URL contains at least all the query parameters with the same values
* from the expected URL.
*
* @param {string} actual The actual URL to match.
* @param {string} expected The expected URL to match.
*/
export function matchPaths(actual, expected) {
const base = document.baseURI;
const url1 = new URL(path1, base);
const url2 = new URL(path2, base);
return url1.origin === url2.origin && url1.pathname === url2.pathname;
const actualUrl = new URL(actual, base);
const expectedUrl = new URL(expected, base);
return (
actualUrl.origin === expectedUrl.origin &&
actualUrl.pathname === expectedUrl.pathname &&
containsQueryParams(actualUrl.searchParams, expectedUrl.searchParams)
);
}

@@ -58,2 +58,9 @@ /**

this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
this.elementsContainer.addEventListener('focusin', (e) => {
this.scrollTarget.dispatchEvent(
new CustomEvent('virtualizer-element-focused', { detail: { element: this.__getFocusedElement() } }),
);
});
if (this.reorderElements) {

@@ -86,2 +93,6 @@ // Reordering the physical elements cancels the user's grab of the scroll bar handle on Safari.

get _maxVirtualIndexOffset() {
return this.size - this._virtualCount;
}
__hasPlaceholders() {

@@ -111,3 +122,3 @@ return this.__getVisibleElements().some((el) => el.__virtualizerPlaceholder);

targetVirtualIndex = this._virtualCount - (this.size - index);
this._vidxOffset = this.size - this._virtualCount;
this._vidxOffset = this._maxVirtualIndexOffset;
} else if (targetVirtualIndex < visibleElementCount) {

@@ -142,3 +153,2 @@ if (index < OFFSET_ADJUST_MIN_THRESHOLD) {

flush() {
const startPhysicalCount = this._physicalCount;
// The scroll target is hidden.

@@ -161,7 +171,2 @@ if (this.scrollTarget.offsetHeight === 0) {

}
if (this._physicalCount !== startPhysicalCount) {
// Flushing again until physical count stabilizes fixes https://github.com/vaadin/flow-components/issues/5595#issuecomment-1770278913
this.flush();
}
}

@@ -235,2 +240,3 @@

el.style.paddingTop = '';
el.style.opacity = '';
el.__virtualizerPlaceholder = false;

@@ -260,2 +266,3 @@ }

el.style.paddingTop = `${this.__placeholderHeight}px`;
el.style.opacity = '0';
el.__virtualizerPlaceholder = true;

@@ -307,20 +314,37 @@

// Prevent element update while the scroll position is being restored
this.__preventElementUpdates = true;
// Record the scroll position before changing the size
let fvi; // First visible index
let fviOffsetBefore; // Scroll offset of the first visible index
if (size > 0) {
fvi = this.adjustedFirstVisibleIndex;
fviOffsetBefore = this.__getIndexScrollOffset(fvi);
}
// Change the size
this.__size = size;
if (!this._physicalItems) {
// Not initialized yet
this._itemsChanged({
path: 'items',
});
this.__preventElementUpdates = true;
flush();
this.__preventElementUpdates = false;
} else {
// Already initialized, just update _virtualCount
this._updateScrollerSize();
this._virtualCount = this.items.length;
this._render();
this._itemsChanged({
path: 'items',
});
flush();
// Try to restore the scroll position if the new size is larger than 0
if (size > 0) {
fvi = Math.min(fvi, size - 1);
// Note, calling scrollToIndex also updates the virtual index offset,
// causing the virtualizer to add more items when size is increased,
// and remove exceeding items when size is decreased.
this.scrollToIndex(fvi);
const fviOffsetAfter = this.__getIndexScrollOffset(fvi);
if (fviOffsetBefore !== undefined && fviOffsetAfter !== undefined) {
this._scrollTop += fviOffsetBefore - fviOffsetAfter;
}
}
this.__preventElementUpdates = false;
// When reducing size while invisible, iron-list does not update items, so

@@ -337,4 +361,3 @@ // their hidden state is not updated and their __lastUpdatedIndex is not

// Schedule and flush a resize handler. This will cause a
// re-render for the elements.
// Schedule and flush a resize handler
this._resizeHandler();

@@ -437,2 +460,71 @@ flush();

/** @private */
__getFocusedElement(visibleElements = this.__getVisibleElements()) {
return visibleElements.find(
(element) =>
element.contains(this.elementsContainer.getRootNode().activeElement) ||
element.contains(this.scrollTarget.getRootNode().activeElement),
);
}
/** @private */
__nextFocusableSiblingMissing(focusedElement, visibleElements) {
return (
// Check if focused element is the last visible DOM element
visibleElements.indexOf(focusedElement) === visibleElements.length - 1 &&
// ...while there are more items available
this.size > focusedElement.__virtualIndex + 1
);
}
/** @private */
__previousFocusableSiblingMissing(focusedElement, visibleElements) {
return (
// Check if focused element is the first visible DOM element
visibleElements.indexOf(focusedElement) === 0 &&
// ...while there are preceding items available
focusedElement.__virtualIndex > 0
);
}
/** @private */
__onElementFocused(e) {
if (!this.reorderElements) {
return;
}
const focusedElement = e.detail.element;
if (!focusedElement) {
return;
}
// User has tabbed to or within a virtualizer element.
// Check if a next or previous focusable sibling is missing while it should be there (so the user can continue tabbing).
// The focusable sibling might be missing due to the elements not yet being in the correct DOM order.
// First try flushing (which also flushes any active __scrollReorderDebouncer).
const visibleElements = this.__getVisibleElements();
if (
this.__previousFocusableSiblingMissing(focusedElement, visibleElements) ||
this.__nextFocusableSiblingMissing(focusedElement, visibleElements)
) {
this.flush();
}
// If the focusable sibling is still missing (because the focused element is at the edge of the viewport and
// the virtual scrolling logic hasn't had the need to recycle elements), scroll the virtualizer just enough to
// have the focusable sibling inside the visible viewport to force the virtualizer to recycle.
const reorderedVisibleElements = this.__getVisibleElements();
if (this.__nextFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
this._scrollTop +=
Math.ceil(focusedElement.getBoundingClientRect().bottom) -
Math.floor(this.scrollTarget.getBoundingClientRect().bottom - 1);
this.flush();
} else if (this.__previousFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
this._scrollTop -=
Math.ceil(this.scrollTarget.getBoundingClientRect().top + 1) -
Math.floor(focusedElement.getBoundingClientRect().top);
this.flush();
}
}
_scrollHandler() {

@@ -675,9 +767,3 @@ // The scroll target is hidden.

const visibleElements = this.__getVisibleElements();
const elementWithFocus = visibleElements.find(
(element) =>
element.contains(this.elementsContainer.getRootNode().activeElement) ||
element.contains(this.scrollTarget.getRootNode().activeElement),
);
const targetElement = elementWithFocus || visibleElements[0];
const targetElement = this.__getFocusedElement(visibleElements) || visibleElements[0];
if (!targetElement) {

@@ -717,2 +803,4 @@ // All elements are hidden, don't reorder

_adjustVirtualIndexOffset(delta) {
const maxOffset = this._maxVirtualIndexOffset;
if (this._virtualCount >= this.size) {

@@ -724,5 +812,4 @@ this._vidxOffset = 0;

// Process a large scroll position change
const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.offsetHeight);
const offset = scale * this.size;
this._vidxOffset = Math.round(offset - scale * this._virtualCount);
const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.clientHeight);
this._vidxOffset = Math.round(scale * maxOffset);
} else {

@@ -746,3 +833,2 @@ // Make sure user can always swipe/wheel scroll to the start and end

// Near end
const maxOffset = this.size - this._virtualCount;
if (this._scrollTop >= this._maxScrollTop && this._maxScrollTop > 0) {

@@ -749,0 +835,0 @@ this._vidxOffset = maxOffset;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc