@operato/popup 10.11.0 → 10.15.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/CHANGELOG.md +9 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +206 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +7675 -0
- package/dist/src/implementation.d.ts +13 -0
- package/dist/src/implementation.js +13 -0
- package/dist/src/implementation.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/open-popup.d.ts +37 -13
- package/dist/src/open-popup.js +79 -12
- package/dist/src/open-popup.js.map +1 -1
- package/dist/src/ox-floating-overlay.d.ts +4 -1
- package/dist/src/ox-floating-overlay.js +19 -2
- package/dist/src/ox-floating-overlay.js.map +1 -1
- package/dist/src/ox-popup-actions.d.ts +36 -0
- package/dist/src/ox-popup-actions.js +129 -0
- package/dist/src/ox-popup-actions.js.map +1 -0
- package/dist/src/ox-prompt.d.ts +9 -3
- package/dist/src/ox-prompt.js +50 -42
- package/dist/src/ox-prompt.js.map +1 -1
- package/dist/src/popup-result.d.ts +19 -0
- package/dist/src/popup-result.js +53 -0
- package/dist/src/popup-result.js.map +1 -0
- package/dist/test/office-control-height.test.d.ts +1 -0
- package/dist/test/office-control-height.test.js +48 -0
- package/dist/test/office-control-height.test.js.map +1 -0
- package/dist/test/ox-popup-actions.test.d.ts +3 -0
- package/dist/test/ox-popup-actions.test.js +104 -0
- package/dist/test/ox-popup-actions.test.js.map +1 -0
- package/dist/test/ox-prompt-actions.test.d.ts +1 -0
- package/dist/test/ox-prompt-actions.test.js +77 -0
- package/dist/test/ox-prompt-actions.test.js.map +1 -0
- package/dist/test/popup-result.test.d.ts +1 -0
- package/dist/test/popup-result.test.js +114 -0
- package/dist/test/popup-result.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -5
- package/test/office-control-height.test.ts +58 -0
- package/test/ox-popup-actions.test.ts +130 -0
- package/test/ox-prompt-actions.test.ts +99 -0
- package/test/popup-result.test.ts +150 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* The row of commands at the bottom of a popup.
|
|
4
|
+
*
|
|
5
|
+
* Popups had nine different button rows (heights 28 to 44, radius 5 to pill, cancel left or right,
|
|
6
|
+
* one app painting cancel red) because every popup wrote its own markup and CSS. A written rule would
|
|
7
|
+
* have produced a tenth. So the row is an element and owns what the rule says:
|
|
8
|
+
*
|
|
9
|
+
* - **Order.** Whatever order the markup uses, it renders
|
|
10
|
+
* `[start] ··· [default slot] [cancel] [confirm]` - the main action is always the rightmost one,
|
|
11
|
+
* cancel always sits just before it, and a destructive side action (delete inside an editor) is
|
|
12
|
+
* pushed to the far left, away from the main action.
|
|
13
|
+
* - **Height and shape.** The height is --popup-action-height (32px by default, ADR-0060 decision 6),
|
|
14
|
+
* for mouse and finger alike. With a mouse the buttons are pills, because the container is a
|
|
15
|
+
* rounded card and controls follow the surface that holds them; with a finger the row becomes a
|
|
16
|
+
* full-width square action bar. Plain
|
|
17
|
+
* `<button>`s get the same height as Material buttons, so one row never mixes two heights.
|
|
18
|
+
* - **Destructive colour.** `destructive` on a slotted button paints it with the error colour. Cancel
|
|
19
|
+
* is never destructive, whatever attribute it carries.
|
|
20
|
+
*
|
|
21
|
+
* ```html
|
|
22
|
+
* <ox-popup-actions>
|
|
23
|
+
* <md-text-button slot="start" destructive @click=${remove}>delete</md-text-button>
|
|
24
|
+
* <md-text-button slot="cancel" @click=${() => closePopup(this)}>cancel</md-text-button>
|
|
25
|
+
* <md-filled-button slot="confirm" @click=${save}>save</md-filled-button>
|
|
26
|
+
* </ox-popup-actions>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* A screen that must be bigger (a shop-floor terminal used with gloves) raises the height, not the
|
|
30
|
+
* markup: `--popup-action-height: 68px`, for mouse and finger alike. Shop-floor popups must declare it
|
|
31
|
+
* (e.g. `var(--ui-tap-glove)`): the default is sized for office screens.
|
|
32
|
+
*/
|
|
33
|
+
export declare class OxPopupActions extends LitElement {
|
|
34
|
+
static styles: import("lit").CSSResult;
|
|
35
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { customElement } from 'lit/decorators.js';
|
|
4
|
+
import { actionHeight } from '@operato/styles/action-heights.js';
|
|
5
|
+
/**
|
|
6
|
+
* The row of commands at the bottom of a popup.
|
|
7
|
+
*
|
|
8
|
+
* Popups had nine different button rows (heights 28 to 44, radius 5 to pill, cancel left or right,
|
|
9
|
+
* one app painting cancel red) because every popup wrote its own markup and CSS. A written rule would
|
|
10
|
+
* have produced a tenth. So the row is an element and owns what the rule says:
|
|
11
|
+
*
|
|
12
|
+
* - **Order.** Whatever order the markup uses, it renders
|
|
13
|
+
* `[start] ··· [default slot] [cancel] [confirm]` - the main action is always the rightmost one,
|
|
14
|
+
* cancel always sits just before it, and a destructive side action (delete inside an editor) is
|
|
15
|
+
* pushed to the far left, away from the main action.
|
|
16
|
+
* - **Height and shape.** The height is --popup-action-height (32px by default, ADR-0060 decision 6),
|
|
17
|
+
* for mouse and finger alike. With a mouse the buttons are pills, because the container is a
|
|
18
|
+
* rounded card and controls follow the surface that holds them; with a finger the row becomes a
|
|
19
|
+
* full-width square action bar. Plain
|
|
20
|
+
* `<button>`s get the same height as Material buttons, so one row never mixes two heights.
|
|
21
|
+
* - **Destructive colour.** `destructive` on a slotted button paints it with the error colour. Cancel
|
|
22
|
+
* is never destructive, whatever attribute it carries.
|
|
23
|
+
*
|
|
24
|
+
* ```html
|
|
25
|
+
* <ox-popup-actions>
|
|
26
|
+
* <md-text-button slot="start" destructive @click=${remove}>delete</md-text-button>
|
|
27
|
+
* <md-text-button slot="cancel" @click=${() => closePopup(this)}>cancel</md-text-button>
|
|
28
|
+
* <md-filled-button slot="confirm" @click=${save}>save</md-filled-button>
|
|
29
|
+
* </ox-popup-actions>
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* A screen that must be bigger (a shop-floor terminal used with gloves) raises the height, not the
|
|
33
|
+
* markup: `--popup-action-height: 68px`, for mouse and finger alike. Shop-floor popups must declare it
|
|
34
|
+
* (e.g. `var(--ui-tap-glove)`): the default is sized for office screens.
|
|
35
|
+
*/
|
|
36
|
+
let OxPopupActions = class OxPopupActions extends LitElement {
|
|
37
|
+
static { this.styles = css `
|
|
38
|
+
:host {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: var(--spacing-small, 4px);
|
|
42
|
+
padding-top: var(--spacing-medium, 8px);
|
|
43
|
+
border-top: 1px solid var(--md-sys-color-outline-variant);
|
|
44
|
+
|
|
45
|
+
--_height: ${actionHeight('--popup-action-height')};
|
|
46
|
+
--_shape: var(--popup-control-radius, 999em);
|
|
47
|
+
|
|
48
|
+
--md-text-button-container-height: var(--_height);
|
|
49
|
+
--md-filled-button-container-height: var(--_height);
|
|
50
|
+
--md-outlined-button-container-height: var(--_height);
|
|
51
|
+
--md-text-button-container-shape: var(--_shape);
|
|
52
|
+
--md-filled-button-container-shape: var(--_shape);
|
|
53
|
+
--md-outlined-button-container-shape: var(--_shape);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[spacer] {
|
|
57
|
+
flex: 1;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
::slotted(button) {
|
|
61
|
+
box-sizing: border-box;
|
|
62
|
+
min-height: var(--_height);
|
|
63
|
+
padding: 0 var(--spacing-large, 16px);
|
|
64
|
+
border-radius: var(--_shape);
|
|
65
|
+
font: inherit;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Destructive: the error colour, on the filled container or on the label. Never on cancel. */
|
|
69
|
+
::slotted(md-filled-button[destructive]:not([slot='cancel'])) {
|
|
70
|
+
--md-filled-button-container-color: var(--md-sys-color-error);
|
|
71
|
+
--md-filled-button-label-text-color: var(--md-sys-color-on-error);
|
|
72
|
+
--md-filled-button-hover-label-text-color: var(--md-sys-color-on-error);
|
|
73
|
+
--md-filled-button-focus-label-text-color: var(--md-sys-color-on-error);
|
|
74
|
+
--md-filled-button-pressed-label-text-color: var(--md-sys-color-on-error);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
::slotted(md-text-button[destructive]:not([slot='cancel'])),
|
|
78
|
+
::slotted(md-outlined-button[destructive]:not([slot='cancel'])) {
|
|
79
|
+
--md-text-button-label-text-color: var(--md-sys-color-error);
|
|
80
|
+
--md-text-button-hover-label-text-color: var(--md-sys-color-error);
|
|
81
|
+
--md-text-button-focus-label-text-color: var(--md-sys-color-error);
|
|
82
|
+
--md-text-button-pressed-label-text-color: var(--md-sys-color-error);
|
|
83
|
+
--md-outlined-button-label-text-color: var(--md-sys-color-error);
|
|
84
|
+
--md-outlined-button-hover-label-text-color: var(--md-sys-color-error);
|
|
85
|
+
--md-outlined-button-focus-label-text-color: var(--md-sys-color-error);
|
|
86
|
+
--md-outlined-button-pressed-label-text-color: var(--md-sys-color-error);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
::slotted(button[destructive]:not([slot='cancel'])) {
|
|
90
|
+
color: var(--md-sys-color-error);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* Fingers: a full-width, square action bar. The line is still the card's bottom edge, so it takes
|
|
95
|
+
* the card's shape - square - and every button shares the width. 36 is a floor, not a ceiling:
|
|
96
|
+
* a terminal that declared 68 keeps 68.
|
|
97
|
+
*/
|
|
98
|
+
@media (pointer: coarse) {
|
|
99
|
+
:host {
|
|
100
|
+
gap: 0;
|
|
101
|
+
padding-top: 0;
|
|
102
|
+
|
|
103
|
+
--_shape: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
[spacer] {
|
|
107
|
+
display: none;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
::slotted(*) {
|
|
111
|
+
flex: 1;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
`; }
|
|
115
|
+
render() {
|
|
116
|
+
return html `
|
|
117
|
+
<slot name="start"></slot>
|
|
118
|
+
<div spacer></div>
|
|
119
|
+
<slot></slot>
|
|
120
|
+
<slot name="cancel"></slot>
|
|
121
|
+
<slot name="confirm"></slot>
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
OxPopupActions = __decorate([
|
|
126
|
+
customElement('ox-popup-actions')
|
|
127
|
+
], OxPopupActions);
|
|
128
|
+
export { OxPopupActions };
|
|
129
|
+
//# sourceMappingURL=ox-popup-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-popup-actions.js","sourceRoot":"","sources":["../../src/ox-popup-actions.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;aACrC,WAAM,GAAG,GAAG,CAAA;;;;;;;;mBAQF,YAAY,CAAC,uBAAuB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqErD,AA7EY,CA6EZ;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;;;;;;KAMV,CAAA;IACH,CAAC;;AAxFU,cAAc;IAD1B,aAAa,CAAC,kBAAkB,CAAC;GACrB,cAAc,CAyF1B","sourcesContent":["import { css, html, LitElement } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\nimport { actionHeight } from '@operato/styles/action-heights.js'\n\n/**\n * The row of commands at the bottom of a popup.\n *\n * Popups had nine different button rows (heights 28 to 44, radius 5 to pill, cancel left or right,\n * one app painting cancel red) because every popup wrote its own markup and CSS. A written rule would\n * have produced a tenth. So the row is an element and owns what the rule says:\n *\n * - **Order.** Whatever order the markup uses, it renders\n * `[start] ··· [default slot] [cancel] [confirm]` - the main action is always the rightmost one,\n * cancel always sits just before it, and a destructive side action (delete inside an editor) is\n * pushed to the far left, away from the main action.\n * - **Height and shape.** The height is --popup-action-height (32px by default, ADR-0060 decision 6),\n * for mouse and finger alike. With a mouse the buttons are pills, because the container is a\n * rounded card and controls follow the surface that holds them; with a finger the row becomes a\n * full-width square action bar. Plain\n * `<button>`s get the same height as Material buttons, so one row never mixes two heights.\n * - **Destructive colour.** `destructive` on a slotted button paints it with the error colour. Cancel\n * is never destructive, whatever attribute it carries.\n *\n * ```html\n * <ox-popup-actions>\n * <md-text-button slot=\"start\" destructive @click=${remove}>delete</md-text-button>\n * <md-text-button slot=\"cancel\" @click=${() => closePopup(this)}>cancel</md-text-button>\n * <md-filled-button slot=\"confirm\" @click=${save}>save</md-filled-button>\n * </ox-popup-actions>\n * ```\n *\n * A screen that must be bigger (a shop-floor terminal used with gloves) raises the height, not the\n * markup: `--popup-action-height: 68px`, for mouse and finger alike. Shop-floor popups must declare it\n * (e.g. `var(--ui-tap-glove)`): the default is sized for office screens.\n */\n@customElement('ox-popup-actions')\nexport class OxPopupActions extends LitElement {\n static styles = css`\n :host {\n display: flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n padding-top: var(--spacing-medium, 8px);\n border-top: 1px solid var(--md-sys-color-outline-variant);\n\n --_height: ${actionHeight('--popup-action-height')};\n --_shape: var(--popup-control-radius, 999em);\n\n --md-text-button-container-height: var(--_height);\n --md-filled-button-container-height: var(--_height);\n --md-outlined-button-container-height: var(--_height);\n --md-text-button-container-shape: var(--_shape);\n --md-filled-button-container-shape: var(--_shape);\n --md-outlined-button-container-shape: var(--_shape);\n }\n\n [spacer] {\n flex: 1;\n }\n\n ::slotted(button) {\n box-sizing: border-box;\n min-height: var(--_height);\n padding: 0 var(--spacing-large, 16px);\n border-radius: var(--_shape);\n font: inherit;\n }\n\n /* Destructive: the error colour, on the filled container or on the label. Never on cancel. */\n ::slotted(md-filled-button[destructive]:not([slot='cancel'])) {\n --md-filled-button-container-color: var(--md-sys-color-error);\n --md-filled-button-label-text-color: var(--md-sys-color-on-error);\n --md-filled-button-hover-label-text-color: var(--md-sys-color-on-error);\n --md-filled-button-focus-label-text-color: var(--md-sys-color-on-error);\n --md-filled-button-pressed-label-text-color: var(--md-sys-color-on-error);\n }\n\n ::slotted(md-text-button[destructive]:not([slot='cancel'])),\n ::slotted(md-outlined-button[destructive]:not([slot='cancel'])) {\n --md-text-button-label-text-color: var(--md-sys-color-error);\n --md-text-button-hover-label-text-color: var(--md-sys-color-error);\n --md-text-button-focus-label-text-color: var(--md-sys-color-error);\n --md-text-button-pressed-label-text-color: var(--md-sys-color-error);\n --md-outlined-button-label-text-color: var(--md-sys-color-error);\n --md-outlined-button-hover-label-text-color: var(--md-sys-color-error);\n --md-outlined-button-focus-label-text-color: var(--md-sys-color-error);\n --md-outlined-button-pressed-label-text-color: var(--md-sys-color-error);\n }\n\n ::slotted(button[destructive]:not([slot='cancel'])) {\n color: var(--md-sys-color-error);\n }\n\n /*\n * Fingers: a full-width, square action bar. The line is still the card's bottom edge, so it takes\n * the card's shape - square - and every button shares the width. 36 is a floor, not a ceiling:\n * a terminal that declared 68 keeps 68.\n */\n @media (pointer: coarse) {\n :host {\n gap: 0;\n padding-top: 0;\n\n --_shape: 0;\n }\n\n [spacer] {\n display: none;\n }\n\n ::slotted(*) {\n flex: 1;\n }\n }\n `\n\n render() {\n return html`\n <slot name=\"start\"></slot>\n <div spacer></div>\n <slot></slot>\n <slot name=\"cancel\"></slot>\n <slot name=\"confirm\"></slot>\n `\n }\n}\n"]}
|
package/dist/src/ox-prompt.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '@material/web/button/filled-button.js';
|
|
2
|
-
import '@material/web/button/
|
|
2
|
+
import '@material/web/button/text-button.js';
|
|
3
|
+
import './ox-popup-actions.js';
|
|
3
4
|
import '@material/web/icon/icon.js';
|
|
4
5
|
import { LitElement } from 'lit';
|
|
5
6
|
/**
|
|
@@ -37,6 +38,7 @@ export declare class OxPrompt extends LitElement {
|
|
|
37
38
|
confirmButton?: {
|
|
38
39
|
text: string;
|
|
39
40
|
color?: string;
|
|
41
|
+
destructive?: boolean;
|
|
40
42
|
};
|
|
41
43
|
/**
|
|
42
44
|
* Specifies settings for the cancel button.
|
|
@@ -58,6 +60,7 @@ export declare class OxPrompt extends LitElement {
|
|
|
58
60
|
_parent?: Element;
|
|
59
61
|
private resolveFn;
|
|
60
62
|
render(): import("lit-html").TemplateResult<1>;
|
|
63
|
+
private renderButtons;
|
|
61
64
|
resolve(result: boolean): void;
|
|
62
65
|
/**
|
|
63
66
|
* Function called when the confirm button is clicked.
|
|
@@ -89,10 +92,12 @@ export declare class OxPrompt extends LitElement {
|
|
|
89
92
|
* @param {string} [options.footer] - Additional information to be displayed at the bottom of the popup.
|
|
90
93
|
* @param {object} [options.confirmButton] - Configuration for the confirmation button in the popup.
|
|
91
94
|
* @param {string} options.confirmButton.text - The text to be displayed on the confirmation button.
|
|
92
|
-
* @param {string} [options.confirmButton.color] - The
|
|
95
|
+
* @param {string} [options.confirmButton.color] - Not applied. The action row owns button colours.
|
|
96
|
+
* @param {boolean} [options.confirmButton.destructive] - The confirmation cannot be undone (delete, discard): the
|
|
97
|
+
* button takes the error colour and cancel gets the first focus.
|
|
93
98
|
* @param {object} [options.cancelButton] - Configuration for the cancel button in the popup.
|
|
94
99
|
* @param {string} options.cancelButton.text - The text to be displayed on the cancel button.
|
|
95
|
-
* @param {string} [options.cancelButton.color] -
|
|
100
|
+
* @param {string} [options.cancelButton.color] - Not applied. Cancel is never coloured.
|
|
96
101
|
* @param {number} [options.top] - The top position of the popup (in pixels).
|
|
97
102
|
* @param {number} [options.left] - The left position of the popup (in pixels).
|
|
98
103
|
* @param {number} [options.right] - The right position of the popup (in pixels).
|
|
@@ -114,6 +119,7 @@ export declare class OxPrompt extends LitElement {
|
|
|
114
119
|
confirmButton?: {
|
|
115
120
|
text: string;
|
|
116
121
|
color?: string;
|
|
122
|
+
destructive?: boolean;
|
|
117
123
|
};
|
|
118
124
|
cancelButton?: {
|
|
119
125
|
text: string;
|
package/dist/src/ox-prompt.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
var OxPrompt_1;
|
|
2
2
|
import { __decorate } from "tslib";
|
|
3
3
|
import '@material/web/button/filled-button.js';
|
|
4
|
-
import '@material/web/button/
|
|
4
|
+
import '@material/web/button/text-button.js';
|
|
5
|
+
import './ox-popup-actions.js';
|
|
5
6
|
import '@material/web/icon/icon.js';
|
|
6
7
|
import { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js';
|
|
7
8
|
import { css, html, nothing, LitElement } from 'lit';
|
|
@@ -156,33 +157,25 @@ let OxPrompt = class OxPrompt extends LitElement {
|
|
|
156
157
|
color: var(--status-success-color, #35a24a);
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
/*
|
|
161
|
+
* The command row is the shared popup action row: confirm on the right, cancel just before it,
|
|
162
|
+
* pills of --popup-action-height with a mouse, a square full-width bar with a finger. Its own margins keep the row
|
|
163
|
+
* inside the card's padding with a mouse.
|
|
164
|
+
*/
|
|
165
|
+
ox-popup-actions {
|
|
166
|
+
margin: 0 var(--ox-prompt-buttons-padding, var(--spacing-medium)) var(--ox-prompt-buttons-padding, var(--spacing-medium));
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
--md-filled-button-container-shape: var(--md-sys-shape-corner-small);
|
|
174
|
-
--md-filled-button-leading-space: var(--spacing-large);
|
|
175
|
-
--md-filled-button-trailing-space: var(--spacing-large);
|
|
176
|
-
}
|
|
169
|
+
@media (pointer: coarse) {
|
|
170
|
+
/* The bar is the card's bottom edge: it reaches both sides, and the card clips its corners. */
|
|
171
|
+
:host {
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
}
|
|
177
174
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
--md-outlined-button-container-height: var(--form-element-height-medium);
|
|
183
|
-
--md-outlined-button-container-shape: var(--md-sys-shape-corner-small);
|
|
184
|
-
--md-outlined-button-leading-space: var(--spacing-large);
|
|
185
|
-
--md-outlined-button-trailing-space: var(--spacing-large);
|
|
175
|
+
ox-popup-actions {
|
|
176
|
+
margin: var(--spacing-medium) calc(-1 * var(--ox-prompt-container-padding, var(--spacing-medium)))
|
|
177
|
+
calc(-1 * var(--ox-prompt-container-padding, var(--spacing-medium)));
|
|
178
|
+
}
|
|
186
179
|
}
|
|
187
180
|
`
|
|
188
181
|
]; }
|
|
@@ -197,23 +190,36 @@ let OxPrompt = class OxPrompt extends LitElement {
|
|
|
197
190
|
<slot> </slot>
|
|
198
191
|
${this.footer ? html ` <div footer class="md-typescale-body-large">${this.footer}</div> ` : nothing}
|
|
199
192
|
</div>
|
|
200
|
-
<
|
|
201
|
-
${this.
|
|
193
|
+
<ox-popup-actions>
|
|
194
|
+
${this.renderButtons()}
|
|
195
|
+
</ox-popup-actions>
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
/*
|
|
199
|
+
* Markup order only decides which button gets the first focus; the row decides where they stand.
|
|
200
|
+
* A destructive confirmation focuses cancel, so a reflexive Enter does not delete anything.
|
|
201
|
+
*/
|
|
202
|
+
renderButtons() {
|
|
203
|
+
const confirm = this.confirmButton
|
|
202
204
|
? html `
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
205
|
+
<md-filled-button
|
|
206
|
+
id="confirm"
|
|
207
|
+
slot="confirm"
|
|
208
|
+
type="button"
|
|
209
|
+
?destructive=${!!this.confirmButton.destructive}
|
|
210
|
+
@click=${() => this.onConfirm()}
|
|
211
|
+
>${this.confirmButton.text}</md-filled-button
|
|
212
|
+
>
|
|
213
|
+
`
|
|
214
|
+
: nothing;
|
|
215
|
+
const cancel = this.cancelButton
|
|
209
216
|
? html `
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
: nothing
|
|
215
|
-
|
|
216
|
-
`;
|
|
217
|
+
<md-text-button id="cancel" slot="cancel" type="button" @click=${() => this.onCancel()}
|
|
218
|
+
>${this.cancelButton.text}</md-text-button
|
|
219
|
+
>
|
|
220
|
+
`
|
|
221
|
+
: nothing;
|
|
222
|
+
return this.confirmButton?.destructive ? html `${cancel}${confirm}` : html `${confirm}${cancel}`;
|
|
217
223
|
}
|
|
218
224
|
resolve(result) {
|
|
219
225
|
if (this.resolveFn) {
|
|
@@ -260,10 +266,12 @@ let OxPrompt = class OxPrompt extends LitElement {
|
|
|
260
266
|
* @param {string} [options.footer] - Additional information to be displayed at the bottom of the popup.
|
|
261
267
|
* @param {object} [options.confirmButton] - Configuration for the confirmation button in the popup.
|
|
262
268
|
* @param {string} options.confirmButton.text - The text to be displayed on the confirmation button.
|
|
263
|
-
* @param {string} [options.confirmButton.color] - The
|
|
269
|
+
* @param {string} [options.confirmButton.color] - Not applied. The action row owns button colours.
|
|
270
|
+
* @param {boolean} [options.confirmButton.destructive] - The confirmation cannot be undone (delete, discard): the
|
|
271
|
+
* button takes the error colour and cancel gets the first focus.
|
|
264
272
|
* @param {object} [options.cancelButton] - Configuration for the cancel button in the popup.
|
|
265
273
|
* @param {string} options.cancelButton.text - The text to be displayed on the cancel button.
|
|
266
|
-
* @param {string} [options.cancelButton.color] -
|
|
274
|
+
* @param {string} [options.cancelButton.color] - Not applied. Cancel is never coloured.
|
|
267
275
|
* @param {number} [options.top] - The top position of the popup (in pixels).
|
|
268
276
|
* @param {number} [options.left] - The left position of the popup (in pixels).
|
|
269
277
|
* @param {number} [options.right] - The right position of the popup (in pixels).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-prompt.js","sourceRoot":"","sources":["../../src/ox-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/outlined-button.js'\nimport '@material/web/icon/icon.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { css, html, nothing, LitElement } from 'lit'\nimport { render } from 'lit-html'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nconst TYPES_ICON = {\n success: 'verified',\n error: 'error',\n warning: 'warning',\n info: 'info',\n question: 'question_mark'\n}\n\n/**\n * The `ox-prompt` custom element represents a modal popup that provides information or options for the user, such as confirmation or cancellation.\n */\n@customElement('ox-prompt')\nexport class OxPrompt extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n :host {\n position: absolute;\n display: flex;\n flex-direction: column;\n gap: var(--ox-prompt-gap, var(--spacing-medium));\n background-color: var(--ox-popup-list-background-color, var(--md-sys-color-surface));\n z-index: 1000;\n padding: var(--ox-prompt-container-padding, var(--spacing-medium));\n box-shadow: var(--ox-prompt-container-box-shadow, 2px 3px 10px 5px rgba(0, 0, 0, 0.15));\n border-radius: var(--ox-prompt-container-border-radius, var(--md-sys-shape-corner-medium));\n box-sizing: border-box;\n min-width: 300;\n line-height: initial;\n text-align: initial;\n }\n\n :host([active]) {\n display: block;\n }\n\n :host(*:focus) {\n outline: none;\n }\n\n [titler] {\n padding: var(--ox-prompt-title-padding, var(--spacing-medium));\n padding-bottom: 0;\n color: var(--ox-prompt-title-color, var(--md-sys-color-primary));\n font-size: var(--md-sys-typescale-title-large-size, 1.375rem);\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n text-align: var(--ox-prompt-title-text-align, 'left');\n }\n\n [content] {\n display: flex;\n flex-direction: column;\n gap: var(--ox-prompt-content-gap, var(--spacing-medium));\n padding: var(--ox-prompt-content-padding, var(--spacing-medium));\n color: var(--ox-prompt-body-color, var(--md-sys-color-on-surface));\n word-break: keep-all;\n white-space: pre-line;\n text-align: var(--ox-prompt-content-text-align, 'left');\n\n md-icon {\n align-self: center;\n --md-icon-size: var(--icon-size-huge);\n color: var(--ox-prompt-body-color-variant, var(--md-sys-color-primary));\n }\n }\n\n [content].warning md-icon {\n color: var(--status-warning-color, #ee8d03);\n }\n\n [content].error md-icon {\n color: var(--md-sys-color-error, var(--md-sys-color-error));\n }\n\n [content].info md-icon {\n color: var(--status-info-color, #398ace);\n }\n\n [content].success md-icon {\n color: var(--status-success-color, #35a24a);\n }\n\n [buttons] {\n display: flex;\n border-top: 1px solid var(--md-sys-color-surface-variant);\n gap: var(--ox-prompt-buttons-spacing, var(--spacing-large));\n padding: var(--ox-prompt-buttons-padding, var(--spacing-medium));\n padding-top: var(--spacing-large);\n justify-content: center;\n }\n\n #confirm {\n --md-filled-button-container-color: var(--md-sys-color-primary);\n --md-filled-button-label-text-color: var(--md-sys-color-on-primary);\n --md-filled-button-label-text-size: var(--md-sys-typescale-label-large-size, 0.875rem);\n --md-filled-button-container-height: var(--form-element-height-medium);\n --md-filled-button-container-shape: var(--md-sys-shape-corner-small);\n --md-filled-button-leading-space: var(--spacing-large);\n --md-filled-button-trailing-space: var(--spacing-large);\n }\n\n #cancel {\n --md-outlined-button-container-color: var(--md-sys-color-surface-variant);\n --md-outlined-button-label-text-color: var(--md-sys-color-on-surface-variant);\n --md-outlined-button-label-text-size: var(--md-sys-typescale-label-large-size, 0.875rem);\n --md-outlined-button-container-height: var(--form-element-height-medium);\n --md-outlined-button-container-shape: var(--md-sys-shape-corner-small);\n --md-outlined-button-leading-space: var(--spacing-large);\n --md-outlined-button-trailing-space: var(--spacing-large);\n }\n `\n ]\n\n /**\n * Specifies the type of the popup. Possible values are 'success', 'error', 'warning', 'info', 'question'.\n */\n @property({ type: String }) type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n\n /**\n * Specifies the icon of the popup.\n */\n @property({ type: String }) icon?: string\n\n /**\n * Specifies the title of the popup.\n */\n @property({ type: String }) titler?: string = ''\n\n /**\n * Specifies the text content of the popup.\n */\n @property({ type: String }) text?: string\n\n /**\n * Specifies the footer (additional information at the bottom) of the popup.\n */\n @property({ type: String }) footer?: string\n\n /**\n * Determines whether the popup is displayed as a toast.\n */\n @property({ type: Boolean }) toast?: boolean\n\n /**\n * Specifies settings for the confirmation button.\n */\n @property({ type: Object }) confirmButton?: { text: string; color?: string }\n\n /**\n * Specifies settings for the cancel button.\n */\n @property({ type: Object }) cancelButton?: { text: string; color?: string }\n\n /**\n * Prevents the popup from closing when it loses focus (blur event).\n */\n @property({ type: Boolean, attribute: 'prevent-close-on-blur' }) preventCloseOnBlur: boolean = false\n\n /**\n * A callback function called when the popup is closed, providing the result of the user's interaction.\n */\n @property({ type: Object }) callback?: (result: { value: boolean }) => void\n\n @state() _parent?: Element\n\n private resolveFn: ((value: boolean) => void) | null = null\n\n render() {\n return html`\n ${this.titler ? html` <div titler class=\"md-typescale-title-large\">${this.titler}</div> ` : nothing}\n <div content class=\"${this.type || 'info'} md-typescale-body-large\">\n ${this.icon || this.type\n ? html` <md-icon icon>${this.icon || TYPES_ICON[this.type || 'info']}</md-icon> `\n : nothing}\n ${this.text ? html` <div text>${this.text}</div> ` : nothing}\n <slot> </slot>\n ${this.footer ? html` <div footer class=\"md-typescale-body-large\">${this.footer}</div> ` : nothing}\n </div>\n <div buttons>\n ${this.confirmButton\n ? html`\n <md-filled-button id=\"confirm\" type=\"button\" @click=${(e: Event) => this.onConfirm()}\n >${this.confirmButton?.text}</md-filled-button\n >\n `\n : nothing}\n ${this.cancelButton\n ? html`\n <md-outlined-button id=\"cancel\" type=\"button\" @click=${(e: Event) => this.onCancel()}\n >${this.cancelButton?.text}</md-outlined-button\n >\n `\n : nothing}\n </div>\n `\n }\n\n resolve(result: boolean) {\n if (this.resolveFn) {\n this.resolveFn(result)\n this.resolveFn = null\n }\n }\n\n /**\n * Function called when the confirm button is clicked.\n */\n onConfirm() {\n this.resolve(true)\n this.close()\n }\n\n /**\n * Function called when the cancel button is clicked.\n */\n onCancel() {\n this.resolve(false)\n this.close()\n }\n\n protected _onfocusout: (e: FocusEvent) => void = function (this: OxPrompt, e: FocusEvent) {\n const to = e.relatedTarget as HTMLElement\n\n if (!this.contains(to)) {\n /* 분명히 내 범위가 아닌 엘리먼트로 포커스가 옮겨졌다면, ox-prompt은 닫혀야 한다. */\n // @ts-ignore for debug\n if (this.preventCloseOnBlur || window.POPUP_DEBUG) {\n return\n }\n\n this.resolve(false)\n this.close()\n }\n }.bind(this)\n\n protected _onkeydown: (e: KeyboardEvent) => void = function (this: OxPrompt, e: KeyboardEvent) {\n e.stopPropagation()\n\n switch (e.key) {\n case 'Esc': // for IE/Edge\n case 'Escape':\n this.resolve(false)\n this.close()\n break\n }\n }.bind(this)\n\n protected _onkeyup: (e: KeyboardEvent) => void = function (this: OxPrompt, e: KeyboardEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onmouseup: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onmousedown: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _oncontextmenu: (e: Event) => void = function (this: OxPrompt, e: Event) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onclick: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onclose: (e: Event) => void = function (this: OxPrompt, e: Event) {\n this.resolve(false)\n this.close()\n }.bind(this)\n\n protected _oncollapse: (e: Event) => void = function (this: OxPrompt, e: Event) {\n e.stopPropagation()\n\n this.resolve(false)\n this.close()\n }.bind(this)\n\n protected _onwindowblur: (e: Event) => void = function (this: OxPrompt, e: Event) {\n // @ts-ignore for debug\n if (this.preventCloseOnBlur || window.POPUP_DEBUG) {\n return\n }\n\n this.resolve(false)\n this.close()\n }.bind(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n this.addEventListener('focusout', this._onfocusout)\n this.addEventListener('keydown', this._onkeydown)\n this.addEventListener('keyup', this._onkeyup)\n this.addEventListener('click', this._onclick)\n this.addEventListener('mouseup', this._onmouseup)\n this.addEventListener('mousedown', this._onmousedown)\n this.addEventListener('contextmenu', this._oncontextmenu)\n this.addEventListener('ox-close', this._onclose)\n this.addEventListener('ox-collapse', this._oncollapse)\n\n this.setAttribute('tabindex', '0') // make this element focusable\n this.guaranteeFocus()\n }\n\n /**\n * Static method to open the `ox-prompt` popup.\n * @param {object} options - An object containing popup options.\n * @param {unknown} [options.template] - An optional content template to render inside the popup.\n * @param {'success' | 'error' | 'warning' | 'info' | 'question'} [options.type] - The type of the popup, which can be one of: 'success', 'error', 'warning', 'info', 'question'.\n * @param {string} [options.icon] - The icon to be displayed in the popup header.\n * @param {string} [options.title] - The title to be displayed in the popup header.\n * @param {string} [options.text] - The main text content of the popup.\n * @param {string} [options.footer] - Additional information to be displayed at the bottom of the popup.\n * @param {object} [options.confirmButton] - Configuration for the confirmation button in the popup.\n * @param {string} options.confirmButton.text - The text to be displayed on the confirmation button.\n * @param {string} [options.confirmButton.color] - The color of the confirmation button (CSS color).\n * @param {object} [options.cancelButton] - Configuration for the cancel button in the popup.\n * @param {string} options.cancelButton.text - The text to be displayed on the cancel button.\n * @param {string} [options.cancelButton.color] - The color of the cancel button (CSS color).\n * @param {number} [options.top] - The top position of the popup (in pixels).\n * @param {number} [options.left] - The left position of the popup (in pixels).\n * @param {number} [options.right] - The right position of the popup (in pixels).\n * @param {number} [options.bottom] - The bottom position of the popup (in pixels).\n * @param {string} [options.width] - The maximum width of the popup (CSS string).\n * @param {string} [options.height] - The maximum height of the popup (CSS string).\n * @param {Element | null} [options.parent] - The parent element to which the popup should be attached. If not provided, it will be attached to the document body.\n * @param {boolean} [options.preventCloseOnBlur] - Prevents the popup from closing when it loses focus (blur event).\n * @param {(result: { value: boolean }) => void} [options.callback] - A callback function that will be invoked when the user interacts with the popup, providing the result of the interaction.\n * @returns {Promise<boolean>} A Promise that resolves based on user interaction with the popup.\n */\n public static async open({\n template,\n type,\n icon,\n title,\n text,\n footer,\n confirmButton,\n cancelButton,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent,\n preventCloseOnBlur,\n callback\n }: {\n template?: unknown\n type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n icon?: string\n title?: string\n text?: string\n footer?: string\n confirmButton?: { text: string; color?: string }\n cancelButton?: { text: string; color?: string }\n top?: number\n left?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n parent?: Element | null\n preventCloseOnBlur?: boolean\n callback?: (result: { value: boolean }) => void\n }): Promise<boolean> {\n const owner = parent || document.body\n const target = document.createElement('ox-prompt') as OxPrompt\n\n target.type = type\n target.icon = icon\n target.text = text\n target.titler = title\n target.footer = footer\n target.confirmButton = confirmButton\n target.cancelButton = cancelButton\n target.preventCloseOnBlur = !!preventCloseOnBlur\n\n render(template, target)\n\n target._parent = owner\n owner.appendChild(target)\n\n const result = await target.open({ top, left, right, bottom, width, height })\n\n if (callback) {\n await callback.call(null, { value: result })\n }\n\n return result\n }\n\n /**\n * Static method to open an input popup — a modal replacement for the native `window.prompt()`.\n *\n * Benchmarks `prompt(message, defaultValue)`: shows a text field and resolves with the entered\n * string on confirm, or `null` on cancel/escape/blur. Single-line inputs also confirm on Enter.\n *\n * This is purely additive and does not change the behavior of `OxPrompt.open()`.\n *\n * @returns {Promise<string | null>} The entered text on confirm, or null on cancel.\n */\n public static async prompt({\n title,\n text,\n defaultValue = '',\n placeholder = '',\n type = 'question',\n icon,\n multiline = false,\n confirmButton,\n cancelButton,\n preventCloseOnBlur = true,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent\n }: {\n title?: string\n text?: string\n defaultValue?: string\n placeholder?: string\n type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n icon?: string\n multiline?: boolean\n confirmButton?: { text: string; color?: string }\n cancelButton?: { text: string; color?: string }\n preventCloseOnBlur?: boolean\n top?: number\n left?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n parent?: Element | null\n }): Promise<string | null> {\n const holder = { value: defaultValue }\n\n const onInput = (e: Event) => {\n holder.value = (e.target as HTMLInputElement | HTMLTextAreaElement).value\n }\n const onKeydown = (e: KeyboardEvent) => {\n // 단일 라인: Enter 로 확정(native prompt 벤치마킹). multiline 은 개행 유지.\n if (!multiline && e.key === 'Enter') {\n e.preventDefault()\n const host = (e.target as HTMLElement).closest('ox-prompt') as OxPrompt | null\n host?.onConfirm()\n }\n }\n\n // 폭은 컨테이너를 최대로 채우고(min-width 로 최소 크기 보장), textarea 는 세로로만 리사이즈.\n const inputStyle =\n 'width: 100%; min-width: var(--ox-prompt-input-min-width, 320px); box-sizing: border-box; padding: 8px; font: inherit;'\n\n const template = multiline\n ? html`\n <textarea\n rows=\"3\"\n placeholder=${placeholder}\n .value=${defaultValue}\n style=\"${inputStyle} resize: vertical;\"\n @input=${onInput}\n @keydown=${onKeydown}\n ></textarea>\n `\n : html`\n <input\n type=\"text\"\n placeholder=${placeholder}\n .value=${defaultValue}\n style=\"${inputStyle} resize: none;\"\n @input=${onInput}\n @keydown=${onKeydown}\n />\n `\n\n const confirmed = await OxPrompt.open({\n template,\n type,\n icon,\n title,\n text,\n confirmButton: confirmButton || { text: 'OK' },\n cancelButton: cancelButton || { text: 'Cancel' },\n preventCloseOnBlur,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent\n })\n\n return confirmed ? holder.value : null\n }\n\n /**\n * Opens the popup with specified position and dimensions.\n * @param {object} options - An object specifying the position and dimensions of the popup.\n * @param {number} [options.left] - The left position of the popup (in pixels). If not provided, the popup will be horizontally centered.\n * @param {number} [options.top] - The top position of the popup (in pixels). If not provided, the popup will be vertically centered.\n * @param {number} [options.right] - The right position of the popup (in pixels). Overrides 'left' if both 'left' and 'right' are provided.\n * @param {number} [options.bottom] - The bottom position of the popup (in pixels). Overrides 'top' if both 'top' and 'bottom' are provided.\n * @param {string} [options.width] - The maximum width of the popup (CSS string). If not provided, no width restriction is applied.\n * @param {string} [options.height] - The maximum height of the popup (CSS string). If not provided, no height restriction is applied.\n * @param {boolean} [options.silent=false] - Determines whether to focus the popup automatically (true) or not (false).\n * @returns {Promise<boolean>} A Promise that resolves based on user interaction with the popup.\n */\n open({\n left,\n top,\n right,\n bottom,\n width,\n height,\n silent = false\n }: {\n left?: number\n top?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n silent?: boolean\n }): Promise<boolean> {\n if (width) {\n this.style.maxWidth = width\n this.style.overflowX = 'auto'\n }\n\n if (height) {\n this.style.maxHeight = height\n this.style.overflowY = 'auto'\n }\n\n if (left === undefined && top === undefined && right === undefined && bottom === undefined) {\n this.style.left = '50%'\n this.style.top = '50%'\n this.style.transform = 'translateX(-50%) translateY(-50%)'\n } else {\n if (left !== undefined) this.style.left = `${left}px`\n if (top !== undefined) this.style.top = `${top}px`\n if (right !== undefined) this.style.right = `${right}px`\n if (bottom !== undefined) this.style.bottom = `${bottom}px`\n }\n\n this.setAttribute('active', '')\n\n // adjust popup position\n requestAnimationFrame(() => {\n const vh = document.body.clientHeight\n const vw = document.body.clientWidth\n\n var bounding = this.getBoundingClientRect()\n\n var h = bounding.height\n var w = bounding.width\n var t = bounding.top\n var l = bounding.left\n\n // If the popup is too large, it will cause overflow scrolling.\n if (vh < h) {\n this.style.height = `${Math.min(Math.max(Math.floor((vh * 2) / 3), vh - (t + 20)), vh)}px`\n this.style.overflow = 'auto'\n h = vh\n }\n\n if (vw < w) {\n this.style.width = `${Math.min(Math.max(Math.floor((vw * 2) / 3), vw - (l + 20)), vw)}px`\n this.style.overflow = 'auto'\n w = vw\n }\n\n // To prevent pop-ups from crossing screen boundaries, use the\n const computedStyle = getComputedStyle(this)\n\n if (t < 0) {\n this.style.top = `calc(${computedStyle.top} + ${t}px)`\n this.style.bottom = ''\n } else if (vh <= t + h) {\n this.style.top = `calc(${computedStyle.top} - ${t + h - vh}px)`\n this.style.bottom = ''\n }\n\n if (l < 0) {\n this.style.left = `calc(${computedStyle.left} + ${l}px)`\n this.style.right = ''\n } else if (vw < l + w) {\n this.style.left = `calc(${computedStyle.left} - ${l + w - vw}px)`\n this.style.right = ''\n }\n })\n\n requestAnimationFrame(() => {\n // auto focusing\n !silent && this.guaranteeFocus()\n })\n\n /* When the window is out of focus, all pop-ups should disappear. */\n window.addEventListener('blur', this._onwindowblur)\n\n return new Promise(resolve => {\n this.resolveFn = resolve\n })\n }\n\n guaranteeFocus(target?: HTMLElement) {\n const focusible = (target || this.renderRoot)?.querySelector(\n ':host > button, :host > [href], :host > input, :host > select, :host > textarea, :host > [tabindex]:not([tabindex=\"-1\"]), :host [type=\"button\"]'\n )\n\n if (focusible) {\n ;(focusible as HTMLElement).focus()\n } else {\n this.focus()\n }\n }\n\n /**\n * Closes the popup.\n */\n close() {\n this.removeAttribute('active')\n\n window.removeEventListener('blur', this._onwindowblur)\n\n if (this._parent) {\n /* this case is when the popup is opened by OxPrompt.open(...) */\n this.removeEventListener('focusout', this._onfocusout)\n this.removeEventListener('keydown', this._onkeydown)\n this.removeEventListener('keyup', this._onkeyup)\n this.removeEventListener('click', this._onclick)\n this.removeEventListener('ox-close', this._onclose)\n this.removeEventListener('ox-collapse', this._oncollapse)\n this.removeEventListener('mouseup', this._onmouseup)\n this.removeEventListener('mousedown', this._onmousedown)\n this.removeEventListener('contextmenu', this._oncontextmenu)\n\n this._parent.removeChild(this)\n delete this._parent\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-prompt.js","sourceRoot":"","sources":["../../src/ox-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport './ox-popup-actions.js'\nimport '@material/web/icon/icon.js'\nimport { styles as MDTypeScaleStyles } from '@material/web/typography/md-typescale-styles.js'\n\nimport { css, html, nothing, LitElement } from 'lit'\nimport { render } from 'lit-html'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nconst TYPES_ICON = {\n success: 'verified',\n error: 'error',\n warning: 'warning',\n info: 'info',\n question: 'question_mark'\n}\n\n/**\n * The `ox-prompt` custom element represents a modal popup that provides information or options for the user, such as confirmation or cancellation.\n */\n@customElement('ox-prompt')\nexport class OxPrompt extends LitElement {\n static styles = [\n MDTypeScaleStyles,\n ScrollbarStyles,\n css`\n :host {\n position: absolute;\n display: flex;\n flex-direction: column;\n gap: var(--ox-prompt-gap, var(--spacing-medium));\n background-color: var(--ox-popup-list-background-color, var(--md-sys-color-surface));\n z-index: 1000;\n padding: var(--ox-prompt-container-padding, var(--spacing-medium));\n box-shadow: var(--ox-prompt-container-box-shadow, 2px 3px 10px 5px rgba(0, 0, 0, 0.15));\n border-radius: var(--ox-prompt-container-border-radius, var(--md-sys-shape-corner-medium));\n box-sizing: border-box;\n min-width: 300;\n line-height: initial;\n text-align: initial;\n }\n\n :host([active]) {\n display: block;\n }\n\n :host(*:focus) {\n outline: none;\n }\n\n [titler] {\n padding: var(--ox-prompt-title-padding, var(--spacing-medium));\n padding-bottom: 0;\n color: var(--ox-prompt-title-color, var(--md-sys-color-primary));\n font-size: var(--md-sys-typescale-title-large-size, 1.375rem);\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n text-align: var(--ox-prompt-title-text-align, 'left');\n }\n\n [content] {\n display: flex;\n flex-direction: column;\n gap: var(--ox-prompt-content-gap, var(--spacing-medium));\n padding: var(--ox-prompt-content-padding, var(--spacing-medium));\n color: var(--ox-prompt-body-color, var(--md-sys-color-on-surface));\n word-break: keep-all;\n white-space: pre-line;\n text-align: var(--ox-prompt-content-text-align, 'left');\n\n md-icon {\n align-self: center;\n --md-icon-size: var(--icon-size-huge);\n color: var(--ox-prompt-body-color-variant, var(--md-sys-color-primary));\n }\n }\n\n [content].warning md-icon {\n color: var(--status-warning-color, #ee8d03);\n }\n\n [content].error md-icon {\n color: var(--md-sys-color-error, var(--md-sys-color-error));\n }\n\n [content].info md-icon {\n color: var(--status-info-color, #398ace);\n }\n\n [content].success md-icon {\n color: var(--status-success-color, #35a24a);\n }\n\n /*\n * The command row is the shared popup action row: confirm on the right, cancel just before it,\n * pills of --popup-action-height with a mouse, a square full-width bar with a finger. Its own margins keep the row\n * inside the card's padding with a mouse.\n */\n ox-popup-actions {\n margin: 0 var(--ox-prompt-buttons-padding, var(--spacing-medium)) var(--ox-prompt-buttons-padding, var(--spacing-medium));\n }\n\n @media (pointer: coarse) {\n /* The bar is the card's bottom edge: it reaches both sides, and the card clips its corners. */\n :host {\n overflow: hidden;\n }\n\n ox-popup-actions {\n margin: var(--spacing-medium) calc(-1 * var(--ox-prompt-container-padding, var(--spacing-medium)))\n calc(-1 * var(--ox-prompt-container-padding, var(--spacing-medium)));\n }\n }\n `\n ]\n\n /**\n * Specifies the type of the popup. Possible values are 'success', 'error', 'warning', 'info', 'question'.\n */\n @property({ type: String }) type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n\n /**\n * Specifies the icon of the popup.\n */\n @property({ type: String }) icon?: string\n\n /**\n * Specifies the title of the popup.\n */\n @property({ type: String }) titler?: string = ''\n\n /**\n * Specifies the text content of the popup.\n */\n @property({ type: String }) text?: string\n\n /**\n * Specifies the footer (additional information at the bottom) of the popup.\n */\n @property({ type: String }) footer?: string\n\n /**\n * Determines whether the popup is displayed as a toast.\n */\n @property({ type: Boolean }) toast?: boolean\n\n /**\n * Specifies settings for the confirmation button.\n */\n @property({ type: Object }) confirmButton?: { text: string; color?: string; destructive?: boolean }\n\n /**\n * Specifies settings for the cancel button.\n */\n @property({ type: Object }) cancelButton?: { text: string; color?: string }\n\n /**\n * Prevents the popup from closing when it loses focus (blur event).\n */\n @property({ type: Boolean, attribute: 'prevent-close-on-blur' }) preventCloseOnBlur: boolean = false\n\n /**\n * A callback function called when the popup is closed, providing the result of the user's interaction.\n */\n @property({ type: Object }) callback?: (result: { value: boolean }) => void\n\n @state() _parent?: Element\n\n private resolveFn: ((value: boolean) => void) | null = null\n\n render() {\n return html`\n ${this.titler ? html` <div titler class=\"md-typescale-title-large\">${this.titler}</div> ` : nothing}\n <div content class=\"${this.type || 'info'} md-typescale-body-large\">\n ${this.icon || this.type\n ? html` <md-icon icon>${this.icon || TYPES_ICON[this.type || 'info']}</md-icon> `\n : nothing}\n ${this.text ? html` <div text>${this.text}</div> ` : nothing}\n <slot> </slot>\n ${this.footer ? html` <div footer class=\"md-typescale-body-large\">${this.footer}</div> ` : nothing}\n </div>\n <ox-popup-actions>\n ${this.renderButtons()}\n </ox-popup-actions>\n `\n }\n\n /*\n * Markup order only decides which button gets the first focus; the row decides where they stand.\n * A destructive confirmation focuses cancel, so a reflexive Enter does not delete anything.\n */\n private renderButtons() {\n const confirm = this.confirmButton\n ? html`\n <md-filled-button\n id=\"confirm\"\n slot=\"confirm\"\n type=\"button\"\n ?destructive=${!!this.confirmButton.destructive}\n @click=${() => this.onConfirm()}\n >${this.confirmButton.text}</md-filled-button\n >\n `\n : nothing\n const cancel = this.cancelButton\n ? html`\n <md-text-button id=\"cancel\" slot=\"cancel\" type=\"button\" @click=${() => this.onCancel()}\n >${this.cancelButton.text}</md-text-button\n >\n `\n : nothing\n\n return this.confirmButton?.destructive ? html`${cancel}${confirm}` : html`${confirm}${cancel}`\n }\n\n resolve(result: boolean) {\n if (this.resolveFn) {\n this.resolveFn(result)\n this.resolveFn = null\n }\n }\n\n /**\n * Function called when the confirm button is clicked.\n */\n onConfirm() {\n this.resolve(true)\n this.close()\n }\n\n /**\n * Function called when the cancel button is clicked.\n */\n onCancel() {\n this.resolve(false)\n this.close()\n }\n\n protected _onfocusout: (e: FocusEvent) => void = function (this: OxPrompt, e: FocusEvent) {\n const to = e.relatedTarget as HTMLElement\n\n if (!this.contains(to)) {\n /* 분명히 내 범위가 아닌 엘리먼트로 포커스가 옮겨졌다면, ox-prompt은 닫혀야 한다. */\n // @ts-ignore for debug\n if (this.preventCloseOnBlur || window.POPUP_DEBUG) {\n return\n }\n\n this.resolve(false)\n this.close()\n }\n }.bind(this)\n\n protected _onkeydown: (e: KeyboardEvent) => void = function (this: OxPrompt, e: KeyboardEvent) {\n e.stopPropagation()\n\n switch (e.key) {\n case 'Esc': // for IE/Edge\n case 'Escape':\n this.resolve(false)\n this.close()\n break\n }\n }.bind(this)\n\n protected _onkeyup: (e: KeyboardEvent) => void = function (this: OxPrompt, e: KeyboardEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onmouseup: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onmousedown: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _oncontextmenu: (e: Event) => void = function (this: OxPrompt, e: Event) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onclick: (e: MouseEvent) => void = function (this: OxPrompt, e: MouseEvent) {\n e.stopPropagation()\n }.bind(this)\n\n protected _onclose: (e: Event) => void = function (this: OxPrompt, e: Event) {\n this.resolve(false)\n this.close()\n }.bind(this)\n\n protected _oncollapse: (e: Event) => void = function (this: OxPrompt, e: Event) {\n e.stopPropagation()\n\n this.resolve(false)\n this.close()\n }.bind(this)\n\n protected _onwindowblur: (e: Event) => void = function (this: OxPrompt, e: Event) {\n // @ts-ignore for debug\n if (this.preventCloseOnBlur || window.POPUP_DEBUG) {\n return\n }\n\n this.resolve(false)\n this.close()\n }.bind(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n this.addEventListener('focusout', this._onfocusout)\n this.addEventListener('keydown', this._onkeydown)\n this.addEventListener('keyup', this._onkeyup)\n this.addEventListener('click', this._onclick)\n this.addEventListener('mouseup', this._onmouseup)\n this.addEventListener('mousedown', this._onmousedown)\n this.addEventListener('contextmenu', this._oncontextmenu)\n this.addEventListener('ox-close', this._onclose)\n this.addEventListener('ox-collapse', this._oncollapse)\n\n this.setAttribute('tabindex', '0') // make this element focusable\n this.guaranteeFocus()\n }\n\n /**\n * Static method to open the `ox-prompt` popup.\n * @param {object} options - An object containing popup options.\n * @param {unknown} [options.template] - An optional content template to render inside the popup.\n * @param {'success' | 'error' | 'warning' | 'info' | 'question'} [options.type] - The type of the popup, which can be one of: 'success', 'error', 'warning', 'info', 'question'.\n * @param {string} [options.icon] - The icon to be displayed in the popup header.\n * @param {string} [options.title] - The title to be displayed in the popup header.\n * @param {string} [options.text] - The main text content of the popup.\n * @param {string} [options.footer] - Additional information to be displayed at the bottom of the popup.\n * @param {object} [options.confirmButton] - Configuration for the confirmation button in the popup.\n * @param {string} options.confirmButton.text - The text to be displayed on the confirmation button.\n * @param {string} [options.confirmButton.color] - Not applied. The action row owns button colours.\n * @param {boolean} [options.confirmButton.destructive] - The confirmation cannot be undone (delete, discard): the\n * button takes the error colour and cancel gets the first focus.\n * @param {object} [options.cancelButton] - Configuration for the cancel button in the popup.\n * @param {string} options.cancelButton.text - The text to be displayed on the cancel button.\n * @param {string} [options.cancelButton.color] - Not applied. Cancel is never coloured.\n * @param {number} [options.top] - The top position of the popup (in pixels).\n * @param {number} [options.left] - The left position of the popup (in pixels).\n * @param {number} [options.right] - The right position of the popup (in pixels).\n * @param {number} [options.bottom] - The bottom position of the popup (in pixels).\n * @param {string} [options.width] - The maximum width of the popup (CSS string).\n * @param {string} [options.height] - The maximum height of the popup (CSS string).\n * @param {Element | null} [options.parent] - The parent element to which the popup should be attached. If not provided, it will be attached to the document body.\n * @param {boolean} [options.preventCloseOnBlur] - Prevents the popup from closing when it loses focus (blur event).\n * @param {(result: { value: boolean }) => void} [options.callback] - A callback function that will be invoked when the user interacts with the popup, providing the result of the interaction.\n * @returns {Promise<boolean>} A Promise that resolves based on user interaction with the popup.\n */\n public static async open({\n template,\n type,\n icon,\n title,\n text,\n footer,\n confirmButton,\n cancelButton,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent,\n preventCloseOnBlur,\n callback\n }: {\n template?: unknown\n type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n icon?: string\n title?: string\n text?: string\n footer?: string\n confirmButton?: { text: string; color?: string; destructive?: boolean }\n cancelButton?: { text: string; color?: string }\n top?: number\n left?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n parent?: Element | null\n preventCloseOnBlur?: boolean\n callback?: (result: { value: boolean }) => void\n }): Promise<boolean> {\n const owner = parent || document.body\n const target = document.createElement('ox-prompt') as OxPrompt\n\n target.type = type\n target.icon = icon\n target.text = text\n target.titler = title\n target.footer = footer\n target.confirmButton = confirmButton\n target.cancelButton = cancelButton\n target.preventCloseOnBlur = !!preventCloseOnBlur\n\n render(template, target)\n\n target._parent = owner\n owner.appendChild(target)\n\n const result = await target.open({ top, left, right, bottom, width, height })\n\n if (callback) {\n await callback.call(null, { value: result })\n }\n\n return result\n }\n\n /**\n * Static method to open an input popup — a modal replacement for the native `window.prompt()`.\n *\n * Benchmarks `prompt(message, defaultValue)`: shows a text field and resolves with the entered\n * string on confirm, or `null` on cancel/escape/blur. Single-line inputs also confirm on Enter.\n *\n * This is purely additive and does not change the behavior of `OxPrompt.open()`.\n *\n * @returns {Promise<string | null>} The entered text on confirm, or null on cancel.\n */\n public static async prompt({\n title,\n text,\n defaultValue = '',\n placeholder = '',\n type = 'question',\n icon,\n multiline = false,\n confirmButton,\n cancelButton,\n preventCloseOnBlur = true,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent\n }: {\n title?: string\n text?: string\n defaultValue?: string\n placeholder?: string\n type?: 'success' | 'error' | 'warning' | 'info' | 'question'\n icon?: string\n multiline?: boolean\n confirmButton?: { text: string; color?: string }\n cancelButton?: { text: string; color?: string }\n preventCloseOnBlur?: boolean\n top?: number\n left?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n parent?: Element | null\n }): Promise<string | null> {\n const holder = { value: defaultValue }\n\n const onInput = (e: Event) => {\n holder.value = (e.target as HTMLInputElement | HTMLTextAreaElement).value\n }\n const onKeydown = (e: KeyboardEvent) => {\n // 단일 라인: Enter 로 확정(native prompt 벤치마킹). multiline 은 개행 유지.\n if (!multiline && e.key === 'Enter') {\n e.preventDefault()\n const host = (e.target as HTMLElement).closest('ox-prompt') as OxPrompt | null\n host?.onConfirm()\n }\n }\n\n // 폭은 컨테이너를 최대로 채우고(min-width 로 최소 크기 보장), textarea 는 세로로만 리사이즈.\n const inputStyle =\n 'width: 100%; min-width: var(--ox-prompt-input-min-width, 320px); box-sizing: border-box; padding: 8px; font: inherit;'\n\n const template = multiline\n ? html`\n <textarea\n rows=\"3\"\n placeholder=${placeholder}\n .value=${defaultValue}\n style=\"${inputStyle} resize: vertical;\"\n @input=${onInput}\n @keydown=${onKeydown}\n ></textarea>\n `\n : html`\n <input\n type=\"text\"\n placeholder=${placeholder}\n .value=${defaultValue}\n style=\"${inputStyle} resize: none;\"\n @input=${onInput}\n @keydown=${onKeydown}\n />\n `\n\n const confirmed = await OxPrompt.open({\n template,\n type,\n icon,\n title,\n text,\n confirmButton: confirmButton || { text: 'OK' },\n cancelButton: cancelButton || { text: 'Cancel' },\n preventCloseOnBlur,\n top,\n left,\n right,\n bottom,\n width,\n height,\n parent\n })\n\n return confirmed ? holder.value : null\n }\n\n /**\n * Opens the popup with specified position and dimensions.\n * @param {object} options - An object specifying the position and dimensions of the popup.\n * @param {number} [options.left] - The left position of the popup (in pixels). If not provided, the popup will be horizontally centered.\n * @param {number} [options.top] - The top position of the popup (in pixels). If not provided, the popup will be vertically centered.\n * @param {number} [options.right] - The right position of the popup (in pixels). Overrides 'left' if both 'left' and 'right' are provided.\n * @param {number} [options.bottom] - The bottom position of the popup (in pixels). Overrides 'top' if both 'top' and 'bottom' are provided.\n * @param {string} [options.width] - The maximum width of the popup (CSS string). If not provided, no width restriction is applied.\n * @param {string} [options.height] - The maximum height of the popup (CSS string). If not provided, no height restriction is applied.\n * @param {boolean} [options.silent=false] - Determines whether to focus the popup automatically (true) or not (false).\n * @returns {Promise<boolean>} A Promise that resolves based on user interaction with the popup.\n */\n open({\n left,\n top,\n right,\n bottom,\n width,\n height,\n silent = false\n }: {\n left?: number\n top?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n silent?: boolean\n }): Promise<boolean> {\n if (width) {\n this.style.maxWidth = width\n this.style.overflowX = 'auto'\n }\n\n if (height) {\n this.style.maxHeight = height\n this.style.overflowY = 'auto'\n }\n\n if (left === undefined && top === undefined && right === undefined && bottom === undefined) {\n this.style.left = '50%'\n this.style.top = '50%'\n this.style.transform = 'translateX(-50%) translateY(-50%)'\n } else {\n if (left !== undefined) this.style.left = `${left}px`\n if (top !== undefined) this.style.top = `${top}px`\n if (right !== undefined) this.style.right = `${right}px`\n if (bottom !== undefined) this.style.bottom = `${bottom}px`\n }\n\n this.setAttribute('active', '')\n\n // adjust popup position\n requestAnimationFrame(() => {\n const vh = document.body.clientHeight\n const vw = document.body.clientWidth\n\n var bounding = this.getBoundingClientRect()\n\n var h = bounding.height\n var w = bounding.width\n var t = bounding.top\n var l = bounding.left\n\n // If the popup is too large, it will cause overflow scrolling.\n if (vh < h) {\n this.style.height = `${Math.min(Math.max(Math.floor((vh * 2) / 3), vh - (t + 20)), vh)}px`\n this.style.overflow = 'auto'\n h = vh\n }\n\n if (vw < w) {\n this.style.width = `${Math.min(Math.max(Math.floor((vw * 2) / 3), vw - (l + 20)), vw)}px`\n this.style.overflow = 'auto'\n w = vw\n }\n\n // To prevent pop-ups from crossing screen boundaries, use the\n const computedStyle = getComputedStyle(this)\n\n if (t < 0) {\n this.style.top = `calc(${computedStyle.top} + ${t}px)`\n this.style.bottom = ''\n } else if (vh <= t + h) {\n this.style.top = `calc(${computedStyle.top} - ${t + h - vh}px)`\n this.style.bottom = ''\n }\n\n if (l < 0) {\n this.style.left = `calc(${computedStyle.left} + ${l}px)`\n this.style.right = ''\n } else if (vw < l + w) {\n this.style.left = `calc(${computedStyle.left} - ${l + w - vw}px)`\n this.style.right = ''\n }\n })\n\n requestAnimationFrame(() => {\n // auto focusing\n !silent && this.guaranteeFocus()\n })\n\n /* When the window is out of focus, all pop-ups should disappear. */\n window.addEventListener('blur', this._onwindowblur)\n\n return new Promise(resolve => {\n this.resolveFn = resolve\n })\n }\n\n guaranteeFocus(target?: HTMLElement) {\n const focusible = (target || this.renderRoot)?.querySelector(\n ':host > button, :host > [href], :host > input, :host > select, :host > textarea, :host > [tabindex]:not([tabindex=\"-1\"]), :host [type=\"button\"]'\n )\n\n if (focusible) {\n ;(focusible as HTMLElement).focus()\n } else {\n this.focus()\n }\n }\n\n /**\n * Closes the popup.\n */\n close() {\n this.removeAttribute('active')\n\n window.removeEventListener('blur', this._onwindowblur)\n\n if (this._parent) {\n /* this case is when the popup is opened by OxPrompt.open(...) */\n this.removeEventListener('focusout', this._onfocusout)\n this.removeEventListener('keydown', this._onkeydown)\n this.removeEventListener('keyup', this._onkeyup)\n this.removeEventListener('click', this._onclick)\n this.removeEventListener('ox-close', this._onclose)\n this.removeEventListener('ox-collapse', this._oncollapse)\n this.removeEventListener('mouseup', this._onmouseup)\n this.removeEventListener('mousedown', this._onmousedown)\n this.removeEventListener('contextmenu', this._oncontextmenu)\n\n this._parent.removeChild(this)\n delete this._parent\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a popup's result waits between "someone asked to close with this value" and "the popup is
|
|
3
|
+
* actually gone".
|
|
4
|
+
*
|
|
5
|
+
* There are two entrances for a value - the opener's `handle.close(value)` and the content's
|
|
6
|
+
* `closePopup(element, value)` - but only one place settles: the overlay leaving the document.
|
|
7
|
+
* Settling at an entrance would give two settling places. So entrances record, the first recorded
|
|
8
|
+
* value wins, and `openPopup` takes it when the implementation reports the popup gone.
|
|
9
|
+
*/
|
|
10
|
+
/** Called by `openPopup` when a popup opens. Overlays that are not popups never get a slot. */
|
|
11
|
+
export declare function beginPopupResult(name: string): void;
|
|
12
|
+
/** Records a close request's value. True when this call recorded it; false when one came first. */
|
|
13
|
+
export declare function recordPopupResult(name: string | undefined, value: unknown): boolean;
|
|
14
|
+
/** Undoes a record whose request turned out not to close anything, so it cannot become the result. */
|
|
15
|
+
export declare function forgetPopupResult(name: string): void;
|
|
16
|
+
/** Takes the value once, when the popup is gone. Undefined when it was only dismissed. */
|
|
17
|
+
export declare function takePopupResult(name: string): unknown;
|
|
18
|
+
/** True for the first request to go back for this overlay; false while that back is still pending. */
|
|
19
|
+
export declare function claimHistoryBack(name: string): boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a popup's result waits between "someone asked to close with this value" and "the popup is
|
|
3
|
+
* actually gone".
|
|
4
|
+
*
|
|
5
|
+
* There are two entrances for a value - the opener's `handle.close(value)` and the content's
|
|
6
|
+
* `closePopup(element, value)` - but only one place settles: the overlay leaving the document.
|
|
7
|
+
* Settling at an entrance would give two settling places. So entrances record, the first recorded
|
|
8
|
+
* value wins, and `openPopup` takes it when the implementation reports the popup gone.
|
|
9
|
+
*/
|
|
10
|
+
const pending = new Map();
|
|
11
|
+
/** Called by `openPopup` when a popup opens. Overlays that are not popups never get a slot. */
|
|
12
|
+
export function beginPopupResult(name) {
|
|
13
|
+
pending.set(name, { recorded: false });
|
|
14
|
+
}
|
|
15
|
+
/** Records a close request's value. True when this call recorded it; false when one came first. */
|
|
16
|
+
export function recordPopupResult(name, value) {
|
|
17
|
+
if (!name)
|
|
18
|
+
return false;
|
|
19
|
+
const slot = pending.get(name);
|
|
20
|
+
if (!slot || slot.recorded)
|
|
21
|
+
return false;
|
|
22
|
+
pending.set(name, { recorded: true, value });
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
/** Undoes a record whose request turned out not to close anything, so it cannot become the result. */
|
|
26
|
+
export function forgetPopupResult(name) {
|
|
27
|
+
if (pending.has(name))
|
|
28
|
+
pending.set(name, { recorded: false });
|
|
29
|
+
}
|
|
30
|
+
/** Takes the value once, when the popup is gone. Undefined when it was only dismissed. */
|
|
31
|
+
export function takePopupResult(name) {
|
|
32
|
+
const slot = pending.get(name);
|
|
33
|
+
pending.delete(name);
|
|
34
|
+
return slot?.recorded ? slot.value : undefined;
|
|
35
|
+
}
|
|
36
|
+
/*
|
|
37
|
+
* History-backed overlays close with history.back(). The state it reads to decide ("am I the top
|
|
38
|
+
* overlay?") only changes when popstate arrives, so two close requests in the same tick both saw
|
|
39
|
+
* themselves on top and went back twice - one page past the popup. The first claim goes back; later
|
|
40
|
+
* claims for the same overlay are refused until the next popstate.
|
|
41
|
+
*/
|
|
42
|
+
const goingBack = new Set();
|
|
43
|
+
if (typeof window !== 'undefined') {
|
|
44
|
+
window.addEventListener('popstate', () => goingBack.clear());
|
|
45
|
+
}
|
|
46
|
+
/** True for the first request to go back for this overlay; false while that back is still pending. */
|
|
47
|
+
export function claimHistoryBack(name) {
|
|
48
|
+
if (goingBack.has(name))
|
|
49
|
+
return false;
|
|
50
|
+
goingBack.add(name);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=popup-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popup-result.js","sourceRoot":"","sources":["../../src/popup-result.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgB,CAAA;AAEvC,+FAA+F;AAC/F,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AACxC,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,iBAAiB,CAAC,IAAwB,EAAE,KAAc;IACxE,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IAEvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAExC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC5C,OAAO,IAAI,CAAA;AACb,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AAC/D,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC9B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAEpB,OAAO,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;AAEnC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;IAClC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IAErC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnB,OAAO,IAAI,CAAA;AACb,CAAC","sourcesContent":["/**\n * Where a popup's result waits between \"someone asked to close with this value\" and \"the popup is\n * actually gone\".\n *\n * There are two entrances for a value - the opener's `handle.close(value)` and the content's\n * `closePopup(element, value)` - but only one place settles: the overlay leaving the document.\n * Settling at an entrance would give two settling places. So entrances record, the first recorded\n * value wins, and `openPopup` takes it when the implementation reports the popup gone.\n */\n\ntype Slot = { recorded: false } | { recorded: true; value: unknown }\n\nconst pending = new Map<string, Slot>()\n\n/** Called by `openPopup` when a popup opens. Overlays that are not popups never get a slot. */\nexport function beginPopupResult(name: string): void {\n pending.set(name, { recorded: false })\n}\n\n/** Records a close request's value. True when this call recorded it; false when one came first. */\nexport function recordPopupResult(name: string | undefined, value: unknown): boolean {\n if (!name) return false\n\n const slot = pending.get(name)\n if (!slot || slot.recorded) return false\n\n pending.set(name, { recorded: true, value })\n return true\n}\n\n/** Undoes a record whose request turned out not to close anything, so it cannot become the result. */\nexport function forgetPopupResult(name: string): void {\n if (pending.has(name)) pending.set(name, { recorded: false })\n}\n\n/** Takes the value once, when the popup is gone. Undefined when it was only dismissed. */\nexport function takePopupResult(name: string): unknown {\n const slot = pending.get(name)\n pending.delete(name)\n\n return slot?.recorded ? slot.value : undefined\n}\n\n/*\n * History-backed overlays close with history.back(). The state it reads to decide (\"am I the top\n * overlay?\") only changes when popstate arrives, so two close requests in the same tick both saw\n * themselves on top and went back twice - one page past the popup. The first claim goes back; later\n * claims for the same overlay are refused until the next popstate.\n */\nconst goingBack = new Set<string>()\n\nif (typeof window !== 'undefined') {\n window.addEventListener('popstate', () => goingBack.clear())\n}\n\n/** True for the first request to go back for this overlay; false while that back is still pending. */\nexport function claimHistoryBack(name: string): boolean {\n if (goingBack.has(name)) return false\n\n goingBack.add(name)\n return true\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|