@watermarkinsights/ripple 5.7.0-0 → 5.7.0-10

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 (95) hide show
  1. package/dist/cjs/{global-b4e48f66.js → global-d1944ab2.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 +27 -19
  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 +85 -38
  9. package/dist/cjs/wm-optgroup.cjs.entry.js +16 -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 +22 -6
  13. package/dist/collection/components/selects/priv-option-list/priv-option-list.js +53 -34
  14. package/dist/collection/components/selects/wm-nested-select/wm-nested-select.css +43 -7
  15. package/dist/collection/components/selects/wm-nested-select/wm-nested-select.js +115 -42
  16. package/dist/collection/components/selects/wm-optgroup/wm-optgroup.js +51 -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-8a4502dd.js → global-687694e4.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 +27 -19
  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 +86 -39
  34. package/dist/esm/wm-optgroup.entry.js +16 -1
  35. package/dist/esm/wm-option_2.entry.js +10 -12
  36. package/dist/esm-es5/global-687694e4.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-226fe4e0.entry.js +1 -0
  50. package/dist/ripple/p-6e725656.system.entry.js +1 -0
  51. package/dist/ripple/p-6fdfe9f4.system.entry.js +1 -0
  52. package/dist/ripple/p-77e48f61.system.entry.js +1 -0
  53. package/dist/ripple/p-ad1bdcd6.js +1 -0
  54. package/dist/ripple/p-add3ab3d.system.js +1 -0
  55. package/dist/ripple/p-bf7d98d8.entry.js +1 -0
  56. package/dist/ripple/p-ca397ba6.system.js +1 -0
  57. package/dist/ripple/p-cff5d7e9.system.entry.js +1 -0
  58. package/dist/ripple/p-f13b034e.entry.js +1 -0
  59. package/dist/ripple/p-f3f4620c.entry.js +1 -0
  60. package/dist/ripple/p-f4bcee58.system.entry.js +1 -0
  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 +4 -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 +100 -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-8a4502dd.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-01addccd.entry.js +0 -1
  80. package/dist/ripple/p-01e29a2a.system.js +0 -1
  81. package/dist/ripple/p-0c259c1a.system.entry.js +0 -1
  82. package/dist/ripple/p-13f51c06.entry.js +0 -1
  83. package/dist/ripple/p-1796b85d.entry.js +0 -1
  84. package/dist/ripple/p-1c170fb3.entry.js +0 -1
  85. package/dist/ripple/p-294b38ca.system.entry.js +0 -1
  86. package/dist/ripple/p-3568472c.entry.js +0 -1
  87. package/dist/ripple/p-3d02b293.system.entry.js +0 -1
  88. package/dist/ripple/p-45dc49e8.entry.js +0 -1
  89. package/dist/ripple/p-50388b6f.system.entry.js +0 -1
  90. package/dist/ripple/p-54f7d3d4.system.entry.js +0 -1
  91. package/dist/ripple/p-84603f1f.system.entry.js +0 -1
  92. package/dist/ripple/p-947f8f0d.system.entry.js +0 -1
  93. package/dist/ripple/p-99058787.entry.js +0 -1
  94. package/dist/ripple/p-db9f8841.system.js +0 -1
  95. package/dist/ripple/p-de8f5e92.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);
@@ -237,19 +276,25 @@ export class NestedSelect {
237
276
  }
238
277
  }
239
278
  renderOverflowCount() {
240
- if (this.overflowCount > 0) {
279
+ if (this.overflowCount > 0 && !this.allSelected) {
241
280
  return (h("span", null, h("span", { class: "overflow-counter" }, "+", this.overflowCount)));
242
281
  }
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
  }
249
294
  }
250
295
  renderClearSelectionButton() {
251
296
  if (this.showClearSelectionButton) {
252
- return (h("button", { class: "menuitem", onClick: () => this.handleClearSelection(), tabindex: -1, onKeyDown: (ev) => this.handleMenuitemKeydown(ev) }, this.clearSelectionMessage));
297
+ return (h("button", { class: "menuitem clear-selection", onClick: () => this.handleClearSelection(), tabindex: -1, onKeyDown: (ev) => this.handleMenuitemKeydown(ev) }, this.clearSelectionMessage));
253
298
  }
254
299
  }
255
300
  renderSelectionCount(optgroupEl) {
@@ -282,12 +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) => {
286
- return (h("button", { class: "menuitem group-btn", role: "menuitem", "data-label": optgroupEl.label, tabindex: -1, onClick: () => {
287
- optgroupEl.isExpanded = !optgroupEl.isExpanded;
288
- forceUpdate(this.el);
289
- }, onKeyDown: (ev) => this.handleMenuitemKeydown(ev) }, h("span", null, optgroupEl.label), this.renderSelectionCount(optgroupEl)));
290
- })), 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)))));
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) => {
331
+ return (h("button", { class: `menuitem group-btn ${optgroupEl.disabled ? "disabled" : ""}`, role: "menuitem", "data-label": optgroupEl.label, tabindex: -1, "aria-disabled": optgroupEl.disabled, onClick: () => {
332
+ if (!optgroupEl.disabled) {
333
+ optgroupEl.isExpanded = !optgroupEl.isExpanded;
334
+ forceUpdate(this.el);
335
+ }
336
+ }, onKeyDown: (ev) => this.handleMenuitemKeydown(ev) }, h("span", null, optgroupEl.label), this.renderSelectionCount(optgroupEl), optgroupEl.disabled && h("div", { class: "disabled-indication" }, "Disabled")));
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)));
291
338
  }
292
339
  static get is() { return "wm-nested-select"; }
293
340
  static get encapsulation() { return "shadow"; }
@@ -327,17 +374,18 @@ export class NestedSelect {
327
374
  "mutable": false,
328
375
  "complexType": {
329
376
  "original": "string",
330
- "resolved": "string | undefined",
377
+ "resolved": "string",
331
378
  "references": {}
332
379
  },
333
380
  "required": false,
334
- "optional": true,
381
+ "optional": false,
335
382
  "docs": {
336
383
  "tags": [],
337
384
  "text": ""
338
385
  },
339
386
  "attribute": "max-height",
340
- "reflect": false
387
+ "reflect": false,
388
+ "defaultValue": "\"200px\""
341
389
  },
342
390
  "label": {
343
391
  "type": "string",
@@ -516,13 +564,32 @@ export class NestedSelect {
516
564
  "attribute": "all-selected-message",
517
565
  "reflect": false,
518
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"
519
585
  }
520
586
  };
521
587
  }
522
588
  static get states() {
523
589
  return {
524
590
  "isExpanded": {},
525
- "showClearSelectionButton": {}
591
+ "showClearSelectionButton": {},
592
+ "announcement": {}
526
593
  };
527
594
  }
528
595
  static get events() {
@@ -563,6 +630,12 @@ export class NestedSelect {
563
630
  "target": undefined,
564
631
  "capture": false,
565
632
  "passive": false
633
+ }, {
634
+ "name": "keydown",
635
+ "method": "handleKeyDown",
636
+ "target": undefined,
637
+ "capture": false,
638
+ "passive": false
566
639
  }, {
567
640
  "name": "click",
568
641
  "method": "handleClick",
@@ -1,13 +1,19 @@
1
1
  import { h, Host } from "@stencil/core";
2
+ import { handleDisabledAttribute, toBool } from "../../../global/functions";
2
3
  export class Optgroup {
3
4
  constructor() {
4
5
  this.label = undefined;
5
6
  this.isExpanded = false;
6
7
  this.multiple = false;
8
+ this.disabled = false;
7
9
  }
8
10
  get parentNestedSelect() {
9
11
  return this.el.parentElement;
10
12
  }
13
+ get isDisabled() {
14
+ // string "false" needs to be treated as bool False because react wrappers convert bool to string.
15
+ return toBool(this.disabled);
16
+ }
11
17
  isExpandedChanged() {
12
18
  if (this.isExpanded) {
13
19
  this.el.classList.add("visible");
@@ -25,15 +31,24 @@ export class Optgroup {
25
31
  this.el.classList.remove("visible");
26
32
  }, 250);
27
33
  }
34
+ if (this.parentNestedSelect.multiple) {
35
+ this.optionListEl.updateOptionVisibility();
36
+ }
28
37
  }
29
38
  async emitDeselection() {
30
39
  this.wmOptgroupAllDeselected.emit();
31
40
  }
41
+ async handleChildChange() {
42
+ this.optionListEl.handleChildChange();
43
+ }
32
44
  handleOptionKeyLeft() {
33
45
  this.isExpanded = false;
34
46
  }
47
+ componentWillLoad() {
48
+ handleDisabledAttribute(this.el, this.isDisabled);
49
+ }
35
50
  render() {
36
- 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)))));
37
52
  }
38
53
  static get is() { return "wm-optgroup"; }
39
54
  static get encapsulation() { return "shadow"; }
@@ -102,6 +117,24 @@ export class Optgroup {
102
117
  "attribute": "multiple",
103
118
  "reflect": false,
104
119
  "defaultValue": "false"
120
+ },
121
+ "disabled": {
122
+ "type": "boolean",
123
+ "mutable": false,
124
+ "complexType": {
125
+ "original": "boolean",
126
+ "resolved": "boolean",
127
+ "references": {}
128
+ },
129
+ "required": false,
130
+ "optional": false,
131
+ "docs": {
132
+ "tags": [],
133
+ "text": ""
134
+ },
135
+ "attribute": "disabled",
136
+ "reflect": false,
137
+ "defaultValue": "false"
105
138
  }
106
139
  };
107
140
  }
@@ -186,6 +219,23 @@ export class Optgroup {
186
219
  "text": "",
187
220
  "tags": []
188
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
+ }
189
239
  }
190
240
  };
191
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
+ }