@m3e/nav-menu 1.0.0-rc.1 → 1.0.0-rc.3
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 -2
- package/dist/custom-elements.json +2629 -8
- package/dist/html-custom-data.json +1 -1
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +37 -37
- package/dist/index.min.js.map +1 -1
- package/dist/src/NavMenuElement.d.ts +0 -1
- package/dist/src/NavMenuElement.d.ts.map +1 -1
- package/dist/src/NavMenuItemElement.d.ts +3 -1
- package/dist/src/NavMenuItemElement.d.ts.map +1 -1
- package/package.json +4 -4
- package/cem.config.mjs +0 -16
- package/demo/index.html +0 -64
- package/eslint.config.mjs +0 -13
- package/rollup.config.js +0 -32
- package/src/NavMenuElement.ts +0 -325
- package/src/NavMenuItemElement.ts +0 -560
- package/src/index.ts +0 -2
- package/tsconfig.json +0 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavMenuItemElement.d.ts","sourceRoot":"","sources":["../../src/NavMenuItemElement.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,cAAc,EAAQ,UAAU,EAAE,cAAc,EAAa,MAAM,KAAK,CAAC;AAIvF,OAAO,EAML,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EAGrB,MAAM,WAAW,CAAC;;AAMnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,qBACa,qBAAsB,SAAQ,0BAI1C;;IACC,iCAAiC;IACjC,OAAgB,MAAM,EAAE,cAAc,CAkLpC;IAEF,gBAAgB,CAAwB,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IACnF,gBAAgB,CAAuB,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChF,gBAAgB,CAAmB,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACtE,eAAe,CAAiB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAc;IAErE,eAAe,CAAU,OAAO,CAAC,cAAc,CAAS;IAOxD;;;OAGG;IACyC,IAAI,UAAS;IAEzD,qDAAqD;IACrD,IAAI,IAAI,IAAI,iBAAiB,GAAG,IAAI,CAEnC;IAED,mCAAmC;IACnC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,2FAA2F;IAC3F,IAAI,IAAI,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAE/C;IAED,wCAAwC;IACxC,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,0BAA0B;IAC1B,IAAI,UAAU,IAAI,qBAAqB,GAAG,IAAI,CAE7C;IAED,yDAAyD;IACzD,IAAI,UAAU,IAAI,SAAS,qBAAqB,EAAE,CAEjD;IAED,uCAAuC;IACvC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;OAGG;IACH,MAAM,CAAC,WAAW,GAAE,OAAe,GAAG,IAAI;IAS1C;;;OAGG;IACH,QAAQ,CAAC,WAAW,GAAE,OAAe,GAAG,IAAI;IAS5C,8CAA8C;IAC9C,MAAM,IAAI,IAAI;IAMd,kBAAkB;IACT,iBAAiB,IAAI,IAAI;IAiBlC,kBAAkB;IACT,oBAAoB,IAAI,IAAI;IAKrC,kBAAkB;cACC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAgBxE,kBAAkB;cACC,YAAY,CAAC,kBAAkB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAS/E,kBAAkB;cACC,MAAM,IAAI,OAAO;
|
|
1
|
+
{"version":3,"file":"NavMenuItemElement.d.ts","sourceRoot":"","sources":["../../src/NavMenuItemElement.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,cAAc,EAAQ,UAAU,EAAE,cAAc,EAAa,MAAM,KAAK,CAAC;AAIvF,OAAO,EAML,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EAGrB,MAAM,WAAW,CAAC;;AAMnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,qBACa,qBAAsB,SAAQ,0BAI1C;;IACC,iCAAiC;IACjC,OAAgB,MAAM,EAAE,cAAc,CAkLpC;IAEF,gBAAgB,CAAwB,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IACnF,gBAAgB,CAAuB,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChF,gBAAgB,CAAmB,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACtE,eAAe,CAAiB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAc;IAErE,eAAe,CAAU,OAAO,CAAC,cAAc,CAAS;IAOxD;;;OAGG;IACyC,IAAI,UAAS;IAEzD,qDAAqD;IACrD,IAAI,IAAI,IAAI,iBAAiB,GAAG,IAAI,CAEnC;IAED,wEAAwE;IACxE,IAAI,KAAK,IAAI,WAAW,GAAG,IAAI,CAE9B;IAED,mCAAmC;IACnC,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,2FAA2F;IAC3F,IAAI,IAAI,IAAI,aAAa,CAAC,qBAAqB,CAAC,CAE/C;IAED,wCAAwC;IACxC,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,0BAA0B;IAC1B,IAAI,UAAU,IAAI,qBAAqB,GAAG,IAAI,CAE7C;IAED,yDAAyD;IACzD,IAAI,UAAU,IAAI,SAAS,qBAAqB,EAAE,CAEjD;IAED,uCAAuC;IACvC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;OAGG;IACH,MAAM,CAAC,WAAW,GAAE,OAAe,GAAG,IAAI;IAS1C;;;OAGG;IACH,QAAQ,CAAC,WAAW,GAAE,OAAe,GAAG,IAAI;IAS5C,8CAA8C;IAC9C,MAAM,IAAI,IAAI;IAMd,kBAAkB;IACT,iBAAiB,IAAI,IAAI;IAiBlC,kBAAkB;IACT,oBAAoB,IAAI,IAAI;IAKrC,kBAAkB;cACC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAgBxE,kBAAkB;cACC,YAAY,CAAC,kBAAkB,EAAE,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI;IAS/E,kBAAkB;cACC,MAAM,IAAI,OAAO;CAoGrC;AAED,UAAU,6BAA8B,SAAQ,mBAAmB;IACjE,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,CAAC,SAAS,MAAM,6BAA6B,EAC5D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAC,CAAC,KAAK,IAAI,EACrF,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IAER,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IAER,mBAAmB,CAAC,CAAC,SAAS,MAAM,6BAA6B,EAC/D,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAC,CAAC,KAAK,IAAI,EACrF,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IAER,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,qBAAqB,CAAC;KAC5C;CACF"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m3e/nav-menu",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.3",
|
|
4
4
|
"description": "Navigation Menu for M3E",
|
|
5
5
|
"author": "matraic <matraic@yahoo.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"homepage": "https://matraic.github.io/m3e/",
|
|
7
|
+
"homepage": "https://matraic.github.io/m3e/#/components/nav-menu.html",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/matraic/m3e.git"
|
|
10
|
+
"url": "git+https://github.com/matraic/m3e.git"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"material design",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"clean": "rimraf dist"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@m3e/core": "1.0.0-rc.
|
|
30
|
+
"@m3e/core": "1.0.0-rc.3",
|
|
31
31
|
"lit": "^3.3.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
package/cem.config.mjs
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { customElementVsCodePlugin } from "custom-element-vs-code-integration";
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
globs: ["src/**/*.ts"],
|
|
5
|
-
exclude: ["src/**/*.spec.ts"],
|
|
6
|
-
packagejson: true,
|
|
7
|
-
outdir: "dist",
|
|
8
|
-
litelement: true,
|
|
9
|
-
plugins: [
|
|
10
|
-
customElementVsCodePlugin({
|
|
11
|
-
outdir: "dist",
|
|
12
|
-
htmlFileName: "html-custom-data.json",
|
|
13
|
-
cssFileName: "css-custom-data.json",
|
|
14
|
-
}),
|
|
15
|
-
],
|
|
16
|
-
};
|
package/demo/index.html
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en" style="overflow-y: auto">
|
|
3
|
-
<head>
|
|
4
|
-
<title>Navigation Menu for M3E</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
<meta name="description" content="Navigation Menu for M3E" />
|
|
8
|
-
<base href="./" />
|
|
9
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
10
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
11
|
-
<link
|
|
12
|
-
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
|
|
13
|
-
rel="stylesheet"
|
|
14
|
-
/>
|
|
15
|
-
<link
|
|
16
|
-
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0"
|
|
17
|
-
rel="stylesheet"
|
|
18
|
-
/>
|
|
19
|
-
<script type="importmap">
|
|
20
|
-
{
|
|
21
|
-
"imports": {
|
|
22
|
-
"lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
|
|
23
|
-
"@m3e/core": "../../core/dist/index.min.js",
|
|
24
|
-
"@m3e/core/a11y": "../../core/dist/a11y.min.js"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
</script>
|
|
28
|
-
<script type="module" src="../../icon/dist/index.min.js"></script>
|
|
29
|
-
<script type="module" src="../../theme/dist/index.min.js"></script>
|
|
30
|
-
<script type="module" src="../dist/index.min.js"></script>
|
|
31
|
-
<style>
|
|
32
|
-
body {
|
|
33
|
-
font-family: "Roboto";
|
|
34
|
-
}
|
|
35
|
-
*:not(:defined) {
|
|
36
|
-
display: none;
|
|
37
|
-
}
|
|
38
|
-
</style>
|
|
39
|
-
</head>
|
|
40
|
-
<body>
|
|
41
|
-
<m3e-theme strong-focus>
|
|
42
|
-
<m3e-nav-menu style="max-width: 300px">
|
|
43
|
-
<m3e-nav-menu-item open>
|
|
44
|
-
<m3e-icon slot="icon" name="rocket_launch"></m3e-icon>
|
|
45
|
-
<span slot="label">Getting Started</span>
|
|
46
|
-
<m3e-nav-menu-item disabled>
|
|
47
|
-
<m3e-icon slot="icon" name="widgets"></m3e-icon>
|
|
48
|
-
<span slot="label">Overview</span>
|
|
49
|
-
</m3e-nav-menu-item>
|
|
50
|
-
<m3e-nav-menu-item>
|
|
51
|
-
<m3e-icon slot="icon" name="package_2"></m3e-icon>
|
|
52
|
-
<span slot="label">Installation</span>
|
|
53
|
-
</m3e-nav-menu-item>
|
|
54
|
-
</m3e-nav-menu-item>
|
|
55
|
-
<m3e-nav-menu-item>
|
|
56
|
-
<span slot="label">Actions</span>
|
|
57
|
-
<m3e-nav-menu-item><span slot="label">Button</span></m3e-nav-menu-item>
|
|
58
|
-
<m3e-nav-menu-item><span slot="label">Icon</span></m3e-nav-menu-item>
|
|
59
|
-
<m3e-nav-menu-item><span slot="label">Icon Button</span></m3e-nav-menu-item>
|
|
60
|
-
</m3e-nav-menu-item>
|
|
61
|
-
</m3e-nav-menu>
|
|
62
|
-
</m3e-theme>
|
|
63
|
-
</body>
|
|
64
|
-
</html>
|
package/eslint.config.mjs
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import eslint from "@eslint/js";
|
|
2
|
-
import tseslint from "typescript-eslint";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { dirname } from "path";
|
|
5
|
-
|
|
6
|
-
export default tseslint.config(eslint.configs.recommended, tseslint.configs.recommended, {
|
|
7
|
-
languageOptions: {
|
|
8
|
-
parserOptions: {
|
|
9
|
-
project: true,
|
|
10
|
-
tsconfigRootDir: dirname(fileURLToPath(import.meta.url)),
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
});
|
package/rollup.config.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import resolve from "@rollup/plugin-node-resolve";
|
|
2
|
-
import terser from "@rollup/plugin-terser";
|
|
3
|
-
import typescript from "@rollup/plugin-typescript";
|
|
4
|
-
|
|
5
|
-
const banner = `/**
|
|
6
|
-
* @license MIT
|
|
7
|
-
* Copyright (c) 2025 matraic
|
|
8
|
-
* See LICENSE file in the project root for full license text.
|
|
9
|
-
*/`;
|
|
10
|
-
|
|
11
|
-
export default [
|
|
12
|
-
{
|
|
13
|
-
input: "src/index.ts",
|
|
14
|
-
output: [
|
|
15
|
-
{
|
|
16
|
-
file: "dist/index.js",
|
|
17
|
-
format: "esm",
|
|
18
|
-
sourcemap: true,
|
|
19
|
-
banner: banner,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
file: "dist/index.min.js",
|
|
23
|
-
format: "esm",
|
|
24
|
-
sourcemap: true,
|
|
25
|
-
banner: banner,
|
|
26
|
-
plugins: [terser({ mangle: true })],
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
external: ["@m3e/core", "@m3e/core/a11y", "lit"],
|
|
30
|
-
plugins: [resolve(), typescript()],
|
|
31
|
-
},
|
|
32
|
-
];
|
package/src/NavMenuElement.ts
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
import { css, CSSResultGroup, html, LitElement } from "lit";
|
|
2
|
-
import { customElement } from "lit/decorators.js";
|
|
3
|
-
|
|
4
|
-
import { DesignToken, FocusController, PressedController, Role, scrollIntoViewIfNeeded } from "@m3e/core";
|
|
5
|
-
import { SelectionManager, selectionManager } from "@m3e/core/a11y";
|
|
6
|
-
|
|
7
|
-
import { M3eNavMenuItemElement } from "./NavMenuItemElement";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @summary
|
|
11
|
-
* Presents a hierarchical menu.
|
|
12
|
-
*
|
|
13
|
-
* @description
|
|
14
|
-
* The `m3e-nav-menu` component provides a hierarchical, accessible navigation menu supporting
|
|
15
|
-
* nested expandable items, keyboard navigation, and focus management. It is highly customizable
|
|
16
|
-
* via slots and CSS custom properties, and is designed for use in sidebars, navigation drawers,
|
|
17
|
-
* and complex menu structures.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* The following example illustrates a multilevel navigation menu.
|
|
21
|
-
* ```html
|
|
22
|
-
* <m3e-nav-menu>
|
|
23
|
-
* <m3e-nav-menu-item open>
|
|
24
|
-
* <m3e-icon slot="icon" name="rocket_launch"></m3e-icon>
|
|
25
|
-
* <span slot="label">Getting Started</span>
|
|
26
|
-
* <m3e-nav-menu-item>
|
|
27
|
-
* <m3e-icon slot="icon" name="widgets"></m3e-icon>
|
|
28
|
-
* <span slot="label">Overview</span>
|
|
29
|
-
* </m3e-nav-menu-item>
|
|
30
|
-
* <m3e-nav-menu-item>
|
|
31
|
-
* <m3e-icon slot="icon" name="package_2"></m3e-icon>
|
|
32
|
-
* <span slot="label">Installation</span>
|
|
33
|
-
* </m3e-nav-menu-item>
|
|
34
|
-
* </m3e-nav-menu-item>
|
|
35
|
-
* <m3e-nav-menu-item>
|
|
36
|
-
* <span slot="label">Actions</span>
|
|
37
|
-
* <m3e-nav-menu-item><span slot="label">Button</span></m3e-nav-menu-item>
|
|
38
|
-
* <m3e-nav-menu-item><span slot="label">Icon</span></m3e-nav-menu-item>
|
|
39
|
-
* <m3e-nav-menu-item><span slot="label">Icon Button</span></m3e-nav-menu-item>
|
|
40
|
-
* </m3e-nav-menu-item>
|
|
41
|
-
* </m3e-nav-menu>
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @tag m3e-nav-menu
|
|
45
|
-
*
|
|
46
|
-
* @slot - Renders the items of the menu.
|
|
47
|
-
*
|
|
48
|
-
* @cssprop --m3e-nav-menu-padding-top - Top padding for the menu.
|
|
49
|
-
* @cssprop --m3e-nav-menu-padding-bottom - Bottom padding for the menu.
|
|
50
|
-
* @cssprop --m3e-nav-menu-padding-left - Left padding for the menu.
|
|
51
|
-
* @cssprop --m3e-nav-menu-padding-right - Right padding for the menu.
|
|
52
|
-
* @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements in the menu.
|
|
53
|
-
* @cssprop --m3e-nav-menu-scrollbar-width - Width of the menu scrollbar.
|
|
54
|
-
* @cssprop --m3e-nav-menu-scrollbar-color - Color of the menu scrollbar.
|
|
55
|
-
*/
|
|
56
|
-
@customElement("m3e-nav-menu")
|
|
57
|
-
export class M3eNavMenuElement extends Role(LitElement, "tree") {
|
|
58
|
-
/** The styles of the element. */
|
|
59
|
-
static override styles: CSSResultGroup = css`
|
|
60
|
-
:host {
|
|
61
|
-
display: flex;
|
|
62
|
-
flex-direction: column;
|
|
63
|
-
outline: none;
|
|
64
|
-
overflow-y: auto;
|
|
65
|
-
overflow-x: hidden;
|
|
66
|
-
position: relative;
|
|
67
|
-
min-height: 0;
|
|
68
|
-
padding-block-start: var(--m3e-nav-menu-padding-top, 0.5rem);
|
|
69
|
-
padding-block-end: var(--m3e-nav-menu-padding-bottom, 0.5rem);
|
|
70
|
-
padding-inline-start: var(--m3e-nav-menu-padding-left, 0.75rem);
|
|
71
|
-
padding-inline-end: var(--m3e-nav-menu-padding-right, 0.75rem);
|
|
72
|
-
scrollbar-width: ${DesignToken.scrollbar.width};
|
|
73
|
-
scrollbar-color: ${DesignToken.scrollbar.color};
|
|
74
|
-
}
|
|
75
|
-
::slotted(m3e-divider) {
|
|
76
|
-
margin-block: var(--m3e-nav-menu-divider-margin, 0.25rem);
|
|
77
|
-
}
|
|
78
|
-
`;
|
|
79
|
-
|
|
80
|
-
/** @private */ private static __nextId = 0;
|
|
81
|
-
/** @private */ #ignoreFocusVisible = false;
|
|
82
|
-
/** @private */ #ignoreFocus = false;
|
|
83
|
-
|
|
84
|
-
/** @private */
|
|
85
|
-
readonly [selectionManager] = new SelectionManager<M3eNavMenuItemElement>()
|
|
86
|
-
.withVerticalOrientation()
|
|
87
|
-
.withHomeAndEnd()
|
|
88
|
-
.withTypeahead()
|
|
89
|
-
.withSkipPredicate((x) => x.disabled || !x.visible)
|
|
90
|
-
.disableRovingTabIndex()
|
|
91
|
-
.onActiveItemChange(() => {
|
|
92
|
-
if (this[selectionManager].activeItem) {
|
|
93
|
-
this.#activateItem(this[selectionManager].activeItem);
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
.onSelectedItemsChange(() => {
|
|
97
|
-
const selected = this.selected;
|
|
98
|
-
for (const item of this.items) {
|
|
99
|
-
if (item !== selected) {
|
|
100
|
-
this.#updateItemFocusVisible(item, false, false);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
/** @private */ readonly #keyDownHandler = (e: KeyboardEvent) => this.#handleKeyDown(e);
|
|
106
|
-
/** @private */ readonly #keyUpHandler = (e: KeyboardEvent) => this.#handleKeyUp(e);
|
|
107
|
-
/** @private */ readonly #pointerDownHandler = (e: Event) => this.#handlePointerDown(e);
|
|
108
|
-
|
|
109
|
-
constructor() {
|
|
110
|
-
super();
|
|
111
|
-
|
|
112
|
-
new PressedController(this, { callback: (pressed) => (this.#ignoreFocus = pressed) });
|
|
113
|
-
new FocusController(this, {
|
|
114
|
-
callback: () => {
|
|
115
|
-
if (!this.#ignoreFocus) {
|
|
116
|
-
this.#updateFocusVisible();
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/** The selected item of the menu. */
|
|
123
|
-
get selected(): M3eNavMenuItemElement | null {
|
|
124
|
-
return this[selectionManager].selectedItems[0] ?? null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** All the items of the menu. */
|
|
128
|
-
get items(): readonly M3eNavMenuItemElement[] {
|
|
129
|
-
return this[selectionManager].items;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Expands the specified items, or all items if no items are provided.
|
|
134
|
-
* @param {M3eNavMenuItemElement | undefined} items The items to expand.
|
|
135
|
-
*/
|
|
136
|
-
expand(items?: M3eNavMenuItemElement[]): void {
|
|
137
|
-
(items ?? this[selectionManager].items).forEach((x) => x.expand());
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Collapses the specified items, or all items if no items are provided.
|
|
142
|
-
* @param {M3eNavMenuItemElement | undefined} items The items to collapse.
|
|
143
|
-
*/
|
|
144
|
-
collapse(items?: M3eNavMenuItemElement[]): void {
|
|
145
|
-
(items ?? this[selectionManager].items).forEach((x) => x.collapse());
|
|
146
|
-
|
|
147
|
-
const activeItem = this[selectionManager].activeItem;
|
|
148
|
-
if (activeItem && !activeItem.visible) {
|
|
149
|
-
for (let parent = activeItem.parentItem; parent; parent = parent.parentItem) {
|
|
150
|
-
if (parent.visible) {
|
|
151
|
-
this[selectionManager].setActiveItem(parent);
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/** @inheritdoc */
|
|
159
|
-
override connectedCallback(): void {
|
|
160
|
-
super.connectedCallback();
|
|
161
|
-
|
|
162
|
-
this.setAttribute("tabindex", "0");
|
|
163
|
-
|
|
164
|
-
this.addEventListener("keydown", this.#keyDownHandler);
|
|
165
|
-
this.addEventListener("keyup", this.#keyUpHandler);
|
|
166
|
-
this.addEventListener("pointerdown", this.#pointerDownHandler);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/** @inheritdoc */
|
|
170
|
-
override disconnectedCallback(): void {
|
|
171
|
-
super.disconnectedCallback();
|
|
172
|
-
|
|
173
|
-
this.removeEventListener("keydown", this.#keyDownHandler);
|
|
174
|
-
this.removeEventListener("keyup", this.#keyUpHandler);
|
|
175
|
-
this.removeEventListener("pointerdown", this.#pointerDownHandler);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/** @inheritdoc */
|
|
179
|
-
protected override render(): unknown {
|
|
180
|
-
return html`<slot @slotchange="${this.#handleSlotChange}"></slot>`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** @private */
|
|
184
|
-
#handleSlotChange(): void {
|
|
185
|
-
const { added } = this[selectionManager].setItems([...this.querySelectorAll("m3e-nav-menu-item")]);
|
|
186
|
-
for (const item of added) {
|
|
187
|
-
item.id = item.id || `m3e-nav-menu-item-${M3eNavMenuElement.__nextId++}`;
|
|
188
|
-
}
|
|
189
|
-
if (this[selectionManager].activeItem) {
|
|
190
|
-
this.setAttribute("aria-activedescendant", this[selectionManager].activeItem.id);
|
|
191
|
-
this.#updateFocusVisible();
|
|
192
|
-
} else {
|
|
193
|
-
this.removeAttribute("aria-activedescendant");
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** @private */
|
|
198
|
-
#handleKeyDown(e: KeyboardEvent): void {
|
|
199
|
-
this.#ignoreFocusVisible = false;
|
|
200
|
-
this.#updateFocusVisible();
|
|
201
|
-
|
|
202
|
-
const item = this[selectionManager].activeItem;
|
|
203
|
-
if (e.defaultPrevented || !item || item.disabled) return;
|
|
204
|
-
|
|
205
|
-
switch (e.key) {
|
|
206
|
-
case "Enter":
|
|
207
|
-
case " ":
|
|
208
|
-
e.preventDefault();
|
|
209
|
-
|
|
210
|
-
if (item.ripple && !item.ripple.visible) {
|
|
211
|
-
item.ripple.show(0, 0, true);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if (item.hasChildItems) {
|
|
215
|
-
item.toggle();
|
|
216
|
-
} else if (!item.selected) {
|
|
217
|
-
this[selectionManager].select(item);
|
|
218
|
-
item.link?.click();
|
|
219
|
-
}
|
|
220
|
-
break;
|
|
221
|
-
|
|
222
|
-
case "*":
|
|
223
|
-
e.preventDefault();
|
|
224
|
-
item.expand(true);
|
|
225
|
-
break;
|
|
226
|
-
|
|
227
|
-
case "Left":
|
|
228
|
-
case "ArrowLeft":
|
|
229
|
-
e.preventDefault();
|
|
230
|
-
if (item.hasChildItems && item.open) {
|
|
231
|
-
item.collapse();
|
|
232
|
-
} else {
|
|
233
|
-
const parent = item.parentItem;
|
|
234
|
-
if (parent) {
|
|
235
|
-
parent.collapse();
|
|
236
|
-
this[selectionManager].setActiveItem(parent);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
break;
|
|
240
|
-
|
|
241
|
-
case "Right":
|
|
242
|
-
case "ArrowRight":
|
|
243
|
-
if (item.hasChildItems) {
|
|
244
|
-
if (!item.open) {
|
|
245
|
-
e.preventDefault();
|
|
246
|
-
item.expand();
|
|
247
|
-
} else {
|
|
248
|
-
try {
|
|
249
|
-
this[selectionManager].vertical = false;
|
|
250
|
-
this[selectionManager].onKeyDown(e);
|
|
251
|
-
} finally {
|
|
252
|
-
this[selectionManager].vertical = true;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
} else {
|
|
256
|
-
e.preventDefault();
|
|
257
|
-
}
|
|
258
|
-
break;
|
|
259
|
-
|
|
260
|
-
default:
|
|
261
|
-
this[selectionManager].onKeyDown(e);
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/** @private */
|
|
267
|
-
#handleKeyUp(e: KeyboardEvent): void {
|
|
268
|
-
const item = this[selectionManager].activeItem;
|
|
269
|
-
if (e.defaultPrevented || !item || item.disabled) return;
|
|
270
|
-
|
|
271
|
-
switch (e.key) {
|
|
272
|
-
case "Enter":
|
|
273
|
-
case " ":
|
|
274
|
-
item.ripple?.hide();
|
|
275
|
-
break;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/** @private */
|
|
280
|
-
#handlePointerDown(e: Event): void {
|
|
281
|
-
if (!e.defaultPrevented && !this.#ignoreFocusVisible) {
|
|
282
|
-
this.#ignoreFocusVisible = true;
|
|
283
|
-
if (this[selectionManager].activeItem) {
|
|
284
|
-
this.#updateItemFocusVisible(this[selectionManager].activeItem, true, false);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/** @private */
|
|
290
|
-
#activateItem(item: M3eNavMenuItemElement): void {
|
|
291
|
-
this.setAttribute("aria-activedescendant", item.id);
|
|
292
|
-
scrollIntoViewIfNeeded(item, this, "instant");
|
|
293
|
-
this.#updateFocusVisible();
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/** @private */
|
|
297
|
-
#updateFocusVisible(): void {
|
|
298
|
-
const focused = this.matches(":focus") || this.matches(":focus-within");
|
|
299
|
-
const focusVisible = !this.#ignoreFocusVisible && this.matches(":focus-visible");
|
|
300
|
-
this[selectionManager].items.forEach((x) => {
|
|
301
|
-
const active = x === this[selectionManager].activeItem;
|
|
302
|
-
this.#updateItemFocusVisible(x, active && focused, active && focusVisible);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/** @private */
|
|
307
|
-
#updateItemFocusVisible(item: M3eNavMenuItemElement, focused: boolean, focusVisible: boolean): void {
|
|
308
|
-
if (focused) {
|
|
309
|
-
item.stateLayer?.show("focused");
|
|
310
|
-
} else {
|
|
311
|
-
item.stateLayer?.hide("focused");
|
|
312
|
-
}
|
|
313
|
-
if (focusVisible) {
|
|
314
|
-
item.focusRing?.show();
|
|
315
|
-
} else {
|
|
316
|
-
item.focusRing?.hide();
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
declare global {
|
|
322
|
-
interface HTMLElementTagNameMap {
|
|
323
|
-
"m3e-nav-menu": M3eNavMenuElement;
|
|
324
|
-
}
|
|
325
|
-
}
|