@watermarkinsights/ripple 5.7.0-1 → 5.7.0-11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/cjs/{global-d996c674.js → global-0515f81a.js} +1 -1
  2. package/dist/cjs/index-e86c28b6.js +8 -12
  3. package/dist/cjs/loader.cjs.js +2 -2
  4. package/dist/cjs/priv-option-list.cjs.entry.js +39 -20
  5. package/dist/cjs/ripple.cjs.js +2 -2
  6. package/dist/cjs/wm-modal-pss_3.cjs.entry.js +213 -0
  7. package/dist/cjs/{wm-modal.cjs.entry.js → wm-modal_3.cjs.entry.js} +73 -0
  8. package/dist/cjs/wm-nested-select.cjs.entry.js +77 -32
  9. package/dist/cjs/wm-optgroup.cjs.entry.js +7 -1
  10. package/dist/cjs/wm-option_2.cjs.entry.js +10 -12
  11. package/dist/collection/collection-manifest.json +17 -5
  12. package/dist/collection/components/selects/priv-option-list/priv-option-list.css +31 -6
  13. package/dist/collection/components/selects/priv-option-list/priv-option-list.js +65 -35
  14. package/dist/collection/components/selects/wm-nested-select/wm-nested-select.css +11 -5
  15. package/dist/collection/components/selects/wm-nested-select/wm-nested-select.js +107 -36
  16. package/dist/collection/components/selects/wm-optgroup/wm-optgroup.js +24 -1
  17. package/dist/collection/components/selects/wm-option/wm-option.css +1 -1
  18. package/dist/collection/components/selects/wm-select/wm-select.css +5 -8
  19. package/dist/collection/components/selects/wm-select/wm-select.js +12 -13
  20. package/dist/collection/components/wm-modal-pss/wm-modal-pss-footer.css +61 -0
  21. package/dist/collection/components/wm-modal-pss/wm-modal-pss-footer.js +138 -0
  22. package/dist/collection/components/wm-modal-pss/wm-modal-pss-header.css +55 -0
  23. package/dist/collection/components/wm-modal-pss/wm-modal-pss-header.js +81 -0
  24. package/dist/collection/components/wm-modal-pss/wm-modal-pss.css +134 -0
  25. package/dist/collection/components/wm-modal-pss/wm-modal-pss.js +361 -0
  26. package/dist/esm/{global-dcf80bdb.js → global-a9138d5f.js} +1 -1
  27. package/dist/esm/index-558b5a82.js +8 -12
  28. package/dist/esm/loader.js +2 -2
  29. package/dist/esm/priv-option-list.entry.js +39 -20
  30. package/dist/esm/ripple.js +2 -2
  31. package/dist/esm/wm-modal-pss_3.entry.js +207 -0
  32. package/dist/esm/{wm-modal.entry.js → wm-modal_3.entry.js} +73 -2
  33. package/dist/esm/wm-nested-select.entry.js +78 -33
  34. package/dist/esm/wm-optgroup.entry.js +7 -1
  35. package/dist/esm/wm-option_2.entry.js +10 -12
  36. package/dist/esm-es5/global-a9138d5f.js +1 -0
  37. package/dist/esm-es5/index-558b5a82.js +1 -1
  38. package/dist/esm-es5/loader.js +1 -1
  39. package/dist/esm-es5/priv-option-list.entry.js +1 -1
  40. package/dist/esm-es5/ripple.js +1 -1
  41. package/dist/esm-es5/wm-modal-pss_3.entry.js +1 -0
  42. package/dist/esm-es5/wm-modal_3.entry.js +1 -0
  43. package/dist/esm-es5/wm-nested-select.entry.js +1 -1
  44. package/dist/esm-es5/wm-optgroup.entry.js +1 -1
  45. package/dist/esm-es5/wm-option_2.entry.js +1 -1
  46. package/dist/ripple/p-012cab20.entry.js +1 -0
  47. package/dist/ripple/p-02deae76.entry.js +1 -0
  48. package/dist/ripple/p-1d18d9d2.system.entry.js +1 -0
  49. package/dist/ripple/p-225f55fa.system.js +1 -0
  50. package/dist/ripple/p-226fe4e0.entry.js +1 -0
  51. package/dist/ripple/p-5fbe6e5e.system.js +1 -0
  52. package/dist/ripple/p-6e725656.system.entry.js +1 -0
  53. package/dist/ripple/p-6fdfe9f4.system.entry.js +1 -0
  54. package/dist/ripple/p-aecf9a22.entry.js +1 -0
  55. package/dist/ripple/p-bf7d98d8.entry.js +1 -0
  56. package/dist/ripple/p-bfae6907.js +1 -0
  57. package/dist/ripple/p-c1714e14.system.entry.js +1 -0
  58. package/dist/ripple/p-cff5d7e9.system.entry.js +1 -0
  59. package/dist/ripple/p-f13b034e.entry.js +1 -0
  60. package/dist/ripple/{p-54d9e467.system.entry.js → p-f4bcee58.system.entry.js} +1 -1
  61. package/dist/ripple/ripple.esm.js +1 -1
  62. package/dist/ripple/ripple.js +1 -1
  63. package/dist/types/components/selects/priv-option-list/priv-option-list.d.ts +6 -2
  64. package/dist/types/components/selects/wm-nested-select/wm-nested-select.d.ts +8 -5
  65. package/dist/types/components/selects/wm-optgroup/wm-optgroup.d.ts +1 -0
  66. package/dist/types/components/selects/wm-select/wm-select.d.ts +2 -2
  67. package/dist/types/components/wm-modal-pss/wm-modal-pss-footer.d.ts +14 -0
  68. package/dist/types/components/wm-modal-pss/wm-modal-pss-header.d.ts +10 -0
  69. package/dist/types/components.d.ts +98 -5
  70. package/package.json +1 -1
  71. package/dist/cjs/wm-modal-footer.cjs.entry.js +0 -47
  72. package/dist/cjs/wm-modal-header.cjs.entry.js +0 -39
  73. package/dist/esm/wm-modal-footer.entry.js +0 -43
  74. package/dist/esm/wm-modal-header.entry.js +0 -35
  75. package/dist/esm-es5/global-dcf80bdb.js +0 -1
  76. package/dist/esm-es5/wm-modal-footer.entry.js +0 -1
  77. package/dist/esm-es5/wm-modal-header.entry.js +0 -1
  78. package/dist/esm-es5/wm-modal.entry.js +0 -1
  79. package/dist/ripple/p-0c259c1a.system.entry.js +0 -1
  80. package/dist/ripple/p-13f51c06.entry.js +0 -1
  81. package/dist/ripple/p-1c170fb3.entry.js +0 -1
  82. package/dist/ripple/p-294b38ca.system.entry.js +0 -1
  83. package/dist/ripple/p-3568472c.entry.js +0 -1
  84. package/dist/ripple/p-45dc49e8.entry.js +0 -1
  85. package/dist/ripple/p-50388b6f.system.entry.js +0 -1
  86. package/dist/ripple/p-54f7d3d4.system.entry.js +0 -1
  87. package/dist/ripple/p-618300c1.entry.js +0 -1
  88. package/dist/ripple/p-76ff5d91.entry.js +0 -1
  89. package/dist/ripple/p-84603f1f.system.entry.js +0 -1
  90. package/dist/ripple/p-99058787.entry.js +0 -1
  91. package/dist/ripple/p-b176c143.system.entry.js +0 -1
  92. package/dist/ripple/p-c6a336d6.system.js +0 -1
  93. package/dist/ripple/p-e209a933.js +0 -1
  94. package/dist/ripple/p-ee4fee7d.system.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { h, Host, forceUpdate } from "@stencil/core";
2
- import { getTextDir, intl, isElOrChild, shouldOpenUp, toBool } from "../../../global/functions";
2
+ import { getContextMeasurements, getTextDir, intl, isElOrChild, shouldOpenUp, toBool } from "../../../global/functions";
3
3
  import { globalMessages } from "../../../global/intl";
4
4
  export class NestedSelect {
5
5
  constructor() {
@@ -18,7 +18,7 @@ export class NestedSelect {
18
18
  description: "Button text to clear selection. Use imperative",
19
19
  });
20
20
  this.disabled = false;
21
- this.maxHeight = undefined;
21
+ this.maxHeight = "200px";
22
22
  this.label = undefined;
23
23
  this.labelPosition = "top";
24
24
  this.requiredField = false;
@@ -49,6 +49,8 @@ export class NestedSelect {
49
49
  });
50
50
  this.isExpanded = false;
51
51
  this.showClearSelectionButton = false;
52
+ this.announcement = "";
53
+ this.constrainedMaxHeight = this.maxHeight;
52
54
  }
53
55
  get isDisabled() {
54
56
  // string "false" needs to be treated as bool False because react wrappers convert bool to string.
@@ -67,7 +69,7 @@ export class NestedSelect {
67
69
  return this.childOptions.every((option) => option.selected);
68
70
  }
69
71
  componentWillLoad() {
70
- const mutationObserver = new MutationObserver((mutationRecordList) => mutationRecordList.forEach((mutationRecord) => this.handleChildChange(mutationRecord)));
72
+ const mutationObserver = new MutationObserver((mutationRecordList) => mutationRecordList.forEach((_mutationRecord) => this.handleChildChange()));
71
73
  mutationObserver.observe(this.el, {
72
74
  childList: true,
73
75
  attributes: true,
@@ -75,16 +77,14 @@ export class NestedSelect {
75
77
  attributeFilter: ["selected"],
76
78
  });
77
79
  }
78
- componentDidLoad() {
79
- if (this.maxHeight) {
80
- this.dropdownEl.style.maxHeight = this.maxHeight;
81
- }
82
- }
83
- handleChildChange(_) {
80
+ handleChildChange() {
84
81
  // on update of children or children selected state, reset button text and rerender
85
82
  this.setButtonText();
86
83
  forceUpdate(this.el);
87
- // this.optionListEl.handleChildChange(_);
84
+ if (this.multiple) {
85
+ // update state of clone options
86
+ this.optgroupEls.forEach((optgroupEl) => optgroupEl.handleChildChange());
87
+ }
88
88
  }
89
89
  setButtonText() {
90
90
  this.displayedOptions = this.childOptions.filter((x) => x.selected);
@@ -124,6 +124,28 @@ export class NestedSelect {
124
124
  closePopupOnEscape() {
125
125
  this.close();
126
126
  }
127
+ handleKeyDown(ev) {
128
+ // when shift tabbing but component is still in focus, close dropdown
129
+ switch (ev.key) {
130
+ case "Tab":
131
+ if (ev.shiftKey) {
132
+ this.close();
133
+ }
134
+ break;
135
+ case "ArrowDown":
136
+ if (this.isExpanded === false) {
137
+ ev.preventDefault();
138
+ this.open();
139
+ }
140
+ break;
141
+ case "ArrowUp":
142
+ if (this.isExpanded === false) {
143
+ ev.preventDefault();
144
+ this.open(true);
145
+ }
146
+ break;
147
+ }
148
+ }
127
149
  close(returnFocus = true) {
128
150
  if (this.isExpanded) {
129
151
  this.isExpanded = false;
@@ -136,40 +158,50 @@ export class NestedSelect {
136
158
  }, 150);
137
159
  }
138
160
  }
139
- open() {
161
+ open(focusLast = false) {
140
162
  if (!this.isDisabled) {
141
163
  this.showClearSelectionButton = this.childOptions.some((o) => o.selected);
164
+ this.dropdownEl.scrollTop = 0;
142
165
  this.isExpanded = true;
143
166
  this.dropdownEl.classList.add("open");
144
167
  const elHeight = this.el.clientHeight;
145
168
  this.openUp = shouldOpenUp(this.el, this.dropdownEl.clientHeight, elHeight, 0);
146
- window.requestAnimationFrame(() => {
147
- this.focusFirstMenuitem();
169
+ this.constrainedMaxHeight = this.maxHeight;
170
+ const spaceAbove = getContextMeasurements(this.el).spaceAbove;
171
+ if (this.openUp) {
172
+ if (parseInt(getComputedStyle(this.menuEl).getPropertyValue("--max-height").replace("px", "")) > spaceAbove) {
173
+ this.constrainedMaxHeight = spaceAbove.toString() + "px";
174
+ }
175
+ }
176
+ // if opening upwards, set an upwards height limit for the optgroup level
177
+ this.optgroupEls.forEach((o) => {
178
+ o.shadowRoot.querySelector("priv-option-list").upwardsHeightLimit = this.openUp
179
+ ? spaceAbove
180
+ : null;
148
181
  });
149
- }
150
- }
151
- focusFirstMenuitem() {
152
- if (this.menuitemEls.length > 0) {
153
- this.menuitemEls[0].focus();
182
+ // scrollIntoView does not work when the container of the element it's called on is not rendered to the page (in our case the dropdown is still closed and has transform: scaleY(0))
183
+ // when opening the dropdown, scrollIntoView must be delayed to a point where the browser recognizes content within it as able to be scrolled to
184
+ // in Safari in particular, the soonest this seems to happen is 20ms. The longest we can wait before any jumping in the open dropdown is noticeable is 60ms
185
+ window.setTimeout(() => {
186
+ if (this.menuitemEls.length > 0) {
187
+ const menuitemToFocus = this.menuitemEls[focusLast ? this.menuitemEls.length - 1 : 0];
188
+ menuitemToFocus.scrollIntoView({ block: "nearest" });
189
+ menuitemToFocus.focus();
190
+ }
191
+ }, 60);
154
192
  }
155
193
  }
156
194
  moveDown(menuitemEl) {
157
195
  const currentIndex = this.menuitemEls.indexOf(menuitemEl);
158
- if (currentIndex == this.menuitemEls.length - 1) {
159
- this.menuitemEls[0].focus();
160
- }
161
- else {
162
- this.menuitemEls[currentIndex + 1].focus();
163
- }
196
+ const menuitemToFocus = this.menuitemEls[currentIndex == this.menuitemEls.length - 1 ? 0 : currentIndex + 1];
197
+ menuitemToFocus.scrollIntoView({ block: "nearest" });
198
+ menuitemToFocus.focus();
164
199
  }
165
200
  moveUp(menuitemEl) {
166
201
  const currentIndex = this.menuitemEls.indexOf(menuitemEl);
167
- if (currentIndex == 0) {
168
- this.menuitemEls[this.menuitemEls.length - 1].focus();
169
- }
170
- else {
171
- this.menuitemEls[currentIndex - 1].focus();
172
- }
202
+ const menuitemToFocus = this.menuitemEls[currentIndex == 0 ? this.menuitemEls.length - 1 : currentIndex - 1];
203
+ menuitemToFocus.scrollIntoView({ block: "nearest" });
204
+ menuitemToFocus.focus();
173
205
  }
174
206
  handleButtonBlur(ev) {
175
207
  if (isElOrChild(this.el, ev.relatedTarget)) {
@@ -225,6 +257,13 @@ export class NestedSelect {
225
257
  const elToFocus = this.el.shadowRoot.querySelector(`button[data-label=${ev.detail}]`);
226
258
  elToFocus.focus();
227
259
  }
260
+ announce(message) {
261
+ // \u00A0 is a non-breaking space character, which causes the message to be read as a new one
262
+ if (this.liveRegionEl.textContent === message) {
263
+ message += "\u00A0";
264
+ }
265
+ this.announcement = message;
266
+ }
228
267
  renderButtonText() {
229
268
  if (this.displayedOptions.length < 1) {
230
269
  return h("span", null, this.placeholder);
@@ -243,6 +282,12 @@ export class NestedSelect {
243
282
  }
244
283
  handleClearSelection() {
245
284
  this.optgroupEls.forEach((optgroupEl) => optgroupEl.emitDeselection());
285
+ const selectionClearedAnnouncement = intl.formatMessage({
286
+ id: "select.selectionCleared",
287
+ defaultMessage: "Selection cleared",
288
+ description: "Screen reader announcement alerting the user they have cleared their selection",
289
+ });
290
+ this.announce(selectionClearedAnnouncement);
246
291
  if (!this.multiple) {
247
292
  this.close();
248
293
  }
@@ -282,14 +327,14 @@ export class NestedSelect {
282
327
  };
283
328
  return (h(Host, { onBlur: (ev) => this.handleComponentBlur(ev) }, h("div", { class: `wrapper ${getTextDir()} label-${this.labelPosition} ${this.errorMessage ? "invalid" : ""}` }, h("div", { class: "label-wrapper" }, h("label", { class: "label", id: "label", htmlFor: "selectbtn" }, this.label,
284
329
  // we can't use aria-required or required attributes because it's invalid on the elements we're using (button controlling a listbox)
285
- this.requiredField ? (h("span", { class: "required" }, h("span", { class: "sr-only" }, globalMessages.requiredField), h("span", { "aria-hidden": "true" }, "*"))) : (""))), h("div", { class: "button-wrapper" }, h("button", Object.assign({}, buttonProps, { class: `displayedoption ${this.isExpanded ? "expanded" : ""}`, ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev), onFocus: () => this.close() }), h("span", { class: "overflowcontrol" }, h("span", { class: "button-text" }, this.renderButtonText())), this.renderOverflowCount(), h("div", { ref: (el) => (this.measurementAreaEl = el), class: "measurement-area", "aria-hidden": "true" })), h("div", { class: `dropdown ${this.openUp ? "upwards" : ""}`, ref: (el) => (this.dropdownEl = el) }, h("div", { ref: (el) => (this.menuEl = el), class: "menu" }, this.renderClearSelectionButton(), this.optgroupEls.map((optgroupEl) => {
330
+ this.requiredField ? (h("span", { class: "required" }, h("span", { class: "sr-only" }, globalMessages.requiredField), h("span", { "aria-hidden": "true" }, "*"))) : (""))), h("div", { class: "button-wrapper" }, h("button", Object.assign({}, buttonProps, { class: `displayedoption ${this.isExpanded ? "expanded" : ""}`, ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev) }), h("span", { class: "overflowcontrol" }, h("span", { class: "button-text" }, this.renderButtonText())), this.renderOverflowCount(), h("div", { ref: (el) => (this.measurementAreaEl = el), class: "measurement-area", "aria-hidden": "true" })), h("div", { class: `dropdown ${this.openUp ? "upwards" : ""}`, ref: (el) => (this.dropdownEl = el) }, h("div", { ref: (el) => (this.menuEl = el), class: "menu", style: { "--max-height": this.constrainedMaxHeight }, tabIndex: -1 }, this.renderClearSelectionButton(), this.optgroupEls.map((optgroupEl) => {
286
331
  return (h("button", { class: `menuitem group-btn ${optgroupEl.disabled ? "disabled" : ""}`, role: "menuitem", "data-label": optgroupEl.label, tabindex: -1, "aria-disabled": optgroupEl.disabled, onClick: () => {
287
332
  if (!optgroupEl.disabled) {
288
333
  optgroupEl.isExpanded = !optgroupEl.isExpanded;
289
334
  forceUpdate(this.el);
290
335
  }
291
336
  }, onKeyDown: (ev) => this.handleMenuitemKeydown(ev) }, h("span", null, optgroupEl.label), this.renderSelectionCount(optgroupEl), optgroupEl.disabled && h("div", { class: "disabled-indication" }, "Disabled")));
292
- })), h("div", { ref: (el) => (this.optListWrapperEl = el), class: "option-list-wrapper hidden" }, h("slot", null))), h("div", { id: "error", class: this.errorMessage ? "error-message" : "" }, this.errorMessage)))));
337
+ })), h("div", { ref: (el) => (this.optListWrapperEl = el), class: "option-list-wrapper hidden" }, h("slot", null))), h("div", { id: "error", class: this.errorMessage ? "error-message" : "" }, this.errorMessage))), h("div", { id: "nestedselect-announcement", "aria-live": "assertive", "aria-atomic": "true", class: "sr-only", ref: (el) => (this.liveRegionEl = el) }, this.announcement)));
293
338
  }
294
339
  static get is() { return "wm-nested-select"; }
295
340
  static get encapsulation() { return "shadow"; }
@@ -329,17 +374,18 @@ export class NestedSelect {
329
374
  "mutable": false,
330
375
  "complexType": {
331
376
  "original": "string",
332
- "resolved": "string | undefined",
377
+ "resolved": "string",
333
378
  "references": {}
334
379
  },
335
380
  "required": false,
336
- "optional": true,
381
+ "optional": false,
337
382
  "docs": {
338
383
  "tags": [],
339
384
  "text": ""
340
385
  },
341
386
  "attribute": "max-height",
342
- "reflect": false
387
+ "reflect": false,
388
+ "defaultValue": "\"200px\""
343
389
  },
344
390
  "label": {
345
391
  "type": "string",
@@ -518,13 +564,32 @@ export class NestedSelect {
518
564
  "attribute": "all-selected-message",
519
565
  "reflect": false,
520
566
  "defaultValue": "intl.formatMessage({\n id: \"select.allSelected\",\n defaultMessage: \"All selected\",\n description: \"Text displayed when all options are selected\",\n })"
567
+ },
568
+ "constrainedMaxHeight": {
569
+ "type": "string",
570
+ "mutable": true,
571
+ "complexType": {
572
+ "original": "string",
573
+ "resolved": "string",
574
+ "references": {}
575
+ },
576
+ "required": false,
577
+ "optional": false,
578
+ "docs": {
579
+ "tags": [],
580
+ "text": ""
581
+ },
582
+ "attribute": "constrained-max-height",
583
+ "reflect": false,
584
+ "defaultValue": "this.maxHeight"
521
585
  }
522
586
  };
523
587
  }
524
588
  static get states() {
525
589
  return {
526
590
  "isExpanded": {},
527
- "showClearSelectionButton": {}
591
+ "showClearSelectionButton": {},
592
+ "announcement": {}
528
593
  };
529
594
  }
530
595
  static get events() {
@@ -565,6 +630,12 @@ export class NestedSelect {
565
630
  "target": undefined,
566
631
  "capture": false,
567
632
  "passive": false
633
+ }, {
634
+ "name": "keydown",
635
+ "method": "handleKeyDown",
636
+ "target": undefined,
637
+ "capture": false,
638
+ "passive": false
568
639
  }, {
569
640
  "name": "click",
570
641
  "method": "handleClick",
@@ -31,10 +31,16 @@ export class Optgroup {
31
31
  this.el.classList.remove("visible");
32
32
  }, 250);
33
33
  }
34
+ if (this.parentNestedSelect.multiple) {
35
+ this.optionListEl.updateOptionVisibility();
36
+ }
34
37
  }
35
38
  async emitDeselection() {
36
39
  this.wmOptgroupAllDeselected.emit();
37
40
  }
41
+ async handleChildChange() {
42
+ this.optionListEl.handleChildChange();
43
+ }
38
44
  handleOptionKeyLeft() {
39
45
  this.isExpanded = false;
40
46
  }
@@ -42,7 +48,7 @@ export class Optgroup {
42
48
  handleDisabledAttribute(this.el, this.isDisabled);
43
49
  }
44
50
  render() {
45
- return (h(Host, null, h("div", { class: `list-wrapper` }, h("priv-option-list", { ref: (el) => (this.optionListEl = el), multiple: this.parentNestedSelect.multiple, search: this.parentNestedSelect.search, searchPlaceholder: this.parentNestedSelect.searchPlaceholder, optgroupLabel: this.label, selectAll: this.parentNestedSelect.selectAll, onOptionListAllSelected: () => this.wmOptgroupAllSelected.emit(), onOptionListAllDeselected: () => this.wmOptgroupAllDeselected.emit() }, h("slot", null)))));
51
+ return (h(Host, null, h("div", { class: `list-wrapper` }, h("priv-option-list", { ref: (el) => (this.optionListEl = el), multiple: this.parentNestedSelect.multiple, search: this.parentNestedSelect.search, maxHeight: this.parentNestedSelect.constrainedMaxHeight, searchPlaceholder: this.parentNestedSelect.searchPlaceholder, optgroupLabel: this.label, selectAll: this.parentNestedSelect.selectAll, onOptionListAllSelected: () => this.wmOptgroupAllSelected.emit(), onOptionListAllDeselected: () => this.wmOptgroupAllDeselected.emit() }, h("slot", null)))));
46
52
  }
47
53
  static get is() { return "wm-optgroup"; }
48
54
  static get encapsulation() { return "shadow"; }
@@ -213,6 +219,23 @@ export class Optgroup {
213
219
  "text": "",
214
220
  "tags": []
215
221
  }
222
+ },
223
+ "handleChildChange": {
224
+ "complexType": {
225
+ "signature": "() => Promise<void>",
226
+ "parameters": [],
227
+ "references": {
228
+ "Promise": {
229
+ "location": "global",
230
+ "id": "global::Promise"
231
+ }
232
+ },
233
+ "return": "Promise<void>"
234
+ },
235
+ "docs": {
236
+ "text": "",
237
+ "tags": []
238
+ }
216
239
  }
217
240
  };
218
241
  }
@@ -151,7 +151,7 @@
151
151
  pointer-events: none;
152
152
  }
153
153
 
154
- :host(:focus) {
154
+ :host(:focus-visible) {
155
155
  outline: none;
156
156
  background: var(--wmcolor-select-option-background-focus);
157
157
  }
@@ -227,9 +227,9 @@
227
227
  margin-left: 0.5rem;
228
228
  }
229
229
  .wrapper .button-wrapper > .displayedoption[disabled] {
230
- color: #6b6b6b;
231
- border-color: #8a8a8a;
232
- background: #f0f0f0;
230
+ color: var(--wmcolor-select-option-text-disabled);
231
+ border-color: var(--wmcolor-border-dark);
232
+ background: var(--wmcolor-select-option-background-disabled);
233
233
  cursor: default;
234
234
  }
235
235
  .wrapper .button-wrapper > .dropdown {
@@ -260,6 +260,8 @@
260
260
  z-index: 100;
261
261
  width: 100%;
262
262
  font-size: 0.875rem;
263
+ max-height: var(--max-height);
264
+ overflow-y: auto;
263
265
  }
264
266
  .wrapper .button-wrapper > .dropdown.upwards {
265
267
  top: unset;
@@ -297,11 +299,6 @@
297
299
  margin-top: 0.25rem;
298
300
  }
299
301
 
300
- .options-wrapper {
301
- max-height: 12.5rem;
302
- overflow: auto;
303
- }
304
-
305
302
  .measurement-area {
306
303
  position: absolute;
307
304
  visibility: hidden;
@@ -10,7 +10,7 @@ export class Select {
10
10
  this.overflowCount = 0;
11
11
  this.displayedOptions = [];
12
12
  this.disabled = false;
13
- this.maxHeight = undefined;
13
+ this.maxHeight = "200px";
14
14
  this.label = undefined;
15
15
  this.labelPosition = "top";
16
16
  this.requiredField = false;
@@ -107,7 +107,7 @@ export class Select {
107
107
  console.error("wm-select should have one initial option selected");
108
108
  }
109
109
  handleDisabledAttribute(this.el, this.isDisabled);
110
- const mutationObserver = new MutationObserver((mutationRecordList) => mutationRecordList.forEach((mutationRecord) => this.handleChildChange(mutationRecord)));
110
+ const mutationObserver = new MutationObserver((mutationRecordList) => mutationRecordList.forEach((_mutationRecord) => this.handleChildChange()));
111
111
  mutationObserver.observe(this.el, {
112
112
  childList: true,
113
113
  attributes: true,
@@ -115,21 +115,19 @@ export class Select {
115
115
  attributeFilter: ["selected"],
116
116
  });
117
117
  }
118
- handleChildChange(_) {
118
+ handleChildChange() {
119
119
  // on update of children or children selected state, reset button text and rerender
120
120
  this.setButtonText();
121
- this.optionListEl.handleChildChange(_);
122
121
  forceUpdate(this.el);
122
+ if (this.multiple) {
123
+ // update state of clone options
124
+ this.optionListEl.handleChildChange();
125
+ }
123
126
  }
124
127
  componentDidLoad() {
125
128
  this.wmSelectDidLoad.emit();
126
129
  this.dropdownEl.classList.add("hidden");
127
130
  forceUpdate(this.el);
128
- // Dev can overwrite the max-height rule set in the Sass file
129
- if (this.maxHeight) {
130
- // this.listboxEl.style.maxHeight = this.maxHeight;
131
- this.dropdownEl.style.maxHeight = this.maxHeight;
132
- }
133
131
  this.setButtonText();
134
132
  }
135
133
  open(optionToSelect) {
@@ -244,7 +242,7 @@ export class Select {
244
242
  };
245
243
  return (h(Host, { onBlur: (ev) => this.handleComponentBlur(ev) }, h("div", { class: `wrapper ${getTextDir()} label-${this.labelPosition} ${this.errorMessage ? "invalid" : ""}` }, h("div", { class: "label-wrapper" }, h("label", { class: "label", id: "label", htmlFor: "selectbtn" }, this.label,
246
244
  // we can't use aria-required or required attributes because it's invalid on the elements we're using (button controlling a listbox)
247
- this.requiredField ? (h("span", { class: "required" }, h("span", { class: "sr-only" }, globalMessages.requiredField), h("span", { "aria-hidden": "true" }, "*"))) : (""))), h("div", { class: "button-wrapper" }, h("button", Object.assign({}, buttonProps, { class: "displayedoption", ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev), onFocus: () => this.close() }), h("span", { class: `overflowcontrol ${showSubinfo ? "hassubinfo" : ""}` }, h("span", { class: "button-text" }, this.renderButtonText()), showSubinfo && h("span", { class: "subinfo" }, this.selectedOptions[0].subinfo)), this.renderOverflowCount(), h("div", { ref: (el) => (this.measurementAreaEl = el), class: "measurement-area", "aria-hidden": "true" })), h("div", { class: `dropdown ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, ref: (el) => (this.dropdownEl = el) }, h("priv-option-list", { ref: (el) => (this.optionListEl = el), multiple: this.multiple, search: this.search, selectAll: this.selectAll, searchPlaceholder: this.searchPlaceholder, onOptionListCloseRequested: () => this.close(), onOptionListAllSelected: () => this.wmSelectAllSelected.emit(), onOptionListAllDeselected: () => this.wmSelectAllDeselected.emit() }, h("slot", null))), h("div", { id: "error", class: this.errorMessage ? "error-message" : "" }, this.errorMessage), h("div", { id: "announcement", "aria-live": "polite", "aria-atomic": "true", class: "sr-only", ref: (el) => (this.liveRegionEl = el) }, this.announcement)))));
245
+ this.requiredField ? (h("span", { class: "required" }, h("span", { class: "sr-only" }, globalMessages.requiredField), h("span", { "aria-hidden": "true" }, "*"))) : (""))), h("div", { class: "button-wrapper" }, h("button", Object.assign({}, buttonProps, { class: "displayedoption", ref: (el) => (this.buttonEl = el), onBlur: (ev) => this.handleButtonBlur(ev), onFocus: () => this.close() }), h("span", { class: `overflowcontrol ${showSubinfo ? "hassubinfo" : ""}` }, h("span", { class: "button-text" }, this.renderButtonText()), showSubinfo && h("span", { class: "subinfo" }, this.selectedOptions[0].subinfo)), this.renderOverflowCount(), h("div", { ref: (el) => (this.measurementAreaEl = el), class: "measurement-area", "aria-hidden": "true" })), h("div", { class: `dropdown ${this.isExpanded ? "open" : ""} ${this.openUp ? "upwards" : ""}`, ref: (el) => (this.dropdownEl = el) }, h("priv-option-list", { ref: (el) => (this.optionListEl = el), multiple: this.multiple, search: this.search, selectAll: this.selectAll, maxHeight: this.maxHeight, searchPlaceholder: this.searchPlaceholder, onOptionListCloseRequested: () => this.close(), onOptionListAllSelected: () => this.wmSelectAllSelected.emit(), onOptionListAllDeselected: () => this.wmSelectAllDeselected.emit() }, h("slot", null))), h("div", { id: "error", class: this.errorMessage ? "error-message" : "" }, this.errorMessage), h("div", { id: "announcement", "aria-live": "polite", "aria-atomic": "true", class: "sr-only", ref: (el) => (this.liveRegionEl = el) }, this.announcement)))));
248
246
  }
249
247
  static get is() { return "wm-select"; }
250
248
  static get encapsulation() { return "shadow"; }
@@ -284,17 +282,18 @@ export class Select {
284
282
  "mutable": false,
285
283
  "complexType": {
286
284
  "original": "string",
287
- "resolved": "string | undefined",
285
+ "resolved": "string",
288
286
  "references": {}
289
287
  },
290
288
  "required": false,
291
- "optional": true,
289
+ "optional": false,
292
290
  "docs": {
293
291
  "tags": [],
294
292
  "text": ""
295
293
  },
296
294
  "attribute": "max-height",
297
- "reflect": false
295
+ "reflect": false,
296
+ "defaultValue": "\"200px\""
298
297
  },
299
298
  "label": {
300
299
  "type": "string",
@@ -0,0 +1,61 @@
1
+ /* --------------------------------------
2
+ 1. Box-shadow
3
+ -------------------------------------- */
4
+ /* --------------------------------------
5
+ 2. Border-radius
6
+ -------------------------------------- */
7
+ /* --------------------------------------
8
+ 3. Transforms
9
+ -------------------------------------- */
10
+ /* --------------------------------------
11
+ 4. Button Focus
12
+ -------------------------------------- */
13
+ /* --------------------------------------
14
+ 5. Flex
15
+ -------------------------------------- */
16
+ /* --------------------------------------
17
+ 7. Screen Reader Only
18
+ -------------------------------------- */
19
+ /* --------------------------------------
20
+ 8. Label styles
21
+ this mixin includes all the styles for the label
22
+ + flex rules on the parent container to switch between top and left position
23
+ + srOnly when label is hidden
24
+ Assumes the following markup:
25
+ div.wrapper[.label-left.invalid] > div.label-wrapper > label.label > span.required
26
+ .wrapper is for the flex rules
27
+ .label-wrapper is to set the height of the label when positioned left so it's the same height as
28
+ the input. It can't be done directly on .label because of possible line wrapping.
29
+ When the label is on top there's no line wrapping at all to ensure proper alignment of inlined elements
30
+ (they can't be aligned on the baseline because of possible description text and error message)
31
+ -------------------------------------- */
32
+ wm-modal-pss-footer {
33
+ border-radius: 0px 0px 5px 5px;
34
+ margin-top: -1px;
35
+ }
36
+ wm-modal-pss-footer .wm-wrapper {
37
+ display: flex;
38
+ justify-content: space-between;
39
+ align-items: center;
40
+ }
41
+ @media only screen and (max-width: 650px) {
42
+ wm-modal-pss-footer .wm-wrapper.footer-text {
43
+ flex-direction: column;
44
+ align-items: flex-start;
45
+ }
46
+ }
47
+ wm-modal-pss-footer .wm-wrapper wm-button + wm-button {
48
+ margin-left: 1rem;
49
+ }
50
+ wm-modal-pss-footer .wm-wrapper .wm-info {
51
+ font-size: 0.875rem;
52
+ font-style: italic;
53
+ }
54
+ @media only screen and (max-width: 650px) {
55
+ wm-modal-pss-footer .wm-wrapper .wm-info {
56
+ padding-bottom: 0.625rem;
57
+ }
58
+ }
59
+ wm-modal-pss-footer .wm-wrapper .wm-info:focus {
60
+ outline: none;
61
+ }
@@ -0,0 +1,138 @@
1
+ import { h } from "@stencil/core";
2
+ export class ModalFooter {
3
+ constructor() {
4
+ this.secondaryText = "";
5
+ this.primaryText = "";
6
+ this.infoText = "";
7
+ this.primaryActionDisabled = false;
8
+ this.deleteStyle = false;
9
+ }
10
+ componentWillLoad() {
11
+ this.uid = this.el.parentElement.uid;
12
+ // Trap focus when user shift+tabs past first element in modal
13
+ // NB @Listen doesn't allow to listen on a specific element (the parent modal)
14
+ // if we listen to the whole doc each modal on the page reacts to every event
15
+ this.el.parentElement.addEventListener("focusLastElement", () => {
16
+ this.lastElement.focus();
17
+ });
18
+ }
19
+ emitParentPrimaryEvent() {
20
+ const parentModal = this.el.parentElement;
21
+ //@ts-ignore
22
+ parentModal.emitPrimaryEvent();
23
+ }
24
+ emitParentSecondaryEvent() {
25
+ const parentModal = this.el.parentElement;
26
+ //@ts-ignore
27
+ parentModal.emitSecondaryEvent();
28
+ }
29
+ render() {
30
+ return (h("div", { class: `wm-wrapper ${this.infoText ? " footer-text" : ""}` }, h("div", { class: "wm-info", "aria-live": "polite" }, this.infoText), h("div", { class: "wm-button-collection" }, this.secondaryText && (h("wm-button", { onClick: () => this.emitParentSecondaryEvent(), id: `wm-secondary-${this.uid}`, ref: (el) => (this.primaryActionDisabled ? (this.lastElement = el) : null) }, this.secondaryText)), h("wm-button", { "button-type": this.deleteStyle ? "secondary" : "primary", "permanently-delete": this.deleteStyle, onClick: () => this.emitParentPrimaryEvent(), disabled: this.primaryActionDisabled, id: `wm-primary-${this.uid}`, ref: (el) => (!this.primaryActionDisabled ? (this.lastElement = el) : null) }, this.primaryText))));
31
+ }
32
+ static get is() { return "wm-modal-pss-footer"; }
33
+ static get originalStyleUrls() {
34
+ return {
35
+ "$": ["wm-modal-pss-footer.scss"]
36
+ };
37
+ }
38
+ static get styleUrls() {
39
+ return {
40
+ "$": ["wm-modal-pss-footer.css"]
41
+ };
42
+ }
43
+ static get properties() {
44
+ return {
45
+ "secondaryText": {
46
+ "type": "string",
47
+ "mutable": false,
48
+ "complexType": {
49
+ "original": "string",
50
+ "resolved": "string | undefined",
51
+ "references": {}
52
+ },
53
+ "required": false,
54
+ "optional": true,
55
+ "docs": {
56
+ "tags": [],
57
+ "text": ""
58
+ },
59
+ "attribute": "secondary-text",
60
+ "reflect": false,
61
+ "defaultValue": "\"\""
62
+ },
63
+ "primaryText": {
64
+ "type": "string",
65
+ "mutable": false,
66
+ "complexType": {
67
+ "original": "string",
68
+ "resolved": "string | undefined",
69
+ "references": {}
70
+ },
71
+ "required": false,
72
+ "optional": true,
73
+ "docs": {
74
+ "tags": [],
75
+ "text": ""
76
+ },
77
+ "attribute": "primary-text",
78
+ "reflect": false,
79
+ "defaultValue": "\"\""
80
+ },
81
+ "infoText": {
82
+ "type": "string",
83
+ "mutable": false,
84
+ "complexType": {
85
+ "original": "string",
86
+ "resolved": "string | undefined",
87
+ "references": {}
88
+ },
89
+ "required": false,
90
+ "optional": true,
91
+ "docs": {
92
+ "tags": [],
93
+ "text": ""
94
+ },
95
+ "attribute": "info-text",
96
+ "reflect": false,
97
+ "defaultValue": "\"\""
98
+ },
99
+ "primaryActionDisabled": {
100
+ "type": "boolean",
101
+ "mutable": false,
102
+ "complexType": {
103
+ "original": "boolean",
104
+ "resolved": "boolean",
105
+ "references": {}
106
+ },
107
+ "required": false,
108
+ "optional": false,
109
+ "docs": {
110
+ "tags": [],
111
+ "text": ""
112
+ },
113
+ "attribute": "primary-action-disabled",
114
+ "reflect": false,
115
+ "defaultValue": "false"
116
+ },
117
+ "deleteStyle": {
118
+ "type": "boolean",
119
+ "mutable": false,
120
+ "complexType": {
121
+ "original": "boolean",
122
+ "resolved": "boolean",
123
+ "references": {}
124
+ },
125
+ "required": false,
126
+ "optional": false,
127
+ "docs": {
128
+ "tags": [],
129
+ "text": ""
130
+ },
131
+ "attribute": "delete-style",
132
+ "reflect": false,
133
+ "defaultValue": "false"
134
+ }
135
+ };
136
+ }
137
+ static get elementRef() { return "el"; }
138
+ }