@operato/popup
Advanced tools
Comparing version 2.0.0-alpha.118 to 2.0.0-alpha.120
@@ -6,2 +6,11 @@ # Change Log | ||
## [2.0.0-alpha.120](https://github.com/hatiolab/operato/compare/v2.0.0-alpha.119...v2.0.0-alpha.120) (2024-05-05) | ||
### :rocket: New Features | ||
* add personalConfigProvider property for ox-grist ([b5804ae](https://github.com/hatiolab/operato/commit/b5804aeb3e57e60856847600b6390112650880fa)) | ||
## [2.0.0-alpha.118](https://github.com/hatiolab/operato/compare/v2.0.0-alpha.117...v2.0.0-alpha.118) (2024-05-04) | ||
@@ -8,0 +17,0 @@ |
@@ -26,2 +26,8 @@ import '@material/web/icon/icon.js'; | ||
/** | ||
* A boolean property that, when set to true, enables the drag-and-drop sorting functionality within the popup list. | ||
* This allows users to reorder the options in the list by dragging them into new positions. | ||
* @type {boolean|undefined} | ||
*/ | ||
sortable?: boolean; | ||
/** | ||
* The value(s) of the selected option(s) in the popup list. | ||
@@ -36,2 +42,5 @@ * This property can be a string or an array of strings, depending on whether multiple selections are allowed. | ||
searchInput: HTMLInputElement; | ||
body: HTMLDivElement; | ||
private sortableObject?; | ||
private locked; | ||
render(): import("lit-html").TemplateResult<1>; | ||
@@ -91,3 +100,3 @@ protected _oninputsearch(e: InputEvent): void; | ||
*/ | ||
static open({ template, top, left, right, bottom, parent, multiple, attrSelected, styles }: { | ||
static open({ template, top, left, right, bottom, parent, multiple, sortable, attrSelected, styles, debug }: { | ||
template: unknown; | ||
@@ -100,2 +109,4 @@ top?: number; | ||
multiple?: boolean; | ||
sortable?: boolean; | ||
debug?: boolean; | ||
attrSelected?: string; | ||
@@ -102,0 +113,0 @@ styles: CSSResult; |
@@ -6,2 +6,3 @@ import { __decorate } from "tslib"; | ||
import { customElement, property, query, state } from 'lit/decorators.js'; | ||
import Sortable from 'sortablejs'; | ||
import { OxPopup } from './ox-popup'; | ||
@@ -31,3 +32,10 @@ function guaranteeFocus(element) { | ||
this.multiple = false; | ||
/** | ||
* A boolean property that, when set to true, enables the drag-and-drop sorting functionality within the popup list. | ||
* This allows users to reorder the options in the list by dragging them into new positions. | ||
* @type {boolean|undefined} | ||
*/ | ||
this.sortable = false; | ||
this.nothingToSelect = false; | ||
this.locked = false; | ||
this._onkeydown = function (e) { | ||
@@ -65,3 +73,3 @@ e.stopPropagation(); | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close(); | ||
!this.debug && !window.POPUP_DEBUG && this.close(); | ||
} | ||
@@ -106,8 +114,11 @@ }.bind(this); | ||
<slot | ||
@change=${(e) => { | ||
<div body> | ||
<slot | ||
@change=${(e) => { | ||
e.stopPropagation(); | ||
}} | ||
> | ||
</slot> | ||
> | ||
</slot> | ||
</div> | ||
${this.nothingToSelect ? html `<label nothing>nothing to select</label>` : html ``} | ||
@@ -135,2 +146,23 @@ `; | ||
} | ||
if (changes.has('sortable')) { | ||
this.sortableObject && this.sortableObject.destroy(); | ||
if (this.sortable) { | ||
this.sortableObject = Sortable.create(this, { | ||
handle: '[option]', | ||
draggable: '[option]', | ||
direction: 'vertical', | ||
animation: 150, | ||
touchStartThreshold: 10, | ||
onEnd: e => { | ||
this.locked = false; | ||
this.dispatchEvent(new CustomEvent('sorted', { | ||
detail: Array.from(this.querySelectorAll('[option]')) | ||
})); | ||
}, | ||
onMove: e => { | ||
this.locked = true; | ||
} | ||
}); | ||
} | ||
} | ||
if (changes.has('searchKeyword')) { | ||
@@ -255,2 +287,5 @@ const attrSelected = this.attrSelected || 'selected'; | ||
close() { | ||
if (this.locked) { | ||
return; | ||
} | ||
if (this.hasAttribute('active')) { | ||
@@ -269,3 +304,3 @@ this.dispatchEvent(new CustomEvent('close', { | ||
*/ | ||
static open({ template, top, left, right, bottom, parent, multiple, attrSelected, styles }) { | ||
static open({ template, top, left, right, bottom, parent, multiple, sortable, attrSelected, styles, debug }) { | ||
const owner = parent || document.body; | ||
@@ -279,5 +314,11 @@ const target = document.createElement('ox-popup-list'); | ||
} | ||
if (!!debug) { | ||
target.setAttribute('debug', ''); | ||
} | ||
if (!!multiple) { | ||
target.setAttribute('multiple', ''); | ||
} | ||
if (!!sortable) { | ||
target.setAttribute('sortable', ''); | ||
} | ||
if (attrSelected) { | ||
@@ -298,8 +339,3 @@ target.setAttribute('attr-selected', attrSelected); | ||
display: none; | ||
flex-direction: column; | ||
align-items: stretch; | ||
background-color: var(--theme-white-color, #fff); | ||
z-index: 100; | ||
box-shadow: 2px 3px 10px 5px rgba(0, 0, 0, 0.15); | ||
padding: 4px 0; | ||
color: var(--theme-primary-text-color, #3c3938); | ||
@@ -313,2 +349,3 @@ font: | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
@@ -355,2 +392,3 @@ | ||
} | ||
::slotted([option] > input) { | ||
@@ -399,2 +437,11 @@ border: var(--border-dark-color, 1px solid rgba(0, 0, 0, 0.3)); | ||
} | ||
div[body] { | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
margin: 0; | ||
padding: 0; | ||
overflow: auto; | ||
} | ||
` | ||
@@ -406,8 +453,11 @@ ]; | ||
__decorate([ | ||
property({ type: String, attribute: 'attr-selected' }) | ||
property({ type: String, attribute: 'attr-selected', reflect: true }) | ||
], OxPopupList.prototype, "attrSelected", void 0); | ||
__decorate([ | ||
property({ type: Boolean, attribute: 'with-search' }) | ||
property({ type: Boolean, attribute: 'with-search', reflect: true }) | ||
], OxPopupList.prototype, "withSearch", void 0); | ||
__decorate([ | ||
property({ type: Boolean, attribute: 'sortable', reflect: true }) | ||
], OxPopupList.prototype, "sortable", void 0); | ||
__decorate([ | ||
property({ type: String }) | ||
@@ -427,2 +477,5 @@ ], OxPopupList.prototype, "value", void 0); | ||
], OxPopupList.prototype, "searchInput", void 0); | ||
__decorate([ | ||
query('div[body]') | ||
], OxPopupList.prototype, "body", void 0); | ||
OxPopupList = __decorate([ | ||
@@ -429,0 +482,0 @@ customElement('ox-popup-list') |
@@ -13,2 +13,3 @@ import { LitElement } from 'lit'; | ||
static styles: import("lit").CSSResult[]; | ||
debug: boolean; | ||
_parent: Element | null; | ||
@@ -15,0 +16,0 @@ private lastActive; |
import { __decorate } from "tslib"; | ||
import { css, html, LitElement } from 'lit'; | ||
import { render } from 'lit-html'; | ||
import { customElement, state } from 'lit/decorators.js'; | ||
import { customElement, property, state } from 'lit/decorators.js'; | ||
import { ScrollbarStyles } from '@operato/styles'; | ||
@@ -18,2 +18,3 @@ /** | ||
super(...arguments); | ||
this.debug = false; | ||
this._parent = null; | ||
@@ -26,3 +27,3 @@ this.lastActive = document.activeElement; | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close(); | ||
!this.debug && !window.POPUP_DEBUG && this.close(); | ||
} | ||
@@ -64,3 +65,3 @@ }.bind(this); | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close(); | ||
!this.debug && !window.POPUP_DEBUG && this.close(); | ||
}.bind(this); | ||
@@ -164,3 +165,3 @@ } | ||
// To prevent pop-ups from crossing screen boundaries, use the | ||
// const computedStyle = getComputedStyle(this) | ||
const computedStyle = getComputedStyle(this); | ||
if (t < 0) { | ||
@@ -171,15 +172,17 @@ this.style.top = '10px'; | ||
else if (vh < t + h) { | ||
// this.style.top = `calc(${computedStyle.top} - ${t + h - vh - 20}px)` // 현재의 top 값에 차감한다. | ||
this.style.top = ''; | ||
this.style.bottom = '10px'; | ||
this.style.top = `calc(${computedStyle.top} - ${t + h - vh + 10}px)`; // 현재의 top 값에 차감한다. | ||
this.style.bottom = ''; | ||
// this.style.top = '' | ||
// this.style.bottom = '10px' | ||
} | ||
if (l < 0) { | ||
// this.style.left = `calc(${computedStyle.left} - ${l - 20}px)` // 현재의 left 값에 l를 차감한다. (왼쪽으로 이탈했기 때문에 오른쪽으로 가야 화면에 보임) | ||
this.style.left = '10px'; | ||
this.style.left = `calc(${computedStyle.left} - ${l - 10}px)`; // 현재의 left 값에 l를 차감한다. (왼쪽으로 이탈했기 때문에 오른쪽으로 가야 화면에 보임) | ||
// this.style.left = '10px' | ||
this.style.right = ''; | ||
} | ||
else if (vw < l + w) { | ||
// this.style.left = `calc(${computedStyle.left} - ${l + w - vw + 20}px)` // 현재의 left 값에 차감한다. | ||
this.style.left = ''; | ||
this.style.right = '10px'; | ||
this.style.left = `calc(${computedStyle.left} - ${l + w - vw + 10}px)`; // 현재의 left 값에 차감한다. | ||
this.style.right = ''; | ||
// this.style.left = '' | ||
// this.style.right = '10px' | ||
} | ||
@@ -244,3 +247,3 @@ }); | ||
:host([active]) { | ||
display: block; | ||
display: flex; | ||
} | ||
@@ -254,2 +257,5 @@ | ||
__decorate([ | ||
property({ type: Boolean }) | ||
], OxPopup.prototype, "debug", void 0); | ||
__decorate([ | ||
state() | ||
@@ -256,0 +262,0 @@ ], OxPopup.prototype, "_parent", void 0); |
@@ -5,3 +5,3 @@ { | ||
"author": "heartyoh", | ||
"version": "2.0.0-alpha.118", | ||
"version": "2.0.0-alpha.120", | ||
"main": "dist/src/index.js", | ||
@@ -84,2 +84,3 @@ "module": "dist/src/index.js", | ||
"prettier": "^3.2.5", | ||
"sortablejs": "^1.15.2", | ||
"tslib": "^2.3.1", | ||
@@ -101,3 +102,3 @@ "typescript": "^5.0.4" | ||
}, | ||
"gitHead": "78a0819daea046dafc63234648df0632f85d7275" | ||
"gitHead": "0b85bb42a80fa8acc1c313cac17733b082f52021" | ||
} |
@@ -6,2 +6,3 @@ import '@material/web/icon/icon.js' | ||
import { customElement, property, query, state } from 'lit/decorators.js' | ||
import Sortable from 'sortablejs' | ||
@@ -37,8 +38,3 @@ import { OxPopup } from './ox-popup' | ||
display: none; | ||
flex-direction: column; | ||
align-items: stretch; | ||
background-color: var(--theme-white-color, #fff); | ||
z-index: 100; | ||
box-shadow: 2px 3px 10px 5px rgba(0, 0, 0, 0.15); | ||
padding: 4px 0; | ||
color: var(--theme-primary-text-color, #3c3938); | ||
@@ -52,2 +48,3 @@ font: | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
@@ -94,2 +91,3 @@ | ||
} | ||
::slotted([option] > input) { | ||
@@ -138,2 +136,11 @@ border: var(--border-dark-color, 1px solid rgba(0, 0, 0, 0.3)); | ||
} | ||
div[body] { | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
margin: 0; | ||
padding: 0; | ||
overflow: auto; | ||
} | ||
` | ||
@@ -152,3 +159,3 @@ ] | ||
*/ | ||
@property({ type: String, attribute: 'attr-selected' }) attrSelected?: string | ||
@property({ type: String, attribute: 'attr-selected', reflect: true }) attrSelected?: string | ||
@@ -160,5 +167,12 @@ /** | ||
*/ | ||
@property({ type: Boolean, attribute: 'with-search' }) withSearch?: boolean | ||
@property({ type: Boolean, attribute: 'with-search', reflect: true }) withSearch?: boolean | ||
/** | ||
* A boolean property that, when set to true, enables the drag-and-drop sorting functionality within the popup list. | ||
* This allows users to reorder the options in the list by dragging them into new positions. | ||
* @type {boolean|undefined} | ||
*/ | ||
@property({ type: Boolean, attribute: 'sortable', reflect: true }) sortable?: boolean = false | ||
/** | ||
* The value(s) of the selected option(s) in the popup list. | ||
@@ -175,3 +189,7 @@ * This property can be a string or an array of strings, depending on whether multiple selections are allowed. | ||
@query('[search] input') searchInput!: HTMLInputElement | ||
@query('div[body]') body!: HTMLDivElement | ||
private sortableObject?: Sortable | ||
private locked: boolean = false | ||
render() { | ||
@@ -204,8 +222,11 @@ return html` | ||
<slot | ||
@change=${(e: Event) => { | ||
e.stopPropagation() | ||
}} | ||
> | ||
</slot> | ||
<div body> | ||
<slot | ||
@change=${(e: Event) => { | ||
e.stopPropagation() | ||
}} | ||
> | ||
</slot> | ||
</div> | ||
${this.nothingToSelect ? html`<label nothing>nothing to select</label>` : html``} | ||
@@ -272,3 +293,3 @@ ` | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close() | ||
!this.debug && !window.POPUP_DEBUG && this.close() | ||
} | ||
@@ -292,2 +313,27 @@ }.bind(this) | ||
if (changes.has('sortable')) { | ||
this.sortableObject && this.sortableObject.destroy() | ||
if (this.sortable) { | ||
this.sortableObject = Sortable.create(this, { | ||
handle: '[option]', | ||
draggable: '[option]', | ||
direction: 'vertical', | ||
animation: 150, | ||
touchStartThreshold: 10, | ||
onEnd: e => { | ||
this.locked = false | ||
this.dispatchEvent( | ||
new CustomEvent('sorted', { | ||
detail: Array.from(this.querySelectorAll('[option]')) | ||
}) | ||
) | ||
}, | ||
onMove: e => { | ||
this.locked = true | ||
} | ||
}) | ||
} | ||
} | ||
if (changes.has('searchKeyword')) { | ||
@@ -438,2 +484,6 @@ const attrSelected = this.attrSelected || 'selected' | ||
override close() { | ||
if (this.locked) { | ||
return | ||
} | ||
if (this.hasAttribute('active')) { | ||
@@ -464,4 +514,6 @@ this.dispatchEvent( | ||
multiple, | ||
sortable, | ||
attrSelected, | ||
styles | ||
styles, | ||
debug | ||
}: { | ||
@@ -475,2 +527,4 @@ template: unknown | ||
multiple?: boolean | ||
sortable?: boolean | ||
debug?: boolean | ||
attrSelected?: string | ||
@@ -490,2 +544,6 @@ styles: CSSResult | ||
if (!!debug) { | ||
target.setAttribute('debug', '') | ||
} | ||
if (!!multiple) { | ||
@@ -495,2 +553,6 @@ target.setAttribute('multiple', '') | ||
if (!!sortable) { | ||
target.setAttribute('sortable', '') | ||
} | ||
if (attrSelected) { | ||
@@ -497,0 +559,0 @@ target.setAttribute('attr-selected', attrSelected) |
import { css, html, LitElement } from 'lit' | ||
import { render } from 'lit-html' | ||
import { customElement, state } from 'lit/decorators.js' | ||
import { customElement, property, state } from 'lit/decorators.js' | ||
@@ -35,3 +35,3 @@ import { ScrollbarStyles } from '@operato/styles' | ||
:host([active]) { | ||
display: block; | ||
display: flex; | ||
} | ||
@@ -45,2 +45,4 @@ | ||
@property({ type: Boolean }) debug: boolean = false | ||
@state() _parent: Element | null = null | ||
@@ -60,3 +62,3 @@ | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close() | ||
!this.debug && !window.POPUP_DEBUG && this.close() | ||
} | ||
@@ -108,3 +110,3 @@ }.bind(this) | ||
// @ts-ignore for debug | ||
!window.POPUP_DEBUG && this.close() | ||
!this.debug && !window.POPUP_DEBUG && this.close() | ||
}.bind(this) | ||
@@ -253,3 +255,3 @@ | ||
// To prevent pop-ups from crossing screen boundaries, use the | ||
// const computedStyle = getComputedStyle(this) | ||
const computedStyle = getComputedStyle(this) | ||
@@ -260,15 +262,17 @@ if (t < 0) { | ||
} else if (vh < t + h) { | ||
// this.style.top = `calc(${computedStyle.top} - ${t + h - vh - 20}px)` // 현재의 top 값에 차감한다. | ||
this.style.top = '' | ||
this.style.bottom = '10px' | ||
this.style.top = `calc(${computedStyle.top} - ${t + h - vh + 10}px)` // 현재의 top 값에 차감한다. | ||
this.style.bottom = '' | ||
// this.style.top = '' | ||
// this.style.bottom = '10px' | ||
} | ||
if (l < 0) { | ||
// this.style.left = `calc(${computedStyle.left} - ${l - 20}px)` // 현재의 left 값에 l를 차감한다. (왼쪽으로 이탈했기 때문에 오른쪽으로 가야 화면에 보임) | ||
this.style.left = '10px' | ||
this.style.left = `calc(${computedStyle.left} - ${l - 10}px)` // 현재의 left 값에 l를 차감한다. (왼쪽으로 이탈했기 때문에 오른쪽으로 가야 화면에 보임) | ||
// this.style.left = '10px' | ||
this.style.right = '' | ||
} else if (vw < l + w) { | ||
// this.style.left = `calc(${computedStyle.left} - ${l + w - vw + 20}px)` // 현재의 left 값에 차감한다. | ||
this.style.left = '' | ||
this.style.right = '10px' | ||
this.style.left = `calc(${computedStyle.left} - ${l + w - vw + 10}px)` // 현재의 left 값에 차감한다. | ||
this.style.right = '' | ||
// this.style.left = '' | ||
// this.style.right = '10px' | ||
} | ||
@@ -275,0 +279,0 @@ }) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
535185
82
6521
18