@spectrum-web-components/menu 1.1.0 → 1.1.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.
- package/package.json +12 -12
- package/sp-menu-divider.d.ts +6 -0
- package/sp-menu-divider.dev.js +5 -0
- package/sp-menu-divider.dev.js.map +7 -0
- package/sp-menu-divider.js +2 -0
- package/sp-menu-divider.js.map +7 -0
- package/sp-menu-group.d.ts +6 -0
- package/sp-menu-group.dev.js +5 -0
- package/sp-menu-group.dev.js.map +7 -0
- package/sp-menu-group.js +2 -0
- package/sp-menu-group.js.map +7 -0
- package/sp-menu-item.d.ts +6 -0
- package/sp-menu-item.dev.js +5 -0
- package/sp-menu-item.dev.js.map +7 -0
- package/sp-menu-item.js +2 -0
- package/sp-menu-item.js.map +7 -0
- package/sp-menu.d.ts +6 -0
- package/sp-menu.dev.js +5 -0
- package/sp-menu.dev.js.map +7 -0
- package/sp-menu.js +2 -0
- package/sp-menu.js.map +7 -0
- package/src/Menu.d.ts +118 -0
- package/src/Menu.dev.js +740 -0
- package/src/Menu.dev.js.map +7 -0
- package/src/Menu.js +8 -0
- package/src/Menu.js.map +7 -0
- package/src/MenuDivider.d.ts +13 -0
- package/src/MenuDivider.dev.js +19 -0
- package/src/MenuDivider.dev.js.map +7 -0
- package/src/MenuDivider.js +2 -0
- package/src/MenuDivider.js.map +7 -0
- package/src/MenuGroup.d.ts +18 -0
- package/src/MenuGroup.dev.js +78 -0
- package/src/MenuGroup.dev.js.map +7 -0
- package/src/MenuGroup.js +7 -0
- package/src/MenuGroup.js.map +7 -0
- package/src/MenuItem.d.ts +125 -0
- package/src/MenuItem.dev.js +518 -0
- package/src/MenuItem.dev.js.map +7 -0
- package/src/MenuItem.js +50 -0
- package/src/MenuItem.js.map +7 -0
- package/src/checkmark-overrides.css.d.ts +2 -0
- package/src/checkmark-overrides.css.dev.js +7 -0
- package/src/checkmark-overrides.css.dev.js.map +7 -0
- package/src/checkmark-overrides.css.js +4 -0
- package/src/checkmark-overrides.css.js.map +7 -0
- package/src/chevron-overrides.css.d.ts +2 -0
- package/src/chevron-overrides.css.dev.js +7 -0
- package/src/chevron-overrides.css.dev.js.map +7 -0
- package/src/chevron-overrides.css.js +4 -0
- package/src/chevron-overrides.css.js.map +7 -0
- package/src/index.d.ts +4 -0
- package/src/index.dev.js +6 -0
- package/src/index.dev.js.map +7 -0
- package/src/index.js +2 -0
- package/src/index.js.map +7 -0
- package/src/menu-divider-overrides.css.d.ts +2 -0
- package/src/menu-divider-overrides.css.dev.js +7 -0
- package/src/menu-divider-overrides.css.dev.js.map +7 -0
- package/src/menu-divider-overrides.css.js +4 -0
- package/src/menu-divider-overrides.css.js.map +7 -0
- package/src/menu-divider.css.d.ts +2 -0
- package/src/menu-divider.css.dev.js +7 -0
- package/src/menu-divider.css.dev.js.map +7 -0
- package/src/menu-divider.css.js +4 -0
- package/src/menu-divider.css.js.map +7 -0
- package/src/menu-group.css.d.ts +2 -0
- package/src/menu-group.css.dev.js +7 -0
- package/src/menu-group.css.dev.js.map +7 -0
- package/src/menu-group.css.js +4 -0
- package/src/menu-group.css.js.map +7 -0
- package/src/menu-item-overrides.css.d.ts +2 -0
- package/src/menu-item-overrides.css.dev.js +7 -0
- package/src/menu-item-overrides.css.dev.js.map +7 -0
- package/src/menu-item-overrides.css.js +4 -0
- package/src/menu-item-overrides.css.js.map +7 -0
- package/src/menu-item.css.d.ts +2 -0
- package/src/menu-item.css.dev.js +7 -0
- package/src/menu-item.css.dev.js.map +7 -0
- package/src/menu-item.css.js +4 -0
- package/src/menu-item.css.js.map +7 -0
- package/src/menu-overrides.css.d.ts +2 -0
- package/src/menu-overrides.css.dev.js +7 -0
- package/src/menu-overrides.css.dev.js.map +7 -0
- package/src/menu-overrides.css.js +4 -0
- package/src/menu-overrides.css.js.map +7 -0
- package/src/menu-sectionHeading-overrides.css.d.ts +2 -0
- package/src/menu-sectionHeading-overrides.css.dev.js +7 -0
- package/src/menu-sectionHeading-overrides.css.dev.js.map +7 -0
- package/src/menu-sectionHeading-overrides.css.js +4 -0
- package/src/menu-sectionHeading-overrides.css.js.map +7 -0
- package/src/menu.css.d.ts +2 -0
- package/src/menu.css.dev.js +7 -0
- package/src/menu.css.dev.js.map +7 -0
- package/src/menu.css.js +4 -0
- package/src/menu.css.js.map +7 -0
- package/src/spectrum-checkmark.css.d.ts +2 -0
- package/src/spectrum-checkmark.css.dev.js +7 -0
- package/src/spectrum-checkmark.css.dev.js.map +7 -0
- package/src/spectrum-checkmark.css.js +4 -0
- package/src/spectrum-checkmark.css.js.map +7 -0
- package/src/spectrum-chevron.css.d.ts +2 -0
- package/src/spectrum-chevron.css.dev.js +7 -0
- package/src/spectrum-chevron.css.dev.js.map +7 -0
- package/src/spectrum-chevron.css.js +4 -0
- package/src/spectrum-chevron.css.js.map +7 -0
- package/src/spectrum-menu-divider.css.d.ts +2 -0
- package/src/spectrum-menu-divider.css.dev.js +7 -0
- package/src/spectrum-menu-divider.css.dev.js.map +7 -0
- package/src/spectrum-menu-divider.css.js +4 -0
- package/src/spectrum-menu-divider.css.js.map +7 -0
- package/src/spectrum-menu-item.css.d.ts +2 -0
- package/src/spectrum-menu-item.css.dev.js +7 -0
- package/src/spectrum-menu-item.css.dev.js.map +7 -0
- package/src/spectrum-menu-item.css.js +4 -0
- package/src/spectrum-menu-item.css.js.map +7 -0
- package/src/spectrum-menu-sectionHeading.css.d.ts +2 -0
- package/src/spectrum-menu-sectionHeading.css.dev.js +7 -0
- package/src/spectrum-menu-sectionHeading.css.dev.js.map +7 -0
- package/src/spectrum-menu-sectionHeading.css.js +4 -0
- package/src/spectrum-menu-sectionHeading.css.js.map +7 -0
- package/src/spectrum-menu.css.d.ts +2 -0
- package/src/spectrum-menu.css.dev.js +7 -0
- package/src/spectrum-menu.css.dev.js.map +7 -0
- package/src/spectrum-menu.css.js +4 -0
- package/src/spectrum-menu.css.js.map +7 -0
- package/stories/index.js +82 -0
- package/stories/index.js.map +7 -0
- package/stories/menu-divider.stories.js +32 -0
- package/stories/menu-divider.stories.js.map +7 -0
- package/stories/menu-group.stories.js +144 -0
- package/stories/menu-group.stories.js.map +7 -0
- package/stories/menu-item.disconnected.stories.js +178 -0
- package/stories/menu-item.disconnected.stories.js.map +7 -0
- package/stories/menu-item.stories.js +73 -0
- package/stories/menu-item.stories.js.map +7 -0
- package/stories/menu-sizes.stories.js +11 -0
- package/stories/menu-sizes.stories.js.map +7 -0
- package/stories/menu.stories.js +407 -0
- package/stories/menu.stories.js.map +7 -0
- package/stories/submenu.stories.js +346 -0
- package/stories/submenu.stories.js.map +7 -0
- package/test/benchmark/test-basic.js +24 -0
- package/test/benchmark/test-basic.js.map +7 -0
- package/test/menu-divider.test-vrt.js +5 -0
- package/test/menu-divider.test-vrt.js.map +7 -0
- package/test/menu-group.test-vrt.js +5 -0
- package/test/menu-group.test-vrt.js.map +7 -0
- package/test/menu-group.test.js +405 -0
- package/test/menu-group.test.js.map +7 -0
- package/test/menu-item.disconnected.test-vrt.js +5 -0
- package/test/menu-item.disconnected.test-vrt.js.map +7 -0
- package/test/menu-item.test-vrt.js +5 -0
- package/test/menu-item.test-vrt.js.map +7 -0
- package/test/menu-item.test.js +189 -0
- package/test/menu-item.test.js.map +7 -0
- package/test/menu-memory.test.js +5 -0
- package/test/menu-memory.test.js.map +7 -0
- package/test/menu-selects.test.js +530 -0
- package/test/menu-selects.test.js.map +7 -0
- package/test/menu-sizes.test-vrt.js +5 -0
- package/test/menu-sizes.test-vrt.js.map +7 -0
- package/test/menu.test-vrt.js +5 -0
- package/test/menu.test-vrt.js.map +7 -0
- package/test/menu.test.js +559 -0
- package/test/menu.test.js.map +7 -0
- package/test/submenu.test-vrt.js +5 -0
- package/test/submenu.test-vrt.js.map +7 -0
- package/test/submenu.test.js +970 -0
- package/test/submenu.test.js.map +7 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { CSSResultArray, PropertyValues, TemplateResult } from '@spectrum-web-components/base';
|
|
2
|
+
import '@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js';
|
|
3
|
+
import { Focusable } from '@spectrum-web-components/shared/src/focusable.js';
|
|
4
|
+
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';
|
|
5
|
+
import type { Menu } from './Menu.js';
|
|
6
|
+
import type { Overlay } from '@spectrum-web-components/overlay';
|
|
7
|
+
type MenuCascadeItem = {
|
|
8
|
+
hadFocusRoot: boolean;
|
|
9
|
+
ancestorWithSelects?: HTMLElement;
|
|
10
|
+
};
|
|
11
|
+
export declare class MenuItemAddedOrUpdatedEvent extends Event {
|
|
12
|
+
constructor(item: MenuItem);
|
|
13
|
+
clear(item: MenuItem): void;
|
|
14
|
+
menuCascade: WeakMap<HTMLElement, MenuCascadeItem>;
|
|
15
|
+
get item(): MenuItem;
|
|
16
|
+
private _item;
|
|
17
|
+
currentAncestorWithSelects?: Menu;
|
|
18
|
+
}
|
|
19
|
+
export type MenuItemChildren = {
|
|
20
|
+
icon: Element[];
|
|
21
|
+
content: Node[];
|
|
22
|
+
};
|
|
23
|
+
declare const MenuItem_base: typeof Focusable & {
|
|
24
|
+
new (...args: any[]): import("@spectrum-web-components/shared").SlotPresenceObservingInterface;
|
|
25
|
+
prototype: import("@spectrum-web-components/shared").SlotPresenceObservingInterface;
|
|
26
|
+
} & {
|
|
27
|
+
new (...args: any[]): import("@spectrum-web-components/shared").SlotTextObservingInterface;
|
|
28
|
+
prototype: import("@spectrum-web-components/shared").SlotTextObservingInterface;
|
|
29
|
+
} & {
|
|
30
|
+
new (...args: any[]): import("@spectrum-web-components/shared").LikeAnchorInterface;
|
|
31
|
+
prototype: import("@spectrum-web-components/shared").LikeAnchorInterface;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* @element sp-menu-item
|
|
35
|
+
*
|
|
36
|
+
* @slot - text content to display within the Menu Item
|
|
37
|
+
* @slot description - description to be placed below the label of the Menu Item
|
|
38
|
+
* @slot icon - icon element to be placed at the start of the Menu Item
|
|
39
|
+
* @slot value - content placed at the end of the Menu Item like values, keyboard shortcuts, etc.
|
|
40
|
+
* @slot submenu - content placed in a submenu
|
|
41
|
+
* @fires sp-menu-item-added - announces the item has been added so a parent menu can take ownerships
|
|
42
|
+
*/
|
|
43
|
+
export declare class MenuItem extends MenuItem_base {
|
|
44
|
+
static get styles(): CSSResultArray;
|
|
45
|
+
abortControllerSubmenu: AbortController;
|
|
46
|
+
active: boolean;
|
|
47
|
+
private dependencyManager;
|
|
48
|
+
focused: boolean;
|
|
49
|
+
selected: boolean;
|
|
50
|
+
get value(): string;
|
|
51
|
+
set value(value: string);
|
|
52
|
+
private _value;
|
|
53
|
+
/**
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
get itemText(): string;
|
|
57
|
+
hasSubmenu: boolean;
|
|
58
|
+
contentSlot: HTMLSlotElement;
|
|
59
|
+
iconSlot: HTMLSlotElement;
|
|
60
|
+
noWrap: boolean;
|
|
61
|
+
private anchorElement;
|
|
62
|
+
overlayElement: Overlay;
|
|
63
|
+
private submenuElement?;
|
|
64
|
+
get focusElement(): HTMLElement;
|
|
65
|
+
protected get hasIcon(): boolean;
|
|
66
|
+
get itemChildren(): MenuItemChildren;
|
|
67
|
+
private _itemChildren?;
|
|
68
|
+
constructor();
|
|
69
|
+
open: boolean;
|
|
70
|
+
click(): void;
|
|
71
|
+
private handleClickCapture;
|
|
72
|
+
private handleSlottableRequest;
|
|
73
|
+
private proxyFocus;
|
|
74
|
+
private shouldProxyClick;
|
|
75
|
+
protected breakItemChildrenCache(): void;
|
|
76
|
+
protected renderSubmenu(): TemplateResult;
|
|
77
|
+
protected render(): TemplateResult;
|
|
78
|
+
protected manageSubmenu(event: Event & {
|
|
79
|
+
target: HTMLSlotElement;
|
|
80
|
+
}): void;
|
|
81
|
+
private handlePointerdown;
|
|
82
|
+
protected firstUpdated(changes: PropertyValues): void;
|
|
83
|
+
protected closeOverlaysForRoot(): void;
|
|
84
|
+
protected handleSubmenuClick(event: Event): void;
|
|
85
|
+
protected handleSubmenuFocus(): void;
|
|
86
|
+
protected handleBeforetoggle: (event: Event) => void;
|
|
87
|
+
protected handlePointerenter(): void;
|
|
88
|
+
protected leaveTimeout?: ReturnType<typeof setTimeout>;
|
|
89
|
+
protected recentlyLeftChild: boolean;
|
|
90
|
+
protected handlePointerleave(): void;
|
|
91
|
+
/**
|
|
92
|
+
* When there is a `change` event in the submenu for this item
|
|
93
|
+
* then we "click" this item to cascade the selection up the
|
|
94
|
+
* menu tree allowing all submenus between the initial selection
|
|
95
|
+
* and the root of the tree to have their selection changes and
|
|
96
|
+
* be closed.
|
|
97
|
+
*/
|
|
98
|
+
protected handleSubmenuChange(event: Event): void;
|
|
99
|
+
protected handleSubmenuPointerenter(): void;
|
|
100
|
+
protected handleSubmenuPointerleave(): Promise<void>;
|
|
101
|
+
protected handleSubmenuOpen(event: Event): void;
|
|
102
|
+
protected cleanup(): void;
|
|
103
|
+
openOverlay(): Promise<void>;
|
|
104
|
+
updateAriaSelected(): void;
|
|
105
|
+
setRole(role: string): void;
|
|
106
|
+
protected updated(changes: PropertyValues<this>): void;
|
|
107
|
+
connectedCallback(): void;
|
|
108
|
+
_parentElement: HTMLElement;
|
|
109
|
+
disconnectedCallback(): void;
|
|
110
|
+
private willDispatchUpdate;
|
|
111
|
+
triggerUpdate(): Promise<void>;
|
|
112
|
+
dispatchUpdate(): void;
|
|
113
|
+
menuData: {
|
|
114
|
+
focusRoot?: Menu;
|
|
115
|
+
parentMenu?: Menu;
|
|
116
|
+
selectionRoot?: Menu;
|
|
117
|
+
cleanupSteps: ((item: MenuItem) => void)[];
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
declare global {
|
|
121
|
+
interface GlobalEventHandlersEventMap {
|
|
122
|
+
'sp-menu-item-added-or-updated': MenuItemAddedOrUpdatedEvent;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export {};
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
5
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
6
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
7
|
+
if (decorator = decorators[i])
|
|
8
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
9
|
+
if (kind && result) __defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
html,
|
|
14
|
+
nothing
|
|
15
|
+
} from "@spectrum-web-components/base";
|
|
16
|
+
import {
|
|
17
|
+
ObserveSlotPresence,
|
|
18
|
+
ObserveSlotText,
|
|
19
|
+
randomID
|
|
20
|
+
} from "@spectrum-web-components/shared";
|
|
21
|
+
import {
|
|
22
|
+
property,
|
|
23
|
+
query
|
|
24
|
+
} from "@spectrum-web-components/base/src/decorators.js";
|
|
25
|
+
import "@spectrum-web-components/icons-ui/icons/sp-icon-checkmark100.js";
|
|
26
|
+
import { LikeAnchor } from "@spectrum-web-components/shared/src/like-anchor.js";
|
|
27
|
+
import { Focusable } from "@spectrum-web-components/shared/src/focusable.js";
|
|
28
|
+
import "@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js";
|
|
29
|
+
import chevronStyles from "@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js";
|
|
30
|
+
import chevronIconOverrides from "@spectrum-web-components/icon/src/icon-chevron-overrides.css.js";
|
|
31
|
+
import { DependencyManagerController } from "@spectrum-web-components/reactive-controllers/src/DependencyManger.js";
|
|
32
|
+
import menuItemStyles from "./menu-item.css.js";
|
|
33
|
+
import checkmarkStyles from "@spectrum-web-components/icon/src/spectrum-icon-checkmark.css.js";
|
|
34
|
+
import checkmarkSmallOverrides from "@spectrum-web-components/icon/src/icon-checkmark-overrides.css.js";
|
|
35
|
+
import { MutationController } from "@lit-labs/observers/mutation-controller.js";
|
|
36
|
+
import { SlottableRequestEvent } from "@spectrum-web-components/overlay/src/slottable-request-event.js";
|
|
37
|
+
const POINTERLEAVE_TIMEOUT = 100;
|
|
38
|
+
export class MenuItemAddedOrUpdatedEvent extends Event {
|
|
39
|
+
constructor(item) {
|
|
40
|
+
super("sp-menu-item-added-or-updated", {
|
|
41
|
+
bubbles: true,
|
|
42
|
+
composed: true
|
|
43
|
+
});
|
|
44
|
+
this.menuCascade = /* @__PURE__ */ new WeakMap();
|
|
45
|
+
this.clear(item);
|
|
46
|
+
}
|
|
47
|
+
clear(item) {
|
|
48
|
+
this._item = item;
|
|
49
|
+
this.currentAncestorWithSelects = void 0;
|
|
50
|
+
item.menuData = {
|
|
51
|
+
cleanupSteps: [],
|
|
52
|
+
focusRoot: void 0,
|
|
53
|
+
selectionRoot: void 0,
|
|
54
|
+
parentMenu: void 0
|
|
55
|
+
};
|
|
56
|
+
this.menuCascade = /* @__PURE__ */ new WeakMap();
|
|
57
|
+
}
|
|
58
|
+
get item() {
|
|
59
|
+
return this._item;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class MenuItem extends LikeAnchor(
|
|
63
|
+
ObserveSlotText(ObserveSlotPresence(Focusable, '[slot="icon"]'))
|
|
64
|
+
) {
|
|
65
|
+
constructor() {
|
|
66
|
+
super();
|
|
67
|
+
this.active = false;
|
|
68
|
+
this.dependencyManager = new DependencyManagerController(this);
|
|
69
|
+
this.focused = false;
|
|
70
|
+
this.selected = false;
|
|
71
|
+
this._value = "";
|
|
72
|
+
this.hasSubmenu = false;
|
|
73
|
+
this.noWrap = false;
|
|
74
|
+
this.open = false;
|
|
75
|
+
this.handleSlottableRequest = (event) => {
|
|
76
|
+
var _a;
|
|
77
|
+
(_a = this.submenuElement) == null ? void 0 : _a.dispatchEvent(
|
|
78
|
+
new SlottableRequestEvent(event.name, event.data)
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
this.proxyFocus = () => {
|
|
82
|
+
this.focus();
|
|
83
|
+
};
|
|
84
|
+
this.handleBeforetoggle = (event) => {
|
|
85
|
+
if (event.newState === "closed") {
|
|
86
|
+
this.open = true;
|
|
87
|
+
this.overlayElement.manuallyKeepOpen();
|
|
88
|
+
this.overlayElement.removeEventListener(
|
|
89
|
+
"beforetoggle",
|
|
90
|
+
this.handleBeforetoggle
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
this.recentlyLeftChild = false;
|
|
95
|
+
this.willDispatchUpdate = false;
|
|
96
|
+
this.menuData = {
|
|
97
|
+
focusRoot: void 0,
|
|
98
|
+
parentMenu: void 0,
|
|
99
|
+
selectionRoot: void 0,
|
|
100
|
+
cleanupSteps: []
|
|
101
|
+
};
|
|
102
|
+
this.addEventListener("click", this.handleClickCapture, {
|
|
103
|
+
capture: true
|
|
104
|
+
});
|
|
105
|
+
new MutationController(this, {
|
|
106
|
+
config: {
|
|
107
|
+
characterData: true,
|
|
108
|
+
childList: true,
|
|
109
|
+
subtree: true
|
|
110
|
+
},
|
|
111
|
+
callback: (mutations) => {
|
|
112
|
+
const isSubmenu = mutations.every(
|
|
113
|
+
(mutation) => mutation.target.slot === "submenu"
|
|
114
|
+
);
|
|
115
|
+
if (isSubmenu) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.breakItemChildrenCache();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
static get styles() {
|
|
123
|
+
return [
|
|
124
|
+
menuItemStyles,
|
|
125
|
+
checkmarkStyles,
|
|
126
|
+
checkmarkSmallOverrides,
|
|
127
|
+
chevronStyles,
|
|
128
|
+
chevronIconOverrides
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
get value() {
|
|
132
|
+
return this._value || this.itemText;
|
|
133
|
+
}
|
|
134
|
+
set value(value) {
|
|
135
|
+
if (value === this._value) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this._value = value || "";
|
|
139
|
+
if (this._value) {
|
|
140
|
+
this.setAttribute("value", this._value);
|
|
141
|
+
} else {
|
|
142
|
+
this.removeAttribute("value");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
get itemText() {
|
|
149
|
+
return this.itemChildren.content.reduce(
|
|
150
|
+
(acc, node) => acc + (node.textContent || "").trim(),
|
|
151
|
+
""
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
get focusElement() {
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
get hasIcon() {
|
|
158
|
+
return this.slotContentIsPresent;
|
|
159
|
+
}
|
|
160
|
+
get itemChildren() {
|
|
161
|
+
if (!this.iconSlot || !this.contentSlot) {
|
|
162
|
+
return {
|
|
163
|
+
icon: [],
|
|
164
|
+
content: []
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (this._itemChildren) {
|
|
168
|
+
return this._itemChildren;
|
|
169
|
+
}
|
|
170
|
+
const icon = this.iconSlot.assignedElements().map((element) => {
|
|
171
|
+
const newElement = element.cloneNode(true);
|
|
172
|
+
newElement.removeAttribute("slot");
|
|
173
|
+
newElement.classList.toggle("icon");
|
|
174
|
+
return newElement;
|
|
175
|
+
});
|
|
176
|
+
const content = this.contentSlot.assignedNodes().map((node) => node.cloneNode(true));
|
|
177
|
+
this._itemChildren = { icon, content };
|
|
178
|
+
return this._itemChildren;
|
|
179
|
+
}
|
|
180
|
+
click() {
|
|
181
|
+
if (this.disabled) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (this.shouldProxyClick()) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
super.click();
|
|
188
|
+
}
|
|
189
|
+
handleClickCapture(event) {
|
|
190
|
+
if (this.disabled) {
|
|
191
|
+
event.preventDefault();
|
|
192
|
+
event.stopImmediatePropagation();
|
|
193
|
+
event.stopPropagation();
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
shouldProxyClick() {
|
|
198
|
+
let handled = false;
|
|
199
|
+
if (this.anchorElement) {
|
|
200
|
+
this.anchorElement.click();
|
|
201
|
+
handled = true;
|
|
202
|
+
}
|
|
203
|
+
return handled;
|
|
204
|
+
}
|
|
205
|
+
breakItemChildrenCache() {
|
|
206
|
+
this._itemChildren = void 0;
|
|
207
|
+
this.triggerUpdate();
|
|
208
|
+
}
|
|
209
|
+
renderSubmenu() {
|
|
210
|
+
const slot = html`
|
|
211
|
+
<slot
|
|
212
|
+
name="submenu"
|
|
213
|
+
@slotchange=${this.manageSubmenu}
|
|
214
|
+
@sp-menu-item-added-or-updated=${{
|
|
215
|
+
handleEvent: (event) => {
|
|
216
|
+
event.clear(event.item);
|
|
217
|
+
},
|
|
218
|
+
capture: true
|
|
219
|
+
}}
|
|
220
|
+
@focusin=${(event) => event.stopPropagation()}
|
|
221
|
+
></slot>
|
|
222
|
+
`;
|
|
223
|
+
if (!this.hasSubmenu) {
|
|
224
|
+
return slot;
|
|
225
|
+
}
|
|
226
|
+
this.dependencyManager.add("sp-overlay");
|
|
227
|
+
this.dependencyManager.add("sp-popover");
|
|
228
|
+
import("@spectrum-web-components/overlay/sp-overlay.js");
|
|
229
|
+
import("@spectrum-web-components/popover/sp-popover.js");
|
|
230
|
+
return html`
|
|
231
|
+
<sp-overlay
|
|
232
|
+
.triggerElement=${this}
|
|
233
|
+
?disabled=${!this.hasSubmenu}
|
|
234
|
+
?open=${this.hasSubmenu && this.open && this.dependencyManager.loaded}
|
|
235
|
+
.placement=${this.isLTR ? "right-start" : "left-start"}
|
|
236
|
+
.offset=${[-10, -5]}
|
|
237
|
+
.type=${"auto"}
|
|
238
|
+
@close=${(event) => event.stopPropagation()}
|
|
239
|
+
@slottable-request=${this.handleSlottableRequest}
|
|
240
|
+
>
|
|
241
|
+
<sp-popover
|
|
242
|
+
@change=${(event) => {
|
|
243
|
+
this.handleSubmenuChange(event);
|
|
244
|
+
this.open = false;
|
|
245
|
+
}}
|
|
246
|
+
@pointerenter=${this.handleSubmenuPointerenter}
|
|
247
|
+
@pointerleave=${this.handleSubmenuPointerleave}
|
|
248
|
+
@sp-menu-item-added-or-updated=${(event) => event.stopPropagation()}
|
|
249
|
+
>
|
|
250
|
+
${slot}
|
|
251
|
+
</sp-popover>
|
|
252
|
+
</sp-overlay>
|
|
253
|
+
<sp-icon-chevron100
|
|
254
|
+
class="spectrum-UIIcon-ChevronRight100 chevron icon"
|
|
255
|
+
></sp-icon-chevron100>
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
258
|
+
render() {
|
|
259
|
+
return html`
|
|
260
|
+
${this.selected ? html`
|
|
261
|
+
<sp-icon-checkmark100
|
|
262
|
+
id="selected"
|
|
263
|
+
class="spectrum-UIIcon-Checkmark100
|
|
264
|
+
icon
|
|
265
|
+
checkmark
|
|
266
|
+
${this.hasIcon ? "checkmark--withAdjacentIcon" : ""}"
|
|
267
|
+
></sp-icon-checkmark100>
|
|
268
|
+
` : nothing}
|
|
269
|
+
<slot name="icon"></slot>
|
|
270
|
+
<div id="label">
|
|
271
|
+
<slot id="slot"></slot>
|
|
272
|
+
</div>
|
|
273
|
+
<slot name="description"></slot>
|
|
274
|
+
<slot name="value"></slot>
|
|
275
|
+
${this.href && this.href.length > 0 ? super.renderAnchor({
|
|
276
|
+
id: "button",
|
|
277
|
+
ariaHidden: true,
|
|
278
|
+
className: "button anchor hidden"
|
|
279
|
+
}) : nothing}
|
|
280
|
+
${this.renderSubmenu()}
|
|
281
|
+
`;
|
|
282
|
+
}
|
|
283
|
+
manageSubmenu(event) {
|
|
284
|
+
this.submenuElement = event.target.assignedElements({
|
|
285
|
+
flatten: true
|
|
286
|
+
})[0];
|
|
287
|
+
this.hasSubmenu = !!this.submenuElement;
|
|
288
|
+
if (this.hasSubmenu) {
|
|
289
|
+
this.setAttribute("aria-haspopup", "true");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
handlePointerdown(event) {
|
|
293
|
+
if (event.target === this && this.hasSubmenu && this.open) {
|
|
294
|
+
this.addEventListener("focus", this.handleSubmenuFocus, {
|
|
295
|
+
once: true
|
|
296
|
+
});
|
|
297
|
+
this.overlayElement.addEventListener(
|
|
298
|
+
"beforetoggle",
|
|
299
|
+
this.handleBeforetoggle
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
firstUpdated(changes) {
|
|
304
|
+
super.firstUpdated(changes);
|
|
305
|
+
this.setAttribute("tabindex", "-1");
|
|
306
|
+
this.addEventListener("pointerdown", this.handlePointerdown);
|
|
307
|
+
this.addEventListener("pointerenter", this.closeOverlaysForRoot);
|
|
308
|
+
if (!this.hasAttribute("id")) {
|
|
309
|
+
this.id = `sp-menu-item-${randomID()}`;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
closeOverlaysForRoot() {
|
|
313
|
+
var _a;
|
|
314
|
+
if (this.open) return;
|
|
315
|
+
(_a = this.menuData.parentMenu) == null ? void 0 : _a.closeDescendentOverlays();
|
|
316
|
+
}
|
|
317
|
+
handleSubmenuClick(event) {
|
|
318
|
+
if (event.composedPath().includes(this.overlayElement)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
this.openOverlay();
|
|
322
|
+
}
|
|
323
|
+
handleSubmenuFocus() {
|
|
324
|
+
requestAnimationFrame(() => {
|
|
325
|
+
this.overlayElement.open = this.open;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
handlePointerenter() {
|
|
329
|
+
if (this.leaveTimeout) {
|
|
330
|
+
clearTimeout(this.leaveTimeout);
|
|
331
|
+
delete this.leaveTimeout;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
this.openOverlay();
|
|
335
|
+
}
|
|
336
|
+
handlePointerleave() {
|
|
337
|
+
if (this.open && !this.recentlyLeftChild) {
|
|
338
|
+
this.leaveTimeout = setTimeout(() => {
|
|
339
|
+
delete this.leaveTimeout;
|
|
340
|
+
this.open = false;
|
|
341
|
+
}, POINTERLEAVE_TIMEOUT);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* When there is a `change` event in the submenu for this item
|
|
346
|
+
* then we "click" this item to cascade the selection up the
|
|
347
|
+
* menu tree allowing all submenus between the initial selection
|
|
348
|
+
* and the root of the tree to have their selection changes and
|
|
349
|
+
* be closed.
|
|
350
|
+
*/
|
|
351
|
+
handleSubmenuChange(event) {
|
|
352
|
+
var _a;
|
|
353
|
+
event.stopPropagation();
|
|
354
|
+
(_a = this.menuData.selectionRoot) == null ? void 0 : _a.selectOrToggleItem(this);
|
|
355
|
+
}
|
|
356
|
+
handleSubmenuPointerenter() {
|
|
357
|
+
this.recentlyLeftChild = true;
|
|
358
|
+
}
|
|
359
|
+
async handleSubmenuPointerleave() {
|
|
360
|
+
requestAnimationFrame(() => {
|
|
361
|
+
this.recentlyLeftChild = false;
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
handleSubmenuOpen(event) {
|
|
365
|
+
this.focused = false;
|
|
366
|
+
const parentOverlay = event.composedPath().find((el) => {
|
|
367
|
+
return el !== this.overlayElement && el.localName === "sp-overlay";
|
|
368
|
+
});
|
|
369
|
+
this.overlayElement.parentOverlayToForceClose = parentOverlay;
|
|
370
|
+
}
|
|
371
|
+
cleanup() {
|
|
372
|
+
this.open = false;
|
|
373
|
+
this.active = false;
|
|
374
|
+
}
|
|
375
|
+
async openOverlay() {
|
|
376
|
+
if (!this.hasSubmenu || this.open || this.disabled) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
this.open = true;
|
|
380
|
+
this.active = true;
|
|
381
|
+
this.setAttribute("aria-expanded", "true");
|
|
382
|
+
this.addEventListener("sp-closed", this.cleanup, {
|
|
383
|
+
once: true
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
updateAriaSelected() {
|
|
387
|
+
const role = this.getAttribute("role");
|
|
388
|
+
if (role === "option") {
|
|
389
|
+
this.setAttribute(
|
|
390
|
+
"aria-selected",
|
|
391
|
+
this.selected ? "true" : "false"
|
|
392
|
+
);
|
|
393
|
+
} else if (role === "menuitemcheckbox" || role === "menuitemradio") {
|
|
394
|
+
this.setAttribute("aria-checked", this.selected ? "true" : "false");
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
setRole(role) {
|
|
398
|
+
this.setAttribute("role", role);
|
|
399
|
+
this.updateAriaSelected();
|
|
400
|
+
}
|
|
401
|
+
updated(changes) {
|
|
402
|
+
var _a, _b;
|
|
403
|
+
super.updated(changes);
|
|
404
|
+
if (changes.has("label") && (this.label || typeof changes.get("label") !== "undefined")) {
|
|
405
|
+
this.setAttribute("aria-label", this.label || "");
|
|
406
|
+
}
|
|
407
|
+
if (changes.has("active") && (this.active || typeof changes.get("active") !== "undefined")) {
|
|
408
|
+
if (this.active) {
|
|
409
|
+
(_a = this.menuData.selectionRoot) == null ? void 0 : _a.closeDescendentOverlays();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (this.anchorElement) {
|
|
413
|
+
this.anchorElement.addEventListener("focus", this.proxyFocus);
|
|
414
|
+
this.anchorElement.tabIndex = -1;
|
|
415
|
+
}
|
|
416
|
+
if (changes.has("selected")) {
|
|
417
|
+
this.updateAriaSelected();
|
|
418
|
+
}
|
|
419
|
+
if (changes.has("hasSubmenu") && (this.hasSubmenu || typeof changes.get("hasSubmenu") !== "undefined")) {
|
|
420
|
+
if (this.hasSubmenu) {
|
|
421
|
+
this.abortControllerSubmenu = new AbortController();
|
|
422
|
+
const options = { signal: this.abortControllerSubmenu.signal };
|
|
423
|
+
this.addEventListener(
|
|
424
|
+
"click",
|
|
425
|
+
this.handleSubmenuClick,
|
|
426
|
+
options
|
|
427
|
+
);
|
|
428
|
+
this.addEventListener(
|
|
429
|
+
"pointerenter",
|
|
430
|
+
this.handlePointerenter,
|
|
431
|
+
options
|
|
432
|
+
);
|
|
433
|
+
this.addEventListener(
|
|
434
|
+
"pointerleave",
|
|
435
|
+
this.handlePointerleave,
|
|
436
|
+
options
|
|
437
|
+
);
|
|
438
|
+
this.addEventListener(
|
|
439
|
+
"sp-opened",
|
|
440
|
+
this.handleSubmenuOpen,
|
|
441
|
+
options
|
|
442
|
+
);
|
|
443
|
+
} else {
|
|
444
|
+
(_b = this.abortControllerSubmenu) == null ? void 0 : _b.abort();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
connectedCallback() {
|
|
449
|
+
super.connectedCallback();
|
|
450
|
+
this.triggerUpdate();
|
|
451
|
+
}
|
|
452
|
+
disconnectedCallback() {
|
|
453
|
+
this.menuData.cleanupSteps.forEach((removal) => removal(this));
|
|
454
|
+
this.menuData = {
|
|
455
|
+
focusRoot: void 0,
|
|
456
|
+
parentMenu: void 0,
|
|
457
|
+
selectionRoot: void 0,
|
|
458
|
+
cleanupSteps: []
|
|
459
|
+
};
|
|
460
|
+
super.disconnectedCallback();
|
|
461
|
+
}
|
|
462
|
+
async triggerUpdate() {
|
|
463
|
+
if (this.willDispatchUpdate) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
this.willDispatchUpdate = true;
|
|
467
|
+
await new Promise((ready) => requestAnimationFrame(ready));
|
|
468
|
+
this.dispatchUpdate();
|
|
469
|
+
}
|
|
470
|
+
dispatchUpdate() {
|
|
471
|
+
if (!this.isConnected) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
this.dispatchEvent(new MenuItemAddedOrUpdatedEvent(this));
|
|
475
|
+
this.willDispatchUpdate = false;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
__decorateClass([
|
|
479
|
+
property({ type: Boolean, reflect: true })
|
|
480
|
+
], MenuItem.prototype, "active", 2);
|
|
481
|
+
__decorateClass([
|
|
482
|
+
property({ type: Boolean, reflect: true })
|
|
483
|
+
], MenuItem.prototype, "focused", 2);
|
|
484
|
+
__decorateClass([
|
|
485
|
+
property({ type: Boolean, reflect: true })
|
|
486
|
+
], MenuItem.prototype, "selected", 2);
|
|
487
|
+
__decorateClass([
|
|
488
|
+
property({ type: String })
|
|
489
|
+
], MenuItem.prototype, "value", 1);
|
|
490
|
+
__decorateClass([
|
|
491
|
+
property({ type: Boolean, reflect: true, attribute: "has-submenu" })
|
|
492
|
+
], MenuItem.prototype, "hasSubmenu", 2);
|
|
493
|
+
__decorateClass([
|
|
494
|
+
query("slot:not([name])")
|
|
495
|
+
], MenuItem.prototype, "contentSlot", 2);
|
|
496
|
+
__decorateClass([
|
|
497
|
+
query('slot[name="icon"]')
|
|
498
|
+
], MenuItem.prototype, "iconSlot", 2);
|
|
499
|
+
__decorateClass([
|
|
500
|
+
property({
|
|
501
|
+
type: Boolean,
|
|
502
|
+
reflect: true,
|
|
503
|
+
attribute: "no-wrap",
|
|
504
|
+
hasChanged() {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
})
|
|
508
|
+
], MenuItem.prototype, "noWrap", 2);
|
|
509
|
+
__decorateClass([
|
|
510
|
+
query(".anchor")
|
|
511
|
+
], MenuItem.prototype, "anchorElement", 2);
|
|
512
|
+
__decorateClass([
|
|
513
|
+
query("sp-overlay")
|
|
514
|
+
], MenuItem.prototype, "overlayElement", 2);
|
|
515
|
+
__decorateClass([
|
|
516
|
+
property({ type: Boolean, reflect: true })
|
|
517
|
+
], MenuItem.prototype, "open", 2);
|
|
518
|
+
//# sourceMappingURL=MenuItem.dev.js.map
|