@operato/popup 10.29.9 → 10.29.13
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 +18 -0
- package/coverage/lcov-report/index.html +24 -24
- package/coverage/lcov.info +4245 -3679
- package/dist/src/ox-prompt.d.ts +3 -0
- package/dist/src/ox-prompt.js +7 -2
- package/dist/src/ox-prompt.js.map +1 -1
- package/dist/test/ox-prompt-ime-enter.test.d.ts +1 -0
- package/dist/test/ox-prompt-ime-enter.test.js +64 -0
- package/dist/test/ox-prompt-ime-enter.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/test/ox-prompt-ime-enter.test.ts +75 -0
package/dist/src/ox-prompt.d.ts
CHANGED
|
@@ -161,6 +161,9 @@ export declare class OxPrompt extends LitElement {
|
|
|
161
161
|
*
|
|
162
162
|
* This is purely additive and does not change the behavior of `OxPrompt.open()`.
|
|
163
163
|
*
|
|
164
|
+
* No icon unless the caller names a `type` or an `icon`: a question mark above a field that asks for a
|
|
165
|
+
* name says nothing the title and the field do not already say (it used to default to 'question').
|
|
166
|
+
*
|
|
164
167
|
* @returns {Promise<string | null>} The entered text on confirm, or null on cancel.
|
|
165
168
|
*/
|
|
166
169
|
static prompt({ title, text, defaultValue, placeholder, type, icon, multiline, confirmButton, cancelButton, preventCloseOnBlur, top, left, right, bottom, width, height, parent }: {
|
package/dist/src/ox-prompt.js
CHANGED
|
@@ -335,16 +335,21 @@ let OxPrompt = class OxPrompt extends LitElement {
|
|
|
335
335
|
*
|
|
336
336
|
* This is purely additive and does not change the behavior of `OxPrompt.open()`.
|
|
337
337
|
*
|
|
338
|
+
* No icon unless the caller names a `type` or an `icon`: a question mark above a field that asks for a
|
|
339
|
+
* name says nothing the title and the field do not already say (it used to default to 'question').
|
|
340
|
+
*
|
|
338
341
|
* @returns {Promise<string | null>} The entered text on confirm, or null on cancel.
|
|
339
342
|
*/
|
|
340
|
-
static async prompt({ title, text, defaultValue = '', placeholder = '', type
|
|
343
|
+
static async prompt({ title, text, defaultValue = '', placeholder = '', type, icon, multiline = false, confirmButton, cancelButton, preventCloseOnBlur = true, top, left, right, bottom, width, height, parent }) {
|
|
341
344
|
const holder = { value: defaultValue };
|
|
342
345
|
const onInput = (e) => {
|
|
343
346
|
holder.value = e.target.value;
|
|
344
347
|
};
|
|
345
348
|
const onKeydown = (e) => {
|
|
346
349
|
// 단일 라인: Enter 로 확정(native prompt 벤치마킹). multiline 은 개행 유지.
|
|
347
|
-
|
|
350
|
+
// An Enter that ends an IME composition (Korean, Japanese) only commits the syllable; confirming on
|
|
351
|
+
// it would resolve with the last syllable missing.
|
|
352
|
+
if (!multiline && e.key === 'Enter' && !e.isComposing) {
|
|
348
353
|
e.preventDefault();
|
|
349
354
|
const host = e.target.closest('ox-prompt');
|
|
350
355
|
host?.onConfirm();
|
|
@@ -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/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 { i18next } from '@operato/i18n'\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 * Asks before deleting — the modal replacement for `confirm('sure to delete?')`.\n *\n * Framework screens asked with the browser's own dialog (17 places, ADR-0060 decision 9): it\n * blocks the page, cannot be styled or translated, and put \"OK\" where every other popup puts\n * \"cancel\". This is the same question in the shared popup: a warning, \"delete\" painted as\n * destructive on the right, \"cancel\" before it and focused.\n *\n * if (!(await OxPrompt.confirmDelete({ count: selected.length }))) return\n *\n * @returns {Promise<boolean>} true when the user chose delete.\n */\n public static async confirmDelete({ count, parent }: { count?: number; parent?: Element | null } = {}): Promise<boolean> {\n return OxPrompt.open({\n type: 'warning',\n title:\n count && count > 1\n ? i18next.t('text.popup-confirm-delete-count', { count, defaultValue: 'delete the {count} selected items?' })\n : i18next.t('text.popup-confirm-delete', { defaultValue: 'delete the selected item?' }),\n confirmButton: { text: i18next.t('button.popup-delete', { defaultValue: 'delete' }), destructive: true },\n cancelButton: { text: i18next.t('button.popup-cancel', { defaultValue: 'cancel' }) },\n parent\n })\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 { i18next } from '@operato/i18n'\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 * Asks before deleting — the modal replacement for `confirm('sure to delete?')`.\n *\n * Framework screens asked with the browser's own dialog (17 places, ADR-0060 decision 9): it\n * blocks the page, cannot be styled or translated, and put \"OK\" where every other popup puts\n * \"cancel\". This is the same question in the shared popup: a warning, \"delete\" painted as\n * destructive on the right, \"cancel\" before it and focused.\n *\n * if (!(await OxPrompt.confirmDelete({ count: selected.length }))) return\n *\n * @returns {Promise<boolean>} true when the user chose delete.\n */\n public static async confirmDelete({ count, parent }: { count?: number; parent?: Element | null } = {}): Promise<boolean> {\n return OxPrompt.open({\n type: 'warning',\n title:\n count && count > 1\n ? i18next.t('text.popup-confirm-delete-count', { count, defaultValue: 'delete the {count} selected items?' })\n : i18next.t('text.popup-confirm-delete', { defaultValue: 'delete the selected item?' }),\n confirmButton: { text: i18next.t('button.popup-delete', { defaultValue: 'delete' }), destructive: true },\n cancelButton: { text: i18next.t('button.popup-cancel', { defaultValue: 'cancel' }) },\n parent\n })\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 * No icon unless the caller names a `type` or an `icon`: a question mark above a field that asks for a\n * name says nothing the title and the field do not already say (it used to default to 'question').\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,\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 // An Enter that ends an IME composition (Korean, Japanese) only commits the syllable; confirming on\n // it would resolve with the last syllable missing.\n if (!multiline && e.key === 'Enter' && !e.isComposing) {\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 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
import { OxPrompt } from '../src/ox-prompt.js';
|
|
3
|
+
/**
|
|
4
|
+
* OxPrompt.prompt confirms on Enter. An Enter that ends an IME composition (Korean, Japanese) only
|
|
5
|
+
* commits the last syllable, so confirming on it resolved with that syllable missing: a screen named
|
|
6
|
+
* "조립 셀" was created as "조립 ". The plant station-screen list guarded this in its own popup; the
|
|
7
|
+
* shared prompt now does, for every caller.
|
|
8
|
+
*/
|
|
9
|
+
const settle = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms));
|
|
10
|
+
/* Watches the step that matters - whether Enter asks the prompt to confirm - without waiting on the close. */
|
|
11
|
+
async function openWatched() {
|
|
12
|
+
void OxPrompt.prompt({ title: 'name', preventCloseOnBlur: true });
|
|
13
|
+
await settle();
|
|
14
|
+
const prompts = document.body.querySelectorAll('ox-prompt');
|
|
15
|
+
const prompt = prompts[prompts.length - 1];
|
|
16
|
+
const field = prompt.querySelector('input');
|
|
17
|
+
let confirmed = 0;
|
|
18
|
+
prompt.onConfirm = () => {
|
|
19
|
+
confirmed++;
|
|
20
|
+
};
|
|
21
|
+
return { field, confirmed: () => confirmed };
|
|
22
|
+
}
|
|
23
|
+
function enter(field, isComposing) {
|
|
24
|
+
field.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', isComposing, bubbles: true, composed: true }));
|
|
25
|
+
}
|
|
26
|
+
describe('OxPrompt.prompt and Enter', () => {
|
|
27
|
+
afterEach(async () => {
|
|
28
|
+
/* Cancel through the prompt itself so its open() settles and leaves nothing listening behind. */
|
|
29
|
+
document.body.querySelectorAll('ox-prompt').forEach(p => p.onCancel());
|
|
30
|
+
await settle(100);
|
|
31
|
+
document.body.querySelectorAll('ox-prompt').forEach(p => p.remove());
|
|
32
|
+
});
|
|
33
|
+
it('an Enter that ends a composition does not confirm', async () => {
|
|
34
|
+
const { field, confirmed } = await openWatched();
|
|
35
|
+
expect(field, 'the prompt draws a field').to.exist;
|
|
36
|
+
enter(field, true);
|
|
37
|
+
expect(confirmed()).to.equal(0);
|
|
38
|
+
});
|
|
39
|
+
it('a plain Enter confirms', async () => {
|
|
40
|
+
const { field, confirmed } = await openWatched();
|
|
41
|
+
enter(field, false);
|
|
42
|
+
expect(confirmed()).to.equal(1);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('OxPrompt.prompt draws no icon unless asked', () => {
|
|
46
|
+
afterEach(async () => {
|
|
47
|
+
/* Cancel through the prompt itself so its open() settles and leaves nothing listening behind. */
|
|
48
|
+
document.body.querySelectorAll('ox-prompt').forEach(p => p.onCancel());
|
|
49
|
+
await settle(100);
|
|
50
|
+
document.body.querySelectorAll('ox-prompt').forEach(p => p.remove());
|
|
51
|
+
});
|
|
52
|
+
it('a plain prompt has no icon; a typed one does', async () => {
|
|
53
|
+
void OxPrompt.prompt({ title: 'name', preventCloseOnBlur: true });
|
|
54
|
+
void OxPrompt.prompt({ title: 'name', type: 'warning', preventCloseOnBlur: true });
|
|
55
|
+
await settle();
|
|
56
|
+
const prompts = document.body.querySelectorAll('ox-prompt');
|
|
57
|
+
const plain = prompts[0];
|
|
58
|
+
const typed = prompts[1];
|
|
59
|
+
await Promise.all([plain.updateComplete, typed.updateComplete]);
|
|
60
|
+
expect(plain.renderRoot.querySelector('[icon]')).to.equal(null);
|
|
61
|
+
expect(typed.renderRoot.querySelector('[icon]')).to.not.equal(null);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=ox-prompt-ime-enter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-prompt-ime-enter.test.js","sourceRoot":"","sources":["../../test/ox-prompt-ime-enter.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing'\n\nimport { OxPrompt } from '../src/ox-prompt.js'\n\n/**\n * OxPrompt.prompt confirms on Enter. An Enter that ends an IME composition (Korean, Japanese) only\n * commits the last syllable, so confirming on it resolved with that syllable missing: a screen named\n * \"조립 셀\" was created as \"조립 \". The plant station-screen list guarded this in its own popup; the\n * shared prompt now does, for every caller.\n */\n\nconst settle = (ms = 50) => new Promise(resolve => setTimeout(resolve, ms))\n\n/* Watches the step that matters - whether Enter asks the prompt to confirm - without waiting on the close. */\nasync function openWatched() {\n void OxPrompt.prompt({ title: 'name', preventCloseOnBlur: true })\n await settle()\n\n const prompts = document.body.querySelectorAll('ox-prompt')\n const prompt = prompts[prompts.length - 1] as OxPrompt\n const field = prompt.querySelector('input') as HTMLInputElement\n let confirmed = 0\n prompt.onConfirm = () => {\n confirmed++\n }\n return { field, confirmed: () => confirmed }\n}\n\nfunction enter(field: HTMLInputElement, isComposing: boolean) {\n field.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', isComposing, bubbles: true, composed: true }))\n}\n\ndescribe('OxPrompt.prompt and Enter', () => {\n afterEach(async () => {\n /* Cancel through the prompt itself so its open() settles and leaves nothing listening behind. */\n document.body.querySelectorAll('ox-prompt').forEach(p => (p as OxPrompt).onCancel())\n await settle(100)\n document.body.querySelectorAll('ox-prompt').forEach(p => p.remove())\n })\n\n it('an Enter that ends a composition does not confirm', async () => {\n const { field, confirmed } = await openWatched()\n expect(field, 'the prompt draws a field').to.exist\n enter(field, true)\n expect(confirmed()).to.equal(0)\n })\n\n it('a plain Enter confirms', async () => {\n const { field, confirmed } = await openWatched()\n enter(field, false)\n expect(confirmed()).to.equal(1)\n })\n})\n\ndescribe('OxPrompt.prompt draws no icon unless asked', () => {\n afterEach(async () => {\n /* Cancel through the prompt itself so its open() settles and leaves nothing listening behind. */\n document.body.querySelectorAll('ox-prompt').forEach(p => (p as OxPrompt).onCancel())\n await settle(100)\n document.body.querySelectorAll('ox-prompt').forEach(p => p.remove())\n })\n\n it('a plain prompt has no icon; a typed one does', async () => {\n void OxPrompt.prompt({ title: 'name', preventCloseOnBlur: true })\n void OxPrompt.prompt({ title: 'name', type: 'warning', preventCloseOnBlur: true })\n await settle()\n\n const prompts = document.body.querySelectorAll('ox-prompt')\n const plain = prompts[0] as OxPrompt\n const typed = prompts[1] as OxPrompt\n await Promise.all([plain.updateComplete, typed.updateComplete])\n expect(plain.renderRoot.querySelector('[icon]')).to.equal(null)\n expect(typed.renderRoot.querySelector('[icon]')).to.not.equal(null)\n })\n})\n"]}
|