lightning-base-components 1.15.1-alpha → 1.15.2-alpha

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 (57) hide show
  1. package/metadata/raptor.json +27 -2
  2. package/package.json +6 -2
  3. package/scopedImports/@salesforce-label-LightningMap.defaultTitle.js +1 -0
  4. package/src/lightning/alert/__docs__/alert.md +0 -2
  5. package/src/lightning/baseCombobox/baseCombobox.html +2 -1
  6. package/src/lightning/baseCombobox/baseCombobox.js +41 -6
  7. package/src/lightning/button/button.js +22 -1
  8. package/src/lightning/checkboxGroup/checkboxGroup.html +2 -2
  9. package/src/lightning/checkboxGroup/checkboxGroup.js +9 -5
  10. package/src/lightning/combobox/__docs__/combobox.md +3 -1
  11. package/src/lightning/combobox/combobox.js +0 -1
  12. package/src/lightning/confirm/__docs__/confirm.md +0 -2
  13. package/src/lightning/datatable/__docs__/datatable.md +45 -0
  14. package/src/lightning/datatable/__wdio__/utam/utam.html +15 -0
  15. package/src/lightning/datatable/__wdio__/utam/utam.spec.js +208 -183
  16. package/src/lightning/datatable/datatable.js +12 -7
  17. package/src/lightning/datatable/inlineEdit.js +0 -5
  18. package/src/lightning/datatable/inlineEditShared.js +4 -2
  19. package/src/lightning/datatable/keyboard.js +7 -3
  20. package/src/lightning/datatable/rowSelection.js +8 -2
  21. package/src/lightning/datatable/state.js +1 -0
  22. package/src/lightning/datatable/templates/table/table.html +2 -2
  23. package/src/lightning/datatable/wrapText.js +1 -0
  24. package/src/lightning/datepicker/datepicker.html +1 -0
  25. package/src/lightning/datepicker/datepicker.js +10 -0
  26. package/src/lightning/datetimepicker/datetimepicker.html +2 -0
  27. package/src/lightning/datetimepicker/datetimepicker.js +8 -0
  28. package/src/lightning/dualListbox/dualListbox.js +2 -1
  29. package/src/lightning/formattedAddress/__docs__/formattedAddress.md +3 -0
  30. package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.html +22 -0
  31. package/src/lightning/formattedAddress/__examples__/customLocale/customLocale.js +3 -0
  32. package/src/lightning/formattedAddress/formattedAddress.js +7 -1
  33. package/src/lightning/groupedCombobox/groupedCombobox.html +2 -1
  34. package/src/lightning/groupedCombobox/groupedCombobox.js +16 -2
  35. package/src/lightning/input/input.html +6 -0
  36. package/src/lightning/input/input.js +2 -1
  37. package/src/lightning/inputAddress/__docs__/inputAddress.md +5 -0
  38. package/src/lightning/inputAddress/__examples__/customLocale/customLocale.html +12 -0
  39. package/src/lightning/inputAddress/__examples__/customLocale/customLocale.js +3 -0
  40. package/src/lightning/inputAddress/inputAddress.html +2 -0
  41. package/src/lightning/inputAddress/inputAddress.js +26 -3
  42. package/src/lightning/inputName/__docs__/inputName.md +2 -0
  43. package/src/lightning/inputName/inputName.html +4 -1
  44. package/src/lightning/inputUtils/inputUtils.js +11 -0
  45. package/src/lightning/picklist/picklist.js +6 -1
  46. package/src/lightning/prompt/__docs__/prompt.md +0 -2
  47. package/src/lightning/radioGroup/radioGroup.js +9 -0
  48. package/src/lightning/select/select.html +3 -1
  49. package/src/lightning/select/select.js +5 -1
  50. package/src/lightning/textarea/textarea.html +1 -0
  51. package/src/lightning/textarea/textarea.js +5 -0
  52. package/src/lightning/timepicker/timepicker.html +3 -1
  53. package/src/lightning/timepicker/timepicker.js +8 -0
  54. package/src/lightning/utilsPrivate/aria.js +26 -0
  55. package/src/lightning/utilsPrivate/linkify.js +1 -1
  56. package/src/lightning/utilsPrivate/utilsPrivate.js +7 -1
  57. package/src/lightning/icon/__component__/icon-spirite.spec.js +0 -59
@@ -6,6 +6,9 @@ examples:
6
6
  - name: latitude
7
7
  label: Formatted Address with Latitude/Longitude
8
8
  description: Displays an address that includes latitude and longitude.
9
+ - name: customLocale
10
+ label: Formatted Address with Custom Locale
11
+ description: Displays an address in the format of a specific locale.
9
12
  ---
10
13
 
11
14
  A `lightning-formatted-address` component displays addresses in a format and field order
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <h1 class="slds-text-heading_small">Address in Spanish format</h1>
3
+
4
+ <lightning-formatted-address
5
+ street="Avenida Concha Espina, Nº 1"
6
+ city="Madrid"
7
+ postal-code="28036"
8
+ country="España"
9
+ locale="es-ES"
10
+ ></lightning-formatted-address>
11
+
12
+ <h1 class="slds-text-heading_small">Address in Japanese format</h1>
13
+
14
+ <lightning-formatted-address
15
+ street="下連雀1丁目1−83"
16
+ city="三鷹市"
17
+ country="日本"
18
+ province="東京都"
19
+ postal-code="181–0013"
20
+ locale="ja-JP"
21
+ ></lightning-formatted-address>
22
+ </template>
@@ -0,0 +1,3 @@
1
+ import { LightningElement } from 'lwc';
2
+
3
+ export default class LightningExampleFormattedAddressCustomLocale extends LightningElement {}
@@ -25,6 +25,12 @@ export default class LightningFormattedAddress extends LightningElement {
25
25
 
26
26
  @track href;
27
27
 
28
+ /**
29
+ * The locale of the address. The default value is 'en-US'.
30
+ * @type {string}
31
+ */
32
+ @api locale = locale;
33
+
28
34
  /**
29
35
  * The street detail for the address.
30
36
  * @type {string}
@@ -188,7 +194,7 @@ export default class LightningFormattedAddress extends LightningElement {
188
194
  }
189
195
 
190
196
  get address() {
191
- const [langCode, countryCode] = locale.split('-');
197
+ const [langCode, countryCode] = this.locale.split('-');
192
198
  return (
193
199
  addressFormat.formatAddressAllFields(langCode, countryCode, {
194
200
  address: this.street,
@@ -57,7 +57,8 @@
57
57
  onendreached={handleEndReached}
58
58
  ondropdownopen={handleDropdownOpen}
59
59
  ondropdownopenrequest={handleDropdownOpenRequest}
60
- onselect={handleSelect}>
60
+ onselect={handleSelect}
61
+ disable-default-highlight={disableDefaultHighlight}>
61
62
  </lightning-base-combobox>
62
63
  </div>
63
64
  <template if:true={_hasPills}>
@@ -45,6 +45,14 @@ export default class LightningGroupedCombobox extends LightningElement {
45
45
  @api filterItems;
46
46
  @api filterInputText;
47
47
 
48
+ /**
49
+ * Whether disable the highlighting default item behavior
50
+ *
51
+ * @type {boolean}
52
+ * @memberof LightningGroupedCombobox
53
+ */
54
+ @api disableDefaultHighlight;
55
+
48
56
  @track _pills;
49
57
 
50
58
  @track _variant;
@@ -378,9 +386,15 @@ export default class LightningGroupedCombobox extends LightningElement {
378
386
  // eslint-disable-next-line @lwc/lwc/no-async-operation
379
387
  requestAnimationFrame(() => {
380
388
  if (this._connected) {
381
- this.template.querySelector(
389
+ // If a new pill has been added but the markup-conditional hasn't had a chance to
390
+ // initialize the pill container, and causes a null gack. Adding a quick safety
391
+ // check here to avoid this case
392
+ const pillContainer = this.template.querySelector(
382
393
  'lightning-pill-container'
383
- ).scrollTop = 0;
394
+ );
395
+ if (pillContainer) {
396
+ pillContainer.scrollTop = 0;
397
+ }
384
398
  }
385
399
  });
386
400
  }
@@ -65,6 +65,7 @@
65
65
  <span class={computedLabelClass}>{label}</span>
66
66
  <input type="checkbox" id="checkbox-toggle"
67
67
  aria-label={computedAriaLabel}
68
+ aria-invalid={computedAriaInvalid}
68
69
  accesskey={accesskey}
69
70
  onblur={handleBlur}
70
71
  onfocus={handleFocus}
@@ -101,6 +102,7 @@
101
102
  </template>
102
103
  <input type="checkbox" id="checkbox"
103
104
  aria-label={computedAriaLabel}
105
+ aria-invalid={computedAriaInvalid}
104
106
  accesskey={accesskey}
105
107
  onblur={handleBlur}
106
108
  onfocus={handleFocus}
@@ -127,6 +129,7 @@
127
129
  <div class="slds-checkbox_add-button">
128
130
  <input type="checkbox" id="checkbox-button"
129
131
  aria-label={computedAriaLabel}
132
+ aria-invalid={computedAriaInvalid}
130
133
  accesskey={accesskey}
131
134
  class="slds-assistive-text"
132
135
  onblur={handleBlur}
@@ -146,6 +149,7 @@
146
149
  <div class="slds-form-element__control">
147
150
  <span class="slds-radio">
148
151
  <input type="radio" id="radio"
152
+ aria-invalid={computedAriaInvalid}
149
153
  accesskey={accesskey}
150
154
  onblur={handleBlur}
151
155
  onfocus={handleFocus}
@@ -174,6 +178,7 @@
174
178
  <lightning-primitive-file-droppable-zone multiple={multiple} disabled={disabled}>
175
179
  <input type="file" id="input-file"
176
180
  aria-label={computedAriaLabel}
181
+ aria-invalid={computedAriaInvalid}
177
182
  accesskey={accesskey}
178
183
  class="slds-file-selector__input slds-assistive-text"
179
184
  onblur={handleBlur}
@@ -228,6 +233,7 @@
228
233
  autocomplete={autocomplete}
229
234
  accesskey={accesskey}
230
235
  aria-label={computedAriaLabel}
236
+ aria-invalid={computedAriaInvalid}
231
237
  disabled={disabled}
232
238
  minlength="4"
233
239
  maxlength="7"
@@ -30,6 +30,7 @@ import {
30
30
  synchronizeAttrs,
31
31
  decorateInputForDragon,
32
32
  setDecoratedDragonInputValueWithoutEvent,
33
+ computeAriaInvalid,
33
34
  } from 'lightning/utilsPrivate';
34
35
  import AriaObserver from 'lightning/ariaObserver';
35
36
  import { normalizeInput } from './normalize';
@@ -1178,7 +1179,7 @@ export default class LightningInput extends LightningElement {
1178
1179
 
1179
1180
  get computedAriaInvalid() {
1180
1181
  // W-8796658: aria-invalid should always follow the visual indication of errors
1181
- return !!this._helpMessage;
1182
+ return computeAriaInvalid(this._helpMessage, this.value);
1182
1183
  }
1183
1184
 
1184
1185
  get isLabelHidden() {
@@ -6,6 +6,9 @@ examples:
6
6
  - name: stateAndCountryPicklists
7
7
  label: Address With State and Country Picklists
8
8
  description: Address fields support predefined lists of states and countries.
9
+ - name: customLocale
10
+ label: Address With Custom Locale
11
+ description: Address input fields ordered depending on custom locale value.
9
12
  ---
10
13
 
11
14
  A `lightning-input-address` component creates a compound field that includes the following constituent fields.
@@ -290,6 +293,8 @@ The `label` attribute creates an HTML `<label>` element for your address.
290
293
  To hide the compound field label from view and make it available to assistive technology, use the `label-hidden` variant.
291
294
  This variant keeps the constituent field labels in view.
292
295
 
296
+ This component uses `button` elements for picklists to comply with the [Lightning Design System combobox blueprint](https://www.lightningdesignsystem.com/components/combobox/#%22Input%22-markup) for select-only comboboxes.
297
+
293
298
  #### Custom Events
294
299
 
295
300
  **`change`**
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <lightning-input-address
3
+ address-label="Address"
4
+ street-label="Street"
5
+ city-label="City"
6
+ country-label="Country"
7
+ province-label="Prefecture"
8
+ postal-code-label="Postal Code"
9
+ locale="ja-JP"
10
+ field-level-help="Help Text for input address field" >
11
+ </lightning-input-address>
12
+ </template>
@@ -0,0 +1,3 @@
1
+ import { LightningElement } from 'lwc';
2
+
3
+ export default class InputAddressCustomLocale extends LightningElement {}
@@ -15,6 +15,7 @@
15
15
  class="slds-form-element slds-show slds-size_6-of-6"
16
16
  onchange={handleAddress}
17
17
  placeholder={addressLookupPlaceholder}
18
+ label={addressLookupLabel}
18
19
  disabled={disabled}>
19
20
  </lightning-lookup-address>
20
21
  </div>
@@ -65,6 +66,7 @@
65
66
  <template if:true={field.isPicklist}>
66
67
  <lightning-picklist
67
68
  key={field.name}
69
+ suppress-none-option={field.suppressNoneOption}
68
70
  data-field={field.name}
69
71
  class={field.classnames}
70
72
  name={field.name}
@@ -111,6 +111,13 @@ export default class LightningInputAddress extends LightningElement {
111
111
  */
112
112
  @api addressLookupPlaceholder;
113
113
 
114
+ /**
115
+ * The label for the address lookup field option.
116
+ * Only visible when show-address-lookup is set to true and label string is passed
117
+ * @type {string}
118
+ */
119
+ @api addressLookupLabel;
120
+
114
121
  /**
115
122
  * The array of label-value pairs for the province. Displays a dropdown menu of options.
116
123
  * @type {list}
@@ -130,6 +137,12 @@ export default class LightningInputAddress extends LightningElement {
130
137
  */
131
138
  @api countryDisabled;
132
139
 
140
+ /**
141
+ * Determines the order of the inputs for the address field.
142
+ * @type {string}
143
+ */
144
+ @api locale = locale;
145
+
133
146
  @track _showAddressLookup;
134
147
  @track _fieldLevelHelp;
135
148
  @track _variant;
@@ -469,12 +482,12 @@ export default class LightningInputAddress extends LightningElement {
469
482
  get inputOrder() {
470
483
  const hasCountryPicklist =
471
484
  this.fieldsTypeMeta.country.type === FIELD_TYPE.PICKLIST;
472
- const [langCode, countryCode] = locale.split('-');
485
+ const [langCode, countryCode] = this.locale.split('-');
473
486
  return getInputOrder(langCode, countryCode, hasCountryPicklist);
474
487
  }
475
488
 
476
489
  get requiredFields() {
477
- const [langCode, countryCode] = locale.split('-');
490
+ const [langCode, countryCode] = this.locale.split('-');
478
491
  return getRequiredFields(langCode, countryCode);
479
492
  }
480
493
 
@@ -502,18 +515,28 @@ export default class LightningInputAddress extends LightningElement {
502
515
  const rowList = row.map((field) => {
503
516
  const { name, type, required, maxlength, autocomplete } = field;
504
517
  const widthClass = getFieldWidthClass(field);
518
+ const value = this.getFieldValue(name);
519
+ const suppressNoneOption =
520
+ this.required &&
521
+ !!required &&
522
+ type === FIELD_TYPE.PICKLIST &&
523
+ value &&
524
+ value !== ''
525
+ ? true
526
+ : false;
505
527
 
506
528
  return {
507
529
  isInput: type === FIELD_TYPE.INPUT,
508
530
  isPicklist: type === FIELD_TYPE.PICKLIST,
509
531
  isTextArea: type === FIELD_TYPE.TEXTAREA,
510
- value: this.getFieldValue(name),
532
+ value: value,
511
533
  options: this.getFieldOptions(name),
512
534
  required: this.required && !!required,
513
535
  disabled: this.getFieldDisabled(name) || this.disabled,
514
536
  classnames: `slds-form-element slds-show ${widthClass}`,
515
537
  placeholder: this.getFieldPlaceholder(name),
516
538
  label: this.getFieldLabel(name),
539
+ suppressNoneOption: suppressNoneOption,
517
540
  autocomplete,
518
541
  maxlength,
519
542
  name,
@@ -154,6 +154,8 @@ See the __Custom Events__ section for a list of `event.target` properties. For m
154
154
  You can use custom labels that display translated values. For more information, see the
155
155
  [Access Static Resources, Labels, Internationalization Properties, and User IDs](docs/component-library/documentation/lwc/create_global_value_providers).
156
156
 
157
+ This component uses `button` elements for dropdown menus to comply with the [Lightning Design System combobox blueprint](https://www.lightningdesignsystem.com/components/combobox/#%22Input%22-markup) for select-only comboboxes.
158
+
157
159
  #### Input Validation
158
160
 
159
161
  When you set `required`, a red asterisk is displayed on the Last Name
@@ -2,9 +2,12 @@
2
2
  <fieldset class="slds-form-element">
3
3
  <legend class={computedLegendClass}>
4
4
  <template if:true={required}>
5
- <abbr class="slds-required" title={i18n.required}>*</abbr>
5
+ <abbr class="slds-required" title={i18n.required} aria-hidden="true">*</abbr>
6
6
  </template>
7
7
  {label}
8
+ <template if:true={required}>
9
+ <span class="slds-assistive-text">{i18n.required}</span>
10
+ </template>
8
11
  </legend>
9
12
  <template if:true={fieldLevelHelp}>
10
13
  <lightning-helptext content={fieldLevelHelp}></lightning-helptext>
@@ -15,3 +15,14 @@ export function isEmptyString(s) {
15
15
  (typeof s === 'string' && s.trim() === '')
16
16
  );
17
17
  }
18
+
19
+ export function isEmptyObject(obj) {
20
+ if (obj === undefined || obj === null || typeof obj !== 'object') {
21
+ return false;
22
+ }
23
+ // eslint-disable-next-line guard-for-in
24
+ for (const name in obj) {
25
+ return false;
26
+ }
27
+ return true;
28
+ }
@@ -31,6 +31,7 @@ export default class LightningPicklist extends LightningElement {
31
31
  @api placeholder;
32
32
  @api variant;
33
33
  @api autocomplete = 'off';
34
+ @api suppressNoneOption;
34
35
 
35
36
  set fieldLevelHelp(value) {
36
37
  this._fieldLevelHelp = value;
@@ -86,6 +87,7 @@ export default class LightningPicklist extends LightningElement {
86
87
  // reset the flag that hides the required indicator when we have no options
87
88
  this._requiredButDisabled = false;
88
89
  }
90
+
89
91
  @api
90
92
  get required() {
91
93
  return this._required;
@@ -293,7 +295,10 @@ export default class LightningPicklist extends LightningElement {
293
295
  // We could have set required=false if the picklist had no options, see updateDisabledState and updateRequiredState
294
296
  const isRequiredPicklist = this.required || this._requiredButDisabled;
295
297
 
296
- if (isRequiredPicklist && numberOfOptions === 1) {
298
+ if (
299
+ this.suppressNoneOption ||
300
+ (isRequiredPicklist && numberOfOptions === 1)
301
+ ) {
297
302
  return false;
298
303
  }
299
304
 
@@ -1,7 +1,5 @@
1
1
  The `lightning/prompt` module lets you create an prompt modal within your component. Use `LightningPrompt` on your components to ask the user to provide information before they continue.
2
2
 
3
- `lightning/prompt` is not supported on mobile devices.
4
-
5
3
  Use `LightningPrompt.open()` instead of the native `window.prompt()` for a more consistent user experience. They have similar functions, but `LightningPrompt.open()` works in cross-origin iframes, where the `.prompt()` method is no longer supported in Chrome and Safari. Unlike `window.prompt()`, `LightningPrompt.open()` doesn't halt execution on the page, it returns a Promise. Use `async`/`await` or `.then()` for any code you want to execute after the prompt has closed.
6
4
 
7
5
  Import `LightningPrompt` from the `lightning/prompt` module in the component that will launch the prompt modal, and call `LightningPrompt.open()` with your desired attributes.
@@ -90,8 +90,17 @@ export default class LightningRadioGroup extends LightningElement {
90
90
  });
91
91
  }
92
92
 
93
+ get fieldsetElement() {
94
+ return this.template.querySelector('fieldset');
95
+ }
96
+
93
97
  renderedCallback() {
94
98
  this.synchronizeA11y();
99
+ synchronizeAttrs(this.fieldsetElement, {
100
+ 'aria-describedby': getRealDOMId(
101
+ this.template.querySelector('[data-help-message]')
102
+ ),
103
+ });
95
104
  }
96
105
 
97
106
  /**
@@ -21,7 +21,9 @@
21
21
  onfocus={handleFocus}
22
22
  required={required}
23
23
  accesskey={accessKey}
24
- size={size}>
24
+ size={size}
25
+ aria-invalid={computedAriaInvalid}
26
+ >
25
27
  <template for:each={options} for:item="option">
26
28
  <template if:true={option.disabled}>
27
29
  <option disabled key={option.value} value={option.value}>{option.label}</option>
@@ -80,11 +80,15 @@ export default class LightningSelect extends LightningElement {
80
80
  }
81
81
  synchronizeAttrs(this.selectElement, {
82
82
  'aria-describedby': getRealDOMId(
83
- this.template.querySelector('#help-message')
83
+ this.template.querySelector('[data-help-message]')
84
84
  ),
85
85
  });
86
86
  }
87
87
 
88
+ get computedAriaInvalid() {
89
+ return !!this._helpMessage || undefined;
90
+ }
91
+
88
92
  /**
89
93
  * Help text detailing the purpose and function of the menu of options.
90
94
  * The text is displayed in a tooltip above the menu.
@@ -9,6 +9,7 @@
9
9
  <div class="slds-form-element__control slds-grow textarea-container">
10
10
  <textarea id="input" class="slds-textarea"
11
11
  aria-describedby={computedUniqueHelpElementId}
12
+ aria-invalid={computedAriaInvalid}
12
13
  autocomplete={autocomplete}
13
14
  oninput={handleInput}
14
15
  onchange={handleChange}
@@ -10,6 +10,7 @@ import {
10
10
  classListMutation,
11
11
  decorateInputForDragon,
12
12
  setDecoratedDragonInputValueWithoutEvent,
13
+ computeAriaInvalid,
13
14
  } from 'lightning/utilsPrivate';
14
15
  import {
15
16
  InteractingState,
@@ -478,6 +479,10 @@ export default class LightningTextarea extends LightningElement {
478
479
  }
479
480
  return this._constraintApi;
480
481
  }
482
+
483
+ get computedAriaInvalid() {
484
+ return computeAriaInvalid(this._helpMessage, this.value);
485
+ }
481
486
  }
482
487
 
483
488
  LightningTextarea.interopMap = {
@@ -31,7 +31,9 @@
31
31
  ondropdownopenrequest={handleDropdownOpenRequest}
32
32
  onfocus={handleFocus}
33
33
  onblur={handleBlur}
34
- onselect={handleTimeSelect}>
34
+ onselect={handleTimeSelect}
35
+ data-aria-invalid={computedAriaInvalid}
36
+ >
35
37
  </lightning-base-combobox>
36
38
  </div>
37
39
 
@@ -23,6 +23,7 @@ import {
23
23
  normalizeBoolean,
24
24
  synchronizeAttrs,
25
25
  normalizeString,
26
+ computeAriaInvalid,
26
27
  } from 'lightning/utilsPrivate';
27
28
  import { normalizeVariant, VARIANT } from 'lightning/inputUtils';
28
29
 
@@ -543,4 +544,11 @@ export default class LightningTimePicker extends LightningElement {
543
544
  this.ariaLabelledByElement.length
544
545
  );
545
546
  }
547
+
548
+ get computedAriaInvalid() {
549
+ const isAriaInvalid =
550
+ this.template.host.getAttribute('data-aria-invalid') ||
551
+ this._errorMessage;
552
+ return computeAriaInvalid(isAriaInvalid, this.value);
553
+ }
546
554
  }
@@ -135,3 +135,29 @@ export function isAriaDescriptionSupported() {
135
135
  }
136
136
  return ariaDescriptionSupported;
137
137
  }
138
+
139
+ export function updateAriaInvalidOnElement(element, isInvalid) {
140
+ if (isInvalid) {
141
+ element.setAttribute('aria-invalid', true);
142
+ } else {
143
+ element.removeAttribute('aria-invalid');
144
+ }
145
+ }
146
+
147
+ /**
148
+ * If value is empty, then do no calculate aria-invalid. This is intentional for 240.
149
+ * In the future, we may be removing emptiness this check.
150
+ *
151
+ * Then if isInvalid is truthy, return true else return undefined to remove
152
+ * aria-invalid attribute.
153
+ *
154
+ * @param isInvalid
155
+ * @param value
156
+ * @returns {boolean|undefined}
157
+ */
158
+ export function computeAriaInvalid(isInvalid, value) {
159
+ if (value === undefined || value === null || value === '') {
160
+ return undefined;
161
+ }
162
+ return !!isInvalid || undefined;
163
+ }
@@ -107,6 +107,6 @@ export function parseToFormattedLinkifiedParts(text, ignoreNewLines = false) {
107
107
  */
108
108
  export function parseToFormattedParts(text) {
109
109
  return text.split(newLineRegex).map((part, index) => {
110
- return index % 2 === 0 ? getTextPart(part) : getNewlinePart();
110
+ return index % 2 === 0 ? getTextPart(part) : getNewlinePart(index);
111
111
  });
112
112
  }
@@ -1,5 +1,11 @@
1
1
  export { assert } from './assert';
2
- export { ARIA, ARIA_TO_CAMEL, isAriaDescriptionSupported } from './aria';
2
+ export {
3
+ ARIA,
4
+ ARIA_TO_CAMEL,
5
+ isAriaDescriptionSupported,
6
+ updateAriaInvalidOnElement,
7
+ computeAriaInvalid,
8
+ } from './aria';
3
9
  export { EventEmitter } from './eventEmitter';
4
10
  export { toNorthAmericanPhoneNumber } from './phonify';
5
11
  export * from './linkUtils';
@@ -1,59 +0,0 @@
1
- import { createElement } from 'lwc';
2
- import Element from 'lightning/icon';
3
-
4
- function createIcon(props = {}) {
5
- const element = createElement('lightning-icon', { is: Element });
6
-
7
- Object.assign(element, props);
8
- document.body.appendChild(element);
9
- return element;
10
- }
11
-
12
- function verifySvgDataKey(element, value) {
13
- const primitiveIcon = element.shadowRoot.querySelector(
14
- 'lightning-primitive-icon'
15
- );
16
- const svg = primitiveIcon.shadowRoot.querySelector('svg');
17
- expect(svg.getAttribute('data-key')).toBe(value);
18
- }
19
-
20
- describe('lightning-icon', () => {
21
- it('should render with prebuilt icon for utility', () => {
22
- const element = createIcon({
23
- iconName: 'utility:check',
24
- });
25
-
26
- verifySvgDataKey(element, 'check');
27
- });
28
- it('should render with prebuilt icon for standard', () => {
29
- const element = createIcon({
30
- iconName: 'standard:account',
31
- });
32
-
33
- verifySvgDataKey(element, 'account');
34
- });
35
-
36
- it('should render with prebuilt icon for action', () => {
37
- const element = createIcon({
38
- iconName: 'action:back',
39
- });
40
-
41
- verifySvgDataKey(element, 'back');
42
- });
43
-
44
- it('should render with prebuilt icon for doctype', () => {
45
- const element = createIcon({
46
- iconName: 'doctype:image',
47
- });
48
-
49
- verifySvgDataKey(element, 'image');
50
- });
51
-
52
- it('should render with prebuilt icon for custom', () => {
53
- const element = createIcon({
54
- iconName: 'custom:custom1',
55
- });
56
-
57
- verifySvgDataKey(element, 'custom1');
58
- });
59
- });