BUG: #145117 - (star-web-components)为当前页面无足够空间放置拖拽节点添加通知的功能
This commit is contained in:
parent
b4fcee6662
commit
e07eb09692
|
@ -1608,6 +1608,13 @@ export class GaiaContainer extends StarBaseElement {
|
|||
composed: true,
|
||||
})
|
||||
)
|
||||
} else if (this._dnd.isSpanning) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('cross-field', {
|
||||
detail: child,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,13 @@ type PlacedRecorder = {
|
|||
* 7. 为满足规则5,规则6的寻位方向变化以顺时针方向转变,如:上左 → 上右 → 下右 → 下左
|
||||
* 8. 图标节点被另一个图标节点挤占位置时,仅能再去挤占相邻网格的图标的位置(即不允许挤占上下相邻图标)
|
||||
* 9. TODO: 图标被小组件挤压后,优先考虑集体移动到组件的相同的某一个方向上
|
||||
* 10. TODO: 被挤占位置时, 比起就近原则再去挤占其他组件或图标的位置, 应优先寻找可放置的空白位置
|
||||
*
|
||||
* 核心准则:
|
||||
* 1. TODO: 应尽量保证用户放置图标、小组件、应用文件夹的页面、位置不被扰乱
|
||||
* 2. 因拖拽、放置的自由度很高, 应尽量降低用户对一次误操作或者一次不满意操作的纠错成本
|
||||
* 3. TODO: 非必要不应挪动其他与本次换位无关的元素的位置
|
||||
* 4. 除非被主动拖拽, 元素不允许任何跨页放置行为(很明显地, 进行一次跨页操作所需要的时间成本和操作成本远大于页内操作)
|
||||
*/
|
||||
|
||||
enum Directions {
|
||||
|
|
|
@ -65,6 +65,8 @@ export default class GaiaContainerChild {
|
|||
_order: number = -1
|
||||
// 用于记录将会与其进行交换的占位DOM
|
||||
_switch?: HTMLElement
|
||||
// 越界标志
|
||||
breakout: boolean = false
|
||||
|
||||
constructor(
|
||||
element: HTMLElement = document.createElement('div'),
|
||||
|
@ -453,7 +455,15 @@ export default class GaiaContainerChild {
|
|||
this._lastElementHeight = this.element?.offsetHeight!
|
||||
}
|
||||
|
||||
const crossResult = this.manager.exchangeStratege.handleCrossField(
|
||||
this.curGridId,
|
||||
this
|
||||
)
|
||||
|
||||
this.breakout = crossResult.bottom || crossResult.right
|
||||
|
||||
!isActive &&
|
||||
!this.breakout &&
|
||||
!this.container.classList.contains('dragging') &&
|
||||
(container.style.transform = 'translate(' + left + 'px, ' + top + 'px)')
|
||||
return true
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
/** Host
|
||||
---------------------------------------------------------*/
|
||||
|
||||
:host {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
bottom: 13.33vh;
|
||||
border-radius: var(--auto-20px);
|
||||
max-width: 70%;
|
||||
text-align: center;
|
||||
z-index: 100;
|
||||
color: var(--font-main-black, #262626);
|
||||
overflow: hidden;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/** Inner
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.inner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.inner.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
---------------------------------------------------------*/
|
||||
|
||||
.bread {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: var(--auto-24px) var(--auto-32px);
|
||||
box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.15);
|
||||
transform: translateY(100%);
|
||||
font-size: var(--auto-26px);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
color: var(--font-normal-color);
|
||||
|
||||
background: var(--base-normal-bgc);
|
||||
transition: color 0.2s, background 0.2s;
|
||||
}
|
||||
|
||||
.bread.animate-in {
|
||||
animation-name: gaia-toast-enter;
|
||||
animation-fill-mode: forwards;
|
||||
animation-duration: 300ms;
|
||||
}
|
||||
|
||||
.bread.animate-out {
|
||||
animation-name: gaia-toast-leave;
|
||||
animation-duration: 600ms;
|
||||
transform: translateY(0%);
|
||||
}
|
||||
|
||||
@keyframes gaia-toast-enter {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
40% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes gaia-toast-leave {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
:host {
|
||||
}
|
||||
}
|
||||
`
|
|
@ -1,6 +1,9 @@
|
|||
import {html, LitElement, CSSResultArray, TemplateResult} from 'lit'
|
||||
import {html, CSSResultArray} from 'lit'
|
||||
import {customElement, property, query, state} from 'lit/decorators.js'
|
||||
import {sharedStyles} from './toast-styles.js'
|
||||
import {autoPxStyle} from '../base/auto-px-style'
|
||||
import {StarBaseElement} from '../base/star-base-element.js'
|
||||
import style from './style'
|
||||
|
||||
export const toastVariants: ToastVariants[] = [
|
||||
'negative',
|
||||
|
@ -18,17 +21,110 @@ export type ToastVariants =
|
|||
| 'warning'
|
||||
| ''
|
||||
|
||||
enum Direction {
|
||||
top,
|
||||
bottom,
|
||||
}
|
||||
|
||||
interface Options {
|
||||
[prop: string]: string | boolean | undefined
|
||||
direction?: keyof typeof Direction
|
||||
icon?: boolean
|
||||
close?: boolean
|
||||
verline?: boolean
|
||||
do?: boolean
|
||||
information: string
|
||||
}
|
||||
// BUG: 该组件存在 UI 隐患, 因为弹出键盘时, 使用该组件的应用将会被键盘挤压窗口
|
||||
// 导致该组件位置会被推至屏幕上方, 无法避免; 即便不被挤压(如Homescreen), 仍会
|
||||
// 存在被键盘遮挡的情况, 依旧无法避免
|
||||
@customElement('star-toast')
|
||||
export class StarToast extends LitElement {
|
||||
export class StarToast extends StarBaseElement {
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [sharedStyles]
|
||||
return [style, sharedStyles, autoPxStyle]
|
||||
}
|
||||
/* 暂时更改使用: start */
|
||||
constructor(options: Options) {
|
||||
super()
|
||||
Object.assign(this, options)
|
||||
document.body.appendChild(this)
|
||||
this.appended = true
|
||||
}
|
||||
|
||||
@property()
|
||||
public direction: keyof typeof Direction = 'bottom'
|
||||
|
||||
@property({type: Number})
|
||||
get timeout() {
|
||||
return Number(this.getAttribute('timeout')) || 3000
|
||||
}
|
||||
|
||||
set timeout(value) {
|
||||
let current = Number(this.getAttribute('timeout'))
|
||||
|
||||
if (current == value) {
|
||||
return
|
||||
} else if (!value) {
|
||||
this.removeAttribute('timeout')
|
||||
} else {
|
||||
this.setAttribute('timeout', String(value))
|
||||
}
|
||||
}
|
||||
|
||||
appended: boolean = false
|
||||
|
||||
onAnimateOutEnd = (_: any) => {}
|
||||
|
||||
hideTimeout?: number
|
||||
|
||||
@query('.inner') inner!: HTMLElement
|
||||
@query('.bread') bread!: HTMLElement
|
||||
|
||||
show = () => {
|
||||
if (!this.appended) {
|
||||
document.body.appendChild(this)
|
||||
this.appended = true
|
||||
}
|
||||
this.open = true
|
||||
this.bread.removeEventListener('animationend', this.onAnimateOutEnd)
|
||||
clearTimeout(this.hideTimeout)
|
||||
|
||||
this.inner.classList.add('visible')
|
||||
this.bread.classList.remove('animate-out')
|
||||
this.bread.classList.add('animate-in')
|
||||
this.hideTimeout = window.setTimeout(this.hide.bind(this), this.timeout)
|
||||
}
|
||||
|
||||
hide = () => {
|
||||
clearTimeout(this.hideTimeout)
|
||||
this.open = false
|
||||
this.bread.classList.remove('animate-in')
|
||||
this.bread.classList.add('animate-out')
|
||||
|
||||
this.bread.removeEventListener('animationend', this.onAnimateOutEnd)
|
||||
this.onAnimateOutEnd = () => {
|
||||
this.bread.removeEventListener('animationend', this.onAnimateOutEnd)
|
||||
this.bread.classList.remove('animate-out')
|
||||
this.inner.classList.remove('visible')
|
||||
}
|
||||
|
||||
this.bread.addEventListener('animationend', this.onAnimateOutEnd)
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="inner">
|
||||
<div class="bread">${this.information}</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
/* 暂时更改使用: end */
|
||||
|
||||
@state()
|
||||
public open: Boolean = false
|
||||
|
||||
@property({type: Number})
|
||||
private timeout = 5000
|
||||
// @property({type: Number})
|
||||
// private timeout = 5000
|
||||
|
||||
@property({type: String})
|
||||
public variant: ToastVariants = ''
|
||||
|
@ -52,77 +148,77 @@ export class StarToast extends LitElement {
|
|||
@property({type: String})
|
||||
public buttonName = ''
|
||||
|
||||
private renderIcon(): TemplateResult {
|
||||
switch (this.variant) {
|
||||
case 'positive':
|
||||
return html`
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 36 36"
|
||||
role="img"
|
||||
fill="white"
|
||||
aria-hidden="false"
|
||||
aria-label="Success"
|
||||
>
|
||||
<path
|
||||
d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2Zm10.666 9.08L16.018 27.341a1.208 1.208 0 0 1-.875.461c-.024.002-.05.002-.073.002a1.2 1.2 0 0 1-.85-.351l-7.784-7.795a1.2 1.2 0 0 1 0-1.698l1.326-1.325a1.201 1.201 0 0 1 1.695 0l5.346 5.347L25.314 8.473A1.203 1.203 0 0 1 27 8.263l1.455 1.133a1.205 1.205 0 0 1 .211 1.684Z"
|
||||
></path>
|
||||
</svg>
|
||||
`
|
||||
case 'warning':
|
||||
case 'info':
|
||||
return html`
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 36 36"
|
||||
role="img"
|
||||
fill="white"
|
||||
aria-hidden="false"
|
||||
aria-label="Information"
|
||||
>
|
||||
<path
|
||||
d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2Zm-.3 4.3a2.718 2.718 0 0 1 2.864 2.824 2.664 2.664 0 0 1-2.864 2.863 2.705 2.705 0 0 1-2.864-2.864A2.717 2.717 0 0 1 17.7 6.3ZM22 27a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1h1v-6h-1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v9h1a1 1 0 0 1 1 1Z"
|
||||
></path>
|
||||
</svg>
|
||||
`
|
||||
case 'error':
|
||||
case 'negative':
|
||||
default:
|
||||
return html`
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 36 36"
|
||||
role="img"
|
||||
fill="white"
|
||||
aria-hidden="false"
|
||||
aria-label="Error"
|
||||
>
|
||||
<path
|
||||
d="M17.127 2.579.4 32.512A1 1 0 0 0 1.272 34h33.456a1 1 0 0 0 .872-1.488L18.873 2.579a1 1 0 0 0-1.746 0ZM20 29.5a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5Zm0-6a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-12a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5Z"
|
||||
></path>
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
}
|
||||
// private renderIcon() {
|
||||
// switch (this.variant) {
|
||||
// case 'positive':
|
||||
// return html`
|
||||
// <svg
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// viewBox="0 0 36 36"
|
||||
// role="img"
|
||||
// fill="white"
|
||||
// aria-hidden="false"
|
||||
// aria-label="Success"
|
||||
// >
|
||||
// <path
|
||||
// d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2Zm10.666 9.08L16.018 27.341a1.208 1.208 0 0 1-.875.461c-.024.002-.05.002-.073.002a1.2 1.2 0 0 1-.85-.351l-7.784-7.795a1.2 1.2 0 0 1 0-1.698l1.326-1.325a1.201 1.201 0 0 1 1.695 0l5.346 5.347L25.314 8.473A1.203 1.203 0 0 1 27 8.263l1.455 1.133a1.205 1.205 0 0 1 .211 1.684Z"
|
||||
// ></path>
|
||||
// </svg>
|
||||
// `
|
||||
// case 'warning':
|
||||
// case 'info':
|
||||
// return html`
|
||||
// <svg
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// viewBox="0 0 36 36"
|
||||
// role="img"
|
||||
// fill="white"
|
||||
// aria-hidden="false"
|
||||
// aria-label="Information"
|
||||
// >
|
||||
// <path
|
||||
// d="M18 2a16 16 0 1 0 16 16A16 16 0 0 0 18 2Zm-.3 4.3a2.718 2.718 0 0 1 2.864 2.824 2.664 2.664 0 0 1-2.864 2.863 2.705 2.705 0 0 1-2.864-2.864A2.717 2.717 0 0 1 17.7 6.3ZM22 27a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1h1v-6h-1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v9h1a1 1 0 0 1 1 1Z"
|
||||
// ></path>
|
||||
// </svg>
|
||||
// `
|
||||
// case 'error':
|
||||
// case 'negative':
|
||||
// default:
|
||||
// return html`
|
||||
// <svg
|
||||
// xmlns="http://www.w3.org/2000/svg"
|
||||
// viewBox="0 0 36 36"
|
||||
// role="img"
|
||||
// fill="white"
|
||||
// aria-hidden="false"
|
||||
// aria-label="Error"
|
||||
// >
|
||||
// <path
|
||||
// d="M17.127 2.579.4 32.512A1 1 0 0 0 1.272 34h33.456a1 1 0 0 0 .872-1.488L18.873 2.579a1 1 0 0 0-1.746 0ZM20 29.5a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5Zm0-6a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-12a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5Z"
|
||||
// ></path>
|
||||
// </svg>
|
||||
// `
|
||||
// }
|
||||
// }
|
||||
|
||||
protected override render(): TemplateResult {
|
||||
return html`
|
||||
<div open=${this.open} class="toast" id="toast" variant=${this.variant}>
|
||||
<div>
|
||||
<icon icon=${this.icon}>${this.renderIcon()}</icon>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text">${this.information}</span>
|
||||
<do do=${this.do} wraping>Do Something</do>
|
||||
</div>
|
||||
<verline verline=${this.verline}></verline>
|
||||
<close close=${this.close} @click=${this.closeToast}>X</close>
|
||||
</div>
|
||||
<div>
|
||||
<do do="true" click @click=${this.toastChange}>${this.buttonName}</do>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
// protected override render() {
|
||||
// return html`
|
||||
// <div open=${this.open} class="toast" id="toast" variant=${this.variant}>
|
||||
// <div>
|
||||
// <icon icon=${this.icon}>${this.renderIcon()}</icon>
|
||||
// </div>
|
||||
// <div>
|
||||
// <span class="text">${this.information}</span>
|
||||
// <do do=${this.do} wraping>Do Something</do>
|
||||
// </div>
|
||||
// <verline verline=${this.verline}></verline>
|
||||
// <close close=${this.close} @click=${this.closeToast}>X</close>
|
||||
// </div>
|
||||
// <div>
|
||||
// <do do="true" click @click=${this.toastChange}>${this.buttonName}</do>
|
||||
// </div>
|
||||
// `
|
||||
// }
|
||||
|
||||
@query('#toast')
|
||||
toast!: HTMLElement
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
"include": ["*.ts", "../base/*.ts"]
|
||||
}
|
||||
|
|
|
@ -1,13 +1,37 @@
|
|||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
import {sharedStyles} from '../../../components/toast/toast-styles'
|
||||
import '../../../components/button'
|
||||
import {StarToast} from '../../../components/toast'
|
||||
|
||||
@customElement('panel-toast')
|
||||
export class PanelToast extends LitElement {
|
||||
toast: StarToast = new StarToast({information: 'test'})
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [sharedStyles]
|
||||
}
|
||||
|
||||
show() {
|
||||
if (this.toast.open) {
|
||||
this.toast.hide()
|
||||
} else {
|
||||
this.toast.show()
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return html`
|
||||
<star-button
|
||||
type="normal"
|
||||
class="$1"
|
||||
@click=${this.show}
|
||||
label="弹出通知"
|
||||
></star-button>
|
||||
`
|
||||
}
|
||||
render_bak() {
|
||||
return html`
|
||||
<div>
|
||||
<h3>普通的</h3>
|
||||
|
|
Loading…
Reference in New Issue