@vaadin/side-nav
Advanced tools
Comparing version 24.4.0-alpha2 to 24.4.0-alpha20
{ | ||
"name": "@vaadin/side-nav", | ||
"version": "24.4.0-alpha2", | ||
"version": "24.4.0-alpha20", | ||
"publishConfig": { | ||
@@ -38,7 +38,7 @@ "access": "public" | ||
"@open-wc/dedupe-mixin": "^1.3.0", | ||
"@vaadin/a11y-base": "24.4.0-alpha2", | ||
"@vaadin/component-base": "24.4.0-alpha2", | ||
"@vaadin/vaadin-lumo-styles": "24.4.0-alpha2", | ||
"@vaadin/vaadin-material-styles": "24.4.0-alpha2", | ||
"@vaadin/vaadin-themable-mixin": "24.4.0-alpha2", | ||
"@vaadin/a11y-base": "24.4.0-alpha20", | ||
"@vaadin/component-base": "24.4.0-alpha20", | ||
"@vaadin/vaadin-lumo-styles": "24.4.0-alpha20", | ||
"@vaadin/vaadin-material-styles": "24.4.0-alpha20", | ||
"@vaadin/vaadin-themable-mixin": "24.4.0-alpha20", | ||
"lit": "^3.0.0" | ||
@@ -56,3 +56,3 @@ }, | ||
], | ||
"gitHead": "f303ead58d27e15d81a55db0559611fb77c0e421" | ||
"gitHead": "9d2eacc494eb27658ba9298be6656815912637be" | ||
} |
@@ -7,4 +7,3 @@ # @vaadin/side-nav | ||
[![npm version](https://badgen.net/npm/v/@vaadin/vaadin-side-nav)](https://www.npmjs.com/package/@vaadin/vaadin-side-nav) | ||
[![Discord](https://img.shields.io/discord/732335336448852018?label=discord)](https://discord.gg/PHmkCKC) | ||
[![npm version](https://badgen.net/npm/v/@vaadin/side-nav)](https://www.npmjs.com/package/@vaadin/side-nav) | ||
@@ -11,0 +10,0 @@ ```html |
@@ -97,8 +97,28 @@ /** | ||
/** | ||
* Whether the path of the item matches the current path. | ||
* Set when the item is appended to DOM or when navigated back | ||
* to the page that contains this item using the browser. | ||
* Whether the item's path matches the current browser URL. | ||
* | ||
* A match occurs when both share the same base origin (like https://example.com), | ||
* the same path (like /path/to/page), and the browser URL contains all | ||
* the query parameters with the same values from the item's path. | ||
* | ||
* The state is updated when the item is added to the DOM or when the browser | ||
* navigates to a new page. | ||
*/ | ||
readonly current: boolean; | ||
/** | ||
* The target of the link. Works only when `path` is set. | ||
*/ | ||
target: string | null | undefined; | ||
/** | ||
* Whether to exclude the item from client-side routing. When enabled, | ||
* this causes the item to behave like a regular anchor, causing a full | ||
* page reload. This only works with supported routers, such as the one | ||
* provided in Vaadin apps, or when using the side nav `onNavigate` hook. | ||
* | ||
* @attr {boolean} router-ignore | ||
*/ | ||
routerIgnore: boolean; | ||
addEventListener<K extends keyof SideNavItemEventMap>( | ||
@@ -105,0 +125,0 @@ type: K, |
@@ -118,6 +118,11 @@ /** | ||
/** | ||
* Whether the path of the item matches the current path. | ||
* Set when the item is appended to DOM or when navigated back | ||
* to the page that contains this item using the browser. | ||
* Whether the item's path matches the current browser URL. | ||
* | ||
* A match occurs when both share the same base origin (like https://example.com), | ||
* the same path (like /path/to/page), and the browser URL contains at least | ||
* all the query parameters with the same values from the item's path. | ||
* | ||
* The state is updated when the item is added to the DOM or when the browser | ||
* navigates to a new page. | ||
* | ||
* @type {boolean} | ||
@@ -131,2 +136,21 @@ */ | ||
}, | ||
/** | ||
* The target of the link. Works only when `path` is set. | ||
*/ | ||
target: String, | ||
/** | ||
* Whether to exclude the item from client-side routing. When enabled, | ||
* this causes the item to behave like a regular anchor, causing a full | ||
* page reload. This only works with supported routers, such as the one | ||
* provided in Vaadin apps, or when using the side nav `onNavigate` hook. | ||
* | ||
* @type {boolean} | ||
* @attr {boolean} router-ignore | ||
*/ | ||
routerIgnore: { | ||
type: Boolean, | ||
value: false, | ||
}, | ||
}; | ||
@@ -189,2 +213,3 @@ } | ||
window.addEventListener('popstate', this.__boundUpdateCurrent); | ||
window.addEventListener('side-nav-location-changed', this.__boundUpdateCurrent); | ||
} | ||
@@ -196,2 +221,3 @@ | ||
window.removeEventListener('popstate', this.__boundUpdateCurrent); | ||
window.removeEventListener('side-nav-location-changed', this.__boundUpdateCurrent); | ||
} | ||
@@ -208,2 +234,4 @@ | ||
href="${ifDefined(this.disabled ? null : this.path)}" | ||
target="${ifDefined(this.target)}" | ||
?router-ignore="${this.routerIgnore}" | ||
part="link" | ||
@@ -257,2 +285,3 @@ aria-current="${this.current ? 'page' : 'false'}" | ||
if (this.current) { | ||
this.__expandParentItems(); | ||
this.expanded = this._items.length > 0; | ||
@@ -263,2 +292,16 @@ } | ||
/** @private */ | ||
__expandParentItems() { | ||
const parentItem = this.__getParentItem(); | ||
if (parentItem) { | ||
parentItem.__expandParentItems(); | ||
} | ||
this.expanded = true; | ||
} | ||
/** @private */ | ||
__getParentItem() { | ||
return this.parentElement instanceof SideNavItem ? this.parentElement : null; | ||
} | ||
/** @private */ | ||
__isCurrent() { | ||
@@ -268,6 +311,5 @@ if (this.path == null) { | ||
} | ||
return ( | ||
matchPaths(document.location.pathname, this.path) || | ||
this.pathAliases.some((alias) => matchPaths(document.location.pathname, alias)) | ||
); | ||
const browserPath = `${document.location.pathname}${document.location.search}`; | ||
return matchPaths(browserPath, this.path) || this.pathAliases.some((alias) => matchPaths(browserPath, alias)); | ||
} | ||
@@ -274,0 +316,0 @@ } |
@@ -10,2 +10,3 @@ /** | ||
import { SideNavChildrenMixin, type SideNavI18n } from './vaadin-side-nav-children-mixin.js'; | ||
import type { SideNavItem } from './vaadin-side-nav-item.js'; | ||
@@ -25,2 +26,11 @@ export type { SideNavI18n }; | ||
export type NavigateEvent = { | ||
path: SideNavItem['path']; | ||
target: SideNavItem['target']; | ||
current: SideNavItem['current']; | ||
expanded: SideNavItem['expanded']; | ||
pathAliases: SideNavItem['pathAliases']; | ||
originalEvent: MouseEvent; | ||
}; | ||
/** | ||
@@ -88,2 +98,36 @@ * `<vaadin-side-nav>` is a Web Component for navigation menus. | ||
/** | ||
* Callback function for router integration. | ||
* | ||
* When a side nav item link is clicked, this function is called and the default click action is cancelled. | ||
* This delegates the responsibility of navigation to the function's logic. | ||
* | ||
* The click event action is not cancelled in the following cases: | ||
* - The click event has a modifier (e.g. `metaKey`, `shiftKey`) | ||
* - The click event is on an external link | ||
* - The click event is on a link with `target="_blank"` | ||
* - The function explicitly returns `false` | ||
* | ||
* The function receives an object with the properties of the clicked side-nav item: | ||
* - `path`: The path of the navigation item. | ||
* - `target`: The target of the navigation item. | ||
* - `current`: A boolean indicating whether the navigation item is currently selected. | ||
* - `expanded`: A boolean indicating whether the navigation item is expanded. | ||
* - `pathAliases`: An array of path aliases for the navigation item. | ||
* - `originalEvent`: The original DOM event that triggered the navigation. | ||
* | ||
* Also see the `location` property for updating the highlighted navigation item on route change. | ||
*/ | ||
onNavigate?: ((event: NavigateEvent) => boolean) | ((event: NavigateEvent) => void); | ||
/** | ||
* A change to this property triggers an update of the highlighted item in the side navigation. While it typically | ||
* corresponds to the browser's URL, the specific value assigned to the property is irrelevant. The component has | ||
* its own internal logic for determining which item is highlighted. | ||
* | ||
* The main use case for this property is when the side navigation is used with a client-side router. In this case, | ||
* the component needs to be informed about route changes so it can update the highlighted item. | ||
*/ | ||
location: any; | ||
addEventListener<K extends keyof SideNavEventMap>( | ||
@@ -90,0 +134,0 @@ type: K, |
@@ -106,2 +106,44 @@ /** | ||
}, | ||
/** | ||
* Callback function for router integration. | ||
* | ||
* When a side nav item link is clicked, this function is called and the default click action is cancelled. | ||
* This delegates the responsibility of navigation to the function's logic. | ||
* | ||
* The click event action is not cancelled in the following cases: | ||
* - The click event has a modifier (e.g. `metaKey`, `shiftKey`) | ||
* - The click event is on an external link | ||
* - The click event is on a link with `target="_blank"` | ||
* - The function explicitly returns `false` | ||
* | ||
* The function receives an object with the properties of the clicked side-nav item: | ||
* - `path`: The path of the navigation item. | ||
* - `target`: The target of the navigation item. | ||
* - `current`: A boolean indicating whether the navigation item is currently selected. | ||
* - `expanded`: A boolean indicating whether the navigation item is expanded. | ||
* - `pathAliases`: An array of path aliases for the navigation item. | ||
* - `originalEvent`: The original DOM event that triggered the navigation. | ||
* | ||
* Also see the `location` property for updating the highlighted navigation item on route change. | ||
* | ||
* @type {function(Object): boolean | undefined} | ||
*/ | ||
onNavigate: { | ||
attribute: false, | ||
}, | ||
/** | ||
* A change to this property triggers an update of the highlighted item in the side navigation. While it typically | ||
* corresponds to the browser's URL, the specific value assigned to the property is irrelevant. The component has | ||
* its own internal logic for determining which item is highlighted. | ||
* | ||
* The main use case for this property is when the side navigation is used with a client-side router. In this case, | ||
* the component needs to be informed about route changes so it can update the highlighted item. | ||
* | ||
* @type {any} | ||
*/ | ||
location: { | ||
observer: '__locationChanged', | ||
}, | ||
}; | ||
@@ -118,2 +160,3 @@ } | ||
this._labelId = `side-nav-label-${generateUniqueId()}`; | ||
this.addEventListener('click', this.__onClick); | ||
} | ||
@@ -209,5 +252,62 @@ | ||
/** @private */ | ||
__locationChanged() { | ||
window.dispatchEvent(new CustomEvent('side-nav-location-changed')); | ||
} | ||
/** @private */ | ||
__toggleCollapsed() { | ||
this.collapsed = !this.collapsed; | ||
} | ||
/** @private */ | ||
__onClick(e) { | ||
if (!this.onNavigate) { | ||
return; | ||
} | ||
const hasModifier = e.metaKey || e.shiftKey; | ||
if (hasModifier) { | ||
// Allow default action for clicks with modifiers | ||
return; | ||
} | ||
const composedPath = e.composedPath(); | ||
const item = composedPath.find((el) => el.localName && el.localName.includes('side-nav-item')); | ||
const anchor = composedPath.find((el) => el instanceof HTMLAnchorElement); | ||
if (!item || !item.shadowRoot.contains(anchor)) { | ||
// Not a click on a side-nav-item anchor | ||
return; | ||
} | ||
const isRelative = anchor.href && anchor.href.startsWith(location.origin); | ||
if (!isRelative) { | ||
// Allow default action for external links | ||
return; | ||
} | ||
if (item.target === '_blank') { | ||
// Allow default action for links with target="_blank" | ||
return; | ||
} | ||
if (item.routerIgnore) { | ||
// Allow default action when client-side routing is ignored | ||
return; | ||
} | ||
// Call the onNavigate callback | ||
const result = this.onNavigate({ | ||
path: item.path, | ||
target: item.target, | ||
current: item.current, | ||
expanded: item.expanded, | ||
pathAliases: item.pathAliases, | ||
originalEvent: e, | ||
}); | ||
if (result !== false) { | ||
// Cancel the default action if the callback didn't return false | ||
e.preventDefault(); | ||
} | ||
} | ||
} | ||
@@ -214,0 +314,0 @@ |
{ | ||
"$schema": "https://json.schemastore.org/web-types", | ||
"name": "@vaadin/side-nav", | ||
"version": "24.4.0-alpha2", | ||
"version": "24.4.0-alpha20", | ||
"description-markup": "markdown", | ||
@@ -45,2 +45,22 @@ "contributions": { | ||
{ | ||
"name": "target", | ||
"description": "The target of the link. Works only when `path` is set.", | ||
"value": { | ||
"type": [ | ||
"string", | ||
"null", | ||
"undefined" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "router-ignore", | ||
"description": "Whether to exclude the item from client-side routing. When enabled,\nthis causes the item to behave like a regular anchor, causing a full\npage reload. This only works with supported routers, such as the one\nprovided in Vaadin apps, or when using the side nav `onNavigate` hook.", | ||
"value": { | ||
"type": [ | ||
"boolean" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "theme", | ||
@@ -107,2 +127,22 @@ "description": "The theme variants to apply to the component.", | ||
} | ||
}, | ||
{ | ||
"name": "target", | ||
"description": "The target of the link. Works only when `path` is set.", | ||
"value": { | ||
"type": [ | ||
"string", | ||
"null", | ||
"undefined" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "routerIgnore", | ||
"description": "Whether to exclude the item from client-side routing. When enabled,\nthis causes the item to behave like a regular anchor, causing a full\npage reload. This only works with supported routers, such as the one\nprovided in Vaadin apps, or when using the side nav `onNavigate` hook.", | ||
"value": { | ||
"type": [ | ||
"boolean" | ||
] | ||
} | ||
} | ||
@@ -141,2 +181,21 @@ ], | ||
{ | ||
"name": "on-navigate", | ||
"description": "Callback function for router integration.\n\nWhen a side nav item link is clicked, this function is called and the default click action is cancelled.\nThis delegates the responsibility of navigation to the function's logic.\n\nThe click event action is not cancelled in the following cases:\n- The click event has a modifier (e.g. `metaKey`, `shiftKey`)\n- The click event is on an external link\n- The click event is on a link with `target=\"_blank\"`\n- The function explicitly returns `false`\n\nThe function receives an object with the properties of the clicked side-nav item:\n- `path`: The path of the navigation item.\n- `target`: The target of the navigation item.\n- `current`: A boolean indicating whether the navigation item is currently selected.\n- `expanded`: A boolean indicating whether the navigation item is expanded.\n- `pathAliases`: An array of path aliases for the navigation item.\n- `originalEvent`: The original DOM event that triggered the navigation.\n\nAlso see the `location` property for updating the highlighted navigation item on route change.", | ||
"value": { | ||
"type": [ | ||
"function Object: boolean", | ||
"undefined" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "location", | ||
"description": "A change to this property triggers an update of the highlighted item in the side navigation. While it typically\ncorresponds to the browser's URL, the specific value assigned to the property is irrelevant. The component has\nits own internal logic for determining which item is highlighted.\n\nThe main use case for this property is when the side navigation is used with a client-side router. In this case,\nthe component needs to be informed about route changes so it can update the highlighted item.", | ||
"value": { | ||
"type": [ | ||
"any" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "theme", | ||
@@ -181,2 +240,21 @@ "description": "The theme variants to apply to the component.", | ||
} | ||
}, | ||
{ | ||
"name": "onNavigate", | ||
"description": "Callback function for router integration.\n\nWhen a side nav item link is clicked, this function is called and the default click action is cancelled.\nThis delegates the responsibility of navigation to the function's logic.\n\nThe click event action is not cancelled in the following cases:\n- The click event has a modifier (e.g. `metaKey`, `shiftKey`)\n- The click event is on an external link\n- The click event is on a link with `target=\"_blank\"`\n- The function explicitly returns `false`\n\nThe function receives an object with the properties of the clicked side-nav item:\n- `path`: The path of the navigation item.\n- `target`: The target of the navigation item.\n- `current`: A boolean indicating whether the navigation item is currently selected.\n- `expanded`: A boolean indicating whether the navigation item is expanded.\n- `pathAliases`: An array of path aliases for the navigation item.\n- `originalEvent`: The original DOM event that triggered the navigation.\n\nAlso see the `location` property for updating the highlighted navigation item on route change.", | ||
"value": { | ||
"type": [ | ||
"function Object: boolean", | ||
"undefined" | ||
] | ||
} | ||
}, | ||
{ | ||
"name": "location", | ||
"description": "A change to this property triggers an update of the highlighted item in the side navigation. While it typically\ncorresponds to the browser's URL, the specific value assigned to the property is irrelevant. The component has\nits own internal logic for determining which item is highlighted.\n\nThe main use case for this property is when the side navigation is used with a client-side router. In this case,\nthe component needs to be informed about route changes so it can update the highlighted item.", | ||
"value": { | ||
"type": [ | ||
"any" | ||
] | ||
} | ||
} | ||
@@ -183,0 +261,0 @@ ], |
{ | ||
"$schema": "https://json.schemastore.org/web-types", | ||
"name": "@vaadin/side-nav", | ||
"version": "24.4.0-alpha2", | ||
"version": "24.4.0-alpha20", | ||
"description-markup": "markdown", | ||
@@ -37,2 +37,9 @@ "framework": "lit", | ||
{ | ||
"name": "?routerIgnore", | ||
"description": "Whether to exclude the item from client-side routing. When enabled,\nthis causes the item to behave like a regular anchor, causing a full\npage reload. This only works with supported routers, such as the one\nprovided in Vaadin apps, or when using the side nav `onNavigate` hook.", | ||
"value": { | ||
"kind": "expression" | ||
} | ||
}, | ||
{ | ||
"name": ".i18n", | ||
@@ -59,2 +66,9 @@ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```", | ||
{ | ||
"name": ".target", | ||
"description": "The target of the link. Works only when `path` is set.", | ||
"value": { | ||
"kind": "expression" | ||
} | ||
}, | ||
{ | ||
"name": "@expanded-changed", | ||
@@ -88,2 +102,9 @@ "description": "Fired when the `expanded` property changes.", | ||
{ | ||
"name": "?onNavigate", | ||
"description": "Callback function for router integration.\n\nWhen a side nav item link is clicked, this function is called and the default click action is cancelled.\nThis delegates the responsibility of navigation to the function's logic.\n\nThe click event action is not cancelled in the following cases:\n- The click event has a modifier (e.g. `metaKey`, `shiftKey`)\n- The click event is on an external link\n- The click event is on a link with `target=\"_blank\"`\n- The function explicitly returns `false`\n\nThe function receives an object with the properties of the clicked side-nav item:\n- `path`: The path of the navigation item.\n- `target`: The target of the navigation item.\n- `current`: A boolean indicating whether the navigation item is currently selected.\n- `expanded`: A boolean indicating whether the navigation item is expanded.\n- `pathAliases`: An array of path aliases for the navigation item.\n- `originalEvent`: The original DOM event that triggered the navigation.\n\nAlso see the `location` property for updating the highlighted navigation item on route change.", | ||
"value": { | ||
"kind": "expression" | ||
} | ||
}, | ||
{ | ||
"name": ".i18n", | ||
@@ -96,2 +117,9 @@ "description": "The object used to localize this component.\n\nTo change the default localization, replace the entire\n`i18n` object with a custom one.\n\nThe object has the following structure and default values:\n```\n{\n toggle: 'Toggle child items'\n}\n```", | ||
{ | ||
"name": ".location", | ||
"description": "A change to this property triggers an update of the highlighted item in the side navigation. While it typically\ncorresponds to the browser's URL, the specific value assigned to the property is irrelevant. The component has\nits own internal logic for determining which item is highlighted.\n\nThe main use case for this property is when the side navigation is used with a client-side router. In this case,\nthe component needs to be informed about route changes so it can update the highlighted item.", | ||
"value": { | ||
"kind": "expression" | ||
} | ||
}, | ||
{ | ||
"name": "@collapsed-changed", | ||
@@ -98,0 +126,0 @@ "description": "Fired when the `collapsed` property changes.", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
86054
32
1948
81
+ Added@vaadin/a11y-base@24.4.0-alpha20(transitive)
+ Added@vaadin/component-base@24.4.0-alpha20(transitive)
+ Added@vaadin/icon@24.4.0-alpha20(transitive)
+ Added@vaadin/vaadin-lumo-styles@24.4.0-alpha20(transitive)
+ Added@vaadin/vaadin-material-styles@24.4.0-alpha20(transitive)
+ Added@vaadin/vaadin-themable-mixin@24.4.0-alpha20(transitive)
- Removed@vaadin/a11y-base@24.4.0-alpha2(transitive)
- Removed@vaadin/component-base@24.4.0-alpha2(transitive)
- Removed@vaadin/icon@24.4.0-alpha2(transitive)
- Removed@vaadin/vaadin-lumo-styles@24.4.0-alpha2(transitive)
- Removed@vaadin/vaadin-material-styles@24.4.0-alpha2(transitive)
- Removed@vaadin/vaadin-themable-mixin@24.4.0-alpha2(transitive)