@m3e/menu 1.0.0-rc.1 → 1.0.0-rc.2

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.
Files changed (40) hide show
  1. package/README.md +1 -2
  2. package/dist/custom-elements.json +3270 -34
  3. package/dist/html-custom-data.json +12 -6
  4. package/dist/index.js +8 -8
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.min.js +7 -7
  7. package/dist/index.min.js.map +1 -1
  8. package/package.json +4 -4
  9. package/cem.config.mjs +0 -16
  10. package/demo/index.html +0 -112
  11. package/dist/src/MenuElement.d.ts +0 -143
  12. package/dist/src/MenuElement.d.ts.map +0 -1
  13. package/dist/src/MenuItemCheckboxElement.d.ts +0 -76
  14. package/dist/src/MenuItemCheckboxElement.d.ts.map +0 -1
  15. package/dist/src/MenuItemElement.d.ts +0 -113
  16. package/dist/src/MenuItemElement.d.ts.map +0 -1
  17. package/dist/src/MenuItemElementBase.d.ts +0 -21
  18. package/dist/src/MenuItemElementBase.d.ts.map +0 -1
  19. package/dist/src/MenuItemGroupElement.d.ts +0 -28
  20. package/dist/src/MenuItemGroupElement.d.ts.map +0 -1
  21. package/dist/src/MenuItemRadioElement.d.ts +0 -77
  22. package/dist/src/MenuItemRadioElement.d.ts.map +0 -1
  23. package/dist/src/MenuPosition.d.ts +0 -5
  24. package/dist/src/MenuPosition.d.ts.map +0 -1
  25. package/dist/src/MenuTriggerElement.d.ts +0 -86
  26. package/dist/src/MenuTriggerElement.d.ts.map +0 -1
  27. package/dist/src/index.d.ts +0 -8
  28. package/dist/src/index.d.ts.map +0 -1
  29. package/eslint.config.mjs +0 -13
  30. package/rollup.config.js +0 -32
  31. package/src/MenuElement.ts +0 -449
  32. package/src/MenuItemCheckboxElement.ts +0 -178
  33. package/src/MenuItemElement.ts +0 -210
  34. package/src/MenuItemElementBase.ts +0 -158
  35. package/src/MenuItemGroupElement.ts +0 -37
  36. package/src/MenuItemRadioElement.ts +0 -169
  37. package/src/MenuPosition.ts +0 -5
  38. package/src/MenuTriggerElement.ts +0 -154
  39. package/src/index.ts +0 -7
  40. package/tsconfig.json +0 -9
@@ -1,169 +0,0 @@
1
- import { CSSResultGroup, html, PropertyValues } from "lit";
2
- import { customElement } from "lit/decorators.js";
3
-
4
- import { Checked, hasAssignedNodes, Role } from "@m3e/core";
5
-
6
- import { M3eMenuItemCheckboxElement } from "./MenuItemCheckboxElement";
7
- import { M3eMenuItemElement } from "./MenuItemElement";
8
- import { MenuItemElementBase } from "./MenuItemElementBase";
9
-
10
- /**
11
- * @summary
12
- * An item of a menu which supports a mutually exclusive checkable state.
13
- *
14
- * @description
15
- * The `m3e-menu-item-radio` component represents a selectable menu item that participates in a mutually exclusive group.
16
- * It reflects a singular choice within a shared context—such as sort order, theme selection, or view mode—and updates
17
- * group state when selected. This component can be nested within an `m3e-menu-item-group`, allowing multiple exclusive
18
- * groups to coexist within a single menu.
19
- *
20
- * @example
21
- * The following example illustrates use of the `m3e-menu-item-radio` in a `m3e-menu` to allow a user to select a sort order.
22
- * The `m3e-menu-trigger` is used to trigger a `m3e-menu` specified by the `for` attribute when its parenting element is activated.
23
- * ```html
24
- * <m3e-button>
25
- * <m3e-menu-trigger for="menu">Sort order</m3e-menu-trigger>
26
- * </m3e-button>
27
- * <m3e-menu id="menu">
28
- * <m3e-menu-item-radio>Ascending</m3e-menu-item-radio>
29
- * <m3e-menu-item-radio>Descending</m3e-menu-item-radio>
30
- * </m3e-menu>
31
- * ```
32
- *
33
- * @tag m3e-menu-item-radio
34
- *
35
- * @slot - Renders the label of the item.
36
- * @slot icon - Renders an icon before the items's label.
37
- * @slot trailing-icon - Renders an icon after the item's label.
38
- *
39
- * @attr disabled - Whether the element is disabled.
40
- * @attr checked - Whether the element is checked.
41
- *
42
- * @cssprop --m3e-menu-item-container-height - Height of the menu item container.
43
- * @cssprop --m3e-menu-item-color - Text color for unselected, enabled menu items.
44
- * @cssprop --m3e-menu-item-container-hover-color - State layer hover color for unselected items.
45
- * @cssprop --m3e-menu-item-container-focus-color - State layer focus color for unselected items.
46
- * @cssprop --m3e-menu-item-ripple-color - Ripple color for unselected items.
47
- * @cssprop --m3e-menu-selected-color - Text color for selected or expanded items.
48
- * @cssprop --m3e-menu-selected-container-color - Background color for selected or expanded items.
49
- * @cssprop --m3e-menu-item-selected-container-hover-color - State layer hover color for selected items.
50
- * @cssprop --m3e-menu-item-selected-container-focus-color - State layer focus color for selected items.
51
- * @cssprop --m3e-menu-item-selected-ripple-color - Ripple color for selected items.
52
- * @cssprop --m3e-menu-item-disabled-color - Base color for disabled items.
53
- * @cssprop --m3e-menu-item-disabled-opacity - Opacity percentage for disabled item color mix.
54
- * @cssprop --m3e-menu-item-icon-label-space - Horizontal gap between icon and content.
55
- * @cssprop --m3e-menu-item-padding-start - Start padding for the item wrapper.
56
- * @cssprop --m3e-menu-item-padding-end - End padding for the item wrapper.
57
- * @cssprop --m3e-menu-item-label-text-font-size - Font size for menu item text.
58
- * @cssprop --m3e-menu-item-label-text-font-weight - Font weight for menu item text.
59
- * @cssprop --m3e-menu-item-label-text-line-height - Line height for menu item text.
60
- * @cssprop --m3e-menu-item-label-text-tracking - Letter spacing for menu item text.
61
- * @cssprop --m3e-menu-item-focus-ring-shape - Border radius for the focus ring.
62
- * @cssprop --m3e-menu-item-icon-size - Font size for leading and trailing icons.
63
- */
64
- @customElement("m3e-menu-item-radio")
65
- export class M3eMenuItemRadioElement extends Checked(Role(MenuItemElementBase, "menuitemradio")) {
66
- /** The styles of the element. */
67
- static override styles: CSSResultGroup = M3eMenuItemCheckboxElement.styles;
68
-
69
- /** @private */ readonly #clickHandler = (e: Event) => this.#handleClick(e);
70
- /** @private */ readonly #keyDownHandler = (e: KeyboardEvent) => this.#handleKeyDown(e);
71
- /** @private */ readonly #keyUpHandler = () => this.#handleKeyUp();
72
- /** @private */ readonly #mouseEnterHandler = () => this.#handleMouseEnter();
73
-
74
- /** @private */ #spacePressed = false;
75
-
76
- /** @inheritdoc */
77
- override connectedCallback(): void {
78
- super.connectedCallback();
79
-
80
- this.addEventListener("click", this.#clickHandler);
81
- this.addEventListener("keydown", this.#keyDownHandler);
82
- this.addEventListener("keyup", this.#keyUpHandler);
83
- this.addEventListener("mouseenter", this.#mouseEnterHandler);
84
- }
85
-
86
- /** @inheritdoc */
87
- override disconnectedCallback(): void {
88
- super.disconnectedCallback();
89
-
90
- this.removeEventListener("click", this.#clickHandler);
91
- this.removeEventListener("keydown", this.#keyDownHandler);
92
- this.removeEventListener("keyup", this.#keyUpHandler);
93
- this.removeEventListener("mouseenter", this.#mouseEnterHandler);
94
- }
95
-
96
- /** @inheritdoc */
97
- protected override update(changedProperties: PropertyValues<this>): void {
98
- super.update(changedProperties);
99
-
100
- if (changedProperties.has("checked") && this.checked) {
101
- (this.closest("[role='group']") ?? this.closest("m3e-menu"))
102
- ?.querySelectorAll("m3e-menu-item-radio")
103
- .forEach((x) => {
104
- if (x !== this && x.checked) {
105
- x.checked = false;
106
- }
107
- });
108
- }
109
- }
110
-
111
- /** @internal @inheritdoc */
112
- protected override _renderContent(): unknown {
113
- return html` <div class="icon">
114
- <svg class="check" viewBox="0 -960 960 960" aria-hidden="true">
115
- <path fill="currentColor" d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z" />
116
- </svg>
117
- <slot name="icon" @slotchange="${this.#handleIconSlotChange}"></slot>
118
- </div>
119
- <slot></slot>
120
- <slot name="trailing-icon" aria-hidden="true" @slotchange="${this.#handleTrailingIconSlotChange}"></slot>`;
121
- }
122
-
123
- /** @private */
124
- #handleIconSlotChange(e: Event): void {
125
- this.classList.toggle("-with-icon", hasAssignedNodes(<HTMLSlotElement>e.target));
126
- }
127
-
128
- /** @private */
129
- #handleTrailingIconSlotChange(e: Event): void {
130
- this.classList.toggle("-with-trailing-icon", hasAssignedNodes(<HTMLSlotElement>e.target));
131
- }
132
-
133
- /** @private */
134
- #handleClick(e: Event): void {
135
- if (!e.defaultPrevented) {
136
- this.checked = true;
137
- this.performUpdate();
138
-
139
- if (!this.#spacePressed) {
140
- this.menu?.hideAll(true);
141
- }
142
- }
143
- }
144
-
145
- /** @private */
146
- #handleKeyDown(e: KeyboardEvent): void {
147
- this.#spacePressed = e.key === " ";
148
- }
149
-
150
- /** @private */
151
- #handleKeyUp(): void {
152
- this.#spacePressed = false;
153
- }
154
-
155
- /** @private */
156
- #handleMouseEnter(): void {
157
- this.menu?.items.forEach((item) => {
158
- if (item instanceof M3eMenuItemElement && item.submenu?.isOpen) {
159
- item.submenu.hide();
160
- }
161
- });
162
- }
163
- }
164
-
165
- declare global {
166
- interface HTMLElementTagNameMap {
167
- "m3e-menu-item-radio": M3eMenuItemRadioElement;
168
- }
169
- }
@@ -1,5 +0,0 @@
1
- /** Specifies the possible positions for a menu, on the x-axis, relative to its trigger. */
2
- export type MenuPositionX = "before" | "after";
3
-
4
- /** Specifies the possible positions for a menu, on the x-axis, relative to its trigger. */
5
- export type MenuPositionY = "above" | "below";
@@ -1,154 +0,0 @@
1
- import { css, CSSResultGroup, html, LitElement } from "lit";
2
- import { customElement } from "lit/decorators.js";
3
-
4
- import { HtmlFor, Role } from "@m3e/core";
5
- import { addAriaReferencedId, removeAriaReferencedId } from "@m3e/core/a11y";
6
-
7
- import type { M3eMenuElement } from "./MenuElement";
8
-
9
- /**
10
- * @summary
11
- * An element, nested within a clickable element, used to open a menu.
12
- *
13
- * @description
14
- * The `m3e-menu-trigger` component is used to open a menu when nested within a clickable element
15
- * such as a button or menu item. It anchors the menu to its invoker, enabling contextual flows and
16
- * nested hierarchies.
17
- *
18
- * @example
19
- * The following example illustrates a basic menu. The `m3e-menu-trigger` is used to trigger a `m3e-menu` specified
20
- * by the `for` attribute when its parenting element is activated.
21
- * ```html
22
- * <m3e-button>
23
- * <m3e-menu-trigger for="menu1">Basic menu</m3e-menu-trigger>
24
- * </m3e-button>
25
- * <m3e-menu id="menu1">
26
- * <m3e-menu-item>Apple</m3e-menu-item>
27
- * <m3e-menu-item>Apricot</m3e-menu-item>
28
- * <m3e-menu-item>Avocado</m3e-menu-item>
29
- * <m3e-menu-item>Green Apple</m3e-menu-item>
30
- * <m3e-menu-item>Green Grapes</m3e-menu-item>
31
- * <m3e-menu-item>Olive</m3e-menu-item>
32
- * <m3e-menu-item>Orange</m3e-menu-item>
33
- * </m3e-menu>
34
- * ```
35
- *
36
- * @example
37
- * The next example illustrates nested menus. Submenus are triggered by placing a `m3e-menu-trigger` inside a `m3e-menu-item`.
38
- * ```html
39
- * <m3e-button>
40
- * <m3e-menu-trigger for="menu2">Nested menus</m3e-menu-trigger>
41
- * </m3e-button>
42
- * <m3e-menu id="menu2">
43
- * <m3e-menu-item>
44
- * <m3e-menu-trigger for="menu3">Fruits with A</m3e-menu-trigger>
45
- * </m3e-menu-item>
46
- * <m3e-menu-item>Grapes</m3e-menu-item>
47
- * <m3e-menu-item>Olive</m3e-menu-item>
48
- * <m3e-menu-item>Orange</m3e-menu-item>
49
- * </m3e-menu>
50
- * <m3e-menu id="menu3">
51
- * <m3e-menu-item>Apricot</m3e-menu-item>
52
- * <m3e-menu-item>Avocado</m3e-menu-item>
53
- * <m3e-menu-item>
54
- * <m3e-menu-trigger for="menu4">Apples</m3e-menu-trigger>
55
- * </m3e-menu-item>
56
- * </m3e-menu>
57
- * <m3e-menu id="menu4">
58
- * <m3e-menu-item>Fuji</m3e-menu-item>
59
- * <m3e-menu-item>Granny Smith</m3e-menu-item>
60
- * <m3e-menu-item>Red Delicious</m3e-menu-item>
61
- * </m3e-menu>
62
- * ```
63
- *
64
- * @tag m3e-menu-trigger
65
- *
66
- * @slot - Renders the contents of the trigger.
67
- */
68
- @customElement("m3e-menu-trigger")
69
- export class M3eMenuTriggerElement extends HtmlFor(Role(LitElement, "none")) {
70
- /** The styles of the element. */
71
- static override styles: CSSResultGroup = css`
72
- :host {
73
- display: contents;
74
- }
75
- ::slotted(.material-icons) {
76
- font-size: inherit !important;
77
- }
78
- `;
79
-
80
- /** @private */ readonly #clickHandler = async (e: Event) => this.#handleClick(e);
81
-
82
- /** The menu triggered by the element. */
83
- get menu(): M3eMenuElement | null {
84
- return this.control?.tagName === "M3E-MENU" ? <M3eMenuElement>this.control : null;
85
- }
86
-
87
- /** @inheritdoc */
88
- override connectedCallback(): void {
89
- super.connectedCallback();
90
- this.parentElement?.addEventListener("click", this.#clickHandler);
91
- }
92
-
93
- /** @inheritdoc */
94
- override disconnectedCallback(): void {
95
- super.disconnectedCallback();
96
- this.parentElement?.removeEventListener("click", this.#clickHandler);
97
- }
98
-
99
- /** @inheritdoc */
100
- override attach(control: HTMLElement): void {
101
- super.attach(control);
102
-
103
- const menu = this.menu;
104
- if (menu) {
105
- if (this.parentElement) {
106
- this.parentElement.ariaHasPopup = "menu";
107
- this.parentElement.ariaExpanded = "false";
108
- if (menu.id) {
109
- addAriaReferencedId(this.parentElement, "aria-controls", menu.id);
110
- }
111
- }
112
- if (this.closest("m3e-menu")) {
113
- menu.submenu = true;
114
- }
115
- }
116
- }
117
-
118
- /** @inheritdoc */
119
- override detach(): void {
120
- if (this.parentElement) {
121
- this.parentElement.ariaHasPopup = null;
122
- this.parentElement.ariaExpanded = null;
123
-
124
- const menu = this.menu;
125
- if (menu?.id) {
126
- removeAriaReferencedId(this.parentElement, "aria-controls", menu.id);
127
- }
128
- }
129
-
130
- super.detach();
131
- }
132
-
133
- /** @inheritdoc */
134
- protected override render(): unknown {
135
- return html`<slot></slot>`;
136
- }
137
-
138
- /** @private */
139
- #handleClick(e: Event): void {
140
- if (!e.defaultPrevented && this.parentElement) {
141
- if (this.parentElement.tagName === "M3E-MENU-ITEM") {
142
- this.menu?.show(this.parentElement);
143
- } else {
144
- this.menu?.toggle(this.parentElement);
145
- }
146
- }
147
- }
148
- }
149
-
150
- declare global {
151
- interface HTMLElementTagNameMap {
152
- "m3e-menu-trigger": M3eMenuTriggerElement;
153
- }
154
- }
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from "./MenuElement";
2
- export * from "./MenuItemCheckboxElement";
3
- export * from "./MenuItemElement";
4
- export * from "./MenuItemGroupElement";
5
- export * from "./MenuItemRadioElement";
6
- export * from "./MenuPosition";
7
- export * from "./MenuTriggerElement";
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "./src",
5
- "outDir": "./dist/src"
6
- },
7
- "include": ["src/**/*.ts", "**/*.mjs", "**/*.js"],
8
- "exclude": []
9
- }