Merge branch 'master' of ssh://172.20.184.160:7999/yr/star-web-components into feature-pattern-New
This commit is contained in:
commit
35a7df3d63
|
@ -28,6 +28,7 @@ types/
|
|||
src/components/**/*.d.ts
|
||||
src/components/**/*.js
|
||||
src/components/**/*.js.map
|
||||
src/widgets/**/*.js
|
||||
src/lib/**/*.d.ts
|
||||
src/lib/**/*.js
|
||||
src/lib/**/*.js.map
|
||||
|
|
|
@ -25,3 +25,6 @@
|
|||
- add homescreen function for storing apps' order
|
||||
- fix bugs of container
|
||||
- add gauss blur component
|
||||
- change container's gesture function
|
||||
- fix bugs of multiple fingers in container
|
||||
- add pagination controller of container
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#! /bin/bash -e
|
||||
|
||||
cmd_run() {
|
||||
./node_modules/.bin/vite build --config ./widgets.config.ts
|
||||
}
|
||||
|
||||
cmd_particular() {
|
||||
export WIDGET_FILE_NAME=${@:1}
|
||||
cmd_run
|
||||
}
|
||||
|
||||
cmd_particular $@
|
|
@ -11,9 +11,10 @@
|
|||
],
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "yarn run esbuild:ts && yarn run build:ts",
|
||||
"build": "yarn run esbuild:ts && yarn run build:ts && yarn build:widgets",
|
||||
"build:ts": "yarn tsc --build tsconfig-all.json",
|
||||
"build:vite": "tsc && vite build",
|
||||
"build:vite": "vite build && yarn build:widgets",
|
||||
"build:widgets": "node ./tasks/build-widgets.js",
|
||||
"esbuild:ts": "node ./tasks/esbuild-packages.js",
|
||||
"format": "npm run format:prettier",
|
||||
"format:prettier": "prettier \"**/*.{cjs,html,js,json,md,ts}\" --write"
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {CSSResultArray, LitElement, ReactiveElement} from 'lit'
|
||||
import GestureDector, {
|
||||
import GestureDetector, {
|
||||
GestureEvents,
|
||||
} from '../../lib/gesture/gesture-detector.js'
|
||||
import {baseStyles} from './base-style.js'
|
||||
GestureOptions,
|
||||
} from '../../lib/gesture/gesture-detector'
|
||||
import {baseStyles} from './base-style'
|
||||
|
||||
export interface StarInterface {
|
||||
hello(): void
|
||||
|
@ -25,17 +26,19 @@ export function StarMixin<T extends Constructor<ReactiveElement>>(
|
|||
export type StarElementEventMap = HTMLElementEventMap & GestureEvents
|
||||
|
||||
export class StarBaseElement extends StarMixin(LitElement) {
|
||||
gestureDetector!: GestureDetector
|
||||
|
||||
/**
|
||||
* 启动手势监听框架
|
||||
*/
|
||||
startGestureDetector() {
|
||||
GestureDector.embedded(this)
|
||||
startGestureDetector(options?: GestureOptions) {
|
||||
GestureDetector.embedded(this, options)
|
||||
}
|
||||
/**
|
||||
* 销毁手势监听框架
|
||||
*/
|
||||
stopGestureDetector() {
|
||||
GestureDector.disembedded(this)
|
||||
GestureDetector.disembedded(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
export const sharedStyles: CSSResult = css`
|
||||
.power {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
inset: 5%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: radial-gradient(
|
||||
60.05% 60.05% at 12.24% 12.74%,
|
||||
#f7f9ff 0%,
|
||||
|
@ -16,38 +27,36 @@ export const sharedStyles: CSSResult = css`
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.percent {
|
||||
position: absolute;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 9vw;
|
||||
color: #717171;
|
||||
padding-inline-start: 40px;
|
||||
padding-inline-start: 25%;
|
||||
padding-top: 2.5%;
|
||||
}
|
||||
|
||||
.lightning {
|
||||
position: absolute;
|
||||
padding-block-end: 65px;
|
||||
width: 20px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
/*进度条为蓝色*/
|
||||
:host([blue]) .container {
|
||||
top: 250px;
|
||||
padding-block-end: 40%;
|
||||
width: 12.5%;
|
||||
height: 15%;
|
||||
}
|
||||
|
||||
/*深色模式*/
|
||||
:host([deep]) .container {
|
||||
left: 300px;
|
||||
background: linear-gradient(
|
||||
131.48deg,
|
||||
rgba(71, 71, 71, 0.8) 7.8%,
|
||||
rgba(20, 20, 20, 0.8) 87.95%
|
||||
);
|
||||
}
|
||||
|
||||
:host([deep]) .percent {
|
||||
color: #f4f4f4;
|
||||
}
|
||||
|
|
|
@ -64,10 +64,12 @@ export class StarBatterysquare extends LitElement {
|
|||
|
||||
render() {
|
||||
return html`
|
||||
<div class="container">
|
||||
<canvas class="canvas" width="160" height="160"></canvas>
|
||||
<img src="src/assets/lightning.svg" class="lightning" />
|
||||
<span class="percent">%</span>
|
||||
<div class="power">
|
||||
<div class="container">
|
||||
<canvas class="canvas" width="160px" height="160px"></canvas>
|
||||
<img src="src/assets/lightning.svg" class="lightning" />
|
||||
<span class="percent">%</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
|
|
@ -1,64 +1,67 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
export const sharedStyles: CSSResult = css`
|
||||
.holder {
|
||||
position: relative;
|
||||
width: var(--battery-width, 100%);
|
||||
height: 0;
|
||||
padding: 0;
|
||||
padding-bottom: 35.4%;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 452px;
|
||||
height: 160px;
|
||||
left: 150px;
|
||||
top: 136px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
137.64deg,
|
||||
#f5f0f5 0%,
|
||||
#fafafa 20.46%,
|
||||
#d5daf2 90.45%
|
||||
);
|
||||
border: 1px dashed rgba(116, 116, 116, 0.12);
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.power {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
right: 36.01%;
|
||||
top: 0%;
|
||||
bottom: 0%;
|
||||
background: linear-gradient(152.36deg, #6be4d0 8.74%, #10a775 82.29%);
|
||||
border-radius: 20px 0px 0px 20px;
|
||||
display: flex;
|
||||
box-shadow: 0px 0.92vw 2.3vw rgba(0, 0, 0, 0.08);
|
||||
border-radius: 4.6vw;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.power {
|
||||
position: absolute;
|
||||
left: 0%;
|
||||
right: var(--power-right);
|
||||
top: 0%;
|
||||
bottom: 0%;
|
||||
background: linear-gradient(152.36deg, #6be4d0 8.74%, #10a775 82.29%);
|
||||
border-radius: 4.6vw 0px 0px 4.6vw;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.number {
|
||||
position: absolute;
|
||||
left: 34px;
|
||||
left: 12%;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 50px;
|
||||
line-height: 66px;
|
||||
font-size: 11.5vw;
|
||||
line-height: 15.18vw;
|
||||
color: #ebc883;
|
||||
}
|
||||
|
||||
.percent {
|
||||
position: absolute;
|
||||
left: 95px;
|
||||
font-style: normal;
|
||||
left: var(--percent-left);
|
||||
font-weight: 400;
|
||||
font-size: 26px;
|
||||
line-height: 26px;
|
||||
font-size: 5.98vw;
|
||||
line-height: 5.98vw;
|
||||
color: #ebc883;
|
||||
bottom: 35%;
|
||||
padding-block-start: 4.5%;
|
||||
}
|
||||
|
||||
.lightning {
|
||||
position: absolute;
|
||||
right: 37.26px;
|
||||
right: 9%;
|
||||
top: 40%;
|
||||
width: 33.74px;
|
||||
height: 37.26px;
|
||||
width: 7.46%;
|
||||
height: 23.28%;
|
||||
}
|
||||
|
||||
.bubbles {
|
||||
|
@ -68,8 +71,8 @@ export const sharedStyles: CSSResult = css`
|
|||
rgba(255, 255, 255, 0.5) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
width: 5.52vw;
|
||||
height: 5.52vw;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: flying 10s ease-in infinite;
|
||||
|
@ -77,24 +80,24 @@ export const sharedStyles: CSSResult = css`
|
|||
|
||||
@keyframes flying {
|
||||
0% {
|
||||
left: 0%;
|
||||
transform: translateY(0px);
|
||||
top: 90%;
|
||||
transform: translateX(0vw);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(25px);
|
||||
transform: translateX(5.75vw);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(75px);
|
||||
transform: translateX(17.25vw);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-25px);
|
||||
transform: translateX(-5.75vw);
|
||||
}
|
||||
88% {
|
||||
transform: translateY(-38px);
|
||||
transform: translateX(-8.74vw);
|
||||
}
|
||||
100% {
|
||||
left: 90%;
|
||||
transform: translateY(-50px);
|
||||
top: 0%;
|
||||
transform: translateX(-11.5vw);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,335 +106,48 @@ export const sharedStyles: CSSResult = css`
|
|||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles:nth-child(2) {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
top: 10%;
|
||||
width: 4.14vw;
|
||||
height: 4.14vw;
|
||||
left: 10%;
|
||||
animation-duration: 8s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles:nth-child(3) {
|
||||
top: 20%;
|
||||
left: 20%;
|
||||
animation-duration: 5s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles:nth-child(4) {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
width: 2.3vw;
|
||||
height: 2.3vw;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles:nth-child(5) {
|
||||
top: 40%;
|
||||
left: 40%;
|
||||
animation-duration: 7s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles:nth-child(6) {
|
||||
top: 80%;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
left: 80%;
|
||||
width: 4.14vw;
|
||||
height: 4.14vw;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles:nth-child(7) {
|
||||
top: 40%;
|
||||
left: 40%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles:nth-child(8) {
|
||||
bottom: 90%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 90%;
|
||||
width: 2.3vw;
|
||||
height: 2.3vw;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
/*mini*/
|
||||
.bubbles_mini {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.5) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: flymini 10s ease-in infinite;
|
||||
}
|
||||
|
||||
@keyframes flymini {
|
||||
0% {
|
||||
left: 0%;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(6px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(19px);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-6px);
|
||||
}
|
||||
88% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
100% {
|
||||
left: 90%;
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
}
|
||||
|
||||
.bubbles_mini:nth-child(1) {
|
||||
animation-duration: 8s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_mini:nth-child(2) {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
top: 10%;
|
||||
animation-duration: 8s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_mini:nth-child(3) {
|
||||
top: 20%;
|
||||
animation-duration: 5s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_mini:nth-child(4) {
|
||||
width: 2.5px;
|
||||
height: 2.5px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_mini:nth-child(5) {
|
||||
top: 40%;
|
||||
animation-duration: 7s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_mini:nth-child(6) {
|
||||
top: 80%;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_mini:nth-child(7) {
|
||||
top: 40%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_mini:nth-child(8) {
|
||||
bottom: 90%;
|
||||
width: 2.5px;
|
||||
height: 2.5px;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
/*small*/
|
||||
.bubbles_small {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.5) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: flysmall 10s ease-in infinite;
|
||||
}
|
||||
|
||||
@keyframes flysmall {
|
||||
0% {
|
||||
left: 0%;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(12px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(38px);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
88% {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
100% {
|
||||
left: 90%;
|
||||
transform: translateY(-24px);
|
||||
}
|
||||
}
|
||||
|
||||
.bubbles_small:nth-child(1) {
|
||||
animation-duration: 8s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_small:nth-child(2) {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
top: 10%;
|
||||
animation-duration: 8s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_small:nth-child(3) {
|
||||
top: 20%;
|
||||
animation-duration: 5s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_small:nth-child(4) {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_small:nth-child(5) {
|
||||
top: 40%;
|
||||
animation-duration: 7s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_small:nth-child(6) {
|
||||
top: 80%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_small:nth-child(7) {
|
||||
top: 40%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_small:nth-child(8) {
|
||||
bottom: 90%;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
/*medium*/
|
||||
.bubbles_medium {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.5) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: flymini 10s ease-in infinite;
|
||||
}
|
||||
|
||||
@keyframes flymini {
|
||||
0% {
|
||||
left: 0%;
|
||||
transform: translateY(0px);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(18px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(57px);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-18px);
|
||||
}
|
||||
88% {
|
||||
transform: translateY(-30px);
|
||||
}
|
||||
100% {
|
||||
left: 90%;
|
||||
transform: translateY(-36px);
|
||||
}
|
||||
}
|
||||
|
||||
.bubbles_medium:nth-child(1) {
|
||||
animation-duration: 8s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_medium:nth-child(2) {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
top: 10%;
|
||||
animation-duration: 8s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_medium:nth-child(3) {
|
||||
top: 20%;
|
||||
animation-duration: 5s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_medium:nth-child(4) {
|
||||
width: 7.5px;
|
||||
height: 7.5px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.bubbles_medium:nth-child(5) {
|
||||
top: 40%;
|
||||
animation-duration: 7s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_medium:nth-child(6) {
|
||||
top: 80%;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
.bubbles_medium:nth-child(7) {
|
||||
top: 40%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
.bubbles_medium:nth-child(8) {
|
||||
bottom: 90%;
|
||||
width: 7.5px;
|
||||
height: 7.5px;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.location {
|
||||
position: absolute;
|
||||
margin-left: 200px;
|
||||
top: -215px;
|
||||
}
|
||||
|
||||
.location_charge {
|
||||
position: absolute;
|
||||
margin-left: 400px;
|
||||
}
|
||||
|
||||
.location_charge_deep {
|
||||
position: absolute;
|
||||
margin-left: 600px;
|
||||
top: -215px;
|
||||
}
|
||||
|
||||
.mini {
|
||||
position: absolute;
|
||||
top: 430px;
|
||||
}
|
||||
|
||||
.small {
|
||||
position: absolute;
|
||||
top: 530px;
|
||||
}
|
||||
|
||||
.medium {
|
||||
position: absolute;
|
||||
top: 670px;
|
||||
}
|
||||
|
||||
/*深色模式*/
|
||||
:host([deep]) .container {
|
||||
box-sizing: border-box;
|
||||
|
@ -441,109 +157,104 @@ export const sharedStyles: CSSResult = css`
|
|||
#302f33 100%
|
||||
);
|
||||
border: none;
|
||||
top: 350px;
|
||||
}
|
||||
|
||||
/*充电模式*/
|
||||
:host([charge]) .container {
|
||||
left: 700px;
|
||||
}
|
||||
|
||||
/*旋转组件*/
|
||||
:host([vertical]) .container {
|
||||
left: 1150px;
|
||||
transform: rotate(270deg);
|
||||
margin-top: 70px;
|
||||
margin-top: 50%;
|
||||
}
|
||||
:host([vertical]) .number {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
:host([vertical]) .percent {
|
||||
transform: rotate(270deg);
|
||||
left: 35px;
|
||||
bottom: 15%;
|
||||
padding-right: var(--vertical-right);
|
||||
padding-block-end: var(--vertical-end);
|
||||
}
|
||||
:host([vertical]) .lightning {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/*mini*/
|
||||
:host([mini]) .container {
|
||||
width: 113px;
|
||||
height: 40px;
|
||||
border-radius: 12px;
|
||||
.bubbles_vertical {
|
||||
position: absolute;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 255, 255, 0.5) 0%,
|
||||
rgba(255, 255, 255, 0) 100%
|
||||
);
|
||||
width: 5.52vw;
|
||||
height: 5.52vw;
|
||||
border-radius: 50%;
|
||||
opacity: 0.5;
|
||||
animation: flying-vertical 10s ease-in infinite;
|
||||
}
|
||||
:host([mini]) .power {
|
||||
border-radius: 12px 0px 0px 12px;
|
||||
}
|
||||
:host([mini]) .number {
|
||||
font-size: 12.5px;
|
||||
left: 13.5px;
|
||||
}
|
||||
:host([mini]) .percent {
|
||||
left: 24px;
|
||||
font-size: 6.5px;
|
||||
line-height: 6.5px;
|
||||
}
|
||||
:host([mini]) .lightning {
|
||||
right: 9.315px;
|
||||
width: 8.435px;
|
||||
height: 9.315px;
|
||||
}
|
||||
:host([mini]) .bubbles {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
@keyframes flying-vertical {
|
||||
0% {
|
||||
left: 0%;
|
||||
transform: translateY(0vw);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(5.75vw);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(17.25vw);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-5.75vw);
|
||||
}
|
||||
88% {
|
||||
transform: translateY(-8.74vw);
|
||||
}
|
||||
100% {
|
||||
left: 90%;
|
||||
transform: translateY(-11.5vw);
|
||||
}
|
||||
}
|
||||
|
||||
/*small*/
|
||||
:host([small]) .container {
|
||||
width: 226px;
|
||||
height: 80px;
|
||||
border-radius: 15px;
|
||||
.bubbles_vertical:nth-child(1) {
|
||||
animation-duration: 8s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
:host([small]) .power {
|
||||
border-radius: 15px 0px 0px 15px;
|
||||
.bubbles_vertical:nth-child(2) {
|
||||
width: 4.14vw;
|
||||
height: 4.14vw;
|
||||
top: 10%;
|
||||
animation-duration: 8s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
:host([small]) .number {
|
||||
font-size: 25px;
|
||||
left: 17px;
|
||||
.bubbles_vertical:nth-child(3) {
|
||||
top: 20%;
|
||||
animation-duration: 5s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
:host([small]) .percent {
|
||||
left: 48px;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
.bubbles_vertical:nth-child(4) {
|
||||
width: 2.3vw;
|
||||
height: 2.3vw;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
:host([small]) .lightning {
|
||||
right: 18.63px;
|
||||
width: 16.87px;
|
||||
height: 18.63px;
|
||||
.bubbles_vertical:nth-child(5) {
|
||||
top: 40%;
|
||||
animation-duration: 7s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
:host([small]) .bubbles {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
.bubbles_vertical:nth-child(6) {
|
||||
top: 80%;
|
||||
width: 4.14vw;
|
||||
height: 4.14vw;
|
||||
animation-duration: 6s;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
/*medium*/
|
||||
:host([medium]) .container {
|
||||
width: 339px;
|
||||
height: 120px;
|
||||
border-radius: 15px;
|
||||
.bubbles_vertical:nth-child(7) {
|
||||
top: 40%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 2s;
|
||||
}
|
||||
:host([medium]) .power {
|
||||
border-radius: 15px 0px 0px 15px;
|
||||
}
|
||||
:host([medium]) .number {
|
||||
font-size: 38px;
|
||||
left: 26px;
|
||||
}
|
||||
:host([medium]) .percent {
|
||||
left: 72px;
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
:host([medium]) .lightning {
|
||||
right: 28px;
|
||||
width: 25.3px;
|
||||
height: 28px;
|
||||
.bubbles_vertical:nth-child(8) {
|
||||
bottom: 90%;
|
||||
width: 2.3vw;
|
||||
height: 2.3vw;
|
||||
animation-duration: 9s;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {html, LitElement, CSSResultArray, nothing} from 'lit'
|
||||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement, property, query} from 'lit/decorators.js'
|
||||
import {sharedStyles} from './battery-styles'
|
||||
|
||||
|
@ -10,103 +10,71 @@ export class StarBattery extends LitElement {
|
|||
|
||||
@property({type: Boolean}) deep = false
|
||||
|
||||
@property({type: Boolean}) charge = false
|
||||
|
||||
@property({type: Boolean}) mini = false
|
||||
|
||||
@property({type: Boolean}) small = false
|
||||
|
||||
@property({type: Boolean}) medium = false
|
||||
@property({type: Boolean, reflect: true}) charge = false
|
||||
|
||||
@query('.power') _power: any
|
||||
|
||||
@query('.percent') _percent: any
|
||||
|
||||
@property({type: Boolean}) vertical = false
|
||||
@property({type: Boolean}) vertical = true
|
||||
|
||||
@property({type: Number}) percent = 22
|
||||
@property({type: Number, reflect: true}) percent = 0
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['charge', 'percent']
|
||||
}
|
||||
|
||||
attributeChangedCallback(name: string, _: any, newValue: any) {
|
||||
//console.log(name, oldValue, newValue)
|
||||
switch (name) {
|
||||
case 'charge':
|
||||
if (newValue !== null) {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
const bubbles = document.createElement('span')
|
||||
if (this.vertical == true) {
|
||||
bubbles.className = 'bubbles_vertical'
|
||||
this._power.append(bubbles)
|
||||
} else {
|
||||
bubbles.className = 'bubbles'
|
||||
this._power.append(bubbles)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._power.innerHTML = ''
|
||||
}
|
||||
break
|
||||
case 'percent':
|
||||
if (newValue !== null) {
|
||||
this.style.setProperty('--power-right', 100 - this.percent + '%')
|
||||
if (this.percent == 0) {
|
||||
this.style.setProperty('--percent-left', '19.5%')
|
||||
this.style.setProperty('--vertical-right', '13%')
|
||||
this.style.setProperty('--vertical-end', '38.5%')
|
||||
} else if (this.percent == 100) {
|
||||
this.style.setProperty('--percent-left', '31.5%')
|
||||
this.style.setProperty('--vertical-right', '25%')
|
||||
this.style.setProperty('--vertical-end', '61.5%')
|
||||
} else {
|
||||
this.style.setProperty('--percent-left', '25.5%')
|
||||
this.style.setProperty('--vertical-right', '20%')
|
||||
this.style.setProperty('--vertical-end', '50%')
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
if (this.charge == true) {
|
||||
var power = this._power
|
||||
power.style.right = this.percent + '%'
|
||||
for (var i = 0; i < 20; i++) {
|
||||
const bubbles = document.createElement('span')
|
||||
if (this.mini == true) {
|
||||
bubbles.className = 'bubbles_mini'
|
||||
} else if (this.small == true) {
|
||||
bubbles.className = 'bubbles_small'
|
||||
} else if (this.medium == true) {
|
||||
bubbles.className = 'bubbles_medium'
|
||||
} else {
|
||||
bubbles.className = 'bubbles'
|
||||
}
|
||||
power.append(bubbles)
|
||||
}
|
||||
|
||||
if (this.percent == 0) {
|
||||
if (this.mini == true) {
|
||||
this._percent.style.left = '35px'
|
||||
this._power.style.borderRadius = '12px'
|
||||
} else if (this.small == true) {
|
||||
this._percent.style.left = '60px'
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else if (this.medium == true) {
|
||||
this._percent.style.left = '90px'
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else {
|
||||
this._percent.style.left = '120px'
|
||||
this._power.style.borderRadius = '20px'
|
||||
}
|
||||
} else if (this.percent <= 2 && this.percent > 1) {
|
||||
if (this.mini == true) {
|
||||
this._power.style.borderRadius = '12px'
|
||||
} else if (this.small == true) {
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else if (this.medium == true) {
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else {
|
||||
this._power.style.borderRadius = '20px 9px 9.5px 20px'
|
||||
}
|
||||
} else if (this.percent <= 1 && this.percent > 0) {
|
||||
if (this.mini == true) {
|
||||
this._power.style.borderRadius = '12px'
|
||||
} else if (this.small == true) {
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else if (this.medium == true) {
|
||||
this._power.style.borderRadius = '15px'
|
||||
} else {
|
||||
this._power.style.borderRadius = '20px 11.5px 12px 20px'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nothing
|
||||
}
|
||||
this.charge = true
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="container">
|
||||
<div class="power">
|
||||
${this.charge == true
|
||||
? html`
|
||||
<span class="number">
|
||||
<!-- ${(100 - this.percent).toLocaleString()} -->
|
||||
${this.percent == 0
|
||||
? html`
|
||||
100
|
||||
`
|
||||
: html`
|
||||
${(100 - this.percent).toPrecision(2)}
|
||||
`}
|
||||
</span>
|
||||
`
|
||||
: html`
|
||||
<span class="number">78</span>
|
||||
`}
|
||||
<div class="holder">
|
||||
<div class="container">
|
||||
<div class="power"></div>
|
||||
<span class="number">${Math.round(this.percent)}</span>
|
||||
<span class="percent">%</span>
|
||||
</div>
|
||||
<div>
|
||||
<img src="src/assets/lightning.svg" class="lightning" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,8 @@ export class BrightnessSlider extends LitElement {
|
|||
@property({type: Number}) currentDistance = 0
|
||||
@property({type: Number}) barWidth = 0
|
||||
@property({type: Number}) max = 100
|
||||
@property({type: Number}) value = 1
|
||||
@property({type: Number}) _value = 1
|
||||
@property({type: Number}) progressLen = 0
|
||||
@property() touchAction = {
|
||||
// 触摸开始落点
|
||||
start: {
|
||||
|
@ -36,10 +37,21 @@ export class BrightnessSlider extends LitElement {
|
|||
}
|
||||
|
||||
set coverLen(value: string) {
|
||||
this.style.setProperty('--cover-length', value)
|
||||
this.style.setProperty('--cover-length', value + 'px')
|
||||
this._coverLen = value
|
||||
}
|
||||
|
||||
@property({type: Number})
|
||||
get value() {
|
||||
return this._value
|
||||
}
|
||||
|
||||
set value(value: number) {
|
||||
this._value = value
|
||||
let len = Math.round((value * this.sliderBar.offsetWidth) / this.max)
|
||||
this.coverLen = len.toString()
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div
|
||||
|
@ -61,9 +73,11 @@ export class BrightnessSlider extends LitElement {
|
|||
width: inherit;
|
||||
height: inherit;
|
||||
dislay: block;
|
||||
--cover-length: 3.78px; // 亮度为1
|
||||
--cover-length: 3.78px;
|
||||
--background-lm: rgba(255, 255, 255, 0.5);
|
||||
--background-dm: rgba(0, 0, 0, 0.15);
|
||||
--icon-color-lm: #4d4d4d;
|
||||
--icon-color-dm: #d1d1d1;
|
||||
--progress-background-lm: rgba(255, 255, 255, 0.8);
|
||||
--progress-background-dm: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
@ -93,23 +107,24 @@ export class BrightnessSlider extends LitElement {
|
|||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
color: var(--icon-color-lm);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
.sliderBar {
|
||||
border-radius: 16px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
border-radius: 16px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 29px;
|
||||
top: 29px;
|
||||
font-size: 48px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,59 +145,71 @@ export class BrightnessSlider extends LitElement {
|
|||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
if (this.value) {
|
||||
let len = Math.floor((this.value * this.sliderBar.offsetWidth) / this.max)
|
||||
this.coverLen = len.toString()
|
||||
@media screen and (min-width: 900px) {
|
||||
.sliderBar {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.sliderBar::before {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
left: 29px;
|
||||
top: 29px;
|
||||
font-size: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
handleEvent(event: TouchEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
this.touchAction.start.clientX = event.touches[0].clientX
|
||||
this.barWidth = this.sliderBar.offsetWidth
|
||||
this.progressLen =
|
||||
this.touchAction.start.clientX -
|
||||
this.sliderBar.getBoundingClientRect().left
|
||||
this.currentDistance = this.progressLen
|
||||
break
|
||||
case 'touchmove':
|
||||
event.preventDefault()
|
||||
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
|
||||
this.currentDistance = this.distance + this.progressLen
|
||||
if (this.currentDistance < this.barWidth / this.max) {
|
||||
this.currentDistance = Math.round(this.barWidth / this.max)
|
||||
}
|
||||
|
||||
if (this.currentDistance > this.barWidth) {
|
||||
this.currentDistance = this.barWidth
|
||||
}
|
||||
this.progress.style.setProperty('width', this.currentDistance + 'px')
|
||||
this.coverLen = this.currentDistance.toString()
|
||||
break
|
||||
case 'touchend':
|
||||
this.value = Math.floor(
|
||||
let preValue = this.value
|
||||
this.value = Math.round(
|
||||
(this.currentDistance * this.max) / this.barWidth
|
||||
)
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('brightness-slider-change', {
|
||||
detail: {
|
||||
value: this.value,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
|
||||
if (preValue !== this.value) {
|
||||
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 {
|
||||
|
|
|
@ -26,12 +26,13 @@ export default css`
|
|||
color: var(--font-main-black);
|
||||
font-size: var(--font-main-size);
|
||||
font-family: 'OPPOSans';
|
||||
background-color: unset;
|
||||
padding: unset;
|
||||
border: none;
|
||||
line-height: var(--line-height);
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
/* 解除默认样式 */
|
||||
border: unset;
|
||||
padding: unset;
|
||||
background: unset;
|
||||
}
|
||||
|
||||
/* different types */
|
||||
|
|
|
@ -26,6 +26,7 @@ export const sharedStyles: CSSResult = css`
|
|||
);
|
||||
}
|
||||
.star-clock-case {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -68,7 +69,7 @@ export const sharedStyles: CSSResult = css`
|
|||
width: var(--autoPoint);
|
||||
height: var(--autoPoint);
|
||||
position: absolute;
|
||||
right: 50%;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
|
@ -86,7 +87,7 @@ export const sharedStyles: CSSResult = css`
|
|||
transform-origin: 0 100%;
|
||||
display: inline-block;
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-hour 86400s linear infinite;
|
||||
animation: var(--anmiate-hour) 86400s linear infinite;
|
||||
}
|
||||
.star-clock-minute-hand {
|
||||
position: absolute;
|
||||
|
@ -96,7 +97,7 @@ export const sharedStyles: CSSResult = css`
|
|||
transform-origin: 0 100%;
|
||||
display: inline-block;
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-minute 3600s linear infinite;
|
||||
animation: var(--anmiate-minute) 3600s linear infinite;
|
||||
}
|
||||
.star-clock-second-hand {
|
||||
position: absolute;
|
||||
|
@ -106,7 +107,7 @@ export const sharedStyles: CSSResult = css`
|
|||
height: 43%;
|
||||
transform-origin: 0 calc(100% - 16px);
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-second 60s linear infinite;
|
||||
animation: var(--anmiate-second) 60s linear infinite;
|
||||
}
|
||||
/*有表盘浅色模式*/
|
||||
.star-clock-main.light {
|
||||
|
@ -166,7 +167,7 @@ export const sharedStyles: CSSResult = css`
|
|||
border-radius: 12px;
|
||||
z-index: 1;
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-hour 86400s linear infinite;
|
||||
animation: var(--anmiate-hour) 86400s linear infinite;
|
||||
}
|
||||
.star-clock-minute-hand-transparent {
|
||||
position: absolute;
|
||||
|
@ -180,7 +181,7 @@ export const sharedStyles: CSSResult = css`
|
|||
border-radius: 12px;
|
||||
z-index: 1;
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-minute 3600s linear infinite;
|
||||
animation: var(--anmiate-minute) 3600s linear infinite;
|
||||
}
|
||||
.star-clock-second-hand-transparent {
|
||||
position: absolute;
|
||||
|
@ -194,7 +195,7 @@ export const sharedStyles: CSSResult = css`
|
|||
border-radius: 12px;
|
||||
z-index: 0;
|
||||
transform: translate(-50%, 0);
|
||||
animation: anmiate-second 60s linear infinite;
|
||||
animation: var(--anmiate-second) 60s linear infinite;
|
||||
}
|
||||
/*无表盘浅色模式*/
|
||||
.star-clock-case-transparent.light .star-clock-point-transparent {
|
||||
|
|
|
@ -21,15 +21,15 @@ export class StarClock extends LitElement {
|
|||
@state() rotateHour = 0
|
||||
@state() rotateMinute = 0
|
||||
@state() rotateSecond = 0
|
||||
private _date = 0
|
||||
set date(val: number) {
|
||||
this._date = val
|
||||
|
||||
@property({type: String})
|
||||
set date(val: Date | String | Number) {
|
||||
if (val.constructor.toString().includes('String')) {
|
||||
val.toString().length <= 13 ? (val = Number(val)) : ''
|
||||
}
|
||||
val && this.dateUpdated(val)
|
||||
}
|
||||
@property({type: Number})
|
||||
get date() {
|
||||
return this._date
|
||||
}
|
||||
|
||||
@query('.star-clock')
|
||||
starClock: HTMLDivElement | undefined
|
||||
getTransparentClock() {
|
||||
|
@ -67,7 +67,8 @@ export class StarClock extends LitElement {
|
|||
>
|
||||
<span
|
||||
class="star-clock-point"
|
||||
style="transform: rotate(${-(360 / 12) * item}deg)"
|
||||
style="transform: rotate(${-(360 / 12) *
|
||||
item}deg) translate(-50%, 0)"
|
||||
></span>
|
||||
</span>
|
||||
`
|
||||
|
@ -110,8 +111,8 @@ export class StarClock extends LitElement {
|
|||
}
|
||||
}
|
||||
}
|
||||
protected dateUpdated(date: any) {
|
||||
let timeMy = new Date(Number(date))
|
||||
dateUpdated(date: any) {
|
||||
let timeMy = new Date(date)
|
||||
let hour = timeMy.getHours()
|
||||
let minute = timeMy.getMinutes()
|
||||
let second = timeMy.getSeconds()
|
||||
|
@ -128,12 +129,17 @@ export class StarClock extends LitElement {
|
|||
this.style.setProperty('--rotateSecondAfter',this.rotateSecond + 360 + 'deg')
|
||||
this.style.setProperty('--rotateMinuteAfter',this.rotateMinute + 360 + 'deg')
|
||||
this.style.setProperty('--rotateHourAfter', this.rotateHour + 360 + 'deg')
|
||||
this.resizeFun()
|
||||
this.style.setProperty('--anmiate-hour', 'anmiate-hour')
|
||||
this.style.setProperty('--anmiate-minute', 'anmiate-minute')
|
||||
this.style.setProperty('--anmiate-second', 'anmiate-second')
|
||||
}
|
||||
protected firstUpdated() {
|
||||
this.resize()
|
||||
window.addEventListener('resize', () => {
|
||||
this.resizeFun()
|
||||
this.resize()
|
||||
})
|
||||
}
|
||||
protected resizeFun(){
|
||||
protected resize() {
|
||||
let min = Math.min(
|
||||
this.starClock?.clientHeight || 100,
|
||||
this.starClock?.clientWidth || 100
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
- 由 0-9 数字组成的数字密码
|
||||
- 默认密码为 `123456`
|
||||
- 点击数字反馈,输入成功上滑,输入错误抖动反馈
|
||||
- 两分钟内记忆用户输入次数,如 : 用户输入3次错误密码后,两分钟内用户输入2次将锁定,两分钟后还原5次机会
|
||||
- 两分钟内记忆用户输入次数,如 : 用户输入 3 次错误密码后,两分钟内用户输入 2 次将锁定,两分钟后还原 5 次机会
|
||||
|
||||
## 使用
|
||||
|
||||
1. 默认情况
|
||||
|
||||
```
|
||||
<star-digicipher></star-digicipher>
|
||||
```
|
||||
|
@ -24,3 +26,6 @@
|
|||
|
||||
|
||||
|
||||
解锁成功:`star-digicipher-unlocksuccess` **value:** `this.passwd`<br>
|
||||
解锁 5 次失败,跳转已锁定:`star-digicipher-locked` **value:** `false`<br>
|
||||
完成存储:`star-digicipher-savesuccess` **value:** `this.passwd`
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
class SlotStyleHandler {
|
||||
regex: {[regStr: string]: RegExp} = {
|
||||
slottedCss: /(?:\:\:slotted\(.*\))[^{]+\{[^}]*\}/g,
|
||||
'::slotted()': /\:\:slotted\(([^\(]+)\)/g,
|
||||
keyframes: /@keyframes[^{]+\{([^{]+\{[^}]*\})*\D*\}/g,
|
||||
}
|
||||
head!: HTMLElement
|
||||
headFirstElement!: ChildNode | null
|
||||
headStyle!: HTMLElement
|
||||
shouldRefresh: boolean = false
|
||||
styles: {[styleName: string]: string} = new Proxy(
|
||||
{},
|
||||
{
|
||||
set: (
|
||||
target: {[styleName: string]: string},
|
||||
prop: string,
|
||||
value: string
|
||||
) => {
|
||||
if (!target[prop] || target[prop] !== value) {
|
||||
target[prop] = value
|
||||
this.shouldRefresh = true
|
||||
}
|
||||
return true
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
processCss(style: string, name: string) {
|
||||
let globalCss = ''
|
||||
style.replace(this.regex.keyframes, (match) => {
|
||||
globalCss += match
|
||||
return ''
|
||||
})
|
||||
style = style.replace(this.regex.slottedCss, (match) => {
|
||||
globalCss += match.replace(this.regex['::slotted()'], name + ' $1')
|
||||
return ''
|
||||
})
|
||||
|
||||
return globalCss
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CSS注入头部<style></style>
|
||||
*
|
||||
* @param {String} style
|
||||
* @param {String} name
|
||||
* @returns
|
||||
*/
|
||||
injectGlobalCss(
|
||||
component: HTMLElement,
|
||||
style: string,
|
||||
name: string,
|
||||
subName = ''
|
||||
) {
|
||||
if (!style) return
|
||||
|
||||
const styleName = subName ? `${name}-${subName}` : name
|
||||
let css = this.processCss(style, name)
|
||||
this.styles[styleName] = css
|
||||
|
||||
if (this.shouldRefresh) {
|
||||
if (!this.head || !this.headFirstElement) {
|
||||
this.head = document.head
|
||||
this.headFirstElement = this.head.firstChild
|
||||
}
|
||||
|
||||
if (!this.headStyle) {
|
||||
this.headStyle = document.createElement('style')
|
||||
if (this.headFirstElement) {
|
||||
this.head.insertBefore(this.headStyle, this.headFirstElement)
|
||||
} else {
|
||||
this.head.appendChild(this.headStyle)
|
||||
}
|
||||
}
|
||||
// 当父节点也是 Web Component时,防止全局注册的 Style 被父节点的
|
||||
// ShadowRoot 隔离,需要再在父节点中插入一份样式
|
||||
if (
|
||||
component.parentNode &&
|
||||
(Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('DocumentFragment') ||
|
||||
Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('ShadowRoot'))
|
||||
) {
|
||||
let scoped = document.createElement('style')
|
||||
scoped.innerHTML = css.trim()
|
||||
component.parentNode.appendChild(scoped)
|
||||
}
|
||||
|
||||
let style = ''
|
||||
for (const styleName in this.styles) {
|
||||
const content = this.styles[styleName]
|
||||
style += content
|
||||
}
|
||||
|
||||
this.headStyle.innerHTML = style
|
||||
this.shouldRefresh = false
|
||||
}
|
||||
}
|
||||
}
|
||||
export default new SlotStyleHandler()
|
|
@ -70,7 +70,7 @@ export default class DockChild {
|
|||
}
|
||||
|
||||
get order() {
|
||||
return Array.from(this.manager.container.children).indexOf(this.master)
|
||||
return Array.from(this.manager.children).indexOf(this.master)
|
||||
}
|
||||
|
||||
synchroniseContainer() {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
:host {
|
||||
// position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-bottom: var(--dock-margin-bottom);
|
||||
width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: auto auto 0;
|
||||
min-width: var(--dock-min-width, 100%);
|
||||
max-width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
::slotted(.dock-child-master) {
|
||||
max-width: var(--dock-grid-width, 92px);
|
||||
max-height: var(--dock-grid-width, 92px);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
::slotted(.dock-child-container) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
}
|
||||
::slotted(.dock-child-container):not(.dragging):not(.added) {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
::slotted(.dock-child-container).dragging {
|
||||
z-index: 1;
|
||||
}
|
||||
`
|
|
@ -1,7 +1,11 @@
|
|||
import {html, css, LitElement, CSSResultGroup} from 'lit'
|
||||
import {html} from 'lit'
|
||||
import {customElement, query} from 'lit/decorators.js'
|
||||
import DockChild from './dock-child'
|
||||
import customStyle from './style'
|
||||
import dockStyle from './dock-styles'
|
||||
import slotStyleHandler from './SlotStyleHandler'
|
||||
import {StarBaseElement} from '../base'
|
||||
|
||||
interface DragAndDrop {
|
||||
// Whether drag-and-drop is enabled
|
||||
enabled: boolean
|
||||
|
@ -62,9 +66,10 @@ const DEFAULT_DND_TIMEOUT = 300
|
|||
const STATE_CHANGE_TIMEOUT = 100
|
||||
|
||||
@customElement('star-dock')
|
||||
export default class StarDock extends LitElement {
|
||||
export default class StarDock extends StarBaseElement {
|
||||
@query('#container') container!: HTMLElement
|
||||
|
||||
name: string = 'star-dock'
|
||||
_children: DockChild[] = []
|
||||
_sortMode: Boolean = false
|
||||
_dragInElement: HTMLElement | undefined
|
||||
|
@ -112,6 +117,15 @@ export default class StarDock extends LitElement {
|
|||
},
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.startGestureDetector({
|
||||
panThreshold: 0,
|
||||
velocityThreshold: 0.2,
|
||||
holdThreshold: 300,
|
||||
})
|
||||
}
|
||||
|
||||
appendContainerChild = (
|
||||
element: HTMLElement,
|
||||
order?: number,
|
||||
|
@ -120,7 +134,7 @@ export default class StarDock extends LitElement {
|
|||
const child =
|
||||
this.getChildByElement(element) || new DockChild(element, this)
|
||||
this._children.push(child)
|
||||
this.container.appendChild(child.master)
|
||||
this.appendChild(child.master)
|
||||
if (typeof order == 'number') {
|
||||
child.order = order
|
||||
}
|
||||
|
@ -141,15 +155,15 @@ export default class StarDock extends LitElement {
|
|||
|
||||
realInsertBefore = (element: HTMLElement, reference: HTMLElement) => {
|
||||
element.style.order = reference.style.order
|
||||
this.container.insertBefore(element, reference)
|
||||
this.insertBefore(element, reference)
|
||||
}
|
||||
|
||||
realInsertAfter = (element: HTMLElement, reference: HTMLElement) => {
|
||||
element.style.order = reference.style.order
|
||||
if (reference.nextSibling) {
|
||||
this.container.insertBefore(element, reference.nextElementSibling)
|
||||
this.insertBefore(element, reference.nextElementSibling)
|
||||
} else {
|
||||
this.container.appendChild(element)
|
||||
this.appendChild(element)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
@ -163,25 +177,28 @@ export default class StarDock extends LitElement {
|
|||
if (mode == 'current') {
|
||||
child.master.style.order = String(child.order)
|
||||
} else if (+child.master.style.order !== child.order) {
|
||||
const insertedMaster =
|
||||
this.container.children[+child.master.style.order]
|
||||
const insertedMaster = this.children[+child.master.style.order]
|
||||
if (insertedMaster) {
|
||||
this.container.insertBefore(child.master, insertedMaster)
|
||||
this.insertBefore(child.master, insertedMaster)
|
||||
}
|
||||
}
|
||||
child.synchroniseContainer()
|
||||
}
|
||||
|
||||
this.reorderChild()
|
||||
this.recorderChild()
|
||||
if (this._children.length) {
|
||||
this._gridSize = this._children[0].master.offsetWidth
|
||||
}
|
||||
}
|
||||
|
||||
reorderChild() {
|
||||
recorderChild() {
|
||||
let children: DockChild[] = []
|
||||
let _children = [...this._children]
|
||||
const childrenElements = [...this.container.children]
|
||||
const childrenElements = [...this.children]
|
||||
|
||||
if (!_children.length || !childrenElements.length) {
|
||||
return
|
||||
}
|
||||
for (const childElement of childrenElements) {
|
||||
let child!: DockChild
|
||||
_children = _children.filter((item) => {
|
||||
|
@ -191,8 +208,7 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
return true
|
||||
})
|
||||
|
||||
children.push(child)
|
||||
child && children.push(child)
|
||||
}
|
||||
|
||||
this._children = children
|
||||
|
@ -215,7 +231,7 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
|
||||
dropPosition: 'outter' | 'inner' = 'inner'
|
||||
handleEvent(event: TouchEvent) {
|
||||
handleEvent(event: CustomEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
case 'mousedown':
|
||||
|
@ -259,30 +275,36 @@ export default class StarDock extends LitElement {
|
|||
return
|
||||
}
|
||||
|
||||
if (this._dnd.delay > 0) {
|
||||
this._dnd.timeout = window.setTimeout(() => {
|
||||
this._dnd.timeout = undefined
|
||||
this.startDrag()
|
||||
}, this._dnd.delay)
|
||||
} else {
|
||||
if (this._dnd.delay <= 0) {
|
||||
this.startDrag()
|
||||
}
|
||||
break
|
||||
|
||||
case 'touchmove':
|
||||
case 'mousemove':
|
||||
let pageX: number, pageY: number, clientX, clientY
|
||||
if (event instanceof MouseEvent) {
|
||||
pageX = event.pageX
|
||||
pageY = event.pageY
|
||||
clientX = event.clientX
|
||||
clientY = event.clientY
|
||||
} else {
|
||||
pageX = (event as TouchEvent).touches[0].pageX
|
||||
pageY = (event as TouchEvent).touches[0].pageY
|
||||
clientX = (event as TouchEvent).touches[0].clientX
|
||||
clientY = (event as TouchEvent).touches[0].clientY
|
||||
case 'holdstart':
|
||||
if (this._dnd.delay > 0) {
|
||||
this.startDrag()
|
||||
}
|
||||
break
|
||||
|
||||
case 'holdmove':
|
||||
// case 'touchmove':
|
||||
// case 'mousemove':
|
||||
let pageX: number, pageY: number, clientX, clientY
|
||||
// if (event instanceof MouseEvent) {
|
||||
// pageX = event.pageX
|
||||
// pageY = event.pageY
|
||||
// clientX = event.clientX
|
||||
// clientY = event.clientY
|
||||
// } else {
|
||||
// pageX = (event as TouchEvent).touches[0].pageX
|
||||
// pageY = (event as TouchEvent).touches[0].pageY
|
||||
// clientX = (event as TouchEvent).touches[0].clientX
|
||||
// clientY = (event as TouchEvent).touches[0].clientY
|
||||
// }
|
||||
pageX = event.detail.touches[0].pageX
|
||||
pageY = event.detail.touches[0].pageY
|
||||
clientX = event.detail.touches[0].clientX
|
||||
clientY = event.detail.touches[0].clientY
|
||||
this.distance = pageX - this._dnd.last.pageX
|
||||
|
||||
if (this._dnd.timeout) {
|
||||
|
@ -343,8 +365,9 @@ export default class StarDock extends LitElement {
|
|||
this.cancelDrag()
|
||||
break
|
||||
|
||||
case 'touchend':
|
||||
case 'mouseup':
|
||||
case 'holdend':
|
||||
// case 'touchend':
|
||||
// case 'mouseup':
|
||||
if (this._dnd.active) {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
@ -406,6 +429,7 @@ export default class StarDock extends LitElement {
|
|||
'px)'
|
||||
|
||||
if (!dropChild) {
|
||||
// this._children.pop()
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -418,19 +442,17 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
} else if (dropChild === this.container) {
|
||||
if (this._children.length && this._children[0].center.x > centerX) {
|
||||
if (this.container.firstElementChild == this._dragChild!.master)
|
||||
return true
|
||||
if (this.firstElementChild == this._dragChild!.master) return true
|
||||
|
||||
this.realInsertBefore(
|
||||
this._dragChild?.master!,
|
||||
this._children[0].master
|
||||
)
|
||||
} else {
|
||||
if (this.container.lastElementChild == this._dragChild!.master)
|
||||
return true
|
||||
if (this.lastElementChild == this._dragChild!.master) return true
|
||||
|
||||
this._dragChild!.order = this._children.length
|
||||
this.container.appendChild(this._dragChild?.master!)
|
||||
this.appendChild(this._dragChild?.master!)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,11 +634,15 @@ export default class StarDock extends LitElement {
|
|||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
this.container.addEventListener('touchstart', this)
|
||||
this.container.addEventListener('click', this)
|
||||
this.container.addEventListener('touchmove', this)
|
||||
this.container.addEventListener('touchend', this)
|
||||
this.container.addEventListener('touchcancel', this)
|
||||
slotStyleHandler.injectGlobalCss(this, dockStyle.cssText, this.name)
|
||||
this.addEventListener('touchstart', this)
|
||||
this.addEventListener('click', this)
|
||||
// this.addEventListener('touchmove', this)
|
||||
// this.addEventListener('touchend', this)
|
||||
this.addEventListener('touchcancel', this)
|
||||
this.addEventListener('holdstart', this)
|
||||
this.addEventListener('holdmove', this)
|
||||
this.addEventListener('holdend', this)
|
||||
|
||||
this.resize()
|
||||
}
|
||||
|
@ -667,7 +693,7 @@ export default class StarDock extends LitElement {
|
|||
child.container.addEventListener('animationstart', animStart)
|
||||
child.container.classList.add(state)
|
||||
|
||||
child[state] = window.window.setTimeout(() => {
|
||||
child[state] = window.setTimeout(() => {
|
||||
delete child[state]
|
||||
child.container.removeEventListener('animationstart', animStart)
|
||||
child.container.classList.remove(state)
|
||||
|
@ -679,52 +705,14 @@ export default class StarDock extends LitElement {
|
|||
|
||||
protected render() {
|
||||
return html`
|
||||
<div id="container"></div>
|
||||
<div id="container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
static styles?: CSSResultGroup | undefined = [
|
||||
customStyle,
|
||||
css`
|
||||
:host {
|
||||
// position: relative;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-bottom: var(--dock-margin-bottom);
|
||||
width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: auto auto 0;
|
||||
min-width: var(--dock-min-width, 100%);
|
||||
max-width: 100%;
|
||||
height: var(--dock-container-height);
|
||||
}
|
||||
|
||||
.dock-child-master {
|
||||
max-width: var(--dock-grid-width, 92px);
|
||||
max-height: var(--dock-grid-width, 92px);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dock-child-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
}
|
||||
.dock-child-container:not(.dragging):not(.added) {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
.dock-child-container.dragging {
|
||||
z-index: 1;
|
||||
}
|
||||
`,
|
||||
]
|
||||
static override get styles() {
|
||||
return [customStyle, dockStyle]
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
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 {
|
||||
customElement,
|
||||
property,
|
||||
query,
|
||||
queryAssignedElements,
|
||||
} from 'lit/decorators.js'
|
||||
import {HeaderBar, HeaderBarType} from '../header-bar/header-bar.js'
|
||||
import {IconControlBarType} from '../icon-control-bar/icon-control-bar.js'
|
||||
import '../icon-control-bar/icon-control-bar.js'
|
||||
import '../header-bar/header-bar.js'
|
||||
|
@ -13,6 +18,7 @@ export enum DropDownMenuType {
|
|||
export class DropDownMenu extends LitElement {
|
||||
@property({type: DropDownMenuType}) type = ''
|
||||
@queryAssignedElements({flatten: true}) slotElements!: HTMLSlotElement[]
|
||||
@query('header-bar') headerBar!: HeaderBar
|
||||
getOnlyTime(): HTMLTemplateResult {
|
||||
return html`
|
||||
<div class="inner">
|
||||
|
@ -64,6 +70,10 @@ export class DropDownMenu extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
observeTimeFormatChange() {
|
||||
this.headerBar.autoUpdateDateTime()
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
width: inherit;
|
||||
|
@ -78,38 +88,39 @@ export class DropDownMenu extends LitElement {
|
|||
}
|
||||
|
||||
.inner {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
header-bar[type='only-time'] {
|
||||
dispaly: flex;
|
||||
width: 512px;
|
||||
height: 52px;
|
||||
width: 170px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
header-bar[type='date-time'] {
|
||||
dispaly: flex;
|
||||
width: 860px;
|
||||
height: 64px;
|
||||
width: 286px;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
.all-quick-icons {
|
||||
width: 100%;
|
||||
height: calc(100% - 52px);
|
||||
height: calc(100% - 31px);
|
||||
position: relative;
|
||||
top: 40px;
|
||||
// top: 40px;
|
||||
top: 2.4%;
|
||||
}
|
||||
|
||||
.others {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
top: 33.3px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,9 +139,10 @@ export class DropDownMenu extends LitElement {
|
|||
|
||||
.all-quick-icons {
|
||||
width: 100%;
|
||||
height: calc(100% - 26px);
|
||||
height: calc(100% - 46px);
|
||||
position: relative;
|
||||
top: 20px;
|
||||
// top: 20px;
|
||||
top: 2.4%;
|
||||
}
|
||||
|
||||
.others {
|
||||
|
@ -140,6 +152,34 @@ export class DropDownMenu extends LitElement {
|
|||
top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
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% - 92px);
|
||||
position: relative;
|
||||
top: 2.4%;
|
||||
}
|
||||
|
||||
.others {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ export default css`
|
|||
:host {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-top: var(--container-margin-top);
|
||||
margin-left: var(--container-margin-left);
|
||||
margin-top: var(--container-margin-top, 0px);
|
||||
margin-left: var(--container-margin-left, 0px);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -31,11 +31,8 @@ export default css`
|
|||
|
||||
::slotted(.gaia-container-page) {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(
|
||||
var(--columns, 4),
|
||||
calc(100% / var(--columns, 4))
|
||||
);
|
||||
grid-template-rows: repeat(var(--rows, 6), calc(100% / var(--rows, 6)));
|
||||
grid-template-columns: repeat(var(--columns, 4), var(--grid-width));
|
||||
grid-template-rows: repeat(var(--rows, 6), var(--grid-height));
|
||||
grid-auto-flow: row dense;
|
||||
|
||||
grid-auto-rows: 33%;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -70,7 +70,7 @@ export default class GaiaContainerChild {
|
|||
this.priority = row * column
|
||||
this.manager = manager
|
||||
this._isStatic = false
|
||||
this.anchorCoordinate = anchorCoordinate ?? defaultCoordinate // 两种屏幕方向的锚固坐标
|
||||
this.anchorCoordinate = anchorCoordinate ?? {...defaultCoordinate} // 两种屏幕方向的锚固坐标
|
||||
this.markDirty()
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ export default class GaiaContainerChild {
|
|||
* 按记录的锚固坐标,将元素锚固到 Grid 网格中
|
||||
*/
|
||||
anchor(type: anchorType = 'recorder') {
|
||||
const area = this.getArea(type)
|
||||
const area = this.setArea(type)
|
||||
if (!area) return
|
||||
|
||||
const [rowStart, columnStart] = area
|
||||
|
@ -194,14 +194,12 @@ export default class GaiaContainerChild {
|
|||
return this.anchorCoordinate[orientation]
|
||||
}
|
||||
|
||||
const unitHeight = this.master.offsetHeight / this.row
|
||||
const unitWidth = this.master.offsetWidth / this.column
|
||||
const offsetTop = Math.abs(this.master.offsetTop)
|
||||
const offsetLeft = Math.abs(
|
||||
this.master.offsetLeft - this.pagination * this.manager.pageHeight
|
||||
)
|
||||
const rowStart = Math.floor(offsetTop / unitHeight) + 1
|
||||
const columnStart = Math.floor(offsetLeft / unitWidth) + 1
|
||||
const rowStart = Math.floor(offsetTop / this.manager.gridHeight) + 1
|
||||
const columnStart = Math.floor(offsetLeft / this.manager.gridWidth) + 1
|
||||
|
||||
return [rowStart, columnStart]
|
||||
}
|
||||
|
@ -220,8 +218,8 @@ export default class GaiaContainerChild {
|
|||
* 解除元素的锚固
|
||||
*/
|
||||
loosen() {
|
||||
const orientation = screen.orientation.type.split('-')[0]
|
||||
this.anchorCoordinate[orientation] = null
|
||||
// const orientation = screen.orientation.type.split('-')[0]
|
||||
// this.anchorCoordinate[orientation] = null
|
||||
this.master.style.gridArea = 'unset'
|
||||
this.master.style.gridRowStart = `span ${this.row}`
|
||||
this.master.style.gridColumnStart = `span ${this.column}`
|
||||
|
|
|
@ -1,19 +1,32 @@
|
|||
import GaiaContainer from './container'
|
||||
import {STATUS} from './contianer-interface'
|
||||
|
||||
class GaiaContainerPage {
|
||||
_pages: HTMLElement[] = [] // 存储所有添加进 gaia-container 的页面
|
||||
// 等待被移除的页面,仅在编辑、拖拽时出现,若结束前两种状态时仍然没有子节点,则删除
|
||||
_suspending: HTMLElement | null = null
|
||||
_suspending: HTMLElement[] = []
|
||||
_manager: GaiaContainer
|
||||
_shadowPagesMap: WeakMap<HTMLElement, HTMLElement> = new WeakMap()
|
||||
|
||||
_tail: HTMLElement | undefined
|
||||
_shadowTail: HTMLElement | undefined
|
||||
observerCallback: MutationCallback
|
||||
constructor(manager: GaiaContainer) {
|
||||
this._manager = manager
|
||||
|
||||
this._manager.addEventListener('statuschange', () => {
|
||||
// gaia-container 退出拖拽模式,且有待删除页面
|
||||
if (!(this._manager._status & 2) && this._suspending) {
|
||||
this.deletePage(this._suspending)
|
||||
if (
|
||||
!(this._manager._status & STATUS.DRAG) &&
|
||||
!(this._manager._status & STATUS.SORT) &&
|
||||
this._suspending.length
|
||||
) {
|
||||
while (this._suspending.length) {
|
||||
const page = this._suspending.shift()
|
||||
this.deletePage(page)
|
||||
}
|
||||
this.removeTail()
|
||||
this._manager.turnPre('reset')
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -26,7 +39,6 @@ class GaiaContainerPage {
|
|||
const page = mutation.target as HTMLElement
|
||||
const container = page.parentElement as any
|
||||
|
||||
page.classList.add('removed')
|
||||
const callback = () => {
|
||||
if (!container || !page.dataset.page) return
|
||||
if (
|
||||
|
@ -37,7 +49,8 @@ class GaiaContainerPage {
|
|||
}
|
||||
|
||||
if (this.editMode) {
|
||||
this._suspending = page
|
||||
// 处于编辑状态时,空白页不被删除
|
||||
this._suspending.push(page)
|
||||
} else {
|
||||
this.deletePage(page)
|
||||
}
|
||||
|
@ -90,8 +103,26 @@ class GaiaContainerPage {
|
|||
}
|
||||
}
|
||||
|
||||
addTail = () => {
|
||||
if (!this._tail || !this._shadowTail || this._tail.children.length) {
|
||||
const pages = this.addPage()
|
||||
this._tail = pages.page
|
||||
this._shadowTail = pages.shadowPage
|
||||
this._manager.addPage({page: this._tail, shadowPage: this._shadowTail})
|
||||
}
|
||||
}
|
||||
|
||||
removeTail = () => {
|
||||
if (!this._tail) return
|
||||
this.deletePage(this._tail)
|
||||
this._tail = undefined
|
||||
this._shadowTail = undefined
|
||||
}
|
||||
|
||||
get editMode() {
|
||||
return this._manager._status & 2 || this._manager._status & 8
|
||||
return (
|
||||
this._manager._status & STATUS.DRAG || this._manager._status & STATUS.SORT
|
||||
)
|
||||
}
|
||||
|
||||
observe = (page: HTMLElement) => {
|
||||
|
@ -102,39 +133,55 @@ class GaiaContainerPage {
|
|||
})
|
||||
}
|
||||
|
||||
deletePage = (page: HTMLElement) => {
|
||||
if (page.children.length) return
|
||||
deletePage = (page?: HTMLElement) => {
|
||||
if (!page || page.children.length) return
|
||||
let index = this._pages.indexOf(page)
|
||||
|
||||
if (this.editMode && index == this.length - 1) {
|
||||
// 处于拖拽状态时,尾页不被删除
|
||||
this._suspending = page
|
||||
this._suspending.push(page)
|
||||
return
|
||||
}
|
||||
delete this._pages[index]
|
||||
this._manager.dispatchEvent(
|
||||
new CustomEvent('page-change', {
|
||||
detail: {
|
||||
deleteIndex: index,
|
||||
},
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
if (this._pages.length < 2) {
|
||||
// 页面数量少于1
|
||||
return
|
||||
}
|
||||
|
||||
if (index > -1) {
|
||||
page?.remove?.()
|
||||
this._shadowPagesMap.get(page)?.remove?.()
|
||||
delete this._pages[index]
|
||||
let flag = false
|
||||
let coordinates: GaiaContainer['childCoordinate'] = []
|
||||
// @ts-ignore
|
||||
this._pages = this._pages.filter((page, i) => {
|
||||
if (flag) {
|
||||
;(page.dataset.page as any) = --i
|
||||
page.style.setProperty('--pagination', String(i))
|
||||
}
|
||||
if (i == index) flag = true
|
||||
coordinates[i] = this._manager.childCoordinate[i - +flag]
|
||||
return i !== index
|
||||
})
|
||||
this._manager.childCoordinate = coordinates
|
||||
this.sortPagination()
|
||||
|
||||
this._manager.dispatchEvent(
|
||||
new CustomEvent('page-change', {
|
||||
detail: {
|
||||
deleteIndex: index,
|
||||
},
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
this._manager.synchronise()
|
||||
}
|
||||
|
||||
sortPagination() {
|
||||
this._pages.forEach((page, i) => {
|
||||
page.dataset.page = String(i)
|
||||
page.style.setProperty('--pagination', String(i))
|
||||
this._shadowPagesMap
|
||||
.get(page)
|
||||
?.style.setProperty('--pagination', String(i))
|
||||
})
|
||||
}
|
||||
|
||||
get length() {
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
import GaiaContainer from './container'
|
||||
|
||||
class GestureManager {
|
||||
element: GaiaContainer
|
||||
touches: Touch[] = []
|
||||
swipeTimer: number | undefined = undefined
|
||||
velocity: number = 0.3
|
||||
duration: number = 10
|
||||
recorder: number = 0
|
||||
swipDirection: string = ''
|
||||
|
||||
constructor(element: GaiaContainer) {
|
||||
this.element = element
|
||||
this.listeneTouch()
|
||||
}
|
||||
|
||||
listeneTouch() {
|
||||
this.element.addEventListener('touchstart', this)
|
||||
this.element.addEventListener('touchmove', this)
|
||||
this.element.addEventListener('touchend', this)
|
||||
}
|
||||
|
||||
handleEvent(evt: TouchEvent) {
|
||||
switch (evt.type) {
|
||||
case 'touchstart':
|
||||
Array.prototype.forEach.call(evt.changedTouches, (touch: Touch) => {
|
||||
;(touch as any).timeStamp = evt.timeStamp
|
||||
this.touches[touch.identifier] = touch
|
||||
})
|
||||
break
|
||||
case 'touchmove':
|
||||
this.detectHorizonSwipe(evt)
|
||||
break
|
||||
case 'touchend':
|
||||
Array.prototype.forEach.call(
|
||||
evt.changedTouches,
|
||||
(touch) => delete this.touches[touch.identifier]
|
||||
)
|
||||
this.dispatchGesture()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
detectHorizonSwipe(event: TouchEvent) {
|
||||
const {changedTouches, timeStamp: curTime} = event
|
||||
Array.prototype.forEach.call(changedTouches, (touch) => {
|
||||
const {identifier, pageX: curX} = touch
|
||||
const {pageX: preX, timeStamp: preTime} = this.touches[identifier] as any
|
||||
const velocity = (curX - preX) / (curTime - preTime)
|
||||
this.swipDirection = velocity < 0 ? 'swipeleft' : 'swiperight'
|
||||
this.recorder = velocity
|
||||
|
||||
// TBD:暂停翻页动画,再划动手指时会出现速度计算异常
|
||||
if (Math.abs(velocity) > this.velocity) {
|
||||
clearTimeout(this.swipeTimer)
|
||||
this.swipeTimer = window.setTimeout(
|
||||
() => (this.swipeTimer = undefined),
|
||||
this.duration
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
dispatchGesture() {
|
||||
if (this.swipeTimer) {
|
||||
this.element.dispatchEvent(new Event(this.swipDirection))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default GestureManager
|
|
@ -121,44 +121,44 @@ export class HeaderBar extends LitElement {
|
|||
color: var(--time-date-date-color-dm);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
.time-outer > #time {
|
||||
height: 52px;
|
||||
line-height: 52px;
|
||||
font-size: 52px;
|
||||
height: 17px;
|
||||
line-height: 17px;
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.time-icons {
|
||||
display: flex;
|
||||
width: 136px;
|
||||
width: 45px;
|
||||
position: relative;
|
||||
right: 4px;
|
||||
right: 1px;
|
||||
}
|
||||
|
||||
.time-icons > ::slotted(:last-child) {
|
||||
position: relative;
|
||||
left: 40px;
|
||||
left: 13px;
|
||||
}
|
||||
|
||||
.time-date {
|
||||
line-height: 64px;
|
||||
left: 10px;
|
||||
line-height: 21px;
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
.time-date > #time {
|
||||
font-size: 64px;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
#date {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
left: 22px;
|
||||
font-size: 26px;
|
||||
height: 11px;
|
||||
line-height: 11px;
|
||||
left: 7px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.time-date-icons {
|
||||
position: relative;
|
||||
right: 11px;
|
||||
right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,6 +202,47 @@ export class HeaderBar extends LitElement {
|
|||
right: 5.5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
firstUpdated() {
|
||||
|
@ -248,31 +289,9 @@ export class HeaderBar extends LitElement {
|
|||
|
||||
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
|
||||
}
|
||||
let day = d.toLocaleString(navigator.languages as string[], {
|
||||
weekday: 'short',
|
||||
})
|
||||
return day
|
||||
}
|
||||
|
||||
|
@ -285,8 +304,8 @@ export class HeaderBar extends LitElement {
|
|||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
@ -304,12 +323,23 @@ export class HeaderBar extends LitElement {
|
|||
}
|
||||
return time
|
||||
} else {
|
||||
return d.toLocaleString(navigator.languages as string[], {
|
||||
// hour12: (navigator as any).mozHour12,
|
||||
hour12: false,
|
||||
d = d.toLocaleString(navigator.languages as string[], {
|
||||
hour12: (navigator as any).mozHour12,
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
})
|
||||
|
||||
if ((navigator as any).mozHour12) {
|
||||
if (d.includes('M')) {
|
||||
d = d.slice(0, -2)
|
||||
} else {
|
||||
d = d.slice(2)
|
||||
}
|
||||
}
|
||||
if (d.indexOf(':') === 1) {
|
||||
d = `0${d}`
|
||||
}
|
||||
return d
|
||||
}
|
||||
} else {
|
||||
if (d.indexOf(':') == 1) {
|
||||
|
|
|
@ -111,19 +111,19 @@ export class IconControlBarGroup extends LitElement {
|
|||
background: var(--background-dm);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
:host {
|
||||
border-radius: 16px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
height: 30px;
|
||||
border-left: 2px solid var(--line-border-lm);
|
||||
border-radius: 2px;
|
||||
height: 10px;
|
||||
border-left: 1px solid var(--line-border-lm);
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
border-left: 2px solid var(--line-border-dm);
|
||||
border-left: 1px solid var(--line-border-dm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,22 @@ export class IconControlBarGroup extends LitElement {
|
|||
border-left: 1px solid var(--line-border-dm);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.icon-only > div > ::slotted(*) {
|
||||
height: 30px;
|
||||
border-left: 2px solid var(--line-border-lm);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
:host([deep-mode]) .icon-only > div > ::slotted(*) {
|
||||
border-left: 2px solid var(--line-border-dm);
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ export class IconControlBar extends LitElement {
|
|||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
:host {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,13 @@ export class IconControlBar extends LitElement {
|
|||
height: 52px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
|
@ -90,10 +97,10 @@ export class IconControlBar extends LitElement {
|
|||
|
||||
const iconstyle = html`
|
||||
<style>
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
:host {
|
||||
width: 240px;
|
||||
height: 108px;
|
||||
width: 80px;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +110,13 @@ export class IconControlBar extends LitElement {
|
|||
height: 54px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host {
|
||||
width: 240px;
|
||||
height: 108px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
|
@ -118,7 +132,7 @@ export class IconControlBar extends LitElement {
|
|||
<div
|
||||
class="more-info-icon"
|
||||
@click=${this.handleInfo}
|
||||
data-icon="expand-left"
|
||||
data-icon="expand"
|
||||
></div>
|
||||
${iconstyle}
|
||||
</div>
|
||||
|
@ -305,20 +319,12 @@ export class IconControlBar extends LitElement {
|
|||
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;
|
||||
.active::before,
|
||||
.active > .more-info-icon::after {
|
||||
color: var(--text-color-active) !important;
|
||||
}
|
||||
|
||||
.icon-button::before,
|
||||
.more-info-icon::after {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
|
@ -327,10 +333,21 @@ export class IconControlBar extends LitElement {
|
|||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
color: var(--text-color-lm);
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-base {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
p {
|
||||
position: relative;
|
||||
left: 13.1%;
|
||||
color: var(--text-color-lm);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
@ -348,16 +365,49 @@ export class IconControlBar extends LitElement {
|
|||
background: var(--background-dm);
|
||||
}
|
||||
|
||||
:host([deep-mode]) p {
|
||||
position: relative;
|
||||
:host([deep-mode]) p,
|
||||
:host([deep-mode]) .icon-button::before,
|
||||
:host([deep-mode]) .more-info-icon::after {
|
||||
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;
|
||||
}
|
||||
|
||||
.icon-with-state::before {
|
||||
position: relative;
|
||||
left: 9.2%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 300px) {
|
||||
.with-border {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.icon-button::before {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
position: relative;
|
||||
left: 19px;
|
||||
}
|
||||
|
||||
.more-info-icon::after {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
line-height: 5px;
|
||||
font-size: 5px;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 33px;
|
||||
height: 7px;
|
||||
font-size: 7px;
|
||||
line-height: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
|
@ -372,11 +422,6 @@ export class IconControlBar extends LitElement {
|
|||
font-size: 24px;
|
||||
}
|
||||
|
||||
.icon-with-state::before {
|
||||
position: relative;
|
||||
left: 11px;
|
||||
}
|
||||
|
||||
.more-info-icon {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
|
@ -394,8 +439,6 @@ export class IconControlBar extends LitElement {
|
|||
p {
|
||||
width: 50px;
|
||||
height: 10px;
|
||||
left: 17px;
|
||||
font-weight: 400;
|
||||
font-size: 10.5px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
|
|
@ -166,24 +166,36 @@ export class StarNotificationGroup extends LitElement {
|
|||
}
|
||||
|
||||
static styles = css`
|
||||
@media screen and (min-width: 900px) {
|
||||
@media screen and (min-width: 300px) {
|
||||
:host {
|
||||
width: 860px;
|
||||
width: 286px;
|
||||
height: 50px;
|
||||
display: block;
|
||||
margin: 16px 170px 0;
|
||||
border-radius: 20px;
|
||||
margin: 5px 56px 0;
|
||||
border-radius: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 600px) {
|
||||
:host {
|
||||
width: 430px;
|
||||
height: 76px;
|
||||
display: block;
|
||||
margin: 8px 85px 0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host {
|
||||
width: 860px;
|
||||
height: 152px;
|
||||
display: block;
|
||||
margin: 16px 170px 0;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
:host([show='false']) ::slotted(*) {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export enum RadiusType {
|
|||
export class StarNotification extends LitElement {
|
||||
// 公共属性
|
||||
@property({type: String}) id = ''
|
||||
@property({type: String}) timestamp = ''
|
||||
@property({type: String}) _timestamp = ''
|
||||
@property({type: String}) src = ''
|
||||
@property({type: String}) type = ''
|
||||
@property({type: NotificationType}) notificationType = 'one-notification'
|
||||
|
@ -44,7 +44,7 @@ export class StarNotification extends LitElement {
|
|||
// 仅more-notifiactions-first有
|
||||
@property({type: String}) secondTitle = ''
|
||||
@property({type: String}) secondText = ''
|
||||
|
||||
@property({type: Boolean}) isToast = false
|
||||
@query('.notification') notification!: HTMLDivElement
|
||||
@query('.btn-tool') btnTool!: HTMLDivElement
|
||||
@query('.arrow-up') arrowUp!: HTMLDivElement
|
||||
|
@ -67,11 +67,11 @@ export class StarNotification extends LitElement {
|
|||
}
|
||||
|
||||
@property({type: String})
|
||||
get _timestamp() {
|
||||
return this.timestamp
|
||||
get timestamp() {
|
||||
return this._timestamp
|
||||
}
|
||||
set _timestamp(value: string) {
|
||||
this.timestamp = value
|
||||
set timestamp(value: string) {
|
||||
this._timestamp = value
|
||||
}
|
||||
|
||||
render(): HTMLTemplateResult | typeof nothing {
|
||||
|
@ -130,41 +130,75 @@ export class StarNotification extends LitElement {
|
|||
this.notificationType == 'more-notifiactions'
|
||||
? this.radiusType
|
||||
: 'border-radius'
|
||||
|
||||
return html`
|
||||
<div class="one">
|
||||
<div
|
||||
class="notification ${otherClass}"
|
||||
role="link"
|
||||
tabindex="0"
|
||||
data-notification-id=${this.id}
|
||||
data-no-clear=${this.noclear}
|
||||
data-obsolete-a-p-i="false"
|
||||
data-type=${this.type}
|
||||
data-manifest-u-r-l=${this.manifesturl}
|
||||
@touchstart=${this}
|
||||
@touchmove=${this}
|
||||
@touchend=${this}
|
||||
>
|
||||
<img src=${this.src} role="presentation" />
|
||||
<div class="title-container">
|
||||
<div class="title" dir="auto">${this.title}</div>
|
||||
<span class="timestamp" data-timestamp=${this.timestamp}>
|
||||
${this.timestamp}
|
||||
</span>
|
||||
if (!this.isToast) {
|
||||
return html`
|
||||
<div class="one">
|
||||
<div
|
||||
class="notification ${otherClass}"
|
||||
role="link"
|
||||
tabindex="0"
|
||||
data-notification-id=${this.id}
|
||||
data-no-clear=${this.noclear}
|
||||
data-obsolete-a-p-i="false"
|
||||
data-type=${this.type}
|
||||
data-manifest-u-r-l=${this.manifesturl}
|
||||
@touchstart=${this}
|
||||
@touchmove=${this}
|
||||
@touchend=${this}
|
||||
@click=${this}
|
||||
>
|
||||
<img src=${this.src} role="presentation" />
|
||||
<div class="title-container">
|
||||
<div class="title" dir="auto">${this.title}</div>
|
||||
<span class="timestamp" data-timestamp=${this.timestamp}>
|
||||
${this.timestamp}
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="detail-content" dir="auto">${this.text}</div>
|
||||
<span class="arrow-up" data-icon="o"></span>
|
||||
${arrowShow}
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="detail-content" dir="auto">${this.text}</div>
|
||||
<span class="arrow-up" data-icon="o"></span>
|
||||
${arrowShow}
|
||||
<div class="btn-tool">
|
||||
<div data-icon="delete" @click=${this}></div>
|
||||
<div data-icon="settings" @click=${this}></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-tool">
|
||||
<div data-icon="delete" @click=${this}></div>
|
||||
<div data-icon="settings" @click=${this}></div>
|
||||
`
|
||||
} else {
|
||||
return html`
|
||||
<div class="one">
|
||||
<div
|
||||
class="notification ${otherClass}"
|
||||
role="link"
|
||||
tabindex="0"
|
||||
data-notification-id=${this.id}
|
||||
data-no-clear=${this.noclear}
|
||||
data-obsolete-a-p-i="false"
|
||||
data-type=${this.type}
|
||||
data-manifest-u-r-l=${this.manifesturl}
|
||||
@touchstart=${this}
|
||||
@touchmove=${this}
|
||||
@touchend=${this}
|
||||
@click=${this}
|
||||
>
|
||||
<img src=${this.src} role="presentation" />
|
||||
<div class="title-container">
|
||||
<div class="title" dir="auto">${this.title}</div>
|
||||
<span class="timestamp" data-timestamp=${this.timestamp}>
|
||||
${this.timestamp}
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail">
|
||||
<div class="detail-content" dir="auto">${this.text}</div>
|
||||
<span class="arrow-up" data-icon="o"></span>
|
||||
${arrowShow}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
getmorefirst(): HTMLTemplateResult | typeof nothing {
|
||||
|
@ -223,6 +257,7 @@ export class StarNotification extends LitElement {
|
|||
@touchstart=${this}
|
||||
@touchmove=${this}
|
||||
@touchend=${this}
|
||||
@click=${this}
|
||||
>
|
||||
<img src=${this.src} role="presentation" />
|
||||
<div class="container one-container">
|
||||
|
@ -248,94 +283,141 @@ export class StarNotification extends LitElement {
|
|||
|
||||
@eventOptions({passive: false})
|
||||
handleEvent(event: TouchEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
this.touchAction.start.clientX = event.touches[0].clientX
|
||||
this.btnTool.style.visibility = 'visiable'
|
||||
break
|
||||
case 'touchmove':
|
||||
this.touchAction.last.clientX = event.touches[0].clientX
|
||||
let touchPosX =
|
||||
this.touchAction.last.clientX - this.touchAction.start.clientX
|
||||
// if (Math.abs(touchPosX) > 266) {
|
||||
// touchPosX = 266;
|
||||
// }
|
||||
|
||||
// this.notification.style.transform = 'translateX(' + touchPosX + 'px)';
|
||||
if (touchPosX < 0) {
|
||||
// if (Math.abs(touchPosX) > 18) {
|
||||
// (this.btnTool.children[1] as HTMLElement).style.visibility = "visible";
|
||||
// }
|
||||
// if (Math.abs(touchPosX) > 142) {
|
||||
// (this.btnTool.children[0] as HTMLElement).style.visibility = "visible";
|
||||
if (!this.isToast) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
this.touchAction.start.clientX = event.touches[0].clientX
|
||||
this.btnTool.style.visibility = 'visiable'
|
||||
break
|
||||
case 'touchmove':
|
||||
event.preventDefault()
|
||||
let deleteBtn = this.btnTool.children[0] as HTMLElement
|
||||
let settingsBtn = this.btnTool.children[1] as HTMLElement
|
||||
this.touchAction.last.clientX = event.touches[0].clientX
|
||||
let touchPosX =
|
||||
this.touchAction.last.clientX - this.touchAction.start.clientX
|
||||
// if (Math.abs(touchPosX) > 266) {
|
||||
// touchPosX = 266;
|
||||
// }
|
||||
|
||||
// if (Math.abs(touchPosX) > 222) {
|
||||
// (this.btnTool.children[1] as HTMLElement).style.opacity = "1";
|
||||
// (this.btnTool.children[0] as HTMLElement).style.opacity = "1";
|
||||
// }
|
||||
;(this.btnTool.children[0] as HTMLElement).style.visibility =
|
||||
'visible'
|
||||
;(this.btnTool.children[1] as HTMLElement).style.visibility =
|
||||
'visible'
|
||||
;(this.btnTool.children[0] as HTMLElement).style.opacity = '1'
|
||||
;(this.btnTool.children[1] as HTMLElement).style.opacity = '1'
|
||||
let translateX
|
||||
if (screen.width >= 900) {
|
||||
translateX = 266
|
||||
} else {
|
||||
translateX = 133
|
||||
// this.notification.style.transform = 'translateX(' + touchPosX + 'px)';
|
||||
if (touchPosX < 0) {
|
||||
// if (Math.abs(touchPosX) > 18) {
|
||||
// (this.btnTool.children[1] as HTMLElement).style.visibility = "visible";
|
||||
// }
|
||||
// if (Math.abs(touchPosX) > 142) {
|
||||
// (this.btnTool.children[0] as HTMLElement).style.visibility = "visible";
|
||||
// }
|
||||
|
||||
// if (Math.abs(touchPosX) > 222) {
|
||||
// (this.btnTool.children[1] as HTMLElement).style.opacity = "1";
|
||||
// (this.btnTool.children[0] as HTMLElement).style.opacity = "1";
|
||||
// }
|
||||
let translateX
|
||||
if (screen.width >= 900) {
|
||||
translateX = 266
|
||||
} else if (screen.width >= 600) {
|
||||
translateX = 133
|
||||
} else {
|
||||
translateX = 88
|
||||
}
|
||||
this.notification.style.transform =
|
||||
'translateX(-' + translateX + 'px)'
|
||||
let self = this
|
||||
this.notification.addEventListener(
|
||||
'transitionend',
|
||||
function tranEnd() {
|
||||
self.notification.removeEventListener('transitionend', tranEnd)
|
||||
deleteBtn.style.visibility = 'visible'
|
||||
settingsBtn.style.visibility = 'visible'
|
||||
deleteBtn.style.opacity = '1'
|
||||
settingsBtn.style.opacity = '1'
|
||||
}
|
||||
)
|
||||
} else if (touchPosX > 0) {
|
||||
// if (touchPosX > 44) {
|
||||
// (this.btnTool.children[0] as any).style.opacity = 0.6;
|
||||
// }
|
||||
|
||||
// if (touchPosX > 124) {
|
||||
// (this.btnTool.children[0] as any).style.visibility = "hidden";
|
||||
// }
|
||||
|
||||
// if (touchPosX > 168) {
|
||||
// (this.btnTool.children[1] as any).style.opacity = 0.6;
|
||||
// }
|
||||
|
||||
// if (touchPosX > 248) {
|
||||
// (this.btnTool.children[1] as any).style.visibility = "hidden";
|
||||
// }
|
||||
deleteBtn.style.visibility = 'hidden'
|
||||
settingsBtn.style.visibility = 'hidden'
|
||||
this.notification.style.transform = 'translateX(' + 0 + 'px)'
|
||||
}
|
||||
this.notification.style.transform =
|
||||
'translateX(-' + translateX + 'px)'
|
||||
} else {
|
||||
// if (touchPosX > 44) {
|
||||
// (this.btnTool.children[0] as any).style.opacity = 0.6;
|
||||
// }
|
||||
|
||||
// if (touchPosX > 124) {
|
||||
// (this.btnTool.children[0] as any).style.visibility = "hidden";
|
||||
// }
|
||||
|
||||
// if (touchPosX > 168) {
|
||||
// (this.btnTool.children[1] as any).style.opacity = 0.6;
|
||||
// }
|
||||
|
||||
// if (touchPosX > 248) {
|
||||
// (this.btnTool.children[1] as any).style.visibility = "hidden";
|
||||
// }
|
||||
;(this.btnTool.children[0] as any).style.visibility = 'hidden'
|
||||
;(this.btnTool.children[1] as any).style.visibility = 'hidden'
|
||||
this.notification.style.transform = 'translateX(' + 0 + 'px)'
|
||||
}
|
||||
break
|
||||
case 'touchend':
|
||||
break
|
||||
case 'click':
|
||||
event.stopPropagation()
|
||||
switch ((event.target as HTMLElement).dataset.icon) {
|
||||
case 'delete':
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('notification-delete', {
|
||||
detail: {
|
||||
id: this.id,
|
||||
notification: this,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
break
|
||||
case 'touchend':
|
||||
break
|
||||
case 'click':
|
||||
event.stopPropagation()
|
||||
let self = this
|
||||
let target = event.target as HTMLElement
|
||||
switch (target.dataset.icon) {
|
||||
case 'delete':
|
||||
target.setAttribute('clicked', 'true')
|
||||
target.addEventListener('transitionend', function tranEnd() {
|
||||
target.removeEventListener('transitionend', tranEnd)
|
||||
target.removeAttribute('clicked')
|
||||
self.dispatchEvent(
|
||||
new CustomEvent('notification-delete', {
|
||||
detail: {
|
||||
id: self.id,
|
||||
notification: self,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
break
|
||||
case 'settings':
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('notification-settings-configure', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
break
|
||||
case 'settings':
|
||||
target.setAttribute('clicked', 'true')
|
||||
target.addEventListener('transitionend', function tranEnd() {
|
||||
target.removeEventListener('transitionend', tranEnd)
|
||||
target.removeAttribute('clicked')
|
||||
self.dispatchEvent(
|
||||
new CustomEvent('notification-settings-configure', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
break
|
||||
}
|
||||
break
|
||||
break
|
||||
default:
|
||||
this.notification.setAttribute('clicked', 'true')
|
||||
this.notification.addEventListener(
|
||||
'transitionend',
|
||||
function tranEnd() {
|
||||
self.notification.removeEventListener(
|
||||
'transitionend',
|
||||
tranEnd
|
||||
)
|
||||
self.notification.removeAttribute('clicked')
|
||||
self.dispatchEvent(
|
||||
new CustomEvent('notification-click', {
|
||||
detail: {
|
||||
id: self.id,
|
||||
notification: self,
|
||||
},
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
}
|
||||
)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,6 +425,7 @@ export class StarNotification extends LitElement {
|
|||
:host {
|
||||
--notification-background-lm: rgba(255, 255, 255, 0.55);
|
||||
--notification-background-dm: rgba(0, 0, 0, 0.25);
|
||||
--notification-background-active: rgba(255, 255, 255, 0.75);
|
||||
--border-lm: rgba(0, 0, 0, 0.09);
|
||||
--border-dm: rgba(0, 0, 0, 0.09);
|
||||
--button-background-color-lm: rgba(255, 255, 255, 0.68);
|
||||
|
@ -357,11 +440,20 @@ export class StarNotification extends LitElement {
|
|||
|
||||
.notification {
|
||||
background: var(--notification-background-lm);
|
||||
transition: transform 0.6s;
|
||||
}
|
||||
|
||||
.notification[clicked] {
|
||||
transition: transform 0.1s;
|
||||
transform: scale(0.9);
|
||||
background: var(--notification-background-active);
|
||||
}
|
||||
|
||||
.notification > div.title-container {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
color: #404040;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
|
@ -370,7 +462,7 @@ export class StarNotification extends LitElement {
|
|||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
color: #404040;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notification > div.title-container .timestamp {
|
||||
|
@ -378,7 +470,6 @@ export class StarNotification extends LitElement {
|
|||
position: absolute;
|
||||
text-align: right;
|
||||
mix-blend-mode: normal;
|
||||
opacity: 0.65;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
@ -450,6 +541,11 @@ export class StarNotification extends LitElement {
|
|||
background: var(--button-background-color-lm);
|
||||
border-radius: 50%;
|
||||
opacity: 0.6;
|
||||
transition: transform 0.1s;
|
||||
}
|
||||
|
||||
.btn-tool > div[clicked] {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.btn-tool > div::after {
|
||||
|
@ -460,6 +556,7 @@ export class StarNotification extends LitElement {
|
|||
font-style: normal;
|
||||
text-rendering: optimizelegibility;
|
||||
font-weight: 500;
|
||||
color: #4d4d4d;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
@ -490,10 +587,13 @@ export class StarNotification extends LitElement {
|
|||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.one-container {
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
.one-container .timestamp {
|
||||
position: absolute;
|
||||
text-align: right;
|
||||
color: #404040;
|
||||
mix-blend-mode: normal;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
@ -514,148 +614,152 @@ export class StarNotification extends LitElement {
|
|||
background: var(--button-background-color-dm);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host([dark-mode]) .btn-tool > div::after {
|
||||
color: #f4f4f4;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 300px) {
|
||||
:host([notificationType='one-notification']) {
|
||||
margin: 16px 0 0 0;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
|
||||
.notification {
|
||||
height: 152px;
|
||||
width: 860px;
|
||||
height: 50px;
|
||||
width: 286px;
|
||||
}
|
||||
|
||||
.top-border-radius {
|
||||
border-top-left-radius: 20px;
|
||||
border-top-right-radius: 20px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
.bottom-border-radius {
|
||||
border-bottom-left-radius: 20px;
|
||||
border-bottom-right-radius: 20px;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
||||
|
||||
.border-radius {
|
||||
border-radius: 20px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.notification > img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
pointer-events: none;
|
||||
margin: 26px 10px 78px 26px;
|
||||
margin: 9px 3px 26px 9px;
|
||||
}
|
||||
|
||||
.notification > div.title-container {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
top: 36px;
|
||||
width: calc(100% - 28px);
|
||||
left: 28px;
|
||||
top: 23.7%;
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 28px;
|
||||
height: 9px;
|
||||
line-height: 9px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.notification > div.title-container .timestamp {
|
||||
height: 32px;
|
||||
right: 32px;
|
||||
top: -4px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
height: 10px;
|
||||
right: 10px;
|
||||
top: -1px;
|
||||
font-size: 8px;
|
||||
line-height: 10px;
|
||||
}
|
||||
|
||||
.notification > div.detail {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
top: 84px;
|
||||
width: calc(100% - 28px);
|
||||
left: 28px;
|
||||
top: 55.3%;
|
||||
}
|
||||
|
||||
.notification > div.detail .detail-content {
|
||||
width: 740px;
|
||||
height: 34px;
|
||||
font-size: 26px;
|
||||
line-height: 34px;
|
||||
width: 246px;
|
||||
height: 11px;
|
||||
font-size: 8px;
|
||||
line-height: 11px;
|
||||
}
|
||||
|
||||
.notification > div.detail .arrow-up {
|
||||
width: 56px;
|
||||
height: 34px;
|
||||
right: 26px;
|
||||
bottom: 30px;
|
||||
line-height: 34px;
|
||||
border-radius: 189px;
|
||||
width: 18px;
|
||||
height: 11px;
|
||||
right: 9px;
|
||||
bottom: 10px;
|
||||
line-height: 11px;
|
||||
border-radius: 63px;
|
||||
}
|
||||
|
||||
.notification > div.detail .arrow-up::after {
|
||||
font-size: 35px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.btn-tool {
|
||||
right: 18px;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
.btn-tool > div:first-child {
|
||||
margin-right: 44px;
|
||||
margin-right: 15px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.btn-tool > div {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.btn-tool > div::after {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-size: 32px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
line-height: 10px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
width: calc(100% - 28px);
|
||||
left: 28px;
|
||||
}
|
||||
|
||||
.one-container {
|
||||
top: 36px;
|
||||
top: 12px;
|
||||
}
|
||||
|
||||
.another-container {
|
||||
top: 89px;
|
||||
top: 29px;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 28px;
|
||||
height: 9px;
|
||||
line-height: 9px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.container .detail-content {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
left: 24px;
|
||||
top: -3px;
|
||||
font-size: 26px;
|
||||
height: 11px;
|
||||
line-height: 11px;
|
||||
left: 8px;
|
||||
top: -1px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.one-container .timestamp {
|
||||
height: 34px;
|
||||
right: 34px;
|
||||
top: -4px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
height: 11px;
|
||||
right: 11px;
|
||||
top: -1px;
|
||||
font-size: 8px;
|
||||
line-height: 11px;
|
||||
}
|
||||
|
||||
.another-container .notificaiton-counts {
|
||||
width: 56px;
|
||||
height: 34px;
|
||||
right: 26px;
|
||||
bottom: 30px;
|
||||
width: 18px;
|
||||
height: 11px;
|
||||
right: 8px;
|
||||
bottom: 10px;
|
||||
top: -1px;
|
||||
line-height: 34px;
|
||||
font-size: 20px;
|
||||
border-radius: 189px;
|
||||
line-height: 11px;
|
||||
font-size: 7px;
|
||||
border-radius: 63px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,6 +798,7 @@ export class StarNotification extends LitElement {
|
|||
width: calc(100% - 42px);
|
||||
left: 42px;
|
||||
top: 18px;
|
||||
top: 23.7%;
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
|
@ -714,6 +819,7 @@ export class StarNotification extends LitElement {
|
|||
width: calc(100% - 42px);
|
||||
left: 42px;
|
||||
top: 42px;
|
||||
top: 55.3%;
|
||||
}
|
||||
|
||||
.notification > div.detail .detail-content {
|
||||
|
@ -803,6 +909,155 @@ export class StarNotification extends LitElement {
|
|||
border-radius: 94.5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 900px) {
|
||||
:host([notificationType='one-notification']) {
|
||||
margin: 16px 0 0 0;
|
||||
}
|
||||
|
||||
.notification {
|
||||
height: 152px;
|
||||
width: 860px;
|
||||
}
|
||||
|
||||
.top-border-radius {
|
||||
border-top-left-radius: 20px;
|
||||
border-top-right-radius: 20px;
|
||||
}
|
||||
|
||||
.bottom-border-radius {
|
||||
border-bottom-left-radius: 20px;
|
||||
border-bottom-right-radius: 20px;
|
||||
}
|
||||
|
||||
.border-radius {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.notification > img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
pointer-events: none;
|
||||
margin: 26px 10px 78px 26px;
|
||||
}
|
||||
|
||||
.notification > div.title-container {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
|
||||
top: 36px;
|
||||
top: 23.7%;
|
||||
}
|
||||
|
||||
.notification > div.title-container .title {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.notification > div.title-container .timestamp {
|
||||
height: 32px;
|
||||
right: 32px;
|
||||
top: -4px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.notification > div.detail {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
top: 84px;
|
||||
|
||||
top: 55.3%;
|
||||
}
|
||||
|
||||
.notification > div.detail .detail-content {
|
||||
width: 740px;
|
||||
height: 34px;
|
||||
font-size: 26px;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.notification > div.detail .arrow-up {
|
||||
width: 56px;
|
||||
height: 34px;
|
||||
right: 26px;
|
||||
bottom: 30px;
|
||||
line-height: 34px;
|
||||
border-radius: 189px;
|
||||
}
|
||||
|
||||
.notification > div.detail .arrow-up::after {
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
.btn-tool {
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
.btn-tool > div:first-child {
|
||||
margin-right: 44px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.btn-tool > div {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.btn-tool > div::after {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: calc(100% - 84px);
|
||||
left: 84px;
|
||||
}
|
||||
|
||||
.one-container {
|
||||
top: 36px;
|
||||
}
|
||||
|
||||
.another-container {
|
||||
top: 89px;
|
||||
}
|
||||
|
||||
.container .title {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.container .detail-content {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
left: 24px;
|
||||
top: -3px;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.one-container .timestamp {
|
||||
height: 34px;
|
||||
right: 34px;
|
||||
top: -4px;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.another-container .notificaiton-counts {
|
||||
width: 56px;
|
||||
height: 34px;
|
||||
right: 26px;
|
||||
bottom: 30px;
|
||||
top: -1px;
|
||||
line-height: 34px;
|
||||
font-size: 20px;
|
||||
border-radius: 189px;
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {LitElement, html, HTMLTemplateResult, CSSResultArray} from 'lit'
|
|||
import {customElement, property, queryAssignedElements} from 'lit/decorators.js'
|
||||
import '../button/button.js'
|
||||
import {OverlayStack} from '../overlay/overlay-stack'
|
||||
import { TriggerInteractions } from '../overlay/overlay-types.js'
|
||||
import {TriggerInteractions} from '../overlay/overlay-types.js'
|
||||
import {sharedStyles} from './overflowmenustyle.js'
|
||||
|
||||
@customElement('star-overflowmenu')
|
||||
|
@ -34,9 +34,16 @@ export class StarOverflowMenu extends LitElement {
|
|||
const overlaycontent = this.querySelector('#menu') as HTMLElement
|
||||
// overlaycontent为空则退出
|
||||
if (!overlaycontent) return
|
||||
const triggerInteraction = this.getAttribute('triggertype') as TriggerInteractions
|
||||
const triggerInteraction = this.getAttribute(
|
||||
'triggertype'
|
||||
) as TriggerInteractions
|
||||
// 开启overlay
|
||||
this.overlayStack.openOverlay(originalNode, targetNode, overlaycontent, triggerInteraction)
|
||||
this.overlayStack.openOverlay(
|
||||
originalNode,
|
||||
targetNode,
|
||||
overlaycontent,
|
||||
triggerInteraction
|
||||
)
|
||||
} else {
|
||||
this.overlayStack.closeOverlay()
|
||||
}
|
||||
|
|
|
@ -108,22 +108,22 @@ export class ActiveOverlay extends LitElement {
|
|||
targettop -
|
||||
(contentheight - targetnode.offsetHeight) -
|
||||
topboundingclient
|
||||
this.setAttribute("placement","rightbottom")
|
||||
this.setAttribute('placement', 'rightbottom')
|
||||
} else if (rightline) {
|
||||
// 右侧边界
|
||||
left = targetleft - this.restoreContent.offsetWidth
|
||||
top = targettop - topboundingclient
|
||||
this.setAttribute("placement","right")
|
||||
this.setAttribute('placement', 'right')
|
||||
} else if (bottomline) {
|
||||
// 下侧边界
|
||||
left = targetleft + targetnode.offsetWidth
|
||||
top = targetbottom - contentheight - topboundingclient
|
||||
this.setAttribute("placement","bottom")
|
||||
this.setAttribute('placement', 'bottom')
|
||||
} else {
|
||||
// 正常情况
|
||||
left = targetleft + targetnode.offsetWidth
|
||||
top = targettop - topboundingclient
|
||||
this.setAttribute("placement","normal")
|
||||
this.setAttribute('placement', 'normal')
|
||||
}
|
||||
this.style.left = left + 'px'
|
||||
this.style.top = top + 'px'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {ActiveOverlay} from './active-overlay'
|
||||
import { TriggerInteractions } from './overlay-types'
|
||||
import {TriggerInteractions} from './overlay-types'
|
||||
|
||||
export class OverlayStack {
|
||||
public overlays: ActiveOverlay[] = []
|
||||
|
@ -12,7 +12,12 @@ export class OverlayStack {
|
|||
triggerInteraction: TriggerInteractions
|
||||
) {
|
||||
// 创建activeoverlay对象
|
||||
const activeOverlay = ActiveOverlay.create(root, targetnode, content, triggerInteraction)
|
||||
const activeOverlay = ActiveOverlay.create(
|
||||
root,
|
||||
targetnode,
|
||||
content,
|
||||
triggerInteraction
|
||||
)
|
||||
// 开启状态
|
||||
this.isOpen = true
|
||||
// 创建注释节点模板——用于替换要展示在overlay中的元素
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
// 定义overlay所需各种参数类型、预留接口
|
||||
|
||||
// 弹窗的交互类型:溢出菜单、底部菜单、信息菜单
|
||||
export type TriggerInteractions =
|
||||
| 'overflowmenu'
|
||||
| 'bottommenu'
|
||||
| 'infomenu'
|
||||
export type TriggerInteractions = 'overflowmenu' | 'bottommenu' | 'infomenu'
|
||||
|
||||
// 主题:lm:light-model; dm:dark-model
|
||||
export type thememode = 'lm' | 'dm'
|
||||
|
@ -19,5 +16,4 @@ export interface OverlayOpenDetail {
|
|||
// skidding?: number // 滑动
|
||||
// virtualTrigger?: VirtualTrigger // 虚拟触发
|
||||
// trigger: HTMLElement // 触发
|
||||
|
||||
}
|
||||
|
|
|
@ -6,42 +6,42 @@ export const sharedStyles: CSSResult = css`
|
|||
|
||||
:host([placement='normal'])::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
content: '';
|
||||
top: 34px;
|
||||
left: -16px;
|
||||
border-top: 16px solid transparent;
|
||||
border-bottom: 16px solid transparent;
|
||||
border-right: 16px solid #F5F5F5;
|
||||
border-right: 16px solid #f5f5f5;
|
||||
}
|
||||
|
||||
:host([placement='right'])::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
content: '';
|
||||
top: 34px;
|
||||
right: -16px;
|
||||
z-index: 2;
|
||||
border-top: 16px solid transparent;
|
||||
border-bottom: 16px solid transparent;
|
||||
border-left: 16px solid #F5F5F5;
|
||||
border-left: 16px solid #f5f5f5;
|
||||
}
|
||||
|
||||
|
||||
:host([placement='bottom'])::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
content: '';
|
||||
bottom: 34px;
|
||||
left: -16px;
|
||||
border-top: 16px solid transparent;
|
||||
border-bottom: 16px solid transparent;
|
||||
border-right: 16px solid #F5F5F5;
|
||||
border-right: 16px solid #f5f5f5;
|
||||
}
|
||||
|
||||
:host([placement='rightbottom'])::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
content: '';
|
||||
bottom: 34px;
|
||||
right: -16px;
|
||||
border-top: 16px solid transparent;
|
||||
border-bottom: 16px solid transparent;
|
||||
border-left: 16px solid #F5F5F5;
|
||||
border-left: 16px solid #f5f5f5;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -17,11 +17,11 @@ export default css`
|
|||
position: relative;
|
||||
}
|
||||
|
||||
:host(#overflowmenu) ul{
|
||||
:host(#overflowmenu) ul {
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
:host(#bottommenu){
|
||||
:host(#bottommenu) {
|
||||
width: 520px;
|
||||
height: 400px;
|
||||
display: block;
|
||||
|
@ -29,7 +29,7 @@ export default css`
|
|||
border-radius: 20px;
|
||||
}
|
||||
|
||||
:host(#bottommenu) ul{
|
||||
:host(#bottommenu) ul {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# star-weather
|
||||
|
||||
星光 Web 组件——天气组件:weather组件介绍(10 月 08 日)
|
||||
|
||||
## 介绍
|
||||
|
||||
star-weather 组件主要是用来显示当前天气状况和预测1周内天气详情的组件
|
||||
star-weather 属性:
|
||||
|
||||
### 1、type 属性
|
||||
天气风格样式类型,type一共包含6种类型,分别为type11、type12、type21、type22、type23和type32,其中
|
||||
type="type11"的内容排布为只包含天气图标的样式,
|
||||
type="type12"的内容排布(从左向右)为包含地理位置信息、温度和对应的天气图标,
|
||||
type="type21"的内容排布(从上至下)为包含天气图标,地理位置和温度信息,
|
||||
type="type22"的内容排布(从上至下)为包含地理位置、温度、天气图标、空气质量、体感温度、湿度、风级、能见度、紫外线等详细信息。
|
||||
`html demo <star-weather type="type22"></star-weather> `
|
||||
|
||||
### 2、data 属性
|
||||
|
||||
天气详细信息,其中包含地理位置、温度、日期、天气情况、风级、湿度、空气质量、体感温度、能见度、紫外线等具体信息
|
||||
`html demo <star-weather type="type22" .data="${this.data}"></star-weather> `
|
||||
### 3、自适应布局
|
||||
天气组件整体布局设计为自适应布局,可自适应缩放显示天气组件。
|
||||
### 4、weatherData数据格式说明
|
||||
weatherData = {
|
||||
location: "", //位置信息
|
||||
weatherInfo: [ //天气详情信息,包含天气情况、风级、湿度、空气质量、体感温度、能见度、紫外线等详情信息
|
||||
{
|
||||
date: new Date(), 日期
|
||||
……
|
||||
},
|
||||
{
|
||||
date: new Date(),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/weather",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./weather.js": {
|
||||
"default": "./weather.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_2914_176526)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.3043 38H32.8696C37.3571 38 41 34.3071 41 29.7451C41 25.3341 37.5789 21.7277 33.2814 21.5117C31.9404 15.4919 26.6398 11 20.3043 11C12.9553 11 7 17.0468 7 24.4973C7 31.4457 12.1739 37.1686 18.8261 37.919L20.3043 38Z" fill="url(#paint0_linear_2914_176526)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_2914_176526" x="3" y="9" width="42" height="35" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2914_176526"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2914_176526" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_2914_176526" x1="48.0217" y1="20.8478" x2="23.747" y2="2.34606" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEDBA"/>
|
||||
<stop offset="1" stop-color="#FFFCF2"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,38 @@
|
|||
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_1658_81628)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M119 53.9935C119 31.9083 101.091 14 78.9935 14C56.9093 14 39 31.9083 39 53.9935C39 76.0917 56.9093 94 78.9935 94C101.091 94 119 76.0917 119 53.9935Z" fill="url(#paint0_linear_1658_81628)"/>
|
||||
<path d="M78.9935 14.5C100.815 14.5 118.5 32.1846 118.5 53.9935C118.5 75.8155 100.815 93.5 78.9935 93.5C57.1855 93.5 39.5 75.8156 39.5 53.9935C39.5 32.1845 57.1854 14.5 78.9935 14.5Z" stroke="#F2F2F2" stroke-opacity="0.9"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d_1658_81628)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.2174 114H77.4783C89.3571 114 99 104.426 99 92.5983C99 81.1626 89.9441 71.8124 78.5683 71.2525C75.0186 55.6457 60.9876 44 44.2174 44C24.764 44 9 59.6769 9 78.993C9 97.0074 22.6957 111.844 40.3043 113.79L44.2174 114Z" fill="url(#paint1_linear_1658_81628)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_1658_81628" x="31" y="6" width="96" height="96" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="4"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1658_81628"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1658_81628" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_1658_81628" x="5" y="42" width="98" height="78" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1658_81628"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1658_81628" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_1658_81628" x1="42.5" y1="46.5" x2="91.7273" y2="106.727" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.0028" stop-color="#DDDBD9"/>
|
||||
<stop offset="1" stop-color="#989CA5"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1658_81628" x1="117.587" y1="69.5314" x2="54.3175" y2="20.2954" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#C7C9D0"/>
|
||||
<stop offset="1" stop-color="#F4F4F3"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,21 @@
|
|||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_2914_176524)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.3043 37H32.8696C37.3571 37 41 33.3071 41 28.7451C41 24.3341 37.5789 20.7277 33.2814 20.5117C31.9404 14.4919 26.6398 10 20.3043 10C12.9553 10 7 16.0468 7 23.4973C7 30.4457 12.1739 36.1686 18.8261 36.919L20.3043 37Z" fill="url(#paint0_linear_2914_176524)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_2914_176524" x="3" y="8" width="42" height="35" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2914_176524"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2914_176524" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_2914_176524" x1="48.0217" y1="19.8478" x2="23.747" y2="1.34606" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#80848D"/>
|
||||
<stop offset="1" stop-color="#BCC2CC"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,38 @@
|
|||
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_1425_53262)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M119 55.9935C119 33.9083 101.091 16 78.9935 16C56.9093 16 39 33.9083 39 55.9935C39 78.0917 56.9093 96 78.9935 96C101.091 96 119 78.0917 119 55.9935Z" fill="url(#paint0_linear_1425_53262)"/>
|
||||
<path d="M78.9935 16.5C100.815 16.5 118.5 34.1846 118.5 55.9935C118.5 77.8155 100.815 95.5 78.9935 95.5C57.1855 95.5 39.5 77.8156 39.5 55.9935C39.5 34.1845 57.1854 16.5 78.9935 16.5Z" stroke="#FFDD80" stroke-opacity="0.9"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d_1425_53262)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.2174 116H77.4783C89.3571 116 99 106.426 99 94.5983C99 83.1626 89.9441 73.8124 78.5683 73.2525C75.0186 57.6457 60.9876 46 44.2174 46C24.764 46 9 61.6769 9 80.993C9 99.0074 22.6957 113.844 40.3043 115.79L44.2174 116Z" fill="url(#paint1_linear_1425_53262)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_1425_53262" x="31" y="8" width="96" height="96" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="4"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.827451 0 0 0 0 0.309804 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1425_53262"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1425_53262" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_1425_53262" x="5" y="44" width="98" height="78" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1425_53262"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1425_53262" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_1425_53262" x1="29.9091" y1="61.4545" x2="91.7273" y2="108.727" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.0028" stop-color="#FFC338"/>
|
||||
<stop offset="1" stop-color="#FF9C12"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_1425_53262" x1="117.587" y1="71.5314" x2="54.3175" y2="22.2954" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEDBA"/>
|
||||
<stop offset="1" stop-color="#FFFCF2"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,38 @@
|
|||
<svg width="54" height="51" viewBox="0 0 54 51" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_2914_176531)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M46 22.9976C46 14.7156 39.284 8 30.9976 8C22.716 8 16 14.7156 16 22.9976C16 31.2844 22.716 38 30.9976 38C39.284 38 46 31.2844 46 22.9976Z" fill="url(#paint0_linear_2914_176531)"/>
|
||||
<path d="M30.9976 8.5C39.008 8.5 45.5 14.9919 45.5 22.9976C45.5 31.0082 39.0079 37.5 30.9976 37.5C22.9922 37.5 16.5 31.0083 16.5 22.9976C16.5 14.9918 22.9921 8.5 30.9976 8.5Z" stroke="#FFDD80" stroke-opacity="0.9"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_d_2914_176531)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.3043 45H29.8696C34.3571 45 38 41.4439 38 37.0508C38 32.8032 34.5789 29.3303 30.2814 29.1224C28.9404 23.3255 23.6398 19 17.3043 19C9.95528 19 4 24.8228 4 31.9974C4 38.6885 9.17391 44.1994 15.8261 44.922L17.3043 45Z" fill="url(#paint1_linear_2914_176531)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_2914_176531" x="8" y="0" width="46" height="46" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="4"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.827451 0 0 0 0 0.309804 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2914_176531"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2914_176531" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_d_2914_176531" x="0" y="17" width="42" height="34" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0 0.25 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2914_176531"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2914_176531" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_2914_176531" x1="12.5909" y1="25.0455" x2="35.7727" y2="42.7727" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.0028" stop-color="#FFC338"/>
|
||||
<stop offset="1" stop-color="#FF9C12"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_2914_176531" x1="45.0217" y1="28.4831" x2="21.4268" y2="9.80775" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFEDBA"/>
|
||||
<stop offset="1" stop-color="#FFFCF2"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,21 @@
|
|||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_2914_176529)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M40 23.9974C40 15.1633 32.8363 8 23.9974 8C15.1637 8 8 15.1633 8 23.9974C8 32.8367 15.1637 40 23.9974 40C32.8363 40 40 32.8367 40 23.9974Z" fill="url(#paint0_linear_2914_176529)"/>
|
||||
<path d="M23.9974 8.5C32.5603 8.5 39.5 15.4396 39.5 23.9974C39.5 32.5605 32.5602 39.5 23.9974 39.5C15.44 39.5 8.5 32.5606 8.5 23.9974C8.5 15.4395 15.4398 8.5 23.9974 8.5Z" stroke="#FFDD80" stroke-opacity="0.9"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_2914_176529" x="0" y="0" width="48" height="48" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="4"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.827451 0 0 0 0 0.309804 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2914_176529"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2914_176529" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_2914_176529" x1="4.36364" y1="26.1818" x2="29.0909" y2="45.0909" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.0028" stop-color="#FFC338"/>
|
||||
<stop offset="1" stop-color="#FF9C12"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,148 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
export const sharedStyles: CSSResult = css`
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.star-weather-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
/* 背景框 */
|
||||
.star-weather {
|
||||
width: var(--autoWidth--);
|
||||
min-width: var(--autoWidth--);
|
||||
height: var(--autoHeight--);
|
||||
min-height: var(--autoHeight--);
|
||||
transform: scale(var(--autoScale--));
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(
|
||||
137.64deg,
|
||||
#f5f0f5 0%,
|
||||
#fafafa 20.46%,
|
||||
#d5daf2 90.45%
|
||||
);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.star-weather * {
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* .star-weather-top */
|
||||
.star-weather-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.type12 .star-weather-top {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.type21 .star-weather-top {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
.type22 .star-weather-top {
|
||||
width: 100%;
|
||||
height: 45%;
|
||||
/* border:1px solid red; */
|
||||
}
|
||||
/* .star-weather-bottom */
|
||||
.star-weather-bottom {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.type22 .star-weather-bottom {
|
||||
height: 50%;
|
||||
}
|
||||
/* 天气图标 */
|
||||
.star-weather-img {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
.type11 .star-weather-img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.type12 .star-weather-img {
|
||||
height: 100%;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.type21 .star-weather-img {
|
||||
width: 100%;
|
||||
}
|
||||
.type22 .star-weather-img {
|
||||
height: 90%;
|
||||
margin-right: 30px;
|
||||
/* border:1px solid red; */
|
||||
}
|
||||
.weather-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/* 位置温度()*/
|
||||
.star-weather-location-temperature {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.type12 .star-weather-location-temperature {
|
||||
height: 100%;
|
||||
margin-left: 47px;
|
||||
}
|
||||
.type21 .star-weather-location-temperature {
|
||||
width: 100%;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.type22 .star-weather-location-temperature {
|
||||
height: 100%;
|
||||
/* margin-top:10%; */
|
||||
margin-left: 47px;
|
||||
}
|
||||
.star-weather-location {
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
font-size: 22px;
|
||||
color: rgba(38, 38, 38, 0.45);
|
||||
}
|
||||
.type21 .star-weather-location {
|
||||
text-align: center;
|
||||
}
|
||||
.star-weather-temperature {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
/* detailType() */
|
||||
.detail-today-item {
|
||||
height: 50%;
|
||||
width: 31%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-left: 47px;
|
||||
}
|
||||
.detail-today-item-top {
|
||||
font-size: 16px;
|
||||
color: rgba(38, 38, 38, 0.45);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.detail-today-item-bottom {
|
||||
font-size: 26px;
|
||||
text-align: left;
|
||||
color: #4d4d4d;
|
||||
}
|
||||
`
|
|
@ -0,0 +1,169 @@
|
|||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement, property, query} from 'lit/decorators.js'
|
||||
import {sharedStyles} from './weather-style'
|
||||
import Sunny from './svg/Sunny.svg'
|
||||
import Cloudy from './svg/Cloudy.svg'
|
||||
import Noload from './svg/Noload.svg'
|
||||
import PartlyCloudy from './svg/Partly Cloudy.svg'
|
||||
const weatherMy: Record<string, boolean> = {
|
||||
Sunny: Sunny,
|
||||
Cloudy: Cloudy,
|
||||
PartlyCloudy: PartlyCloudy,
|
||||
}
|
||||
const typeMy: Record<string, string> = {
|
||||
// height / width
|
||||
type11: '1',
|
||||
type12: '0.4',
|
||||
type21: '1.9',
|
||||
type22: '0.8',
|
||||
type23: '0.7',
|
||||
type32: '1.6',
|
||||
}
|
||||
const minAll: Record<string, string> = {
|
||||
// width
|
||||
type11: '100',
|
||||
type12: '400',
|
||||
type21: '200',
|
||||
type22: '500',
|
||||
type23: '600',
|
||||
type32: '600',
|
||||
}
|
||||
@customElement('star-weather')
|
||||
export class StarWeather extends LitElement {
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [sharedStyles]
|
||||
}
|
||||
@property({type: String}) type = 'type11'
|
||||
@property({type: Object}) data = Object()
|
||||
|
||||
@query('.star-weather-main')
|
||||
starWeather: HTMLDivElement | undefined
|
||||
|
||||
dataBoo() {
|
||||
return !!Object.keys(this.data).length
|
||||
}
|
||||
render() {
|
||||
return html`
|
||||
<div class="star-weather-main">
|
||||
<div class="star-weather ${this.type}">
|
||||
<div class="star-weather-top">
|
||||
${this.locationType()} ${this.weatherType()}
|
||||
</div>
|
||||
<div class="star-weather-bottom">${this.detailType()}</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
weatherType() {
|
||||
return html`
|
||||
<div class="star-weather-img">
|
||||
<img
|
||||
class="weather-img"
|
||||
src="${weatherMy[
|
||||
this.dataBoo() && this.data.weatherInfo[0]?.weather?.labelEn] || Noload}"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
locationType() {
|
||||
if (this.type !== 'type11' && typeMy[this.type]) {
|
||||
return html`
|
||||
<div class="star-weather-location-temperature">
|
||||
<div class="star-weather-location-temperature-main">
|
||||
<div class="star-weather-location">
|
||||
${(this.dataBoo() && this.data.location) || ''}
|
||||
</div>
|
||||
<div class="star-weather-temperature">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.temperature?.max) || ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
detailType() {
|
||||
if (this.type === 'type22') {
|
||||
return html`
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">空气质量</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${this.dataBoo() && (this.data.weatherInfo[0]?.airQuality?.value +
|
||||
this.data.weatherInfo[0]?.airQuality?.type) || ''}
|
||||
</span>
|
||||
</span>
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">体感温度</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${(this.dataBoo() &&
|
||||
this.data.weatherInfo[0].somatosensoryTemperature) || ''}
|
||||
</span>
|
||||
</span>
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">湿度</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.humidity) || ''}
|
||||
</span>
|
||||
</span>
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.wind?.label) || '风向'}
|
||||
</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.wind?.value) || ''}
|
||||
</span>
|
||||
</span>
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">能见度</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.visibility) || ''}
|
||||
</span>
|
||||
</span>
|
||||
<span class="detail-today-item">
|
||||
<span class="detail-today-item-top">紫外线</span>
|
||||
<span class="detail-today-item-bottom">
|
||||
${(this.dataBoo() && this.data.weatherInfo[0]?.ultravioletRys) || ''}
|
||||
</span>
|
||||
</span>
|
||||
`
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
protected firstUpdated() {
|
||||
this.resize()
|
||||
window.addEventListener('resize', () => {
|
||||
this.resize()
|
||||
})
|
||||
}
|
||||
protected resize() {
|
||||
let parentHeight, parentWidth
|
||||
if (this.parentElement){
|
||||
parentHeight = this.parentElement.offsetHeight
|
||||
parentWidth = this.parentElement.offsetWidth
|
||||
}else if(this.parentNode instanceof ShadowRoot){
|
||||
parentHeight=(this.parentNode.host as HTMLElement).offsetHeight
|
||||
parentWidth=(this.parentNode.host as HTMLElement).offsetWidth
|
||||
}
|
||||
let height = parentHeight || 10
|
||||
let width = parentWidth || 10
|
||||
// console.log(height,width,'111111111')
|
||||
// this.style.setProperty('--autoWidth2--', width + 'px')
|
||||
// this.style.setProperty('--autoHeight2--', height + 'px')
|
||||
let proportion: any = typeMy[this.type]
|
||||
let minOne: any = minAll[this.type]
|
||||
this.style.setProperty('--autoWidth--', minOne + 'px')
|
||||
this.style.setProperty('--autoHeight--', minOne * proportion + 'px')
|
||||
if (height / width >= proportion) {
|
||||
this.style.setProperty('--autoScale--', width / minOne + '')
|
||||
} else {
|
||||
this.style.setProperty('--autoScale--', height / (minOne * proportion) + '')
|
||||
}
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'star-weather': StarWeather
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import './components/radio/radio-group'
|
|||
import './components/radio/radio'
|
||||
import './components/confirm/confirm'
|
||||
import './components/clock/clock'
|
||||
import './components/weather/weather'
|
||||
import './components/toast/toast'
|
||||
import './components/picker/picker'
|
||||
import './components/overflowmenu/overflowmenu'
|
||||
|
@ -23,7 +24,8 @@ import './components/prompt/prompt'
|
|||
import './components/digicipher/digicipher'
|
||||
import './components/pattern-view/pattern-view'
|
||||
import './components/overlay/active-overlay'
|
||||
|
||||
import './components/battery/battery'
|
||||
import './components/battery-square/battery-square'
|
||||
@customElement('settings-app')
|
||||
export class SettingsApp extends LitElement {
|
||||
@query('star-animate-section#root') private rootSection!: StarAnimateSection
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
### 1.在普通 HTMLElement 上使用 GestureDetector 的方法:
|
||||
|
||||
```js
|
||||
import GestureDector from '@star-web-lib/gesture-detector/gesture-detector.js'
|
||||
import GestureDetector from '@star-web-lib/gesture-detector/gesture-detector.js'
|
||||
|
||||
const myElement = document.querySelector('#myel')
|
||||
GestureDector.embedded(myElement)
|
||||
GestureDetector.embedded(myElement)
|
||||
myElement.addEventListener('tap', function () {})
|
||||
myElement.addEventListener('doubletap', function () {}, {once: true})
|
||||
```
|
||||
|
|
|
@ -262,7 +262,7 @@ type GestureTouchEvent = TouchEvent & {
|
|||
|
||||
type EmbededGestureHTMLElement = HTMLElement & {
|
||||
_addEventListener?: HTMLElement['addEventListener']
|
||||
gestureDector?: GestureDector
|
||||
gestureDetector?: GestureDetector
|
||||
cacheListeners?: {
|
||||
type: keyof HTMLElementEventMap & GestureEvents
|
||||
listener: EventListenerOrEventListenerObject
|
||||
|
@ -270,7 +270,7 @@ type EmbededGestureHTMLElement = HTMLElement & {
|
|||
}[]
|
||||
}
|
||||
|
||||
type GestureOptions = {
|
||||
export type GestureOptions = {
|
||||
get holdThreshold(): number
|
||||
set holdThreshold(t: number)
|
||||
get panThreshold(): number
|
||||
|
@ -477,31 +477,58 @@ const getTouchFromTouches = (
|
|||
})[0]
|
||||
}
|
||||
|
||||
export default class GestureDector {
|
||||
export default class GestureDetector {
|
||||
// 进入长按状态的阈值
|
||||
static HOLD_THRESHOLD = 500
|
||||
static #HOLD_THRESHOLD = 300
|
||||
static get HOLD_THRESHOLD() {
|
||||
return this.#HOLD_THRESHOLD
|
||||
}
|
||||
|
||||
// 进入滑动状态的阈值
|
||||
static PAN_THRESHOLD = 20
|
||||
static #PAN_THRESHOLD = 20
|
||||
static get PAN_THRESHOLD() {
|
||||
return this.#PAN_THRESHOLD
|
||||
}
|
||||
|
||||
// 判定是swipe事件的速度阈值,单位: px/ms
|
||||
static VELOCITY_THRESHOLD = 0.3
|
||||
static #VELOCITY_THRESHOLD = 0.3
|
||||
static get VELOCITY_THRESHOLD() {
|
||||
return this.#VELOCITY_THRESHOLD
|
||||
}
|
||||
|
||||
static THRESHOLD_SMOOTHING = 0.9
|
||||
static #THRESHOLD_SMOOTHING = 0.9
|
||||
static get THRESHOLD_SMOOTHING() {
|
||||
return this.#THRESHOLD_SMOOTHING
|
||||
}
|
||||
|
||||
static VELOCITY_SMOOTHING = 0.5
|
||||
static #VELOCITY_SMOOTHING = 0.5
|
||||
static get VELOCITY_SMOOTHING() {
|
||||
return this.#VELOCITY_SMOOTHING
|
||||
}
|
||||
|
||||
// 连续两次点触(双击或三击)允许的x和y坐标的最大偏移量
|
||||
static DOUBLE_TAP_DISTANCE = 50
|
||||
static #DOUBLE_TAP_DISTANCE = 50
|
||||
static get DOUBLE_TAP_DISTANCE() {
|
||||
return this.#DOUBLE_TAP_DISTANCE
|
||||
}
|
||||
|
||||
// 连续两次点触(双击或三击)允许的最大间隔时间
|
||||
static DOUBLE_TAP_TIME = 300
|
||||
static #DOUBLE_TAP_TIME = 300
|
||||
static get DOUBLE_TAP_TIME() {
|
||||
return this.#DOUBLE_TAP_TIME
|
||||
}
|
||||
|
||||
// scale 触发阈值, 单位: px
|
||||
static SCALE_THRESHOLD = 20
|
||||
static #SCALE_THRESHOLD = 20
|
||||
static get SCALE_THRESHOLD() {
|
||||
return this.#SCALE_THRESHOLD
|
||||
}
|
||||
|
||||
// rotate 触发阈值, 单位: 度°
|
||||
static ROTATE_THRESHOLD = 22.5
|
||||
static #ROTATE_THRESHOLD = 22.5
|
||||
static get ROTATE_THRESHOLD() {
|
||||
return this.#ROTATE_THRESHOLD
|
||||
}
|
||||
|
||||
// _options 是 option 的备份,用于重置
|
||||
_options!: GestureOptions | null
|
||||
|
@ -583,16 +610,16 @@ export default class GestureDector {
|
|||
this.element = el
|
||||
this.options = {
|
||||
...{
|
||||
holdThreshold: GestureDector.HOLD_THRESHOLD,
|
||||
panThreshold: GestureDector.PAN_THRESHOLD,
|
||||
velocityThreshold: GestureDector.VELOCITY_THRESHOLD,
|
||||
holdThreshold: GestureDetector.HOLD_THRESHOLD,
|
||||
panThreshold: GestureDetector.PAN_THRESHOLD,
|
||||
velocityThreshold: GestureDetector.VELOCITY_THRESHOLD,
|
||||
},
|
||||
...options,
|
||||
}
|
||||
this.state = this.initialState
|
||||
|
||||
// 用于审计
|
||||
GestureDector._GestureDetectorId++
|
||||
GestureDetector._GestureDetectorId++
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -921,12 +948,12 @@ export default class GestureDector {
|
|||
// 否则,
|
||||
if (
|
||||
Math.abs(distance - this.startDistance) >
|
||||
GestureDector.SCALE_THRESHOLD
|
||||
GestureDetector.SCALE_THRESHOLD
|
||||
) {
|
||||
this.scaled = true
|
||||
this.startDistance = this.lastDistance = Math.floor(
|
||||
this.startDistance +
|
||||
GestureDector.THRESHOLD_SMOOTHING *
|
||||
GestureDetector.THRESHOLD_SMOOTHING *
|
||||
(distance - this.startDistance)
|
||||
)
|
||||
} else {
|
||||
|
@ -936,7 +963,7 @@ export default class GestureDector {
|
|||
|
||||
if (this.rotated === false) {
|
||||
// 如果达到触发 rotate 的阈值, 则进入旋转状态, 更新
|
||||
if (Math.abs(rotation) > GestureDector.ROTATE_THRESHOLD) {
|
||||
if (Math.abs(rotation) > GestureDetector.ROTATE_THRESHOLD) {
|
||||
this.rotated = true
|
||||
} else {
|
||||
direction = this.startDirection
|
||||
|
@ -985,7 +1012,6 @@ export default class GestureDector {
|
|||
private holdState: FSMGestureState = {
|
||||
name: 'holdState',
|
||||
init: () => {
|
||||
// debugInfo('HOLD-STATE---holdstart')
|
||||
// holdState 的 holdStart 事件只能基于传递过来的 touchStart 封装
|
||||
this.justEnteredHoldState = true
|
||||
if (this.listenEvents.has('holdstart')) {
|
||||
|
@ -999,9 +1025,8 @@ export default class GestureDector {
|
|||
},
|
||||
touchstart: null,
|
||||
touchmove: (evt, touch) => {
|
||||
// debugInfo('HOLD-STATE---holdmove')
|
||||
// debugInfo(Array.prototype.map.call(evt.touches, (i) => i.identifier))
|
||||
if (evt.touches.length > 1) {
|
||||
// 针对 hold + pan/swipe 的代码块
|
||||
if (evt.touches.length > 1 && touch?.identifier !== this.touch1ID) {
|
||||
if (
|
||||
this.justEnteredHoldState === true &&
|
||||
this.hasEnteredPanState === false
|
||||
|
@ -1027,6 +1052,7 @@ export default class GestureDector {
|
|||
}
|
||||
}
|
||||
|
||||
// 如果当前触摸的 id 非第一指的 id,则退出。
|
||||
if (touch?.identifier !== this.touch1ID) return
|
||||
|
||||
const current = generateCoordinate(evt.timeStamp, touch as Touch)
|
||||
|
@ -1186,7 +1212,7 @@ export default class GestureDector {
|
|||
const gValue = (
|
||||
oldvx: number,
|
||||
newvx: number,
|
||||
r = GestureDector.VELOCITY_SMOOTHING
|
||||
r = GestureDetector.VELOCITY_SMOOTHING
|
||||
) => oldvx * r + newvx * (1 - r)
|
||||
|
||||
this.vx = gValue(this.vx, vx)
|
||||
|
@ -1309,7 +1335,14 @@ export default class GestureDector {
|
|||
touchmove: null,
|
||||
touchend: (evt, touch) => {
|
||||
// if (touch?.identifier !== this.touch1ID) return
|
||||
const isSecondFinger = evt.touches[1] === touch
|
||||
let isSecondFinger = false
|
||||
// 判断当前是否是第二指,需满足以下:
|
||||
// 1. 当前传入的 touch 的 id 为 1,代表是第2指
|
||||
// 2. 当前事件的变更触摸列表的第1项和传入的 touch 相同
|
||||
if (touch?.identifier === 1 && evt.changedTouches[0] === touch) {
|
||||
isSecondFinger = true
|
||||
}
|
||||
|
||||
debugInfo('SWIPE-STARTED-STATE---touchend')
|
||||
|
||||
// 一旦进入 swipeState 状态,则必发布事件
|
||||
|
@ -1380,9 +1413,9 @@ export default class GestureDector {
|
|||
const dt = thisTap.timeStamp - lastTap.timeStamp
|
||||
|
||||
return (
|
||||
dx < GestureDector.DOUBLE_TAP_DISTANCE &&
|
||||
dy < GestureDector.DOUBLE_TAP_DISTANCE &&
|
||||
dt < GestureDector.DOUBLE_TAP_TIME
|
||||
dx < GestureDetector.DOUBLE_TAP_DISTANCE &&
|
||||
dy < GestureDetector.DOUBLE_TAP_DISTANCE &&
|
||||
dt < GestureDetector.DOUBLE_TAP_TIME
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1393,7 +1426,7 @@ export default class GestureDector {
|
|||
* 根据平滑系数阈值(THRESHOLD_SMOOTHING),生成拟合手势中间点坐标
|
||||
*/
|
||||
private gBtCoordinate<T extends GestureCoordinate>(c1: T, c2: T): T {
|
||||
const r = GestureDector.THRESHOLD_SMOOTHING
|
||||
const r = GestureDetector.THRESHOLD_SMOOTHING
|
||||
const gValue = (arg: keyof GestureCoordinate) =>
|
||||
Math.floor(c1[arg] + r * (c2[arg] - c1[arg]))
|
||||
|
||||
|
@ -1543,7 +1576,7 @@ export default class GestureDector {
|
|||
}
|
||||
|
||||
/**
|
||||
* 在 GestureDector 运行时可传入可选项参数,即动态修改一些手势状态的阈值
|
||||
* 在 GestureDetector 运行时可传入可选项参数,即动态修改一些手势状态的阈值
|
||||
*
|
||||
* 设置新的 option 时,会转存当前运行初始设置的 options,用于未来重置
|
||||
*/
|
||||
|
@ -1577,14 +1610,13 @@ export default class GestureDector {
|
|||
public static embedded<T extends EmbededGestureHTMLElement>(
|
||||
el: T,
|
||||
options?: GestureOptions
|
||||
): T {
|
||||
if (el._addEventListener || el.gestureDector) {
|
||||
console.error(el + 'had been embedded!')
|
||||
return el
|
||||
): GestureDetector {
|
||||
if (el._addEventListener || el.gestureDetector) {
|
||||
throw new Error(el + 'had been embedded!')
|
||||
}
|
||||
|
||||
el._addEventListener = el.addEventListener
|
||||
el.gestureDector = new GestureDector(el, options)
|
||||
el.gestureDetector = new GestureDetector(el, options)
|
||||
el.cacheListeners = []
|
||||
el.addEventListener = function cAddEventListener<
|
||||
K extends keyof HTMLElementEventMap & GestureEvents
|
||||
|
@ -1613,7 +1645,7 @@ export default class GestureDector {
|
|||
case 'swiperight':
|
||||
case 'swipedown':
|
||||
case 'swipeup':
|
||||
this.gestureDector!.add(type, options)
|
||||
this.gestureDetector!.add(type, options)
|
||||
break
|
||||
}
|
||||
el.cacheListeners!.push({
|
||||
|
@ -1623,25 +1655,23 @@ export default class GestureDector {
|
|||
})
|
||||
el._addEventListener!.bind(this)(type, listener, options)
|
||||
}
|
||||
return el
|
||||
return el.gestureDetector
|
||||
}
|
||||
|
||||
public static disembedded<T extends EmbededGestureHTMLElement>(el: T): T {
|
||||
if (!(el._addEventListener && el.gestureDector)) {
|
||||
console.error(el + "can't be disembedded!")
|
||||
return el
|
||||
public static disembedded<T extends EmbededGestureHTMLElement>(el: T) {
|
||||
if (!(el._addEventListener && el.gestureDetector)) {
|
||||
throw new Error(el + "can't be disembedded!")
|
||||
}
|
||||
el.cacheListeners?.forEach(({type, listener, options}) => {
|
||||
el.removeEventListener(type, listener, options)
|
||||
})
|
||||
// TODO: 清理 GestureDetector 中的内容
|
||||
|
||||
el.gestureDector.listenEvents.clear()
|
||||
el.gestureDector.listenOnceEvents.clear()
|
||||
el.gestureDetector.listenEvents.clear()
|
||||
el.gestureDetector.listenOnceEvents.clear()
|
||||
el.cacheListeners = []
|
||||
delete el._addEventListener
|
||||
delete el.gestureDector
|
||||
return el
|
||||
delete el.gestureDetector
|
||||
}
|
||||
|
||||
private static _GestureDetectorId = 0
|
||||
|
|
|
@ -25,7 +25,12 @@ export class PanelActiveOverlay extends LitElement {
|
|||
const content = targetNode?.nextElementSibling as HTMLElement
|
||||
if (!content) return
|
||||
// 调用overlayStack中的openOverlay方法创建节点
|
||||
this.overlayStack.openOverlay(originalNode, targetNode, content)
|
||||
this.overlayStack.openOverlay(
|
||||
originalNode,
|
||||
targetNode,
|
||||
content,
|
||||
'overflowmenu'
|
||||
)
|
||||
} else {
|
||||
this.overlayStack.closeOverlay()
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ export class PanelBatterysquare extends LitElement {
|
|||
render() {
|
||||
return html`
|
||||
<star-batterysquare></star-batterysquare>
|
||||
<star-batterysquare blue></star-batterysquare>
|
||||
<star-batterysquare deep></star-batterysquare>
|
||||
<star-batterysquare deep blue></star-batterysquare>
|
||||
<!-- <star-batterysquare blue></star-batterysquare> -->
|
||||
<!-- <star-batterysquare deep></star-batterysquare> -->
|
||||
<!-- <star-batterysquare deep blue></star-batterysquare> -->
|
||||
`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,34 @@
|
|||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
import {html, LitElement, CSSResultArray, css} from 'lit'
|
||||
import {customElement, query} from 'lit/decorators.js'
|
||||
import {sharedStyles} from '../../../components/battery/battery-styles'
|
||||
|
||||
@customElement('panel-battery')
|
||||
export class PanelBattery extends LitElement {
|
||||
@query('#container') container!: HTMLElement
|
||||
render() {
|
||||
return html`
|
||||
<star-battery></star-battery>
|
||||
<star-battery deep></star-battery>
|
||||
<star-battery charge></star-battery>
|
||||
<star-battery charge deep></star-battery>
|
||||
<star-battery vertical></star-battery>
|
||||
<star-battery vertical deep class="location"></star-battery>
|
||||
<star-battery vertical charge class="location_charge"></star-battery>
|
||||
<star-battery vertical charge deep class="location_charge_deep"></star-battery>
|
||||
<star-battery class="mini" mini></star-battery>
|
||||
<star-battery class="mini" mini charge></star-battery>
|
||||
<star-battery class="small" small></star-battery>
|
||||
<star-battery class="small" small charge></star-battery>
|
||||
<star-battery class="medium" medium></star-battery>
|
||||
<star-battery class="medium" medium charge></star-battery>
|
||||
<div id="container">
|
||||
<star-battery vertical></star-battery>
|
||||
</div>
|
||||
<!-- <star-battery deep></star-battery> -->
|
||||
<!-- <star-battery charge></star-battery> -->
|
||||
`
|
||||
}
|
||||
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [sharedStyles]
|
||||
return [
|
||||
sharedStyles,
|
||||
css`
|
||||
:host {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
#container {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
`,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import {html, css, LitElement} from 'lit'
|
||||
import {customElement, property, state} from 'lit/decorators.js'
|
||||
import {customElement, property, query, state} from 'lit/decorators.js'
|
||||
import {StarClock} from '../../../components/clock/clock'
|
||||
@customElement('panel-clock')
|
||||
export class PanelClock extends LitElement {
|
||||
@property()
|
||||
foo = ''
|
||||
@state()
|
||||
date = 0
|
||||
date: any = '0'
|
||||
@query('#test1') clockTest1!: StarClock
|
||||
@query('#test2') clockTest2!: StarClock
|
||||
@query('#test3') clockTest3!: StarClock
|
||||
@query('#test4') clockTest4!: StarClock
|
||||
render() {
|
||||
return html`
|
||||
<h3
|
||||
|
@ -17,14 +22,10 @@ export class PanelClock extends LitElement {
|
|||
style="display:flex;justify-content: center; align-items: center; padding: 20px 0;"
|
||||
>
|
||||
<div style=" width: 380px; height: 380px;overflow: hidden">
|
||||
<star-clock date="${this.date}" type="diale"></star-clock>
|
||||
<star-clock id="test1" type="diale"></star-clock>
|
||||
</div>
|
||||
<div style="width: 380px; height: 380px;overflow: hidden">
|
||||
<star-clock
|
||||
date="${this.date}"
|
||||
type="diale"
|
||||
mode="light"
|
||||
></star-clock>
|
||||
<star-clock id="test2" type="diale" mode="light"></star-clock>
|
||||
</div>
|
||||
</div>
|
||||
<h3
|
||||
|
@ -36,26 +37,23 @@ export class PanelClock extends LitElement {
|
|||
style="display:flex;justify-content: center; align-items: center; padding: 20px 0"
|
||||
>
|
||||
<div style="width: 380px; height: 380px;overflow: hidden">
|
||||
<star-clock date="${this.date}" type="transparent"></star-clock>
|
||||
<star-clock id="test3" type="transparent"></star-clock>
|
||||
</div>
|
||||
<div style="width: 380px; height: 380px;overflow: hidden">
|
||||
<star-clock
|
||||
date="${this.date}"
|
||||
type="transparent"
|
||||
mode="light"
|
||||
></star-clock>
|
||||
<star-clock id="test4" type="transparent" mode="light"></star-clock>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
static styles = css``
|
||||
protected firstUpdated() {
|
||||
this.date = new Date().getTime()
|
||||
let timeMy = new Date(Number(this.date))
|
||||
let hour = timeMy.getHours()
|
||||
let minute = timeMy.getMinutes()
|
||||
let second = timeMy.getSeconds()
|
||||
console.log('传的值和类型:000', hour, minute, second)
|
||||
this.clockTest1.date = new Date() // 传Date型
|
||||
this.clockTest2.date = new Date().getTime() // 传Number型
|
||||
this.clockTest3.date = new Date().toString() // 传string型
|
||||
this.clockTest4.date = new Date().toString() // 传string型
|
||||
// this.date = new Date().toString()
|
||||
// this.date = new Date().getTime()
|
||||
// this.date = new Date()
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
|
|
|
@ -75,6 +75,7 @@ export class PanelContainer extends LitElement {
|
|||
// 存储全局变量
|
||||
;(window as any).dock = this.dock
|
||||
;(window as any).container = this.container
|
||||
;(window as any).pageIndicator = this.pageIndicator
|
||||
;(window as any).home = this
|
||||
|
||||
// container 相关事件
|
||||
|
@ -128,6 +129,7 @@ export class PanelContainer extends LitElement {
|
|||
})
|
||||
} else {
|
||||
this.addAppIcon(1, 1)
|
||||
this.container.changeLayout()
|
||||
let promise = new Promise((res) => {
|
||||
res(undefined)
|
||||
})
|
||||
|
@ -236,14 +238,13 @@ export class PanelContainer extends LitElement {
|
|||
|
||||
// 此时的拖拽进 container 组件的标志才意味着是否成功放置成功
|
||||
if (this.dragInContainer) {
|
||||
this.dock.removeContainerChild(evt.detail.target)
|
||||
if (this.container._dnd.child) {
|
||||
this.container._dnd.child.element = evt.detail.target
|
||||
this.container._dnd.child.container.classList.remove('dragging')
|
||||
this.container._dnd.child = undefined
|
||||
this.container.synchronise()
|
||||
}
|
||||
|
||||
this.dock.removeContainerChild(evt.detail.target)
|
||||
} else {
|
||||
this.container.removeContainerChild(this.elementPlaceholder)
|
||||
}
|
||||
|
@ -409,6 +410,12 @@ export class PanelContainer extends LitElement {
|
|||
height: 2px;
|
||||
background-color: pink;
|
||||
}
|
||||
|
||||
star-dock .dock-child-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
`,
|
||||
homescreenStyle,
|
||||
]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {html, LitElement, css, CSSResultArray} from 'lit'
|
||||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
import '../../../components/button/button'
|
||||
import '../../../components/ul/ul'
|
||||
|
@ -15,7 +15,12 @@ export class PanelOverflowMenu extends LitElement {
|
|||
return html`
|
||||
<star-overflowmenu triggertype="overflowmenu">
|
||||
<div id="menu">
|
||||
<star-ul type="base" id="overflowmenu" class="appinfo" background="var(--bg-dialog)">
|
||||
<star-ul
|
||||
type="base"
|
||||
id="overflowmenu"
|
||||
class="appinfo"
|
||||
background="var(--bg-dialog)"
|
||||
>
|
||||
<star-button
|
||||
type="iconlabel"
|
||||
icon="info"
|
||||
|
@ -52,7 +57,12 @@ export class PanelOverflowMenu extends LitElement {
|
|||
triggertype="overflowmenu"
|
||||
>
|
||||
<div id="menu">
|
||||
<star-ul type="base" id="overflowmenu" class="appinfo" background="var(--bg-dialog)">
|
||||
<star-ul
|
||||
type="base"
|
||||
id="overflowmenu"
|
||||
class="appinfo"
|
||||
background="var(--bg-dialog)"
|
||||
>
|
||||
<star-button
|
||||
type="iconlabel"
|
||||
icon="info"
|
||||
|
@ -89,7 +99,12 @@ export class PanelOverflowMenu extends LitElement {
|
|||
triggertype="overflowmenu"
|
||||
>
|
||||
<div id="menu">
|
||||
<star-ul type="base" id="overflowmenu" class="appinfo" background="var(--bg-dialog)">
|
||||
<star-ul
|
||||
type="base"
|
||||
id="overflowmenu"
|
||||
class="appinfo"
|
||||
background="var(--bg-dialog)"
|
||||
>
|
||||
<star-button
|
||||
type="iconlabel"
|
||||
icon="info"
|
||||
|
@ -126,7 +141,12 @@ export class PanelOverflowMenu extends LitElement {
|
|||
triggertype="overflowmenu"
|
||||
>
|
||||
<div id="menu">
|
||||
<star-ul type="base" id="overflowmenu" class="appinfo" background="var(--bg-dialog)">
|
||||
<star-ul
|
||||
type="base"
|
||||
id="overflowmenu"
|
||||
class="appinfo"
|
||||
background="var(--bg-dialog)"
|
||||
>
|
||||
<star-button
|
||||
type="iconlabel"
|
||||
icon="info"
|
||||
|
@ -163,7 +183,12 @@ export class PanelOverflowMenu extends LitElement {
|
|||
triggertype="overflowmenu"
|
||||
>
|
||||
<div id="menu">
|
||||
<star-ul type="base" id="overflowmenu" class="appinfo" background="var(--bg-dialog)">
|
||||
<star-ul
|
||||
type="base"
|
||||
id="overflowmenu"
|
||||
class="appinfo"
|
||||
background="var(--bg-dialog)"
|
||||
>
|
||||
<star-button
|
||||
type="iconlabel"
|
||||
icon="info"
|
||||
|
|
|
@ -21,6 +21,7 @@ import './container/container'
|
|||
import './radio/radio'
|
||||
import './confirm/confirm'
|
||||
import './clock/clock'
|
||||
import './weather/weather'
|
||||
import './overflowmenu/overflowmenu'
|
||||
import './switch/switch'
|
||||
import './slider/slider'
|
||||
|
@ -35,7 +36,8 @@ import './notification/notification'
|
|||
|
||||
import './switch/switch'
|
||||
import './activeoverlay/activeoverlay'
|
||||
|
||||
import './battery/battery'
|
||||
import './battery-square/battery-square'
|
||||
type SEID = string
|
||||
|
||||
@customElement('panel-root')
|
||||
|
@ -316,6 +318,14 @@ export class PanelRoot extends LitElement {
|
|||
iconcolor="green"
|
||||
href="#clock"
|
||||
></star-li>
|
||||
<hr />
|
||||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
label="天气"
|
||||
icon="moon"
|
||||
iconcolor="green"
|
||||
href="#weather"
|
||||
></star-li>
|
||||
</star-ul>
|
||||
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="手势">
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
|
||||
export const sharedStyles: CSSResult = css`
|
||||
.location {
|
||||
margin-left: 40px;
|
||||
hr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
border-color: #ccc;
|
||||
}
|
||||
hr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-width: 0 0 1px 0;
|
||||
border-style: solid;
|
||||
border-color: #ccc;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import {html, css, LitElement} from 'lit'
|
||||
import {customElement, query, state} from 'lit/decorators.js'
|
||||
import {StarWeather} from '../../../components/weather/weather.js'
|
||||
import {weatherData} from './weatherData.js'
|
||||
@customElement('panel-weather')
|
||||
export class PanelWeather extends LitElement {
|
||||
@state()
|
||||
foo = ''
|
||||
@state()
|
||||
data = Array()
|
||||
@query('#type11') weatherDemo1!: StarWeather
|
||||
@query('#type12') weatherDemo2!: StarWeather
|
||||
@query('#type21') weatherDemo3!: StarWeather
|
||||
@query('#type22') weatherDemo4!: StarWeather
|
||||
render() {
|
||||
return html`
|
||||
<div
|
||||
style="width: 100vw; height: 100vh;background: rgba(53,168,239,0.3);display:flex;justify-content: center; align-items: center;padding: 90px 0; flex-wrap: wrap"
|
||||
>
|
||||
<!-- <div style="width: 20%;height:20%; border: 1px dashed #bd135f; ">
|
||||
<star-weather id="type11" type="type11"></star-weather>
|
||||
</div>
|
||||
<div style="width: 25%;height:50%; border: 1px dashed #bd135f; ">
|
||||
<star-weather id="type12" type="type12"></star-weather>
|
||||
</div>
|
||||
<div style="width: 25%;height:50%;border: 1px dashed #bd135f;">
|
||||
<star-weather id="type21" type="type21"></star-weather>
|
||||
</div> -->
|
||||
<!-- <div style="width: 50%;height:50%; border: 1px dashed #e72517;"> -->
|
||||
<star-weather id="type22" type="type22"></star-weather>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
`
|
||||
}
|
||||
static styles = css`
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`
|
||||
protected firstUpdated() {
|
||||
// this.weatherDemo1.data = weatherData
|
||||
// this.weatherDemo2.data = weatherData
|
||||
// this.weatherDemo3.data = weatherData
|
||||
this.weatherDemo4.data = weatherData
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'panel-weather': PanelWeather
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
export const weatherData = {
|
||||
location: '长沙市',
|
||||
weatherInfo: [
|
||||
{
|
||||
date: new Date(),
|
||||
temperature: {
|
||||
min: '22℃',
|
||||
max: '29℃',
|
||||
},
|
||||
weather: {
|
||||
labelZh: '多云',
|
||||
labelEn: 'PartlyCloudy',
|
||||
},
|
||||
wind: {
|
||||
label: '南风',
|
||||
value: '6级',
|
||||
},
|
||||
humidity: '40%',
|
||||
airQuality: {
|
||||
label: '空气质量',
|
||||
value: '28',
|
||||
type: '优',
|
||||
},
|
||||
somatosensoryTemperature: '32°C',
|
||||
visibility: '33km',
|
||||
ultravioletRys: '强',
|
||||
},
|
||||
{},
|
||||
],
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import GaiaWidget from '../gaia-widget'
|
||||
import '../../components/clock/clock'
|
||||
import {StarClock} from '../../components/clock/clock'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
|
||||
@customElement('gaia-clock')
|
||||
class ClockWidget extends GaiaWidget {
|
||||
_type: 'transparent' | 'daile' = 'daile'
|
||||
|
||||
get type() {
|
||||
return this._type
|
||||
}
|
||||
|
||||
set type(value: 'transparent' | 'daile') {
|
||||
if (value !== this._type) {
|
||||
this._type = value
|
||||
this.clock.type = value
|
||||
}
|
||||
}
|
||||
|
||||
constructor({
|
||||
url,
|
||||
appName,
|
||||
origin,
|
||||
size,
|
||||
manifestWidgetName,
|
||||
}: {
|
||||
url: string
|
||||
size: [number, number]
|
||||
origin: string
|
||||
appName: string
|
||||
manifestWidgetName: string
|
||||
}) {
|
||||
super({
|
||||
url: url || 'js/widgets/clock.js',
|
||||
appName: appName || 'homescreen',
|
||||
origin: origin || 'http://homescreen.localhost/manifest.webmanifest',
|
||||
size: size || [2, 2],
|
||||
manifestWidgetName: manifestWidgetName || 'clock',
|
||||
})
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
clock!: StarClock
|
||||
connectedCallback() {
|
||||
this.clock = this.shadowRoot!.querySelector('star-clock')!
|
||||
this.clock.date = new Date()
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.clock.date = new Date()
|
||||
}
|
||||
get template() {
|
||||
return `
|
||||
<style>
|
||||
:host {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<star-clock type="diale"></star-clock>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
export default ClockWidget
|
|
@ -0,0 +1,443 @@
|
|||
// import {html, LitElement, css} from 'lit'
|
||||
// import {customElement} from 'lit/decorators.js'
|
||||
|
||||
import {StarBaseElement} from '../components/base'
|
||||
|
||||
/**
|
||||
* 主屏小组件:
|
||||
*
|
||||
* const widget = new GaiaWidget({
|
||||
* url: 'http://rigesterapp.localhost/widget/a_widget.html',
|
||||
* size: manifest.b2g_features.widget.a_widget.size || [1, 1],
|
||||
* origin: 'http://rigesterapp.localhost',
|
||||
* appName: 'rigesterapp'
|
||||
* manifestWidgetName: 'test-widget'
|
||||
* })
|
||||
*
|
||||
* 向注册小组件的应用发送Activity请求:
|
||||
* new WebActivity(activityName, {
|
||||
* data: {
|
||||
* widgetTitle, // 组件名,写在小组件页面的 title 标签内
|
||||
* manifestName, // 清单内的组件名,写在清单文件的 widget 对象中
|
||||
* viewName, // 视图名,写在 template 标签内
|
||||
* },
|
||||
* type: ['widget']
|
||||
* })
|
||||
*
|
||||
* TBD:
|
||||
* 1. 多视图功能,每个视图由 <template name="view-name"></template> 包裹,与单视图
|
||||
* 写法(没有 <template> 标签)互斥
|
||||
*/
|
||||
// @customElement('gaia-widget')
|
||||
|
||||
function lowerCase(str: string) {
|
||||
str = str.replace(/\s/g, '')
|
||||
return str.toLocaleLowerCase()
|
||||
}
|
||||
export default class GaiaWidget extends StarBaseElement {
|
||||
url!: string
|
||||
size!: [number, number]
|
||||
origin!: string
|
||||
appName!: string
|
||||
manifestWidgetName!: string // 清单文件中的组件名
|
||||
widgetTitle: string = '' // 组件名
|
||||
viewName: string = '' // 视图名,当该组件有多个视图时,视图名用于区分
|
||||
createTime: number = new Date().getTime()
|
||||
container!: HTMLElement
|
||||
activityRequestTimer: number | undefined
|
||||
constructor({
|
||||
url,
|
||||
size,
|
||||
origin,
|
||||
appName,
|
||||
manifestWidgetName,
|
||||
}: {
|
||||
url: string
|
||||
size: [number, number]
|
||||
origin: string
|
||||
appName: string
|
||||
manifestWidgetName: string
|
||||
}) {
|
||||
super()
|
||||
this.widgetTitle = ''
|
||||
this.manifestWidgetName = manifestWidgetName
|
||||
this.viewName = ''
|
||||
this.createTime = new Date().getTime()
|
||||
this.url = url // 组件文件地址
|
||||
this.origin = origin // 注册应用 origin
|
||||
this.size = size // 组件行列大小
|
||||
this.appName = lowerCase(appName)
|
||||
this.attachShadow({mode: 'open'})
|
||||
this.shadowRoot!.innerHTML = this.template
|
||||
|
||||
this.init()
|
||||
this.dispatchReady()
|
||||
}
|
||||
|
||||
init() {
|
||||
// 补全小组件入口地址
|
||||
if (!/^http(s)?:\/\//.test(this.url)) {
|
||||
if (/^\//.test(this.url)) {
|
||||
this.url = this.origin + this.url
|
||||
} else {
|
||||
this.url = this.origin + '/' + this.url
|
||||
}
|
||||
}
|
||||
this.container = this.shadowRoot!.querySelector(
|
||||
'#gaia-widget-container-' + this.createTime
|
||||
)!
|
||||
this.container.addEventListener('touchstart', this)
|
||||
this.container.addEventListener('touchmove', this)
|
||||
this.container.addEventListener('touchend', this)
|
||||
this.container.addEventListener('click', this)
|
||||
}
|
||||
|
||||
dispatchReady = () => {
|
||||
// 需要在构造函数中被调用,在connectedCallback中调用会导致移动元素时刷新的问题
|
||||
// 防止安装、更新应用时,首次 Activity 请求因注册方 Service Worker 未完成安装而丢失
|
||||
let n = 0
|
||||
this.activityRequestTimer = window.setInterval(() => {
|
||||
if (n++ > 4) clearInterval(this.activityRequestTimer)
|
||||
this.openActivity({data: {type: 'ready'}})
|
||||
}, 100)
|
||||
}
|
||||
|
||||
refresh(widgetInfo: {size: [number, number]; url: string}) {
|
||||
if (
|
||||
this.size[0] != widgetInfo.size[0] ||
|
||||
this.size[1] != widgetInfo.size[1]
|
||||
) {
|
||||
// 更新后的组件大小发生了变化
|
||||
this.dispatchEvent(new CustomEvent('widget-resize'))
|
||||
}
|
||||
|
||||
this.url = widgetInfo.url
|
||||
this.shadowRoot!.innerHTML = this.template
|
||||
this.container.removeEventListener('touchstart', this)
|
||||
this.container.removeEventListener('touchmove', this)
|
||||
this.container.removeEventListener('touchend', this)
|
||||
this.container.removeEventListener('click', this)
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
touchTimer: number | undefined
|
||||
handleEvent(event: TouchEvent) {
|
||||
switch (event.type) {
|
||||
case 'touchstart':
|
||||
console.log(event)
|
||||
clearTimeout(this.touchTimer)
|
||||
this.touchTimer = window.setTimeout(() => {
|
||||
console.log('touchTimer end')
|
||||
this.touchTimer = undefined
|
||||
}, 100)
|
||||
break
|
||||
case 'touchmove':
|
||||
break
|
||||
case 'touchend':
|
||||
case 'click':
|
||||
console.log(this.touchTimer)
|
||||
// @ts-ignore
|
||||
this.touchTimer && this.dispatch(event)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
toCamelCase = (string: string) => {
|
||||
// @ts-ignore
|
||||
return string.replace(/\-(.)/g, function replacer(str, p1) {
|
||||
return p1.toUpperCase()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 向注册应用发送事件
|
||||
*/
|
||||
dispatch = (event: CustomEvent) => {
|
||||
// @ts-ignore
|
||||
if (!WebActivity) {
|
||||
return console.error('WebActivity is not defined!')
|
||||
}
|
||||
|
||||
const data = this.wrapEvent(event)
|
||||
this.openActivity({data})
|
||||
}
|
||||
|
||||
openActivity = ({data}: any) => {
|
||||
data.widgetTitle = this.widgetTitle
|
||||
data.manifestName = this.manifestWidgetName
|
||||
data.viewName = this.viewName
|
||||
|
||||
// @ts-ignore
|
||||
const activity = new WebActivity(
|
||||
`${this.appName}_${this.manifestWidgetName}`,
|
||||
{data, type: ['widget']}
|
||||
)
|
||||
|
||||
activity
|
||||
.start()
|
||||
.then((result: any) => {
|
||||
if (this.activityRequestTimer) clearInterval(this.activityRequestTimer)
|
||||
this.handleActivity(result)
|
||||
})
|
||||
.catch((err: any) => console.log(err))
|
||||
}
|
||||
|
||||
wrapEvent = (event: any) => {
|
||||
const target = event?.path?.[0] || event.originalTarget
|
||||
const style: {[prop: string]: string} = {}
|
||||
for (let index = 0; index < target.style.length; index++) {
|
||||
const styleName = target.style.item(index)
|
||||
const camelName = this.toCamelCase(styleName)
|
||||
style[styleName] = target.style[camelName]
|
||||
}
|
||||
|
||||
return {
|
||||
timeStamp: event.timeStamp,
|
||||
type: event.type,
|
||||
id: target.id,
|
||||
className: target.className,
|
||||
classList: target.classList,
|
||||
dataset: target.dataset,
|
||||
style,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求组件资源
|
||||
*/
|
||||
querySources(url: string) {
|
||||
return new Promise((res, rej) => {
|
||||
// @ts-ignore
|
||||
const xhr = new XMLHttpRequest({mozSystem: true})
|
||||
xhr.open('GET', url, true)
|
||||
// xhr.responseType = "text";
|
||||
xhr.send()
|
||||
xhr.onload = () => {
|
||||
if (xhr.status == 200) {
|
||||
if (!xhr.response) {
|
||||
rej(
|
||||
new Error(
|
||||
'Empty response to ' + url + ', ' + 'possibly syntax error'
|
||||
)
|
||||
)
|
||||
}
|
||||
res(xhr.response)
|
||||
} else {
|
||||
rej(
|
||||
new Error(
|
||||
`query soures err! xhr.status: ${xhr.status}; xhr.url: ${url}`
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文档字符串转化为 DOM 节点
|
||||
* TBD:当前一个组件仅能有一个视图,需要添加多视图情况
|
||||
* @param {DOMString} html 文档字符串
|
||||
* @returns
|
||||
*/
|
||||
parseHTML = (html: string) => {
|
||||
html = this.handleSource(this.filterDom(html))
|
||||
|
||||
const parse = new DOMParser()
|
||||
const htmlDocument = parse.parseFromString(html, 'text/html')
|
||||
const {head, body} = htmlDocument
|
||||
// @ts-ignore
|
||||
this.widgetTitle = head?.querySelector('title').innerHTML
|
||||
if (this.widgetTitle === void 0) {
|
||||
throw new Error('There is not a widget name yet!')
|
||||
}
|
||||
|
||||
this.appendStyle(htmlDocument)
|
||||
this.container.innerHTML = body.innerHTML
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理来自注册应用的 Activity 传入的操作命令
|
||||
*/
|
||||
handleActivity = (data: any) => {
|
||||
const {changeContext, changeAttributes, changeProperties} = data
|
||||
|
||||
this.changeAttributes(changeAttributes)
|
||||
this.changeContext(changeContext)
|
||||
this.changeProperties(changeProperties)
|
||||
}
|
||||
|
||||
changeContext = (data: any) => {
|
||||
if (!data) return
|
||||
|
||||
data.forEach((operator: any) => {
|
||||
const dom = this.shadowRoot!.querySelector(operator.target)
|
||||
dom.innerText = operator.data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 setAttribute 改变指定元素的属性
|
||||
*/
|
||||
changeAttributes = (data: any) => {
|
||||
if (!data) return
|
||||
|
||||
data.forEach((operator: any) => {
|
||||
if (operator?.data?.length !== 2) throw new Error('Illegal parameter')
|
||||
|
||||
const dom = this.shadowRoot!.querySelector(operator.target)
|
||||
|
||||
if (operator.data[0] === 'src' && !/^http:\/\//.test(operator.data[1])) {
|
||||
let str = operator.data[1].replace(/^\//, '')
|
||||
operator.data[1] = this.origin + '/' + str
|
||||
}
|
||||
dom.setAttribute(...operator.data)
|
||||
})
|
||||
}
|
||||
|
||||
changeProperties = (data: any) => {
|
||||
if (!data) return
|
||||
|
||||
for (const key in data) {
|
||||
const value = data[key] as string
|
||||
// @ts-ignore
|
||||
this[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TBD: 需要考虑更多元素
|
||||
* 处理img资源请求路径
|
||||
*/
|
||||
handleSource = (html: string) => {
|
||||
html = html.replace(
|
||||
/<img.*?src="(.*?)"/g,
|
||||
(string: string, url: string) => {
|
||||
if (!/^http:\/\//.test(url)) {
|
||||
string = string.replace(url, `${this.origin}/${url}`)
|
||||
}
|
||||
return string
|
||||
}
|
||||
)
|
||||
return html
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定元素内的style标签和[rel="stylesheet"]标签的样式
|
||||
* 加载并添加进影子节点内
|
||||
*/
|
||||
appendStyle = (dom: Document) => {
|
||||
this.collectStyle(dom).then((styles) => {
|
||||
for (const style of styles) {
|
||||
this.shadowRoot!.appendChild(style)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集指定元素内的style标签和[rel="stylesheet"]标签
|
||||
*/
|
||||
collectStyle(dom: any): Promise<HTMLStyleElement[]> {
|
||||
return new Promise((res) => {
|
||||
let promises: Promise<any>[] = []
|
||||
let styles = [...dom.querySelectorAll('style')] || []
|
||||
const links = dom.querySelectorAll('[rel="stylesheet"]')
|
||||
|
||||
if (links?.length) {
|
||||
links.forEach((element: HTMLLinkElement) => {
|
||||
let href = element.href
|
||||
// 将href的源改为注册组件的源
|
||||
href = href.replace(location.origin, this.origin)
|
||||
if (!/^http:\/\//.test(href)) {
|
||||
href = `${this.origin}/${href}`
|
||||
}
|
||||
promises.push(this.querySources(href))
|
||||
})
|
||||
|
||||
Promise.all(promises).then((sheets) => {
|
||||
for (const css of sheets) {
|
||||
const style = document.createElement('style')
|
||||
style.innerHTML = this.modifyCss(css)
|
||||
styles.push(style)
|
||||
}
|
||||
|
||||
res(styles)
|
||||
})
|
||||
} else {
|
||||
for (const style of styles) {
|
||||
style.innerHTML = this.modifyCss(style.innerHTML)
|
||||
}
|
||||
|
||||
res(styles)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 html body 样式,并将其样式转为对该组件的样式
|
||||
*/
|
||||
modifyCss = (css: string) => {
|
||||
return css.replace(
|
||||
/([^{]+)(\{[^}]+\})/g,
|
||||
// @ts-ignore
|
||||
(group, selector, declarations) => {
|
||||
selector = selector.replace(
|
||||
/(?<!=[a-zA-Z]|-)(html|body)(?!=[a-zA-Z]|-)/g,
|
||||
// @ts-ignore
|
||||
(selecor, str) => {
|
||||
return `#gaia-widget-container-${this.createTime}`
|
||||
}
|
||||
)
|
||||
return selector + declarations
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛除 a、script 标签,更改 form 标签的 action 属性
|
||||
*/
|
||||
filterDom = (string: string) => {
|
||||
string = string.replace(
|
||||
/(<a)(.*?>.*)(<\/a>)/g,
|
||||
// @ts-ignore
|
||||
function (string, head, body, tail) {
|
||||
body = body.replace(/href=".*?"(.*>)/, '$1')
|
||||
return `<span${body}</span>`
|
||||
}
|
||||
)
|
||||
|
||||
string = string.replace(/<script.*?<\/script>/, '')
|
||||
|
||||
// @ts-ignore
|
||||
string = string.replace(/(<form .*action=")(.*)/g, function (string, form) {
|
||||
return `${form}#`
|
||||
})
|
||||
|
||||
return string
|
||||
}
|
||||
|
||||
get template() {
|
||||
return `
|
||||
<div id="gaia-widget-container-${this.createTime}"></div>
|
||||
<style>${this.shadowStyle}</style>
|
||||
`
|
||||
}
|
||||
|
||||
get shadowStyle() {
|
||||
return `
|
||||
:host {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
:host > div[id^=gaia-widget-container-] {
|
||||
overflow: hidden;
|
||||
border-radius: 8px;
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
import GaiaWidget from '../gaia-widget'
|
||||
import '../../components/weather/weather'
|
||||
import {StarWeather} from '../../components/weather/weather'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
|
||||
@customElement('gaia-weather')
|
||||
class WeatherWidget extends GaiaWidget {
|
||||
_type: string = 'type22'
|
||||
_data: any
|
||||
widget!: StarWeather
|
||||
constructor({
|
||||
url,
|
||||
appName,
|
||||
origin,
|
||||
size,
|
||||
manifestWidgetName,
|
||||
}: {
|
||||
url: string
|
||||
size: [number, number]
|
||||
origin: string
|
||||
appName: string
|
||||
manifestWidgetName: string
|
||||
}) {
|
||||
super({
|
||||
url: url || 'js/widgets/weather.js',
|
||||
appName: appName || 'homescreen',
|
||||
origin: origin || 'http://homescreen.localhost/manifest.webmanifest',
|
||||
size: size || [2, 2],
|
||||
manifestWidgetName: manifestWidgetName || 'weather',
|
||||
})
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type
|
||||
}
|
||||
|
||||
set type(value) {
|
||||
this.type = value
|
||||
this.widget.type = value
|
||||
}
|
||||
|
||||
get data() {
|
||||
return this._data
|
||||
}
|
||||
|
||||
set data(value: any) {
|
||||
this._data = value
|
||||
if (!this.widget) {
|
||||
setTimeout(() => {
|
||||
this.widget.data = value
|
||||
}, 100)
|
||||
} else {
|
||||
this.widget.data = value
|
||||
}
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
||||
connectedCallback() {
|
||||
this.widget = this.shadowRoot?.querySelector('star-weather') as StarWeather
|
||||
}
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['type']
|
||||
}
|
||||
|
||||
attributeChangedCallback(name: string, _: string, newValue: string) {
|
||||
switch (name) {
|
||||
case 'type':
|
||||
this.type = newValue
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
get template() {
|
||||
return `
|
||||
<star-weather type="type22"></star-weather>
|
||||
<style>
|
||||
:host {
|
||||
height: 100%;
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
export default WeatherWidget
|
|
@ -0,0 +1,77 @@
|
|||
import fs from 'fs'
|
||||
import {build} from 'vite'
|
||||
const PWD = process.cwd()
|
||||
|
||||
const clearDir = (path, exclude) => {
|
||||
var files = []
|
||||
|
||||
if (fs.existsSync(path)) {
|
||||
files = fs.readdirSync(path)
|
||||
|
||||
for (const file of files) {
|
||||
if (file === exclude) continue
|
||||
var curPath = path + '/' + file
|
||||
|
||||
if (fs.statSync(curPath).isDirectory()) {
|
||||
clearDir(curPath)
|
||||
fs.rmdirSync(curPath)
|
||||
} else {
|
||||
fs.unlinkSync(curPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fun = async (widgetName, entryName) => {
|
||||
await build({
|
||||
build: {
|
||||
lib: {
|
||||
entry: `src/widgets/${widgetName}/${entryName}.ts`,
|
||||
formats: ['es'],
|
||||
fileName: `${widgetName}`,
|
||||
},
|
||||
outDir: `dist/widgets/${widgetName}/`,
|
||||
},
|
||||
})
|
||||
|
||||
clearDir(`dist/widgets/${widgetName}`, `${widgetName}.js`)
|
||||
}
|
||||
|
||||
const safeReadDirSync = (path) => {
|
||||
let dirData = {}
|
||||
try {
|
||||
dirData = fs.readdirSync(path)
|
||||
} catch (ex) {
|
||||
if (ex.code == 'EACCES' || ex.code == 'EPERM') {
|
||||
// 无权访问该文件夹,跳过
|
||||
return null
|
||||
} else {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
return dirData
|
||||
}
|
||||
|
||||
const buildAll = () => {
|
||||
const widgetsFilePath = `${PWD}/src/widgets`
|
||||
const dirData = safeReadDirSync(widgetsFilePath)
|
||||
|
||||
dirData?.forEach((fileName) => {
|
||||
const widgetPath = `${widgetsFilePath}/${fileName}`
|
||||
const stats = fs.statSync(widgetPath)
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
const files = safeReadDirSync(widgetPath)
|
||||
if (files.includes(`${fileName}.ts`)) {
|
||||
fun(fileName, fileName)
|
||||
} else if (files.includes(`index.ts`)) {
|
||||
fun(fileName, 'index')
|
||||
} else {
|
||||
throw new Error(`Entry file of ${fileName} widget dose not exist!`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
buildAll()
|
|
@ -21,6 +21,8 @@ export const watchFiles = async () => {
|
|||
const files = await fg([
|
||||
'./src/components/**/!(*.d).ts',
|
||||
'./src/lib/**/!(*.d).ts',
|
||||
'src/widgets/*.ts',
|
||||
'src/widgets/**/*.ts',
|
||||
])
|
||||
return files
|
||||
}
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
"noEmit": true,
|
||||
"emitDeclarationOnly": false
|
||||
},
|
||||
"include": ["src/components/**/*.ts", "src/lib/**/*.ts"],
|
||||
"include": [
|
||||
"src/components/**/*.ts",
|
||||
"src/lib/**/*.ts",
|
||||
"src/widgets/*.ts",
|
||||
"src/widgets/**/.ts"
|
||||
],
|
||||
"exclude": ["src/*/node_modules/**/*.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue