TASK: #109666 - fix bug of container
This commit is contained in:
parent
a4727b4a79
commit
dc18d4783d
|
@ -28,6 +28,7 @@ types/
|
|||
src/components/**/*.d.ts
|
||||
src/components/**/*.js
|
||||
src/components/**/*.js.map
|
||||
src/widgets/**/*.js
|
||||
src/lib/**/*.d.ts
|
||||
src/lib/**/*.js
|
||||
src/lib/**/*.js.map
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
class SlotStyleHandler {
|
||||
regex: {[regStr: string]: RegExp} = {
|
||||
slottedCss: /(?:\:\:slotted\(.*\))[^{]+\{[^}]*\}/g,
|
||||
'::slotted()': /\:\:slotted\(([^\(]+)\)/g,
|
||||
keyframes: /@keyframes[^{]+\{([^{]+\{[^}]*\})*\D*\}/g,
|
||||
}
|
||||
head!: HTMLElement
|
||||
headFirstElement!: ChildNode | null
|
||||
headStyle!: HTMLElement
|
||||
shouldRefresh: boolean = false
|
||||
styles: {[styleName: string]: string} = new Proxy(
|
||||
{},
|
||||
{
|
||||
set: (
|
||||
target: {[styleName: string]: string},
|
||||
prop: string,
|
||||
value: string
|
||||
) => {
|
||||
if (!target[prop] || target[prop] !== value) {
|
||||
target[prop] = value
|
||||
this.shouldRefresh = true
|
||||
}
|
||||
return true
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
processCss(style: string, name: string) {
|
||||
let globalCss = ''
|
||||
style.replace(this.regex.keyframes, (match) => {
|
||||
globalCss += match
|
||||
return ''
|
||||
})
|
||||
style = style.replace(this.regex.slottedCss, (match) => {
|
||||
globalCss += match.replace(this.regex['::slotted()'], name + ' $1')
|
||||
return ''
|
||||
})
|
||||
|
||||
return globalCss
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CSS注入头部<style></style>
|
||||
*
|
||||
* @param {String} style
|
||||
* @param {String} name
|
||||
* @returns
|
||||
*/
|
||||
injectGlobalCss(
|
||||
component: HTMLElement,
|
||||
style: string,
|
||||
name: string,
|
||||
subName = ''
|
||||
) {
|
||||
if (!style) return
|
||||
|
||||
const styleName = subName ? `${name}-${subName}` : name
|
||||
let css = this.processCss(style, name)
|
||||
this.styles[styleName] = css
|
||||
|
||||
if (this.shouldRefresh) {
|
||||
if (!this.head || !this.headFirstElement) {
|
||||
this.head = document.head
|
||||
this.headFirstElement = this.head.firstChild
|
||||
}
|
||||
|
||||
if (!this.headStyle) {
|
||||
this.headStyle = document.createElement('style')
|
||||
if (this.headFirstElement) {
|
||||
this.head.insertBefore(this.headStyle, this.headFirstElement)
|
||||
} else {
|
||||
this.head.appendChild(this.headStyle)
|
||||
}
|
||||
}
|
||||
// 当父节点也是 Web Component时,防止全局注册的 Style 被父节点的
|
||||
// ShadowRoot 隔离,需要再在父节点中插入一份样式
|
||||
if (
|
||||
component.parentNode &&
|
||||
(Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('DocumentFragment') ||
|
||||
Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('ShadowRoot'))
|
||||
) {
|
||||
let scoped = document.createElement('style')
|
||||
scoped.innerHTML = css.trim()
|
||||
component.parentNode.appendChild(scoped)
|
||||
}
|
||||
|
||||
let style = ''
|
||||
for (const styleName in this.styles) {
|
||||
const content = this.styles[styleName]
|
||||
style += content
|
||||
}
|
||||
|
||||
this.headStyle.innerHTML = style
|
||||
this.shouldRefresh = false
|
||||
}
|
||||
}
|
||||
}
|
||||
export default new SlotStyleHandler()
|
|
@ -70,7 +70,7 @@ export default class DockChild {
|
|||
}
|
||||
|
||||
get order() {
|
||||
return Array.from(this.manager.container.children).indexOf(this.master)
|
||||
return Array.from(this.manager.children).indexOf(this.master)
|
||||
}
|
||||
|
||||
synchroniseContainer() {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
:host {
|
||||
// position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-bottom: var(--dock-margin-bottom);
|
||||
width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: auto auto 0;
|
||||
min-width: var(--dock-min-width, 100%);
|
||||
max-width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
::slotted(.dock-child-master) {
|
||||
max-width: var(--dock-grid-width, 92px);
|
||||
max-height: var(--dock-grid-width, 92px);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
::slotted(.dock-child-container) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
}
|
||||
::slotted(.dock-child-container):not(.dragging):not(.added) {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
::slotted(.dock-child-container).dragging {
|
||||
z-index: 1;
|
||||
}
|
||||
`
|
|
@ -1,7 +1,10 @@
|
|||
import {html, css, LitElement, CSSResultGroup} from 'lit'
|
||||
import {html, LitElement} from 'lit'
|
||||
import {customElement, query} from 'lit/decorators.js'
|
||||
import DockChild from './dock-child'
|
||||
import customStyle from './style'
|
||||
import dockStyle from './dock-styles'
|
||||
import slotStyleHandler from './SlotStyleHandler'
|
||||
|
||||
interface DragAndDrop {
|
||||
// Whether drag-and-drop is enabled
|
||||
enabled: boolean
|
||||
|
@ -65,6 +68,7 @@ const STATE_CHANGE_TIMEOUT = 100
|
|||
export default class StarDock extends LitElement {
|
||||
@query('#container') container!: HTMLElement
|
||||
|
||||
name: string = 'star-dock'
|
||||
_children: DockChild[] = []
|
||||
_sortMode: Boolean = false
|
||||
_dragInElement: HTMLElement | undefined
|
||||
|
@ -120,7 +124,7 @@ export default class StarDock extends LitElement {
|
|||
const child =
|
||||
this.getChildByElement(element) || new DockChild(element, this)
|
||||
this._children.push(child)
|
||||
this.container.appendChild(child.master)
|
||||
this.appendChild(child.master)
|
||||
if (typeof order == 'number') {
|
||||
child.order = order
|
||||
}
|
||||
|
@ -141,15 +145,15 @@ export default class StarDock extends LitElement {
|
|||
|
||||
realInsertBefore = (element: HTMLElement, reference: HTMLElement) => {
|
||||
element.style.order = reference.style.order
|
||||
this.container.insertBefore(element, reference)
|
||||
this.insertBefore(element, reference)
|
||||
}
|
||||
|
||||
realInsertAfter = (element: HTMLElement, reference: HTMLElement) => {
|
||||
element.style.order = reference.style.order
|
||||
if (reference.nextSibling) {
|
||||
this.container.insertBefore(element, reference.nextElementSibling)
|
||||
this.insertBefore(element, reference.nextElementSibling)
|
||||
} else {
|
||||
this.container.appendChild(element)
|
||||
this.appendChild(element)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
@ -164,24 +168,28 @@ export default class StarDock extends LitElement {
|
|||
child.master.style.order = String(child.order)
|
||||
} else if (+child.master.style.order !== child.order) {
|
||||
const insertedMaster =
|
||||
this.container.children[+child.master.style.order]
|
||||
this.children[+child.master.style.order]
|
||||
if (insertedMaster) {
|
||||
this.container.insertBefore(child.master, insertedMaster)
|
||||
this.insertBefore(child.master, insertedMaster)
|
||||
}
|
||||
}
|
||||
child.synchroniseContainer()
|
||||
}
|
||||
|
||||
this.reorderChild()
|
||||
this.recorderChild()
|
||||
if (this._children.length) {
|
||||
this._gridSize = this._children[0].master.offsetWidth
|
||||
}
|
||||
}
|
||||
|
||||
reorderChild() {
|
||||
recorderChild() {
|
||||
let children: DockChild[] = []
|
||||
let _children = [...this._children]
|
||||
const childrenElements = [...this.container.children]
|
||||
const childrenElements = [...this.children]
|
||||
|
||||
if (!_children.length || !childrenElements.length) {
|
||||
return
|
||||
}
|
||||
for (const childElement of childrenElements) {
|
||||
let child!: DockChild
|
||||
_children = _children.filter((item) => {
|
||||
|
@ -191,8 +199,7 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
return true
|
||||
})
|
||||
|
||||
children.push(child)
|
||||
child && children.push(child)
|
||||
}
|
||||
|
||||
this._children = children
|
||||
|
@ -406,6 +413,7 @@ export default class StarDock extends LitElement {
|
|||
'px)'
|
||||
|
||||
if (!dropChild) {
|
||||
// this._children.pop()
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -418,19 +426,17 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
} else if (dropChild === this.container) {
|
||||
if (this._children.length && this._children[0].center.x > centerX) {
|
||||
if (this.container.firstElementChild == this._dragChild!.master)
|
||||
return true
|
||||
if (this.firstElementChild == this._dragChild!.master) return true
|
||||
|
||||
this.realInsertBefore(
|
||||
this._dragChild?.master!,
|
||||
this._children[0].master
|
||||
)
|
||||
} else {
|
||||
if (this.container.lastElementChild == this._dragChild!.master)
|
||||
return true
|
||||
if (this.lastElementChild == this._dragChild!.master) return true
|
||||
|
||||
this._dragChild!.order = this._children.length
|
||||
this.container.appendChild(this._dragChild?.master!)
|
||||
this.appendChild(this._dragChild?.master!)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,11 +618,12 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
this.container.addEventListener('touchstart', this)
|
||||
this.container.addEventListener('click', this)
|
||||
this.container.addEventListener('touchmove', this)
|
||||
this.container.addEventListener('touchend', this)
|
||||
this.container.addEventListener('touchcancel', this)
|
||||
slotStyleHandler.injectGlobalCss(this, dockStyle.cssText, this.name)
|
||||
this.addEventListener('touchstart', this)
|
||||
this.addEventListener('click', this)
|
||||
this.addEventListener('touchmove', this)
|
||||
this.addEventListener('touchend', this)
|
||||
this.addEventListener('touchcancel', this)
|
||||
|
||||
this.resize()
|
||||
}
|
||||
|
@ -667,7 +674,7 @@ export default class StarDock extends LitElement {
|
|||
child.container.addEventListener('animationstart', animStart)
|
||||
child.container.classList.add(state)
|
||||
|
||||
child[state] = window.window.setTimeout(() => {
|
||||
child[state] = window.setTimeout(() => {
|
||||
delete child[state]
|
||||
child.container.removeEventListener('animationstart', animStart)
|
||||
child.container.classList.remove(state)
|
||||
|
@ -679,52 +686,12 @@ export default class StarDock extends LitElement {
|
|||
|
||||
protected render() {
|
||||
return html`
|
||||
<div id="container"></div>
|
||||
<div id="container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
static styles?: CSSResultGroup | undefined = [
|
||||
customStyle,
|
||||
css`
|
||||
:host {
|
||||
// position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-bottom: var(--dock-margin-bottom);
|
||||
width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: auto auto 0;
|
||||
min-width: var(--dock-min-width, 100%);
|
||||
max-width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
.dock-child-master {
|
||||
max-width: var(--dock-grid-width, 92px);
|
||||
max-height: var(--dock-grid-width, 92px);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dock-child-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
}
|
||||
.dock-child-container:not(.dragging):not(.added) {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.dock-child-container.dragging {
|
||||
z-index: 1;
|
||||
}
|
||||
`,
|
||||
]
|
||||
static styles = [customStyle, dockStyle]
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
|
|
@ -803,12 +803,14 @@ class GaiaContainer extends StarBaseElement {
|
|||
* @param {Object} options 所添加元素的尺寸信息和添加回调
|
||||
*/
|
||||
appendContainerChild(element: HTMLElement, options?: ChildElementInfo) {
|
||||
if (element.tagName === 'GAIA-WIDGET') {
|
||||
if (element.tagName.split('-').length > 1) {
|
||||
let obj: ChildElementInfo = options
|
||||
? {...options}
|
||||
: ({} as ChildElementInfo)
|
||||
if ((element as any).size) {
|
||||
obj.row = (element as any).size[0]
|
||||
obj.column = (element as any).size[1]
|
||||
}
|
||||
this.insertContainerBefore(element, null, obj)
|
||||
} else {
|
||||
this.insertContainerBefore(element, null, options)
|
||||
|
@ -1239,10 +1241,10 @@ class GaiaContainer extends StarBaseElement {
|
|||
|
||||
cancelDrag() {
|
||||
this.dataset.dragging = 'false'
|
||||
if (this._dnd.timeout !== null) {
|
||||
/* if (this._dnd.timeout !== null) {
|
||||
clearTimeout(this._dnd.timeout)
|
||||
this._dnd.timeout = undefined
|
||||
}
|
||||
} */
|
||||
|
||||
if (this._dnd.moveTimeout !== null) {
|
||||
clearTimeout(this._dnd.moveTimeout)
|
||||
|
@ -1861,14 +1863,14 @@ class GaiaContainer extends StarBaseElement {
|
|||
composed: true,
|
||||
})
|
||||
)
|
||||
} else if (this._dnd.timeout !== null && this._dnd.child?.isFolder) {
|
||||
} else if (/* this._dnd.timeout !== null && */ this._dnd.child?.isFolder) {
|
||||
this._dnd.child.open()
|
||||
} else if (
|
||||
!(
|
||||
this.status & // 不处于四种状态的任何一种时,才可以发送 activate 事件
|
||||
(STATUS.DRAG | STATUS.SWIPE | STATUS.TURN | STATUS.SORT)
|
||||
) &&
|
||||
this._dnd.timeout !== null &&
|
||||
// this._dnd.timeout !== null &&
|
||||
this._dnd.child?.element
|
||||
) {
|
||||
let handled = !this.dispatchEvent(
|
||||
|
@ -1910,7 +1912,7 @@ class GaiaContainer extends StarBaseElement {
|
|||
// 拖拽节点所处位置
|
||||
dragPosition: 'inner' | 'outter' = 'inner'
|
||||
// 翻页控制事件
|
||||
turnEvent: 'holdmove' | 'panmove' | undefined
|
||||
turnEvent: string | undefined
|
||||
handleEvent(event: CustomEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
|
@ -2128,7 +2130,7 @@ class GaiaContainer extends StarBaseElement {
|
|||
|
||||
handleMove(event: CustomEvent) {
|
||||
if (!this.turnEvent || this.turnEvent == event.type) {
|
||||
this.turnEvent = (event.type as 'holdmove' | 'panmove')
|
||||
this.turnEvent = event.type
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
@ -2170,7 +2172,7 @@ class GaiaContainer extends StarBaseElement {
|
|||
}
|
||||
|
||||
handleEnd(event: CustomEvent) {
|
||||
if (this.turnEvent == event.type) {
|
||||
if (this.turnEvent?.replace('move', 'end') == event.type) {
|
||||
this.turnEvent = undefined
|
||||
} else {
|
||||
return
|
||||
|
|
|
@ -236,14 +236,13 @@ export class PanelContainer extends LitElement {
|
|||
|
||||
// 此时的拖拽进 container 组件的标志才意味着是否成功放置成功
|
||||
if (this.dragInContainer) {
|
||||
this.dock.removeContainerChild(evt.detail.target)
|
||||
if (this.container._dnd.child) {
|
||||
this.container._dnd.child.element = evt.detail.target
|
||||
this.container._dnd.child.container.classList.remove('dragging')
|
||||
this.container._dnd.child = undefined
|
||||
this.container.synchronise()
|
||||
}
|
||||
|
||||
this.dock.removeContainerChild(evt.detail.target)
|
||||
} else {
|
||||
this.container.removeContainerChild(this.elementPlaceholder)
|
||||
}
|
||||
|
@ -409,6 +408,12 @@ export class PanelContainer extends LitElement {
|
|||
height: 2px;
|
||||
background-color: pink;
|
||||
}
|
||||
|
||||
star-dock .dock-child-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
`,
|
||||
homescreenStyle,
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue