lightning-base-components 1.16.2-alpha → 1.16.4-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.
- package/metadata/raptor.json +120 -0
- package/package.json +57 -1
- package/scopedImports/@salesforce-label-LightningForm.cancel.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.closeError.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.edit.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.editErrorHelp.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.error.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.errorPopoverHeading.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.preview.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.previewHeader.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.reload.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.save.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.saveFieldErrorSummary.js +1 -0
- package/scopedImports/@salesforce-label-LightningForm.undo.js +1 -0
- package/scopedImports/@salesforce-label-LightningLookup.messageWhenMissingInformation.js +1 -0
- package/src/lightning/button/__docs__/button.md +13 -0
- package/src/lightning/button/button.slds.css +155 -11
- package/src/lightning/buttonGroup/button-group.slds.css +35 -59
- package/src/lightning/buttonIcon/button-icon.slds.css +287 -122
- package/src/lightning/buttonIconStateful/button-icon-stateful.slds.css +224 -39
- package/src/lightning/buttonStateful/button-stateful.slds.css +3269 -0
- package/src/lightning/card/card.slds.css +50 -0
- package/src/lightning/colorPickerCustom/color-picker-custom.slds.css +180 -364
- package/src/lightning/colorPickerPanel/color-picker-panel.slds.css +46 -413
- package/src/lightning/colorPickerPanel/colorPickerPanel.css +9 -0
- package/src/lightning/colorPickerPanel/colorPickerPanel.html +2 -2
- package/src/lightning/datatable/datatable.js +2 -2
- package/src/lightning/datatable/rowSelection.js +21 -4
- package/src/lightning/datetimepicker/datetimepicker.html +1 -3
- package/src/lightning/datetimepicker/datetimepicker.js +5 -0
- package/src/lightning/fileDownload/__docs__/fileDownload.md +41 -0
- package/src/lightning/helptext/help-text.slds.css +184 -39
- package/src/lightning/icon/icon.slds.css +823 -3
- package/src/lightning/input/input-checkbox.slds.css +291 -32
- package/src/lightning/input/input-text.slds.css +70 -7
- package/src/lightning/input/input.js +1 -1
- package/src/lightning/inputAddress/__docs__/inputAddress.md +1 -1
- package/src/lightning/inputAddress/inputAddress.js +2 -1
- package/src/lightning/internationalizationLibrary/datetime/intlFormat.js +20 -2
- package/src/lightning/iso8601Utils/iso8601Utils.js +2 -3
- package/src/lightning/modal/__docs__/migration.md +158 -0
- package/src/lightning/modal/__docs__/modal.md +414 -0
- package/src/lightning/modal/__examples__disabled/all/all.css +7 -0
- package/src/lightning/modal/__examples__disabled/all/all.html +9 -0
- package/src/lightning/modal/__examples__disabled/all/all.js +25 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.css +7 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.html +9 -0
- package/src/lightning/modal/__examples__disabled/allform/allform.js +49 -0
- package/src/lightning/modal/__examples__disabled/allmulti/allmulti.html +24 -0
- package/src/lightning/modal/__examples__disabled/allmulti/allmulti.js +12 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.css +7 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.html +9 -0
- package/src/lightning/modal/__examples__disabled/basic/basic.js +27 -0
- package/src/lightning/modal/__examples__disabled/demo/demo.html +15 -0
- package/src/lightning/modal/__examples__disabled/demo/demo.js +13 -0
- package/src/lightning/modal/__examples__disabled/demoall/demoall.html +26 -0
- package/src/lightning/modal/__examples__disabled/demoall/demoall.js +13 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.css +3 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.html +146 -0
- package/src/lightning/modal/__examples__disabled/demoallform/demoallform.js +240 -0
- package/src/lightning/modal/__examples__disabled/demofootless/demofootless.html +17 -0
- package/src/lightning/modal/__examples__disabled/demofootless/demofootless.js +11 -0
- package/src/lightning/modal/__examples__disabled/demoheadless/demoheadless.html +20 -0
- package/src/lightning/modal/__examples__disabled/demoheadless/demoheadless.js +12 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.css +7 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.html +9 -0
- package/src/lightning/modal/__examples__disabled/footless/footless.js +19 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.css +7 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.html +9 -0
- package/src/lightning/modal/__examples__disabled/headless/headless.js +27 -0
- package/src/lightning/modal/modal.html +3 -0
- package/src/lightning/modal/modal.js +93 -0
- package/src/lightning/modal/modal.js-meta.xml +6 -0
- package/src/lightning/modalBody/__docs__/modalBody.md +61 -0
- package/src/lightning/modalBody/modalBody.html +13 -0
- package/src/lightning/modalBody/modalBody.js +203 -0
- package/src/lightning/modalBody/modalBody.js-meta.xml +6 -0
- package/src/lightning/modalFooter/__docs__/modalFooter.md +72 -0
- package/src/lightning/modalFooter/modalFooter.html +8 -0
- package/src/lightning/modalFooter/modalFooter.js +161 -0
- package/src/lightning/modalFooter/modalFooter.js-meta.xml +6 -0
- package/src/lightning/modalHeader/__docs__/modalHeader.md +64 -0
- package/src/lightning/modalHeader/modalHeader.html +16 -0
- package/src/lightning/modalHeader/modalHeader.js +204 -0
- package/src/lightning/modalHeader/modalHeader.js-meta.xml +6 -0
- package/src/lightning/primitiveBubble/tooltip.slds.css +45 -1
- package/src/lightning/primitiveCellFactory/primitiveCellFactory.js +4 -12
- package/src/lightning/primitiveColorpickerButton/color-picker-button.slds.css +2994 -319
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.html +14 -11
- package/src/lightning/primitiveDatatableIeditPanel/primitiveDatatableIeditPanel.js +1 -0
- package/src/lightning/primitiveIcon/icon.slds.css +823 -3
- package/src/lightning/radioGroup/input-radio-group.slds.css +168 -379
- package/src/lightning/spinner/spinner.slds.css +8 -2
- package/src/lightning/timepicker/timepicker.html +1 -4
- package/src/lightning/timepicker/timepicker.js +9 -5
- package/src/lightning/treeGrid/treeGrid.js +66 -1
- package/src/lightning/formattedAddress/__component__/formattedAddress.spec.js +0 -61
- package/src/lightning/formattedAddress/__component__/formattedAddressDisabled.spec.js +0 -20
- package/src/lightning/formattedAddress/__component__/x/basic/basic.html +0 -10
- package/src/lightning/formattedAddress/__component__/x/basic/basic.js +0 -17
- package/src/lightning/input/__component__/inputCheckbox.spec.js +0 -60
- package/src/lightning/input/__component__/inputDateTimePicker.spec.js +0 -60
- package/src/lightning/input/__component__/inputNumber.spec.js +0 -75
- package/src/lightning/input/__component__/inputSelection.spec.js +0 -83
- package/src/lightning/input/__component__/x/tall/tall.css +0 -5
- package/src/lightning/input/__component__/x/tall/tall.html +0 -5
- package/src/lightning/input/__component__/x/tall/tall.js +0 -7
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import ModalDemoFootless from 'modal/demofootless';
|
|
3
|
+
|
|
4
|
+
export default class ModalFootless extends LightningElement {
|
|
5
|
+
demoResult = 'unset';
|
|
6
|
+
|
|
7
|
+
handleDemoModal() {
|
|
8
|
+
ModalDemoFootless.open({
|
|
9
|
+
// LightningModal
|
|
10
|
+
size: 'small',
|
|
11
|
+
}).then((result) => {
|
|
12
|
+
if (result === null) {
|
|
13
|
+
this.demoResult = 'dismiss';
|
|
14
|
+
} else {
|
|
15
|
+
this.demoResult = result;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import ModalDemoHeadless from 'modal/demoheadless';
|
|
3
|
+
|
|
4
|
+
export default class ModalAllChildren extends LightningElement {
|
|
5
|
+
demoResult = 'unset';
|
|
6
|
+
|
|
7
|
+
handleDemoModal() {
|
|
8
|
+
ModalDemoHeadless.open({
|
|
9
|
+
// LightningModal
|
|
10
|
+
size: 'small',
|
|
11
|
+
label: 'Modal Header',
|
|
12
|
+
// ModalDemo
|
|
13
|
+
body: 'Select an option:',
|
|
14
|
+
options: [
|
|
15
|
+
{ id: 1, variant: 'neutral', label: 'Option 1' },
|
|
16
|
+
{ id: 2, variant: 'neutral', label: 'Option 2' },
|
|
17
|
+
{ id: 3, variant: 'brand', label: 'Main Option' },
|
|
18
|
+
],
|
|
19
|
+
}).then((result) => {
|
|
20
|
+
if (result === null) {
|
|
21
|
+
this.demoResult = 'dismiss';
|
|
22
|
+
} else {
|
|
23
|
+
this.demoResult = result;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { api } from 'lwc';
|
|
2
|
+
import LightningOverlay from 'lightning/overlay';
|
|
3
|
+
import { parent, instanceName, secure } from 'lightning/overlayUtils';
|
|
4
|
+
import LightningModalBase from 'lightning/modalBase';
|
|
5
|
+
import { normalizeBoolean } from 'lightning/utilsPrivate';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extend this component to create a message modal overlayed on the current app window.
|
|
9
|
+
*/
|
|
10
|
+
export default class LightningModal extends LightningOverlay {
|
|
11
|
+
static [parent] = LightningModalBase;
|
|
12
|
+
static [instanceName] = 'lightning-modal';
|
|
13
|
+
|
|
14
|
+
// private tracked state
|
|
15
|
+
_disableClose = false;
|
|
16
|
+
|
|
17
|
+
// public api
|
|
18
|
+
/**
|
|
19
|
+
* How much of the viewport width the modal uses. Supported values are small, medium, or large.
|
|
20
|
+
* @type {string}
|
|
21
|
+
* @default medium
|
|
22
|
+
*/
|
|
23
|
+
@api size = 'medium';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Sets the modal's title and assistive device label.
|
|
27
|
+
* @type {string}
|
|
28
|
+
* @required true
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
@api label = '';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Sets the modal's accessible description.
|
|
35
|
+
* @type {boolean}
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
@api description = '';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Prevents closing the modal by normal means like the ESC key, the close button, or `.close()`.
|
|
42
|
+
* @type {boolean}
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
@api
|
|
46
|
+
get disableClose() {
|
|
47
|
+
return this._disableClose;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set disableClose(value) {
|
|
51
|
+
const currentDisableClose = this._disableClose;
|
|
52
|
+
this._disableClose = normalizeBoolean(value);
|
|
53
|
+
// if there is a change, dispatch private event for modalBase
|
|
54
|
+
if (currentDisableClose !== this._disableClose) {
|
|
55
|
+
this.dispatchEvent(
|
|
56
|
+
new CustomEvent('privatedisableclosebutton', {
|
|
57
|
+
detail: {
|
|
58
|
+
disableClose: this._disableClose,
|
|
59
|
+
[secure]: true,
|
|
60
|
+
},
|
|
61
|
+
bubbles: true,
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@api
|
|
68
|
+
close(result) {
|
|
69
|
+
// Prevent close() private event until disableClose removed
|
|
70
|
+
if (!this.disableClose) {
|
|
71
|
+
const promise = new Promise((resolve) => {
|
|
72
|
+
this.dispatchEvent(
|
|
73
|
+
new CustomEvent('privateclose', {
|
|
74
|
+
detail: {
|
|
75
|
+
resolve,
|
|
76
|
+
[secure]: true,
|
|
77
|
+
},
|
|
78
|
+
bubbles: true,
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
super.close(result, promise);
|
|
83
|
+
} else {
|
|
84
|
+
// Intentionally console error when devs have not disabled elements
|
|
85
|
+
// when disableClose has been set true
|
|
86
|
+
let errorMsg =
|
|
87
|
+
'LightningModal - Any interactions (buttons, processes, etc) that call modal.close() should be ';
|
|
88
|
+
errorMsg += '(a) disabled, while disableClose api set true, and ';
|
|
89
|
+
errorMsg += '(b) re-enabled, when disableClose set false';
|
|
90
|
+
console.error(errorMsg);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
The `lightning-modal-body` component renders the content of a modal.
|
|
2
|
+
|
|
3
|
+
The modal components render in the order they appear in the template. Place the `lightning-modal-body`
|
|
4
|
+
component after `lightning-modal-header` and before `lightning-modal-footer` components, if you're providing them.
|
|
5
|
+
|
|
6
|
+
This sample code shows the expected order of the modal components. The modal content is
|
|
7
|
+
created in a separate component extended from `LightningModal`. See
|
|
8
|
+
[Lightning Web Components Developer Guide](docs/component-library/documentation/en/lwc/)
|
|
9
|
+
|
|
10
|
+
```html
|
|
11
|
+
<!-- my/modalDialog.html -->
|
|
12
|
+
<template>
|
|
13
|
+
<lightning-modal-header label="My Modal Heading">
|
|
14
|
+
Tagline content with <a href="https://salesforce.com">Salesforce.com link</a>
|
|
15
|
+
</lightning-modal-header>
|
|
16
|
+
<lightning-modal-body>
|
|
17
|
+
<!-- modal content specified in LightningModal component -->
|
|
18
|
+
{ content }
|
|
19
|
+
<!-- alternatively, add content here directly -->
|
|
20
|
+
</lightning-modal-body>
|
|
21
|
+
<lightning-modal-footer>
|
|
22
|
+
Footer Content
|
|
23
|
+
</lightning-modal-footer>
|
|
24
|
+
</template>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can nest content in `lightning-modal-body` or
|
|
28
|
+
`lightning-modal-body` automatically scrolls the modal's content when necessary.
|
|
29
|
+
The modal's maximum height is calculated to prevent the content from exceeding the screen height,
|
|
30
|
+
and scroll bars are automatically added.
|
|
31
|
+
#### Component Styling
|
|
32
|
+
|
|
33
|
+
`lightning-modal-body` implements the [modals](https://www.lightningdesignsystem.com/components/modals/) blueprint in the Salesforce Lightning Design System (SLDS).
|
|
34
|
+
|
|
35
|
+
To apply custom styling, use the `:host` selector or define a custom class using the `class` attribute.
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<lightning-modal-body class="my-modal-body">
|
|
39
|
+
|
|
40
|
+
</lightning-modal-body>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Use SLDS styling hooks to customize the component's styles. The `--sds-c-modal-content-*` hooks
|
|
44
|
+
enable you to customize the background color and text color of the modal body.
|
|
45
|
+
|
|
46
|
+
For example, specify the background color on the modal using the `sds-c-modal-content-color-background` custom property.
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
.my-modal-body {
|
|
50
|
+
--sds-c-modal-content-color-background: LightBlue;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
See the modal blueprint's [Styling Hooks Overview](https://www.lightningdesignsystem.com/components/modals/#Styling-Hooks-Overview) for a list of CSS custom properties.
|
|
55
|
+
|
|
56
|
+
For more information, see [Style Components Using Lightning Design System Styling Hooks](docs/component-library/documentation/lwc/lwc.create_components_css_custom_properties) in the Lightning Web Components Developer Guide.
|
|
57
|
+
|
|
58
|
+
#### Accessibility
|
|
59
|
+
|
|
60
|
+
See [Lightning Web Components Developer Guide](docs/component-library/documentation/en/lwc/) for more information about accessibility in modals.
|
|
61
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
id="modal-content"
|
|
4
|
+
class={modalBodyCssClasses}
|
|
5
|
+
data-content-container
|
|
6
|
+
onprivatescrollablecontainer={handleScrollableContainerRepositionEvent}
|
|
7
|
+
>
|
|
8
|
+
<slot
|
|
9
|
+
data-default-slot
|
|
10
|
+
onslotchange={handleDefaultSlotChange}
|
|
11
|
+
></slot>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { LightningElement } from 'lwc';
|
|
2
|
+
import { classSet } from 'lightning/utils';
|
|
3
|
+
import { getRealDOMId } from 'lightning/utilsPrivate';
|
|
4
|
+
import { findAllTabbableElements, filterTooltips } from 'lightning/focusUtils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The modal body component to display main content area in lightning modal.
|
|
8
|
+
* */
|
|
9
|
+
export default class LightningModalBody extends LightningElement {
|
|
10
|
+
// private tracked state
|
|
11
|
+
initialRender = true;
|
|
12
|
+
initialSlotRender = true;
|
|
13
|
+
unregisterCallback = null;
|
|
14
|
+
headerPresent = false;
|
|
15
|
+
footerPresent = false;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Handle the default slot change event
|
|
19
|
+
* Always register with parent every slot change
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
handleDefaultSlotChange() {
|
|
23
|
+
// Set this once so that parent can know slot has rendered
|
|
24
|
+
if (this.initialSlotRender) {
|
|
25
|
+
this.initialSlotRender = false;
|
|
26
|
+
}
|
|
27
|
+
this.registerWithParent();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Handle the 'privatescrollablecontainer from positionLibrary.js
|
|
32
|
+
* This repositions elements with overlays that use positionLibrary
|
|
33
|
+
* like helptext, combobox, etc
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
handleScrollableContainerRepositionEvent(event) {
|
|
37
|
+
const { callback: repositionCallback } = event.detail;
|
|
38
|
+
repositionCallback(event.composedPath());
|
|
39
|
+
event.stopPropagation();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Gets the CSS classes applicable to the modal body element.
|
|
44
|
+
* Hidden classes included for sibling components
|
|
45
|
+
* @return {string} CSS class applied to modal body
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
get modalBodyCssClasses() {
|
|
49
|
+
const classes = classSet('slds-modal__content slds-p-around_medium');
|
|
50
|
+
classes.add({
|
|
51
|
+
'slds-modal__content_headless': !this.headerPresent,
|
|
52
|
+
'slds-modal__content_footless': !this.footerPresent,
|
|
53
|
+
});
|
|
54
|
+
return classes.toString();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get a reference to the modal body content area wrapper div element
|
|
59
|
+
* @returns {(HTMLElement|null)} Outer wrapper for modal body
|
|
60
|
+
* @private
|
|
61
|
+
*/
|
|
62
|
+
get contentElem() {
|
|
63
|
+
return this.template.querySelector('[data-content-container]');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the main content div element assigned ID value
|
|
68
|
+
* @type {(string|null)}
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
get modalContentId() {
|
|
72
|
+
return getRealDOMId(this.contentElem);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get the default slot element for modal body component
|
|
77
|
+
* @returns {(HTMLElement|null)}
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
get defaultSlotElement() {
|
|
81
|
+
return this.template.querySelector('[data-default-slot]');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Determine whether the default slot is populated
|
|
86
|
+
* @returns {boolean}
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
get isDefaultSlotPopulated() {
|
|
90
|
+
const slotElement = this.defaultSlotElement;
|
|
91
|
+
if (slotElement && slotElement.assignedNodes) {
|
|
92
|
+
return slotElement.assignedNodes().length > 0;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get first tabbable element within modalBody, if exists
|
|
99
|
+
* This is passed to parent in order to autoFocus
|
|
100
|
+
* @return {(HTMLElement|null)}
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
get firstTabbableElement() {
|
|
104
|
+
let firstElem = null;
|
|
105
|
+
if (this.isDefaultSlotPopulated) {
|
|
106
|
+
const tabbableElements = findAllTabbableElements(
|
|
107
|
+
this.defaultSlotElement
|
|
108
|
+
);
|
|
109
|
+
const filteredElements = filterTooltips(tabbableElements);
|
|
110
|
+
if (filteredElements.length > 0) {
|
|
111
|
+
firstElem = filteredElements[0];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return firstElem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Set the max-height style inline on modalBody to prevent vertical height
|
|
119
|
+
* of overall modal to overflow
|
|
120
|
+
* This function is passed to the parent modal as a callback
|
|
121
|
+
* and will be called on first modal load, and then on window resize events
|
|
122
|
+
* as long as modalBody is present
|
|
123
|
+
* @param {Object} values Representing headerHeight, footerHeight, backdropHeight
|
|
124
|
+
* @returns {object} Representing headerHeight, footerHeight, backdropHeight
|
|
125
|
+
* @private
|
|
126
|
+
*/
|
|
127
|
+
handleUpdateHeight({ headerHeight, footerHeight, backdropHeight }) {
|
|
128
|
+
if (!this.initialRender) {
|
|
129
|
+
const paddingTop = 48; // 3rem
|
|
130
|
+
const paddingBottom = 80; // 5rem
|
|
131
|
+
const modalBodyMinHeight = 80;
|
|
132
|
+
const modalUsableHeight =
|
|
133
|
+
backdropHeight - paddingTop - paddingBottom;
|
|
134
|
+
const modalBodyUsableHeight =
|
|
135
|
+
modalUsableHeight - headerHeight - footerHeight;
|
|
136
|
+
const divElem = this.contentElem;
|
|
137
|
+
const styles = {
|
|
138
|
+
maxHeight: `${modalBodyUsableHeight}px`,
|
|
139
|
+
minHeight: `${modalBodyMinHeight}px`,
|
|
140
|
+
};
|
|
141
|
+
// set the max and min height value on modal body wrapper div
|
|
142
|
+
Object.assign(divElem.style, styles);
|
|
143
|
+
this.headerPresent = headerHeight !== 0;
|
|
144
|
+
this.footerPresent = footerHeight !== 0;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Register modalBody with modal parent, including callbacks to
|
|
150
|
+
* unregister the modal body, and update the modal body height
|
|
151
|
+
* this will get called multiple times over component lifecycle
|
|
152
|
+
* @type {CustomEvent}
|
|
153
|
+
* @private
|
|
154
|
+
*/
|
|
155
|
+
registerWithParent() {
|
|
156
|
+
const evtRegister = new CustomEvent('privatemodalbodyregister', {
|
|
157
|
+
bubbles: true,
|
|
158
|
+
composed: true,
|
|
159
|
+
detail: {
|
|
160
|
+
bodyId: this.modalContentId,
|
|
161
|
+
bodyIsPopulated: this.isDefaultSlotPopulated,
|
|
162
|
+
defaultSlotHasRendered: !this.initialSlotRender,
|
|
163
|
+
updateBodyCallback: this.handleUpdateHeight.bind(this),
|
|
164
|
+
unRegisterCallback: (unregisterCallback) => {
|
|
165
|
+
this.unregisterCallback = unregisterCallback;
|
|
166
|
+
},
|
|
167
|
+
firstTabbableElemRef: this.firstTabbableElement,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
this.dispatchEvent(evtRegister);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* When modal body is being created, initialize
|
|
175
|
+
* private tracked modal body state
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
initState() {
|
|
179
|
+
this.initialRender = true;
|
|
180
|
+
this.initialSlotRender = true;
|
|
181
|
+
this.unregisterCallback = null;
|
|
182
|
+
this.headerPresent = false;
|
|
183
|
+
this.footerPresent = false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
connectedCallback() {
|
|
187
|
+
// handle case where modalBody is added/removed/re-added to DOM
|
|
188
|
+
this.initState();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
disconnectedCallback() {
|
|
192
|
+
if (this.unregisterCallback) {
|
|
193
|
+
this.unregisterCallback();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
renderedCallback() {
|
|
198
|
+
if (this.initialRender) {
|
|
199
|
+
this.registerWithParent();
|
|
200
|
+
this.initialRender = false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
The `lightning-modal-footer` component creates a footer at the bottom of a modal dialog.
|
|
2
|
+
Use of a footer is optional.
|
|
3
|
+
|
|
4
|
+
The modal components render in the order they appear in the template.
|
|
5
|
+
Place the `lightning-modal-footer` component after the `lightning-modal-body` component.
|
|
6
|
+
|
|
7
|
+
This sample code shows the expected order of the modal components. The modal content is
|
|
8
|
+
created in a separate component extended from `LightningModal`. See
|
|
9
|
+
[Lightning Web Components Developer Guide](docs/component-library/documentation/en/lwc/)
|
|
10
|
+
|
|
11
|
+
This sample's `lightning-modal-footer` includes two `lightning-button` components,
|
|
12
|
+
but you can also use `<button>` elements.
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<!-- my/modalDialog.html -->
|
|
16
|
+
<template>
|
|
17
|
+
<lightning-modal-header label="My Modal">
|
|
18
|
+
</lightning-modal-header>
|
|
19
|
+
<lightning-modal-body>
|
|
20
|
+
<!-- modal content specified in LightningModal component -->
|
|
21
|
+
</lightning-modal-body>
|
|
22
|
+
<lightning-modal-footer>
|
|
23
|
+
<lightning-button
|
|
24
|
+
class="slds-button"
|
|
25
|
+
variant="neutral"
|
|
26
|
+
label="Cancel"
|
|
27
|
+
onclick={handleDismiss}
|
|
28
|
+
></lightning-button>
|
|
29
|
+
<lightning-button
|
|
30
|
+
class="slds-button slds-m-left_x-small"
|
|
31
|
+
variant="brand"
|
|
32
|
+
label="Save"
|
|
33
|
+
></lightning-button>
|
|
34
|
+
</lightning-modal-footer>
|
|
35
|
+
</template>
|
|
36
|
+
```
|
|
37
|
+
#### Component Styling
|
|
38
|
+
|
|
39
|
+
`lightning-modal-footer` implements the [modals](https://www.lightningdesignsystem.com/components/modals/) blueprint in the Salesforce Lightning Design System (SLDS).
|
|
40
|
+
|
|
41
|
+
To apply custom styling, use the `:host` selector or define a custom class using the `class` attribute.
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<lightning-modal-footer class="my-modal-footer">
|
|
45
|
+
|
|
46
|
+
</lightning-modal-footer>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use SLDS styling hooks to customize the component's styles. Several `--sds-c-modal-footer-*` hooks
|
|
50
|
+
enable you to customize the footer spacing, background color, and text color.
|
|
51
|
+
|
|
52
|
+
For example, specify the background color on the footer using the `sds-c-modal-footer-color-background` custom property.
|
|
53
|
+
|
|
54
|
+
```css
|
|
55
|
+
.my-modal-footer {
|
|
56
|
+
--sds-c-modal-footer-color-background: LightGray;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
See the modal blueprint's [Styling Hooks Overview](https://www.lightningdesignsystem.com/components/modals/#Styling-Hooks-Overview) for a list of CSS custom properties.
|
|
61
|
+
|
|
62
|
+
For more information, see [Style Components Using Lightning Design System Styling Hooks](docs/component-library/documentation/lwc/lwc.create_components_css_custom_properties) in the Lightning Web Components Developer Guide.
|
|
63
|
+
|
|
64
|
+
#### Accessibility
|
|
65
|
+
|
|
66
|
+
If you add buttons to the footer, you can use the accessibility attributes described in [`lightning-button`](bundle/lightning-button/documentation).
|
|
67
|
+
|
|
68
|
+
When the modal opens, focus goes to the first interactive element in the modal. If there are no links in the header or any interactive elements
|
|
69
|
+
in the modal body, the first footer button gets initial focus.
|
|
70
|
+
|
|
71
|
+
See [Lightning Web Components Developer Guide](docs/component-library/documentation/en/lwc/) for more information about accessibility in modals.
|
|
72
|
+
|