@outbook/webcomponents-modal-dialog 1.0.3 → 1.1.0
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/README.md +101 -40
- package/_style/modal-dialog-content.style.js +4 -0
- package/_style/modal-dialog-message.style.js +4 -0
- package/modal-dialog.js +80 -28
- package/package.json +3 -2
- package/_lib/tmpl-slot.js +0 -9
- package/_style/modal-dialog.style.js +0 -4
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @outbook/webcomponents-modal-dialog
|
|
2
2
|
|
|
3
|
-
This package provides a
|
|
3
|
+
This package provides a modal dialog component with two built-in layouts:
|
|
4
|
+
|
|
5
|
+
- `content`: full-screen content dialog
|
|
6
|
+
- `message`: centered message dialog with veil
|
|
7
|
+
|
|
8
|
+
The package is intended to be used through the `ModalDialog()` wrapper, which creates, renders, and removes the dialog for you.
|
|
4
9
|
|
|
5
10
|
## Installation
|
|
6
11
|
|
|
@@ -10,16 +15,18 @@ npm install @outbook/webcomponents-modal-dialog
|
|
|
10
15
|
|
|
11
16
|
## Usage
|
|
12
17
|
|
|
13
|
-
###
|
|
18
|
+
### Content Dialog
|
|
14
19
|
|
|
15
20
|
```javascript
|
|
16
|
-
import {html} from 'lit';
|
|
17
|
-
import {ModalDialog} from '@outbook/webcomponents-modal-dialog';
|
|
21
|
+
import { html } from 'lit';
|
|
22
|
+
import { ModalDialog } from '@outbook/webcomponents-modal-dialog';
|
|
18
23
|
|
|
19
|
-
function openExampleModal() {
|
|
24
|
+
function openExampleModal(ev) {
|
|
20
25
|
ModalDialog({
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
origin: ev.currentTarget.id,
|
|
27
|
+
title: 'Example modal',
|
|
28
|
+
type: 'content',
|
|
29
|
+
view: ({ closeDialog }) => html`
|
|
23
30
|
<p>This is the content of the modal dialog.</p>
|
|
24
31
|
<button @click="${closeDialog}">Close</button>
|
|
25
32
|
`
|
|
@@ -28,60 +35,114 @@ function openExampleModal() {
|
|
|
28
35
|
|
|
29
36
|
function render() {
|
|
30
37
|
return html`
|
|
31
|
-
<button @click="${openExampleModal}">
|
|
38
|
+
<button id="open-modal" @click="${openExampleModal}">
|
|
39
|
+
Open modal
|
|
40
|
+
</button>
|
|
32
41
|
`;
|
|
33
42
|
}
|
|
34
43
|
```
|
|
35
44
|
|
|
36
|
-
###
|
|
37
|
-
|
|
38
|
-
You can also use the custom element directly in your HTML. Remember to import the component's JavaScript for the custom element to be defined. Note that direct HTML usage for `outbook-modal-dialog` is primarily for rendering by the `ModalDialog` wrapper function.
|
|
45
|
+
### Message Dialog With Actions
|
|
39
46
|
|
|
40
47
|
```javascript
|
|
41
|
-
import '
|
|
42
|
-
|
|
48
|
+
import { html } from 'lit';
|
|
49
|
+
import { ModalDialog } from '@outbook/webcomponents-modal-dialog';
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
const saveAction = ({ detail }) => {
|
|
52
|
+
console.log('button interaction:', detail.originalEvent.type);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function openMessageModal(ev) {
|
|
56
|
+
ModalDialog({
|
|
57
|
+
origin: ev.currentTarget.id,
|
|
58
|
+
title: 'Confirm action',
|
|
59
|
+
type: 'message',
|
|
60
|
+
view: () => html`
|
|
61
|
+
<p>Do you want to save your changes?</p>
|
|
62
|
+
`,
|
|
63
|
+
actions: [
|
|
64
|
+
{
|
|
65
|
+
text: 'Save',
|
|
66
|
+
type: 'positive',
|
|
67
|
+
eventFn: saveAction
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
text: 'Cancel',
|
|
71
|
+
type: 'neutral',
|
|
72
|
+
handler: 'close'
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
47
77
|
```
|
|
48
78
|
|
|
49
|
-
##
|
|
79
|
+
## API
|
|
50
80
|
|
|
51
|
-
|
|
81
|
+
### `ModalDialog(props)`
|
|
52
82
|
|
|
53
|
-
|
|
83
|
+
Creates and renders an `outbook-modal-dialog`.
|
|
54
84
|
|
|
55
|
-
|
|
85
|
+
| Property | Type | Default | Description |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| `origin` | `String` | `undefined` | Id of the element that opened the dialog. Focus is returned to this element when the dialog closes. |
|
|
88
|
+
| `title` | `String` | `undefined` | Dialog title shown in the header. |
|
|
89
|
+
| `type` | `String` | `'content'` | Dialog layout. Supported values are `'content'` and `'message'`. |
|
|
90
|
+
| `view` | `Function` | `null` | Function that returns the dialog body. Receives `{ closeDialog }`. |
|
|
91
|
+
| `tabs` | `Array` | `[]` | Tab configuration passed to `@outbook/webcomponents-tabs`. If present, it is rendered instead of `view`. |
|
|
92
|
+
| `hasScroll` | `Boolean` | `true` | Enables scrolling for `content` dialogs. Ignored for `message` dialogs and for dialogs with tabs. |
|
|
93
|
+
| `actions` | `Array` | `[]` | Footer button configuration. |
|
|
94
|
+
| `portalWrapperId` | `String` | `null` | Optional container element id for rendering the dialog portal. Defaults to `document.body`. |
|
|
95
|
+
| `content` | `Function` | `undefined` | Optional fallback slot content renderer used internally by the component. |
|
|
56
96
|
|
|
57
|
-
|
|
58
|
-
|------------------------------|-------------|-------------|---------------------------------------------------------------------------------------------------------|
|
|
59
|
-
| `title` | `String` | `''` | The title displayed in the modal dialog's header. |
|
|
60
|
-
| `view` | `Function` | `null` | A function that returns the content to be displayed in the modal body. Receives `closeDialog` as an argument. |
|
|
61
|
-
| `tabs` | `Array` | `[]` | An array of tab configurations (`{ label, content }`) to display tabbed content. Overrides `view` if present. |
|
|
62
|
-
| `hasScroll` | `Boolean` | `true` | If `true`, the content area will be scrollable. Ignored if `tabs` are used. |
|
|
63
|
-
| `extraClasses` | `String` | `undefined` | Additional CSS classes to apply to the dialog's host element. |
|
|
97
|
+
### `actions`
|
|
64
98
|
|
|
65
|
-
|
|
99
|
+
Each action item supports the following properties:
|
|
66
100
|
|
|
67
|
-
|
|
101
|
+
| Property | Type | Default | Description |
|
|
102
|
+
|---|---|---|---|
|
|
103
|
+
| `text` | `String` | `undefined` | Button label. |
|
|
104
|
+
| `type` | `String` | `'neutral'` | Visual variant. Supported values are `'neutral'`, `'positive'`, and `'negative'`. |
|
|
105
|
+
| `handler` | `String` | `undefined` | Name of an internal dialog handler. Currently `close` is supported. |
|
|
106
|
+
| `eventFn` | `Function` | `() => {}` | Handler for the button `button-interaction` event when no `handler` is defined. |
|
|
68
107
|
|
|
69
|
-
|
|
108
|
+
Action handler resolution order:
|
|
70
109
|
|
|
71
|
-
|
|
110
|
+
1. `handlers[handler]`
|
|
111
|
+
2. `eventFn`
|
|
112
|
+
3. empty function
|
|
113
|
+
|
|
114
|
+
When `handler: 'close'` is used, the dialog closes and focus returns to `origin`.
|
|
115
|
+
|
|
116
|
+
## Component
|
|
117
|
+
|
|
118
|
+
### `outbook-modal-dialog`
|
|
119
|
+
|
|
120
|
+
This is the underlying custom element used by `ModalDialog()`. It is not usually instantiated directly, because the wrapper manages portal rendering, lifecycle, keyboard handling, and focus return.
|
|
121
|
+
|
|
122
|
+
## Styling
|
|
123
|
+
|
|
124
|
+
The component uses Shadow DOM and exposes styling hooks through CSS custom properties.
|
|
72
125
|
|
|
73
126
|
### Custom Properties
|
|
74
127
|
|
|
75
|
-
|
|
128
|
+
| Custom Property | Description |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `--outbook-modal-dialog--veil-color` | Veil color behind the dialog. Used by `message` dialogs. |
|
|
131
|
+
| `--outbook-modal-dialog--neutral-background` | Background color for neutral action buttons. |
|
|
132
|
+
| `--outbook-modal-dialog--neutral-background-hover` | Hover background color for neutral action buttons. |
|
|
133
|
+
| `--outbook-modal-dialog--positive-background` | Background color for positive action buttons. |
|
|
134
|
+
| `--outbook-modal-dialog--positive-background-hover` | Hover background color for positive action buttons. |
|
|
135
|
+
| `--outbook-modal-dialog--negative-background` | Background color for negative action buttons. |
|
|
136
|
+
| `--outbook-modal-dialog--negative-background-hover` | Hover background color for negative action buttons. |
|
|
137
|
+
|
|
138
|
+
The dialog also forwards `--outbook-scrollable--indicator-max-width` internally for the scrollable content area.
|
|
139
|
+
|
|
140
|
+
## Notes
|
|
76
141
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
| `--outbook-modal-dialog--button-close-text-display` | Controls the display of the close button text. |
|
|
82
|
-
| `--outbook-modal-dialog--main-text-color` | The main text color within the modal. |
|
|
83
|
-
| `--outbook-modal-dialog--main-background-color` | The main background color of the modal. |
|
|
84
|
-
| `--outbook-modal-dialog--header-background-color` | The background color of the modal header. |
|
|
142
|
+
- `type: 'content'` renders a full-screen dialog layout.
|
|
143
|
+
- `type: 'message'` renders a centered dialog with a veil overlay.
|
|
144
|
+
- The close button responds to mouse click, `Enter`, and `Space`.
|
|
145
|
+
- `Escape` closes the dialog.
|
|
85
146
|
|
|
86
147
|
## License
|
|
87
148
|
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { css } from 'lit';
|
|
3
|
+
|
|
4
|
+
export default css`:host{display:block;color-scheme:inherit;container-name:modalDialog;container-type:inline-size;--outbook-scrollable--indicator-max-width: 60rem;--_container-max-width: 60rem;--_height: 100dvh;--_button-close-text-display: none;--_main-text-color: light-dark( oklch(20.5% 0 0deg), oklch(98.5% 0 0deg) );--_main-background-color: light-dark( oklch(100% 0 0deg), oklch(14.5% 0 0deg) );--_header-background-color: light-dark( oklch(92.2% 0 0deg), oklch(43.9% 0 0deg) )}:host .dialog--in-element{--_height: 100%}*{box-sizing:border-box}@container modalDialog (min-width: 540px){.dialog{--_button-close-text-display: inline-block}}.dialog{position:fixed;width:100%;height:var(--_height);top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:var(--background-color);color:var(--_main-text-color);z-index:2;transition:background-color 0.3s,color 0.3s}.dialog__close-button{display:flex;align-items:center;cursor:pointer}.dialog__close-button-icon{width:1.5rem;height:1.5rem}.dialog__close-button-text{display:var(--_button-close-text-display);font-size:1rem;line-height:1.5rem;margin-left:0.25rem}.dialog__inner{background-color:var(--_main-background-color);height:100%;position:relative;display:flex;flex-direction:column;width:100%}.dialog__header{display:flex;flex-direction:column;align-items:center;width:100%}.dialog__header>*{width:100%;max-width:var(--_container-max-width, 87.5rem)}.dialog__header{margin-bottom:0.5rem;background-color:var(--_header-background-color);padding:0.75rem 0.5rem}.dialog__header-inner{display:flex;justify-content:space-between;align-items:center;padding:0 0.5rem;height:1.5rem}.dialog__title{font-size:1.375rem;font-weight:normal;line-height:1.5rem}.dialog--scroll .dialog__content-wrapper{display:flex;flex-direction:column;align-items:center;width:100%}.dialog--scroll .dialog__content-wrapper>*{width:100%;max-width:var(--_container-max-width, 87.5rem)}.dialog__content-scroll{flex:1 0 0;overflow-y:auto;padding:0 0.5rem 1rem 0.5rem}.dialog__content{padding:0.5rem 0.5rem 0 1rem}.dialog--no-scroll .dialog__content,.dialog--no-scroll .dialog__content slot{max-height:calc(100dvh - 3.5rem);overflow:hidden;display:block}.dialog__footer{padding:0 0.5rem 1rem 0.5rem;display:flex;justify-content:center}.dialog__footer-actions{list-style:none;display:flex;padding:0;margin:0;width:100%;max-width:var(--_container-max-width)}.dialog__action{padding:0;margin-left:1rem;--outbook-button-default--background-color: var( --outbook-modal-dialog--neutral-background, light-dark( oklch(37.1% 0 0deg), oklch(92.2% 0 0deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--neutral-background-hover, light-dark( oklch(20.5% 0 0deg), oklch(70.8% 0 0deg) ) )}.dialog__action:first-child{margin-left:0}.dialog__action.positive{--outbook-button-default--background-color: var( --outbook-modal-dialog--positive-background, light-dark( oklch(52.7% 0.154 150.069deg), oklch(92.5% 0.084 155.995deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--positive-background-hover, light-dark( oklch(39.3% 0.095 152.535deg), oklch(79.2% 0.209 151.711deg) ) )}.dialog__action.negative{--outbook-button-default--background-color: var( --outbook-modal-dialog--negative-background, light-dark( oklch(50.5% 0.213 27.518deg), oklch(88.5% 0.062 18.334deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--negative-background-hover, light-dark( oklch(39.6% 0.141 25.723deg), oklch(70.4% 0.191 22.216deg) ) )}`;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { css } from 'lit';
|
|
3
|
+
|
|
4
|
+
export default css`:host{display:block;color-scheme:inherit;container-name:modalDialog;container-type:inline-size;--outbook-scrollable--indicator-max-width: 60rem;--_container-max-width: 60rem;--_button-close-text-display: none;--_main-text-color: light-dark( oklch(20.5% 0 0deg), oklch(98.5% 0 0deg) );--_main-background-color: light-dark( oklch(100% 0 0deg), oklch(14.5% 0 0deg) );--_veil-background-color: var( --outbook-modal-dialog--veil-color, light-dark( oklch(70.8% 0 0deg), oklch(26.9% 0 0deg) ) );--_header-background-color: light-dark( oklch(92.2% 0 0deg), oklch(43.9% 0 0deg) )}*{box-sizing:border-box}.dialog:before{content:"";position:fixed;top:0;left:0;height:100dvh;width:100%;background-color:var(--_veil-background-color);opacity:.85}.dialog__inner{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%);width:80%;max-width:60rem;min-height:20rem;max-height:80dvh;color:var(--_main-text-color);background:var(--_main-background-color);border-radius:0.75rem;padding:1.5rem;display:flex;flex-direction:column}.dialog__header{margin-bottom:1rem}.dialog__header-inner{display:flex;flex-wrap:nowrap;justify-content:space-between}.dialog__title{font-size:1.5rem}.dialog__close-button{display:flex;align-items:center;cursor:pointer}.dialog__close-button-icon{width:1.5rem;height:1.5rem}.dialog__close-button-text{display:none}.dialog__footer{margin-top:auto}.dialog__footer-actions{list-style:none;display:flex;padding:0;margin:0;width:100%;max-width:var(--_container-max-width)}.dialog__action{padding:0;margin-left:1rem;--outbook-button-default--background-color: var( --outbook-modal-dialog--neutral-background, light-dark( oklch(37.1% 0 0deg), oklch(92.2% 0 0deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--neutral-background-hover, light-dark( oklch(20.5% 0 0deg), oklch(70.8% 0 0deg) ) )}.dialog__action:first-child{margin-left:0}.dialog__action.positive{--outbook-button-default--background-color: var( --outbook-modal-dialog--positive-background, light-dark( oklch(52.7% 0.154 150.069deg), oklch(92.5% 0.084 155.995deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--positive-background-hover, light-dark( oklch(39.3% 0.095 152.535deg), oklch(79.2% 0.209 151.711deg) ) )}.dialog__action.negative{--outbook-button-default--background-color: var( --outbook-modal-dialog--negative-background, light-dark( oklch(50.5% 0.213 27.518deg), oklch(88.5% 0.062 18.334deg) ) );--outbook-button-default--background-color-hover: var( --outbook-modal-dialog--negative-background-hover, light-dark( oklch(39.6% 0.141 25.723deg), oklch(70.4% 0.191 22.216deg) ) )}`;
|
package/modal-dialog.js
CHANGED
|
@@ -3,12 +3,13 @@ import { classMap } from 'lit/directives/class-map.js';
|
|
|
3
3
|
import { useEffect, useState, component } from 'haunted';
|
|
4
4
|
import { Scrollable } from '@outbook/webcomponents-scrollable';
|
|
5
5
|
import { TypeIcon } from '@outbook/webcomponents-type-icon/shadow';
|
|
6
|
+
import { ButtonDefault } from '@outbook/webcomponents-button-default';
|
|
6
7
|
import { close } from '@outbook/icons';
|
|
7
8
|
import { DialogBase } from './_lib/dialog-base.js';
|
|
8
|
-
import { tmplSlot } from './_lib/tmpl-slot.js';
|
|
9
9
|
import { Tabs } from '@outbook/webcomponents-tabs';
|
|
10
10
|
import { getI18n } from './_i18n/i18n.js';
|
|
11
|
-
import
|
|
11
|
+
import styleComponentContent from './_style/modal-dialog-content.style.js';
|
|
12
|
+
import styleComponentMessage from './_style/modal-dialog-message.style.js';
|
|
12
13
|
|
|
13
14
|
export function ModalDialog(props) {
|
|
14
15
|
DialogBase({
|
|
@@ -25,31 +26,34 @@ function DialogUi(props) {
|
|
|
25
26
|
handlers,
|
|
26
27
|
portalWrapperId,
|
|
27
28
|
view = null,
|
|
28
|
-
tabs = []
|
|
29
|
+
tabs = [],
|
|
30
|
+
type = 'content'
|
|
29
31
|
} = props;
|
|
32
|
+
const dialogContent =
|
|
33
|
+
view !== null
|
|
34
|
+
? view({ closeDialog: handlers.close })
|
|
35
|
+
: tabs.length
|
|
36
|
+
? Tabs({ items: tabs, isInDialog: true })
|
|
37
|
+
: nothing;
|
|
38
|
+
|
|
30
39
|
return html`
|
|
31
40
|
<outbook-modal-dialog
|
|
32
41
|
class="dialog--host"
|
|
42
|
+
type="${type}"
|
|
33
43
|
.props="${{
|
|
34
44
|
...props,
|
|
35
45
|
literals,
|
|
36
46
|
handlers,
|
|
37
47
|
dialogId: baseId,
|
|
38
|
-
portalWrapperId
|
|
39
|
-
content: () => {
|
|
40
|
-
return view !== null
|
|
41
|
-
? view({ closeDialog: handlers.close })
|
|
42
|
-
: tabs.length
|
|
43
|
-
? Tabs({ items: tabs, isInDialog: true })
|
|
44
|
-
: nothing;
|
|
45
|
-
}
|
|
48
|
+
portalWrapperId
|
|
46
49
|
}}"
|
|
47
|
-
|
|
50
|
+
>${dialogContent}</outbook-modal-dialog
|
|
51
|
+
>
|
|
48
52
|
`;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
function DialogUiComponent(element) {
|
|
52
|
-
const { props } = element;
|
|
56
|
+
const { props, type } = element;
|
|
53
57
|
const {
|
|
54
58
|
title,
|
|
55
59
|
dialogId,
|
|
@@ -58,14 +62,17 @@ function DialogUiComponent(element) {
|
|
|
58
62
|
portalWrapperId,
|
|
59
63
|
hasScroll: _hasScroll = true,
|
|
60
64
|
tabs = [],
|
|
65
|
+
actions = [],
|
|
61
66
|
content
|
|
62
67
|
} = props;
|
|
63
68
|
const [initialized, setInitialized] = useState(false);
|
|
64
|
-
const hasScroll = tabs.length > 0 ? false : _hasScroll;
|
|
69
|
+
const hasScroll = tabs.length > 0 || type !== 'content' ? false : _hasScroll;
|
|
65
70
|
|
|
66
71
|
useEffect(() => {
|
|
67
72
|
if (element.shadowRoot) {
|
|
68
|
-
adoptStyles(element.shadowRoot, [
|
|
73
|
+
adoptStyles(element.shadowRoot, [
|
|
74
|
+
type === 'message' ? styleComponentMessage : styleComponentContent
|
|
75
|
+
]);
|
|
69
76
|
}
|
|
70
77
|
}, []);
|
|
71
78
|
|
|
@@ -86,26 +93,37 @@ function DialogUiComponent(element) {
|
|
|
86
93
|
|
|
87
94
|
const mainClasses = classMap({
|
|
88
95
|
dialog: true,
|
|
96
|
+
[`dialog--type-${type}`]: portalWrapperId,
|
|
89
97
|
'dialog--in-element': portalWrapperId,
|
|
90
98
|
'dialog--no-scroll': !hasScroll,
|
|
91
99
|
'dialog--scroll': hasScroll
|
|
92
100
|
});
|
|
93
101
|
|
|
102
|
+
function contentSlot() {
|
|
103
|
+
return html`
|
|
104
|
+
<div class="dialog__content-wrapper">
|
|
105
|
+
<div class="dialog__content" id="${dialogId}-view">
|
|
106
|
+
<slot>${content ? content() : nothing}</slot>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
|
|
94
112
|
return html`
|
|
95
113
|
<div tabindex="0" @focus="${refocusEnd}"></div>
|
|
96
|
-
<div
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
<div class="${mainClasses}">
|
|
115
|
+
<div
|
|
116
|
+
class="dialog__inner"
|
|
117
|
+
tabindex="-1"
|
|
118
|
+
id="${dialogId}-main"
|
|
119
|
+
@keydown="${handlers.escape}"
|
|
120
|
+
role="dialog"
|
|
121
|
+
aria-labelledby="${dialogId}-title"
|
|
122
|
+
>
|
|
105
123
|
<div class="dialog__header">
|
|
106
124
|
<div class="dialog__header-inner">
|
|
107
125
|
<div
|
|
108
|
-
role="
|
|
126
|
+
role="heading"
|
|
109
127
|
aria-level="1"
|
|
110
128
|
class="dialog__title"
|
|
111
129
|
data-test-id="dialog-title"
|
|
@@ -137,9 +155,43 @@ function DialogUiComponent(element) {
|
|
|
137
155
|
${hasScroll
|
|
138
156
|
? Scrollable({
|
|
139
157
|
extraClasses: 'dialog__content-scroll',
|
|
140
|
-
content:
|
|
158
|
+
content: contentSlot
|
|
141
159
|
})
|
|
142
|
-
:
|
|
160
|
+
: contentSlot()}
|
|
161
|
+
${actions.length > 0
|
|
162
|
+
? html`
|
|
163
|
+
<div class="dialog__footer">
|
|
164
|
+
<ul class="dialog__footer-actions">
|
|
165
|
+
${actions.map(
|
|
166
|
+
({
|
|
167
|
+
type: _type = 'neutral',
|
|
168
|
+
text,
|
|
169
|
+
handler,
|
|
170
|
+
eventFn = () => {}
|
|
171
|
+
}) => {
|
|
172
|
+
const namedHandler =
|
|
173
|
+
typeof handler === 'string'
|
|
174
|
+
? handlers?.[handler]
|
|
175
|
+
: undefined;
|
|
176
|
+
const buttonEventFn = namedHandler
|
|
177
|
+
? ev => namedHandler(ev?.detail?.originalEvent || ev)
|
|
178
|
+
: eventFn;
|
|
179
|
+
|
|
180
|
+
return html`
|
|
181
|
+
<li class="dialog__action ${_type}">
|
|
182
|
+
${ButtonDefault({
|
|
183
|
+
text,
|
|
184
|
+
size: 'compact',
|
|
185
|
+
eventFn: buttonEventFn
|
|
186
|
+
})}
|
|
187
|
+
</li>
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
)}
|
|
191
|
+
</ul>
|
|
192
|
+
</div>
|
|
193
|
+
`
|
|
194
|
+
: nothing}
|
|
143
195
|
</div>
|
|
144
196
|
</div>
|
|
145
197
|
<div tabindex="0" @focus="${refocusStart}"></div>
|
|
@@ -150,7 +202,7 @@ if (!customElements.get('outbook-modal-dialog')) {
|
|
|
150
202
|
customElements.define(
|
|
151
203
|
'outbook-modal-dialog',
|
|
152
204
|
component(DialogUiComponent, {
|
|
153
|
-
observedAttributes: [],
|
|
205
|
+
observedAttributes: ['type'],
|
|
154
206
|
useShadowDOM: true
|
|
155
207
|
})
|
|
156
208
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outbook/webcomponents-modal-dialog",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"main": "modal-dialog.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -27,8 +27,9 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@outbook/icons": ">=1.3.1",
|
|
29
29
|
"@outbook/webcomponents-tabs": ">=1.0.1",
|
|
30
|
-
"@outbook/webcomponents-type-icon": ">=1.1.
|
|
30
|
+
"@outbook/webcomponents-type-icon": ">=1.1.4",
|
|
31
31
|
"@outbook/webcomponents-scrollable": ">=1.0.2",
|
|
32
|
+
"@outbook/webcomponents-button-default": ">=1.2.0",
|
|
32
33
|
"a11y-key-conjurer": "1.1.2"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
package/_lib/tmpl-slot.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
import { css } from 'lit';
|
|
3
|
-
|
|
4
|
-
export default css`:host{display:block;color-scheme:inherit;container-name:groupRadio;container-type:inline-size;--outbook-scrollable--indicator-max-width: 60rem;--_container-max-width: 60rem;--_height: 100dvh;--_button-close-text-display: none;--_main-text-color: light-dark( oklch(20.5% 0 0deg), oklch(98.5% 0 0deg) );--_main-background-color: light-dark( oklch(100% 0 0deg), oklch(14.5% 0 0deg) );--_header-background-color: light-dark( oklch(92.2% 0 0deg), oklch(43.9% 0 0deg) )}:host .dialog--in-element{--_height: 100%}*{box-sizing:border-box}@container groupRadio (min-width: 540px){.dialog{--_button-close-text-display: inline-block}}.dialog{position:fixed;width:100%;height:var(--_height);top:0;left:0;display:flex;justify-content:center;align-items:center;background-color:var(--background-color);color:var(--_main-text-color);z-index:2;transition:background-color 0.3s,color 0.3s}.dialog__close-button{display:flex;align-items:center;cursor:pointer}.dialog__close-button-icon{width:1.5rem;height:1.5rem}.dialog__close-button-text{display:var(--_button-close-text-display);font-size:1rem;line-height:1.5rem;margin-left:0.25rem}.dialog__inner{background-color:var(--_main-background-color);height:100%;position:relative;display:flex;flex-direction:column;width:100%}.dialog__header{display:flex;flex-direction:column;align-items:center;width:100%}.dialog__header>*{width:100%;max-width:var(--_container-max-width, 87.5rem)}.dialog__header{margin-bottom:0.5rem;background-color:var(--_header-background-color);padding:0.75rem 0.5rem}.dialog__header-inner{display:flex;justify-content:space-between;align-items:center;padding:0 0.5rem;height:1.5rem}.dialog__title{font-size:1.375rem;font-weight:normal;line-height:1.5rem}.dialog--scroll .dialog__content-wrapper{display:flex;flex-direction:column;align-items:center;width:100%}.dialog--scroll .dialog__content-wrapper>*{width:100%;max-width:var(--_container-max-width, 87.5rem)}.dialog__content-scroll{flex:1 0 0;overflow-y:auto;padding:0 0.5rem 1rem 0.5rem}.dialog__content{padding:0.5rem 0.5rem 0 1rem}.dialog--no-scroll .dialog__content,.dialog--no-scroll .dialog__content slot{max-height:calc(100dvh - 3.5rem);overflow:hidden;display:block}`;
|