细分组件
This commit is contained in:
parent
9191e09646
commit
861ad2a586
|
@ -1,9 +0,0 @@
|
|||
interface WebActivity {
|
||||
start(): Promise<any>;
|
||||
cancel(): void;
|
||||
}
|
||||
|
||||
declare var WebActivity: {
|
||||
prototype: WebActivity;
|
||||
new(name: string, data?: any): WebActivity;
|
||||
};
|
|
@ -0,0 +1,193 @@
|
|||
import {html, css, LitElement, HTMLTemplateResult} from 'lit'
|
||||
import {customElement, property, query} from 'lit/decorators.js'
|
||||
@customElement('brightness-slider')
|
||||
export class BrightnessSlider extends LitElement {
|
||||
@query('.progress') progress!: HTMLDivElement
|
||||
@query('.sliderBar') sliderBar!: HTMLDivElement
|
||||
@property({type: String}) id = ''
|
||||
@property({type: String}) _coverLen = ''
|
||||
@property({type: Number}) innerWidth = 0
|
||||
@property({type: Number}) distance = 0
|
||||
@property({type: Number}) currentDistance = 0
|
||||
@property({type: Number}) barWidth = 0
|
||||
@property({type: Number}) max = 100
|
||||
@property({type: Number}) value = 1
|
||||
@property() touchAction = {
|
||||
// 触摸开始落点
|
||||
start: {
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
},
|
||||
|
||||
// 触摸结束落点
|
||||
last: {
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
},
|
||||
}
|
||||
|
||||
@property({type: String})
|
||||
get coverLen() {
|
||||
return this._coverLen
|
||||
}
|
||||
|
||||
set coverLen(value: string) {
|
||||
this.style.setProperty('--cover-length', value)
|
||||
this._coverLen = value
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div
|
||||
class="sliderBar"
|
||||
data-icon="brightness"
|
||||
value=${this.value}
|
||||
max=${this.max}
|
||||
@touchstart=${this}
|
||||
@touchmove=${this}
|
||||
@touchend=${this}
|
||||
>
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
dislay: block;
|
||||
--cover-length: 3.78px; // 亮度为1
|
||||
--background-lm: rgba(255, 255, 255, 0.5);
|
||||
--background-dm: rgba(0, 0, 0, 0.15);
|
||||
--progress-background-lm: rgba(255, 255, 255, 0.8);
|
||||
--progress-background-dm: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.sliderBar {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background: var(--background-lm);
|
||||
}
|
||||
|
||||
.progress {
|
||||
width: var(--cover-length);
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background: var(--progress-background-lm);
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
position: absolute;
|
||||
content: attr(data-icon);
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.sliderBar {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 29px;
|
||||
top: 29px;
|
||||
font-size: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.sliderBar {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
left: 14px;
|
||||
top: 24px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
if (this.value) {
|
||||
let len = Math.floor((this.value * this.sliderBar.offsetWidth) / this.max)
|
||||
this.coverLen = len.toString()
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(event: TouchEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
this.touchAction.start.clientX = event.touches[0].clientX
|
||||
this.barWidth = this.sliderBar.offsetWidth
|
||||
break
|
||||
case 'touchmove':
|
||||
this.touchAction.last.clientX = event.touches[0].clientX
|
||||
this.distance =
|
||||
this.touchAction.last.clientX - this.touchAction.start.clientX
|
||||
this.currentDistance = this.distance + this.progress.offsetWidth
|
||||
|
||||
if (this.currentDistance < 0) {
|
||||
// this.currentDistance = 0;
|
||||
this.currentDistance = this.barWidth / this.max
|
||||
}
|
||||
|
||||
if (this.currentDistance > this.barWidth) {
|
||||
this.currentDistance = this.barWidth
|
||||
}
|
||||
this.progress.style.setProperty('width', this.currentDistance + 'px')
|
||||
break
|
||||
case 'touchend':
|
||||
this.value = Math.floor(
|
||||
(this.currentDistance * this.max) / this.barWidth
|
||||
)
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('brightness-slider-change', {
|
||||
detail: {
|
||||
value: this.value,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
setValue(value: number) {
|
||||
this.value = value
|
||||
let len = Math.floor((value * this.sliderBar.offsetWidth) / this.max)
|
||||
this.coverLen = len.toString()
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'brightness-slider': BrightnessSlider
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './brightness-slider.js'
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/brightness-slider",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./brightness-slider.js": {
|
||||
"default": "./brightness-slider.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -4,5 +4,5 @@
|
|||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["../../../global.d.ts", "*.ts"]
|
||||
}
|
||||
"include": ["*.ts"]
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
# icon-item
|
||||
用于显示下拉控件栏中的icon。
|
||||
分为两类:
|
||||
`IconType.BASE`类型:
|
||||
须传入`icon`(用于图标内容),`bgchange`(用于点击图标时的样式变化),`bgchange`未传参时,默认图标点击时不改变图标背景
|
||||
`IconType.WITH_STATE`类型:
|
||||
须传入`icon`(用于图标内容),`stateDesc`(用于蓝牙、wifi状态显示)
|
||||
可选参数`settingsKey`: 用于settingsObsever。
|
||||
|
||||
`IconType.BASE_WITHOUT_BORDER`类型:
|
||||
须传入`icon`(用于图标内容),图标不带边框。
|
||||
|
||||
|
||||
示例:
|
||||
```html
|
||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
||||
|
||||
<icon-item type=${IconType.BASE} icon="crop"></icon-item>
|
||||
|
||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness"></icon-item>
|
||||
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
```
|
||||
|
||||
|
||||
# icons-online
|
||||
对`icon-item`的进一步组合、封装。
|
||||
分为两类:
|
||||
`IconsOneLineType.BASE`类型:
|
||||
需传入`count`,为所插入插槽元素的个数,默认数值为4;
|
||||
需插入插槽元素,显示为一个box框,框内是由短竖线分隔开的基本图标。
|
||||
`IconsOneLineType.WITH_STATE`类型:
|
||||
需传入`count`,为所插入插槽元素的个数,默认数值为2;
|
||||
需插入插槽元素,显示为一行带状态的图标。
|
||||
|
||||
示例:
|
||||
```html
|
||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" isActive=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="bluetooth" isActive=true settingsKey="bluetooth.enabled"></icon-item>
|
||||
</icons-one-line>
|
||||
|
||||
|
||||
<icons-one-line type=${IconsOneLineType.BASE} count=3>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
||||
</icons-one-line>
|
||||
|
||||
```
|
||||
|
||||
|
||||
# header-bar
|
||||
用于显示下拉控件栏、下拉通知栏最顶部的header。
|
||||
分为两类:
|
||||
`HeaderBarType.ONLY_TIME`类型:
|
||||
header中显示时间和任意图标,需插入插槽元素
|
||||
`HeaderBarType.DATE_TIME`类型:
|
||||
header中显示日期、星期、时间和任意图标,需插入插槽元素
|
||||
示例:
|
||||
```html
|
||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
</header-bar>
|
||||
|
||||
|
||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
</header-bar>
|
||||
|
||||
```
|
||||
|
||||
# control-center
|
||||
下拉控件栏组件。
|
||||
包括`header-bar`和中间控件部分。中间控件部分由slot元素插入。
|
||||
|
||||
```html
|
||||
<control-center>
|
||||
<div class="brightness"></div>
|
||||
<icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
||||
</control-center>
|
||||
```
|
||||
|
||||
# control-center-bar
|
||||
`control-center`实例
|
||||
|
||||
说明: 因现有下拉栏顶部的状态栏是采用`background-image:-moz-element(#statusbar-icons)`方式获取,所以使用`slot`获取。
|
||||
```html
|
||||
<control-center-bar>
|
||||
<div slot="status-bar"></div>
|
||||
</control-center-bar>
|
||||
```
|
|
@ -1,926 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult } from 'lit'
|
||||
import { customElement, property, query } from 'lit/decorators.js'
|
||||
import { settingsObserver as settingsObserver} from "./mock_settings_observer";
|
||||
import { IconsOneLine, IconsOneLineType } from './icons-one-line'
|
||||
import { IconItem, IconType } from './icon-item';
|
||||
import { PullDownMenuType } from './pull-down-menu';
|
||||
import './icons-one-line';
|
||||
import './icon-item';
|
||||
import './pull-down-menu';
|
||||
import './light-slider';
|
||||
import "./gaia-container";
|
||||
// import "../gaia_dialog/gaia-dialog-list.js";
|
||||
// import WifiContext from "../../js/utils/origin/wifi/wifi_context.js";
|
||||
import IconDB from "./icondb";
|
||||
import { LightSlider } from './light-slider';
|
||||
// import WifiNetworkList from "../../js/utils/origin/wifi/wifi_network_list.js";
|
||||
// import WifiItem from "../../js/utils/origin/wifi/wifi_item.js";
|
||||
// import BtTemplateFactory from '../../js/utils/origin/bluetooth/bt_template_factory.js';
|
||||
// import ListView from '../../js/utils/origin/mvvm/list_view.js';
|
||||
// import BtContext from '../../js/utils/origin/bluetooth/bluetooth_context.js';
|
||||
// import BluetoothItem from "../../js/utils/origin/bluetooth/bluetooth_item.js";
|
||||
const WIFIENABLED = "wifi.enabled";
|
||||
// const BLUETOOTHENABLED = "bluetooth.enabled";
|
||||
// const BRIGHTNESS = "screen.brightness";
|
||||
// const AUTOBRIGHTNESS = "screen.automatic-brightness";
|
||||
const GEOLOCATIONENABLED = "geolocation.enabled";
|
||||
const WIFI_HOTSPOT = "tethering.wifi.enabled";
|
||||
const LOCK_SCREEN_KEY = "screen.orientation.lock";
|
||||
// const AUDIO_VOLUME_NOTIFICATION = "audio.volume.notification";
|
||||
// const VIBRATEENABLED = "vibration.enabled";
|
||||
// const WIFI_SSID_KEY = "tethering.wifi.ssid";
|
||||
// const WIFI_SECURITY_KEY = "tethering.wifi.security.type";
|
||||
// const WIFI_PASSWORD_KEY = "tethering.wifi.security.password";
|
||||
|
||||
let _debug = false;
|
||||
_debug = true;
|
||||
let debug = function (msg?: string | any) {
|
||||
console.log(msg);
|
||||
};
|
||||
if (_debug) {
|
||||
debug = function btp_debug(msg) {
|
||||
console.log('--> [ControlCenter]: ' + msg);
|
||||
};
|
||||
}
|
||||
|
||||
@customElement('control-center-bar')
|
||||
export class ControlCenterBar extends LitElement {
|
||||
@query('gaia-container') icons!: any;
|
||||
@query('gaia-dialog-list#wifi-list') wifiListDialog!: any;
|
||||
@query('gaia-dialog-list#bluetooth-list') bluetoothListDialog!: any;
|
||||
@query('icons-one-line[type="base"]') cameraPhoto!: IconsOneLine;
|
||||
@query('icon-item[icon="bluetooth"]') bluetooth!: IconItem;
|
||||
@query('icon-item[icon="wifi-4"]') wifi!: IconItem;
|
||||
@query('icon-item[icon="brightness"]') autoBrightness!: IconItem;
|
||||
@query('#screen-brightness') brightness!: LightSlider;
|
||||
@property({type: IconDB}) icondb = new IconDB();
|
||||
@property() settings = {
|
||||
wifi: false,
|
||||
airplaneMode: false,
|
||||
data: false,
|
||||
bluetooth: false,
|
||||
wifihotspot: false,
|
||||
geolocation: false,
|
||||
screenLock: false,
|
||||
brightness: 1,
|
||||
autoBrightness: false,
|
||||
};
|
||||
@property({type: Number}) iconsLeft = 0;
|
||||
@property({type: Number}) iconsRight = 0;
|
||||
@property({type: Boolean}) airplaneModeSwitching = false;
|
||||
@property({type: Number}) lastWindowWidth = window.innerWidth;
|
||||
@property({type: Number}) lastWindowHeight = window.innerHeight;
|
||||
@property() pairedDevicesListView = null;
|
||||
@property({type: String}) iconOnlyElements = ["data", "airplane-mode", "geolocation", "wifi-hotspot", "dark-mode", "sound", "auto-rotate", "addons"];
|
||||
@property({type: []}) startupOrder !: any[];
|
||||
@property({type: Boolean}) draggable = false;
|
||||
@property({type: Number}) minRange = 10; // 最小滑动距离
|
||||
@property() touchAction = { // 触摸开始落点
|
||||
start: {
|
||||
pageX: 0,
|
||||
pageY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
},
|
||||
|
||||
last: { // 触摸结束落点
|
||||
pageX: 0,
|
||||
pageY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
}
|
||||
}
|
||||
@property({type: Number}) preVolumeValue = 1;
|
||||
@property({type: IconItem}) wifiHotspot!: IconItem;
|
||||
@property({type: IconItem}) autoRotate!: IconItem;
|
||||
@property({type: IconItem}) sound!: IconItem;
|
||||
@property({type: IconItem}) airplaneMode!: IconItem;
|
||||
@property({type: IconItem}) data!: IconItem;
|
||||
@property({type: IconItem}) geolocation!: IconItem;
|
||||
@property({type: Number}) timer!: NodeJS.Timeout;
|
||||
render(): HTMLTemplateResult {
|
||||
console.log("dddd render");
|
||||
return html`
|
||||
<slot name="status-bar"></slot>
|
||||
<pull-down-menu type=${PullDownMenuType.HEADER_WITH_TIME}>
|
||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
||||
<icon-item type=${IconType.WITH_STATE} id="wifi" icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
||||
<icon-item type=${IconType.WITH_STATE} id="bluetooth" icon="bluetooth" bgchange=true settingsKey="bluetooth.enabled"></icon-item>
|
||||
</icons-one-line>
|
||||
<div class="icon-section">
|
||||
<gaia-container id="icon-only"></gaia-container>
|
||||
</div>
|
||||
<div class="brightness">
|
||||
<light-slider id="screen-brightness"></light-slider>
|
||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness"></icon-item>
|
||||
</div>
|
||||
<icons-one-line type=${IconsOneLineType.BASE}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="o"></icon-item>
|
||||
</icons-one-line>
|
||||
<div class="button-wrapper">
|
||||
<div id="toggle-button"></div>
|
||||
</div>
|
||||
<div class="media-player"></div>
|
||||
<gaia-dialog-list id="wifi-list" hidden>
|
||||
<h1>WLAN</h1>
|
||||
<h2>可用WLAN列表</h2>
|
||||
</gaia-dialog-list>
|
||||
<gaia-dialog-list id="bluetooth-list" hidden>
|
||||
<h1>蓝牙</h1>
|
||||
<h2>已配对的设备</h2>
|
||||
</gaia-dialog-list>
|
||||
</pull-down-menu>
|
||||
`
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--background-color-lm: rgba(217, 217, 217, 0.65);
|
||||
--background-color-dm: rgba(89, 89, 89, 0.68);
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
display: block;
|
||||
background: var(--background-color-lm);
|
||||
backdrop-filter: blur(120px);
|
||||
transform: translateY(0);
|
||||
transition: transform 300ms ease, visibility 300ms;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
:host([open]) {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
::slotted(div) {
|
||||
background-image: -moz-element(#statusbar-icons);
|
||||
background-repeat: no-repeat;
|
||||
width: 100%;
|
||||
height: 3rem;
|
||||
filter: none;
|
||||
// background-position: 600px center;
|
||||
background-position: right;
|
||||
}
|
||||
|
||||
pull-down-menu {
|
||||
// width: 100%;
|
||||
// height: calc(100% - 3rem)
|
||||
position; absolute;
|
||||
top: 140px;
|
||||
left: 628px;
|
||||
width: 512px;
|
||||
}
|
||||
|
||||
icons-one-line {
|
||||
width: 512px;
|
||||
height: 112px;
|
||||
}
|
||||
|
||||
icons-one-line[type='with-state'] {
|
||||
position: relative;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.icon-section {
|
||||
// width: inherit;
|
||||
// height: 238px;
|
||||
|
||||
width: 540px;
|
||||
height: 268px;
|
||||
position: relative;
|
||||
top: 72px;
|
||||
|
||||
left: -9px;
|
||||
}
|
||||
|
||||
gaia-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-content: flex-start;
|
||||
box-sizing: padding-box;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
// height: 119px;
|
||||
// width: 128px;
|
||||
height: 134px;
|
||||
width: 135px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.icon-container > icon-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition: transform 0.2s, opacity 0.2s;
|
||||
transform: translate(12px, 7.5px);
|
||||
}
|
||||
|
||||
gaia-container:not(.loading) > .gaia-container-child:not(.added):not(.dragging) {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
gaia-container > .gaia-container-child.dragging {
|
||||
z-index: 1;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.brightness {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
position: relative;
|
||||
// top: 104px;
|
||||
top: 89px; //104-15
|
||||
}
|
||||
|
||||
#screen-brightness {
|
||||
width: 378px;
|
||||
height: 104px;
|
||||
}
|
||||
|
||||
icons-one-line[type='base'] {
|
||||
position: relative;
|
||||
top: 136px;
|
||||
}
|
||||
|
||||
#toggle-button {
|
||||
width: 88px;
|
||||
height: 10px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.media-player { // 占位隐藏
|
||||
// width: inherit;
|
||||
// height: 134px;
|
||||
// position: relative;
|
||||
// top: 200px;
|
||||
// border: 1px solid white;
|
||||
|
||||
// height: 67px;
|
||||
// top: 100px;
|
||||
// border: 0.5px solid white;
|
||||
}
|
||||
|
||||
.button-wrapper {
|
||||
position: relative;
|
||||
top: 168px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
:host([dark-mode]) {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
display: block;
|
||||
background: var(--background-color-dm);
|
||||
backdrop-filter: blur(120px);
|
||||
}
|
||||
|
||||
[disabled="true"] {
|
||||
pointer-events: none;
|
||||
opacity: 0.2;
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
this.iconAdded().then(() => {
|
||||
this.monitorWifiChange();
|
||||
this.monitorTetheringStatusChange();
|
||||
window.addEventListener("send-to-control-center", this.toggleActive.bind(this));
|
||||
this.monitorAirplaneModeChange();
|
||||
this.monitorBluetoothChange();
|
||||
|
||||
this.cameraPhoto.addEventListener("click", this.handleCamera.bind(this));
|
||||
// ["click", "touchstart", "touchend", "drag-end",
|
||||
["touch-start", "touchend", "drag-end",
|
||||
"drag-rearrange", "drag-finish"].forEach(eventName => {
|
||||
this.icons.addEventListener(eventName, this.handleContainerEvent.bind(this))
|
||||
});
|
||||
|
||||
|
||||
[this.wifiListDialog, this.bluetoothListDialog].forEach(dialog => {
|
||||
dialog.addEventListener("more-settings", this.handleNavigate.bind(this));
|
||||
});
|
||||
|
||||
window.addEventListener("touchstart", this.handleStart.bind(this));
|
||||
window.addEventListener("touchmove", this.handleMove.bind(this));
|
||||
window.addEventListener("editor-action", this.handleEditor.bind(this));
|
||||
window.addEventListener("icon-item-click", this.handleIconButtonClick.bind(this));
|
||||
window.addEventListener("more-info-action", this.showListDialog.bind(this));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
iconAdded() {
|
||||
return new Promise((resolve: (value: void) => void) => {
|
||||
this.icondb.init().then(() => {
|
||||
// return this.icondb.getAll((result: any) => {
|
||||
// console.log("iconAdded icondb getAll: ", result);
|
||||
|
||||
// if (result) {
|
||||
// let id = result.id;
|
||||
// this.startupOrder.push(id);
|
||||
// this.iconOnlyElements = this.startupOrder;
|
||||
// }
|
||||
// return Promise.resolve();
|
||||
// });
|
||||
}).then(() => {
|
||||
this.addIcon();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
toggleActive() {
|
||||
if (this.autoBrightness.active == this.settings.autoBrightness) {
|
||||
this.autoBrightness.activeOrInactive(!this.settings.autoBrightness);
|
||||
}
|
||||
if (this.geolocation.active == this.settings.geolocation) {
|
||||
this.geolocation.activeOrInactive(!this.settings.geolocation);
|
||||
}
|
||||
|
||||
if (this.wifiHotspot.active == this.settings.wifihotspot) {
|
||||
this.wifiHotspot.activeOrInactive(!this.settings.wifihotspot);
|
||||
}
|
||||
|
||||
if (this.autoRotate.active == this.settings.screenLock) {
|
||||
|
||||
this.autoRotate.activeOrInactive(!this.settings.screenLock);
|
||||
}
|
||||
|
||||
if (this.brightness.value == this.settings.brightness) {
|
||||
|
||||
// this.brightness.value = this.settings.brightness;
|
||||
this.brightness.setValue(this.settings.brightness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
monitorWifiChange() {
|
||||
// WifiItem(this.wifiStatusText).enabled = true;
|
||||
// WifiItem(this.wifi.stateDesc).enabled = true;
|
||||
window.addEventListener("wifi-enabled", this.handleWifiChange.bind(this));
|
||||
window.addEventListener("wifi-disabled", this.handleWifiChange.bind(this));
|
||||
window.addEventListener("wifi-statuschange", this.handleWifiChange.bind(this));
|
||||
}
|
||||
|
||||
monitorAirplaneModeChange() {
|
||||
|
||||
window.addEventListener("send-airplaneMode-status", (evt: any) => {
|
||||
let value = evt.detail.value;
|
||||
this.airplaneModeSwitching = false;
|
||||
let target = this.airplaneMode; // 飞行模式element
|
||||
|
||||
switch (value) {
|
||||
case "enabled":
|
||||
this.setSettingEnabled("airplaneMode", true);
|
||||
target.activeOrInactive(false); // addClass
|
||||
this.wifiHotspot.setAttribute("disabled", "true"); // 飞行模式下禁用wifi热点和移动数据
|
||||
this.data.setAttribute("disabled", "true");
|
||||
if (this.data.active) {
|
||||
this.data.activeOrInactive(true);
|
||||
}
|
||||
break;
|
||||
case "disabled":
|
||||
this.setSettingEnabled("airplaneMode", false);
|
||||
target.activeOrInactive(true);// removeClass
|
||||
this.wifiHotspot.removeAttribute("disabled");
|
||||
this.data.removeAttribute("disabled");
|
||||
if (!this.data.active) {
|
||||
this.data.activeOrInactive(false);
|
||||
}
|
||||
break;
|
||||
case "enabling":
|
||||
this.airplaneModeSwitching = true;
|
||||
break;
|
||||
case "disabling":
|
||||
this.airplaneModeSwitching = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
monitorBluetoothChange() {
|
||||
window.addEventListener("bluetooth-enabled", this.handleBlueToothChange.bind(this));
|
||||
window.addEventListener("bluetooth-disabled", this.handleBlueToothChange.bind(this));
|
||||
}
|
||||
|
||||
monitorTetheringStatusChange() {
|
||||
window.addEventListener("tethering-status-change", evt => {
|
||||
settingsObserver.getValue(WIFIENABLED).then(wifiEnabled => {
|
||||
if (!wifiEnabled && (evt as any).detail === 0) { // wifi打开状态下,wifi热点打开再关闭, 应恢复wifi
|
||||
settingsObserver.setValue([{name: WIFIENABLED, value: true }]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setSettingEnabled(settingKey: string, enabled: any) {
|
||||
(this.settings as any)[settingKey] = enabled;
|
||||
}
|
||||
|
||||
onPairedDeviceItemClick(deviceItem: any) {
|
||||
debug('onPairedDeviceItemClick(): deviceItem.address = ' +
|
||||
deviceItem.address);
|
||||
debug('onPairedDeviceItemClick(): deviceItem.paired = ' +
|
||||
deviceItem.paired);
|
||||
}
|
||||
|
||||
handleWifiChange(evt: Event) {
|
||||
evt.preventDefault();
|
||||
switch (evt.type) {
|
||||
case "wifi-enabled":
|
||||
// debug("handleWifiChange wifi-enabled!!");
|
||||
this.setSettingEnabled("wifi", true);
|
||||
this.wifi.activeOrInactive(false);
|
||||
this.scan();
|
||||
break;
|
||||
case "wifi-disabled":
|
||||
// debug("handleWifiChange wifi-disabled!!");
|
||||
this.setSettingEnabled("wifi", false);
|
||||
this.wifi.activeOrInactive(true);
|
||||
/*
|
||||
WifiItem(this.wifi.stateDesc).enabled = false;
|
||||
*/
|
||||
break;
|
||||
case "wifi-statuschange":
|
||||
// debug("handleWifiChange wifi-statuschange!!");
|
||||
let scanStates = new Set(["connected", "connectingfailed", "disconnected"]);
|
||||
if (scanStates.has((evt as any).detail.event.status)) {
|
||||
this.scan();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleBlueToothChange(event: Event) {
|
||||
// event.preventDefault();
|
||||
switch (event.type) {
|
||||
case "bluetooth-enabled":
|
||||
this.setSettingEnabled("bluetooth", true);
|
||||
this.bluetooth.activeOrInactive(false);
|
||||
|
||||
// let pairedDeviceTemplate =
|
||||
// BtTemplateFactory("paired", this.onPairedDeviceItemClick.bind(this));
|
||||
|
||||
// this.pairedDevicesListView = ListView(this.bluetoothListDialog,
|
||||
// BtContext.getPairedDevices(),
|
||||
// pairedDeviceTemplate);
|
||||
(this.pairedDevicesListView as any).enabled = true;
|
||||
break;
|
||||
case "bluetooth-disabled":
|
||||
this.setSettingEnabled("bluetooth", false);
|
||||
this.bluetooth.activeOrInactive(true);
|
||||
if (this.pairedDevicesListView) {
|
||||
(this.pairedDevicesListView as any).enabled = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleEditor() {
|
||||
let dragAndDrop = this.icons.getAttribute("drag-and-drop");
|
||||
this.icons.setAttribute("drag-and-drop", (!dragAndDrop).toString());
|
||||
this.draggable = !dragAndDrop;
|
||||
}
|
||||
|
||||
handleSettings() {
|
||||
let activity = new WebActivity("configure", {});
|
||||
activity.start().then(() => {}, () => {});
|
||||
}
|
||||
|
||||
showListDialog(event: Event) {
|
||||
let target = (event as any).detail;
|
||||
switch (target) {
|
||||
case "wifi-4":
|
||||
this.wifiListDialog.open(event);
|
||||
break;
|
||||
case "bluetooth":
|
||||
this.bluetoothListDialog.open(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleIconButtonClick(event: any) {
|
||||
let target = event.detail.target;
|
||||
console.log("handleIconButtonClick target: ", target);
|
||||
console.log("handleIconButtonClick event.detail: ", event.detail);
|
||||
let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only";
|
||||
if (isContainer && this.draggable) {
|
||||
return;
|
||||
}
|
||||
|
||||
let isActive = event.detail.isActive;
|
||||
let id = event.detail.id;
|
||||
|
||||
switch (id) {
|
||||
case "wifi":
|
||||
if (this.airplaneModeSwitching) {
|
||||
return;
|
||||
}
|
||||
this.fireEvent(id, !isActive);
|
||||
break;
|
||||
case "bluetooth":
|
||||
if (this.airplaneModeSwitching) {
|
||||
return;
|
||||
}
|
||||
let enabled = this.settings.bluetooth;
|
||||
var toggleb = enabled ?
|
||||
"request-disable-bluetooth" :
|
||||
"request-enable-bluetooth";
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(toggleb, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
break;
|
||||
case "screen-auto-brightness":
|
||||
this.fireEvent(id, !isActive);
|
||||
break;
|
||||
case "airplane-mode":
|
||||
if (this.airplaneModeSwitching) {
|
||||
return;
|
||||
}
|
||||
|
||||
var toggle = isActive ?
|
||||
"request-airplane-mode-disable" :
|
||||
"request-airplane-mode-enable";
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(toggle, {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
if (isActive) {
|
||||
this.wifiHotspot.removeAttribute("disabled");
|
||||
this.data.removeAttribute("disabled");
|
||||
} else {
|
||||
this.wifiHotspot.setAttribute("disabled", "true");
|
||||
this.data.setAttribute("disabled", "true");
|
||||
}
|
||||
break;
|
||||
case "geolocation":
|
||||
this.fireEvent(id, !isActive);
|
||||
break;
|
||||
case "wifi-hotspot":
|
||||
if (this.airplaneModeSwitching) {
|
||||
return;
|
||||
}
|
||||
this.fireEvent(id, !isActive);
|
||||
break;
|
||||
case "dark-mode":
|
||||
break;
|
||||
|
||||
case "sound":
|
||||
if (this.sound.icon == "alarm") {
|
||||
this.sound.icon = "mute";
|
||||
this.fireEvent("mute", 0);
|
||||
} else if (this.sound.icon == "mute") {
|
||||
this.sound.icon = "alarm";
|
||||
this.fireEvent("alarm", this.preVolumeValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case "auto-rotate":
|
||||
this.fireEvent(id, !isActive);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleIconButtonPress(event: any) {
|
||||
let target = event.detail.target;
|
||||
let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only";
|
||||
|
||||
if (isContainer && this.draggable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.className == "icon-container") {
|
||||
target = target.children[0];
|
||||
}
|
||||
|
||||
if (target.getAttribute("disabled") === "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.close();
|
||||
let section = target.id;
|
||||
this.timer = setTimeout(() => {
|
||||
let activity = new WebActivity("moz_configure_window", {
|
||||
data: {
|
||||
target: "device",
|
||||
section: section
|
||||
}
|
||||
});
|
||||
activity.start();
|
||||
}, 800);
|
||||
}
|
||||
|
||||
handleIconButtonPressEnd(event: any) {
|
||||
let target = event.target;
|
||||
let isContainer = target.parentElement?.parentElement?.parentElement?.id == "icon-only";
|
||||
if (isContainer && this.draggable) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
handleNavigate(event: any) {
|
||||
let section = event.target.id;
|
||||
let activity = new WebActivity("moz_configure_window", {
|
||||
data: {
|
||||
target: "device",
|
||||
section: section
|
||||
}
|
||||
});
|
||||
activity.start();
|
||||
}
|
||||
|
||||
handleCamera(event: any) {
|
||||
let target = event.target.icon;
|
||||
switch (target) {
|
||||
case "crop":
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("volumedown+sleep", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
this.close();
|
||||
break;
|
||||
case "video":
|
||||
let takeVideo = new WebActivity("record", {
|
||||
type: "videos"
|
||||
});
|
||||
takeVideo.start();
|
||||
this.close();
|
||||
break;
|
||||
case "camera":
|
||||
let takePhotos = new WebActivity("record", {
|
||||
type: "photos"
|
||||
});
|
||||
takePhotos.start();
|
||||
this.close();
|
||||
break;
|
||||
case "shut-down":
|
||||
// powerManager.powerOff();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleContainerEvent(event: Event) {
|
||||
switch (event.type) {
|
||||
case "icon-item-click":
|
||||
this.handleIconButtonClick(event);
|
||||
break;
|
||||
case "touch-start":
|
||||
this.handleIconButtonPress(event);
|
||||
break;
|
||||
case "touchend":
|
||||
this.handleIconButtonPressEnd(event);
|
||||
break;
|
||||
case "drag-end":
|
||||
case "drag-rearrange":
|
||||
case "drag-finish":
|
||||
this.handleContainerDrag(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleContainerDrag(e: any) {
|
||||
switch(e.type) {
|
||||
// Activate drag-and-drop immediately for selected icons
|
||||
case "touchstart":
|
||||
this.icons.dragAndDropTimeout = 0;
|
||||
break;
|
||||
|
||||
case "drag-finish":
|
||||
debug("Drag-finish");
|
||||
// Restore normal drag-and-drop after dragging selected icons
|
||||
this.icons.dragAndDropTimeout = -1;
|
||||
break;
|
||||
|
||||
// Handle icon editing and dragging to the end of the icon grid.
|
||||
case "drag-end":
|
||||
debug("Drag-end, target: " + (e.detail.dropTarget ?
|
||||
e.detail.dropTarget.firstElementChild : "none"));//e.detail.target --> div.icon-container
|
||||
|
||||
if (e.detail.dropTarget === null &&
|
||||
e.detail.clientX >= this.iconsLeft &&
|
||||
e.detail.clientX < this.iconsRight) {
|
||||
// If the drop target is null, and the client coordinates are
|
||||
// within the panel, we must be dropping over the start or end of
|
||||
// the container.
|
||||
e.preventDefault();
|
||||
let bottom = e.detail.clientY < this.lastWindowHeight / 2;
|
||||
debug("Reordering dragged icon to " +
|
||||
(bottom ? "bottom" : "top"));
|
||||
this.icons.reorderChild(e.detail.target,
|
||||
bottom ? this.icons.firstChild : null as any,
|
||||
this.storeIconOrder.bind(this));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// Save the icon grid after rearrangement
|
||||
case "drag-rearrange":
|
||||
debug("Drag rearrange");
|
||||
this.storeIconOrder();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scan() {
|
||||
// WifiNetworkList(this.wifiListDialog).scan();
|
||||
}
|
||||
|
||||
clearList(enabled: boolean) {
|
||||
console.log(enabled);
|
||||
|
||||
// WifiNetworkList(this.wifiListDialog).clear(enabled);
|
||||
}
|
||||
|
||||
activeOrInactive(isActive: boolean, element: HTMLElement) {
|
||||
if (element.id === "sound") {
|
||||
element.classList.add("active");
|
||||
return;
|
||||
}
|
||||
isActive ? element.classList.remove("active") :
|
||||
element.classList.add("active");
|
||||
}
|
||||
|
||||
addIcon() {
|
||||
this.iconOnlyElements.forEach((icon) => {
|
||||
let iconDiv = document.createElement("icon-item");
|
||||
iconDiv.type = "base";
|
||||
iconDiv.id = icon;
|
||||
let key = null;
|
||||
switch (icon) {
|
||||
case "data":
|
||||
iconDiv.icon = "data";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "airplane-mode":
|
||||
iconDiv.icon = "airplane";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "geolocation":
|
||||
key = GEOLOCATIONENABLED;
|
||||
iconDiv.icon = "location";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "wifi-hotspot":
|
||||
key = WIFI_HOTSPOT;
|
||||
iconDiv.icon = "tethering";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "dark-mode":
|
||||
iconDiv.icon = "themes";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "auto-rotate":
|
||||
key = LOCK_SCREEN_KEY;
|
||||
iconDiv.icon = "sync";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
case "sound":
|
||||
iconDiv.icon = "alarm";
|
||||
iconDiv.id = "sound";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
// 填充 无意义
|
||||
case "addons":
|
||||
iconDiv.icon = "addons";
|
||||
iconDiv.id = "addons";
|
||||
iconDiv.bgchange = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (key) {
|
||||
iconDiv.settingsKey = key;
|
||||
}
|
||||
|
||||
// iconDiv.id = icon;
|
||||
// iconDiv.setAttribute("id", icon);
|
||||
(this as any)[this.toCamelCase(iconDiv.id)] = iconDiv;
|
||||
this.addIconContainer(iconDiv);
|
||||
});
|
||||
}
|
||||
|
||||
addIconContainer(iconDiv: IconItem) {
|
||||
let container = document.createElement("div") as HTMLElement;
|
||||
container.classList.add("icon-container");
|
||||
(container as any).order = -1;
|
||||
container.appendChild(iconDiv);
|
||||
|
||||
if (!container.parentNode) {
|
||||
this.icons.appendChild(container);
|
||||
this.refreshGridSize();
|
||||
}
|
||||
}
|
||||
|
||||
refreshGridSize() {
|
||||
let children = this.icons.children;
|
||||
let visibleChildren = 0;
|
||||
let cols = 4;
|
||||
let firstVisibleChild = -1;
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
// if ((children[i] as HTMLElement).style.display !== "none") {
|
||||
visibleChildren ++;
|
||||
if (firstVisibleChild === -1) {
|
||||
firstVisibleChild = i;
|
||||
this.iconsLeft = this.icons.getChildOffsetRect((children[i]) as HTMLElement).left;
|
||||
} else if (visibleChildren === cols) {
|
||||
this.iconsRight = this.icons.getChildOffsetRect(children[i] as HTMLElement).right;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
toCamelCase(str: string) {
|
||||
return str.replace(/\-(.)/g, function replacer(str, p1) {
|
||||
console.log(str);
|
||||
return p1.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
storeIconOrder() {
|
||||
let storedOrders = [];
|
||||
let children = this.icons.children;
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
let icon = children[i].firstElementChild as Element;
|
||||
storedOrders.push({ id: icon.id, order: i });
|
||||
}
|
||||
this.icondb.set(storedOrders).then(
|
||||
() => {},
|
||||
(e) => {
|
||||
console.error("Error storing icon order", e);
|
||||
});
|
||||
}
|
||||
|
||||
handleStart(event: TouchEvent) {
|
||||
this.touchAction.start.pageX = event.touches[0].pageX;
|
||||
this.touchAction.start.pageY = event.touches[0].pageY;
|
||||
}
|
||||
|
||||
handleMove(event: TouchEvent) {
|
||||
this.touchAction.last.pageX = event.touches[0].pageX;
|
||||
this.touchAction.last.pageY = event.touches[0].pageY;
|
||||
let distanceY = this.touchAction.last.pageY - this.touchAction.start.pageY;
|
||||
|
||||
if (this.touchAction.start.pageY > 0 &&
|
||||
this.touchAction.start.pageY < this.minRange &&
|
||||
this.touchAction.start.pageX > window.screen.width / 2
|
||||
&& distanceY >= this.minRange) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
if (this.touchAction.start.pageY > window.screen.height - this.minRange
|
||||
&& this.touchAction.start.pageY <= window.screen.height) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
open() {
|
||||
let isOpen = this.getAttribute("open");
|
||||
if (isOpen !== "") {
|
||||
this.setAttribute("open", "");
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
let isOpen = this.getAttribute("open");
|
||||
if (isOpen == "") {
|
||||
this.removeAttribute("open");
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent(name: string, value: string | boolean | number) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("control-center-dispatched", {
|
||||
detail: {
|
||||
name,
|
||||
value
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'control-center-bar': ControlCenterBar
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
|
||||
export default class GaiaContainerChild {
|
||||
constructor(element) {
|
||||
this._element = element;
|
||||
this.markDirty();
|
||||
}
|
||||
|
||||
get element() {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
/**
|
||||
* The element that will contain the child element and control its position.
|
||||
*/
|
||||
get container() {
|
||||
if (!this._container) {
|
||||
// Create container
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("gaia-container-child");
|
||||
container.style.position = "absolute";
|
||||
container.style.top = "0";
|
||||
container.style.left = "0";
|
||||
container.appendChild(this.element);//this.element是div.icon-container
|
||||
|
||||
this._container = container;
|
||||
}
|
||||
return this._container;
|
||||
}
|
||||
|
||||
/**
|
||||
* The element that will be added to the container that will
|
||||
* control the element's transform.
|
||||
*/
|
||||
get master() {
|
||||
if (!this._master) {
|
||||
// Create master
|
||||
let master = document.createElement("div");
|
||||
master.style.visibility = "hidden";
|
||||
this._master = master;
|
||||
|
||||
}
|
||||
return this._master;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any cached style properties. To be used if elements are
|
||||
* manipulated outside of the methods of this object.
|
||||
*/
|
||||
markDirty() {
|
||||
this._lastElementWidth = null;
|
||||
this._lastElementHeight = null;
|
||||
this._lastElementDisplay = null;
|
||||
this._lastElementOrder = null;
|
||||
this._lastMasterTop = null;
|
||||
this._lastMasterLeft = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise the size of the master with the managed child element.
|
||||
*/
|
||||
synchroniseMaster() {
|
||||
let master = this.master;
|
||||
let element = this.element;
|
||||
|
||||
let style = window.getComputedStyle(element);
|
||||
let display = style.display;
|
||||
let order = style.order;
|
||||
let width = element.offsetWidth;
|
||||
let height = element.offsetHeight;
|
||||
|
||||
if (this._lastElementWidth !== width ||
|
||||
this._lastElementHeight !== height ||
|
||||
this._lastElementDisplay !== display ||
|
||||
this._lastElementOrder !== order) {
|
||||
this._lastElementWidth = width;
|
||||
this._lastElementHeight = height;
|
||||
this._lastElementDisplay = display;
|
||||
this._lastElementOrder = order;
|
||||
|
||||
master.style.width = width + "px";
|
||||
master.style.height = height + "px";
|
||||
master.style.display = display;
|
||||
master.style.order = order;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise the container's transform with the position of the master.
|
||||
*/
|
||||
synchroniseContainer() {
|
||||
let master = this.master;
|
||||
let container = this.container;
|
||||
let top = master.offsetTop;
|
||||
let left = master.offsetLeft;
|
||||
|
||||
if (this._lastMasterTop !== top ||
|
||||
this._lastMasterLeft !== left) {
|
||||
this._lastMasterTop = top;
|
||||
this._lastMasterLeft = left;
|
||||
container.style.transform = "translate(" + left + "px, " + top + "px)";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,789 +0,0 @@
|
|||
import GaiaContainerChild from "./gaia-container-child.js";
|
||||
|
||||
/**
|
||||
* The time, in ms, to wait for an animation to start in response to a state
|
||||
* change, before removing the associated style class.
|
||||
*/
|
||||
const STATE_CHANGE_TIMEOUT = 100;
|
||||
|
||||
/**
|
||||
* The time, in ms, to wait before initiating a drag-and-drop from a
|
||||
* long-press.
|
||||
*/
|
||||
const DEFAULT_DND_TIMEOUT = 300;
|
||||
|
||||
/**
|
||||
* The distance, in CSS pixels, in which a touch or mouse point can deviate
|
||||
* before it being discarded for initiation of a drag-and-drop action.
|
||||
*/
|
||||
const DND_THRESHOLD = 5;
|
||||
|
||||
/**
|
||||
* The minimum time between sending move events during drag-and-drop.
|
||||
*/
|
||||
const DND_MOVE_THROTTLE = 50;
|
||||
|
||||
class GaiaContainer extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
this.shadowRoot.innerHTML = this.template;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this._frozen = false;
|
||||
this._pendingStateChanges = [];
|
||||
this._children = [];
|
||||
this._dnd = {
|
||||
// Whether drag-and-drop is enabled
|
||||
enabled: false,
|
||||
|
||||
// The time, in ms, to wait before initiating a drag-and-drop from a
|
||||
// long-press
|
||||
delay: DEFAULT_DND_TIMEOUT,
|
||||
|
||||
// Timeout used to initiate drag-and-drop actions
|
||||
timeout: null,
|
||||
|
||||
// The child that was tapped/clicked
|
||||
child: null,
|
||||
|
||||
// Whether a drag is active
|
||||
active: false,
|
||||
|
||||
// The start point of the drag action
|
||||
start: {
|
||||
pageX: 0,
|
||||
pageY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
},
|
||||
|
||||
// The last point of the drag action
|
||||
last: {
|
||||
pageX: 0,
|
||||
pageY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
timeStamp: 0
|
||||
},
|
||||
|
||||
// Timeout used to send drag-move events
|
||||
moveTimeout: null,
|
||||
|
||||
// The last time a move event was fired
|
||||
lastMoveEventTime: 0,
|
||||
|
||||
// Whether to capture the next click event
|
||||
clickCapture: false,
|
||||
};
|
||||
|
||||
let dndObserverCallback = (mutations) => {
|
||||
if (this._dnd.enabled !== this.dragAndDrop) {
|
||||
this._dnd.enabled = this.dragAndDrop;
|
||||
if (this._dnd.enabled) {
|
||||
this.addEventListener("touchstart", this);
|
||||
this.addEventListener("touchmove", this);
|
||||
this.addEventListener("touchcancel", this);
|
||||
this.addEventListener("touchend", this);
|
||||
this.addEventListener("mousedown", this);
|
||||
this.addEventListener("mousemove", this);
|
||||
this.addEventListener("mouseup", this);
|
||||
this.addEventListener("click", this, true);
|
||||
this.addEventListener("contextmenu", this, true);
|
||||
} else {
|
||||
this.cancelDrag();
|
||||
this.removeEventListener("touchstart", this);
|
||||
this.removeEventListener("touchmove", this);
|
||||
this.removeEventListener("touchcancel", this);
|
||||
this.removeEventListener("touchend", this);
|
||||
this.removeEventListener("mousedown", this);
|
||||
this.removeEventListener("mousemove", this);
|
||||
this.removeEventListener("mouseup", this);
|
||||
this.removeEventListener("click", this, true);
|
||||
this.removeEventListener("contextmenu", this, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.dndObserver = new MutationObserver(dndObserverCallback);
|
||||
this.dndObserver.observe(this, {
|
||||
attributes: true,
|
||||
attributeFilter: ["drag-and-drop"]
|
||||
});
|
||||
|
||||
dndObserverCallback(null);
|
||||
}
|
||||
|
||||
get children() { //div.icon-container
|
||||
return this._children.map((child) => {
|
||||
return child.element;
|
||||
});
|
||||
}
|
||||
|
||||
get firstChild() {
|
||||
return this._children.length ?
|
||||
this._children[0].element :
|
||||
null;
|
||||
}
|
||||
|
||||
get lastChild() {
|
||||
const length = this._children.length;
|
||||
return (length ?
|
||||
this._children[length - 1].element :
|
||||
null);
|
||||
}
|
||||
|
||||
get dragAndDrop() {
|
||||
return (this.getAttribute("drag-and-drop") !== null);
|
||||
}
|
||||
|
||||
get dragAndDropTimeout() {
|
||||
return this._dnd.delay;
|
||||
}
|
||||
|
||||
set dragAndDropTimeout(timeout) {
|
||||
if (timeout >= 0) {
|
||||
this._dnd.delay = timeout;
|
||||
} else {
|
||||
this._dnd.delay = DEFAULT_DND_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
realAppendChild() {
|
||||
let proto = HTMLElement.prototype.appendChild;
|
||||
let func = proto.apply(this, arguments);
|
||||
return func;
|
||||
}
|
||||
|
||||
realRemoveChild() {
|
||||
let proto = HTMLElement.prototype.removeChild;
|
||||
let func = proto.apply(this, arguments);
|
||||
return func;
|
||||
}
|
||||
|
||||
realInsertBefore() {
|
||||
let proto = HTMLElement.prototype.insertBefore;
|
||||
let func = proto.apply(this, arguments);
|
||||
return func;
|
||||
}
|
||||
|
||||
realReplaceChild() {
|
||||
let proto = HTMLElement.prototype.replaceChild;
|
||||
let func = proto.apply(this, arguments);
|
||||
return func;
|
||||
}
|
||||
|
||||
appendChild(element, callback) {
|
||||
this.insertBefore(element, null, callback);
|
||||
}
|
||||
|
||||
removeChild(element, callback) {
|
||||
let children = this._children;
|
||||
let childToRemove = null;
|
||||
|
||||
for (let child of children) {
|
||||
if (child.element === element) {
|
||||
childToRemove = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (childToRemove === null) {
|
||||
throw "removeChild called on unknown child";
|
||||
}
|
||||
let that = this;
|
||||
this.changeState(childToRemove, "removed", () => {
|
||||
that.realRemoveChild(childToRemove.container);
|
||||
that.realRemoveChild(childToRemove.master);
|
||||
|
||||
// Find the child again. We need to do this in case the container was
|
||||
// manipulated between removing the child and this callback being reached.
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
if (children[i] === childToRemove) {
|
||||
children.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
this.synchronise();
|
||||
});
|
||||
}
|
||||
|
||||
replaceChild(newElement, oldElement, callback) {
|
||||
if (!newElement || !oldElement) {
|
||||
throw "replaceChild called with null arguments";
|
||||
}
|
||||
|
||||
// Unparent the newElement if necessary (with support for gaia-container)
|
||||
if (newElement.parentNode) {
|
||||
newElement.parentNode.removeChild(newElement, () => {
|
||||
this.replaceChild(newElement, oldElement, callback);
|
||||
});
|
||||
if (newElement.parentNode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the old child and add the new one, but don't run the removed/
|
||||
// added state changes.
|
||||
let children = this._children;
|
||||
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
let oldChild = children[i];
|
||||
if (oldChild.element === oldElement) {
|
||||
let newChild = new GaiaContainerChild(newElement);
|
||||
this.realInsertBefore(newChild.container, oldChild.container);
|
||||
this.realInsertBefore(newChild.master, oldChild.master);
|
||||
this.realRemoveChild(oldChild.container);
|
||||
this.realRemoveChild(oldChild.master);
|
||||
this.children.splice(i, 1, newChild);
|
||||
this.synchronise();
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw "removeChild called on unknown child";
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorders the given element to appear before referenceElement.
|
||||
*/
|
||||
reorderChild(element, referenceElement, callback) {
|
||||
if (!element) {
|
||||
throw "reorderChild called with null element";
|
||||
}
|
||||
|
||||
let children = this._children;
|
||||
let child = null;
|
||||
let childIndex = null;
|
||||
let referenceChild = null;
|
||||
let referenceChildIndex = null;
|
||||
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
if (children[i].element === element) {
|
||||
child = children[i];
|
||||
childIndex = i;
|
||||
} else if (children[i].element === referenceElement) {
|
||||
referenceChild = children[i];
|
||||
referenceChildIndex = i;
|
||||
}
|
||||
|
||||
if (child && (referenceChild || !referenceElement)) {
|
||||
this.realRemoveChild(child.container);
|
||||
this.realRemoveChild(child.master);
|
||||
children.splice(childIndex, 1);
|
||||
|
||||
if (referenceChild) {
|
||||
this.realInsertBefore(child.container, referenceChild.container);
|
||||
this.realInsertBefore(child.master, referenceChild.master);
|
||||
} else {
|
||||
(children.length === 0) ?
|
||||
this.realAppendChild(child.container):
|
||||
this.realInsertBefore(child.container, children[0].master);
|
||||
this.realAppendChild(child.master);
|
||||
}
|
||||
|
||||
referenceChild ?
|
||||
children.splice(
|
||||
referenceChildIndex - (childIndex < referenceChildIndex) ? 1 : 0,
|
||||
0, child) :
|
||||
children.splice(children.length, 0, child);
|
||||
|
||||
this.synchronise();
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw child ? "reorderChild called on unknown reference element" :
|
||||
"reorderChild called on unknown child";
|
||||
}
|
||||
|
||||
insertBefore(element, reference, callback) {
|
||||
let children = this._children;
|
||||
let childToInsert = new GaiaContainerChild(element);
|
||||
// console.log("childToInsert: ",childToInsert);// gaia-container-child
|
||||
// console.log("children: ", children);//包括gaia-container-child 、icon-container等
|
||||
let referenceIndex = -1;
|
||||
|
||||
if (reference !== null) {
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
if (children[i].element === reference) {
|
||||
referenceIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (referenceIndex === -1) {
|
||||
throw "insertBefore called on unknown child";
|
||||
}
|
||||
}
|
||||
|
||||
if (referenceIndex === -1) {
|
||||
(children.length === 0) ?
|
||||
this.realAppendChild(childToInsert.container):
|
||||
this.realInsertBefore(childToInsert.container, children[0].master);
|
||||
this.realAppendChild(childToInsert.master);
|
||||
children.push(childToInsert);
|
||||
} else {
|
||||
this.realInsertBefore(childToInsert.container,
|
||||
children[referenceIndex].container);
|
||||
this.realInsertBefore(childToInsert.master,
|
||||
children[referenceIndex].master);
|
||||
children.splice(referenceIndex, 0, childToInsert);
|
||||
}
|
||||
|
||||
this.changeState(childToInsert, "added", callback);
|
||||
this.synchronise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to execute a state-change of a child that may possibly be animated.
|
||||
* @state will be added to the child's class-list. If an animation starts that
|
||||
* has the same name, that animation will complete and @callback will be
|
||||
* called. Otherwise, the class will be removed and @callback called on the
|
||||
* next frame.
|
||||
*/
|
||||
changeState(child, state, callback) {
|
||||
// Check that the child is still attached to this parent (can happen if
|
||||
// the child is removed while frozen).
|
||||
if (child.container.parentNode !== this) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for a redundant state change.
|
||||
if (child.container.classList.contains(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Queue up state change if we're frozen.
|
||||
if (this._frozen) {
|
||||
this._pendingStateChanges.push(
|
||||
this.changeState.bind(this, child, state, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
let animStart = (e) => {
|
||||
if (!e.animationName.endsWith(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
child.container.removeEventListener("animationstart", animStart);
|
||||
|
||||
window.clearTimeout(child[state]);
|
||||
delete child[state];
|
||||
|
||||
let self = this;
|
||||
child.container.addEventListener("animationend", function animEnd() {
|
||||
child.container.removeEventListener("animationend", animEnd);
|
||||
child.container.classList.remove(state);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
child.container.addEventListener("animationstart", animStart);
|
||||
child.container.classList.add(state);
|
||||
|
||||
child[state] = window.setTimeout(() => {
|
||||
delete child[state];
|
||||
child.container.removeEventListener("animationstart", animStart);
|
||||
child.container.classList.remove(state);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}, STATE_CHANGE_TIMEOUT);
|
||||
}
|
||||
|
||||
getChildOffsetRect(element) {
|
||||
let children = this._children;
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
let child = children[i];
|
||||
if (child.element === element) {
|
||||
let top = child._lastMasterTop;
|
||||
let left = child._lastMasterLeft;
|
||||
let width = child._lastElementWidth;
|
||||
let height = child._lastElementHeight;
|
||||
|
||||
return {
|
||||
top: top,
|
||||
left: left,
|
||||
width: width,
|
||||
height: height,
|
||||
right: left + width,
|
||||
bottom: top + height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw "getChildOffsetRect called on unknown child";
|
||||
}
|
||||
|
||||
getChildFromPoint(x, y) {
|
||||
let children = this._children;
|
||||
for (let parent = this.parentElement; parent; parent = parent.parentElement) {
|
||||
x += parent.scrollLeft - parent.offsetLeft;
|
||||
y += parent.scrollTop - parent.offsetTop;
|
||||
}
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
let child = children[i];
|
||||
if (x >= child._lastMasterLeft &&
|
||||
y >= child._lastMasterTop &&
|
||||
x < child._lastMasterLeft + child._lastElementWidth &&
|
||||
y < child._lastMasterTop + child._lastElementHeight) {
|
||||
return child.element;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
cancelDrag() {
|
||||
if (this._dnd.timeout !== null) {
|
||||
clearTimeout(this._dnd.timeout);
|
||||
this._dnd.timeout = null;
|
||||
}
|
||||
|
||||
if (this._dnd.moveTimeout !== null) {
|
||||
clearTimeout(this._dnd.moveTimeout);
|
||||
this._dnd.moveTimeout = null;
|
||||
}
|
||||
|
||||
if (this._dnd.active) {
|
||||
this._dnd.child.container.classList.remove("dragging");
|
||||
this._dnd.child.container.style.position = "absolute";
|
||||
this._dnd.child.container.style.top = "0";
|
||||
this._dnd.child.container.style.left = "0";
|
||||
this._dnd.child.markDirty();
|
||||
this._dnd.child = null;
|
||||
this._dnd.active = false;
|
||||
this.synchronise();
|
||||
this._dnd.clickCapture = true;
|
||||
this.dispatchEvent(new CustomEvent("drag-finish"));
|
||||
}
|
||||
}
|
||||
|
||||
startDrag() {
|
||||
if (!this.dispatchEvent(new CustomEvent("drag-start", {
|
||||
cancelable: true,
|
||||
detail: {
|
||||
target: this._dnd.child.element,
|
||||
pageX: this._dnd.start.pageX,
|
||||
pageY: this._dnd.start.pageY,
|
||||
clientX: this._dnd.start.clientX,
|
||||
clientY: this._dnd.start.clientY
|
||||
}
|
||||
}))) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._dnd.active = true;
|
||||
this._dnd.child.container.classList.add("dragging");
|
||||
this._dnd.child.container.style.position = "fixed";
|
||||
let rect = this.getBoundingClientRect();
|
||||
this._dnd.child.container.style.top = rect.top + "px";
|
||||
this._dnd.child.container.style.left = rect.left + "px";
|
||||
}
|
||||
|
||||
continueDrag() {
|
||||
if (!this._dnd.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
let left = this._dnd.child.master.offsetLeft +
|
||||
(this._dnd.last.pageX - this._dnd.start.pageX);
|
||||
let top = this._dnd.child.master.offsetTop +
|
||||
(this._dnd.last.pageY - this._dnd.start.pageY);
|
||||
this._dnd.child.container.style.transform =
|
||||
"translate(" + left + "px, " + top + "px)";
|
||||
|
||||
if (this._dnd.moveTimeout === null) {
|
||||
let delay = Math.max(0, DND_MOVE_THROTTLE -
|
||||
(this._dnd.last.timeStamp - this._dnd.lastMoveEventTime));
|
||||
this._dnd.moveTimeout = setTimeout(() => {
|
||||
this._dnd.moveTimeout = null;
|
||||
this._dnd.lastMoveEventTime = this._dnd.last.timeStamp;
|
||||
this.dispatchEvent(new CustomEvent("drag-move", {
|
||||
detail: {
|
||||
target: this._dnd.child.element,
|
||||
pageX: this._dnd.last.pageX,
|
||||
pageY: this._dnd.last.pageY,
|
||||
clientX: this._dnd.last.clientX,
|
||||
clientY: this._dnd.last.clientY
|
||||
}
|
||||
}));
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
|
||||
endDrag(event) {
|
||||
if (this._dnd.active) {
|
||||
let dropTarget = this.getChildFromPoint(this._dnd.last.clientX,
|
||||
this._dnd.last.clientY);
|
||||
|
||||
if (this.dispatchEvent(new CustomEvent("drag-end", {
|
||||
cancelable: true,
|
||||
detail: {
|
||||
target: this._dnd.child.element,
|
||||
dropTarget: dropTarget,
|
||||
pageX: this._dnd.last.pageX,
|
||||
pageY: this._dnd.last.pageY,
|
||||
clientX: this._dnd.last.clientX,
|
||||
clientY: this._dnd.last.clientY
|
||||
}
|
||||
}))) {
|
||||
let children = this._children;
|
||||
|
||||
if (dropTarget && dropTarget !== this._dnd.child.element) {
|
||||
let dropChild = null;
|
||||
let dropIndex = -1;
|
||||
let childIndex = -1;
|
||||
let insertBefore = true;
|
||||
for (let i = 0, iLen = children.length; i < iLen; i++) {
|
||||
if (children[i] === this._dnd.child) {
|
||||
childIndex = i;
|
||||
if (!dropChild) {
|
||||
insertBefore = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (children[i].element === dropTarget) {
|
||||
dropChild = children[i];
|
||||
dropIndex = i;
|
||||
}
|
||||
|
||||
if (dropIndex >= 0 && childIndex >= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dropIndex >= 0 && childIndex >= 0) {
|
||||
// Default action, rearrange the dragged child to before or after
|
||||
// the child underneath the touch/mouse point.
|
||||
this.realRemoveChild(this._dnd.child.container);
|
||||
this.realRemoveChild(this._dnd.child.master);
|
||||
this.realInsertBefore(this._dnd.child.container,
|
||||
insertBefore ? dropChild.container :
|
||||
dropChild.container.nextSibling);
|
||||
this.realInsertBefore(this._dnd.child.master,
|
||||
insertBefore ? dropChild.master :
|
||||
dropChild.master.nextSibling);
|
||||
children.splice(dropIndex, 0,
|
||||
children.splice(childIndex, 1)[0]);
|
||||
this.dispatchEvent(new CustomEvent("drag-rearrange"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this._dnd.timeout !== null) {
|
||||
let handled = !this.dispatchEvent(new CustomEvent("activate", {
|
||||
cancelable: true,
|
||||
detail: {
|
||||
target: this._dnd.child.element
|
||||
}
|
||||
}));
|
||||
if (handled) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
this.cancelDrag();
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
switch (event.type) {
|
||||
case "touchstart":
|
||||
case "mousedown":
|
||||
if (this._dnd.active || this._dnd.timeout) {
|
||||
this.cancelDrag();
|
||||
break;
|
||||
}
|
||||
|
||||
if (event instanceof MouseEvent) {
|
||||
this._dnd.start.pageX = event.pageX;
|
||||
this._dnd.start.pageY = event.pageY;
|
||||
this._dnd.start.clientX = event.clientX;
|
||||
this._dnd.start.clientY = event.clientY;
|
||||
// this._dnd.start.clientX = event.pageX;
|
||||
// this._dnd.start.clientY = event.pageY;
|
||||
} else {
|
||||
this._dnd.start.pageX = event.touches[0].pageX;
|
||||
this._dnd.start.pageY = event.touches[0].pageY;
|
||||
this._dnd.start.clientX = event.touches[0].clientX;
|
||||
this._dnd.start.clientY = event.touches[0].clientY;
|
||||
}
|
||||
|
||||
this._dnd.last.pageX = this._dnd.start.pageX;
|
||||
this._dnd.last.pageY = this._dnd.start.pageY;
|
||||
this._dnd.last.clientX = this._dnd.start.clientX;
|
||||
this._dnd.last.clientY = this._dnd.start.clientY;
|
||||
this._dnd.last.timeStamp = event.timeStamp;
|
||||
|
||||
let target = event.target;//gaia-app-icon
|
||||
|
||||
for (; target.parentNode !== this; target = target.parentNode) {
|
||||
if (target === this || !target.parentNode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the child
|
||||
let children = this._children;
|
||||
for (let child of children) {
|
||||
if (child.container === target) {
|
||||
this._dnd.child = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._dnd.child) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._dnd.delay > 0) {
|
||||
this._dnd.timeout = setTimeout(() => {
|
||||
this._dnd.timeout = null;
|
||||
this.startDrag();
|
||||
}, this._dnd.delay);
|
||||
} else {
|
||||
this.startDrag();
|
||||
}
|
||||
break;
|
||||
|
||||
case "touchmove":
|
||||
case "mousemove":
|
||||
let pageX, pageY, clientX, clientY;
|
||||
if (event instanceof MouseEvent) {
|
||||
pageX = event.pageX;
|
||||
pageY = event.pageY;
|
||||
clientX = event.clientX;
|
||||
clientY = event.clientY;
|
||||
} else {
|
||||
pageX = event.touches[0].pageX;
|
||||
pageY = event.touches[0].pageY;
|
||||
clientX = event.touches[0].clientX;
|
||||
clientY = event.touches[0].clientY;
|
||||
}
|
||||
|
||||
if (this._dnd.timeout) {
|
||||
if (Math.abs(pageX - this._dnd.start.pageX) > DND_THRESHOLD ||
|
||||
Math.abs(pageY - this._dnd.start.pageY) > DND_THRESHOLD) {
|
||||
clearTimeout(this._dnd.timeout);
|
||||
this._dnd.timeout = null;
|
||||
}
|
||||
} else if (this._dnd.active) {
|
||||
event.preventDefault();
|
||||
this._dnd.last.pageX = pageX;
|
||||
this._dnd.last.pageY = pageY;
|
||||
this._dnd.last.clientX = clientX;
|
||||
this._dnd.last.clientY = clientY;
|
||||
this._dnd.last.timeStamp = event.timeStamp;
|
||||
|
||||
this.continueDrag();
|
||||
}
|
||||
break;
|
||||
|
||||
case "touchcancel":
|
||||
this.cancelDrag();
|
||||
break;
|
||||
|
||||
case "touchend":
|
||||
case "mouseup":
|
||||
if (this._dnd.active) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
this.endDrag(event);
|
||||
break;
|
||||
|
||||
case "click":
|
||||
if (this._dnd.clickCapture) {
|
||||
this._dnd.clickCapture = false;
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
break;
|
||||
|
||||
case "contextmenu":
|
||||
if (this._dnd.active || this._dnd.timeout) {
|
||||
event.stopImmediatePropagation();
|
||||
// event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily disables element position synchronisation. Useful when adding
|
||||
* multiple elements to the container at the same time, or in quick
|
||||
* succession.
|
||||
*/
|
||||
freeze() {
|
||||
this._frozen = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables element position synchronisation after freeze() has been called.
|
||||
*/
|
||||
thaw() {
|
||||
if (this._frozen) {
|
||||
this._frozen = false;
|
||||
for (let callback of this._pendingStateChanges) {
|
||||
callback();
|
||||
}
|
||||
this._pendingStateChanges = [];
|
||||
this.synchronise();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronise positions between the managed container and all children.
|
||||
* This is called automatically when adding/inserting or removing children,
|
||||
* but must be called manually if the managed container is manipulated
|
||||
* outside of these methods (for example, if style properties change, or
|
||||
* if it's resized).
|
||||
*/
|
||||
synchronise() {
|
||||
if (this._frozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
let child;
|
||||
for (child of this._children) {
|
||||
if (!this._dnd.active || child !== this._dnd.child) {
|
||||
child.synchroniseMaster();
|
||||
}
|
||||
}
|
||||
|
||||
for (child of this._children) {
|
||||
if (!this._dnd.active || child !== this._dnd.child) {
|
||||
child.synchroniseContainer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shadowStyle = `
|
||||
:host {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
|
||||
template = `
|
||||
<slot></slot>
|
||||
<style>${this.shadowStyle}</style>
|
||||
`
|
||||
}
|
||||
|
||||
customElements.define("gaia-container", GaiaContainer);
|
|
@ -1,289 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit'
|
||||
import { customElement, property, query, state } from 'lit/decorators.js'
|
||||
|
||||
export enum HeaderBarType {
|
||||
ONLY_TIME = 'only-time',
|
||||
DATE_TIME = 'date-time'
|
||||
}
|
||||
|
||||
@customElement('header-bar')
|
||||
export class HeaderBar extends LitElement {
|
||||
@state() updateTimeTimeout!: number;
|
||||
@state() updateDateTimeout!: number;
|
||||
@property({type: HeaderBarType}) type = '';
|
||||
|
||||
@query('#time') time!: HTMLDivElement;
|
||||
@query('#date') date!: HTMLDivElement;
|
||||
|
||||
getTime(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="time-outer">
|
||||
<div id="time"></div>
|
||||
<div class="time-icons">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
getTimeAndDate(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="time-date-outer">
|
||||
<div class="time-date">
|
||||
<div id="time"></div>
|
||||
<div id="date"></div>
|
||||
</div>
|
||||
<div class="time-date-icons">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
render() {
|
||||
switch (this.type) {
|
||||
case HeaderBarType.ONLY_TIME:
|
||||
return this.getTime();
|
||||
case HeaderBarType.DATE_TIME:
|
||||
return this.getTimeAndDate();
|
||||
default:
|
||||
console.error('unhandled 【header-bar】 type');
|
||||
return nothing;
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--only-time-color-lm: #292929;
|
||||
--only-time-color-dm: #F0F0F0;
|
||||
--time-date-time-color-lm: #404040;
|
||||
--time-date-date-color-lm: #000000;
|
||||
--time-date-time-color-dm: #E0E0E0;
|
||||
--time-date-date-color-dm: #E0E0E0;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
.time-outer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.time-outer > #time {
|
||||
height: 52px;
|
||||
line-height: 52px;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 52px;
|
||||
color: var(--only-time-color-lm);
|
||||
}
|
||||
|
||||
.time-icons {
|
||||
display: flex;
|
||||
width: 136px;
|
||||
position: relative;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(*) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(:last-child) {
|
||||
position: relative;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
.time-date-outer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.time-date {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
line-height: 64px;
|
||||
vertical-align: middle;
|
||||
font-family: 'OPPOSans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.time-date > #time {
|
||||
color: var(--time-date-time-color-lm);
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
#date {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
position: relative;
|
||||
left: 22px;
|
||||
font-size: 26px;
|
||||
opacity: 0.6;
|
||||
color: var(--time-date-date-color-lm);
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
.time-date-icons {
|
||||
position: relative;
|
||||
right: 11px;
|
||||
}
|
||||
|
||||
.host([deep-mode]) .time-outer > #time {
|
||||
height: 52px;
|
||||
line-height: 52px;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 52px;
|
||||
color: var(--only-time-color-dm);
|
||||
}
|
||||
|
||||
.host([deep-mode]) .time-date > #time {
|
||||
color: var(--time-date-time-color-dm);
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
.host([deep-mode]) #date {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
position: relative;
|
||||
left: 22px;
|
||||
font-size: 26px;
|
||||
opacity: 0.6;
|
||||
color: var(--time-date-date-color-dm);
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
this.autoUpdateDateTime();
|
||||
}
|
||||
|
||||
autoUpdateDateTime() {
|
||||
switch (this.type) {
|
||||
case HeaderBarType.ONLY_TIME:
|
||||
window.clearTimeout(this.updateTimeTimeout);
|
||||
this.autoUpdateTime();
|
||||
break;
|
||||
case HeaderBarType.DATE_TIME:
|
||||
window.clearTimeout(this.updateDateTimeout);
|
||||
window.clearTimeout(this.updateTimeTimeout);
|
||||
this.autoUpdateDate();
|
||||
this.autoUpdateTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
autoUpdateTime() {
|
||||
var d = new Date();
|
||||
this.time.innerHTML = this.formatTime(d);
|
||||
let self = this;
|
||||
var remainMillisecond = (60 - d.getSeconds()) * 1000;
|
||||
this.updateTimeTimeout = window.setTimeout(() => {
|
||||
self.autoUpdateTime();
|
||||
}, remainMillisecond);
|
||||
}
|
||||
|
||||
autoUpdateDate() {
|
||||
var d = new Date();
|
||||
this.date.innerHTML = this.formatDate(d) + " " + this.getWeekDay();
|
||||
let remainMillisecond = (24 - d.getHours()) * 3600 * 1000 -
|
||||
d.getMinutes() * 60 * 1000 - d.getMilliseconds();
|
||||
let self = this;
|
||||
this.updateDateTimeout = window.setTimeout(
|
||||
function updateDateTimeout() {
|
||||
self.autoUpdateDate();
|
||||
}, remainMillisecond);
|
||||
}
|
||||
|
||||
getWeekDay() {
|
||||
var d = new Date();
|
||||
let daynumber = d.getDay();
|
||||
let day = "";
|
||||
switch (daynumber) {
|
||||
case 0:
|
||||
day = "周日";
|
||||
break;
|
||||
case 1:
|
||||
day = "周一";
|
||||
break;
|
||||
case 2:
|
||||
day = "周二";
|
||||
break;
|
||||
case 3:
|
||||
day = "周三";
|
||||
break;
|
||||
case 4:
|
||||
day = "周四";
|
||||
break;
|
||||
case 5:
|
||||
day = "周五";
|
||||
break;
|
||||
case 6:
|
||||
day = "周六";
|
||||
break;
|
||||
}
|
||||
return day;
|
||||
}
|
||||
|
||||
formatDate(d: Date | string, iso?: boolean) {
|
||||
if (d instanceof Date) {
|
||||
if (iso) {
|
||||
let date = d.toISOString(); // Thu Oct 07 2021 07:45:18 GMT+0800
|
||||
date = date.split("T")[0];
|
||||
return date;
|
||||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
formatTime(d: Date | string, iso?: boolean) {
|
||||
if (d instanceof Date) {
|
||||
if (iso) {
|
||||
let time = d.toLocaleTimeString();
|
||||
time = time.split(" ")[0];
|
||||
if (time.indexOf(":") === 1) {
|
||||
time = `0${time}`;
|
||||
}
|
||||
return time;
|
||||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// hour12: (navigator as any).mozHour12,
|
||||
hour12: false,
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (d.indexOf(":") == 1) {
|
||||
d = "0" + d;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'header-bar': HeaderBar
|
||||
}
|
||||
}
|
|
@ -1,318 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit'
|
||||
import { customElement, property, eventOptions, query, state } from 'lit/decorators.js'
|
||||
|
||||
export enum IconType {
|
||||
BASE = 'base',
|
||||
BASE_WITHOUT_BORDER = 'base-without-border',
|
||||
WITH_STATE = 'with-state'
|
||||
}
|
||||
|
||||
@customElement('icon-item')
|
||||
export class IconItem extends LitElement {
|
||||
@property({type: IconType}) type = '';
|
||||
@property({type: String}) icon = '';
|
||||
@property({type: String}) stateDesc = '';
|
||||
@property({type: String}) settingsKey = '';
|
||||
@property({type: Boolean}) bgchange = false;
|
||||
@property({type: String}) id = '';
|
||||
@property({type: Boolean}) active = false;
|
||||
@state({}) timer!: NodeJS.Timeout;
|
||||
|
||||
@query('.more-info-icon') moreInfoIcon!: HTMLDivElement;
|
||||
@query('.icon-button') iconBtn!: HTMLDivElement;
|
||||
|
||||
getbase(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-item】缺少 icon 参数');
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
:host {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
return html `
|
||||
<div class="icon-button icon-base with-border" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
||||
${iconstyle}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-item】缺少 icon 参数');
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html `
|
||||
<div class="icon-button icon-base without-border" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
getwithstate(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-item】缺少 icon 参数');
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
:host {
|
||||
width: 240px;
|
||||
height: 108px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
return html`
|
||||
<div class="icon-button icon-with-state with-border config-activity" data-icon=${this.icon} @click=${this.handleClick} @touchstart=${this.handlePress} @touchend=${this.handlePressEnd}>
|
||||
<p>${this.stateDesc}</p>
|
||||
<div class="more-info-icon" @click=${this.handleInfo} data-icon="expand-left"></div>
|
||||
${iconstyle}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@eventOptions({passive: false})
|
||||
handleClick(event: Event) {
|
||||
let isActive = true; // 闹铃
|
||||
if (this.bgchange) {
|
||||
let target = event.target as HTMLElement;
|
||||
if (target.nodeName == "P") {
|
||||
target = target.parentElement as HTMLElement;
|
||||
}
|
||||
|
||||
if (target.className == "more-info-icon") {
|
||||
target = target.parentElement as HTMLElement;
|
||||
}
|
||||
|
||||
isActive = target.classList.contains("active");
|
||||
this.activeOrInactive(isActive, target);
|
||||
}
|
||||
|
||||
// if (this.type == IconType.WITH_STATE) {
|
||||
// if (target.className == "more-info-icon") {
|
||||
// target = target.parentElement as HTMLElement;
|
||||
// }
|
||||
// if (target.classList.contains("active")) {
|
||||
// this.moreInfoIcon.dataset.icon = "expand-left";
|
||||
// } else {
|
||||
// this.moreInfoIcon.dataset.icon = "";
|
||||
// }
|
||||
// }
|
||||
|
||||
let self = this;
|
||||
window.dispatchEvent(new CustomEvent("icon-item-click", {
|
||||
detail: {
|
||||
id: self.id ? self.id : self.icon,
|
||||
isActive: isActive,
|
||||
target: self
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
handleInfo() {
|
||||
let self = this;
|
||||
window.dispatchEvent(new CustomEvent("more-info-action", {detail: self.icon}));
|
||||
}
|
||||
|
||||
handlePress(event: Event) {
|
||||
let target = event.target as HTMLElement;
|
||||
if (target.nodeName == "P") {
|
||||
target = target.parentElement as HTMLElement;
|
||||
}
|
||||
|
||||
if (this.getAttribute("disabled") === "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
let section = this.icon;
|
||||
this.timer = setTimeout(() => {
|
||||
let activity = new WebActivity("moz_configure_window", {
|
||||
data: {
|
||||
target: "device",
|
||||
section: section
|
||||
}
|
||||
});
|
||||
activity.start();
|
||||
}, 300);
|
||||
|
||||
let self = this;
|
||||
window.dispatchEvent(new CustomEvent("touch-start", {
|
||||
detail: {
|
||||
id: self.id ? self.id : self.icon,
|
||||
target: self
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
handlePressEnd() {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
|
||||
activeOrInactive(isActive: boolean, element?: HTMLElement) {
|
||||
if (element == null) {
|
||||
isActive ? this.iconBtn.classList.remove("active") :
|
||||
this.iconBtn.classList.add("active");
|
||||
this.active = isActive;
|
||||
} else {
|
||||
isActive ? element.classList.remove("active") :
|
||||
element.classList.add("active");
|
||||
}
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult | typeof nothing {
|
||||
switch (this.type) {
|
||||
case IconType.BASE:
|
||||
return this.getbase();
|
||||
case IconType.BASE_WITHOUT_BORDER:
|
||||
return this.getbaseWithOutBorder();
|
||||
case IconType.WITH_STATE:
|
||||
return this.getwithstate();
|
||||
default:
|
||||
console.error('unhandled 【icon-item】 type')
|
||||
return nothing;
|
||||
}
|
||||
}
|
||||
|
||||
addClass(className: string[]) {
|
||||
this.iconBtn.classList.add(...className);
|
||||
}
|
||||
|
||||
removeClass(className: string) {
|
||||
this.iconBtn.classList.remove(className);
|
||||
}
|
||||
|
||||
getClassList() {
|
||||
return this.iconBtn.classList;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--background-active: #1D98F5;
|
||||
--background-lm: rgba(255, 255, 255, 0.35);
|
||||
--background-dm: rgba(0, 0, 0, 0.15);
|
||||
--text-color-lm: #4D4D4D;
|
||||
--text-color-dm: #D1D1D1;
|
||||
--text-color-active: #FFFFFF;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--background-active) !important;
|
||||
color: var(--text-color-active) !important;
|
||||
}
|
||||
|
||||
.with-border {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 16px;
|
||||
background: var(--background-lm);
|
||||
}
|
||||
|
||||
.icon-button::before {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
content: attr(data-icon);
|
||||
font-size: 48px;
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.icon-with-state::before {
|
||||
position: relative;
|
||||
left: 22px;
|
||||
}
|
||||
|
||||
.icon-base {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
left: 58px;
|
||||
}
|
||||
|
||||
.more-info-icon::after {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 16px;
|
||||
content: attr(data-icon);
|
||||
font-size: 16px;
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
left: 34px;
|
||||
color: var(--text-color-lm);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 21px;
|
||||
line-height: 20px;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
.active > p {
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
|
||||
:host([deep-mode]) .with-border {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 16px;
|
||||
// border-radius: 8px;
|
||||
background: var(--background-dm);
|
||||
}
|
||||
|
||||
:host([deep-mode]) p {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
left: 34px;
|
||||
color: var(--text-color-dm);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 21px;
|
||||
line-height: 20px;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'icon-item': IconItem
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
export default class IconDB {
|
||||
db: any;
|
||||
DB_NAME = 'icon-db';
|
||||
DB_ORDER_STORE = 'order';
|
||||
DB_VERSION = 1;
|
||||
|
||||
init() {
|
||||
return new Promise((resolve: (value: void) => void, reject) => {
|
||||
var req = window.indexedDB.open(this.DB_NAME, this.DB_VERSION);
|
||||
req.onupgradeneeded = this.upgradeSchema;
|
||||
req.onsuccess = () => {
|
||||
this.db = req.result;
|
||||
resolve();
|
||||
};
|
||||
req.onerror = (e) => {
|
||||
console.error('Error opening icon db', e);
|
||||
reject(e);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
upgradeSchema(e: any) {
|
||||
var db = e.target.result;
|
||||
var fromVersion = e.oldVersion;
|
||||
if (fromVersion < 1) {
|
||||
var store = db.createObjectStore(this.DB_ORDER_STORE, { keyPath: 'id' });
|
||||
store.createIndex('order', 'order', { unique: false });
|
||||
}
|
||||
}
|
||||
|
||||
set(data: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var txn = this.db.transaction(this.DB_ORDER_STORE,
|
||||
'readwrite');
|
||||
for (var entry of data) {
|
||||
if (!entry.id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof entry.order !== 'undefined') {
|
||||
txn.objectStore(this.DB_ORDER_STORE).
|
||||
put({ id: entry.id, order: entry.order });
|
||||
}
|
||||
}
|
||||
txn.oncomplete = resolve;
|
||||
txn.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
remove(id: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var txn = this.db.transaction(this.DB_ORDER_STORE, 'readwrite');
|
||||
txn.objectStore(this.DB_ORDER_STORE).delete(id);
|
||||
txn.oncomplete = resolve;
|
||||
txn.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
getAll(onResult: Function) {
|
||||
return new Promise((resolve: (value?: any) => void) => {
|
||||
try {
|
||||
|
||||
var txn = this.db.transaction(this.DB_ORDER_STORE, 'readonly');
|
||||
var orderStore = txn.objectStore(this.DB_ORDER_STORE);
|
||||
var cursor = orderStore.index('order').openCursor();
|
||||
var results: any[] = [];
|
||||
|
||||
cursor.onsuccess = (e: any) => {
|
||||
var cursor = e.target.result;
|
||||
if (cursor) {
|
||||
var result = cursor.value;
|
||||
console.log("ffff result: ", result);
|
||||
if (onResult) {
|
||||
onResult(result);
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
|
||||
txn.oncomplete = () => {
|
||||
resolve(results);
|
||||
};
|
||||
} catch (error) {
|
||||
resolve("error");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit'
|
||||
import { customElement, property, queryAssignedElements } from 'lit/decorators.js'
|
||||
|
||||
export enum IconsOneLineType {
|
||||
BASE = 'base',
|
||||
WITH_STATE = 'with-state'
|
||||
}
|
||||
|
||||
@customElement('icons-one-line')
|
||||
export class IconsOneLine extends LitElement {
|
||||
@property({type: IconsOneLineType}) type = '';
|
||||
@property({type: Number}) count = 2;
|
||||
@queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[];
|
||||
|
||||
getbase(): HTMLTemplateResult {
|
||||
const colorstyle = this.count !== 4
|
||||
? html`
|
||||
<style>
|
||||
.icon-only > div > ::slotted(*) {
|
||||
width: calc(100% / ${this.count}) !important;
|
||||
}
|
||||
</style>
|
||||
`
|
||||
: nothing;
|
||||
return html`
|
||||
<div class="icon-only">
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
${colorstyle}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
getIconWithState(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="icon-with-state">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.count = this.slotElements.length;
|
||||
}
|
||||
|
||||
render() {
|
||||
switch (this.type) {
|
||||
case IconsOneLineType.BASE:
|
||||
return this.getbase();
|
||||
case IconsOneLineType.WITH_STATE:
|
||||
return this.getIconWithState();
|
||||
default:
|
||||
console.error('unhandled 【icons-one-line】 type')
|
||||
return nothing;
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--background-lm: #FFFFFF;
|
||||
--background-dm: #000000;
|
||||
--opacity-lm: 0.75;
|
||||
--opacity-dm: 0.25;
|
||||
--line-border-lm: rgba(0, 0, 0, 0.07);
|
||||
--line-border-dm: rgba(255, 255, 255, 0.07);
|
||||
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: var(--background-lm);
|
||||
mix-blend-mode: normal;
|
||||
opacity: var(--opacity-lm);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.icon-with-state {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: space-around;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.icon-only {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: inherit;
|
||||
border-radius: inherit;
|
||||
opacity: inherit;
|
||||
}
|
||||
|
||||
.icon-only > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
width: 25%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-left: 2px solid var(--line-border-lm);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(:first-child) {
|
||||
border-left-style: none;
|
||||
}
|
||||
|
||||
:host([deep-mode]) {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: var(--background-dm);
|
||||
mix-blend-mode: normal;
|
||||
opacity: var(--opacity-dm);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
width: 25%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-left: 2px solid var(--line-border-dm);
|
||||
border-radius: 2px;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'icons-one-line': IconsOneLine
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export * from './control-center-bar.js'
|
|
@ -1,153 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult } from 'lit'
|
||||
import { customElement, property, query } from 'lit/decorators.js'
|
||||
@customElement('light-slider')
|
||||
export class LightSlider extends LitElement {
|
||||
@query('.progress') progress!: HTMLDivElement;
|
||||
@query('.sliderBar') sliderBar!: HTMLDivElement;
|
||||
@property({type: String}) id = '';
|
||||
@property({type: String}) _coverLen = '';
|
||||
@property({type: Number}) innerWidth = 0;
|
||||
@property({type: Number}) distance = 0;
|
||||
@property({type: Number}) currentDistance = 0;
|
||||
@property({type: Number}) barWidth = 0;
|
||||
@property({type: Number}) max = 100;
|
||||
@property({type: Number}) value = 1;
|
||||
@property() touchAction = {
|
||||
// 触摸开始落点
|
||||
start: {
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
},
|
||||
|
||||
// 触摸结束落点
|
||||
last: {
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0
|
||||
}
|
||||
}
|
||||
|
||||
@property({type: String})
|
||||
get coverLen() {
|
||||
return this._coverLen;
|
||||
}
|
||||
|
||||
set coverLen(value: string) {
|
||||
this.style.setProperty('--cover-length', value);
|
||||
this._coverLen = value;
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="sliderBar" data-icon="brightness" value=${this.value} max=${this.max} @touchstart=${this} @touchmove=${this} @touchend=${this}>
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
dislay: block;
|
||||
--cover-length: 3.78px; // 亮度为1
|
||||
--background-lm: rgba(255, 255, 255, 0.5);
|
||||
--background-dm: rgba(0, 0, 0, 0.15);
|
||||
--progress-background-lm: rgba(255, 255, 255, 0.8);
|
||||
--progress-background-dm: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
.sliderBar {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background: var(--background-lm);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
width: var(--cover-length);
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
background: var(--progress-background-lm);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
position: absolute;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 29px;
|
||||
top: 29px;
|
||||
content: attr(data-icon);
|
||||
font-size: 48px;
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
if (this.value) {
|
||||
let len = Math.floor(this.value * this.sliderBar.offsetWidth / this.max);
|
||||
this.coverLen = len.toString();
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(event: TouchEvent) {
|
||||
switch (event.type) {
|
||||
case "touchstart":
|
||||
this.touchAction.start.clientX = event.touches[0].clientX;
|
||||
this.barWidth = this.sliderBar.offsetWidth;
|
||||
break;
|
||||
case "touchmove":
|
||||
this.touchAction.last.clientX = event.touches[0].clientX;
|
||||
this.distance = this.touchAction.last.clientX - this.touchAction.start.clientX;
|
||||
this.currentDistance = this.distance + this.progress.offsetWidth;
|
||||
|
||||
if (this.currentDistance < 0) {
|
||||
// this.currentDistance = 0;
|
||||
this.currentDistance = this.barWidth / this.max;
|
||||
}
|
||||
|
||||
if (this.currentDistance > this.barWidth) {
|
||||
this.currentDistance = this.barWidth;
|
||||
}
|
||||
this.progress.style.setProperty('width', this.currentDistance + 'px');
|
||||
break;
|
||||
case "touchend":
|
||||
this.value = Math.floor(this.currentDistance * this.max / this.barWidth);
|
||||
this.dispatchEvent(new CustomEvent("light-slider-change", {
|
||||
detail: {
|
||||
value: this.value
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setValue(value: number) {
|
||||
console.log("light00 set value: ", value);
|
||||
this.value = value;
|
||||
console.log("light00 set this.value: ", this.value);
|
||||
let len = Math.floor(value * this.sliderBar.offsetWidth / this.max);
|
||||
this.coverLen = len.toString();
|
||||
console.log("light00 set this.coverLen: ", this.coverLen);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'light-slider': LightSlider
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
interface Obj {
|
||||
name?: string;
|
||||
value?: any;
|
||||
callback: (name: string, value: any)=> void;
|
||||
}
|
||||
|
||||
interface Pair {
|
||||
name: string;
|
||||
value: any;
|
||||
}
|
||||
|
||||
|
||||
export var settingsObserver = {
|
||||
_keyvaluepairs: [] as Pair[], // 存放设定的设置键值对
|
||||
_observers: [] as Obj[], // 存放observe方法存入的
|
||||
|
||||
getValue: function(name: string) {
|
||||
// return new Promise((resolve: (value: any) => void) => {
|
||||
// resolve(true);
|
||||
// })
|
||||
|
||||
return new Promise(resovle => {
|
||||
let value;
|
||||
this._keyvaluepairs.forEach((pair: any) => {
|
||||
if(pair.name == name) {
|
||||
value = pair.value;
|
||||
}
|
||||
});
|
||||
return resovle(value);
|
||||
})
|
||||
},
|
||||
|
||||
observe: function(name: string, defaultValue: any, callback: (name: string, value: any)=> void, observeOnly: boolean) {
|
||||
if (!observeOnly) {
|
||||
this.getValue(name).then((value) => {
|
||||
callback(name, value !== null && value !== void 0 ? value : defaultValue); // 重启前设置值为false或0时,重启后返回的值不应该为默认值
|
||||
});
|
||||
}
|
||||
this._observers.push({
|
||||
name,
|
||||
callback
|
||||
});
|
||||
},
|
||||
|
||||
setValue: function(args: any[]) {
|
||||
return new Promise((resovle: (value: void)=> void) => {
|
||||
// 将传入的设置值更新/设置入_keyvaluepairs
|
||||
args.forEach((pair: any) => {
|
||||
let targetPair = this._keyvaluepairs.find((item: any) => {
|
||||
return item.name == pair.name
|
||||
});
|
||||
if (targetPair as any) {
|
||||
// 在_keyvaluepairs根据pair.name找到了相同的设置值,更新键值对的value
|
||||
(targetPair as any).value = pair.value;
|
||||
} else {
|
||||
// 在_keyvaluepairs不存在该设置值,新增键值对
|
||||
let newPair = {
|
||||
name: pair.name,
|
||||
value: pair.value
|
||||
};
|
||||
this._keyvaluepairs.push(newPair);
|
||||
}
|
||||
|
||||
// 同时检查_observers中是否有该设置值变化时的回调
|
||||
this._observers.forEach(ob => {
|
||||
ob.name = pair.name && ob.callback?.(pair.name, pair.value);
|
||||
});
|
||||
|
||||
resovle();
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
getBatch: function (names: string[]) {
|
||||
return new Promise((resolve: ({}) => void) => {
|
||||
let result = [];
|
||||
for (let index = 0; index < names.length; index++) {
|
||||
const name = names[index];
|
||||
let value = true;
|
||||
result.push({name, value: value});
|
||||
}
|
||||
|
||||
if (result.length == names.length) {
|
||||
resolve(result);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"name": "@star-web-components/control-center-bar",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./icon-item.js": {
|
||||
"default": "./icon-item.js"
|
||||
},
|
||||
"./icons-one-line.js": {
|
||||
"default": "./icons-one-line.js"
|
||||
},
|
||||
"./header-bar.js": {
|
||||
"default": "./header-bar.js"
|
||||
},
|
||||
"./light-slider.js": {
|
||||
"default": "./light-slider.js"
|
||||
},
|
||||
"./pull-down-menu.js": {
|
||||
"default": "./pull-down-menu.js"
|
||||
},
|
||||
"./control-center-bar.js": {
|
||||
"default": "./control-center-bar.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
import { html, css, LitElement, HTMLTemplateResult, nothing } from 'lit'
|
||||
import { customElement, property, queryAssignedElements } from 'lit/decorators.js'
|
||||
import { HeaderBarType } from './header-bar';
|
||||
import { IconItem, IconType } from './icon-item';
|
||||
import './icon-item';
|
||||
import './header-bar';
|
||||
export enum PullDownMenuType {
|
||||
HEADER_WITH_TIME = 'header-with-time',
|
||||
HEADER_WITH_DATE_TIME = 'header-with-date-time'
|
||||
}
|
||||
|
||||
@customElement('pull-down-menu')
|
||||
export class PullDownMenu extends LitElement {
|
||||
@property({type: PullDownMenuType}) type = '';
|
||||
@queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[];
|
||||
getOnlyTime(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="inner">
|
||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose" @click=${this}></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings" @click=${this}></icon-item>
|
||||
</header-bar>
|
||||
<div class="all-quick-icons">
|
||||
<slot @slotchange=${this}></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
getTimeAndDate(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="inner">
|
||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings" @click=${this}></icon-item>
|
||||
</header-bar>
|
||||
<div class="others">
|
||||
<slot @slotchange=${this}></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult | typeof nothing {
|
||||
switch (this.type) {
|
||||
case PullDownMenuType.HEADER_WITH_TIME:
|
||||
return this.getOnlyTime();
|
||||
case PullDownMenuType.HEADER_WITH_DATE_TIME:
|
||||
return this.getTimeAndDate();
|
||||
default:
|
||||
console.error('unhandled 【pull-down-menu】 type');
|
||||
return nothing;
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
:host([open]) {
|
||||
transform: translateY(0);
|
||||
transition: transform 300ms ease, visibility 300ms;
|
||||
will-change: transform;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
header-bar[type='only-time'] {
|
||||
dispaly: flex;
|
||||
width: 512px;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
header-bar[type='date-time'] {
|
||||
dispaly: flex;
|
||||
width: 860px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.all-quick-icons {
|
||||
width: 100%;
|
||||
height: calc(100% - 52px);
|
||||
position: relative;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.others {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
}
|
||||
`
|
||||
|
||||
handleEvent(event: Event) {
|
||||
switch (event.type) {
|
||||
case "click":
|
||||
switch ((event.target as IconItem).icon) {
|
||||
case "compose":
|
||||
window.dispatchEvent(new CustomEvent("editor-action"));
|
||||
break;
|
||||
case "settings":
|
||||
let activity = new WebActivity("configure", {});
|
||||
activity.start().then(() => {}, () => {});
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'pull-down-menu': PullDownMenu
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit'
|
||||
import {customElement, property, queryAssignedElements} from 'lit/decorators.js'
|
||||
import {HeaderBarType} from '../header-bar/header-bar.js'
|
||||
import {IconControlBar, IconControlBarType} from '../icon-control-bar/icon-control-bar.js'
|
||||
import {WebActivity} from './interface.js'
|
||||
import '../icon-control-bar/icon-control-bar.js'
|
||||
import '../header-bar/header-bar.js'
|
||||
export enum DropDownMenuType {
|
||||
HEADER_WITH_TIME = 'header-with-time',
|
||||
HEADER_WITH_DATE_TIME = 'header-with-date-time',
|
||||
}
|
||||
|
||||
@customElement('pull-down-menu')
|
||||
export class DropDownMenu extends LitElement {
|
||||
@property({type: DropDownMenuType}) type = ''
|
||||
@queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[]
|
||||
getOnlyTime(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="inner">
|
||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="compose"
|
||||
@click=${this}
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="settings"
|
||||
@click=${this}
|
||||
></icon-control-bar>
|
||||
</header-bar>
|
||||
<div class="all-quick-icons">
|
||||
<slot @slotchange=${this}></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
getTimeAndDate(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="inner">
|
||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="settings"
|
||||
@click=${this}
|
||||
></icon-control-bar>
|
||||
</header-bar>
|
||||
<div class="others">
|
||||
<slot @slotchange=${this}></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult | typeof nothing {
|
||||
switch (this.type) {
|
||||
case DropDownMenuType.HEADER_WITH_TIME:
|
||||
return this.getOnlyTime()
|
||||
case DropDownMenuType.HEADER_WITH_DATE_TIME:
|
||||
return this.getTimeAndDate()
|
||||
default:
|
||||
console.error('unhandled 【pull-down-menu】 type')
|
||||
return nothing
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
:host([open]) {
|
||||
transform: translateY(0);
|
||||
transition: transform 300ms ease, visibility 300ms;
|
||||
will-change: transform;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
header-bar[type='only-time'] {
|
||||
dispaly: flex;
|
||||
width: 512px;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
header-bar[type='date-time'] {
|
||||
dispaly: flex;
|
||||
width: 860px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.all-quick-icons {
|
||||
width: 100%;
|
||||
height: calc(100% - 52px);
|
||||
position: relative;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.others {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
header-bar[type='only-time'] {
|
||||
dispaly: flex;
|
||||
width: 256px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
header-bar[type='date-time'] {
|
||||
dispaly: flex;
|
||||
width: 430px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.all-quick-icons {
|
||||
width: 100%;
|
||||
height: calc(100% - 26px);
|
||||
position: relative;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
.others {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
handleEvent(event: Event) {
|
||||
switch (event.type) {
|
||||
case 'click':
|
||||
switch ((event.target as IconControlBar).icon) {
|
||||
case 'compose':
|
||||
window.dispatchEvent(new CustomEvent('editor-action'))
|
||||
break
|
||||
case 'settings':
|
||||
let activity = new WebActivity('configure', {})
|
||||
activity.start().then(
|
||||
() => {},
|
||||
() => {}
|
||||
)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'pull-down-menu': DropDownMenu
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './drop-down-menu.js'
|
|
@ -0,0 +1,9 @@
|
|||
export interface WebActivity {
|
||||
start(): Promise<any>
|
||||
cancel(): void
|
||||
}
|
||||
|
||||
export var WebActivity: {
|
||||
prototype: WebActivity
|
||||
new (name: string, data?: any): WebActivity
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/drop-down-menu",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./drop-down-menu.js": {
|
||||
"default": "./drop-down-menu.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": [
|
||||
"*.ts",
|
||||
"../icon-control-bar/icon-control-bar.js",
|
||||
"../header-bar/header-bar.js",
|
||||
"./interface.js"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,327 @@
|
|||
import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit'
|
||||
import {customElement, property, query, state} from 'lit/decorators.js'
|
||||
|
||||
export enum HeaderBarType {
|
||||
ONLY_TIME = 'only-time',
|
||||
DATE_TIME = 'date-time',
|
||||
}
|
||||
|
||||
@customElement('header-bar')
|
||||
export class HeaderBar extends LitElement {
|
||||
@state() updateTimeTimeout!: number
|
||||
@state() updateDateTimeout!: number
|
||||
@property({type: HeaderBarType}) type = ''
|
||||
|
||||
@query('#time') time!: HTMLDivElement
|
||||
@query('#date') date!: HTMLDivElement
|
||||
|
||||
getTime(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="time-outer">
|
||||
<div id="time"></div>
|
||||
<div class="time-icons">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
getTimeAndDate(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="time-date-outer">
|
||||
<div class="time-date">
|
||||
<div id="time"></div>
|
||||
<div id="date"></div>
|
||||
</div>
|
||||
<div class="time-date-icons">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
render() {
|
||||
switch (this.type) {
|
||||
case HeaderBarType.ONLY_TIME:
|
||||
return this.getTime()
|
||||
case HeaderBarType.DATE_TIME:
|
||||
return this.getTimeAndDate()
|
||||
default:
|
||||
console.error('unhandled 【header-bar】 type')
|
||||
return nothing
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--only-time-color-lm: #292929;
|
||||
--only-time-color-dm: #f0f0f0;
|
||||
--time-date-time-color-lm: #404040;
|
||||
--time-date-date-color-lm: #000000;
|
||||
--time-date-time-color-dm: #e0e0e0;
|
||||
--time-date-date-color-dm: #e0e0e0;
|
||||
width: inherit;
|
||||
height: inherit;;
|
||||
}
|
||||
|
||||
.time-outer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.time-outer > #time {
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: var(--only-time-color-lm);
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(*) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.time-date-outer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.time-date {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: end;
|
||||
vertical-align: middle;
|
||||
font-family: 'OPPOSans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.time-date > #time {
|
||||
color: var(--time-date-time-color-lm);
|
||||
}
|
||||
|
||||
#date {
|
||||
position: relative;
|
||||
opacity: 0.6;
|
||||
color: var(--time-date-date-color-lm);
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
.host([deep-mode]) .time-outer > #time {
|
||||
color: var(--only-time-color-dm);
|
||||
}
|
||||
|
||||
.host([deep-mode]) #date {
|
||||
color: var(--time-date-date-color-dm);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.time-outer > #time {
|
||||
height: 52px;
|
||||
line-height: 52px;
|
||||
font-size: 52px;
|
||||
}
|
||||
|
||||
.time-icons {
|
||||
display: flex;
|
||||
width: 136px;
|
||||
position: relative;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(:last-child) {
|
||||
position: relative;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
.time-date {
|
||||
line-height: 64px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.time-date > #time {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
#date {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
left: 22px;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.time-date-icons {
|
||||
position: relative;
|
||||
right: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.time-outer > #time {
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.time-icons {
|
||||
display: flex;
|
||||
width: 68px;
|
||||
position: relative;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(:last-child) {
|
||||
position: relative;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.time-date {
|
||||
line-height: 32px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.time-date > #time {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
#date {
|
||||
height: 17px;
|
||||
line-height: 17px;
|
||||
left: 11px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.time-date-icons {
|
||||
position: relative;
|
||||
right: 5.5px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
this.autoUpdateDateTime()
|
||||
}
|
||||
|
||||
autoUpdateDateTime() {
|
||||
switch (this.type) {
|
||||
case HeaderBarType.ONLY_TIME:
|
||||
window.clearTimeout(this.updateTimeTimeout)
|
||||
this.autoUpdateTime()
|
||||
break
|
||||
case HeaderBarType.DATE_TIME:
|
||||
window.clearTimeout(this.updateDateTimeout)
|
||||
window.clearTimeout(this.updateTimeTimeout)
|
||||
this.autoUpdateDate()
|
||||
this.autoUpdateTime()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
autoUpdateTime() {
|
||||
var d = new Date()
|
||||
this.time.innerHTML = this.formatTime(d)
|
||||
let self = this
|
||||
var remainMillisecond = (60 - d.getSeconds()) * 1000
|
||||
this.updateTimeTimeout = window.setTimeout(() => {
|
||||
self.autoUpdateTime()
|
||||
}, remainMillisecond)
|
||||
}
|
||||
|
||||
autoUpdateDate() {
|
||||
var d = new Date()
|
||||
this.date.innerHTML = this.formatDate(d) + ' ' + this.getWeekDay()
|
||||
let remainMillisecond =
|
||||
(24 - d.getHours()) * 3600 * 1000 -
|
||||
d.getMinutes() * 60 * 1000 -
|
||||
d.getMilliseconds()
|
||||
let self = this
|
||||
this.updateDateTimeout = window.setTimeout(function updateDateTimeout() {
|
||||
self.autoUpdateDate()
|
||||
}, remainMillisecond)
|
||||
}
|
||||
|
||||
getWeekDay() {
|
||||
var d = new Date()
|
||||
let daynumber = d.getDay()
|
||||
let day = ''
|
||||
switch (daynumber) {
|
||||
case 0:
|
||||
day = '周日'
|
||||
break
|
||||
case 1:
|
||||
day = '周一'
|
||||
break
|
||||
case 2:
|
||||
day = '周二'
|
||||
break
|
||||
case 3:
|
||||
day = '周三'
|
||||
break
|
||||
case 4:
|
||||
day = '周四'
|
||||
break
|
||||
case 5:
|
||||
day = '周五'
|
||||
break
|
||||
case 6:
|
||||
day = '周六'
|
||||
break
|
||||
}
|
||||
return day
|
||||
}
|
||||
|
||||
formatDate(d: Date | string, iso?: boolean) {
|
||||
if (d instanceof Date) {
|
||||
if (iso) {
|
||||
let date = d.toISOString() // Thu Oct 07 2021 07:45:18 GMT+0800
|
||||
date = date.split('T')[0]
|
||||
return date
|
||||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return d
|
||||
}
|
||||
}
|
||||
|
||||
formatTime(d: Date | string, iso?: boolean) {
|
||||
if (d instanceof Date) {
|
||||
if (iso) {
|
||||
let time = d.toLocaleTimeString()
|
||||
time = time.split(' ')[0]
|
||||
if (time.indexOf(':') === 1) {
|
||||
time = `0${time}`
|
||||
}
|
||||
return time
|
||||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// hour12: (navigator as any).mozHour12,
|
||||
hour12: false,
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (d.indexOf(':') == 1) {
|
||||
d = '0' + d
|
||||
}
|
||||
return d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'header-bar': HeaderBar
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './header-bar.js'
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/header-bar",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./header-bar.js": {
|
||||
"default": "./header-bar.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit'
|
||||
import {customElement, property, queryAssignedElements} from 'lit/decorators.js'
|
||||
|
||||
export enum IconControlBarGroupType {
|
||||
BASE = 'base',
|
||||
WITH_STATE = 'with-state',
|
||||
}
|
||||
|
||||
@customElement('icon-control-bar-group')
|
||||
export class IconControlBarGroup extends LitElement {
|
||||
@property({type: IconControlBarGroupType}) type = ''
|
||||
@property({type: Number}) count = 2
|
||||
@queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[]
|
||||
|
||||
getbase(): HTMLTemplateResult {
|
||||
const colorstyle =
|
||||
this.count !== 4
|
||||
? html`
|
||||
<style>
|
||||
.icon-only > div > ::slotted(*) {
|
||||
width: calc(100% / ${this.count}) !important;
|
||||
}
|
||||
</style>
|
||||
`
|
||||
: nothing
|
||||
return html`
|
||||
<div class="icon-only">
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
${colorstyle}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
getIconWithState(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="icon-with-state">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.count = this.slotElements.length
|
||||
}
|
||||
|
||||
render() {
|
||||
switch (this.type) {
|
||||
case IconControlBarGroupType.BASE:
|
||||
return this.getbase()
|
||||
case IconControlBarGroupType.WITH_STATE:
|
||||
return this.getIconWithState()
|
||||
default:
|
||||
console.error('unhandled 【icon-control-bar-group】 type')
|
||||
return nothing
|
||||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--background-lm: #ffffff;
|
||||
--background-dm: #000000;
|
||||
--opacity-lm: 0.75;
|
||||
--opacity-dm: 0.25;
|
||||
--line-border-lm: rgba(0, 0, 0, 0.07);
|
||||
--line-border-dm: rgba(255, 255, 255, 0.07);
|
||||
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: var(--background-lm);
|
||||
mix-blend-mode: normal;
|
||||
opacity: var(--opacity-lm);
|
||||
}
|
||||
|
||||
.icon-with-state {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: space-around;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.icon-only {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background: inherit;
|
||||
border-radius: inherit;
|
||||
opacity: inherit;
|
||||
}
|
||||
|
||||
.icon-only > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
width: 25%;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(:first-child) {
|
||||
border-left-style: none;
|
||||
}
|
||||
|
||||
:host([deep-mode]) {
|
||||
background: var(--background-dm);
|
||||
}
|
||||
|
||||
// :host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
// width: 25%;
|
||||
// // height: 30px;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
// // border-left: 2px solid var(--line-border-dm);
|
||||
// // border-radius: 2px;
|
||||
// }
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
:host {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
height: 30px;
|
||||
border-left: 2px solid var(--line-border-lm);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
border-left: 2px solid var(--line-border-dm);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
:host {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
height: 15px;
|
||||
border-left: 1px solid var(--line-border-lm);
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
border-left: 1px solid var(--line-border-dm);
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'icon-control-bar-group': IconControlBarGroup
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './icon-control-bar-group.js'
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/icon-control-bar-group",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./icon-control-bar-group.js": {
|
||||
"default": "./icon-control-bar-group.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
}
|
|
@ -0,0 +1,426 @@
|
|||
import {html, css, LitElement, HTMLTemplateResult, nothing} from 'lit'
|
||||
import {
|
||||
customElement,
|
||||
property,
|
||||
eventOptions,
|
||||
query,
|
||||
state,
|
||||
} from 'lit/decorators.js'
|
||||
import {WebActivity} from './interface.js'
|
||||
|
||||
export enum IconControlBarType {
|
||||
BASE = 'base',
|
||||
BASE_WITHOUT_BORDER = 'base-without-border',
|
||||
WITH_STATE = 'with-state',
|
||||
}
|
||||
|
||||
@customElement('icon-control-bar')
|
||||
export class IconControlBar extends LitElement {
|
||||
@property({type: IconControlBarType}) type = ''
|
||||
@property({type: String}) icon = ''
|
||||
@property({type: String}) stateDesc = ''
|
||||
@property({type: String}) settingsKey = ''
|
||||
@property({type: Boolean}) bgchange = false
|
||||
@property({type: String}) id = ''
|
||||
@property({type: Boolean}) active = false
|
||||
@state({}) timer!: NodeJS.Timeout
|
||||
|
||||
@query('.more-info-icon') moreInfoIcon!: HTMLDivElement
|
||||
@query('.icon-button') iconBtn!: HTMLDivElement
|
||||
|
||||
getbase(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-control-bar】缺少 icon 参数')
|
||||
return nothing
|
||||
}
|
||||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
@media screen and (max-width: 1200px) {
|
||||
:host {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
:host {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="icon-button icon-base with-border"
|
||||
data-icon=${this.icon}
|
||||
@click=${this.handleClick}
|
||||
@touchstart=${this.handlePress}
|
||||
@touchend=${this.handlePressEnd}
|
||||
>
|
||||
${iconstyle}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
getbaseWithOutBorder(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-control-bar】缺少 icon 参数')
|
||||
return nothing
|
||||
}
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="icon-button icon-base without-border"
|
||||
data-icon=${this.icon}
|
||||
@click=${this.handleClick}
|
||||
@touchstart=${this.handlePress}
|
||||
@touchend=${this.handlePressEnd}
|
||||
></div>
|
||||
`
|
||||
}
|
||||
|
||||
getwithstate(): HTMLTemplateResult | typeof nothing {
|
||||
if (!this.icon) {
|
||||
console.error('【icon-control-bar】缺少 icon 参数')
|
||||
return nothing
|
||||
}
|
||||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
@media screen and (max-width: 1200px) {
|
||||
:host {
|
||||
width: 240px;
|
||||
height: 108px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
:host {
|
||||
width: 120px;
|
||||
height: 54px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="icon-button icon-with-state with-border config-activity"
|
||||
data-icon=${this.icon}
|
||||
@click=${this.handleClick}
|
||||
@touchstart=${this.handlePress}
|
||||
@touchend=${this.handlePressEnd}
|
||||
>
|
||||
<p>${this.stateDesc}</p>
|
||||
<div
|
||||
class="more-info-icon"
|
||||
@click=${this.handleInfo}
|
||||
data-icon="expand-left"
|
||||
></div>
|
||||
${iconstyle}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
@eventOptions({passive: false})
|
||||
handleClick(event: Event) {
|
||||
let isActive = true // 闹铃
|
||||
if (this.bgchange) {
|
||||
let target = event.target as HTMLElement
|
||||
if (target.nodeName == 'P') {
|
||||
target = target.parentElement as HTMLElement
|
||||
}
|
||||
|
||||
if (target.className == 'more-info-icon') {
|
||||
target = target.parentElement as HTMLElement
|
||||
}
|
||||
|
||||
isActive = target.classList.contains('active')
|
||||
this.activeOrInactive(isActive, target)
|
||||
}
|
||||
|
||||
// if (this.type == IconControlBarType.WITH_STATE) {
|
||||
// if (target.className == "more-info-icon") {
|
||||
// target = target.parentElement as HTMLElement;
|
||||
// }
|
||||
// if (target.classList.contains("active")) {
|
||||
// this.moreInfoIcon.dataset.icon = "expand-left";
|
||||
// } else {
|
||||
// this.moreInfoIcon.dataset.icon = "";
|
||||
// }
|
||||
// }
|
||||
|
||||
let self = this
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('icon-control-bar-click', {
|
||||
detail: {
|
||||
id: self.id ? self.id : self.icon,
|
||||
isActive: isActive,
|
||||
target: self,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
handleInfo() {
|
||||
let self = this
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('more-info-action', {detail: self.icon})
|
||||
)
|
||||
}
|
||||
|
||||
handlePress(event: Event) {
|
||||
let target = event.target as HTMLElement
|
||||
if (target.nodeName == 'P') {
|
||||
target = target.parentElement as HTMLElement
|
||||
}
|
||||
|
||||
if (this.getAttribute('disabled') === 'true') {
|
||||
return
|
||||
}
|
||||
|
||||
let section = this.icon
|
||||
this.timer = setTimeout(() => {
|
||||
let activity = new WebActivity('moz_configure_window', {
|
||||
data: {
|
||||
target: 'device',
|
||||
section: section,
|
||||
},
|
||||
})
|
||||
activity.start()
|
||||
}, 300)
|
||||
|
||||
let self = this
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('touch-start', {
|
||||
detail: {
|
||||
id: self.id ? self.id : self.icon,
|
||||
target: self,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
handlePressEnd() {
|
||||
clearTimeout(this.timer)
|
||||
}
|
||||
|
||||
activeOrInactive(isActive: boolean, element?: HTMLElement) {
|
||||
if (element == null) {
|
||||
isActive
|
||||
? this.iconBtn.classList.remove('active')
|
||||
: this.iconBtn.classList.add('active')
|
||||
this.active = isActive
|
||||
} else {
|
||||
isActive
|
||||
? element.classList.remove('active')
|
||||
: element.classList.add('active')
|
||||
}
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult | typeof nothing {
|
||||
switch (this.type) {
|
||||
case IconControlBarType.BASE:
|
||||
return this.getbase()
|
||||
case IconControlBarType.BASE_WITHOUT_BORDER:
|
||||
return this.getbaseWithOutBorder()
|
||||
case IconControlBarType.WITH_STATE:
|
||||
return this.getwithstate()
|
||||
default:
|
||||
console.error('unhandled 【icon-control-bar】 type')
|
||||
return nothing
|
||||
}
|
||||
}
|
||||
|
||||
addClass(className: string[]) {
|
||||
this.iconBtn.classList.add(...className)
|
||||
}
|
||||
|
||||
removeClass(className: string) {
|
||||
this.iconBtn.classList.remove(className)
|
||||
}
|
||||
|
||||
getClassList() {
|
||||
return this.iconBtn.classList
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
--background-active: #1d98f5;
|
||||
--background-lm: rgba(255, 255, 255, 0.35);
|
||||
--background-dm: rgba(0, 0, 0, 0.15);
|
||||
--text-color-lm: #4d4d4d;
|
||||
--text-color-dm: #d1d1d1;
|
||||
--text-color-active: #ffffff;
|
||||
}
|
||||
|
||||
.active {
|
||||
background-color: var(--background-active) !important;
|
||||
color: var(--text-color-active) !important;
|
||||
}
|
||||
|
||||
.with-border {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--background-lm);
|
||||
}
|
||||
|
||||
.icon-button::before {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
content: attr(data-icon);
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.icon-base {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.more-info-icon::after {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
content: attr(data-icon);
|
||||
font-family: gaia-icons;
|
||||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
p {
|
||||
position: relative;
|
||||
color: var(--text-color-lm);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
.active > p {
|
||||
color: var(--text-color-active);
|
||||
}
|
||||
|
||||
:host([deep-mode]) .with-border {
|
||||
background: var(--background-dm);
|
||||
}
|
||||
|
||||
:host([deep-mode]) p {
|
||||
position: relative;
|
||||
color: var(--text-color-dm);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-family: OPPOSans;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.with-border {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.icon-button::before {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.icon-with-state::before {
|
||||
position: relative;
|
||||
left: 11px;
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: relative;
|
||||
left: 29px;
|
||||
}
|
||||
|
||||
.more-info-icon::after {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
line-height: 8px;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 50px;
|
||||
height: 10px;
|
||||
left: 17px;
|
||||
font-weight: 400;
|
||||
font-size: 10.5px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) p {
|
||||
width: 50px;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
left: 17px;
|
||||
font-weight: 400;
|
||||
font-size: 10.5px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.with-border {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.icon-button::before {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.icon-with-state::before {
|
||||
position: relative;
|
||||
left: 22px;
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
left: 58px;
|
||||
}
|
||||
|
||||
.more-info-icon::after {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
left: 34px;
|
||||
font-size: 21px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'icon-control-bar': IconControlBar
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './icon-control-bar.js'
|
|
@ -0,0 +1,9 @@
|
|||
export interface WebActivity {
|
||||
start(): Promise<any>
|
||||
cancel(): void
|
||||
}
|
||||
|
||||
export var WebActivity: {
|
||||
prototype: WebActivity
|
||||
new (name: string, data?: any): WebActivity
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/icon-control-bar",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./icon-control-bar.js": {
|
||||
"default": "./icon-control-bar.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["*.ts", "./interface.js"]
|
||||
}
|
|
@ -15,8 +15,8 @@ import './components/toast/toast'
|
|||
import './components/picker/picker'
|
||||
import './components/overflowmenu/overflowmenu'
|
||||
import './components/slider/slider'
|
||||
import './components/control-center/icon-item'
|
||||
import './components/control-center/icons-one-line'
|
||||
import './components/icon-control-bar/icon-control-bar'
|
||||
import './components/icon-control-bar-group/icon-control-bar-group'
|
||||
import './components/prompt/prompt'
|
||||
import './components/digicipher/digicipher'
|
||||
import './components/pattern-view/pattern-view'
|
||||
|
|
|
@ -1,101 +1,117 @@
|
|||
import {html, css, LitElement} from 'lit'
|
||||
import {html, LitElement} from 'lit'
|
||||
import {customElement, query} from 'lit/decorators.js'
|
||||
import {IconItem, IconType} from "../../../components/control-center/icon-item"
|
||||
import "../../../components/control-center/icon-item"
|
||||
import {IconsOneLineType} from "../../../components/control-center/icons-one-line"
|
||||
import {UlType} from "../../../components/ul/ul"
|
||||
import {HeaderBarType} from "../../../components/control-center/header-bar"
|
||||
import "../../../components/control-center/icons-one-line"
|
||||
import "../../../components/ul/ul"
|
||||
import "../../../components/control-center/header-bar"
|
||||
import "../../../components/control-center/pull-down-menu"
|
||||
import "../../../components/control-center/control-center-bar"
|
||||
import {IconControlBarType} from '../../../components/icon-control-bar/icon-control-bar'
|
||||
import '../../../components/icon-control-bar/icon-control-bar'
|
||||
import {IconControlBarGroupType} from '../../../components/icon-control-bar-group/icon-control-bar-group'
|
||||
import {UlType} from '../../../components/ul/ul'
|
||||
import {HeaderBarType} from '../../../components/header-bar/header-bar'
|
||||
import '../../../components/icon-control-bar-group/icon-control-bar-group'
|
||||
import '../../../components/ul/ul'
|
||||
import '../../../components/header-bar/header-bar'
|
||||
@customElement('panel-control-center')
|
||||
export class PanelControlCenter extends LitElement {
|
||||
@query('icon-item[icon="wifi-4"]') wifiIcon!: LitElement;
|
||||
@query('icon-item[icon="crop"]') cropBtn!: LitElement;
|
||||
@query('icon-item[icon="brightness"]') brightnessBtn!: LitElement;
|
||||
@query('icon-control-bar[icon="wifi-4"]') wifiIcon!: LitElement
|
||||
@query('icon-control-bar[icon="crop"]') cropBtn!: LitElement
|
||||
@query('icon-control-bar[icon="brightness"]') brightnessBtn!: LitElement
|
||||
render() {
|
||||
return html`
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="icon-item">
|
||||
<p>带状态的图标,点击有背景色变化,绑定settingsObserver监测值</p>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc="fgfgfhhhh" @click=${this}></icon-item>
|
||||
<br/>
|
||||
<p>基本图标</p>
|
||||
<icon-item type=${IconType.BASE} icon="crop" @click=${this}></icon-item>
|
||||
<br/>
|
||||
<p>基本图标,点击有背景色变化</p>
|
||||
<icon-item type=${IconType.BASE} icon="brightness" bgchange=true settingsKey="screen.automatic-brightness" @click=${this}></icon-item>
|
||||
<br/>
|
||||
<p>基本图标,不带边框</p>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
</star-ul>
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="icon-control-bar">
|
||||
<p>带状态的图标,点击有背景色变化,绑定settingsObserver监测值</p>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.WITH_STATE}
|
||||
icon="wifi-4"
|
||||
bgchange="true"
|
||||
settingsKey="wifi.enabled"
|
||||
stateDesc="fgfgfhhhh"
|
||||
@click=${this}
|
||||
></icon-control-bar>
|
||||
<br />
|
||||
<p>基本图标</p>
|
||||
<icon-control-bar type=${IconControlBarType.BASE} icon="crop" @click=${this}></icon-control-bar>
|
||||
<br />
|
||||
<p>基本图标,点击有背景色变化</p>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE}
|
||||
icon="brightness"
|
||||
bgchange="true"
|
||||
settingsKey="screen.automatic-brightness"
|
||||
@click=${this}
|
||||
></icon-control-bar>
|
||||
<br />
|
||||
<p>基本图标,不带边框</p>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="settings"
|
||||
></icon-control-bar>
|
||||
</star-ul>
|
||||
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="icons-one-line">
|
||||
<p>一行带状态的图标</p>
|
||||
<icons-one-line type=${IconsOneLineType.WITH_STATE}>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="wifi-4" bgchange=true settingsKey="wifi.enabled" stateDesc=""></icon-item>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="bluetooth" bgchange=true settingsKey="bluetooth.enabled"></icon-item>
|
||||
<icon-item type=${IconType.WITH_STATE} icon="data" bgchange=true settingsKey="a.enabled"></icon-item>
|
||||
</icons-one-line>
|
||||
<br/>
|
||||
<br/>
|
||||
<p>一个box框,框内是由短竖线分隔开的基本图标</p>
|
||||
<icons-one-line type=${IconsOneLineType.BASE} count=4>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="crop"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="video"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="camera"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="o"></icon-item>
|
||||
</icons-one-line>
|
||||
<br/>
|
||||
</star-ul>
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="icon-control-bar-group">
|
||||
<p>一行带状态的图标</p>
|
||||
<icon-control-bar-group type=${IconControlBarGroupType.WITH_STATE}>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.WITH_STATE}
|
||||
icon="wifi-4"
|
||||
bgchange="true"
|
||||
settingsKey="wifi.enabled"
|
||||
stateDesc=""
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.WITH_STATE}
|
||||
icon="bluetooth"
|
||||
bgchange="true"
|
||||
settingsKey="bluetooth.enabled"
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.WITH_STATE}
|
||||
icon="data"
|
||||
bgchange="true"
|
||||
settingsKey="a.enabled"
|
||||
></icon-control-bar>
|
||||
</icon-control-bar-group>
|
||||
<br />
|
||||
<br />
|
||||
<p>一个box框,框内是由短竖线分隔开的基本图标</p>
|
||||
<icon-control-bar-group type=${IconControlBarGroupType.BASE} count="4">
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="crop"
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="video"
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="camera"
|
||||
></icon-control-bar>
|
||||
<icon-control-bar type=${IconControlBarType.BASE_WITHOUT_BORDER} icon="o"></icon-control-bar>
|
||||
</icon-control-bar-group>
|
||||
<br />
|
||||
</star-ul>
|
||||
|
||||
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="header-bar">
|
||||
<p>header带时间</p>
|
||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="compose"></icon-item>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
</header-bar>
|
||||
<br/>
|
||||
<p>header带时间/日期/星期</p>
|
||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||
<icon-item type=${IconType.BASE_WITHOUT_BORDER} icon="settings"></icon-item>
|
||||
</header-bar>
|
||||
<br/>
|
||||
</star-ul>
|
||||
|
||||
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="control-center">
|
||||
<control-center>
|
||||
<panel-icon></panel-icon>
|
||||
<icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
||||
</control-center>
|
||||
</star-ul>
|
||||
`
|
||||
|
||||
// return html`
|
||||
// <control-center>
|
||||
// <panel-icon></panel-icon>
|
||||
// <icon-item type=${IconType.BASE} icon="brightness"></icon-item>
|
||||
// </control-center>
|
||||
|
||||
// `
|
||||
|
||||
// return html`
|
||||
// <control-center-bar>
|
||||
// </control-center-bar>
|
||||
// `
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
control-center-bar {
|
||||
width: 1200px;
|
||||
height: 1920px;
|
||||
}
|
||||
`;
|
||||
handleEvent(event: Event) {
|
||||
console.log("click on icon item: " + (event.target as IconItem).icon);
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="header-bar">
|
||||
<p>header带时间</p>
|
||||
<header-bar type=${HeaderBarType.ONLY_TIME}>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="compose"
|
||||
></icon-control-bar>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="settings"
|
||||
></icon-control-bar>
|
||||
</header-bar>
|
||||
<br />
|
||||
<p>header带时间/日期/星期</p>
|
||||
<header-bar type=${HeaderBarType.DATE_TIME}>
|
||||
<icon-control-bar
|
||||
type=${IconControlBarType.BASE_WITHOUT_BORDER}
|
||||
icon="settings"
|
||||
></icon-control-bar>
|
||||
</header-bar>
|
||||
<br />
|
||||
</star-ul>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,9 +119,6 @@ export class PanelRoot extends LitElement {
|
|||
<hr />
|
||||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
<<<<<<< HEAD
|
||||
label="SliderTest"
|
||||
=======
|
||||
label="开关"
|
||||
icon="switch"
|
||||
iconcolor="#EB7347"
|
||||
|
@ -131,7 +128,6 @@ export class PanelRoot extends LitElement {
|
|||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
label="滑动条"
|
||||
>>>>>>> 45627df8470c7bd87bfd6e38897cf3b896b0234d
|
||||
icon="scene"
|
||||
iconcolor="#EB7347"
|
||||
href="#slider"
|
||||
|
|
Loading…
Reference in New Issue