@openremote/or-mwc-components 1.8.0-snapshot.20250725074716 → 1.8.0-snapshot.20250725120000
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 +32 -32
- package/build.gradle +19 -19
- package/custom-elements.json +4 -4
- package/lib/or-mwc-dialog.js +329 -76
- package/lib/or-mwc-drawer.js +114 -10
- package/lib/or-mwc-input.js +1760 -439
- package/lib/or-mwc-list.js +283 -71
- package/lib/or-mwc-menu.js +237 -45
- package/lib/or-mwc-snackbar.d.ts +1 -1
- package/lib/or-mwc-snackbar.js +141 -17
- package/lib/or-mwc-table.js +685 -245
- package/lib/or-mwc-tabs.js +173 -53
- package/lib/style.js +125 -121
- package/package.json +5 -5
- package/rspack.config.js +7 -7
- package/src/or-mwc-dialog.ts +374 -374
- package/src/or-mwc-drawer.ts +100 -100
- package/src/or-mwc-input.ts +1876 -1876
- package/src/or-mwc-list.ts +335 -335
- package/src/or-mwc-menu.ts +279 -279
- package/src/or-mwc-snackbar.ts +157 -157
- package/src/or-mwc-table.ts +712 -712
- package/src/or-mwc-tabs.ts +175 -175
- package/src/style.ts +125 -125
- package/tsconfig.json +15 -15
- package/tsconfig.tsbuildinfo +1 -1
package/src/or-mwc-list.ts
CHANGED
|
@@ -1,335 +1,335 @@
|
|
|
1
|
-
import {
|
|
2
|
-
css,
|
|
3
|
-
html,
|
|
4
|
-
LitElement,
|
|
5
|
-
PropertyValues,
|
|
6
|
-
TemplateResult,
|
|
7
|
-
unsafeCSS
|
|
8
|
-
} from "lit";
|
|
9
|
-
import {customElement, property, query} from "lit/decorators.js";
|
|
10
|
-
import {styleMap} from "lit/directives/style-map.js";
|
|
11
|
-
import {ifDefined} from "lit/directives/if-defined.js";
|
|
12
|
-
import {MDCList, MDCListActionEvent} from "@material/list";
|
|
13
|
-
import { DefaultColor8, DefaultColor4, Util } from "@openremote/core";
|
|
14
|
-
import "@openremote/or-translate";
|
|
15
|
-
import { i18next } from "@openremote/or-translate";
|
|
16
|
-
const listStyle = require("@material/list/dist/mdc.list.css");
|
|
17
|
-
const checkboxStyle = require("@material/checkbox/dist/mdc.checkbox.css");
|
|
18
|
-
|
|
19
|
-
export {MDCListActionEvent};
|
|
20
|
-
|
|
21
|
-
export interface ListItem {
|
|
22
|
-
icon?: string;
|
|
23
|
-
trailingIcon?: string;
|
|
24
|
-
text?: string;
|
|
25
|
-
translate?: boolean;
|
|
26
|
-
secondaryText?: string;
|
|
27
|
-
value: any;
|
|
28
|
-
data?: any;
|
|
29
|
-
styleMap?: {[style: string]: string};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export class OrMwcListChangedEvent extends CustomEvent<ListItem[]> {
|
|
33
|
-
|
|
34
|
-
public static readonly NAME = "or-mwc-list-changed";
|
|
35
|
-
|
|
36
|
-
constructor(items: ListItem[]) {
|
|
37
|
-
super(OrMwcListChangedEvent.NAME, {
|
|
38
|
-
detail: items,
|
|
39
|
-
bubbles: true,
|
|
40
|
-
composed: true
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
declare global {
|
|
45
|
-
export interface HTMLElementEventMap {
|
|
46
|
-
[OrMwcListChangedEvent.NAME]: OrMwcListChangedEvent;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export enum ListType {
|
|
51
|
-
PLAIN = "PLAIN",
|
|
52
|
-
SELECT = "SELECT",
|
|
53
|
-
RADIO = "RADIO",
|
|
54
|
-
MULTI_CHECKBOX = "MULTI_CHECKBOX",
|
|
55
|
-
MULTI_TICK = "MULTI_TICK"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export type ListGroupItem = {
|
|
59
|
-
heading: string;
|
|
60
|
-
list: TemplateResult;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export function createListGroup(lists: ListGroupItem[]) {
|
|
64
|
-
return html`
|
|
65
|
-
<div class="mdc-list-group">
|
|
66
|
-
${lists.map((list) => {
|
|
67
|
-
return html`
|
|
68
|
-
<h3 class="mdc-list-group__subheader">${list.heading}</h3>
|
|
69
|
-
${list.list}
|
|
70
|
-
`
|
|
71
|
-
})}
|
|
72
|
-
</div>
|
|
73
|
-
`;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function getListTemplate(type: ListType, content: TemplateResult, isTwoLine?: boolean, role?: string, actionHandler?: (ev: MDCListActionEvent) => void): TemplateResult {
|
|
77
|
-
|
|
78
|
-
role = role || "listbox";
|
|
79
|
-
|
|
80
|
-
switch (type) {
|
|
81
|
-
case ListType.RADIO:
|
|
82
|
-
role = "radiogroup";
|
|
83
|
-
break;
|
|
84
|
-
case ListType.MULTI_CHECKBOX:
|
|
85
|
-
role = "group";
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return html`
|
|
90
|
-
<ul id="list" class="mdc-list${isTwoLine ? " mdc-list--two-line" : ""}" role="${ifDefined(role)}" @MDCList:action="${(ev: MDCListActionEvent) => actionHandler && actionHandler(ev)}" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
|
91
|
-
${content}
|
|
92
|
-
</ul>
|
|
93
|
-
`;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function getItemTemplate(item: ListItem | null, index: number, selectedValues: any[], type: ListType, translate?: boolean, itemClickCallback?: (e: MouseEvent, item: ListItem) => void): TemplateResult {
|
|
97
|
-
|
|
98
|
-
if (item === null) {
|
|
99
|
-
// Divider
|
|
100
|
-
return html`<li role="separator" class="mdc-list-divider"></li>`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const listItem = item as ListItem;
|
|
104
|
-
const multiSelect = type === ListType.MULTI_CHECKBOX || type === ListType.MULTI_TICK;
|
|
105
|
-
const value = listItem.value;
|
|
106
|
-
const isSelected = type !== ListType.PLAIN && selectedValues.length > 0 && selectedValues.some((v) => v === value);
|
|
107
|
-
const text = listItem.text !== undefined ? listItem.text : listItem.value;
|
|
108
|
-
const secondaryText = listItem.secondaryText;
|
|
109
|
-
let role: string | undefined = "menuitem";
|
|
110
|
-
let ariaSelected: string | undefined;
|
|
111
|
-
let ariaChecked: string | undefined;
|
|
112
|
-
let tabIndex: string | undefined;
|
|
113
|
-
let textTemplate: TemplateResult | string = ``;
|
|
114
|
-
let leftTemplate: TemplateResult | string = ``;
|
|
115
|
-
let rightTemplate: TemplateResult | string = ``;
|
|
116
|
-
let icon = listItem.icon;
|
|
117
|
-
let selectedClassName = "mdc-list-item--selected";
|
|
118
|
-
translate = translate || item.translate;
|
|
119
|
-
|
|
120
|
-
if (multiSelect && type === ListType.MULTI_TICK) {
|
|
121
|
-
icon = isSelected ? "checkbox-marked" : "checkbox-blank-outline";
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (type === ListType.MULTI_TICK || icon) {
|
|
125
|
-
leftTemplate = html`
|
|
126
|
-
<span class="mdc-list-item__graphic">
|
|
127
|
-
<or-icon icon="${icon}"></or-icon>
|
|
128
|
-
</span>
|
|
129
|
-
`;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (listItem.trailingIcon) {
|
|
133
|
-
rightTemplate = html`
|
|
134
|
-
<span class="mdc-list-item__meta" aria-hidden="true">
|
|
135
|
-
<or-icon icon="${listItem.trailingIcon}"></or-icon>
|
|
136
|
-
</span>
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
switch (type) {
|
|
141
|
-
case ListType.SELECT:
|
|
142
|
-
ariaSelected = isSelected ? "true" : "false";
|
|
143
|
-
tabIndex = isSelected || ((!selectedValues || selectedValues.length === 0) && index === 0) ? "0" : undefined;
|
|
144
|
-
role = "option";
|
|
145
|
-
break;
|
|
146
|
-
case ListType.RADIO:
|
|
147
|
-
ariaChecked = isSelected ? "true" : "false";
|
|
148
|
-
role = "radio";
|
|
149
|
-
leftTemplate = html`
|
|
150
|
-
<span class="mdc-list-item__graphic">
|
|
151
|
-
<div class="mdc-radio">
|
|
152
|
-
<input class="mdc-radio__native-control" id="radio-item-${index+1}" type="radio" value="${value}" />
|
|
153
|
-
<div class="mdc-radio__background">
|
|
154
|
-
<div class="mdc-radio__outer-circle"></div>
|
|
155
|
-
<div class="mdc-radio__inner-circle"></div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</span>
|
|
159
|
-
`;
|
|
160
|
-
break;
|
|
161
|
-
case ListType.MULTI_CHECKBOX:
|
|
162
|
-
ariaChecked = isSelected ? "true" : "false";
|
|
163
|
-
role = "checkbox";
|
|
164
|
-
leftTemplate = html`
|
|
165
|
-
<div class="mdc-checkbox">
|
|
166
|
-
<input type="checkbox" class="mdc-checkbox__native-control" />
|
|
167
|
-
<div class="mdc-checkbox__background">
|
|
168
|
-
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
|
|
169
|
-
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
|
|
170
|
-
</svg>
|
|
171
|
-
<div class="mdc-checkbox__mixedmark"></div>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
`;
|
|
175
|
-
break;
|
|
176
|
-
case ListType.MULTI_TICK:
|
|
177
|
-
ariaChecked = isSelected ? "true" : "false";
|
|
178
|
-
selectedClassName = "mdc-list-item--selected";
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (text) {
|
|
183
|
-
if (secondaryText !== undefined) {
|
|
184
|
-
textTemplate = html`
|
|
185
|
-
<span class="mdc-list-item__text">
|
|
186
|
-
<span class="mdc-list-item__primary-text">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</span>
|
|
187
|
-
<span class="mdc-list-item__secondary-text">${translate && !!secondaryText ? html`<or-translate value="${secondaryText}"></or-translate>` : secondaryText}</span>
|
|
188
|
-
</span>
|
|
189
|
-
`;
|
|
190
|
-
} else {
|
|
191
|
-
if (type === ListType.RADIO) {
|
|
192
|
-
textTemplate = html`<label class="mdc-list-item__text" for="radio-item-${index+1}">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</label>`;
|
|
193
|
-
} else {
|
|
194
|
-
textTemplate = html`<span class="mdc-list-item__text" title="${translate && !!text ? i18next.t(text) : text}">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</span>`;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return html`
|
|
200
|
-
<li @click="${(e: MouseEvent) => { itemClickCallback && itemClickCallback(e, item)}}" style="${listItem.styleMap ? styleMap(listItem.styleMap) : ""}" class="mdc-list-item ${isSelected ? selectedClassName : ""}" role="${ifDefined(role)}" tabindex="${ifDefined(tabIndex)}" aria-checked="${ifDefined(ariaChecked)}" aria-selected="${ifDefined(ariaSelected)}" data-value="${value}">
|
|
201
|
-
<span class="mdc-list-item__ripple"></span>
|
|
202
|
-
${leftTemplate}
|
|
203
|
-
${textTemplate}
|
|
204
|
-
${rightTemplate}
|
|
205
|
-
</li>
|
|
206
|
-
`;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// language=CSS
|
|
210
|
-
const style = css`
|
|
211
|
-
:host {
|
|
212
|
-
white-space: nowrap;
|
|
213
|
-
--internal-or-mwc-input-color: var(--or-mwc-input-color, var(--or-app-color4, ${unsafeCSS(DefaultColor4)}));
|
|
214
|
-
--internal-or-mwc-input-text-color: var(--or-mwc-input-text-color, var(--or-app-color8, ${unsafeCSS(DefaultColor8)}));
|
|
215
|
-
|
|
216
|
-
--mdc-theme-primary: var(--internal-or-mwc-input-color);
|
|
217
|
-
--mdc-theme-on-primary: var(--internal-or-mwc-input-text-color);
|
|
218
|
-
--mdc-theme-secondary: var(--internal-or-mwc-input-color);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.mdc-list-item__graphic {
|
|
222
|
-
margin-right: 16px;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
a {
|
|
226
|
-
text-decoration: none;
|
|
227
|
-
color: rgba(0, 0, 0, 0.87);
|
|
228
|
-
}
|
|
229
|
-
`;
|
|
230
|
-
|
|
231
|
-
@customElement("or-mwc-list")
|
|
232
|
-
export class OrMwcList extends LitElement {
|
|
233
|
-
|
|
234
|
-
static get styles() {
|
|
235
|
-
return [
|
|
236
|
-
css`${unsafeCSS(listStyle)}`,
|
|
237
|
-
css`${unsafeCSS(checkboxStyle)}`,
|
|
238
|
-
style
|
|
239
|
-
];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
@property({type: Array})
|
|
243
|
-
public listItems?: (ListItem | null)[];
|
|
244
|
-
|
|
245
|
-
@property({type: Array})
|
|
246
|
-
public values?: string[] | string;
|
|
247
|
-
|
|
248
|
-
@property({type: String, attribute: true})
|
|
249
|
-
public type: ListType = ListType.SELECT;
|
|
250
|
-
|
|
251
|
-
@query("#wrapper")
|
|
252
|
-
protected _wrapperElem!: HTMLElement;
|
|
253
|
-
|
|
254
|
-
@query("#list")
|
|
255
|
-
protected _mdcElem!: HTMLElement;
|
|
256
|
-
|
|
257
|
-
protected _mdcComponent?: MDCList;
|
|
258
|
-
|
|
259
|
-
constructor() {
|
|
260
|
-
super();
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
disconnectedCallback(): void {
|
|
264
|
-
super.disconnectedCallback();
|
|
265
|
-
if (this._mdcComponent) {
|
|
266
|
-
this._mdcComponent.destroy();
|
|
267
|
-
this._mdcComponent = undefined;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
protected shouldUpdate(_changedProperties: PropertyValues): boolean {
|
|
272
|
-
if (this._mdcComponent && _changedProperties.has("values")) {
|
|
273
|
-
if (!Util.objectsEqual(this.values, _changedProperties.get("values"))) {
|
|
274
|
-
const vals = this.values ? Array.isArray(this.values) ? this.values : [this.values] : [];
|
|
275
|
-
this.setSelectedItems(this.values && this.listItems ? this.listItems.filter((li) => li && vals?.includes(li.value)) as ListItem[] : undefined);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
protected render() {
|
|
283
|
-
const content = !this.listItems ? html`` : html`${this.listItems.map((listItem, index) => getItemTemplate(listItem, index, (Array.isArray(this.values) ? this.values : this.values ? [this.values] : []), this.type))}`;
|
|
284
|
-
const isTwoLine = this.listItems && this.listItems.some((item) => item && !!item.secondaryText);
|
|
285
|
-
return getListTemplate(this.type, content, isTwoLine, undefined, (ev) => this._onSelected(ev));
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
protected firstUpdated(_changedProperties: PropertyValues): void {
|
|
289
|
-
super.firstUpdated(_changedProperties);
|
|
290
|
-
if (this._mdcElem) {
|
|
291
|
-
this._mdcComponent = new MDCList(this._mdcElem);
|
|
292
|
-
if (this.type === ListType.SELECT || this.type === ListType.RADIO) {
|
|
293
|
-
this._mdcComponent.singleSelection = true;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
public get selectedItems(): ListItem[] {
|
|
299
|
-
if (!this._mdcComponent) {
|
|
300
|
-
return [];
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const selectedIndexes = Array.isArray(this._mdcComponent.selectedIndex) ? this._mdcComponent.selectedIndex : [this._mdcComponent.selectedIndex];
|
|
304
|
-
const items = this.listItems ? this.listItems.filter((item) => item !== null) as ListItem[] : [];
|
|
305
|
-
return selectedIndexes.map((index) => items![index]);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
public setSelectedItems(items: ListItem | ListItem[] | string | string[] | undefined) {
|
|
309
|
-
if (!this._mdcComponent || !this.listItems) {
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
if (!items) {
|
|
313
|
-
this._mdcComponent.selectedIndex = -1;
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const itemArr = (!Array.isArray(items) ? [items] : items).map((item) => typeof(item) === "string" ? item : item.value);
|
|
318
|
-
const listItems = this.listItems.filter((item) => item !== null) as ListItem[];
|
|
319
|
-
|
|
320
|
-
const indexes = listItems.reduce((indexes, listItem, index) => {
|
|
321
|
-
if (listItem && itemArr.includes(listItem.value)) {
|
|
322
|
-
indexes.push(index);
|
|
323
|
-
}
|
|
324
|
-
return indexes;
|
|
325
|
-
}, [] as number[]);
|
|
326
|
-
|
|
327
|
-
this._mdcComponent.selectedIndex = this.type === ListType.MULTI_CHECKBOX ? indexes : indexes.length >= 1 ? indexes[0] : -1;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
protected _onSelected(ev: MDCListActionEvent) {
|
|
331
|
-
this.values = this.selectedItems.map((item) => item.value!);
|
|
332
|
-
ev.stopPropagation();
|
|
333
|
-
this.dispatchEvent(new OrMwcListChangedEvent(this.selectedItems));
|
|
334
|
-
}
|
|
335
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
html,
|
|
4
|
+
LitElement,
|
|
5
|
+
PropertyValues,
|
|
6
|
+
TemplateResult,
|
|
7
|
+
unsafeCSS
|
|
8
|
+
} from "lit";
|
|
9
|
+
import {customElement, property, query} from "lit/decorators.js";
|
|
10
|
+
import {styleMap} from "lit/directives/style-map.js";
|
|
11
|
+
import {ifDefined} from "lit/directives/if-defined.js";
|
|
12
|
+
import {MDCList, MDCListActionEvent} from "@material/list";
|
|
13
|
+
import { DefaultColor8, DefaultColor4, Util } from "@openremote/core";
|
|
14
|
+
import "@openremote/or-translate";
|
|
15
|
+
import { i18next } from "@openremote/or-translate";
|
|
16
|
+
const listStyle = require("@material/list/dist/mdc.list.css");
|
|
17
|
+
const checkboxStyle = require("@material/checkbox/dist/mdc.checkbox.css");
|
|
18
|
+
|
|
19
|
+
export {MDCListActionEvent};
|
|
20
|
+
|
|
21
|
+
export interface ListItem {
|
|
22
|
+
icon?: string;
|
|
23
|
+
trailingIcon?: string;
|
|
24
|
+
text?: string;
|
|
25
|
+
translate?: boolean;
|
|
26
|
+
secondaryText?: string;
|
|
27
|
+
value: any;
|
|
28
|
+
data?: any;
|
|
29
|
+
styleMap?: {[style: string]: string};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class OrMwcListChangedEvent extends CustomEvent<ListItem[]> {
|
|
33
|
+
|
|
34
|
+
public static readonly NAME = "or-mwc-list-changed";
|
|
35
|
+
|
|
36
|
+
constructor(items: ListItem[]) {
|
|
37
|
+
super(OrMwcListChangedEvent.NAME, {
|
|
38
|
+
detail: items,
|
|
39
|
+
bubbles: true,
|
|
40
|
+
composed: true
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
declare global {
|
|
45
|
+
export interface HTMLElementEventMap {
|
|
46
|
+
[OrMwcListChangedEvent.NAME]: OrMwcListChangedEvent;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export enum ListType {
|
|
51
|
+
PLAIN = "PLAIN",
|
|
52
|
+
SELECT = "SELECT",
|
|
53
|
+
RADIO = "RADIO",
|
|
54
|
+
MULTI_CHECKBOX = "MULTI_CHECKBOX",
|
|
55
|
+
MULTI_TICK = "MULTI_TICK"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type ListGroupItem = {
|
|
59
|
+
heading: string;
|
|
60
|
+
list: TemplateResult;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export function createListGroup(lists: ListGroupItem[]) {
|
|
64
|
+
return html`
|
|
65
|
+
<div class="mdc-list-group">
|
|
66
|
+
${lists.map((list) => {
|
|
67
|
+
return html`
|
|
68
|
+
<h3 class="mdc-list-group__subheader">${list.heading}</h3>
|
|
69
|
+
${list.list}
|
|
70
|
+
`
|
|
71
|
+
})}
|
|
72
|
+
</div>
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function getListTemplate(type: ListType, content: TemplateResult, isTwoLine?: boolean, role?: string, actionHandler?: (ev: MDCListActionEvent) => void): TemplateResult {
|
|
77
|
+
|
|
78
|
+
role = role || "listbox";
|
|
79
|
+
|
|
80
|
+
switch (type) {
|
|
81
|
+
case ListType.RADIO:
|
|
82
|
+
role = "radiogroup";
|
|
83
|
+
break;
|
|
84
|
+
case ListType.MULTI_CHECKBOX:
|
|
85
|
+
role = "group";
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return html`
|
|
90
|
+
<ul id="list" class="mdc-list${isTwoLine ? " mdc-list--two-line" : ""}" role="${ifDefined(role)}" @MDCList:action="${(ev: MDCListActionEvent) => actionHandler && actionHandler(ev)}" aria-hidden="true" aria-orientation="vertical" tabindex="-1">
|
|
91
|
+
${content}
|
|
92
|
+
</ul>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getItemTemplate(item: ListItem | null, index: number, selectedValues: any[], type: ListType, translate?: boolean, itemClickCallback?: (e: MouseEvent, item: ListItem) => void): TemplateResult {
|
|
97
|
+
|
|
98
|
+
if (item === null) {
|
|
99
|
+
// Divider
|
|
100
|
+
return html`<li role="separator" class="mdc-list-divider"></li>`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const listItem = item as ListItem;
|
|
104
|
+
const multiSelect = type === ListType.MULTI_CHECKBOX || type === ListType.MULTI_TICK;
|
|
105
|
+
const value = listItem.value;
|
|
106
|
+
const isSelected = type !== ListType.PLAIN && selectedValues.length > 0 && selectedValues.some((v) => v === value);
|
|
107
|
+
const text = listItem.text !== undefined ? listItem.text : listItem.value;
|
|
108
|
+
const secondaryText = listItem.secondaryText;
|
|
109
|
+
let role: string | undefined = "menuitem";
|
|
110
|
+
let ariaSelected: string | undefined;
|
|
111
|
+
let ariaChecked: string | undefined;
|
|
112
|
+
let tabIndex: string | undefined;
|
|
113
|
+
let textTemplate: TemplateResult | string = ``;
|
|
114
|
+
let leftTemplate: TemplateResult | string = ``;
|
|
115
|
+
let rightTemplate: TemplateResult | string = ``;
|
|
116
|
+
let icon = listItem.icon;
|
|
117
|
+
let selectedClassName = "mdc-list-item--selected";
|
|
118
|
+
translate = translate || item.translate;
|
|
119
|
+
|
|
120
|
+
if (multiSelect && type === ListType.MULTI_TICK) {
|
|
121
|
+
icon = isSelected ? "checkbox-marked" : "checkbox-blank-outline";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (type === ListType.MULTI_TICK || icon) {
|
|
125
|
+
leftTemplate = html`
|
|
126
|
+
<span class="mdc-list-item__graphic">
|
|
127
|
+
<or-icon icon="${icon}"></or-icon>
|
|
128
|
+
</span>
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (listItem.trailingIcon) {
|
|
133
|
+
rightTemplate = html`
|
|
134
|
+
<span class="mdc-list-item__meta" aria-hidden="true">
|
|
135
|
+
<or-icon icon="${listItem.trailingIcon}"></or-icon>
|
|
136
|
+
</span>
|
|
137
|
+
`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
switch (type) {
|
|
141
|
+
case ListType.SELECT:
|
|
142
|
+
ariaSelected = isSelected ? "true" : "false";
|
|
143
|
+
tabIndex = isSelected || ((!selectedValues || selectedValues.length === 0) && index === 0) ? "0" : undefined;
|
|
144
|
+
role = "option";
|
|
145
|
+
break;
|
|
146
|
+
case ListType.RADIO:
|
|
147
|
+
ariaChecked = isSelected ? "true" : "false";
|
|
148
|
+
role = "radio";
|
|
149
|
+
leftTemplate = html`
|
|
150
|
+
<span class="mdc-list-item__graphic">
|
|
151
|
+
<div class="mdc-radio">
|
|
152
|
+
<input class="mdc-radio__native-control" id="radio-item-${index+1}" type="radio" value="${value}" />
|
|
153
|
+
<div class="mdc-radio__background">
|
|
154
|
+
<div class="mdc-radio__outer-circle"></div>
|
|
155
|
+
<div class="mdc-radio__inner-circle"></div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</span>
|
|
159
|
+
`;
|
|
160
|
+
break;
|
|
161
|
+
case ListType.MULTI_CHECKBOX:
|
|
162
|
+
ariaChecked = isSelected ? "true" : "false";
|
|
163
|
+
role = "checkbox";
|
|
164
|
+
leftTemplate = html`
|
|
165
|
+
<div class="mdc-checkbox">
|
|
166
|
+
<input type="checkbox" class="mdc-checkbox__native-control" />
|
|
167
|
+
<div class="mdc-checkbox__background">
|
|
168
|
+
<svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24">
|
|
169
|
+
<path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
|
|
170
|
+
</svg>
|
|
171
|
+
<div class="mdc-checkbox__mixedmark"></div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
`;
|
|
175
|
+
break;
|
|
176
|
+
case ListType.MULTI_TICK:
|
|
177
|
+
ariaChecked = isSelected ? "true" : "false";
|
|
178
|
+
selectedClassName = "mdc-list-item--selected";
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (text) {
|
|
183
|
+
if (secondaryText !== undefined) {
|
|
184
|
+
textTemplate = html`
|
|
185
|
+
<span class="mdc-list-item__text">
|
|
186
|
+
<span class="mdc-list-item__primary-text">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</span>
|
|
187
|
+
<span class="mdc-list-item__secondary-text">${translate && !!secondaryText ? html`<or-translate value="${secondaryText}"></or-translate>` : secondaryText}</span>
|
|
188
|
+
</span>
|
|
189
|
+
`;
|
|
190
|
+
} else {
|
|
191
|
+
if (type === ListType.RADIO) {
|
|
192
|
+
textTemplate = html`<label class="mdc-list-item__text" for="radio-item-${index+1}">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</label>`;
|
|
193
|
+
} else {
|
|
194
|
+
textTemplate = html`<span class="mdc-list-item__text" title="${translate && !!text ? i18next.t(text) : text}">${translate && !!text ? html`<or-translate value="${text}"></or-translate>` : text}</span>`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return html`
|
|
200
|
+
<li @click="${(e: MouseEvent) => { itemClickCallback && itemClickCallback(e, item)}}" style="${listItem.styleMap ? styleMap(listItem.styleMap) : ""}" class="mdc-list-item ${isSelected ? selectedClassName : ""}" role="${ifDefined(role)}" tabindex="${ifDefined(tabIndex)}" aria-checked="${ifDefined(ariaChecked)}" aria-selected="${ifDefined(ariaSelected)}" data-value="${value}">
|
|
201
|
+
<span class="mdc-list-item__ripple"></span>
|
|
202
|
+
${leftTemplate}
|
|
203
|
+
${textTemplate}
|
|
204
|
+
${rightTemplate}
|
|
205
|
+
</li>
|
|
206
|
+
`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// language=CSS
|
|
210
|
+
const style = css`
|
|
211
|
+
:host {
|
|
212
|
+
white-space: nowrap;
|
|
213
|
+
--internal-or-mwc-input-color: var(--or-mwc-input-color, var(--or-app-color4, ${unsafeCSS(DefaultColor4)}));
|
|
214
|
+
--internal-or-mwc-input-text-color: var(--or-mwc-input-text-color, var(--or-app-color8, ${unsafeCSS(DefaultColor8)}));
|
|
215
|
+
|
|
216
|
+
--mdc-theme-primary: var(--internal-or-mwc-input-color);
|
|
217
|
+
--mdc-theme-on-primary: var(--internal-or-mwc-input-text-color);
|
|
218
|
+
--mdc-theme-secondary: var(--internal-or-mwc-input-color);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.mdc-list-item__graphic {
|
|
222
|
+
margin-right: 16px;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
a {
|
|
226
|
+
text-decoration: none;
|
|
227
|
+
color: rgba(0, 0, 0, 0.87);
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
|
|
231
|
+
@customElement("or-mwc-list")
|
|
232
|
+
export class OrMwcList extends LitElement {
|
|
233
|
+
|
|
234
|
+
static get styles() {
|
|
235
|
+
return [
|
|
236
|
+
css`${unsafeCSS(listStyle)}`,
|
|
237
|
+
css`${unsafeCSS(checkboxStyle)}`,
|
|
238
|
+
style
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@property({type: Array})
|
|
243
|
+
public listItems?: (ListItem | null)[];
|
|
244
|
+
|
|
245
|
+
@property({type: Array})
|
|
246
|
+
public values?: string[] | string;
|
|
247
|
+
|
|
248
|
+
@property({type: String, attribute: true})
|
|
249
|
+
public type: ListType = ListType.SELECT;
|
|
250
|
+
|
|
251
|
+
@query("#wrapper")
|
|
252
|
+
protected _wrapperElem!: HTMLElement;
|
|
253
|
+
|
|
254
|
+
@query("#list")
|
|
255
|
+
protected _mdcElem!: HTMLElement;
|
|
256
|
+
|
|
257
|
+
protected _mdcComponent?: MDCList;
|
|
258
|
+
|
|
259
|
+
constructor() {
|
|
260
|
+
super();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
disconnectedCallback(): void {
|
|
264
|
+
super.disconnectedCallback();
|
|
265
|
+
if (this._mdcComponent) {
|
|
266
|
+
this._mdcComponent.destroy();
|
|
267
|
+
this._mdcComponent = undefined;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
protected shouldUpdate(_changedProperties: PropertyValues): boolean {
|
|
272
|
+
if (this._mdcComponent && _changedProperties.has("values")) {
|
|
273
|
+
if (!Util.objectsEqual(this.values, _changedProperties.get("values"))) {
|
|
274
|
+
const vals = this.values ? Array.isArray(this.values) ? this.values : [this.values] : [];
|
|
275
|
+
this.setSelectedItems(this.values && this.listItems ? this.listItems.filter((li) => li && vals?.includes(li.value)) as ListItem[] : undefined);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
protected render() {
|
|
283
|
+
const content = !this.listItems ? html`` : html`${this.listItems.map((listItem, index) => getItemTemplate(listItem, index, (Array.isArray(this.values) ? this.values : this.values ? [this.values] : []), this.type))}`;
|
|
284
|
+
const isTwoLine = this.listItems && this.listItems.some((item) => item && !!item.secondaryText);
|
|
285
|
+
return getListTemplate(this.type, content, isTwoLine, undefined, (ev) => this._onSelected(ev));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
protected firstUpdated(_changedProperties: PropertyValues): void {
|
|
289
|
+
super.firstUpdated(_changedProperties);
|
|
290
|
+
if (this._mdcElem) {
|
|
291
|
+
this._mdcComponent = new MDCList(this._mdcElem);
|
|
292
|
+
if (this.type === ListType.SELECT || this.type === ListType.RADIO) {
|
|
293
|
+
this._mdcComponent.singleSelection = true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public get selectedItems(): ListItem[] {
|
|
299
|
+
if (!this._mdcComponent) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const selectedIndexes = Array.isArray(this._mdcComponent.selectedIndex) ? this._mdcComponent.selectedIndex : [this._mdcComponent.selectedIndex];
|
|
304
|
+
const items = this.listItems ? this.listItems.filter((item) => item !== null) as ListItem[] : [];
|
|
305
|
+
return selectedIndexes.map((index) => items![index]);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
public setSelectedItems(items: ListItem | ListItem[] | string | string[] | undefined) {
|
|
309
|
+
if (!this._mdcComponent || !this.listItems) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (!items) {
|
|
313
|
+
this._mdcComponent.selectedIndex = -1;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const itemArr = (!Array.isArray(items) ? [items] : items).map((item) => typeof(item) === "string" ? item : item.value);
|
|
318
|
+
const listItems = this.listItems.filter((item) => item !== null) as ListItem[];
|
|
319
|
+
|
|
320
|
+
const indexes = listItems.reduce((indexes, listItem, index) => {
|
|
321
|
+
if (listItem && itemArr.includes(listItem.value)) {
|
|
322
|
+
indexes.push(index);
|
|
323
|
+
}
|
|
324
|
+
return indexes;
|
|
325
|
+
}, [] as number[]);
|
|
326
|
+
|
|
327
|
+
this._mdcComponent.selectedIndex = this.type === ListType.MULTI_CHECKBOX ? indexes : indexes.length >= 1 ? indexes[0] : -1;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
protected _onSelected(ev: MDCListActionEvent) {
|
|
331
|
+
this.values = this.selectedItems.map((item) => item.value!);
|
|
332
|
+
ev.stopPropagation();
|
|
333
|
+
this.dispatchEvent(new OrMwcListChangedEvent(this.selectedItems));
|
|
334
|
+
}
|
|
335
|
+
}
|