@api-client/ui 0.4.2 → 0.4.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/.vscode/settings.json +1 -0
- package/build/src/index.d.ts +3 -0
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +4 -0
- package/build/src/index.js.map +1 -1
- package/build/src/lib/Dom.d.ts +5 -0
- package/build/src/lib/Dom.d.ts.map +1 -0
- package/build/src/lib/Dom.js +24 -0
- package/build/src/lib/Dom.js.map +1 -0
- package/build/src/md/button/internals/base.d.ts +27 -0
- package/build/src/md/button/internals/base.d.ts.map +1 -1
- package/build/src/md/button/internals/base.js +90 -1
- package/build/src/md/button/internals/base.js.map +1 -1
- package/build/src/md/icons/internals/Icon.js +2 -2
- package/build/src/md/icons/internals/Icon.js.map +1 -1
- package/build/src/md/list/internals/List.d.ts +1 -1
- package/build/src/md/list/internals/List.d.ts.map +1 -1
- package/build/src/md/list/internals/List.js +4 -4
- package/build/src/md/list/internals/List.js.map +1 -1
- package/build/src/md/list/internals/ListItem.d.ts +1 -0
- package/build/src/md/list/internals/ListItem.d.ts.map +1 -1
- package/build/src/md/list/internals/ListItem.js +10 -10
- package/build/src/md/list/internals/ListItem.js.map +1 -1
- package/build/src/md/list/internals/ListItem.styles.d.ts.map +1 -1
- package/build/src/md/list/internals/ListItem.styles.js +2 -20
- package/build/src/md/list/internals/ListItem.styles.js.map +1 -1
- package/build/src/md/menu/index.d.ts +4 -0
- package/build/src/md/menu/index.d.ts.map +1 -0
- package/build/src/md/menu/index.js +4 -0
- package/build/src/md/menu/index.js.map +1 -0
- package/build/src/md/menu/internal/Menu.d.ts +76 -0
- package/build/src/md/menu/internal/Menu.d.ts.map +1 -0
- package/build/src/md/menu/internal/Menu.js +235 -0
- package/build/src/md/menu/internal/Menu.js.map +1 -0
- package/build/src/md/menu/internal/Menu.styles.d.ts +3 -0
- package/build/src/md/menu/internal/Menu.styles.d.ts.map +1 -0
- package/build/src/md/menu/internal/Menu.styles.js +185 -0
- package/build/src/md/menu/internal/Menu.styles.js.map +1 -0
- package/build/src/md/menu/internal/MenuItem.d.ts +77 -0
- package/build/src/md/menu/internal/MenuItem.d.ts.map +1 -0
- package/build/src/md/menu/internal/MenuItem.js +216 -0
- package/build/src/md/menu/internal/MenuItem.js.map +1 -0
- package/build/src/md/menu/internal/MenuItem.styles.d.ts +3 -0
- package/build/src/md/menu/internal/MenuItem.styles.d.ts.map +1 -0
- package/build/src/md/menu/internal/MenuItem.styles.js +64 -0
- package/build/src/md/menu/internal/MenuItem.styles.js.map +1 -0
- package/build/src/md/menu/internal/SubMenu.d.ts +56 -0
- package/build/src/md/menu/internal/SubMenu.d.ts.map +1 -0
- package/build/src/md/menu/internal/SubMenu.js +171 -0
- package/build/src/md/menu/internal/SubMenu.js.map +1 -0
- package/build/src/md/menu/internal/SubMenu.styles.d.ts +3 -0
- package/build/src/md/menu/internal/SubMenu.styles.d.ts.map +1 -0
- package/build/src/md/menu/internal/SubMenu.styles.js +8 -0
- package/build/src/md/menu/internal/SubMenu.styles.js.map +1 -0
- package/build/src/md/menu/ui-menu-item.d.ts +20 -0
- package/build/src/md/menu/ui-menu-item.d.ts.map +1 -0
- package/build/src/md/menu/ui-menu-item.js +37 -0
- package/build/src/md/menu/ui-menu-item.js.map +1 -0
- package/build/src/md/menu/ui-menu.d.ts +22 -0
- package/build/src/md/menu/ui-menu.d.ts.map +1 -0
- package/build/src/md/menu/ui-menu.js +38 -0
- package/build/src/md/menu/ui-menu.js.map +1 -0
- package/build/src/md/menu/ui-sub-menu.d.ts +20 -0
- package/build/src/md/menu/ui-sub-menu.d.ts.map +1 -0
- package/build/src/md/menu/ui-sub-menu.js +37 -0
- package/build/src/md/menu/ui-sub-menu.js.map +1 -0
- package/build/src/mixins/FileDropMixin.d.ts.map +1 -1
- package/build/src/mixins/FileDropMixin.js +7 -8
- package/build/src/mixins/FileDropMixin.js.map +1 -1
- package/build/src/mixins/RenderableMixin.d.ts.map +1 -1
- package/build/src/mixins/RenderableMixin.js +2 -3
- package/build/src/mixins/RenderableMixin.js.map +1 -1
- package/demo/md/index.html +2 -0
- package/demo/md/menu/index.html +19 -0
- package/demo/md/menu/index.ts +154 -0
- package/package.json +2 -3
- package/src/index.ts +5 -0
- package/src/lib/Dom.ts +26 -0
- package/src/md/button/internals/base.ts +77 -0
- package/src/md/icons/internals/Icon.ts +2 -2
- package/src/md/list/internals/List.ts +4 -4
- package/src/md/list/internals/ListItem.styles.ts +2 -20
- package/src/md/list/internals/ListItem.ts +11 -11
- package/src/md/menu/README.md +253 -0
- package/src/md/menu/index.ts +3 -0
- package/src/md/menu/internal/Menu.styles.ts +185 -0
- package/src/md/menu/internal/Menu.ts +205 -0
- package/src/md/menu/internal/MenuItem.styles.ts +64 -0
- package/src/md/menu/internal/MenuItem.ts +217 -0
- package/src/md/menu/internal/SubMenu.styles.ts +8 -0
- package/src/md/menu/internal/SubMenu.ts +179 -0
- package/src/md/menu/ui-menu-item.ts +25 -0
- package/src/md/menu/ui-menu.ts +26 -0
- package/src/md/menu/ui-sub-menu.ts +25 -0
- package/src/mixins/FileDropMixin.ts +106 -107
- package/src/mixins/RenderableMixin.ts +107 -108
- package/test/md/menu/Menu.test.ts +509 -0
- package/test/md/menu/MenuIntegration.test.ts +426 -0
- package/test/md/menu/MenuItem.test.ts +361 -0
- package/test/md/menu/SubMenu.test.ts +411 -0
- /package/test/{ui → md}/button/UiButton.test.ts +0 -0
- /package/test/{ui → md}/button/UiIconButton.test.ts +0 -0
- /package/test/{ui → md}/chip/UiChip.test.ts +0 -0
- /package/test/{ui → md}/collapse/UiCollapse.test.ts +0 -0
- /package/test/{ui → md}/collapse/flex-layout.test.ts +0 -0
- /package/test/{ui → md}/date-time/DateTime.test.ts +0 -0
- /package/test/{ui → md}/dialog/UiDialog.test.ts +0 -0
- /package/test/{ui → md}/progress/UiProgressElement.test.ts +0 -0
- /package/test/{ui → md}/progress/UiRangeElement.test.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Material Design 3 Menu Component Demo</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0">
|
|
8
|
+
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet" />
|
|
10
|
+
<link href="../../../src/styles/m3/tokens.css" rel="stylesheet" type="text/css" />
|
|
11
|
+
<link href="../../../src/styles/m3/theme.css" rel="stylesheet" type="text/css" />
|
|
12
|
+
<link href="../../../src/styles/m3/native.css" rel="stylesheet" type="text/css" />
|
|
13
|
+
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<div id="app"></div>
|
|
17
|
+
<script type="module" src="/.tmp/demo/md/menu/index.js"></script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { html, TemplateResult } from 'lit'
|
|
2
|
+
import { DemoPage } from '../../../src/demo/DemoPage.js'
|
|
3
|
+
import reactive from '../../../src/decorators/reactive.js'
|
|
4
|
+
|
|
5
|
+
import '../../../src/md/menu/ui-menu.js'
|
|
6
|
+
import '../../../src/md/menu/ui-sub-menu.js'
|
|
7
|
+
import '../../../src/md/menu/ui-menu-item.js'
|
|
8
|
+
import '../../../src/md/button/ui-button.js'
|
|
9
|
+
import '../../../src/md/icons/ui-icon.js'
|
|
10
|
+
|
|
11
|
+
class ComponentDemoPage extends DemoPage {
|
|
12
|
+
override accessor componentName = 'UI menu'
|
|
13
|
+
|
|
14
|
+
@reactive() accessor basicMenuOutput = ''
|
|
15
|
+
@reactive() accessor basicCount = 0
|
|
16
|
+
@reactive() accessor nestedMenuOutput = ''
|
|
17
|
+
@reactive() accessor nestedCount = 0
|
|
18
|
+
|
|
19
|
+
handleBasicMenuSelect(e: CustomEvent): void {
|
|
20
|
+
const item = e.detail.item as HTMLElement
|
|
21
|
+
const index = e.detail.index
|
|
22
|
+
this.basicMenuOutput = `Selected item: ${item.textContent}, Index: ${index}`
|
|
23
|
+
this.basicCount++
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
handleNestedMenuSelect(e: CustomEvent): void {
|
|
27
|
+
const item = e.detail.item as HTMLElement
|
|
28
|
+
const index = e.detail.index
|
|
29
|
+
this.nestedMenuOutput = `Selected item: ${item.textContent}, Index: ${index}`
|
|
30
|
+
this.nestedCount++
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
contentTemplate(): TemplateResult {
|
|
34
|
+
const { basicMenuOutput, nestedMenuOutput, nestedCount, basicCount } = this
|
|
35
|
+
return html`
|
|
36
|
+
<a href="../">Back</a>
|
|
37
|
+
|
|
38
|
+
<section class="demo-section">
|
|
39
|
+
<h2 class="title-large">Basic Menu</h2>
|
|
40
|
+
<p>Click the button below to open a basic menu:</p>
|
|
41
|
+
<ui-button id="basic-menu-trigger" color="filled" popovertarget="basic-menu">Open Basic Menu</ui-button>
|
|
42
|
+
<ui-menu id="basic-menu" popover="auto" @select="${this.handleBasicMenuSelect}">
|
|
43
|
+
<ui-menu-item>
|
|
44
|
+
<span slot="start"><ui-icon>add</ui-icon></span>
|
|
45
|
+
<span>New</span>
|
|
46
|
+
</ui-menu-item>
|
|
47
|
+
<ui-menu-item>
|
|
48
|
+
<span slot="start"><ui-icon>folder</ui-icon></span>
|
|
49
|
+
<span>Open</span>
|
|
50
|
+
</ui-menu-item>
|
|
51
|
+
<ui-menu-item>
|
|
52
|
+
<span slot="start"><ui-icon>save</ui-icon></span>
|
|
53
|
+
<span>Save</span>
|
|
54
|
+
</ui-menu-item>
|
|
55
|
+
<div class="menu-divider" role="separator"></div>
|
|
56
|
+
<ui-menu-item>
|
|
57
|
+
<span slot="start"><ui-icon>print</ui-icon></span>
|
|
58
|
+
<span>Print</span>
|
|
59
|
+
</ui-menu-item>
|
|
60
|
+
<ui-menu-item>
|
|
61
|
+
<span slot="start"><ui-icon>file_export</ui-icon></span>
|
|
62
|
+
<span>Export</span>
|
|
63
|
+
</ui-menu-item>
|
|
64
|
+
</ui-menu>
|
|
65
|
+
${basicMenuOutput
|
|
66
|
+
? html`<p>${basicMenuOutput}</p>
|
|
67
|
+
<p>Count: ${basicCount}</p>`
|
|
68
|
+
: ''}
|
|
69
|
+
</section>
|
|
70
|
+
|
|
71
|
+
<section class="demo-section">
|
|
72
|
+
<h2 class="title-large">Submenus</h2>
|
|
73
|
+
<p>A menu with submenus:</p>
|
|
74
|
+
<ui-button id="submenu-trigger" color="filled" popovertarget="submenu-demo"
|
|
75
|
+
>Open Attribute-based Menu</ui-button
|
|
76
|
+
>
|
|
77
|
+
|
|
78
|
+
<!-- Main Menu -->
|
|
79
|
+
<ui-menu id="submenu-demo" popover="auto" @select="${this.handleNestedMenuSelect}">
|
|
80
|
+
<ui-menu-item id="file-item" submenu="file-submenu">
|
|
81
|
+
<span slot="start"><ui-icon>docs</ui-icon></span>
|
|
82
|
+
<span>File</span>
|
|
83
|
+
</ui-menu-item>
|
|
84
|
+
<ui-menu-item id="edit-item" submenu="edit-submenu">
|
|
85
|
+
<span slot="start"><ui-icon>edit</ui-icon></span>
|
|
86
|
+
<span>Edit</span>
|
|
87
|
+
</ui-menu-item>
|
|
88
|
+
<ui-menu-item id="view-item">
|
|
89
|
+
<span slot="start"><ui-icon>visibility</ui-icon></span>
|
|
90
|
+
<span>View</span>
|
|
91
|
+
</ui-menu-item>
|
|
92
|
+
<!-- File Submenu (separate from main menu) -->
|
|
93
|
+
<ui-sub-menu id="file-submenu" anchor="file-item" popover="auto">
|
|
94
|
+
<ui-menu-item>
|
|
95
|
+
<span slot="start"><ui-icon>add</ui-icon></span>
|
|
96
|
+
<span>New File</span>
|
|
97
|
+
</ui-menu-item>
|
|
98
|
+
<ui-menu-item>
|
|
99
|
+
<span slot="start"><ui-icon>folder</ui-icon></span>
|
|
100
|
+
<span>Open File</span>
|
|
101
|
+
</ui-menu-item>
|
|
102
|
+
<ui-menu-item>
|
|
103
|
+
<span slot="start"><ui-icon>save</ui-icon></span>
|
|
104
|
+
<span>Save File</span>
|
|
105
|
+
</ui-menu-item>
|
|
106
|
+
<ui-menu-item id="export-item" submenu="export-submenu">
|
|
107
|
+
<span slot="start"><ui-icon>file_export</ui-icon></span>
|
|
108
|
+
<span>Export</span>
|
|
109
|
+
</ui-menu-item>
|
|
110
|
+
|
|
111
|
+
<!-- Nested Export Submenu -->
|
|
112
|
+
<ui-sub-menu id="export-submenu" anchor="export-item" popover="auto">
|
|
113
|
+
<ui-menu-item>
|
|
114
|
+
<span>Export as PDF</span>
|
|
115
|
+
</ui-menu-item>
|
|
116
|
+
<ui-menu-item>
|
|
117
|
+
<span>Export as PNG</span>
|
|
118
|
+
</ui-menu-item>
|
|
119
|
+
<ui-menu-item>
|
|
120
|
+
<span>Export as SVG</span>
|
|
121
|
+
</ui-menu-item>
|
|
122
|
+
</ui-sub-menu>
|
|
123
|
+
</ui-sub-menu>
|
|
124
|
+
<!-- Edit Submenu -->
|
|
125
|
+
<ui-sub-menu id="edit-submenu" anchor="edit-item" popover="auto">
|
|
126
|
+
<ui-menu-item>
|
|
127
|
+
<span slot="start"><ui-icon>undo</ui-icon></span>
|
|
128
|
+
<span>Undo</span>
|
|
129
|
+
</ui-menu-item>
|
|
130
|
+
<ui-menu-item>
|
|
131
|
+
<span slot="start"><ui-icon>redo</ui-icon></span>
|
|
132
|
+
<span>Redo</span>
|
|
133
|
+
</ui-menu-item>
|
|
134
|
+
<ui-menu-item>
|
|
135
|
+
<span slot="start"><ui-icon>cut</ui-icon></span>
|
|
136
|
+
<span>Cut</span>
|
|
137
|
+
</ui-menu-item>
|
|
138
|
+
<ui-menu-item>
|
|
139
|
+
<span slot="start"><ui-icon>content_copy</ui-icon></span>
|
|
140
|
+
<span>Copy</span>
|
|
141
|
+
</ui-menu-item>
|
|
142
|
+
</ui-sub-menu>
|
|
143
|
+
</ui-menu>
|
|
144
|
+
${nestedMenuOutput
|
|
145
|
+
? html`<p>${nestedMenuOutput}</p>
|
|
146
|
+
<p>Count: ${nestedCount}</p>`
|
|
147
|
+
: ''}
|
|
148
|
+
</section>
|
|
149
|
+
`
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const instance = new ComponentDemoPage()
|
|
154
|
+
instance.render()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@api-client/ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Internal UI component library for the API Client ecosystem.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"main": "build/src/index.js",
|
|
@@ -173,12 +173,11 @@
|
|
|
173
173
|
}
|
|
174
174
|
},
|
|
175
175
|
"dependencies": {
|
|
176
|
-
"@api-client/core": "^0.
|
|
176
|
+
"@api-client/core": "^0.17.3",
|
|
177
177
|
"@api-client/graph": "^0.3.6",
|
|
178
178
|
"@api-client/json": "^0.2.0",
|
|
179
179
|
"@github/relative-time-element": "^4.4.6",
|
|
180
180
|
"@material/web": "^2.3.0",
|
|
181
|
-
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
182
181
|
"@types/har-format": "^1.2.8",
|
|
183
182
|
"dompurify": "^3.2.5",
|
|
184
183
|
"idb-keyval": "^6.1.0",
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,11 @@ export { default as MarkedHighlightElement } from './elements/highlight/MarkedHi
|
|
|
4
4
|
export { default as PrismHighlightElement } from './elements/highlight/PrismHighlight.js'
|
|
5
5
|
export { default as HarViewerElement } from './elements/har/HarViewer.js'
|
|
6
6
|
|
|
7
|
+
// Menu Components
|
|
8
|
+
export { default as Menu } from './md/menu/internal/Menu.js'
|
|
9
|
+
export { default as MenuItem } from './md/menu/internal/MenuItem.js'
|
|
10
|
+
export { default as SubMenu } from './md/menu/internal/SubMenu.js'
|
|
11
|
+
|
|
7
12
|
// Demo
|
|
8
13
|
export { DemoPage } from './demo/DemoPage.js'
|
|
9
14
|
|
package/src/lib/Dom.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Searches for an element with the given ID in parent shadow roots
|
|
3
|
+
*/
|
|
4
|
+
export function findElementInShadowRoots(id: string, from: Element): HTMLElement | null {
|
|
5
|
+
// First try to find in document
|
|
6
|
+
const rootElm = document.getElementById(id)
|
|
7
|
+
if (rootElm) {
|
|
8
|
+
return rootElm
|
|
9
|
+
}
|
|
10
|
+
// If not found in document, search in parent shadow roots
|
|
11
|
+
let current: Element | null | undefined = from
|
|
12
|
+
|
|
13
|
+
while (current) {
|
|
14
|
+
const shadowRoot = current.shadowRoot
|
|
15
|
+
if (shadowRoot) {
|
|
16
|
+
const element = shadowRoot.getElementById(id)
|
|
17
|
+
if (element) {
|
|
18
|
+
return element as HTMLElement
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
current = current.parentElement ?? current.shadowRoot?.host
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { html, nothing, type PropertyValues, type TemplateResult } from 'lit'
|
|
2
2
|
import { property, query } from 'lit/decorators.js'
|
|
3
|
+
import { nanoid } from 'nanoid'
|
|
3
4
|
import { UiElement } from '../../UiElement.js'
|
|
4
5
|
import type { BeginPressConfig, EndPressConfig } from '../../../controllers/ActionController.js'
|
|
5
6
|
import { isDisabled, setDisabled } from '../../../lib/disabled.js'
|
|
6
7
|
import type UiRipple from '../../ripple/internals/ripple.js'
|
|
8
|
+
import { findElementInShadowRoots } from '../../../lib/Dom.js'
|
|
7
9
|
|
|
8
10
|
import '../../ripple/ui-ripple.js'
|
|
9
11
|
import '@material/web/focus/md-focus-ring.js'
|
|
@@ -126,6 +128,26 @@ export default class BaseButton extends UiElement {
|
|
|
126
128
|
|
|
127
129
|
@query('ui-ripple') protected accessor ripple!: UiRipple | null
|
|
128
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Turns a `<ui-button>` element into a popover control button; takes the ID
|
|
133
|
+
* of the popover element to control as its value.
|
|
134
|
+
* @attribute
|
|
135
|
+
*/
|
|
136
|
+
@property({ type: String, reflect: true }) accessor popoverTarget: string | undefined
|
|
137
|
+
/**
|
|
138
|
+
* Specifies the action to be performed on a popover element being controlled
|
|
139
|
+
* by a control <ui-button>. Possible values are:
|
|
140
|
+
*
|
|
141
|
+
* - `hide` - The button will hide a shown popover. If you try to hide an already hidden popover,
|
|
142
|
+
* no action will be taken.
|
|
143
|
+
* - `show` - The button will show a hidden popover. If you try to show an already showing popover,
|
|
144
|
+
* no action will be taken.
|
|
145
|
+
* - `toggle` - The button will toggle a popover between showing and hidden. If the popover is hidden,
|
|
146
|
+
* it will be shown; if the popover is showing, it will be hidden. If popoverTargetAction is omitted,
|
|
147
|
+
* "toggle" is the default action that will be performed by the control button.
|
|
148
|
+
*/
|
|
149
|
+
@property({ type: String, reflect: true }) accessor popoverTargetAction: string | undefined
|
|
150
|
+
|
|
129
151
|
constructor() {
|
|
130
152
|
super()
|
|
131
153
|
this.actionController.cancelKeyboardEvents = true
|
|
@@ -150,6 +172,13 @@ export default class BaseButton extends UiElement {
|
|
|
150
172
|
}
|
|
151
173
|
}
|
|
152
174
|
|
|
175
|
+
protected override update(changedProperties: PropertyValues<this>): void {
|
|
176
|
+
if (changedProperties.has('popoverTarget')) {
|
|
177
|
+
this.setupPopoverTarget()
|
|
178
|
+
}
|
|
179
|
+
super.update(changedProperties)
|
|
180
|
+
}
|
|
181
|
+
|
|
153
182
|
protected override updated(cp: PropertyValues<this>): void {
|
|
154
183
|
super.updated(cp)
|
|
155
184
|
|
|
@@ -228,9 +257,57 @@ export default class BaseButton extends UiElement {
|
|
|
228
257
|
})
|
|
229
258
|
this.dispatchEvent(e)
|
|
230
259
|
}
|
|
260
|
+
this.handlePopoverAction()
|
|
231
261
|
this.endPress({ cancelled: false, actionData: { event: e } })
|
|
232
262
|
}
|
|
233
263
|
|
|
264
|
+
protected setupPopoverTarget(): void {
|
|
265
|
+
const id = this.popoverTarget
|
|
266
|
+
if (!id) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
const element = findElementInShadowRoots(id, this)
|
|
270
|
+
if (!element) {
|
|
271
|
+
return
|
|
272
|
+
}
|
|
273
|
+
// A regular button first sets its value to the popover target ID,
|
|
274
|
+
this.value = id
|
|
275
|
+
// create an anchor association with the popover target
|
|
276
|
+
if (!this.id) {
|
|
277
|
+
this.id = nanoid()
|
|
278
|
+
}
|
|
279
|
+
const anchorName = `--anchor-${this.id}`
|
|
280
|
+
this.style.setProperty('anchor-name', anchorName)
|
|
281
|
+
element.style.setProperty('position-anchor', anchorName)
|
|
282
|
+
this.setAttribute('aria-details', id)
|
|
283
|
+
this.setAttribute('aria-controls', id)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* When the button has a popover target, this method toggles the popover
|
|
288
|
+
* visibility by finding the element in the shadow roots and calling its
|
|
289
|
+
* `togglePopover` method.
|
|
290
|
+
*/
|
|
291
|
+
protected handlePopoverAction(): void {
|
|
292
|
+
const id = this.popoverTarget
|
|
293
|
+
if (!id) {
|
|
294
|
+
return
|
|
295
|
+
}
|
|
296
|
+
const element = findElementInShadowRoots(id, this)
|
|
297
|
+
if (!element) {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
const action = this.popoverTargetAction || 'toggle'
|
|
301
|
+
if (action === 'hide') {
|
|
302
|
+
element.hidePopover()
|
|
303
|
+
} else if (action === 'show') {
|
|
304
|
+
element.showPopover()
|
|
305
|
+
} else {
|
|
306
|
+
element.togglePopover()
|
|
307
|
+
}
|
|
308
|
+
element.focus()
|
|
309
|
+
}
|
|
310
|
+
|
|
234
311
|
protected handleSubmit(): void {
|
|
235
312
|
const { name, value, type, disabled, form } = this
|
|
236
313
|
if (!form || !type || disabled) {
|
|
@@ -62,10 +62,10 @@ export default class UiIcon extends LitElement {
|
|
|
62
62
|
* @return Template result for an icon
|
|
63
63
|
*/
|
|
64
64
|
override render(): TemplateResult {
|
|
65
|
-
const { hasIcon, iconValue
|
|
65
|
+
const { hasIcon, iconValue } = this
|
|
66
66
|
if (!hasIcon) {
|
|
67
67
|
return html`<slot></slot>`
|
|
68
68
|
}
|
|
69
|
-
return html`${
|
|
69
|
+
return html`${iconValue}`
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -354,16 +354,16 @@ export default class UiList extends LitElement {
|
|
|
354
354
|
* @param item The UiListItem that is selected.
|
|
355
355
|
* @returns True when the event was canceled.
|
|
356
356
|
*/
|
|
357
|
-
notifySelect(item: UiListItem): boolean {
|
|
358
|
-
const
|
|
359
|
-
if (
|
|
357
|
+
notifySelect(item: UiListItem, index?: number): boolean {
|
|
358
|
+
const resolvedIndex = index ?? this.items.indexOf(item)
|
|
359
|
+
if (resolvedIndex === -1) {
|
|
360
360
|
return false
|
|
361
361
|
}
|
|
362
362
|
const event = new CustomEvent<UiListSelection>('select', {
|
|
363
363
|
cancelable: true,
|
|
364
364
|
detail: {
|
|
365
365
|
item,
|
|
366
|
-
index,
|
|
366
|
+
index: resolvedIndex,
|
|
367
367
|
},
|
|
368
368
|
})
|
|
369
369
|
this.dispatchEvent(event)
|
|
@@ -34,26 +34,8 @@ export default css`
|
|
|
34
34
|
|
|
35
35
|
.surface {
|
|
36
36
|
height: inherit;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
display: flex;
|
|
40
|
-
align-items: center;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.surface,
|
|
44
|
-
.content {
|
|
45
|
-
width: 100%;
|
|
46
|
-
}
|
|
37
|
+
box-sizing: border-box;
|
|
47
38
|
|
|
48
|
-
.container {
|
|
49
|
-
position: absolute;
|
|
50
|
-
inset: 0;
|
|
51
|
-
z-index: 1;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.content {
|
|
55
|
-
position: relative;
|
|
56
|
-
z-index: 2;
|
|
57
39
|
display: flex;
|
|
58
40
|
align-items: center;
|
|
59
41
|
overflow: hidden;
|
|
@@ -64,7 +46,7 @@ export default css`
|
|
|
64
46
|
z-index: 3;
|
|
65
47
|
}
|
|
66
48
|
|
|
67
|
-
:host([image='video']) .
|
|
49
|
+
:host([image='video']) .surface {
|
|
68
50
|
/* The spec says the right padding is 24px but counting from the checkbox check border.
|
|
69
51
|
This does not include spacing presented by the checkbox itself (18 box, 40px state layer)
|
|
70
52
|
*/
|
|
@@ -5,7 +5,6 @@ import { UiElement } from '../../UiElement.js'
|
|
|
5
5
|
import { BeginPressConfig, EndPressConfig } from '../../../controllers/ActionController.js'
|
|
6
6
|
import UiRipple from '../../ripple/internals/ripple.js'
|
|
7
7
|
import { setDisabled } from '../../../lib/disabled.js'
|
|
8
|
-
import { ripple } from '../../effects/rippleDirective.js'
|
|
9
8
|
|
|
10
9
|
import '@material/web/focus/md-focus-ring.js'
|
|
11
10
|
import '../../ripple/ui-ripple.js'
|
|
@@ -196,20 +195,12 @@ export default class UiListItem extends UiElement {
|
|
|
196
195
|
}
|
|
197
196
|
|
|
198
197
|
protected override render(): TemplateResult {
|
|
199
|
-
const { pressed = false } = this
|
|
200
198
|
const surfaceClasses = classMap({
|
|
201
199
|
surface: true,
|
|
202
|
-
pressed,
|
|
203
200
|
})
|
|
204
|
-
|
|
205
201
|
return html`
|
|
206
|
-
|
|
207
|
-
<div class="${surfaceClasses}" ${
|
|
208
|
-
<div class="container"></div>
|
|
209
|
-
<div class="state"></div>
|
|
210
|
-
<div class="content">${this.renderStart()} ${this.renderBody()} ${this.renderEnd()}</div>
|
|
211
|
-
${this.renderRipple()}
|
|
212
|
-
</div>
|
|
202
|
+
${this.renderFocusRing()} ${this.renderRipple()}
|
|
203
|
+
<div class="${surfaceClasses}">${this.renderStart()} ${this.renderBody()} ${this.renderEnd()}</div>
|
|
213
204
|
`
|
|
214
205
|
}
|
|
215
206
|
|
|
@@ -218,6 +209,15 @@ export default class UiListItem extends UiElement {
|
|
|
218
209
|
return html`<ui-ripple class="ripple" ?disabled="${disabled || isStatic}"></ui-ripple>`
|
|
219
210
|
}
|
|
220
211
|
|
|
212
|
+
protected renderFocusRing(): TemplateResult {
|
|
213
|
+
return html`<md-focus-ring
|
|
214
|
+
part="focus-ring"
|
|
215
|
+
class="focus-ring"
|
|
216
|
+
.control="${this as HTMLElement}"
|
|
217
|
+
inward
|
|
218
|
+
></md-focus-ring>`
|
|
219
|
+
}
|
|
220
|
+
|
|
221
221
|
protected renderStart(): TemplateResult {
|
|
222
222
|
return html`<div class="start">
|
|
223
223
|
<slot name="start" @slotchange=${this.handleSlotChange}></slot>
|