@watermarkinsights/ripple 3.3.0-0 → 3.3.1
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/dist/cjs/{global-9bd085c7.js → global-605fbf89.js} +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/ripple.cjs.js +2 -2
- package/dist/cjs/wm-action-menu_2.cjs.entry.js +34 -6
- package/dist/cjs/wm-button.cjs.entry.js +20 -21
- package/dist/cjs/wm-chart.cjs.entry.js +18 -9
- package/dist/cjs/wm-option_2.cjs.entry.js +26 -4
- package/dist/cjs/wm-tag-input.cjs.entry.js +4 -4
- package/dist/cjs/wm-timepicker.cjs.entry.js +6 -4
- package/dist/collection/components/wm-action-menu/wm-action-menu.js +31 -6
- package/dist/collection/components/wm-button/wm-button.js +20 -21
- package/dist/collection/components/wm-chart/wm-chart.css +14 -0
- package/dist/collection/components/wm-chart/wm-chart.js +35 -8
- package/dist/collection/components/wm-menuitem/wm-menuitem.js +35 -2
- package/dist/collection/components/wm-option/wm-option.js +28 -0
- package/dist/collection/components/wm-select/wm-select.js +47 -22
- package/dist/collection/components/wm-tag-input/wm-tag-input.js +4 -4
- package/dist/collection/components/wm-timepicker/wm-timepicker.js +7 -5
- package/dist/collection/global/__mocks__/functions.js +1 -0
- package/dist/esm/{global-11e6d295.js → global-dbc19362.js} +1 -1
- package/dist/esm/loader.js +2 -2
- package/dist/esm/ripple.js +2 -2
- package/dist/esm/wm-action-menu_2.entry.js +34 -6
- package/dist/esm/wm-button.entry.js +20 -21
- package/dist/esm/wm-chart.entry.js +18 -9
- package/dist/esm/wm-option_2.entry.js +26 -4
- package/dist/esm/wm-tag-input.entry.js +4 -4
- package/dist/esm/wm-timepicker.entry.js +6 -4
- package/dist/ripple/p-042d6449.entry.js +1 -0
- package/dist/ripple/p-053e8324.entry.js +1 -0
- package/dist/ripple/p-1a934627.entry.js +1 -0
- package/dist/ripple/p-80c1162f.js +1 -0
- package/dist/ripple/p-af4b2ea9.entry.js +1 -0
- package/dist/ripple/p-b03382ea.entry.js +1 -0
- package/dist/ripple/p-ec5db255.entry.js +1 -0
- package/dist/ripple/ripple.esm.js +1 -1
- package/dist/types/components/wm-action-menu/wm-action-menu.d.ts +4 -2
- package/dist/types/components/wm-button/wm-button.d.ts +1 -0
- package/dist/types/components/wm-chart/wm-chart.d.ts +2 -1
- package/dist/types/components/wm-menuitem/wm-menuitem.d.ts +4 -0
- package/dist/types/components/wm-option/wm-option.d.ts +4 -0
- package/dist/types/components/wm-select/wm-select.d.ts +3 -1
- package/dist/types/components/wm-tag-input/wm-tag-input.d.ts +1 -1
- package/dist/types/components/wm-timepicker/wm-timepicker.d.ts +2 -2
- package/dist/types/components.d.ts +4 -0
- package/dist/types/global/__mocks__/functions.d.ts +1 -0
- package/package.json +1 -1
- package/dist/ripple/p-14b37f79.entry.js +0 -1
- package/dist/ripple/p-27c6abf9.entry.js +0 -1
- package/dist/ripple/p-336c0ed7.entry.js +0 -1
- package/dist/ripple/p-6933edc6.entry.js +0 -1
- package/dist/ripple/p-73ebc395.js +0 -1
- package/dist/ripple/p-c31c4d52.entry.js +0 -1
- package/dist/ripple/p-d079df21.entry.js +0 -1
|
@@ -46,7 +46,7 @@ export class ActionMenu {
|
|
|
46
46
|
this.close();
|
|
47
47
|
this.wmButtonEl.focus();
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
handleClick(ev) {
|
|
50
50
|
const isElOrChild = ev.target === this.el || this.el.contains(ev.target);
|
|
51
51
|
if (!isElOrChild && this.isExpanded) {
|
|
52
52
|
this.close();
|
|
@@ -70,6 +70,24 @@ export class ActionMenu {
|
|
|
70
70
|
break;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
handleMenuitemBlur(ev) {
|
|
74
|
+
const toElOrChild = ev.detail.relatedTarget === this.el || this.el.contains(ev.detail.relatedTarget);
|
|
75
|
+
// if the Menuitem is blurred to something other than the component, emit a blur event with the appropriate relatedTarget
|
|
76
|
+
// keeps our component's blur events accurate, and closes when focusing browser address bar
|
|
77
|
+
if (!toElOrChild) {
|
|
78
|
+
const event = new CustomEvent("blur");
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
event.relatedTarget = ev.detail.relatedTarget;
|
|
81
|
+
this.el.dispatchEvent(event);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
handleButtonBlur(ev) {
|
|
85
|
+
const toElOrChild = ev.relatedTarget === this.el || this.el.contains(ev.relatedTarget);
|
|
86
|
+
if (toElOrChild) {
|
|
87
|
+
// do not emit a blur event when opening the dropdown and focusing the Menuitems
|
|
88
|
+
ev.stopPropagation();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
73
91
|
componentWillLoad() {
|
|
74
92
|
this.uid = this.el.id ? this.el.id : generateId();
|
|
75
93
|
this.el.focus = function () {
|
|
@@ -128,7 +146,7 @@ export class ActionMenu {
|
|
|
128
146
|
window.requestAnimationFrame(() => this.focusFirstItem());
|
|
129
147
|
}
|
|
130
148
|
}
|
|
131
|
-
close() {
|
|
149
|
+
close(returnFocus = true) {
|
|
132
150
|
this.isExpanded = false;
|
|
133
151
|
this.childItems.forEach((i) => (i.focused = false));
|
|
134
152
|
window.setTimeout(() => {
|
|
@@ -141,7 +159,8 @@ export class ActionMenu {
|
|
|
141
159
|
// is not visible anymore, so we need to wait for the transition to
|
|
142
160
|
// finish and the hidden class to be applied.
|
|
143
161
|
// also checking if focus stayed on the menuitem
|
|
144
|
-
if (
|
|
162
|
+
if (returnFocus &&
|
|
163
|
+
(document.activeElement.tagName === "BODY" || document.activeElement.tagName === "WM-MENUITEM")) {
|
|
145
164
|
this.wmButtonEl.focus();
|
|
146
165
|
}
|
|
147
166
|
}, 250);
|
|
@@ -198,9 +217,9 @@ export class ActionMenu {
|
|
|
198
217
|
return null;
|
|
199
218
|
}
|
|
200
219
|
render() {
|
|
201
|
-
return (h(Host,
|
|
220
|
+
return (h(Host, { onBlur: () => this.close(false) },
|
|
202
221
|
h("div", { class: getTextDir() },
|
|
203
|
-
h("wm-button", { "button-type": `${this.tempActionMenuType}only`, tooltip: this.tooltip, "label-for-identical-buttons": this.labelForIdenticalButtons, icon: this.tempActionMenuType === "icon" ? "f1d9" : "", id: `menubtn-${this.uid}`, onClick: () => (this.isExpanded ? this.close() : this.open()), disabled: this.disabled, ref: (el) => (this.wmButtonEl = el), "tooltip-position": this.tooltipPosition || this.horizontalPosition, "aria-haspopup": "true", "aria-expanded": this.isExpanded ? "true" : "false", "aria-controls": `menu-${this.uid}` }, this.buttonText),
|
|
222
|
+
h("wm-button", { "button-type": `${this.tempActionMenuType}only`, tooltip: this.tooltip, "label-for-identical-buttons": this.labelForIdenticalButtons, icon: this.tempActionMenuType === "icon" ? "f1d9" : "", id: `menubtn-${this.uid}`, onClick: () => (this.isExpanded ? this.close() : this.open()), onBlur: (ev) => this.handleButtonBlur(ev), disabled: this.disabled, ref: (el) => (this.wmButtonEl = el), "tooltip-position": this.tooltipPosition || this.horizontalPosition, "aria-haspopup": "true", "aria-expanded": this.isExpanded ? "true" : "false", "aria-controls": `menu-${this.uid}` }, this.buttonText),
|
|
204
223
|
h("div", { class: `dropdown ${this.openUp ? "open-up" : ""} ${this.horizontalPosition} ${this.isExpanded ? "open" : ""} hidden`, id: `menu-${this.uid}`, tabindex: -1, role: "menu", ref: (el) => (this.itemsEl = el) },
|
|
205
224
|
h("slot", null)))));
|
|
206
225
|
}
|
|
@@ -415,7 +434,7 @@ export class ActionMenu {
|
|
|
415
434
|
"passive": false
|
|
416
435
|
}, {
|
|
417
436
|
"name": "click",
|
|
418
|
-
"method": "
|
|
437
|
+
"method": "handleClick",
|
|
419
438
|
"target": "document",
|
|
420
439
|
"capture": false,
|
|
421
440
|
"passive": false
|
|
@@ -425,6 +444,12 @@ export class ActionMenu {
|
|
|
425
444
|
"target": undefined,
|
|
426
445
|
"capture": false,
|
|
427
446
|
"passive": false
|
|
447
|
+
}, {
|
|
448
|
+
"name": "wmMenuitemBlurred",
|
|
449
|
+
"method": "handleMenuitemBlur",
|
|
450
|
+
"target": undefined,
|
|
451
|
+
"capture": false,
|
|
452
|
+
"passive": false
|
|
428
453
|
}, {
|
|
429
454
|
"name": "wmLetterPressed",
|
|
430
455
|
"method": "findAndFocusItem",
|
|
@@ -31,6 +31,9 @@ export class Button {
|
|
|
31
31
|
// tooltip is only rendered for icononly and navigational types, or if the button text is truncated
|
|
32
32
|
return this.tempButtonType === "icononly" || this.tempButtonType === "navigational" || this.isTruncated;
|
|
33
33
|
}
|
|
34
|
+
get tooltipEl() {
|
|
35
|
+
return document.getElementById("wm-tooltip");
|
|
36
|
+
}
|
|
34
37
|
toggleTabbingOn() {
|
|
35
38
|
this.isTabbing = true;
|
|
36
39
|
}
|
|
@@ -127,23 +130,20 @@ export class Button {
|
|
|
127
130
|
}
|
|
128
131
|
showTooltip() {
|
|
129
132
|
if (this.hasTooltip) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this.tooltipVisible = true;
|
|
145
|
-
}, 500);
|
|
146
|
-
}
|
|
133
|
+
// set tooltip text
|
|
134
|
+
this.tooltipEl.textContent = this.isTruncated ? this.el.textContent : this.tooltip;
|
|
135
|
+
// adjust position in case there is no space to place the tooltip where specified via prop
|
|
136
|
+
this.adjustedTooltipPosition = adjustTooltipPosition(this.tooltipPosition, this.buttonEl, this.tooltipEl);
|
|
137
|
+
this.positionTooltip(this.adjustedTooltipPosition, this.tooltipEl);
|
|
138
|
+
this.tooltipEl.style.transitionDelay = "500ms";
|
|
139
|
+
this.tooltipEl.style.opacity = "1";
|
|
140
|
+
// tooltip is only visible after the transition delay.
|
|
141
|
+
// This also fixes an issue for keyboard users:
|
|
142
|
+
// if they tab to a button out of screen bounds, the page scrolls
|
|
143
|
+
// and hideTooltip() would be triggered before the tooltip would show
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
this.tooltipVisible = true;
|
|
146
|
+
}, 500);
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
positionTooltip(tPos, tooltipEl) {
|
|
@@ -177,10 +177,9 @@ export class Button {
|
|
|
177
177
|
tooltipEl.style.left = (horizontalPos / 16).toString() + "rem";
|
|
178
178
|
}
|
|
179
179
|
hideTooltip() {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
tooltipEl.style.
|
|
183
|
-
tooltipEl.style.opacity = "0";
|
|
180
|
+
if (this.hasTooltip) {
|
|
181
|
+
this.tooltipEl.style.transitionDelay = "0s";
|
|
182
|
+
this.tooltipEl.style.opacity = "0";
|
|
184
183
|
this.tooltipVisible = false;
|
|
185
184
|
}
|
|
186
185
|
}
|
|
@@ -223,6 +223,7 @@
|
|
|
223
223
|
}
|
|
224
224
|
.component-wrapper.bar1 .bar-wrapper .single-perc {
|
|
225
225
|
width: 4rem;
|
|
226
|
+
flex: none;
|
|
226
227
|
}
|
|
227
228
|
.component-wrapper.bar1 .bar-wrapper .chart-svg {
|
|
228
229
|
flex: 1;
|
|
@@ -238,6 +239,7 @@
|
|
|
238
239
|
text-align: left;
|
|
239
240
|
padding-right: 1.25rem;
|
|
240
241
|
padding-bottom: 0;
|
|
242
|
+
flex: none;
|
|
241
243
|
}
|
|
242
244
|
.component-wrapper.bar1 .completion-message {
|
|
243
245
|
right: 5.75rem;
|
|
@@ -309,6 +311,18 @@
|
|
|
309
311
|
transform: translate(4px, 24px);
|
|
310
312
|
text-anchor: middle;
|
|
311
313
|
}
|
|
314
|
+
.component-wrapper.left-label {
|
|
315
|
+
flex-direction: row;
|
|
316
|
+
}
|
|
317
|
+
.component-wrapper.left-label .label {
|
|
318
|
+
width: 12rem;
|
|
319
|
+
padding-right: 1.25rem;
|
|
320
|
+
flex: none;
|
|
321
|
+
align-self: flex-end;
|
|
322
|
+
min-height: 30px;
|
|
323
|
+
display: flex;
|
|
324
|
+
align-items: center;
|
|
325
|
+
}
|
|
312
326
|
|
|
313
327
|
/* KEYBOARD USERS */
|
|
314
328
|
:host(:focus) {
|
|
@@ -6,6 +6,9 @@ export class Chart {
|
|
|
6
6
|
this.chartType = "doughnut1";
|
|
7
7
|
this.showLegend = true;
|
|
8
8
|
this.notStartedColor = false;
|
|
9
|
+
// left labels are a temporary solution for the lack of a stacked bar chart and is undocumented
|
|
10
|
+
// it only works with bar4 and should be used without a legend
|
|
11
|
+
this.labelPosition = "top";
|
|
9
12
|
this.isTabbing = false;
|
|
10
13
|
this.uid = generateId();
|
|
11
14
|
this.slicesData = [];
|
|
@@ -86,11 +89,13 @@ export class Chart {
|
|
|
86
89
|
},
|
|
87
90
|
};
|
|
88
91
|
/* LIFECYCLE METHODS + EVENTS FROM THE CHILDREN */
|
|
89
|
-
this.
|
|
90
|
-
this.
|
|
91
|
-
|
|
92
|
+
this.debouncedResize = debounce(async () => {
|
|
93
|
+
if (this.chartType === "hybrid") {
|
|
94
|
+
this.setHybridType();
|
|
95
|
+
await this.getData();
|
|
96
|
+
}
|
|
92
97
|
forceUpdate(this.el);
|
|
93
|
-
},
|
|
98
|
+
}, 10);
|
|
94
99
|
this.debouncedSliceUpdate = debounce(async () => {
|
|
95
100
|
await this.getData();
|
|
96
101
|
forceUpdate(this.el);
|
|
@@ -338,8 +343,9 @@ export class Chart {
|
|
|
338
343
|
}
|
|
339
344
|
}
|
|
340
345
|
handleResize() {
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
// handling resizing only needs to occur for bar charts (hybrid included)
|
|
347
|
+
if (this.chartType.includes("bar") || this.chartType === "hybrid") {
|
|
348
|
+
this.debouncedResize();
|
|
343
349
|
}
|
|
344
350
|
}
|
|
345
351
|
async componentWillLoad() {
|
|
@@ -444,13 +450,16 @@ export class Chart {
|
|
|
444
450
|
default:
|
|
445
451
|
y = "0";
|
|
446
452
|
}
|
|
453
|
+
// adjusting the width of the rect slightly ensures repainting on rerenders
|
|
454
|
+
// important for updating width accurate when resizing the page
|
|
455
|
+
const randomTinyNumber = Math.random() / 1000;
|
|
447
456
|
return (h("g", { class: "barcontainer" },
|
|
448
457
|
h("style", null, ` #${s.id} {
|
|
449
458
|
fill:${s.color};
|
|
450
459
|
x: ${`${this.amountToPercent(s.offset, false)}%`};
|
|
451
460
|
y: ${y};
|
|
452
461
|
height: 30px;
|
|
453
|
-
width: calc(${this.amountToPercent(s.amount, false)}%${idx !== this.slicesData.length - 1 ? " - 2px" : ""});
|
|
462
|
+
width: calc(${this.amountToPercent(s.amount, false) + randomTinyNumber}%${idx !== this.slicesData.length - 1 ? " - 2px" : ""});
|
|
454
463
|
}`),
|
|
455
464
|
h("rect", { id: s.id, onClick: (ev) => {
|
|
456
465
|
if (this.popoverEl) {
|
|
@@ -537,7 +546,7 @@ export class Chart {
|
|
|
537
546
|
id: "chart.interactiveChart",
|
|
538
547
|
defaultMessage: "Interactive chart. Use arrow keys to browse elements, press Tab to exit.",
|
|
539
548
|
}), tabindex: "0" },
|
|
540
|
-
h("div", { class: `component-wrapper ${this.getType()}` },
|
|
549
|
+
h("div", { class: `component-wrapper ${this.getType()} ${this.labelPosition === "left" && this.chartType === "bar4" ? "left-label" : ""}` },
|
|
541
550
|
h("label", { class: "label", id: `label-${this.uid}`, htmlFor: `graphic-${this.uid}` },
|
|
542
551
|
h("span", { class: "label-text" }, this.label),
|
|
543
552
|
this.subinfo ? h("span", { class: "subinfo" }, this.subinfo) : ""),
|
|
@@ -694,6 +703,24 @@ export class Chart {
|
|
|
694
703
|
"attribute": "not-started-color",
|
|
695
704
|
"reflect": false,
|
|
696
705
|
"defaultValue": "false"
|
|
706
|
+
},
|
|
707
|
+
"labelPosition": {
|
|
708
|
+
"type": "string",
|
|
709
|
+
"mutable": false,
|
|
710
|
+
"complexType": {
|
|
711
|
+
"original": "\"left\" | \"top\"",
|
|
712
|
+
"resolved": "\"left\" | \"top\"",
|
|
713
|
+
"references": {}
|
|
714
|
+
},
|
|
715
|
+
"required": false,
|
|
716
|
+
"optional": false,
|
|
717
|
+
"docs": {
|
|
718
|
+
"tags": [],
|
|
719
|
+
"text": ""
|
|
720
|
+
},
|
|
721
|
+
"attribute": "label-position",
|
|
722
|
+
"reflect": false,
|
|
723
|
+
"defaultValue": "\"top\""
|
|
697
724
|
}
|
|
698
725
|
}; }
|
|
699
726
|
static get states() { return {
|
|
@@ -16,6 +16,9 @@ export class Menuitem {
|
|
|
16
16
|
this.isKeying = false;
|
|
17
17
|
}
|
|
18
18
|
handleKeydown(ev) {
|
|
19
|
+
const modifierKeyUsed = ev.altKey || ev.ctrlKey || ev.metaKey;
|
|
20
|
+
const isSingleCharacter = /^.$/.test(ev.key);
|
|
21
|
+
const isCharacterEntry = isSingleCharacter && !modifierKeyUsed;
|
|
19
22
|
switch (ev.key) {
|
|
20
23
|
case "ArrowUp":
|
|
21
24
|
ev.preventDefault();
|
|
@@ -48,8 +51,10 @@ export class Menuitem {
|
|
|
48
51
|
this.wmTabKeyPressed.emit();
|
|
49
52
|
break;
|
|
50
53
|
default:
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
if (isCharacterEntry) {
|
|
55
|
+
ev.preventDefault();
|
|
56
|
+
this.wmLetterPressed.emit(ev.key);
|
|
57
|
+
}
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
handleClick() {
|
|
@@ -57,6 +62,9 @@ export class Menuitem {
|
|
|
57
62
|
this.wmMenuitemClicked.emit();
|
|
58
63
|
}
|
|
59
64
|
}
|
|
65
|
+
handleBlur(ev) {
|
|
66
|
+
this.wmMenuitemBlurred.emit({ relatedTarget: ev.relatedTarget });
|
|
67
|
+
}
|
|
60
68
|
setOnClick() {
|
|
61
69
|
if (this.disabled && this.el.onclick) {
|
|
62
70
|
this.onClickFunc = this.el.onclick;
|
|
@@ -365,6 +373,25 @@ export class Menuitem {
|
|
|
365
373
|
"resolved": "any",
|
|
366
374
|
"references": {}
|
|
367
375
|
}
|
|
376
|
+
}, {
|
|
377
|
+
"method": "wmMenuitemBlurred",
|
|
378
|
+
"name": "wmMenuitemBlurred",
|
|
379
|
+
"bubbles": true,
|
|
380
|
+
"cancelable": true,
|
|
381
|
+
"composed": true,
|
|
382
|
+
"docs": {
|
|
383
|
+
"tags": [],
|
|
384
|
+
"text": ""
|
|
385
|
+
},
|
|
386
|
+
"complexType": {
|
|
387
|
+
"original": "{ relatedTarget: EventTarget | null }",
|
|
388
|
+
"resolved": "{ relatedTarget: EventTarget | null; }",
|
|
389
|
+
"references": {
|
|
390
|
+
"EventTarget": {
|
|
391
|
+
"location": "global"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
368
395
|
}]; }
|
|
369
396
|
static get elementRef() { return "el"; }
|
|
370
397
|
static get watchers() { return [{
|
|
@@ -407,5 +434,11 @@ export class Menuitem {
|
|
|
407
434
|
"target": undefined,
|
|
408
435
|
"capture": false,
|
|
409
436
|
"passive": false
|
|
437
|
+
}, {
|
|
438
|
+
"name": "blur",
|
|
439
|
+
"method": "handleBlur",
|
|
440
|
+
"target": undefined,
|
|
441
|
+
"capture": false,
|
|
442
|
+
"passive": false
|
|
410
443
|
}]; }
|
|
411
444
|
}
|
|
@@ -65,6 +65,9 @@ export class Option {
|
|
|
65
65
|
// the parent wm-select is in charge of the actual selection
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
handleBlur(ev) {
|
|
69
|
+
this.wmOptionBlurred.emit({ relatedTarget: ev.relatedTarget });
|
|
70
|
+
}
|
|
68
71
|
syncAriaSelected() {
|
|
69
72
|
// this function only keeps the aria-selected attr in sync with the selected prop
|
|
70
73
|
// all the logic for selecting / deselecting happens in the parent wm-select
|
|
@@ -363,6 +366,25 @@ export class Option {
|
|
|
363
366
|
"resolved": "string",
|
|
364
367
|
"references": {}
|
|
365
368
|
}
|
|
369
|
+
}, {
|
|
370
|
+
"method": "wmOptionBlurred",
|
|
371
|
+
"name": "wmOptionBlurred",
|
|
372
|
+
"bubbles": true,
|
|
373
|
+
"cancelable": true,
|
|
374
|
+
"composed": true,
|
|
375
|
+
"docs": {
|
|
376
|
+
"tags": [],
|
|
377
|
+
"text": ""
|
|
378
|
+
},
|
|
379
|
+
"complexType": {
|
|
380
|
+
"original": "{ relatedTarget: EventTarget | null }",
|
|
381
|
+
"resolved": "{ relatedTarget: EventTarget | null; }",
|
|
382
|
+
"references": {
|
|
383
|
+
"EventTarget": {
|
|
384
|
+
"location": "global"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
366
388
|
}]; }
|
|
367
389
|
static get elementRef() { return "el"; }
|
|
368
390
|
static get watchers() { return [{
|
|
@@ -390,5 +412,11 @@ export class Option {
|
|
|
390
412
|
"target": undefined,
|
|
391
413
|
"capture": false,
|
|
392
414
|
"passive": false
|
|
415
|
+
}, {
|
|
416
|
+
"name": "blur",
|
|
417
|
+
"method": "handleBlur",
|
|
418
|
+
"target": undefined,
|
|
419
|
+
"capture": false,
|
|
420
|
+
"passive": false
|
|
393
421
|
}]; }
|
|
394
422
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h, Component, Element, Event, Listen, Prop, State, Watch } from "@stencil/core";
|
|
1
|
+
import { h, Component, Element, Event, Listen, Prop, State, Watch, Host } from "@stencil/core";
|
|
2
2
|
import { forceUpdate } from "@stencil/core";
|
|
3
3
|
import { generateId, getTextDir, shouldOpenUp, intl } from "../../global/functions";
|
|
4
4
|
export class Select {
|
|
@@ -80,12 +80,30 @@ export class Select {
|
|
|
80
80
|
closePopupOnEscape() {
|
|
81
81
|
this.close();
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
handleOptionBlur(ev) {
|
|
84
|
+
const toElOrChild = ev.detail.relatedTarget === this.el || this.el.contains(ev.detail.relatedTarget);
|
|
85
|
+
// if the Option is blurred to something other than the component emit a blur event with the appropriate relatedTarget
|
|
86
|
+
// keeps our component's blur events accurate, and closes when focusing browser address bar
|
|
87
|
+
if (!toElOrChild) {
|
|
88
|
+
const event = new CustomEvent("blur");
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
event.relatedTarget = ev.detail.relatedTarget;
|
|
91
|
+
this.el.dispatchEvent(event);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
handleClick(ev) {
|
|
84
95
|
const isElOrChild = ev.target === this.el || this.el.contains(ev.target);
|
|
85
96
|
if (!isElOrChild && this.isExpanded) {
|
|
86
97
|
this.close();
|
|
87
98
|
}
|
|
88
99
|
}
|
|
100
|
+
handleButtonBlur(ev) {
|
|
101
|
+
const toElOrChild = ev.relatedTarget === this.el || this.el.contains(ev.relatedTarget);
|
|
102
|
+
if (toElOrChild) {
|
|
103
|
+
// do not emit a blur event when opening the dropdown and focusing the Options
|
|
104
|
+
ev.stopPropagation();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
89
107
|
handleKey(ev) {
|
|
90
108
|
switch (ev.keyCode) {
|
|
91
109
|
// Arrow down
|
|
@@ -347,25 +365,26 @@ export class Select {
|
|
|
347
365
|
onClick: () => (this.isExpanded ? this.close() : this.open()),
|
|
348
366
|
onBlur: () => this.handleComponentBlur(),
|
|
349
367
|
};
|
|
350
|
-
return (h(
|
|
351
|
-
h("div", { class:
|
|
352
|
-
h("
|
|
353
|
-
this.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
h("span", { class: "
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
h("
|
|
360
|
-
h("
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
h("
|
|
368
|
-
|
|
368
|
+
return (h(Host, { onBlur: () => this.close(false) },
|
|
369
|
+
h("div", { class: `wrapper ${getTextDir()} label-${this.labelPosition} ${this.invalid || this.errorMessage ? "invalid" : ""}` },
|
|
370
|
+
h("div", { class: "label-wrapper" },
|
|
371
|
+
h("label", { class: "label", id: `label-${this.uid}`, htmlFor: `selectbtn-${this.uid}` },
|
|
372
|
+
this.label,
|
|
373
|
+
// we can't use aria-required or required attributes because it's invalid on the elements we're using (button controlling a listbox)
|
|
374
|
+
this.requiredField ? (h("span", { class: "required" },
|
|
375
|
+
h("span", { class: "sr-only" }, this.requiredMessage),
|
|
376
|
+
h("span", { "aria-hidden": "true" }, "*"))) : (""))),
|
|
377
|
+
h("div", { class: "dropdown" },
|
|
378
|
+
h("button", Object.assign({}, buttonProps, { class: `displayedoption ${this.isTabbing ? "user-is-tabbing" : ""}`, ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev) }),
|
|
379
|
+
h("span", { class: this.selectedItems.length > 0 && this.selectedItems.filter((x) => x.subinfo).length > 0
|
|
380
|
+
? "overflowcontrol hassubinfo"
|
|
381
|
+
: "overflowcontrol" },
|
|
382
|
+
h("span", { class: "button-text" }, this.renderButtonText()),
|
|
383
|
+
this.renderSubinfo()),
|
|
384
|
+
this.renderOverflowCount()),
|
|
385
|
+
h("div", { class: `options ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, id: `list-${this.uid}`, tabindex: -1, role: "listbox", "aria-multiselectable": this.multiple ? "true" : null, "aria-labelledby": `label-${this.uid}`, ref: (el) => (this.optionsEl = el) },
|
|
386
|
+
h("slot", null)),
|
|
387
|
+
this.renderErrorContainer()))));
|
|
369
388
|
}
|
|
370
389
|
static get is() { return "wm-select"; }
|
|
371
390
|
static get encapsulation() { return "shadow"; }
|
|
@@ -670,9 +689,15 @@ export class Select {
|
|
|
670
689
|
"target": undefined,
|
|
671
690
|
"capture": false,
|
|
672
691
|
"passive": false
|
|
692
|
+
}, {
|
|
693
|
+
"name": "wmOptionBlurred",
|
|
694
|
+
"method": "handleOptionBlur",
|
|
695
|
+
"target": undefined,
|
|
696
|
+
"capture": false,
|
|
697
|
+
"passive": false
|
|
673
698
|
}, {
|
|
674
699
|
"name": "click",
|
|
675
|
-
"method": "
|
|
700
|
+
"method": "handleClick",
|
|
676
701
|
"target": "document",
|
|
677
702
|
"capture": true,
|
|
678
703
|
"passive": false
|
|
@@ -52,14 +52,14 @@ export class TagInput {
|
|
|
52
52
|
description: "An alert for adding a tag that is already present.",
|
|
53
53
|
}, { tagName: tag });
|
|
54
54
|
}
|
|
55
|
-
generateTagCounterMessage() {
|
|
55
|
+
generateTagCounterMessage(x, y) {
|
|
56
56
|
return intl.formatMessage({
|
|
57
57
|
id: "tagInput.tagsAddedCounter",
|
|
58
58
|
defaultMessage: "Tags added: {x, number}/{y, number}",
|
|
59
59
|
description: "For the user to understand how close they are to the tag limit.",
|
|
60
60
|
}, {
|
|
61
|
-
x:
|
|
62
|
-
y:
|
|
61
|
+
x: x,
|
|
62
|
+
y: y,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
componentWillLoad() {
|
|
@@ -533,7 +533,7 @@ export class TagInput {
|
|
|
533
533
|
if (this.maxTags) {
|
|
534
534
|
return (h("div", { class: "lower-row" },
|
|
535
535
|
h("div", { id: "max-tags" },
|
|
536
|
-
this.generateTagCounterMessage(),
|
|
536
|
+
this.generateTagCounterMessage(this.tagsList.length, this.maxTags),
|
|
537
537
|
this.tagsList.length >= this.maxTags && h("span", { class: "sr-only" }, this.maxTagsReachedMessage))));
|
|
538
538
|
}
|
|
539
539
|
}
|
|
@@ -271,7 +271,7 @@ export class Timepicker {
|
|
|
271
271
|
}
|
|
272
272
|
});
|
|
273
273
|
}
|
|
274
|
-
close() {
|
|
274
|
+
close(returnFocus = true) {
|
|
275
275
|
this.isExpanded = false;
|
|
276
276
|
window.setTimeout(() => {
|
|
277
277
|
this.optionsEl.classList.add("hidden");
|
|
@@ -279,7 +279,9 @@ export class Timepicker {
|
|
|
279
279
|
// Delay is necessary for screenreader to get new expanded state before focus
|
|
280
280
|
// window.requestAnimationFrame is probably enough, but since we are already using setTimeout it may as well be here
|
|
281
281
|
// also UX wise, it makes sense for the button to only be focused after the animation is complete
|
|
282
|
-
|
|
282
|
+
if (returnFocus) {
|
|
283
|
+
this.buttonEl.focus();
|
|
284
|
+
}
|
|
283
285
|
}, 150);
|
|
284
286
|
}
|
|
285
287
|
focusOption(item) {
|
|
@@ -358,7 +360,7 @@ export class Timepicker {
|
|
|
358
360
|
this.setDropdownPosition("center", this.selectedOption);
|
|
359
361
|
}
|
|
360
362
|
}
|
|
361
|
-
|
|
363
|
+
handleInputBlur(ev) {
|
|
362
364
|
// do not validate if clicking to an element that should prevent validation (e.g. close button on modal)
|
|
363
365
|
const shouldPreventValidation = this.preventValidation && isRelatedTarget(ev, this.preventValidation);
|
|
364
366
|
if (!shouldPreventValidation) {
|
|
@@ -370,14 +372,14 @@ export class Timepicker {
|
|
|
370
372
|
return this.times.map((time, index) => (h("li", { id: `option${index + 1}`, role: "option", "aria-selected": time === "09:00" ? "true" : false, onClick: () => this.handleOptionClick(time) }, this.formatToDisplay(time))));
|
|
371
373
|
}
|
|
372
374
|
render() {
|
|
373
|
-
return (h(Host, { id: this.uid, invalid: !!this.displayedErrorMessage ? "true" : null },
|
|
375
|
+
return (h(Host, { id: this.uid, invalid: !!this.displayedErrorMessage ? "true" : null, onBlur: () => this.close(false) },
|
|
374
376
|
h("div", { class: `wrapper label-${this.labelPosition} ${!!this.displayedErrorMessage ? "invalid" : ""}`, ref: (t) => (this.tpWrapper = t) },
|
|
375
377
|
h("div", { class: "label-wrapper" }, this.labelPosition !== "none" && (h("label", { id: `label-${this.uid}`, class: "label", htmlFor: `time-input-${this.uid}` },
|
|
376
378
|
this.label,
|
|
377
379
|
this.requiredField && (h("span", { class: "required", "aria-hidden": "true" }, "*"))))),
|
|
378
380
|
h("div", null,
|
|
379
381
|
h("div", { class: "inner-wrapper" },
|
|
380
|
-
h("input", { id: `time-input-${this.uid}`, "aria-label": this.label, "aria-describedby": `error-${this.uid}`, ref: (el) => (this.inputEl = el), onBlur: (ev) => this.
|
|
382
|
+
h("input", { id: `time-input-${this.uid}`, "aria-label": this.label, "aria-describedby": `error-${this.uid}`, ref: (el) => (this.inputEl = el), onBlur: (ev) => this.handleInputBlur(ev), onInput: () => this.handleInput(), disabled: this.disabled, required: this.requiredField, placeholder: this.timeFormat, autocomplete: "off", onFocus: () => this.tpWrapper.classList.add("focus") }),
|
|
381
383
|
h("button", { id: `btn-${this.uid}`, class: this.isTabbing ? "user-is-tabbing" : "", ref: (el) => (this.buttonEl = el), disabled: this.disabled, "aria-controls": `list-${this.uid}`, "aria-expanded": this.isExpanded ? "true" : "false", "aria-label": this.buttonAriaLabel, "aria-describedby": `time-input-${this.uid}`, onClick: () => (this.isExpanded ? this.close() : this.open()) },
|
|
382
384
|
h("span", { class: "clock" })),
|
|
383
385
|
h("ul", { class: `options ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, id: `list-${this.uid}`, role: "listbox", "aria-labelledby": `label-${this.uid}`, "aria-describedby": this.isExpanded ? "collapsed" : null, ref: (el) => (this.optionsEl = el) }, this.renderOptions())),
|