@operato/popup 10.29.49 → 10.29.59
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 +24 -0
- package/dist/src/ox-floating-overlay.js +1 -1
- package/dist/src/ox-floating-overlay.js.map +1 -1
- package/dist/src/ox-popup-list.d.ts +2 -0
- package/dist/src/ox-popup-list.js +34 -1
- package/dist/src/ox-popup-list.js.map +1 -1
- package/dist/src/ox-popup.d.ts +16 -1
- package/dist/src/ox-popup.js +47 -3
- package/dist/src/ox-popup.js.map +1 -1
- package/dist/test/ox-popup-asked-size.test.d.ts +1 -0
- package/dist/test/ox-popup-asked-size.test.js +43 -0
- package/dist/test/ox-popup-asked-size.test.js.map +1 -0
- package/dist/test/ox-popup-list-search.test.d.ts +1 -0
- package/dist/test/ox-popup-list-search.test.js +61 -0
- package/dist/test/ox-popup-list-search.test.js.map +1 -0
- package/dist/test/ox-popup-placement.test.d.ts +1 -0
- package/dist/test/ox-popup-placement.test.js +69 -0
- package/dist/test/ox-popup-placement.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/test/ox-popup-asked-size.test.ts +48 -0
- package/test/ox-popup-list-search.test.ts +71 -0
- package/test/ox-popup-placement.test.ts +81 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [10.29.59](https://github.com/hatiolab/operato/compare/v10.29.58...v10.29.59) (2026-10-28)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* **popup:** a popup opens at the height its opener gave it ([4ceb5c5](https://github.com/hatiolab/operato/commit/4ceb5c50c0d6727ada2c0bf866dddc749400ae56))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### :memo: Documentation
|
|
15
|
+
|
|
16
|
+
* write 패널 and 회차 where 판 meant a panel or a run ([5e3551a](https://github.com/hatiolab/operato/commit/5e3551a47e2651f4cdf0e75712821d0957c0fbea))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### [10.29.52](https://github.com/hatiolab/operato/compare/v10.29.51...v10.29.52) (2026-10-25)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### :bug: Bug Fix
|
|
24
|
+
|
|
25
|
+
* **popup:** a popup never covers the select or point it opens from ([129bffe](https://github.com/hatiolab/operato/commit/129bffe96a3812e3dad0bdb7daae6db307d0afe9))
|
|
26
|
+
* **popup:** searchable list opens with the focus in its search box ([ba42c80](https://github.com/hatiolab/operato/commit/ba42c8005b44431c66244b202013c4641c9347a3))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
### [10.29.49](https://github.com/hatiolab/operato/compare/v10.29.48...v10.29.49) (2026-10-23)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @operato/popup
|
|
@@ -198,7 +198,7 @@ let OxFloatingOverlay = class OxFloatingOverlay extends LitElement {
|
|
|
198
198
|
* ── --popup-radius 는 **카드의 모서리**다. 여기가 그 임자다 ─────────────
|
|
199
199
|
* 이 값이 팝업 안 컨트롤의 모서리를 함께 정한다 — 모서리는 담는 면을 따른다(동심 모서리).
|
|
200
200
|
* 그 짝은 --popup-control-radius 이고 CommonPopupStyles 가 선언한다. 카드를 각지게
|
|
201
|
-
* 하려면 두 값을 **함께** 내려라. 한쪽만 바꾸면 둥근 틀에 각진
|
|
201
|
+
* 하려면 두 값을 **함께** 내려라. 한쪽만 바꾸면 둥근 틀에 각진 패널이 박힌다.
|
|
202
202
|
*/
|
|
203
203
|
border: 1px solid var(--md-sys-color-outline-variant);
|
|
204
204
|
border-radius: var(--popup-radius, 16px);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-floating-overlay.js","sourceRoot":"","sources":["../../src/ox-floating-overlay.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n// 순환 참조가 되어서 일단 코멘트 처리함.\n// import '@operato/input/ox-input-search.js'\n\nimport { css, html, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { OxPrompt } from './ox-prompt.js'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isHandheldDevice } from '@operato/utils'\n\nimport { claimHistoryBack, recordPopupResult } from './popup-result.js'\n\nfunction getPoint(e: Event): { x: number; y: number } | undefined {\n if ((e as MouseEvent).button == 0) {\n return {\n x: (e as MouseEvent).clientX,\n y: (e as MouseEvent).clientY\n }\n } else if ((e as TouchEvent).touches?.length == 1) {\n const touch = (e as TouchEvent).touches[0]\n return {\n x: touch.clientX,\n y: touch.clientY\n }\n } else {\n return\n }\n}\n\n/**\n * Custom element for creating floating overlays.\n * These overlays can have various properties like direction, size, title, and more.\n * They are often used for modal dialogs, pop-ups, and similar UI elements.\n */\n@customElement('ox-floating-overlay')\nexport class OxFloatingOverlay extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n /* for layout style */\n :host {\n position: relative;\n z-index: var(--z-index, 10);\n /*\n * ── 그림자는 층으로 쌓는다 ──────────────────────────────────────────\n * 전에는 2px 3px 10px 5px 였다 — 오른쪽 아래로 치우친 데다 5px 퍼짐이 있어서 상자 네 변에\n * 회색 테를 두른 것처럼 보였다. 떠 있는 느낌이 아니라 덧그린 느낌이다.\n *\n * 가까운 층 하나로 경계를 세우고, 먼 층 하나로 높이를 만든다. 먼 층은 위로 퍼지지 않게\n * 음수 spread 를 준다 — 빛이 위에서 온다는 그 규칙만 지켜도 상자가 뜬다.\n */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 16px 40px -12px rgba(0, 0, 0, 0.28);\n }\n\n :host([hovering='edge']) {\n /* edge hovering 인 경우에는 상위 relative position 크기와 위치를 반영한다. */\n position: initial;\n }\n\n #backdrop {\n position: fixed;\n left: 0;\n top: 0;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n\n background-color: var(--md-sys-color-shadow, #000);\n opacity: 0.4;\n }\n\n [overlayed] {\n position: absolute;\n\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n [overlayed][hovering='center'] {\n position: fixed;\n\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n\n opacity: 0;\n /*\n * ── 테두리는 실선 한 올, 모서리는 둥글게 ────────────────────────────\n * 2px outline 이었다. 화면에서 가장 굵고 가장 진한 선이 상자의 테두리여서, 안에 든 내용보다\n * 상자가 먼저 보였다. 경계는 한 올로 충분하다 — 나머지는 그림자가 맡는다.\n *\n * 모서리도 각이었다. 이 제품의 카드·표는 모두 둥글다(10~14px). 팝업만 각이면 그 하나가\n * 딴 세대의 것으로 보인다.\n *\n * ── --popup-radius 는 **카드의 모서리**다. 여기가 그 임자다 ─────────────\n * 이 값이 팝업 안 컨트롤의 모서리를 함께 정한다 — 모서리는 담는 면을 따른다(동심 모서리).\n * 그 짝은 --popup-control-radius 이고 CommonPopupStyles 가 선언한다. 카드를 각지게\n * 하려면 두 값을 **함께** 내려라. 한쪽만 바꾸면 둥근 틀에 각진 판이 박힌다.\n */\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: var(--popup-radius, 16px);\n }\n\n [overlayed][hovering='center'][opened] {\n opacity: 1;\n transition: opacity 0.3s ease-in;\n background-color: var(--md-sys-color-surface-container-lowest);\n }\n\n [hovering='center'] {\n width: var(--overlay-center-normal-width, 60%);\n height: var(--overlay-center-normal-height, 60%);\n }\n\n [hovering='center'][size='small'] {\n width: var(--overlay-center-small-width, 40%);\n height: var(--overlay-center-small-height, 40%);\n }\n\n [hovering='center'][size='large'] {\n width: var(--overlay-center-large-width, 100%);\n height: var(--overlay-center-large-height, 100%);\n }\n\n [hovering='center'][size='full'] {\n width: var(--overlay-center-full-width, 100%);\n height: var(--overlay-center-full-height, 100%);\n }\n\n /*\n * A form of a few fields stands at its own height. The other sizes are fractions of the screen, so\n * five fields in a medium popup left half the card empty under them. Bounded by the screen; past\n * that the content scrolls in its own body.\n */\n [hovering='center'][size='fit'] {\n width: min(var(--overlay-center-fit-width, 480px), calc(100vw - 32px));\n height: auto;\n max-height: calc(100vh - 32px);\n max-height: calc(100dvh - 32px);\n }\n\n [header] {\n --help-icon-color: var(--md-sys-color-on-primary-container);\n --help-icon-hover-color: var(--md-sys-color-on-primary-container);\n\n pointer-events: initial;\n }\n\n [content] {\n flex: 1;\n overflow: hidden;\n }\n\n ::slotted(*) {\n box-sizing: border-box;\n pointer-events: initial;\n }\n\n [hovering='center'] [content] ::slotted(*) {\n width: 100%;\n height: 100%;\n }\n [direction='up'],\n [direction='down'] {\n width: 100%;\n\n max-height: 0;\n transition: max-height 0.7s ease-in;\n }\n [direction='up'] {\n bottom: 0;\n }\n [direction='down'] {\n top: 0;\n }\n\n [direction='up'][opened],\n [direction='down'][opened] {\n max-height: 100vh;\n max-height: 100dvh;\n }\n\n [settled][direction='down'] [content],\n [settled][direction='up'] [content] {\n overflow-y: auto;\n }\n\n [direction='left'],\n [direction='right'] {\n height: 100%;\n\n max-width: 0;\n transition: max-width 0.5s ease-in;\n }\n [direction='left'] {\n right: 0;\n }\n [direction='right'] {\n left: 0;\n }\n\n [direction='left'][opened],\n [direction='right'][opened] {\n max-width: 100vw;\n }\n\n [settled][direction='left'] [content],\n [settled][direction='right'] [content] {\n overflow-x: auto;\n }\n\n @media screen and (max-width: 460px) {\n [direction='up'],\n [direction='down'] {\n max-height: 100vh;\n max-height: 100dvh;\n }\n\n [direction='left'],\n [direction='right'] {\n max-width: 100vw;\n }\n }\n `,\n css`\n /*\n * for header style\n *\n * primary 는 어두운 표면 위에 놓는 강조색이라 큰 면을 채우면 다크에서 밝은 띠가 된다\n * (실제로 팝업 제목줄이 탄색 블록으로 보였다). 제목줄은 표면이므로 container 역할을 쓴다.\n * 앱이 조정하려면 --popup-header-background / --popup-header-color 를 지정한다.\n */\n [header] {\n display: flex;\n flex-direction: row;\n align-items: center;\n /*\n * 머리는 슬래브가 아니다. 채움과 아래 실선을 둘 다 쓰고 있었고, 채움이 한 단 진해서 그 띠가\n * 안에 든 내용보다 무거웠다. 한 단 낮춘다 — 선은 남긴다(목록이 올라올 때 그 선이 머리를 말한다).\n */\n background-color: var(--popup-header-background, var(--md-sys-color-surface-container-low));\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n color: var(--popup-header-color, var(--md-sys-color-on-surface));\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n slot[name='header'] {\n flex: 1;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n text-transform: capitalize;\n }\n\n [name='header']::slotted(*) {\n margin: 0 auto;\n }\n\n [name='header'] > h1 {\n font-size: var(--md-sys-typescale-title-medium-size, 1rem);\n margin-block: 0.4rem;\n }\n\n [historyback] {\n margin-left: var(--spacing-medium);\n margin-right: auto;\n }\n\n [close] {\n margin-left: auto;\n margin-right: var(--spacing-medium);\n }\n\n [historyback],\n [close] {\n display: none;\n }\n\n [closable][close] {\n display: block;\n cursor: pointer;\n }\n\n /*\n * ── 머리의 아이콘은 **꾸밈이 아니라 곁것**이다 ────────────────────────\n *\n * 닫기와 손잡이가 제목과 같은 잉크에 24px 였다. 제목이 16px 이니 **곁것이 내용보다 굵고\n * 컸다** — 팝업을 열면 눈이 먼저 ✕ 로 갔다.\n *\n * 크기는 이 제품의 아이콘 눈금(18~19px)에 맞추고, 색은 한 단 흐리게 두었다가 마우스를\n * 올릴 때만 짙어진다. 누를 자리는 여백으로 넓혀 둔다 — 아이콘이 작아도 28px 안에서 눌린다.\n *\n * 손잡이(drag_indicator)는 그중 **가장 흐리다.** 그것은 동작이 아니라 「여기를 잡으면\n * 움직인다」는 표시이고, 잡으려는 사람은 이미 그 자리를 안다.\n */\n /*\n * 앱이 --popup-header-background 를 primary 같은 짙은 색으로 바꾸면 아이콘도 함께 밝아져야 한다.\n * --popup-header-icon-color 하나로 닫기/뒤로/손잡이 색을 맞추고, 호버 면은 --popup-header-icon-hover-background.\n */\n [header] md-icon {\n --md-icon-size: 18px;\n\n padding: 5px;\n border-radius: 999em;\n color: var(--popup-header-icon-color, var(--md-sys-color-outline));\n transition:\n color 0.12s ease-out,\n background-color 0.12s ease-out;\n }\n\n [header] md-icon[historyback]:hover,\n [header] md-icon[close]:hover {\n color: var(--popup-header-icon-hover-color, var(--md-sys-color-on-surface));\n background-color: var(--popup-header-icon-hover-background, var(--md-sys-color-surface-container-high));\n }\n\n /* 손잡이는 눌리는 것이 아니라 잡히는 것이다. 면을 주지 않고 색만 한 단 올린다. */\n [header] md-icon:not([close]):not([historyback]) {\n color: var(--popup-header-icon-color, var(--md-sys-color-outline-variant));\n opacity: var(--popup-header-handle-opacity, 1);\n cursor: grab;\n }\n\n [header] md-icon:not([close]):not([historyback]):hover {\n color: var(--popup-header-icon-color, var(--md-sys-color-outline));\n opacity: 1;\n }\n\n [search] ox-help-icon {\n color: var(--md-sys-color-on-secondary-container);\n }\n\n [search] {\n --help-icon-color: var(--md-sys-color-primary);\n --help-icon-hover-color: var(--md-sys-color-primary);\n --help-icon-opacity: 0.2;\n --help-icon-size: 20px;\n\n --md-icon-size: 20px;\n\n --input-search-padding: var(--spacing-medium);\n --input-search-focus-border-bottom: none;\n --input-search-font: normal 16px var(--theme-font);\n\n display: flex;\n justify-content: space-between;\n align-items: center;\n\n align-self: center;\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-on-primary);\n border-radius: 999em;\n padding: 0 var(--spacing-medium);\n }\n\n [search] > * {\n align-self: center;\n }\n\n ox-input-search {\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-on-primary);\n border-radius: var(--md-sys-shape-corner-full);\n }\n\n @media screen and (max-width: 460px) {\n [closable][historyback] {\n display: block;\n }\n\n [closable][close] {\n display: none;\n }\n }\n `\n ]\n\n /**\n * A boolean property that determines whether a backdrop should be displayed behind the overlay.\n * Backdrop provides a semi-transparent background that covers the entire screen when the overlay is open.\n */\n @property({ type: Boolean }) backdrop?: boolean = false\n\n /**\n * A string property that specifies the direction in which the overlay should appear.\n * Possible values are: 'up', 'down', 'left', or 'right'.\n */\n @property({ type: String }) direction?: 'up' | 'down' | 'left' | 'right'\n\n /**\n * A string property that reflects the hovering state of the overlay.\n * Possible values are: 'center', 'edge', or 'next'.\n */\n @property({ type: String, reflect: true }) hovering?: 'center' | 'edge' | 'next'\n\n /**\n * A string property that specifies the size of the overlay.\n * Possible values are: 'small', 'medium', 'large', 'full', or 'fit' (as tall as its content).\n */\n @property({ type: String }) size?: 'small' | 'medium' | 'large' | 'full' | 'fit'\n\n /**\n * A string property that represents the name of the overlay.\n * This can be used for identification or other purposes.\n */\n @property({ type: String }) name?: string\n\n /**\n * A string property that sets the title of the overlay.\n * The title is typically displayed in the header of the overlay.\n */\n @property({ type: String }) title: string = ''\n\n /**\n * A boolean property that determines whether the overlay can be closed by the user.\n * If set to true, a close button will be displayed in the header.\n */\n @property({ type: Boolean }) closable?: boolean = false\n\n /**\n * An object property that can hold custom properties for the template of the overlay.\n * These properties can be used to customize the template's behavior.\n */\n @property({ type: Object }) templateProperties: any\n\n /**\n * An object property that can hold information related to help or assistance for the overlay.\n * This information may be used to provide additional guidance to users.\n */\n @property({ type: Object }) help: any\n\n /**\n * A boolean property that determines whether the overlay is considered historical.\n * Historical overlays may have specific behavior or interactions, such as navigating back in history.\n */\n /**\n * ESC 로 바로 닫아도 되나.\n *\n * 이 속성이 **없었다.** `openPopup({ escapable: true })` 로 줘도 부품까지 오지 않았고, 값은\n * 브라우저 이력 상태에만 담겨 바탕 클릭 판정에만 쓰였다. 그래서 이 값을 참으로 준 팝업도 ESC\n * 로는 닫히지 않았다.\n *\n * 기본값은 거짓이다 — 잃을 것이 있는 팝업이 실수로 닫히지 않게. 거짓이어도 ESC 는 듣는다.\n * 닫을지 물어본다(`onEscape`).\n */\n @property({ type: Boolean }) escapable?: boolean = false\n\n @property({ type: Boolean }) historical?: boolean = false\n\n /**\n * A boolean property that determines whether the overlay can be moved by dragging.\n * If set to true, the overlay can be repositioned by dragging its header.\n */\n @property({ type: Boolean }) movable?: boolean = false\n\n /**\n * An object property that can hold information related to a search feature within the overlay.\n * It can include properties like 'value', 'handler', and 'placeholder'.\n */\n @property({ type: Object }) search?: {\n value?: string\n handler?: (instance: any, value: string) => void\n placeholder?: string\n }\n\n /**\n * An object property that can hold information related to a filter feature within the overlay.\n * It can include a 'handler' function for filtering content.\n */\n @property({ type: Object }) filter?: { handler?: (instance: any) => void }\n\n /**\n * A numeric property that specifies the z-index of the overlay.\n * The z-index determines the stacking order of the overlay in relation to other elements on the page.\n */\n @property({ type: Number, attribute: 'z-index' }) zIndex?: number\n\n private dragStart?: { x: number; y: number }\n private dragEndHandler = this.onDragEnd.bind(this) as EventListener\n private dragMoveHandler = this.onDragMove.bind(this) as EventListener\n\n @query('[overlayed]') overlayed!: HTMLDivElement\n @query('[content]') content!: HTMLDivElement\n\n render() {\n const direction = this.hovering == 'center' ? undefined : this.direction\n\n const { value = '', handler: searchHandler, placeholder = '', autofocus = true } = this.search || ({} as any)\n const { handler: filterHandler } = this.filter || ({} as any)\n\n const searchable = typeof searchHandler == 'function'\n const filterable = typeof filterHandler == 'function'\n\n return html`\n ${Boolean(this.backdrop)\n ? html`\n <div\n id=\"backdrop\"\n ?hidden=${!this.backdrop}\n @click=${(e: Event) => this.onClose(e, true /* escape */)}\n ></div>\n `\n : html``}\n\n <div\n overlayed\n hovering=${this.hovering || 'center'}\n direction=${ifDefined(direction)}\n size=${this.size || 'medium'}\n @close-overlay=${(e: Event) => {\n e.stopPropagation()\n this.onClose(e, false, (e as CustomEvent).detail)\n }}\n @transitionstart=${(e: Event) => {\n /* to hide scrollbar during transition */\n ;(e.target as HTMLElement).removeAttribute('settled')\n }}\n @transitionend=${(e: Event) => {\n ;(e.target as HTMLElement).setAttribute('settled', '')\n }}\n @click=${(e: MouseEvent) => {\n if (this.backdrop && e.target === this.content) {\n this.onClose(e, true /* escape */)\n }\n }}\n >\n <div\n header\n @mousedown=${this.onDragStart.bind(this)}\n @touchstart=${this.onDragStart.bind(this)}\n draggable=\"false\"\n >\n <md-icon\n role=\"button\"\n tabindex=${this.closable ? 0 : -1}\n @click=${(e: Event) => this.onClose(e)}\n @keydown=${(e: KeyboardEvent) => this.onActivateKey(e, () => this.onClose(e))}\n ?closable=${this.closable}\n historyback\n >arrow_back</md-icon\n >\n ${this.movable ? html`<md-icon>drag_indicator</md-icon>` : html``}\n <slot name=\"header\">\n ${this.title || this.closable\n ? html`\n <h1>\n ${this.title || ''} ${this.help\n ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>`\n : html``}\n </h1>\n `\n : html``}\n ${searchable || filterable\n ? html`\n <div search>\n ${searchable\n ? html` <ox-input-search\n .placeholder=${placeholder}\n .value=${value || ''}\n ?autofocus=${autofocus}\n @change=${(e: Event) => {\n searchHandler(this.firstElementChild, (e.target as any).value)\n }}\n ></ox-input-search>`\n : html``}\n ${this.help && searchable ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>` : html``}\n ${filterable\n ? html`<md-icon\n role=\"button\"\n tabindex=\"0\"\n @click=${(e: MouseEvent) => filterHandler(this.firstElementChild)}\n @keydown=${(e: KeyboardEvent) =>\n this.onActivateKey(e, () => filterHandler(this.firstElementChild))}\n >tune</md-icon\n >`\n : html``}\n </div>\n `\n : html``}\n ${this.help && !searchable && !this.title /* help only */\n ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>`\n : html``}\n </slot>\n <md-icon\n role=\"button\"\n tabindex=${this.closable ? 0 : -1}\n title=${i18next.t('button.close', { defaultValue: 'close' })}\n @click=${(e: Event) => this.onClose(e)}\n @keydown=${(e: KeyboardEvent) => this.onActivateKey(e, () => this.onClose(e))}\n ?closable=${this.closable}\n close\n >close</md-icon\n >\n </div>\n\n <div content>\n <slot> </slot>\n </div>\n </div>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('templateProperties') && this.templateProperties) {\n var template = this.firstElementChild\n if (template) {\n for (let prop in this.templateProperties) {\n //@ts-ignore\n template[prop] = this.templateProperties[prop]\n }\n }\n }\n }\n\n firstUpdated() {\n if (this.zIndex) {\n this.style.setProperty('--z-index', String(this.zIndex))\n }\n\n requestAnimationFrame(() => {\n /* transition(animation) 효과를 위해 'opened' 속성을 변화시킨다. */\n this.overlayed?.setAttribute('opened', 'true')\n })\n }\n\n /**\n * 팝업을 연 자리. **닫히면 여기로 돌려준다.**\n *\n * 안 돌려주면 포커스가 body 로 떨어진다. 키보드로 일하는 사람은 자기 자리를 잃고,\n * 그리드에서는 팝업을 닫자마자 화살표가 안 먹는다. 대화상자의 표준 동작이다\n * (WAI-ARIA 의 dialog 패턴).\n */\n /**\n * Enter · Space 로도 눌린다.\n *\n * 머리의 표식들은 `md-icon` 이라 **키보드 초점을 받지 못한다.** 마우스로만 닫히는 팝업이 되는데,\n * 이 앱의 `openPopup` 은 기본값이 `escapable: false` 라서 ESC 로도 닫히지 않는다 — 키보드만\n * 쓰는 사람에게는 나갈 방법이 없어진다.\n *\n * 그래서 role · tabindex 를 주고 이 처리기를 단다. Space 는 기본 동작(스크롤)을 막아야 한다.\n */\n /**\n * ── ESC ─────────────────────────────────────────────────────────────────\n *\n * 이 부품은 **ESC 를 아예 듣지 않았다.** `escapable` 은 바탕을 눌렀을 때만 보던 값이라,\n * `escapable: true` 로 연 팝업도 ESC 로는 닫히지 않았다. 문서에는 기본값이 참이라고 적혀\n * 있는데 코드의 기본값은 거짓이다(`open-popup.ts`) — 그 어긋남도 여기서 드러났다.\n *\n * 기본값은 바꾸지 않는다. 팝업마다 무엇을 잃을지 다르고, 그 판단은 여는 쪽이 한다.\n * 대신 **두 갈래로 답한다.**\n *\n * escapable: true 바로 닫는다 — 여는 쪽이 그래도 된다고 말한 것이다\n * escapable: false 닫을지 묻는다 — 실수로 닫히지 않으면서, 나갈 길은 있다\n *\n * 묻는 쪽을 고른 이유: 닫는 길을 막는 것은 잃을 것을 지키는 방법이 아니라 **나갈 길을 없애는**\n * 방법이다. 키보드만 쓰는 사람에게는 그것이 유일한 길일 수 있다.\n *\n * 겹쳐 있으면 **맨 위 것만** 답한다. 둘이 함께 닫히면 뒤엣것까지 사라진다.\n */\n private onEscape = async (event: KeyboardEvent) => {\n if (event.key !== 'Escape' && event.key !== 'Esc') {\n return\n }\n\n if (!this.isTopOverlay()) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.escapable) {\n this.close()\n return\n }\n\n const leave = await OxPrompt.open({\n type: 'question',\n title: i18next.t('text.close-this-popup', { defaultValue: 'close this popup?' }),\n text: i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' }),\n confirmButton: { text: i18next.t('button.close', { defaultValue: 'close' }) },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) }\n })\n\n if (leave) {\n this.close()\n }\n }\n\n /** 겹친 팝업 중 맨 위인가 — 나중에 붙은 것이 위다. */\n private isTopOverlay(): boolean {\n const root = this.getRootNode() as Document | ShadowRoot\n const all = Array.from(root.querySelectorAll('ox-floating-overlay'))\n\n return all.length === 0 || all[all.length - 1] === this\n }\n\n private onActivateKey(event: KeyboardEvent, run: () => void) {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n run()\n }\n\n private opener?: HTMLElement\n\n connectedCallback(): void {\n super.connectedCallback()\n\n /*\n * ESC 는 **문서에서** 듣는다. 초점이 팝업 안에 없을 수도 있는데(연 직후, 또는 바탕을 눌러\n * 초점이 빠졌을 때) 그때도 나갈 수 있어야 한다.\n */\n document.addEventListener('keydown', this.onEscape)\n\n /*\n * 그림자 안에 있는 요소도 찾아 들어간다 — document.activeElement 는 그 요소를 품은\n * 호스트까지만 알려 준다. 그리드의 칸이 그림자 두 겹 안에 있다.\n */\n let active = document.activeElement as HTMLElement | null\n\n while (active?.shadowRoot?.activeElement) {\n active = active.shadowRoot.activeElement as HTMLElement\n }\n\n /* 자기 자신이나 자기 안의 것은 기억하지 않는다 — 돌아갈 자리가 아니다. */\n this.opener = active && !this.contains(active) ? active : undefined\n\n this.movable = this.movable && !isHandheldDevice()\n\n if (this.movable) {\n document.addEventListener('mouseup', this.dragEndHandler)\n document.addEventListener('touchend', this.dragEndHandler)\n document.addEventListener('touchcancel', this.dragEndHandler)\n document.addEventListener('mousemove', this.dragMoveHandler)\n document.addEventListener('touchmove', this.dragMoveHandler)\n }\n }\n\n disconnectedCallback() {\n document.removeEventListener('keydown', this.onEscape)\n\n document.dispatchEvent(\n new CustomEvent('overlay-closed', {\n detail: this.name\n })\n )\n\n /*\n * 열어 준 자리로 돌려준다.\n *\n * **사라졌으면 조용히 넘어간다** — 줄이 다시 그려졌거나 목록이 바뀌었으면 그 요소는 이미\n * 문서에 없다. 없는 곳에 포커스를 주려다 오류를 내면 팝업 닫기가 통째로 멈춘다.\n *\n * 다음 프레임에 준다. 지금 주면 아직 이 오버레이가 떼어지는 중이라 브라우저가 다시\n * 가져간다.\n */\n const opener = this.opener\n\n this.opener = undefined\n\n if (opener?.isConnected) {\n requestAnimationFrame(() => {\n try {\n opener.focus({ preventScroll: true })\n } catch (e) {\n /* 포커스를 못 받는 요소였다. 팝업 닫기를 막을 일은 아니다. */\n }\n })\n }\n\n if (this.movable) {\n document.removeEventListener('mouseup', this.dragEndHandler!)\n document.removeEventListener('touchend', this.dragEndHandler!)\n document.removeEventListener('touchcancel', this.dragEndHandler!)\n document.removeEventListener('mousemove', this.dragMoveHandler!)\n document.removeEventListener('touchmove', this.dragMoveHandler!)\n }\n\n super.disconnectedCallback()\n }\n\n onDragStart(e: Event) {\n if (!this.movable) {\n return\n }\n\n const point = getPoint(e)\n\n if (point) {\n this.dragStart = point\n e.stopPropagation()\n return false\n }\n }\n\n onDragMove(e: Event) {\n if (!this.movable || !this.dragStart) {\n return false\n }\n\n const point = getPoint(e)\n\n if (!point) {\n return false\n }\n\n e.stopPropagation()\n e.preventDefault()\n\n const dragStart = point\n var { x, y } = point\n\n x -= this.dragStart.x\n y -= this.dragStart.y\n\n this.dragStart = dragStart\n\n const overlayed = this.overlayed\n\n var boundingRect = overlayed.getBoundingClientRect()\n\n overlayed.style.left =\n Math.min(document.body.offsetWidth - 40, Math.max(40 - overlayed.offsetWidth, boundingRect.left + x)) + 'px'\n overlayed.style.top = Math.min(document.body.offsetHeight - 40, Math.max(0, boundingRect.top + y)) + 'px'\n\n overlayed.style.transform = 'initial'\n\n return false\n }\n\n onDragEnd(e: Event) {\n if (this.movable && this.dragStart) {\n e.stopPropagation()\n e.preventDefault()\n\n delete this.dragStart\n }\n }\n\n /**\n * A method that closes the overlay by removing it from its parent node in the DOM.\n * When called, this method removes the overlay element, effectively hiding it from the user interface.\n */\n close() {\n this.parentNode?.removeChild(this)\n }\n\n onClose(e: Event, escape?: boolean, request?: { result: unknown }) {\n e.stopPropagation()\n /* 현재 overlay state를 확인해서, 자신이 포함하고 있는 템플릿인 경우에 history.back() 한다. */\n\n if (this.historical) {\n const detail = { name: this.name, accepted: false }\n const close = new CustomEvent('close-overlay', { detail, bubbles: true, composed: true, cancelable: true })\n if (escape && !history.state?.overlay?.escapable) return true\n this.dispatchEvent(close)\n if (close.defaultPrevented) {\n if (detail.accepted) this.recordResult(request)\n return\n }\n var state = history.state\n var overlay = (state || {}).overlay\n\n if (!overlay || overlay.name !== this.name) {\n return\n }\n\n /* Backdrop click 경우는 escape 시도라고 정의한다. overlay 속성이 escapable이 아닌 경우에는 동작하지 않는다. */\n if (escape && !overlay.escapable) {\n return true\n }\n\n /* A second close in the same tick would see the same state and go back one page too far. */\n if (!claimHistoryBack(overlay.name)) {\n return\n }\n\n this.recordResult(request)\n history.back()\n } else {\n this.recordResult(request)\n this.close()\n }\n }\n\n /*\n * A value from the content (`closePopup(element, value)`) is recorded only once the overlay is really\n * going to close, and nothing settles here - the result settles when the overlay leaves the document,\n * where every way of closing ends. If another request recorded first, this value is dropped.\n */\n private recordResult(request?: { result: unknown }) {\n if (request && 'result' in request) {\n recordPopupResult(this.name, request.result)\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-floating-overlay.js","sourceRoot":"","sources":["../../src/ox-floating-overlay.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,yBAAyB;AACzB,6CAA6C;AAE7C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,KAAK,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEvE,SAAS,QAAQ,CAAC,CAAQ;IACxB,IAAK,CAAgB,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,CAAC,EAAG,CAAgB,CAAC,OAAO;YAC5B,CAAC,EAAG,CAAgB,CAAC,OAAO;SAC7B,CAAA;IACH,CAAC;SAAM,IAAK,CAAgB,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,KAAK,GAAI,CAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAC1C,OAAO;YACL,CAAC,EAAE,KAAK,CAAC,OAAO;YAChB,CAAC,EAAE,KAAK,CAAC,OAAO;SACjB,CAAA;IACH,CAAC;SAAM,CAAC;QACN,OAAM;IACR,CAAC;AACH,CAAC;AAED;;;;GAIG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,UAAU;IAA1C;;QA4VL;;;WAGG;QAC0B,aAAQ,GAAa,KAAK,CAAA;QA0BvD;;;WAGG;QACyB,UAAK,GAAW,EAAE,CAAA;QAE9C;;;WAGG;QAC0B,aAAQ,GAAa,KAAK,CAAA;QAcvD;;;WAGG;QACH;;;;;;;;;WASG;QAC0B,cAAS,GAAa,KAAK,CAAA;QAE3B,eAAU,GAAa,KAAK,CAAA;QAEzD;;;WAGG;QAC0B,YAAO,GAAa,KAAK,CAAA;QAyB9C,mBAAc,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAkB,CAAA;QAC3D,oBAAe,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAkB,CAAA;QAkJrE;;;;;;WAMG;QACH;;;;;;;;WAQG;QACH;;;;;;;;;;;;;;;;;WAiBG;QACK,aAAQ,GAAG,KAAK,EAAE,KAAoB,EAAE,EAAE;YAChD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClD,OAAM;YACR,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;gBACzB,OAAM;YACR,CAAC;YAED,KAAK,CAAC,cAAc,EAAE,CAAA;YACtB,KAAK,CAAC,eAAe,EAAE,CAAA;YAEvB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC,KAAK,EAAE,CAAA;gBACZ,OAAM;YACR,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;gBAChC,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,uBAAuB,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;gBAChF,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,0BAA0B,EAAE,EAAE,YAAY,EAAE,6BAA6B,EAAE,CAAC;gBAC5F,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE;gBAC7E,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAAE;aAC/E,CAAC,CAAA;YAEF,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,KAAK,EAAE,CAAA;YACd,CAAC;QACH,CAAC,CAAA;IAoNH,CAAC;aAr2BQ,WAAM,GAAG;QACd,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6LF;QACD,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAwJF;KACF,AAzVY,CAyVZ;IA6GD,MAAM;QACJ,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAA;QAExE,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,GAAG,EAAE,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,IAAK,EAAU,CAAA;QAC7G,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,MAAM,IAAK,EAAU,CAAA;QAE7D,MAAM,UAAU,GAAG,OAAO,aAAa,IAAI,UAAU,CAAA;QACrD,MAAM,UAAU,GAAG,OAAO,aAAa,IAAI,UAAU,CAAA;QAErD,OAAO,IAAI,CAAA;QACP,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;YACtB,CAAC,CAAC,IAAI,CAAA;;;wBAGU,CAAC,IAAI,CAAC,QAAQ;uBACf,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC;;WAE5D;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;;;;mBAIG,IAAI,CAAC,QAAQ,IAAI,QAAQ;oBACxB,SAAS,CAAC,SAAS,CAAC;eACzB,IAAI,CAAC,IAAI,IAAI,QAAQ;yBACX,CAAC,CAAQ,EAAE,EAAE;YAC5B,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAG,CAAiB,CAAC,MAAM,CAAC,CAAA;QACnD,CAAC;2BACkB,CAAC,CAAQ,EAAE,EAAE;YAC9B,yCAAyC;YACzC,CAAC;YAAC,CAAC,CAAC,MAAsB,CAAC,eAAe,CAAC,SAAS,CAAC,CAAA;QACvD,CAAC;yBACgB,CAAC,CAAQ,EAAE,EAAE;YAC5B,CAAC;YAAC,CAAC,CAAC,MAAsB,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;QACxD,CAAC;iBACQ,CAAC,CAAa,EAAE,EAAE;YACzB,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC/C,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;YACpC,CAAC;QACH,CAAC;;;;uBAIc,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;wBAC1B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;uBAK5B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;qBACxB,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;uBAC3B,CAAC,CAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;wBACjE,IAAI,CAAC,QAAQ;;;;YAIzB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,mCAAmC,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;;cAE7D,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ;YAC3B,CAAC,CAAC,IAAI,CAAA;;sBAEE,IAAI,CAAC,KAAK,IAAI,EAAE,SAAS,IAAI,CAAC,IAAI;gBAClC,CAAC,CAAC,IAAI,CAAA,wBAAwB,IAAI,CAAC,IAAI,kBAAkB;gBACzD,CAAC,CAAC,IAAI,CAAA,EAAE;;iBAEb;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;cACR,UAAU,IAAI,UAAU;YACxB,CAAC,CAAC,IAAI,CAAA;;sBAEE,UAAU;gBACV,CAAC,CAAC,IAAI,CAAA;yCACa,WAAW;mCACjB,KAAK,IAAI,EAAE;uCACP,SAAS;oCACZ,CAAC,CAAQ,EAAE,EAAE;oBACrB,aAAa,CAAC,IAAI,CAAC,iBAAiB,EAAG,CAAC,CAAC,MAAc,CAAC,KAAK,CAAC,CAAA;gBAChE,CAAC;4CACiB;gBACtB,CAAC,CAAC,IAAI,CAAA,EAAE;sBACR,IAAI,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA,wBAAwB,IAAI,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;sBAC1F,UAAU;gBACV,CAAC,CAAC,IAAI,CAAA;;;mCAGO,CAAC,CAAa,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC;qCACtD,CAAC,CAAgB,EAAE,EAAE,CAC9B,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;;0BAEpE;gBACJ,CAAC,CAAC,IAAI,CAAA,EAAE;;iBAEb;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;cACR,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe;YACvD,CAAC,CAAC,IAAI,CAAA,wBAAwB,IAAI,CAAC,IAAI,kBAAkB;YACzD,CAAC,CAAC,IAAI,CAAA,EAAE;;;;uBAIC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACzB,OAAO,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;qBACnD,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;uBAC3B,CAAC,CAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;wBACjE,IAAI,CAAC,QAAQ;;;;;;;;;;KAUhC,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAA6B;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACjE,IAAI,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAA;YACrC,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBACzC,YAAY;oBACZ,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,YAAY;QACV,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QAC1D,CAAC;QAED,qBAAqB,CAAC,GAAG,EAAE;YACzB,sDAAsD;YACtD,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;IACJ,CAAC;IAkED,oCAAoC;IAC5B,YAAY;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAA2B,CAAA;QACxD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAC,CAAA;QAEpE,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,CAAA;IACzD,CAAC;IAEO,aAAa,CAAC,KAAoB,EAAE,GAAe;QACzD,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;YAC/C,OAAM;QACR,CAAC;QAED,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,KAAK,CAAC,eAAe,EAAE,CAAA;QACvB,GAAG,EAAE,CAAA;IACP,CAAC;IAID,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB;;;WAGG;QACH,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEnD;;;WAGG;QACH,IAAI,MAAM,GAAG,QAAQ,CAAC,aAAmC,CAAA;QAEzD,OAAO,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;YACzC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,aAA4B,CAAA;QACzD,CAAC;QAED,8CAA8C;QAC9C,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;QAEnE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAElD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;YACzD,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;YAC1D,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;YAC7D,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAA;YAC5D,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAe,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;IAED,oBAAoB;QAClB,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEtD,QAAQ,CAAC,aAAa,CACpB,IAAI,WAAW,CAAC,gBAAgB,EAAE;YAChC,MAAM,EAAE,IAAI,CAAC,IAAI;SAClB,CAAC,CACH,CAAA;QAED;;;;;;;;WAQG;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAE1B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAA;QAEvB,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;YACxB,qBAAqB,CAAC,GAAG,EAAE;gBACzB,IAAI,CAAC;oBACH,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;gBACvC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,uCAAuC;gBACzC,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,cAAe,CAAC,CAAA;YAC7D,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,cAAe,CAAC,CAAA;YAC9D,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,cAAe,CAAC,CAAA;YACjE,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAgB,CAAC,CAAA;YAChE,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,eAAgB,CAAC,CAAA;QAClE,CAAC;QAED,KAAK,CAAC,oBAAoB,EAAE,CAAA;IAC9B,CAAC;IAED,WAAW,CAAC,CAAQ;QAClB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAEzB,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;YACtB,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,UAAU,CAAC,CAAQ;QACjB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;QAEzB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAA;QACd,CAAC;QAED,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,CAAC,CAAC,cAAc,EAAE,CAAA;QAElB,MAAM,SAAS,GAAG,KAAK,CAAA;QACvB,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,CAAA;QAEpB,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;QACrB,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;QAErB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;QAEhC,IAAI,YAAY,GAAG,SAAS,CAAC,qBAAqB,EAAE,CAAA;QAEpD,SAAS,CAAC,KAAK,CAAC,IAAI;YAClB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;QAC9G,SAAS,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;QAEzG,SAAS,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAA;QAErC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,SAAS,CAAC,CAAQ;QAChB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,CAAC,CAAC,cAAc,EAAE,CAAA;YAElB,OAAO,IAAI,CAAC,SAAS,CAAA;QACvB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,OAAO,CAAC,CAAQ,EAAE,MAAgB,EAAE,OAA6B;QAC/D,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,qEAAqE;QAErE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;YACnD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,eAAe,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;YAC3G,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS;gBAAE,OAAO,IAAI,CAAA;YAC7D,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YACzB,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,IAAI,MAAM,CAAC,QAAQ;oBAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;gBAC/C,OAAM;YACR,CAAC;YACD,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;YACzB,IAAI,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAA;YAEnC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAM;YACR,CAAC;YAED,mFAAmF;YACnF,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACjC,OAAO,IAAI,CAAA;YACb,CAAC;YAED,4FAA4F;YAC5F,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,OAAM;YACR,CAAC;YAED,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;YAC1B,OAAO,CAAC,IAAI,EAAE,CAAA;QAChB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;YAC1B,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,YAAY,CAAC,OAA6B;QAChD,IAAI,OAAO,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;YACnC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;;AArgB4B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;mDAA2B;AAM3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oDAA6C;AAM7B;IAA1C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;mDAAsC;AAMpD;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAqD;AAMpD;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAc;AAMb;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDAAmB;AAMjB;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;mDAA2B;AAM3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;6DAAwB;AAMvB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAU;AAgBR;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oDAA4B;AAE3B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qDAA6B;AAM5B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;kDAA0B;AAM1B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iDAI1B;AAM2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;iDAA+C;AAMxB;IAAjD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;iDAAgB;AAM3C;IAArB,KAAK,CAAC,aAAa,CAAC;oDAA2B;AAC5B;IAAnB,KAAK,CAAC,WAAW,CAAC;kDAAyB;AArcjC,iBAAiB;IAD7B,aAAa,CAAC,qBAAqB,CAAC;GACxB,iBAAiB,CAs2B7B","sourcesContent":["import '@material/web/icon/icon.js'\n// 순환 참조가 되어서 일단 코멘트 처리함.\n// import '@operato/input/ox-input-search.js'\n\nimport { css, html, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { OxPrompt } from './ox-prompt.js'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isHandheldDevice } from '@operato/utils'\n\nimport { claimHistoryBack, recordPopupResult } from './popup-result.js'\n\nfunction getPoint(e: Event): { x: number; y: number } | undefined {\n if ((e as MouseEvent).button == 0) {\n return {\n x: (e as MouseEvent).clientX,\n y: (e as MouseEvent).clientY\n }\n } else if ((e as TouchEvent).touches?.length == 1) {\n const touch = (e as TouchEvent).touches[0]\n return {\n x: touch.clientX,\n y: touch.clientY\n }\n } else {\n return\n }\n}\n\n/**\n * Custom element for creating floating overlays.\n * These overlays can have various properties like direction, size, title, and more.\n * They are often used for modal dialogs, pop-ups, and similar UI elements.\n */\n@customElement('ox-floating-overlay')\nexport class OxFloatingOverlay extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n /* for layout style */\n :host {\n position: relative;\n z-index: var(--z-index, 10);\n /*\n * ── 그림자는 층으로 쌓는다 ──────────────────────────────────────────\n * 전에는 2px 3px 10px 5px 였다 — 오른쪽 아래로 치우친 데다 5px 퍼짐이 있어서 상자 네 변에\n * 회색 테를 두른 것처럼 보였다. 떠 있는 느낌이 아니라 덧그린 느낌이다.\n *\n * 가까운 층 하나로 경계를 세우고, 먼 층 하나로 높이를 만든다. 먼 층은 위로 퍼지지 않게\n * 음수 spread 를 준다 — 빛이 위에서 온다는 그 규칙만 지켜도 상자가 뜬다.\n */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 16px 40px -12px rgba(0, 0, 0, 0.28);\n }\n\n :host([hovering='edge']) {\n /* edge hovering 인 경우에는 상위 relative position 크기와 위치를 반영한다. */\n position: initial;\n }\n\n #backdrop {\n position: fixed;\n left: 0;\n top: 0;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n\n background-color: var(--md-sys-color-shadow, #000);\n opacity: 0.4;\n }\n\n [overlayed] {\n position: absolute;\n\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n [overlayed][hovering='center'] {\n position: fixed;\n\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n\n opacity: 0;\n /*\n * ── 테두리는 실선 한 올, 모서리는 둥글게 ────────────────────────────\n * 2px outline 이었다. 화면에서 가장 굵고 가장 진한 선이 상자의 테두리여서, 안에 든 내용보다\n * 상자가 먼저 보였다. 경계는 한 올로 충분하다 — 나머지는 그림자가 맡는다.\n *\n * 모서리도 각이었다. 이 제품의 카드·표는 모두 둥글다(10~14px). 팝업만 각이면 그 하나가\n * 딴 세대의 것으로 보인다.\n *\n * ── --popup-radius 는 **카드의 모서리**다. 여기가 그 임자다 ─────────────\n * 이 값이 팝업 안 컨트롤의 모서리를 함께 정한다 — 모서리는 담는 면을 따른다(동심 모서리).\n * 그 짝은 --popup-control-radius 이고 CommonPopupStyles 가 선언한다. 카드를 각지게\n * 하려면 두 값을 **함께** 내려라. 한쪽만 바꾸면 둥근 틀에 각진 패널이 박힌다.\n */\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: var(--popup-radius, 16px);\n }\n\n [overlayed][hovering='center'][opened] {\n opacity: 1;\n transition: opacity 0.3s ease-in;\n background-color: var(--md-sys-color-surface-container-lowest);\n }\n\n [hovering='center'] {\n width: var(--overlay-center-normal-width, 60%);\n height: var(--overlay-center-normal-height, 60%);\n }\n\n [hovering='center'][size='small'] {\n width: var(--overlay-center-small-width, 40%);\n height: var(--overlay-center-small-height, 40%);\n }\n\n [hovering='center'][size='large'] {\n width: var(--overlay-center-large-width, 100%);\n height: var(--overlay-center-large-height, 100%);\n }\n\n [hovering='center'][size='full'] {\n width: var(--overlay-center-full-width, 100%);\n height: var(--overlay-center-full-height, 100%);\n }\n\n /*\n * A form of a few fields stands at its own height. The other sizes are fractions of the screen, so\n * five fields in a medium popup left half the card empty under them. Bounded by the screen; past\n * that the content scrolls in its own body.\n */\n [hovering='center'][size='fit'] {\n width: min(var(--overlay-center-fit-width, 480px), calc(100vw - 32px));\n height: auto;\n max-height: calc(100vh - 32px);\n max-height: calc(100dvh - 32px);\n }\n\n [header] {\n --help-icon-color: var(--md-sys-color-on-primary-container);\n --help-icon-hover-color: var(--md-sys-color-on-primary-container);\n\n pointer-events: initial;\n }\n\n [content] {\n flex: 1;\n overflow: hidden;\n }\n\n ::slotted(*) {\n box-sizing: border-box;\n pointer-events: initial;\n }\n\n [hovering='center'] [content] ::slotted(*) {\n width: 100%;\n height: 100%;\n }\n [direction='up'],\n [direction='down'] {\n width: 100%;\n\n max-height: 0;\n transition: max-height 0.7s ease-in;\n }\n [direction='up'] {\n bottom: 0;\n }\n [direction='down'] {\n top: 0;\n }\n\n [direction='up'][opened],\n [direction='down'][opened] {\n max-height: 100vh;\n max-height: 100dvh;\n }\n\n [settled][direction='down'] [content],\n [settled][direction='up'] [content] {\n overflow-y: auto;\n }\n\n [direction='left'],\n [direction='right'] {\n height: 100%;\n\n max-width: 0;\n transition: max-width 0.5s ease-in;\n }\n [direction='left'] {\n right: 0;\n }\n [direction='right'] {\n left: 0;\n }\n\n [direction='left'][opened],\n [direction='right'][opened] {\n max-width: 100vw;\n }\n\n [settled][direction='left'] [content],\n [settled][direction='right'] [content] {\n overflow-x: auto;\n }\n\n @media screen and (max-width: 460px) {\n [direction='up'],\n [direction='down'] {\n max-height: 100vh;\n max-height: 100dvh;\n }\n\n [direction='left'],\n [direction='right'] {\n max-width: 100vw;\n }\n }\n `,\n css`\n /*\n * for header style\n *\n * primary 는 어두운 표면 위에 놓는 강조색이라 큰 면을 채우면 다크에서 밝은 띠가 된다\n * (실제로 팝업 제목줄이 탄색 블록으로 보였다). 제목줄은 표면이므로 container 역할을 쓴다.\n * 앱이 조정하려면 --popup-header-background / --popup-header-color 를 지정한다.\n */\n [header] {\n display: flex;\n flex-direction: row;\n align-items: center;\n /*\n * 머리는 슬래브가 아니다. 채움과 아래 실선을 둘 다 쓰고 있었고, 채움이 한 단 진해서 그 띠가\n * 안에 든 내용보다 무거웠다. 한 단 낮춘다 — 선은 남긴다(목록이 올라올 때 그 선이 머리를 말한다).\n */\n background-color: var(--popup-header-background, var(--md-sys-color-surface-container-low));\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n color: var(--popup-header-color, var(--md-sys-color-on-surface));\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n slot[name='header'] {\n flex: 1;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n text-transform: capitalize;\n }\n\n [name='header']::slotted(*) {\n margin: 0 auto;\n }\n\n [name='header'] > h1 {\n font-size: var(--md-sys-typescale-title-medium-size, 1rem);\n margin-block: 0.4rem;\n }\n\n [historyback] {\n margin-left: var(--spacing-medium);\n margin-right: auto;\n }\n\n [close] {\n margin-left: auto;\n margin-right: var(--spacing-medium);\n }\n\n [historyback],\n [close] {\n display: none;\n }\n\n [closable][close] {\n display: block;\n cursor: pointer;\n }\n\n /*\n * ── 머리의 아이콘은 **꾸밈이 아니라 곁것**이다 ────────────────────────\n *\n * 닫기와 손잡이가 제목과 같은 잉크에 24px 였다. 제목이 16px 이니 **곁것이 내용보다 굵고\n * 컸다** — 팝업을 열면 눈이 먼저 ✕ 로 갔다.\n *\n * 크기는 이 제품의 아이콘 눈금(18~19px)에 맞추고, 색은 한 단 흐리게 두었다가 마우스를\n * 올릴 때만 짙어진다. 누를 자리는 여백으로 넓혀 둔다 — 아이콘이 작아도 28px 안에서 눌린다.\n *\n * 손잡이(drag_indicator)는 그중 **가장 흐리다.** 그것은 동작이 아니라 「여기를 잡으면\n * 움직인다」는 표시이고, 잡으려는 사람은 이미 그 자리를 안다.\n */\n /*\n * 앱이 --popup-header-background 를 primary 같은 짙은 색으로 바꾸면 아이콘도 함께 밝아져야 한다.\n * --popup-header-icon-color 하나로 닫기/뒤로/손잡이 색을 맞추고, 호버 면은 --popup-header-icon-hover-background.\n */\n [header] md-icon {\n --md-icon-size: 18px;\n\n padding: 5px;\n border-radius: 999em;\n color: var(--popup-header-icon-color, var(--md-sys-color-outline));\n transition:\n color 0.12s ease-out,\n background-color 0.12s ease-out;\n }\n\n [header] md-icon[historyback]:hover,\n [header] md-icon[close]:hover {\n color: var(--popup-header-icon-hover-color, var(--md-sys-color-on-surface));\n background-color: var(--popup-header-icon-hover-background, var(--md-sys-color-surface-container-high));\n }\n\n /* 손잡이는 눌리는 것이 아니라 잡히는 것이다. 면을 주지 않고 색만 한 단 올린다. */\n [header] md-icon:not([close]):not([historyback]) {\n color: var(--popup-header-icon-color, var(--md-sys-color-outline-variant));\n opacity: var(--popup-header-handle-opacity, 1);\n cursor: grab;\n }\n\n [header] md-icon:not([close]):not([historyback]):hover {\n color: var(--popup-header-icon-color, var(--md-sys-color-outline));\n opacity: 1;\n }\n\n [search] ox-help-icon {\n color: var(--md-sys-color-on-secondary-container);\n }\n\n [search] {\n --help-icon-color: var(--md-sys-color-primary);\n --help-icon-hover-color: var(--md-sys-color-primary);\n --help-icon-opacity: 0.2;\n --help-icon-size: 20px;\n\n --md-icon-size: 20px;\n\n --input-search-padding: var(--spacing-medium);\n --input-search-focus-border-bottom: none;\n --input-search-font: normal 16px var(--theme-font);\n\n display: flex;\n justify-content: space-between;\n align-items: center;\n\n align-self: center;\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-on-primary);\n border-radius: 999em;\n padding: 0 var(--spacing-medium);\n }\n\n [search] > * {\n align-self: center;\n }\n\n ox-input-search {\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-on-primary);\n border-radius: var(--md-sys-shape-corner-full);\n }\n\n @media screen and (max-width: 460px) {\n [closable][historyback] {\n display: block;\n }\n\n [closable][close] {\n display: none;\n }\n }\n `\n ]\n\n /**\n * A boolean property that determines whether a backdrop should be displayed behind the overlay.\n * Backdrop provides a semi-transparent background that covers the entire screen when the overlay is open.\n */\n @property({ type: Boolean }) backdrop?: boolean = false\n\n /**\n * A string property that specifies the direction in which the overlay should appear.\n * Possible values are: 'up', 'down', 'left', or 'right'.\n */\n @property({ type: String }) direction?: 'up' | 'down' | 'left' | 'right'\n\n /**\n * A string property that reflects the hovering state of the overlay.\n * Possible values are: 'center', 'edge', or 'next'.\n */\n @property({ type: String, reflect: true }) hovering?: 'center' | 'edge' | 'next'\n\n /**\n * A string property that specifies the size of the overlay.\n * Possible values are: 'small', 'medium', 'large', 'full', or 'fit' (as tall as its content).\n */\n @property({ type: String }) size?: 'small' | 'medium' | 'large' | 'full' | 'fit'\n\n /**\n * A string property that represents the name of the overlay.\n * This can be used for identification or other purposes.\n */\n @property({ type: String }) name?: string\n\n /**\n * A string property that sets the title of the overlay.\n * The title is typically displayed in the header of the overlay.\n */\n @property({ type: String }) title: string = ''\n\n /**\n * A boolean property that determines whether the overlay can be closed by the user.\n * If set to true, a close button will be displayed in the header.\n */\n @property({ type: Boolean }) closable?: boolean = false\n\n /**\n * An object property that can hold custom properties for the template of the overlay.\n * These properties can be used to customize the template's behavior.\n */\n @property({ type: Object }) templateProperties: any\n\n /**\n * An object property that can hold information related to help or assistance for the overlay.\n * This information may be used to provide additional guidance to users.\n */\n @property({ type: Object }) help: any\n\n /**\n * A boolean property that determines whether the overlay is considered historical.\n * Historical overlays may have specific behavior or interactions, such as navigating back in history.\n */\n /**\n * ESC 로 바로 닫아도 되나.\n *\n * 이 속성이 **없었다.** `openPopup({ escapable: true })` 로 줘도 부품까지 오지 않았고, 값은\n * 브라우저 이력 상태에만 담겨 바탕 클릭 판정에만 쓰였다. 그래서 이 값을 참으로 준 팝업도 ESC\n * 로는 닫히지 않았다.\n *\n * 기본값은 거짓이다 — 잃을 것이 있는 팝업이 실수로 닫히지 않게. 거짓이어도 ESC 는 듣는다.\n * 닫을지 물어본다(`onEscape`).\n */\n @property({ type: Boolean }) escapable?: boolean = false\n\n @property({ type: Boolean }) historical?: boolean = false\n\n /**\n * A boolean property that determines whether the overlay can be moved by dragging.\n * If set to true, the overlay can be repositioned by dragging its header.\n */\n @property({ type: Boolean }) movable?: boolean = false\n\n /**\n * An object property that can hold information related to a search feature within the overlay.\n * It can include properties like 'value', 'handler', and 'placeholder'.\n */\n @property({ type: Object }) search?: {\n value?: string\n handler?: (instance: any, value: string) => void\n placeholder?: string\n }\n\n /**\n * An object property that can hold information related to a filter feature within the overlay.\n * It can include a 'handler' function for filtering content.\n */\n @property({ type: Object }) filter?: { handler?: (instance: any) => void }\n\n /**\n * A numeric property that specifies the z-index of the overlay.\n * The z-index determines the stacking order of the overlay in relation to other elements on the page.\n */\n @property({ type: Number, attribute: 'z-index' }) zIndex?: number\n\n private dragStart?: { x: number; y: number }\n private dragEndHandler = this.onDragEnd.bind(this) as EventListener\n private dragMoveHandler = this.onDragMove.bind(this) as EventListener\n\n @query('[overlayed]') overlayed!: HTMLDivElement\n @query('[content]') content!: HTMLDivElement\n\n render() {\n const direction = this.hovering == 'center' ? undefined : this.direction\n\n const { value = '', handler: searchHandler, placeholder = '', autofocus = true } = this.search || ({} as any)\n const { handler: filterHandler } = this.filter || ({} as any)\n\n const searchable = typeof searchHandler == 'function'\n const filterable = typeof filterHandler == 'function'\n\n return html`\n ${Boolean(this.backdrop)\n ? html`\n <div\n id=\"backdrop\"\n ?hidden=${!this.backdrop}\n @click=${(e: Event) => this.onClose(e, true /* escape */)}\n ></div>\n `\n : html``}\n\n <div\n overlayed\n hovering=${this.hovering || 'center'}\n direction=${ifDefined(direction)}\n size=${this.size || 'medium'}\n @close-overlay=${(e: Event) => {\n e.stopPropagation()\n this.onClose(e, false, (e as CustomEvent).detail)\n }}\n @transitionstart=${(e: Event) => {\n /* to hide scrollbar during transition */\n ;(e.target as HTMLElement).removeAttribute('settled')\n }}\n @transitionend=${(e: Event) => {\n ;(e.target as HTMLElement).setAttribute('settled', '')\n }}\n @click=${(e: MouseEvent) => {\n if (this.backdrop && e.target === this.content) {\n this.onClose(e, true /* escape */)\n }\n }}\n >\n <div\n header\n @mousedown=${this.onDragStart.bind(this)}\n @touchstart=${this.onDragStart.bind(this)}\n draggable=\"false\"\n >\n <md-icon\n role=\"button\"\n tabindex=${this.closable ? 0 : -1}\n @click=${(e: Event) => this.onClose(e)}\n @keydown=${(e: KeyboardEvent) => this.onActivateKey(e, () => this.onClose(e))}\n ?closable=${this.closable}\n historyback\n >arrow_back</md-icon\n >\n ${this.movable ? html`<md-icon>drag_indicator</md-icon>` : html``}\n <slot name=\"header\">\n ${this.title || this.closable\n ? html`\n <h1>\n ${this.title || ''} ${this.help\n ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>`\n : html``}\n </h1>\n `\n : html``}\n ${searchable || filterable\n ? html`\n <div search>\n ${searchable\n ? html` <ox-input-search\n .placeholder=${placeholder}\n .value=${value || ''}\n ?autofocus=${autofocus}\n @change=${(e: Event) => {\n searchHandler(this.firstElementChild, (e.target as any).value)\n }}\n ></ox-input-search>`\n : html``}\n ${this.help && searchable ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>` : html``}\n ${filterable\n ? html`<md-icon\n role=\"button\"\n tabindex=\"0\"\n @click=${(e: MouseEvent) => filterHandler(this.firstElementChild)}\n @keydown=${(e: KeyboardEvent) =>\n this.onActivateKey(e, () => filterHandler(this.firstElementChild))}\n >tune</md-icon\n >`\n : html``}\n </div>\n `\n : html``}\n ${this.help && !searchable && !this.title /* help only */\n ? html`<ox-help-icon .topic=${this.help}></ox-help-icon>`\n : html``}\n </slot>\n <md-icon\n role=\"button\"\n tabindex=${this.closable ? 0 : -1}\n title=${i18next.t('button.close', { defaultValue: 'close' })}\n @click=${(e: Event) => this.onClose(e)}\n @keydown=${(e: KeyboardEvent) => this.onActivateKey(e, () => this.onClose(e))}\n ?closable=${this.closable}\n close\n >close</md-icon\n >\n </div>\n\n <div content>\n <slot> </slot>\n </div>\n </div>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('templateProperties') && this.templateProperties) {\n var template = this.firstElementChild\n if (template) {\n for (let prop in this.templateProperties) {\n //@ts-ignore\n template[prop] = this.templateProperties[prop]\n }\n }\n }\n }\n\n firstUpdated() {\n if (this.zIndex) {\n this.style.setProperty('--z-index', String(this.zIndex))\n }\n\n requestAnimationFrame(() => {\n /* transition(animation) 효과를 위해 'opened' 속성을 변화시킨다. */\n this.overlayed?.setAttribute('opened', 'true')\n })\n }\n\n /**\n * 팝업을 연 자리. **닫히면 여기로 돌려준다.**\n *\n * 안 돌려주면 포커스가 body 로 떨어진다. 키보드로 일하는 사람은 자기 자리를 잃고,\n * 그리드에서는 팝업을 닫자마자 화살표가 안 먹는다. 대화상자의 표준 동작이다\n * (WAI-ARIA 의 dialog 패턴).\n */\n /**\n * Enter · Space 로도 눌린다.\n *\n * 머리의 표식들은 `md-icon` 이라 **키보드 초점을 받지 못한다.** 마우스로만 닫히는 팝업이 되는데,\n * 이 앱의 `openPopup` 은 기본값이 `escapable: false` 라서 ESC 로도 닫히지 않는다 — 키보드만\n * 쓰는 사람에게는 나갈 방법이 없어진다.\n *\n * 그래서 role · tabindex 를 주고 이 처리기를 단다. Space 는 기본 동작(스크롤)을 막아야 한다.\n */\n /**\n * ── ESC ─────────────────────────────────────────────────────────────────\n *\n * 이 부품은 **ESC 를 아예 듣지 않았다.** `escapable` 은 바탕을 눌렀을 때만 보던 값이라,\n * `escapable: true` 로 연 팝업도 ESC 로는 닫히지 않았다. 문서에는 기본값이 참이라고 적혀\n * 있는데 코드의 기본값은 거짓이다(`open-popup.ts`) — 그 어긋남도 여기서 드러났다.\n *\n * 기본값은 바꾸지 않는다. 팝업마다 무엇을 잃을지 다르고, 그 판단은 여는 쪽이 한다.\n * 대신 **두 갈래로 답한다.**\n *\n * escapable: true 바로 닫는다 — 여는 쪽이 그래도 된다고 말한 것이다\n * escapable: false 닫을지 묻는다 — 실수로 닫히지 않으면서, 나갈 길은 있다\n *\n * 묻는 쪽을 고른 이유: 닫는 길을 막는 것은 잃을 것을 지키는 방법이 아니라 **나갈 길을 없애는**\n * 방법이다. 키보드만 쓰는 사람에게는 그것이 유일한 길일 수 있다.\n *\n * 겹쳐 있으면 **맨 위 것만** 답한다. 둘이 함께 닫히면 뒤엣것까지 사라진다.\n */\n private onEscape = async (event: KeyboardEvent) => {\n if (event.key !== 'Escape' && event.key !== 'Esc') {\n return\n }\n\n if (!this.isTopOverlay()) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.escapable) {\n this.close()\n return\n }\n\n const leave = await OxPrompt.open({\n type: 'question',\n title: i18next.t('text.close-this-popup', { defaultValue: 'close this popup?' }),\n text: i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' }),\n confirmButton: { text: i18next.t('button.close', { defaultValue: 'close' }) },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) }\n })\n\n if (leave) {\n this.close()\n }\n }\n\n /** 겹친 팝업 중 맨 위인가 — 나중에 붙은 것이 위다. */\n private isTopOverlay(): boolean {\n const root = this.getRootNode() as Document | ShadowRoot\n const all = Array.from(root.querySelectorAll('ox-floating-overlay'))\n\n return all.length === 0 || all[all.length - 1] === this\n }\n\n private onActivateKey(event: KeyboardEvent, run: () => void) {\n if (event.key !== 'Enter' && event.key !== ' ') {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n run()\n }\n\n private opener?: HTMLElement\n\n connectedCallback(): void {\n super.connectedCallback()\n\n /*\n * ESC 는 **문서에서** 듣는다. 초점이 팝업 안에 없을 수도 있는데(연 직후, 또는 바탕을 눌러\n * 초점이 빠졌을 때) 그때도 나갈 수 있어야 한다.\n */\n document.addEventListener('keydown', this.onEscape)\n\n /*\n * 그림자 안에 있는 요소도 찾아 들어간다 — document.activeElement 는 그 요소를 품은\n * 호스트까지만 알려 준다. 그리드의 칸이 그림자 두 겹 안에 있다.\n */\n let active = document.activeElement as HTMLElement | null\n\n while (active?.shadowRoot?.activeElement) {\n active = active.shadowRoot.activeElement as HTMLElement\n }\n\n /* 자기 자신이나 자기 안의 것은 기억하지 않는다 — 돌아갈 자리가 아니다. */\n this.opener = active && !this.contains(active) ? active : undefined\n\n this.movable = this.movable && !isHandheldDevice()\n\n if (this.movable) {\n document.addEventListener('mouseup', this.dragEndHandler)\n document.addEventListener('touchend', this.dragEndHandler)\n document.addEventListener('touchcancel', this.dragEndHandler)\n document.addEventListener('mousemove', this.dragMoveHandler)\n document.addEventListener('touchmove', this.dragMoveHandler)\n }\n }\n\n disconnectedCallback() {\n document.removeEventListener('keydown', this.onEscape)\n\n document.dispatchEvent(\n new CustomEvent('overlay-closed', {\n detail: this.name\n })\n )\n\n /*\n * 열어 준 자리로 돌려준다.\n *\n * **사라졌으면 조용히 넘어간다** — 줄이 다시 그려졌거나 목록이 바뀌었으면 그 요소는 이미\n * 문서에 없다. 없는 곳에 포커스를 주려다 오류를 내면 팝업 닫기가 통째로 멈춘다.\n *\n * 다음 프레임에 준다. 지금 주면 아직 이 오버레이가 떼어지는 중이라 브라우저가 다시\n * 가져간다.\n */\n const opener = this.opener\n\n this.opener = undefined\n\n if (opener?.isConnected) {\n requestAnimationFrame(() => {\n try {\n opener.focus({ preventScroll: true })\n } catch (e) {\n /* 포커스를 못 받는 요소였다. 팝업 닫기를 막을 일은 아니다. */\n }\n })\n }\n\n if (this.movable) {\n document.removeEventListener('mouseup', this.dragEndHandler!)\n document.removeEventListener('touchend', this.dragEndHandler!)\n document.removeEventListener('touchcancel', this.dragEndHandler!)\n document.removeEventListener('mousemove', this.dragMoveHandler!)\n document.removeEventListener('touchmove', this.dragMoveHandler!)\n }\n\n super.disconnectedCallback()\n }\n\n onDragStart(e: Event) {\n if (!this.movable) {\n return\n }\n\n const point = getPoint(e)\n\n if (point) {\n this.dragStart = point\n e.stopPropagation()\n return false\n }\n }\n\n onDragMove(e: Event) {\n if (!this.movable || !this.dragStart) {\n return false\n }\n\n const point = getPoint(e)\n\n if (!point) {\n return false\n }\n\n e.stopPropagation()\n e.preventDefault()\n\n const dragStart = point\n var { x, y } = point\n\n x -= this.dragStart.x\n y -= this.dragStart.y\n\n this.dragStart = dragStart\n\n const overlayed = this.overlayed\n\n var boundingRect = overlayed.getBoundingClientRect()\n\n overlayed.style.left =\n Math.min(document.body.offsetWidth - 40, Math.max(40 - overlayed.offsetWidth, boundingRect.left + x)) + 'px'\n overlayed.style.top = Math.min(document.body.offsetHeight - 40, Math.max(0, boundingRect.top + y)) + 'px'\n\n overlayed.style.transform = 'initial'\n\n return false\n }\n\n onDragEnd(e: Event) {\n if (this.movable && this.dragStart) {\n e.stopPropagation()\n e.preventDefault()\n\n delete this.dragStart\n }\n }\n\n /**\n * A method that closes the overlay by removing it from its parent node in the DOM.\n * When called, this method removes the overlay element, effectively hiding it from the user interface.\n */\n close() {\n this.parentNode?.removeChild(this)\n }\n\n onClose(e: Event, escape?: boolean, request?: { result: unknown }) {\n e.stopPropagation()\n /* 현재 overlay state를 확인해서, 자신이 포함하고 있는 템플릿인 경우에 history.back() 한다. */\n\n if (this.historical) {\n const detail = { name: this.name, accepted: false }\n const close = new CustomEvent('close-overlay', { detail, bubbles: true, composed: true, cancelable: true })\n if (escape && !history.state?.overlay?.escapable) return true\n this.dispatchEvent(close)\n if (close.defaultPrevented) {\n if (detail.accepted) this.recordResult(request)\n return\n }\n var state = history.state\n var overlay = (state || {}).overlay\n\n if (!overlay || overlay.name !== this.name) {\n return\n }\n\n /* Backdrop click 경우는 escape 시도라고 정의한다. overlay 속성이 escapable이 아닌 경우에는 동작하지 않는다. */\n if (escape && !overlay.escapable) {\n return true\n }\n\n /* A second close in the same tick would see the same state and go back one page too far. */\n if (!claimHistoryBack(overlay.name)) {\n return\n }\n\n this.recordResult(request)\n history.back()\n } else {\n this.recordResult(request)\n this.close()\n }\n }\n\n /*\n * A value from the content (`closePopup(element, value)`) is recorded only once the overlay is really\n * going to close, and nothing settles here - the result settles when the overlay leaves the document,\n * where every way of closing ends. If another request recorded first, this value is dropped.\n */\n private recordResult(request?: { result: unknown }) {\n if (request && 'result' in request) {\n recordPopupResult(this.name, request.result)\n }\n }\n}\n"]}
|
|
@@ -90,7 +90,9 @@ export declare class OxPopupList extends OxPopup {
|
|
|
90
90
|
width?: string;
|
|
91
91
|
height?: string;
|
|
92
92
|
silent?: boolean;
|
|
93
|
+
anchorTop?: number;
|
|
93
94
|
}): void;
|
|
95
|
+
guaranteeFocus(target?: HTMLElement): void;
|
|
94
96
|
/**
|
|
95
97
|
* Overrides the 'close' method of the base class 'OxPopup' to dispatch a custom event
|
|
96
98
|
* indicating that the popup list is being closed. This event can be used for further interactions
|
|
@@ -16,7 +16,9 @@ function guaranteeFocus(element) {
|
|
|
16
16
|
}
|
|
17
17
|
// 2. Give focus opportunity to the closest parent, including itself.
|
|
18
18
|
const closest = element.closest('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
|
|
19
|
-
|
|
19
|
+
/* The popup itself places itself in view; scrolling the page to it, while it still stands at full height before
|
|
20
|
+
it is fitted, moved it and its select off the place it was fitted to. */
|
|
21
|
+
closest?.focus({ preventScroll: closest instanceof OxPopup });
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* A custom element representing a list-like popup menu.
|
|
@@ -190,6 +192,8 @@ let OxPopupList = class OxPopupList extends OxPopup {
|
|
|
190
192
|
|
|
191
193
|
div[body] {
|
|
192
194
|
flex: 1;
|
|
195
|
+
/* Cut to the room it has, the list scrolls under the search box rather than past it. */
|
|
196
|
+
min-height: 0;
|
|
193
197
|
display: flex;
|
|
194
198
|
flex-direction: column;
|
|
195
199
|
margin: 0;
|
|
@@ -252,6 +256,17 @@ let OxPopupList = class OxPopupList extends OxPopup {
|
|
|
252
256
|
if (!keys.includes(e.key)) {
|
|
253
257
|
e.stopPropagation();
|
|
254
258
|
}
|
|
259
|
+
/* Enter picks from the search box: the first match once something is typed, the active option before that. */
|
|
260
|
+
if (e.key === 'Enter' && !e.isComposing) {
|
|
261
|
+
e.preventDefault();
|
|
262
|
+
const visible = Array.from(this.querySelectorAll(':scope > [option]:not([hidden])'));
|
|
263
|
+
const active = this.querySelector(':scope > [option][active]:not([hidden])');
|
|
264
|
+
const option = this.searchKeyword ? visible[0] : active || visible[0];
|
|
265
|
+
if (option) {
|
|
266
|
+
this.setActive(option, true);
|
|
267
|
+
this.select();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
255
270
|
}
|
|
256
271
|
updated(changes) {
|
|
257
272
|
if (changes.has('activeIndex')) {
|
|
@@ -405,6 +420,24 @@ let OxPopupList = class OxPopupList extends OxPopup {
|
|
|
405
420
|
else {
|
|
406
421
|
this.setActive(this.activeIndex);
|
|
407
422
|
}
|
|
423
|
+
/* A searchable list opens ready to type, with the last search cleared. */
|
|
424
|
+
if (this.withSearch) {
|
|
425
|
+
this.searchKeyword = '';
|
|
426
|
+
this.updateComplete.then(() => {
|
|
427
|
+
if (!this.searchInput)
|
|
428
|
+
return;
|
|
429
|
+
this.searchInput.value = '';
|
|
430
|
+
this.searchInput.focus();
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/* The popup takes the focus when it opens and again a frame after it is attached; a searchable list gives it to the search box. */
|
|
435
|
+
guaranteeFocus(target) {
|
|
436
|
+
if (!target && this.withSearch && this.searchInput) {
|
|
437
|
+
this.searchInput.focus();
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
super.guaranteeFocus(target);
|
|
408
441
|
}
|
|
409
442
|
/**
|
|
410
443
|
* Overrides the 'close' method of the base class 'OxPopup' to dispatch a custom event
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-popup-list.js","sourceRoot":"","sources":["../../src/ox-popup-list.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAa,IAAI,EAAkB,MAAM,KAAK,CAAA;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,QAAQ,MAAM,YAAY,CAAA;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAEhE,SAAS,cAAc,CAAC,OAAoB;IAC1C,sFAAsF;IACtF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,0EAA0E,CAAC,CAAA;IAEnH,IAAI,SAAS,EAAE,CAAC;QACd,CAAC;QAAC,SAAyB,CAAC,KAAK,EAAE,CAAA;QACnC,OAAM;IACR,CAAC;IAED,qEAAqE;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAC7B,0EAA0E,CAC5D,CAAA;IAEhB,OAAO,EAAE,KAAK,EAAE,CAAA;AAClB,CAAC;AAED;;GAEG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,OAAO;IAAjC;;QAmHL;;;WAGG;QAC0D,aAAQ,GAAY,KAAK,CAAA;QAetF;;;;WAIG;QACgE,aAAQ,GAAa,KAAK,CAAA;QAWpF,oBAAe,GAAY,KAAK,CAAA;QAMjC,WAAM,GAAY,KAAK,CAAA;QA8DrB,eAAU,GAA+B,UAA6B,CAAgB;YAC9F,CAAC,CAAC,eAAe,EAAE,CAAA;YAEnB,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;gBACd,KAAK,KAAK,CAAC,CAAC,cAAc;gBAC1B,KAAK,QAAQ;oBACX,IAAI,CAAC,KAAK,EAAE,CAAA;oBACZ,MAAK;gBAEP,KAAK,MAAM,CAAC,CAAC,cAAc;gBAC3B,KAAK,WAAW,CAAC;gBACjB,KAAK,IAAI,CAAC,CAAC,cAAc;gBACzB,KAAK,SAAS;oBACZ,IAAI,CAAC,WAAY,EAAE,CAAA;oBACnB,MAAK;gBAEP,KAAK,OAAO,CAAC,CAAC,cAAc;gBAC5B,KAAK,YAAY,CAAC;gBAClB,KAAK,MAAM,CAAC,CAAC,cAAc;gBAC3B,KAAK,WAAW;oBACd,IAAI,CAAC,WAAY,EAAE,CAAA;oBACnB,MAAK;gBAEP,KAAK,OAAO,CAAC;gBACb,KAAK,GAAG,CAAC;gBACT,KAAK,UAAU,EAAE,kBAAkB;oBACjC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAY,EAAE,IAAI,CAAC,CAAA;oBACvC,IAAI,CAAC,MAAM,EAAE,CAAA;oBACb,MAAK;YACT,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEF,gBAAW,GAA4B,UAA6B,CAAa;YACzF,MAAM,EAAE,GAAG,CAAC,CAAC,aAA4B,CAAA;YAEzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBACvB,2GAA2G;gBAC3G,uBAAuB;gBACvB,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,EAAE,CAAA;YAChF,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEF,aAAQ,GAA4B,UAA6B,CAAa;YACtF,CAAC,CAAC,eAAe,EAAE,CAAA;YAEnB,gDAAgD;YAChD,IAAK,CAAC,CAAC,MAAsB,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBAChE,OAAM,CAAC,0CAA0C;YACnD,CAAC;YAED,MAAM,MAAM,GAAI,CAAC,CAAC,MAAsB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;YAC7D,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IA6Rd,CAAC;aA7iBQ,WAAM,GAAG;QACd,GAAG,OAAO,CAAC,MAAM;QACjB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6GF;KACF,AAhHY,CAgHZ;IA6CD,MAAM;QACJ,OAAO,IAAI,CAAA;;;QAGP,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAA;gDACkC,CAAC,CAAa,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;;;;;;2BAM9D,CAAC,CAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;0BAC/C,CAAC,CAAa,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;;;yBAG3C,GAAG,EAAE;gBACZ,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE,CAAA;gBAC3B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;YACzB,CAAC;;;;;WAKN;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;;;;oBAII,CAAC,CAAQ,EAAE,EAAE;YACrB,CAAC,CAAC,eAAe,EAAE,CAAA;QACrB,CAAC;wBACa,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE;;;;;QAK3C,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAA,0CAA0C,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;KACjF,CAAA;IACH,CAAC;IAES,cAAc,CAAC,CAAa;QACpC,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,CAAC,CAAC,cAAc,EAAE,CAAA;QAElB,IAAI,CAAC,aAAa,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;IAC3D,CAAC;IAES,eAAe,CAAC,CAAa;QACrC,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,aAAa,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;IAC3D,CAAC;IAES,gBAAgB,CAAC,CAAgB;QACzC,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;QACpE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,CAAC,CAAC,eAAe,EAAE,CAAA;QACrB,CAAC;IACH,CAAC;IA2DD,OAAO,CAAC,OAA6B;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACpE,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAA;YAEpD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE;oBAC1C,MAAM,EAAE,UAAU;oBAClB,SAAS,EAAE,UAAU;oBACrB,SAAS,EAAE,UAAU;oBACrB,SAAS,EAAE,GAAG;oBACd,mBAAmB,EAAE,EAAE;oBACvB,KAAK,EAAE,CAAC,CAAC,EAAE;wBACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;wBACnB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;4BACxB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;yBACtD,CAAC,CACH,CAAA;oBACH,CAAC;oBACD,MAAM,EAAE,CAAC,CAAC,EAAE;wBACV,+CAA+C;wBAC/C,IAAK,CAAC,CAAC,OAAuB,CAAC,aAAa,CAAC,wBAAwB,CAAC,EAAE,CAAC;4BACvE,OAAO,KAAK,CAAA,CAAC,0CAA0C;wBACzD,CAAC;wBACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;oBACpB,CAAC;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,UAAU,CAAA;YACpD,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC/C,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;oBACxF,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;gBAChC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;oBAChC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;gBACjC,CAAC;YACH,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAA;QACrF,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,IAAI,CAAC,YAAY,EAAE,CAAA;IAC/C,CAAC;IAED,2CAA2C;IACnC,YAAY;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,CAAC,CAAC,MAAM,YAAY,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,CAAC,MAAgB,CAAC,CAAA;QAC7B,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACvB,IAAI,MAAM,EAAE,QAAQ,CAAE,MAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC1E,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,EAAE,EAAE,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAA;YACzD,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;OAGG;IACK,cAAc;QACpB,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC1E,CAAC;IAED;;;;OAIG;IACI,iBAAiB;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,MAAM,QAAQ,GAAG,OAAO;aACrB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC;aACtG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAA;QAE1C,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,CAAC,cAAc,CAAA;QAEzB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,MAAM,QAAQ,GAAG,OAAO;aACrB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC;aACtG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAE9C,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC/C,CAAC,CACH,CAAA;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,WAAY,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9E,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,MAA+B,EAAE,UAAoB;QAC7D,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,CAAA;QACzE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,CAAE,CAAC,CAAA;QAC1D,CAAC;QAED,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAA;YAC5D,IAAI,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;YACpD,OAAM;QACR,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,UAAU,CAAA;QAEpD,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;gBACvF,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;gBAEjC,IAAI,UAAU,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;oBACrC,uGAAuG;oBACvG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;gBAC1F,CAAC;gBAED,cAAc,CAAC,MAAqB,CAAC,CAAA;gBAErC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;gBAChC,oFAAoF;gBACpF,CAAC,IAAI,CAAC,QAAQ,IAAI,UAAU,IAAI,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAA;YACtE,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACM,IAAI,CAAC,MASb;QACC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAElB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,YAAY,IAAI,UAAU,GAAG,CAAC,CAAA;YAChF,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAClC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACM,KAAK;QACZ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAM;QACR,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,OAAO,EAAE;gBACvB,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;aACf,CAAC,CACH,CAAA;QACH,CAAC;QAED,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,EACV,QAAQ,EACR,GAAG,EACH,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,MAAM,EACN,KAAK,EAaN;QACC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAgB,CAAA;QAErE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;YAC7C,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,OAAO,CAAA;YAElC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YACpD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QAClC,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAExB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAAC;gBACxD,IAAI;gBACJ,GAAG;gBACH,KAAK;gBACL,MAAM;gBACN,eAAe,EAAE,MAAqB;aACvC,CAAC,CAAA;QACJ,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QACjC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAA;QAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAEzC,OAAO,MAAM,CAAA;IACf,CAAC;;AAtb4D;IAA5D,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;6CAA0B;AAMf;IAAtE,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iDAAsB;AAOtB;IAArE,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;+CAAqB;AAOvB;IAAlE,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;6CAA2B;AAOjE;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAA0B;AAE5C;IAAR,KAAK,EAAE;gDAAqB;AACpB;IAAR,KAAK,EAAE;kDAAuB;AACtB;IAAR,KAAK,EAAE;oDAAiC;AAEhB;IAAxB,KAAK,CAAC,gBAAgB,CAAC;gDAA+B;AACnC;IAAnB,KAAK,CAAC,WAAW,CAAC;yCAAsB;AAzJ9B,WAAW;IADvB,aAAa,CAAC,eAAe,CAAC;GAClB,WAAW,CA8iBvB","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, CSSResult, html, PropertyValues } from 'lit'\nimport { render } from 'lit-html'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport Sortable from 'sortablejs'\n\nimport { OxPopup } from './ox-popup.js'\nimport { convertToFixedPosition } from './position-converter.js'\n\nfunction guaranteeFocus(element: HTMLElement) {\n // 1. Give focus opportunity to the first focusable element within the option element.\n const focusible = element.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])')\n\n if (focusible) {\n ;(focusible as HTMLElement).focus()\n return\n }\n\n // 2. Give focus opportunity to the closest parent, including itself.\n const closest = element.closest(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n ) as HTMLElement\n\n closest?.focus()\n}\n\n/**\n * A custom element representing a list-like popup menu.\n */\n@customElement('ox-popup-list')\nexport class OxPopupList extends OxPopup {\n static styles = [\n ...OxPopup.styles,\n css`\n :host {\n display: none;\n align-items: stretch;\n background-color: var(--ox-popup-list-background-color, var(--md-sys-color-surface-container-lowest));\n color: var(--ox-popup-list-color, var(--md-sys-color-on-surface));\n z-index: 1000;\n box-shadow: 2px 3px 10px 5px rgba(0, 0, 0, 0.15);\n padding: var(--spacing-small) 0;\n border-radius: var(--md-sys-shape-corner-small, 5px);\n\n font-size: var(--md-sys-typescale-label-large-size, 0.875rem);\n }\n\n :host([active]) {\n display: flex;\n flex-direction: column;\n }\n\n :host(*:focus) {\n outline: none;\n }\n\n :host([nowrap]) ::slotted([option]) {\n white-space: nowrap;\n }\n\n ::slotted([option]) {\n border-left: 3px solid transparent;\n }\n\n ::slotted(*) {\n padding: var(--spacing-medium);\n border-bottom: 1px solid var(--md-sys-color-surface-variant);\n cursor: pointer;\n outline: none;\n color: var(--ox-popup-list-color, var(--md-sys-color-on-surface-variant));\n }\n\n ::slotted(*:focus) {\n outline: none;\n }\n\n ::slotted([option][active]),\n ::slotted([option]:hover) {\n background-color: var(--ox-popup-list-background-color-variant, var(--md-sys-color-surface-variant));\n color: var(--ox-popup-list-color-variant, var(--md-sys-color-on-surface-variant));\n }\n\n ::slotted([option][selected]) {\n border-left: 3px solid var(--md-sys-color-primary);\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n }\n\n ::slotted([separator]) {\n height: 1px;\n width: 100%;\n padding: 0;\n background-color: var(--ox-popup-menu-separator-color, var(--md-sys-color-surface-variant));\n }\n\n ::slotted([hidden]) {\n display: none;\n }\n\n [search] {\n display: flex;\n position: relative;\n align-items: center;\n padding: var(--spacing-small) var(--spacing-medium);\n\n --md-icon-size: var(--icon-size-small);\n }\n\n [search] [type='text'] {\n flex: 1;\n background-color: transparent;\n border: 0;\n padding: 0 0 0 var(--spacing-huge);\n outline: none;\n width: 50px;\n }\n\n [search] md-icon {\n color: var(--md-sys-color-secondary);\n }\n\n [search] md-icon[search-icon] {\n position: absolute;\n }\n\n [search] md-icon[delete-icon] {\n opacity: 0.5;\n --md-icon-size: var(--icon-size-tiny);\n }\n\n [nothing] {\n opacity: 0.5;\n text-align: center;\n }\n\n div[body] {\n flex: 1;\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n overflow: auto;\n }\n `\n ]\n\n /**\n * A boolean property that, when set to true, allows multiple options to be selected in the popup list.\n * @type {boolean}\n */\n @property({ type: Boolean, attribute: true, reflect: true }) multiple: boolean = false\n\n /**\n * An optional attribute that specifies the name of the attribute used to mark selected options in the list.\n * @type {string|undefined}\n */\n @property({ type: String, attribute: 'attr-selected', reflect: true }) attrSelected?: string\n\n /**\n * A boolean property that, when set to true, enables the search functionality in the popup list.\n * Users can search/filter options by typing in a search bar.\n * @type {boolean|undefined}\n */\n @property({ type: Boolean, attribute: 'with-search', reflect: true }) withSearch?: boolean\n\n /**\n * A boolean property that, when set to true, enables the drag-and-drop sorting functionality within the popup list.\n * This allows users to reorder the options in the list by dragging them into new positions.\n * @type {boolean|undefined}\n */\n @property({ type: Boolean, attribute: 'sortable', reflect: true }) sortable?: boolean = false\n\n /**\n * The value(s) of the selected option(s) in the popup list.\n * This property can be a string or an array of strings, depending on whether multiple selections are allowed.\n * @type {string|string[]|undefined}\n */\n @property({ type: String }) value?: string | string[]\n\n @state() activeIndex?: number\n @state() searchKeyword?: string\n @state() nothingToSelect: boolean = false\n\n @query('[search] input') searchInput!: HTMLInputElement\n @query('div[body]') body!: HTMLDivElement\n\n private sortableObject?: Sortable\n private locked: boolean = false\n\n render() {\n return html`\n <slot name=\"header\"> </slot>\n\n ${this.withSearch\n ? html`\n <label search for=\"search\" @input=${(e: InputEvent) => this._oninputsearch(e)}>\n <md-icon search-icon>search</md-icon>\n <input\n id=\"search\"\n type=\"text\"\n autocomplete=\"off\"\n @keydown=${(e: KeyboardEvent) => this._onkeydownsearch(e)}\n @change=${(e: InputEvent) => this._onchangesearch(e)}\n />\n <md-icon\n @click=${() => {\n this.searchInput.value = ''\n this.searchKeyword = ''\n }}\n delete-icon\n >delete</md-icon\n >\n </label>\n `\n : html``}\n\n <div body>\n <slot\n @change=${(e: Event) => {\n e.stopPropagation()\n }}\n @slotchange=${() => this.optionsChanged()}\n >\n </slot>\n </div>\n\n ${this.nothingToSelect ? html`<label nothing>nothing to select</label>` : html``}\n `\n }\n\n protected _oninputsearch(e: InputEvent) {\n e.stopPropagation()\n e.preventDefault()\n\n this.searchKeyword = (e.target as HTMLInputElement).value\n }\n\n protected _onchangesearch(e: InputEvent) {\n e.stopPropagation()\n this.searchKeyword = (e.target as HTMLInputElement).value\n }\n\n protected _onkeydownsearch(e: KeyboardEvent) {\n const keys = ['Esc', 'Escape', 'Up', 'ArrowUp', 'Down', 'ArrowDown']\n if (!keys.includes(e.key)) {\n e.stopPropagation()\n }\n }\n\n protected _onkeydown: (e: KeyboardEvent) => void = function (this: OxPopupList, e: KeyboardEvent) {\n e.stopPropagation()\n\n switch (e.key) {\n case 'Esc': // for IE/Edge\n case 'Escape':\n this.close()\n break\n\n case 'Left': // for IE/Edge\n case 'ArrowLeft':\n case 'Up': // for IE/Edge\n case 'ArrowUp':\n this.activeIndex!--\n break\n\n case 'Right': // for IE/Edge\n case 'ArrowRight':\n case 'Down': // for IE/Edge\n case 'ArrowDown':\n this.activeIndex!++\n break\n\n case 'Enter':\n case ' ':\n case 'Spacebar': // for old firefox\n this.setActive(this.activeIndex!, true)\n this.select()\n break\n }\n }.bind(this)\n\n protected _onfocusout: (e: FocusEvent) => void = function (this: OxPopupList, e: FocusEvent) {\n const to = e.relatedTarget as HTMLElement\n\n if (!this.contains(to)) {\n /* If the focus has clearly moved to an element outside of my range, the ox-popup-list should be closed. */\n // @ts-ignore for debug\n !this.preventCloseOnBlur && !this.debug && !window.POPUP_DEBUG && this.close()\n }\n }.bind(this)\n\n protected _onclick: (e: MouseEvent) => void = function (this: OxPopupList, e: MouseEvent) {\n e.stopPropagation()\n\n // Check if the click event target is a checkbox\n if ((e.target as HTMLElement).closest('input[type=\"checkbox\"]')) {\n return // Do not proceed if it's a checkbox click\n }\n\n const option = (e.target as HTMLElement)?.closest('[option]')\n if (option) {\n this.setActive(option, true)\n this.select()\n }\n }.bind(this)\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('activeIndex')) {\n this.activeIndex !== undefined && this.setActive(this.activeIndex)\n }\n\n if (changes.has('sortable')) {\n this.sortableObject && this.sortableObject.destroy()\n\n if (this.sortable) {\n this.sortableObject = Sortable.create(this, {\n handle: '[option]',\n draggable: '[option]',\n direction: 'vertical',\n animation: 150,\n touchStartThreshold: 10,\n onEnd: e => {\n this.locked = false\n this.dispatchEvent(\n new CustomEvent('sorted', {\n detail: Array.from(this.querySelectorAll('[option]'))\n })\n )\n },\n onMove: e => {\n // Check if the drag event target is a checkbox\n if ((e.dragged as HTMLElement).querySelector('input[type=\"checkbox\"]')) {\n return false // Prevent sorting if it's a checkbox drag\n }\n this.locked = true\n }\n })\n }\n }\n\n if (changes.has('searchKeyword')) {\n const attrSelected = this.attrSelected || 'selected'\n this.querySelectorAll(`[option]`).forEach(item => {\n if (!this.searchKeyword || item.textContent?.match(new RegExp(this.searchKeyword, 'i'))) {\n item.removeAttribute('hidden')\n } else {\n item.removeAttribute('selected')\n item.setAttribute('hidden', '')\n }\n })\n this.nothingToSelect = this.querySelectorAll(`[option]:not([hidden])`).length === 0\n }\n\n if (changes.has('value')) this.markSelected()\n }\n\n /** Marks the options holding the value. */\n private markSelected() {\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n var values = this.value\n if (!(values instanceof Array)) {\n values = [values as string]\n }\n\n options.forEach(option => {\n if (values?.includes((option as HTMLElement).getAttribute('value') || '')) {\n option.setAttribute(this.attrSelected || 'selected', '')\n } else {\n option.removeAttribute(this.attrSelected || 'selected')\n }\n })\n }\n\n /**\n * Options can arrive after the value - choices read from the server. They are marked when they arrive, and the\n * owner is told so it can show the chosen label instead of the raw value.\n */\n private optionsChanged() {\n this.markSelected()\n this.dispatchEvent(new CustomEvent('options-change', { bubbles: true }))\n }\n\n /**\n * Retrieves the labels of the selected options in the popup list.\n * If multiple selections are allowed, an array of labels is returned. Otherwise, a single label is returned.\n * @returns {string|string[]} The label(s) of the selected option(s).\n */\n public getSelectedLabels(): string | string[] {\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n const selected = options\n .filter(option => option.hasAttribute('value') && option.hasAttribute(this.attrSelected || 'selected'))\n .map(option => option.textContent || '')\n\n return this.multiple ? selected : selected[0]\n }\n\n /**\n * Handles the selection of options in the popup list and dispatches a 'select' event with the selected value(s).\n * If multiple selections are allowed, an array of selected values is dispatched; otherwise, a single value is dispatched.\n * Also, it checks whether the selected option should remain alive and whether the popup should be closed.\n */\n async select() {\n await this.updateComplete\n\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n const selected = options\n .filter(option => option.hasAttribute('value') && option.hasAttribute(this.attrSelected || 'selected'))\n .map(option => option.getAttribute('value'))\n\n this.dispatchEvent(\n new CustomEvent('select', {\n bubbles: true,\n composed: true,\n detail: this.multiple ? selected : selected[0]\n })\n )\n\n const option = options[this.activeIndex!]\n if (!option.hasAttribute('alive-on-select') && !this.hasAttribute('multiple')) {\n this.close()\n }\n }\n\n /**\n * Sets the active option within the popup list based on the given index or Element.\n * If 'withSelect' is true, it also manages the selection state of the option.\n *\n * @param {number | Element | null} active - The index or Element of the option to set as active.\n * @param {boolean | undefined} withSelect - Indicates whether to manage the selection state of the option.\n */\n setActive(active: number | Element | null, withSelect?: boolean) {\n var options = Array.from(this.querySelectorAll('[option]:not([hidden])'))\n if (this.withSearch) {\n options.push(this.renderRoot.querySelector('[search]')!)\n }\n\n if (active instanceof Element) {\n const index = options.findIndex(option => option === active)\n this.setActive(index === -1 ? 0 : index, withSelect)\n return\n }\n\n const attrSelected = this.attrSelected || 'selected'\n\n options.forEach(async (option, index) => {\n if (typeof active === 'number' && index === (active + options.length) % options.length) {\n option.setAttribute('active', '')\n\n if (withSelect && !this.attrSelected) {\n /* being set attribute attrs-selected means, that element should know how to do when event happened. */\n this.multiple ? option.toggleAttribute('selected') : option.setAttribute('selected', '')\n }\n\n guaranteeFocus(option as HTMLElement)\n\n this.activeIndex = index\n } else {\n option.removeAttribute('active')\n /* even thought attribute attrs-selected set, ox-popup-list have to unset others. */\n !this.multiple && withSelect && option.removeAttribute(attrSelected)\n }\n })\n }\n\n /**\n * Overrides the 'open' method of the base class 'OxPopup' to set the initial active index\n * when the popup list is opened. It ensures that an option is initially selected for user interaction.\n *\n * @param {object} params - The parameters for opening the popup, including position and size.\n */\n override open(params: {\n left?: number\n top?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n silent?: boolean\n // fixed?: boolean\n }) {\n super.open(params)\n\n if (this.activeIndex === undefined) {\n const activeElement = this.querySelector(`[${this.attrSelected || 'selected'}]`)\n this.setActive(activeElement || 0)\n } else {\n this.setActive(this.activeIndex)\n }\n }\n\n /**\n * Overrides the 'close' method of the base class 'OxPopup' to dispatch a custom event\n * indicating that the popup list is being closed. This event can be used for further interactions\n * or logic in the application.\n */\n override close() {\n if (this.locked) {\n return\n }\n\n if (this.hasAttribute('active')) {\n this.dispatchEvent(\n new CustomEvent('close', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n super.close()\n }\n\n /**\n * Open OxPopup\n *\n * @param {PopupOpenOptions}\n */\n static open({\n template,\n top,\n left,\n right,\n bottom,\n parent,\n multiple,\n sortable,\n attrSelected,\n styles,\n debug\n }: {\n template: unknown\n top?: number\n left?: number\n right?: number\n bottom?: number\n parent?: Element | null\n multiple?: boolean\n sortable?: boolean\n debug?: boolean\n attrSelected?: string\n styles?: CSSResult\n }): OxPopupList {\n const target = document.createElement('ox-popup-list') as OxPopupList\n\n if (styles) {\n const style = document.createElement('style')\n style.textContent = styles.cssText\n\n const shadow = target.attachShadow({ mode: 'open' })\n shadow.appendChild(style)\n }\n\n if (!!debug) {\n target.setAttribute('debug', '')\n }\n\n if (!!multiple) {\n target.setAttribute('multiple', '')\n }\n\n if (!!sortable) {\n target.setAttribute('sortable', '')\n }\n\n if (attrSelected) {\n target.setAttribute('attr-selected', attrSelected)\n }\n\n render(template, target)\n\n if (parent) {\n var { left, top, right, bottom } = convertToFixedPosition({\n left,\n top,\n right,\n bottom,\n relativeElement: parent as HTMLElement\n })\n }\n\n document.body.appendChild(target)\n target.removeAfterUse = true\n target.open({ top, left, right, bottom })\n\n return target\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-popup-list.js","sourceRoot":"","sources":["../../src/ox-popup-list.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAa,IAAI,EAAkB,MAAM,KAAK,CAAA;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,QAAQ,MAAM,YAAY,CAAA;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAEhE,SAAS,cAAc,CAAC,OAAoB;IAC1C,sFAAsF;IACtF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,0EAA0E,CAAC,CAAA;IAEnH,IAAI,SAAS,EAAE,CAAC;QACd,CAAC;QAAC,SAAyB,CAAC,KAAK,EAAE,CAAA;QACnC,OAAM;IACR,CAAC;IAED,qEAAqE;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAC7B,0EAA0E,CAC5D,CAAA;IAEhB;+EAC2E;IAC3E,OAAO,EAAE,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,YAAY,OAAO,EAAE,CAAC,CAAA;AAC/D,CAAC;AAED;;GAEG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,OAAO;IAAjC;;QAqHL;;;WAGG;QAC0D,aAAQ,GAAY,KAAK,CAAA;QAetF;;;;WAIG;QACgE,aAAQ,GAAa,KAAK,CAAA;QAWpF,oBAAe,GAAY,KAAK,CAAA;QAMjC,WAAM,GAAY,KAAK,CAAA;QA0ErB,eAAU,GAA+B,UAA6B,CAAgB;YAC9F,CAAC,CAAC,eAAe,EAAE,CAAA;YAEnB,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;gBACd,KAAK,KAAK,CAAC,CAAC,cAAc;gBAC1B,KAAK,QAAQ;oBACX,IAAI,CAAC,KAAK,EAAE,CAAA;oBACZ,MAAK;gBAEP,KAAK,MAAM,CAAC,CAAC,cAAc;gBAC3B,KAAK,WAAW,CAAC;gBACjB,KAAK,IAAI,CAAC,CAAC,cAAc;gBACzB,KAAK,SAAS;oBACZ,IAAI,CAAC,WAAY,EAAE,CAAA;oBACnB,MAAK;gBAEP,KAAK,OAAO,CAAC,CAAC,cAAc;gBAC5B,KAAK,YAAY,CAAC;gBAClB,KAAK,MAAM,CAAC,CAAC,cAAc;gBAC3B,KAAK,WAAW;oBACd,IAAI,CAAC,WAAY,EAAE,CAAA;oBACnB,MAAK;gBAEP,KAAK,OAAO,CAAC;gBACb,KAAK,GAAG,CAAC;gBACT,KAAK,UAAU,EAAE,kBAAkB;oBACjC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAY,EAAE,IAAI,CAAC,CAAA;oBACvC,IAAI,CAAC,MAAM,EAAE,CAAA;oBACb,MAAK;YACT,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEF,gBAAW,GAA4B,UAA6B,CAAa;YACzF,MAAM,EAAE,GAAG,CAAC,CAAC,aAA4B,CAAA;YAEzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBACvB,2GAA2G;gBAC3G,uBAAuB;gBACvB,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,EAAE,CAAA;YAChF,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEF,aAAQ,GAA4B,UAA6B,CAAa;YACtF,CAAC,CAAC,eAAe,EAAE,CAAA;YAEnB,gDAAgD;YAChD,IAAK,CAAC,CAAC,MAAsB,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBAChE,OAAM,CAAC,0CAA0C;YACnD,CAAC;YAED,MAAM,MAAM,GAAI,CAAC,CAAC,MAAsB,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;YAC7D,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAiTd,CAAC;aA/kBQ,WAAM,GAAG;QACd,GAAG,OAAO,CAAC,MAAM;QACjB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+GF;KACF,AAlHY,CAkHZ;IA6CD,MAAM;QACJ,OAAO,IAAI,CAAA;;;QAGP,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAA;gDACkC,CAAC,CAAa,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;;;;;;2BAM9D,CAAC,CAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;0BAC/C,CAAC,CAAa,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;;;yBAG3C,GAAG,EAAE;gBACZ,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE,CAAA;gBAC3B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;YACzB,CAAC;;;;;WAKN;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;;;;oBAII,CAAC,CAAQ,EAAE,EAAE;YACrB,CAAC,CAAC,eAAe,EAAE,CAAA;QACrB,CAAC;wBACa,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE;;;;;QAK3C,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAA,0CAA0C,CAAC,CAAC,CAAC,IAAI,CAAA,EAAE;KACjF,CAAA;IACH,CAAC;IAES,cAAc,CAAC,CAAa;QACpC,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,CAAC,CAAC,cAAc,EAAE,CAAA;QAElB,IAAI,CAAC,aAAa,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;IAC3D,CAAC;IAES,eAAe,CAAC,CAAa;QACrC,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,aAAa,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;IAC3D,CAAC;IAES,gBAAgB,CAAC,CAAgB;QACzC,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAA;QACpE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,CAAC,CAAC,eAAe,EAAE,CAAA;QACrB,CAAC;QAED,8GAA8G;QAC9G,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACxC,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,iCAAiC,CAAC,CAAC,CAAA;YACpF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,yCAAyC,CAAC,CAAA;YAC5E,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAAA;YACrE,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAA;YACf,CAAC;QACH,CAAC;IACH,CAAC;IA2DD,OAAO,CAAC,OAA6B;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACpE,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAA;YAEpD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE;oBAC1C,MAAM,EAAE,UAAU;oBAClB,SAAS,EAAE,UAAU;oBACrB,SAAS,EAAE,UAAU;oBACrB,SAAS,EAAE,GAAG;oBACd,mBAAmB,EAAE,EAAE;oBACvB,KAAK,EAAE,CAAC,CAAC,EAAE;wBACT,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;wBACnB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;4BACxB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;yBACtD,CAAC,CACH,CAAA;oBACH,CAAC;oBACD,MAAM,EAAE,CAAC,CAAC,EAAE;wBACV,+CAA+C;wBAC/C,IAAK,CAAC,CAAC,OAAuB,CAAC,aAAa,CAAC,wBAAwB,CAAC,EAAE,CAAC;4BACvE,OAAO,KAAK,CAAA,CAAC,0CAA0C;wBACzD,CAAC;wBACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;oBACpB,CAAC;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,UAAU,CAAA;YACpD,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC/C,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;oBACxF,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;gBAChC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;oBAChC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;gBACjC,CAAC;YACH,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAA;QACrF,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,IAAI,CAAC,YAAY,EAAE,CAAA;IAC/C,CAAC;IAED,2CAA2C;IACnC,YAAY;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,CAAC,CAAC,MAAM,YAAY,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,CAAC,MAAgB,CAAC,CAAA;QAC7B,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACvB,IAAI,MAAM,EAAE,QAAQ,CAAE,MAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC1E,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,EAAE,EAAE,CAAC,CAAA;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAA;YACzD,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;OAGG;IACK,cAAc;QACpB,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC1E,CAAC;IAED;;;;OAIG;IACI,iBAAiB;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,MAAM,QAAQ,GAAG,OAAO;aACrB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC;aACtG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAA;QAE1C,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,CAAC,cAAc,CAAA;QAEzB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAEtE,MAAM,QAAQ,GAAG,OAAO;aACrB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,CAAC;aACtG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAA;QAE9C,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC/C,CAAC,CACH,CAAA;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,WAAY,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9E,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,MAA+B,EAAE,UAAoB;QAC7D,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,CAAA;QACzE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,UAAU,CAAE,CAAC,CAAA;QAC1D,CAAC;QAED,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAA;YAC5D,IAAI,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;YACpD,OAAM;QACR,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,UAAU,CAAA;QAEpD,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;YACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;gBACvF,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;gBAEjC,IAAI,UAAU,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;oBACrC,uGAAuG;oBACvG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;gBAC1F,CAAC;gBAED,cAAc,CAAC,MAAqB,CAAC,CAAA;gBAErC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAA;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;gBAChC,oFAAoF;gBACpF,CAAC,IAAI,CAAC,QAAQ,IAAI,UAAU,IAAI,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAA;YACtE,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACM,IAAI,CAAC,MAUb;QACC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAElB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,YAAY,IAAI,UAAU,GAAG,CAAC,CAAA;YAChF,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAClC,CAAC;QAED,0EAA0E;QAC1E,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;YACvB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,OAAM;gBAC7B,IAAI,CAAC,WAAW,CAAC,KAAK,GAAG,EAAE,CAAA;gBAC3B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;YAC1B,CAAC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,mIAAmI;IAC1H,cAAc,CAAC,MAAoB;QAC1C,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;YACxB,OAAM;QACR,CAAC;QACD,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED;;;;OAIG;IACM,KAAK;QACZ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAM;QACR,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,OAAO,EAAE;gBACvB,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;aACf,CAAC,CACH,CAAA;QACH,CAAC;QAED,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,IAAI,CAAC,EACV,QAAQ,EACR,GAAG,EACH,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,YAAY,EACZ,MAAM,EACN,KAAK,EAaN;QACC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,eAAe,CAAgB,CAAA;QAErE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;YAC7C,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,OAAO,CAAA;YAElC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;YACpD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;QAClC,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE,YAAY,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAExB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAAC;gBACxD,IAAI;gBACJ,GAAG;gBACH,KAAK;gBACL,MAAM;gBACN,eAAe,EAAE,MAAqB;aACvC,CAAC,CAAA;QACJ,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QACjC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAA;QAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;QAEzC,OAAO,MAAM,CAAA;IACf,CAAC;;AAtd4D;IAA5D,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;6CAA0B;AAMf;IAAtE,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iDAAsB;AAOtB;IAArE,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;+CAAqB;AAOvB;IAAlE,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;6CAA2B;AAOjE;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAA0B;AAE5C;IAAR,KAAK,EAAE;gDAAqB;AACpB;IAAR,KAAK,EAAE;kDAAuB;AACtB;IAAR,KAAK,EAAE;oDAAiC;AAEhB;IAAxB,KAAK,CAAC,gBAAgB,CAAC;gDAA+B;AACnC;IAAnB,KAAK,CAAC,WAAW,CAAC;yCAAsB;AA3J9B,WAAW;IADvB,aAAa,CAAC,eAAe,CAAC;GAClB,WAAW,CAglBvB","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, CSSResult, html, PropertyValues } from 'lit'\nimport { render } from 'lit-html'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport Sortable from 'sortablejs'\n\nimport { OxPopup } from './ox-popup.js'\nimport { convertToFixedPosition } from './position-converter.js'\n\nfunction guaranteeFocus(element: HTMLElement) {\n // 1. Give focus opportunity to the first focusable element within the option element.\n const focusible = element.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])')\n\n if (focusible) {\n ;(focusible as HTMLElement).focus()\n return\n }\n\n // 2. Give focus opportunity to the closest parent, including itself.\n const closest = element.closest(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n ) as HTMLElement\n\n /* The popup itself places itself in view; scrolling the page to it, while it still stands at full height before\n it is fitted, moved it and its select off the place it was fitted to. */\n closest?.focus({ preventScroll: closest instanceof OxPopup })\n}\n\n/**\n * A custom element representing a list-like popup menu.\n */\n@customElement('ox-popup-list')\nexport class OxPopupList extends OxPopup {\n static styles = [\n ...OxPopup.styles,\n css`\n :host {\n display: none;\n align-items: stretch;\n background-color: var(--ox-popup-list-background-color, var(--md-sys-color-surface-container-lowest));\n color: var(--ox-popup-list-color, var(--md-sys-color-on-surface));\n z-index: 1000;\n box-shadow: 2px 3px 10px 5px rgba(0, 0, 0, 0.15);\n padding: var(--spacing-small) 0;\n border-radius: var(--md-sys-shape-corner-small, 5px);\n\n font-size: var(--md-sys-typescale-label-large-size, 0.875rem);\n }\n\n :host([active]) {\n display: flex;\n flex-direction: column;\n }\n\n :host(*:focus) {\n outline: none;\n }\n\n :host([nowrap]) ::slotted([option]) {\n white-space: nowrap;\n }\n\n ::slotted([option]) {\n border-left: 3px solid transparent;\n }\n\n ::slotted(*) {\n padding: var(--spacing-medium);\n border-bottom: 1px solid var(--md-sys-color-surface-variant);\n cursor: pointer;\n outline: none;\n color: var(--ox-popup-list-color, var(--md-sys-color-on-surface-variant));\n }\n\n ::slotted(*:focus) {\n outline: none;\n }\n\n ::slotted([option][active]),\n ::slotted([option]:hover) {\n background-color: var(--ox-popup-list-background-color-variant, var(--md-sys-color-surface-variant));\n color: var(--ox-popup-list-color-variant, var(--md-sys-color-on-surface-variant));\n }\n\n ::slotted([option][selected]) {\n border-left: 3px solid var(--md-sys-color-primary);\n font-weight: var(--md-sys-typescale-label-large-weight, var(--md-ref-typeface-weight-medium, 500));\n }\n\n ::slotted([separator]) {\n height: 1px;\n width: 100%;\n padding: 0;\n background-color: var(--ox-popup-menu-separator-color, var(--md-sys-color-surface-variant));\n }\n\n ::slotted([hidden]) {\n display: none;\n }\n\n [search] {\n display: flex;\n position: relative;\n align-items: center;\n padding: var(--spacing-small) var(--spacing-medium);\n\n --md-icon-size: var(--icon-size-small);\n }\n\n [search] [type='text'] {\n flex: 1;\n background-color: transparent;\n border: 0;\n padding: 0 0 0 var(--spacing-huge);\n outline: none;\n width: 50px;\n }\n\n [search] md-icon {\n color: var(--md-sys-color-secondary);\n }\n\n [search] md-icon[search-icon] {\n position: absolute;\n }\n\n [search] md-icon[delete-icon] {\n opacity: 0.5;\n --md-icon-size: var(--icon-size-tiny);\n }\n\n [nothing] {\n opacity: 0.5;\n text-align: center;\n }\n\n div[body] {\n flex: 1;\n /* Cut to the room it has, the list scrolls under the search box rather than past it. */\n min-height: 0;\n display: flex;\n flex-direction: column;\n margin: 0;\n padding: 0;\n overflow: auto;\n }\n `\n ]\n\n /**\n * A boolean property that, when set to true, allows multiple options to be selected in the popup list.\n * @type {boolean}\n */\n @property({ type: Boolean, attribute: true, reflect: true }) multiple: boolean = false\n\n /**\n * An optional attribute that specifies the name of the attribute used to mark selected options in the list.\n * @type {string|undefined}\n */\n @property({ type: String, attribute: 'attr-selected', reflect: true }) attrSelected?: string\n\n /**\n * A boolean property that, when set to true, enables the search functionality in the popup list.\n * Users can search/filter options by typing in a search bar.\n * @type {boolean|undefined}\n */\n @property({ type: Boolean, attribute: 'with-search', reflect: true }) withSearch?: boolean\n\n /**\n * A boolean property that, when set to true, enables the drag-and-drop sorting functionality within the popup list.\n * This allows users to reorder the options in the list by dragging them into new positions.\n * @type {boolean|undefined}\n */\n @property({ type: Boolean, attribute: 'sortable', reflect: true }) sortable?: boolean = false\n\n /**\n * The value(s) of the selected option(s) in the popup list.\n * This property can be a string or an array of strings, depending on whether multiple selections are allowed.\n * @type {string|string[]|undefined}\n */\n @property({ type: String }) value?: string | string[]\n\n @state() activeIndex?: number\n @state() searchKeyword?: string\n @state() nothingToSelect: boolean = false\n\n @query('[search] input') searchInput!: HTMLInputElement\n @query('div[body]') body!: HTMLDivElement\n\n private sortableObject?: Sortable\n private locked: boolean = false\n\n render() {\n return html`\n <slot name=\"header\"> </slot>\n\n ${this.withSearch\n ? html`\n <label search for=\"search\" @input=${(e: InputEvent) => this._oninputsearch(e)}>\n <md-icon search-icon>search</md-icon>\n <input\n id=\"search\"\n type=\"text\"\n autocomplete=\"off\"\n @keydown=${(e: KeyboardEvent) => this._onkeydownsearch(e)}\n @change=${(e: InputEvent) => this._onchangesearch(e)}\n />\n <md-icon\n @click=${() => {\n this.searchInput.value = ''\n this.searchKeyword = ''\n }}\n delete-icon\n >delete</md-icon\n >\n </label>\n `\n : html``}\n\n <div body>\n <slot\n @change=${(e: Event) => {\n e.stopPropagation()\n }}\n @slotchange=${() => this.optionsChanged()}\n >\n </slot>\n </div>\n\n ${this.nothingToSelect ? html`<label nothing>nothing to select</label>` : html``}\n `\n }\n\n protected _oninputsearch(e: InputEvent) {\n e.stopPropagation()\n e.preventDefault()\n\n this.searchKeyword = (e.target as HTMLInputElement).value\n }\n\n protected _onchangesearch(e: InputEvent) {\n e.stopPropagation()\n this.searchKeyword = (e.target as HTMLInputElement).value\n }\n\n protected _onkeydownsearch(e: KeyboardEvent) {\n const keys = ['Esc', 'Escape', 'Up', 'ArrowUp', 'Down', 'ArrowDown']\n if (!keys.includes(e.key)) {\n e.stopPropagation()\n }\n\n /* Enter picks from the search box: the first match once something is typed, the active option before that. */\n if (e.key === 'Enter' && !e.isComposing) {\n e.preventDefault()\n const visible = Array.from(this.querySelectorAll(':scope > [option]:not([hidden])'))\n const active = this.querySelector(':scope > [option][active]:not([hidden])')\n const option = this.searchKeyword ? visible[0] : active || visible[0]\n if (option) {\n this.setActive(option, true)\n this.select()\n }\n }\n }\n\n protected _onkeydown: (e: KeyboardEvent) => void = function (this: OxPopupList, e: KeyboardEvent) {\n e.stopPropagation()\n\n switch (e.key) {\n case 'Esc': // for IE/Edge\n case 'Escape':\n this.close()\n break\n\n case 'Left': // for IE/Edge\n case 'ArrowLeft':\n case 'Up': // for IE/Edge\n case 'ArrowUp':\n this.activeIndex!--\n break\n\n case 'Right': // for IE/Edge\n case 'ArrowRight':\n case 'Down': // for IE/Edge\n case 'ArrowDown':\n this.activeIndex!++\n break\n\n case 'Enter':\n case ' ':\n case 'Spacebar': // for old firefox\n this.setActive(this.activeIndex!, true)\n this.select()\n break\n }\n }.bind(this)\n\n protected _onfocusout: (e: FocusEvent) => void = function (this: OxPopupList, e: FocusEvent) {\n const to = e.relatedTarget as HTMLElement\n\n if (!this.contains(to)) {\n /* If the focus has clearly moved to an element outside of my range, the ox-popup-list should be closed. */\n // @ts-ignore for debug\n !this.preventCloseOnBlur && !this.debug && !window.POPUP_DEBUG && this.close()\n }\n }.bind(this)\n\n protected _onclick: (e: MouseEvent) => void = function (this: OxPopupList, e: MouseEvent) {\n e.stopPropagation()\n\n // Check if the click event target is a checkbox\n if ((e.target as HTMLElement).closest('input[type=\"checkbox\"]')) {\n return // Do not proceed if it's a checkbox click\n }\n\n const option = (e.target as HTMLElement)?.closest('[option]')\n if (option) {\n this.setActive(option, true)\n this.select()\n }\n }.bind(this)\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('activeIndex')) {\n this.activeIndex !== undefined && this.setActive(this.activeIndex)\n }\n\n if (changes.has('sortable')) {\n this.sortableObject && this.sortableObject.destroy()\n\n if (this.sortable) {\n this.sortableObject = Sortable.create(this, {\n handle: '[option]',\n draggable: '[option]',\n direction: 'vertical',\n animation: 150,\n touchStartThreshold: 10,\n onEnd: e => {\n this.locked = false\n this.dispatchEvent(\n new CustomEvent('sorted', {\n detail: Array.from(this.querySelectorAll('[option]'))\n })\n )\n },\n onMove: e => {\n // Check if the drag event target is a checkbox\n if ((e.dragged as HTMLElement).querySelector('input[type=\"checkbox\"]')) {\n return false // Prevent sorting if it's a checkbox drag\n }\n this.locked = true\n }\n })\n }\n }\n\n if (changes.has('searchKeyword')) {\n const attrSelected = this.attrSelected || 'selected'\n this.querySelectorAll(`[option]`).forEach(item => {\n if (!this.searchKeyword || item.textContent?.match(new RegExp(this.searchKeyword, 'i'))) {\n item.removeAttribute('hidden')\n } else {\n item.removeAttribute('selected')\n item.setAttribute('hidden', '')\n }\n })\n this.nothingToSelect = this.querySelectorAll(`[option]:not([hidden])`).length === 0\n }\n\n if (changes.has('value')) this.markSelected()\n }\n\n /** Marks the options holding the value. */\n private markSelected() {\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n var values = this.value\n if (!(values instanceof Array)) {\n values = [values as string]\n }\n\n options.forEach(option => {\n if (values?.includes((option as HTMLElement).getAttribute('value') || '')) {\n option.setAttribute(this.attrSelected || 'selected', '')\n } else {\n option.removeAttribute(this.attrSelected || 'selected')\n }\n })\n }\n\n /**\n * Options can arrive after the value - choices read from the server. They are marked when they arrive, and the\n * owner is told so it can show the chosen label instead of the raw value.\n */\n private optionsChanged() {\n this.markSelected()\n this.dispatchEvent(new CustomEvent('options-change', { bubbles: true }))\n }\n\n /**\n * Retrieves the labels of the selected options in the popup list.\n * If multiple selections are allowed, an array of labels is returned. Otherwise, a single label is returned.\n * @returns {string|string[]} The label(s) of the selected option(s).\n */\n public getSelectedLabels(): string | string[] {\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n const selected = options\n .filter(option => option.hasAttribute('value') && option.hasAttribute(this.attrSelected || 'selected'))\n .map(option => option.textContent || '')\n\n return this.multiple ? selected : selected[0]\n }\n\n /**\n * Handles the selection of options in the popup list and dispatches a 'select' event with the selected value(s).\n * If multiple selections are allowed, an array of selected values is dispatched; otherwise, a single value is dispatched.\n * Also, it checks whether the selected option should remain alive and whether the popup should be closed.\n */\n async select() {\n await this.updateComplete\n\n const options = Array.from(this.querySelectorAll(':scope > [option]'))\n\n const selected = options\n .filter(option => option.hasAttribute('value') && option.hasAttribute(this.attrSelected || 'selected'))\n .map(option => option.getAttribute('value'))\n\n this.dispatchEvent(\n new CustomEvent('select', {\n bubbles: true,\n composed: true,\n detail: this.multiple ? selected : selected[0]\n })\n )\n\n const option = options[this.activeIndex!]\n if (!option.hasAttribute('alive-on-select') && !this.hasAttribute('multiple')) {\n this.close()\n }\n }\n\n /**\n * Sets the active option within the popup list based on the given index or Element.\n * If 'withSelect' is true, it also manages the selection state of the option.\n *\n * @param {number | Element | null} active - The index or Element of the option to set as active.\n * @param {boolean | undefined} withSelect - Indicates whether to manage the selection state of the option.\n */\n setActive(active: number | Element | null, withSelect?: boolean) {\n var options = Array.from(this.querySelectorAll('[option]:not([hidden])'))\n if (this.withSearch) {\n options.push(this.renderRoot.querySelector('[search]')!)\n }\n\n if (active instanceof Element) {\n const index = options.findIndex(option => option === active)\n this.setActive(index === -1 ? 0 : index, withSelect)\n return\n }\n\n const attrSelected = this.attrSelected || 'selected'\n\n options.forEach(async (option, index) => {\n if (typeof active === 'number' && index === (active + options.length) % options.length) {\n option.setAttribute('active', '')\n\n if (withSelect && !this.attrSelected) {\n /* being set attribute attrs-selected means, that element should know how to do when event happened. */\n this.multiple ? option.toggleAttribute('selected') : option.setAttribute('selected', '')\n }\n\n guaranteeFocus(option as HTMLElement)\n\n this.activeIndex = index\n } else {\n option.removeAttribute('active')\n /* even thought attribute attrs-selected set, ox-popup-list have to unset others. */\n !this.multiple && withSelect && option.removeAttribute(attrSelected)\n }\n })\n }\n\n /**\n * Overrides the 'open' method of the base class 'OxPopup' to set the initial active index\n * when the popup list is opened. It ensures that an option is initially selected for user interaction.\n *\n * @param {object} params - The parameters for opening the popup, including position and size.\n */\n override open(params: {\n left?: number\n top?: number\n right?: number\n bottom?: number\n width?: string\n height?: string\n silent?: boolean\n // fixed?: boolean\n anchorTop?: number\n }) {\n super.open(params)\n\n if (this.activeIndex === undefined) {\n const activeElement = this.querySelector(`[${this.attrSelected || 'selected'}]`)\n this.setActive(activeElement || 0)\n } else {\n this.setActive(this.activeIndex)\n }\n\n /* A searchable list opens ready to type, with the last search cleared. */\n if (this.withSearch) {\n this.searchKeyword = ''\n this.updateComplete.then(() => {\n if (!this.searchInput) return\n this.searchInput.value = ''\n this.searchInput.focus()\n })\n }\n }\n\n /* The popup takes the focus when it opens and again a frame after it is attached; a searchable list gives it to the search box. */\n override guaranteeFocus(target?: HTMLElement) {\n if (!target && this.withSearch && this.searchInput) {\n this.searchInput.focus()\n return\n }\n super.guaranteeFocus(target)\n }\n\n /**\n * Overrides the 'close' method of the base class 'OxPopup' to dispatch a custom event\n * indicating that the popup list is being closed. This event can be used for further interactions\n * or logic in the application.\n */\n override close() {\n if (this.locked) {\n return\n }\n\n if (this.hasAttribute('active')) {\n this.dispatchEvent(\n new CustomEvent('close', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n super.close()\n }\n\n /**\n * Open OxPopup\n *\n * @param {PopupOpenOptions}\n */\n static open({\n template,\n top,\n left,\n right,\n bottom,\n parent,\n multiple,\n sortable,\n attrSelected,\n styles,\n debug\n }: {\n template: unknown\n top?: number\n left?: number\n right?: number\n bottom?: number\n parent?: Element | null\n multiple?: boolean\n sortable?: boolean\n debug?: boolean\n attrSelected?: string\n styles?: CSSResult\n }): OxPopupList {\n const target = document.createElement('ox-popup-list') as OxPopupList\n\n if (styles) {\n const style = document.createElement('style')\n style.textContent = styles.cssText\n\n const shadow = target.attachShadow({ mode: 'open' })\n shadow.appendChild(style)\n }\n\n if (!!debug) {\n target.setAttribute('debug', '')\n }\n\n if (!!multiple) {\n target.setAttribute('multiple', '')\n }\n\n if (!!sortable) {\n target.setAttribute('sortable', '')\n }\n\n if (attrSelected) {\n target.setAttribute('attr-selected', attrSelected)\n }\n\n render(template, target)\n\n if (parent) {\n var { left, top, right, bottom } = convertToFixedPosition({\n left,\n top,\n right,\n bottom,\n relativeElement: parent as HTMLElement\n })\n }\n\n document.body.appendChild(target)\n target.removeAfterUse = true\n target.open({ top, left, right, bottom })\n\n return target\n }\n}\n"]}
|
package/dist/src/ox-popup.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export declare class OxPopup extends LitElement {
|
|
|
19
19
|
backdrop: boolean;
|
|
20
20
|
private lastActive;
|
|
21
21
|
protected removeAfterUse: boolean;
|
|
22
|
+
/** The height its opener gave it in `style` (OxPopup.open): where every opening starts, before any cut. */
|
|
23
|
+
protected askedHeight: {
|
|
24
|
+
height: string;
|
|
25
|
+
maxHeight: string;
|
|
26
|
+
};
|
|
22
27
|
render(): import("lit-html").TemplateResult<1>;
|
|
23
28
|
protected _onfocusout: (e: FocusEvent) => void;
|
|
24
29
|
protected _onkeydown: (e: KeyboardEvent) => void;
|
|
@@ -72,8 +77,10 @@ export declare class OxPopup extends LitElement {
|
|
|
72
77
|
* @param {string} options.height - The maximum height of the popup (CSS string). For example, '200px'.
|
|
73
78
|
* @param {boolean} [options.silent=false] - A flag indicating whether the popup should auto-focus or not. If set to true, the popup won't attempt to focus on any element.
|
|
74
79
|
* @param {boolean} [options.fixed=false] - A flag indicating whether the popup should be positioned fixed relative to the viewport. If set to true, the popup will be fixed.
|
|
80
|
+
* @param {number} [options.anchorTop] - Where the element the popup opens under begins, in the same terms as `top` (which is where it ends).
|
|
81
|
+
* A popup with too little room below opens above that line instead. Without it, `top` is a point.
|
|
75
82
|
*/
|
|
76
|
-
open({ left, top, right, bottom, width, height, silent, fixed }: {
|
|
83
|
+
open({ left, top, right, bottom, width, height, silent, fixed, anchorTop }: {
|
|
77
84
|
left?: number;
|
|
78
85
|
top?: number;
|
|
79
86
|
right?: number;
|
|
@@ -82,7 +89,15 @@ export declare class OxPopup extends LitElement {
|
|
|
82
89
|
height?: string;
|
|
83
90
|
silent?: boolean;
|
|
84
91
|
fixed?: boolean;
|
|
92
|
+
anchorTop?: number;
|
|
85
93
|
}): void;
|
|
94
|
+
/**
|
|
95
|
+
* A popup opened downward from a line - the bottom of its select, or a point - never covers that line or what is
|
|
96
|
+
* above it down to `anchorTop`: covered, the select's next press lands on the popup (a double-click in a grid cell
|
|
97
|
+
* picked an option). With too little room below it opens above, if there is more room there; either way it is cut
|
|
98
|
+
* to the room it has and scrolls inside.
|
|
99
|
+
*/
|
|
100
|
+
private keepOffTheLine;
|
|
86
101
|
guaranteeFocus(target?: HTMLElement): void;
|
|
87
102
|
/**
|
|
88
103
|
* Closes the 'ox-popup'.
|