Compare commits

...

10 Commits

Author SHA1 Message Date
宇天 48536d29e8 更新UI库 2021-02-05 16:38:38 +08:00
宇天 cc7562db6e 优化toc 2021-01-14 13:49:54 +08:00
宇天 9252e0c180 优化阅读窗口 2021-01-14 11:18:20 +08:00
宇天 f1fe597317 优化epub解析;优化目录; 2021-01-14 11:12:31 +08:00
宇天 1155252604 优化代码块 2021-01-12 20:09:19 +08:00
宇天 fbdef3c56f 修复图片显示异常的bug;优化无封面书籍自动生成封面 2021-01-12 20:04:18 +08:00
宇天 99a97c5242 1.0.0 2021-01-08 20:36:28 +08:00
宇天 6c161866da 完成阅读器1.0.0 2021-01-08 20:34:22 +08:00
宇天 71aebe5cbd 完成书本解析 2021-01-07 19:46:23 +08:00
宇天 4b4ef306c2 修复书本读取 2021-01-06 20:21:11 +08:00
46 changed files with 1849 additions and 4433 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "org.bytedo.epub", "name": "org.bytedo.epub",
"version": "2.1.2", "version": "1.2.1",
"description": "E-pub Reader", "description": "E-pub Reader",
"main": "src/main.js", "main": "src/main.js",
"scripts": { "scripts": {

View File

@ -1 +1 @@
html{font-size:12.8px;width:100%;height:100vh}body{overflow:hidden;display:flex;flex-direction:column;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}.app{position:relative;display:flex;height:100%}.app .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .detail{position:relative;flex:1;height:100%;border-left:1px solid var(--color-plain-2);background:rgba(255,255,255,0.5)}.app .detail .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:35px;padding:0 16px;font-size:16px;font-weight:bold}.app .detail .title span{display:inline-flex}.app .detail .title wc-button{margin:0 6px}.app .detail .card{width:96%;padding:12px 12px 16px;margin:12px 2% 24px;border:0;background:#fff;box-shadow:0 0 8px rgba(0,0,0,0.075)}.app .detail .card legend{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#64b5f6}.app .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, #fff3e3 200px)}.app .drag-mask::after{font-size:46px;text-indent:300px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}} html{width:100%;height:100vh}body{overflow:hidden;display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;width:100%;height:100%}.app .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .books-scroll{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .books{display:flex;flex-wrap:wrap}.app .books .book{display:flex;flex-direction:column;width:128px;margin:24px;background:#fff;box-shadow:0 0 12px rgba(0,0,0,0.15);transition:box-shadow 0.1s ease-in;cursor:pointer}.app .books .book img{width:100%;height:160px;-o-object-fit:fill;object-fit:fill}.app .books .book:hover{box-shadow:0 0 12px rgba(0,0,0,0.35)}.app .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, rgba(252,232,207,0.6) 200px)}.app .drag-mask::after{font-size:46px;text-indent:360px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}.app .context-menu{display:flex;flex-direction:column;width:100px;padding:5px 0;background:#fff}.app .context-menu .item{height:30px;line-height:30px;padding:0 15px;cursor:pointer}.app .context-menu .item:hover{background:#f2f5fc}.app .context-menu .item.diabled{color:var(--color-plain-2);background:#fff;cursor:default}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}

View File

@ -6,7 +6,6 @@
*/ */
html { html {
font-size: 12.8px;
width: 100%; width: 100%;
height: 100vh; height: 100vh;
} }
@ -14,7 +13,6 @@ html {
body { body {
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column;
width: 100%; width: 100%;
height: 100%; height: 100%;
line-height: 1.25; line-height: 1.25;
@ -23,17 +21,10 @@ body {
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
} }
.app-drag {
-webkit-app-region: drag;
user-select: none;
}
.app-nodrag {
-webkit-app-region: no-drag;
}
.app { .app {
position: relative; position: relative;
display: flex; display: flex;
width: 100%;
height: 100%; height: 100%;
.category { .category {
@ -90,43 +81,34 @@ body {
} }
} }
.detail { .books-scroll {
position: relative;
flex: 1; flex: 1;
height: 100%; height: 100%;
border-left: 1px solid var(--color-plain-2); border-left: 1px solid var(--color-plain-2);
background: rgba(255, 255, 255, 0.5); }
.title { .books {
display: flex; display: flex;
justify-content: space-between; flex-wrap: wrap;
align-items: center;
width: 100%;
height: 35px;
padding: 0 16px;
font-size: 16px;
font-weight: bold;
span { .book {
display: inline-flex; display: flex;
} flex-direction: column;
wc-button { width: 128px;
margin: 0 6px; margin: 24px;
}
}
.card {
width: 96%;
padding: 12px 12px 16px;
margin: 12px 2% 24px;
border: 0;
background: #fff; background: #fff;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.075); box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
transition: box-shadow 0.1s ease-in;
cursor: pointer;
legend { img {
-webkit-touch-callout: none; width: 100%;
user-select: none; height: 160px;
color: #64b5f6; object-fit: fill;
}
&:hover {
box-shadow: 0 0 12px rgba(0, 0, 0, 0.35);
} }
} }
} }
@ -144,12 +126,12 @@ body {
to right, to right,
transparent, transparent,
transparent 200px, transparent 200px,
#fff3e3 200px rgba(252, 232, 207, 0.6) 200px
); );
&::after { &::after {
font-size: 46px; font-size: 46px;
text-indent: 300px; text-indent: 360px;
content: 'Drop epub file here...'; content: 'Drop epub file here...';
color: var(--color-grey-1); color: var(--color-grey-1);
} }
@ -182,6 +164,31 @@ body {
} }
} }
} }
.context-menu {
display: flex;
flex-direction: column;
width: 100px;
padding: 5px 0;
background: #fff;
.item {
height: 30px;
line-height: 30px;
padding: 0 15px;
cursor: pointer;
&:hover {
background: #f2f5fc;
}
&.diabled {
color: var(--color-plain-2);
background: #fff;
cursor: default;
}
}
}
} }
@keyframes loading { @keyframes loading {

View File

@ -1 +0,0 @@
html{font-size:12.8px;width:100%;height:100vh}body{display:flex;flex-direction:column;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}.app{position:relative;display:flex;flex-direction:column;height:100%;padding:6px 0}.app .list{flex:1}.app .list .item{display:flex;align-items:center;height:54px;padding:10px 12px;line-height:15px;border-bottom:1px solid rgba(155,155,155,0.3)}.app .list .item:last-child{border-bottom:0}.app .list .item .info{overflow:hidden;flex:1}.app .list .item .info h3{font-size:14px}.app .list .item .info cite{color:var(--color-grey-2)}.app .list .item .last-days{display:flex;width:64px;height:30px;margin:0 6px}.app .list .item .today{width:52px;font-size:12px;text-align:right}.app .list .item .today span{display:block;padding:0 4px}.app .list .item .today .percent{border-radius:2px;color:#fff}.app .list .item .today .percent.red{background:var(--color-red-1)}.app .list .item .today .percent.green{background:var(--color-green-3)}

View File

@ -1,97 +0,0 @@
@charset "UTF-8";
/**
*
* @authors yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:07
*/
html {
font-size: 12.8px;
width: 100%;
height: 100vh;
}
body {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
line-height: 1.25;
font-size: 14px;
color: var(--color-dark-1);
background: rgba(255, 255, 255, 0.3);
}
.app-drag {
-webkit-app-region: drag;
user-select: none;
}
.app-nodrag {
-webkit-app-region: no-drag;
}
.app {
position: relative;
display: flex;
flex-direction: column;
height: 100%;
padding: 6px 0;
.list {
flex: 1;
.item {
display: flex;
align-items: center;
height: 54px;
padding: 10px 12px;
line-height: 15px;
border-bottom: 1px solid rgba(155, 155, 155, 0.3);
&:last-child {
border-bottom: 0;
}
.info {
overflow: hidden;
flex: 1;
h3 {
font-size: 14px;
}
cite {
color: var(--color-grey-2);
}
}
.last-days {
display: flex;
width: 64px;
height: 30px;
margin: 0 6px;
}
.today {
width: 52px;
font-size: 12px;
text-align: right;
span {
display: block;
padding: 0 4px;
}
.percent {
border-radius: 2px;
color: #fff;
&.red {
background: var(--color-red-1);
}
&.green {
background: var(--color-green-3);
}
}
}
}
}
}

1
src/css/view.css Normal file
View File

@ -0,0 +1 @@
html{width:100%;height:100vh}body{display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;width:100%;height:100%}.app .toc{width:260px;height:100%}.app .toc item{display:flex;align-items:center;height:36px;padding:0 12px;border-bottom:1px solid var(--color-plain-1);cursor:pointer}.app .toc item.lev-0{font-weight:bold}.app .toc item.lev-1{padding-left:24px;font-weight:bold}.app .toc item.lev-2{padding-left:36px}.app .toc item.lev-3{padding-left:48px}.app .toc item:hover{color:var(--color-blue-1)}.app .toc item.active{color:#fff;background:var(--color-blue-1)}.app .toc item:last-child{border-bottom:0}.app .chapter-box{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .chapter{display:flex;justify-content:center;padding:8px 24px}.app .chapter .detail{width:768px;line-height:1.5;font-size:14px}.app .chapter .detail .cover{display:block;width:100%;height:calc(100vh - 16px);-o-object-fit:contain;object-fit:contain}.app .chapter .detail a{text-decoration:underline;color:var(--color-teal-2)}.app .chapter .detail a:hover{color:var(--color-teal-1);text-decoration:none}.app .chapter .detail em,.app .chapter .detail del{color:var(--color-grey-2)}.app .chapter .detail strong,.app .chapter .detail strong em,.app .chapter .detail strong{color:var(--color-dark-3)}.app .chapter .detail a strong,.app .chapter .detail a em{color:inherit}.app .chapter .detail em,.app .chapter .detail strong,.app .chapter .detail del{padding:0 2px}.app .chapter .detail img{max-width:100%}.app .chapter .detail blockquote{margin:10px 0;padding:5px 10px;line-height:1.5;border-left:5px solid var(--color-teal-1);background:#f2faf7;color:var(--color-grey-2)}.app .chapter .detail blockquote p{margin:0}.app .chapter .detail code{display:inline;margin:0 2px;padding:0 2px;color:var(--color-orange-3);background:var(--color-plain-1);border-radius:2px;font-family:Menlo, Monaco, Consolas, 'Courier New', monospace}.app .chapter .detail>p{margin:12px 0}.app .chapter .detail ol{margin-left:1em;list-style:decimal outside none}.app .chapter .detail ul{margin-left:1em;list-style:disc outside none}.app .chapter .detail li{margin:0.5em 0}.app .chapter .detail li ol{margin-left:1em}.app .chapter .detail li ul{margin-left:1em;list-style-type:circle}.app .chapter .detail li ol ul,.app .chapter .detail li ul ul{list-style-type:square}.app .chapter .detail h1,.app .chapter .detail h2,.app .chapter .detail h3,.app .chapter .detail h4,.app .chapter .detail h5,.app .chapter .detail h6{margin:15px 0;line-height:2;font-weight:bold;font-size:16px}.app .chapter .detail h1 code,.app .chapter .detail h2 code,.app .chapter .detail h3 code,.app .chapter .detail h4 code,.app .chapter .detail h5 code,.app .chapter .detail h6 code{background:none}.app .chapter .detail h1 a,.app .chapter .detail h2 a,.app .chapter .detail h3 a,.app .chapter .detail h4 a,.app .chapter .detail h5 a,.app .chapter .detail h6 a{text-decoration:none;color:#333}.app .chapter .detail h3 a::before,.app .chapter .detail h4 a::before,.app .chapter .detail h5 a::before,.app .chapter .detail h6 a::before{content:'∮ ';color:var(--color-teal-1);font-weight:normal}.app .chapter .detail h1{margin:0 0 30px;font-size:24px;text-align:center}.app .chapter .detail h2{margin:20px 0;font-size:22px;border-bottom:1px solid var(--color-plain-2)}.app .chapter .detail h3{margin:20px 0 15px;font-size:20px}.app .chapter .detail h4{font-size:18px}.app .chapter .detail table{width:100%;border-spacing:0;border-collapse:collapse}.app .chapter .detail table tr{background-color:#fff}.app .chapter .detail table thead tr{background:var(--color-plain-1)}.app .chapter .detail table th,.app .chapter .detail table td{padding:6px 13px;border:1px solid var(--color-plain-2)}.app .chapter .detail table th{font-weight:bold}.app .chapter .detail table tr:nth-child(2n){background-color:#fcfdff}

250
src/css/view.scss Normal file
View File

@ -0,0 +1,250 @@
@charset "UTF-8";
/**
*
* @authors yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:07
*/
html {
width: 100%;
height: 100vh;
}
body {
display: flex;
width: 100%;
height: 100%;
line-height: 1.25;
font-size: 14px;
color: var(--color-dark-1);
background: rgba(255, 255, 255, 0.3);
}
.app {
position: relative;
display: flex;
width: 100%;
height: 100%;
.toc {
width: 260px;
height: 100%;
item {
display: flex;
align-items: center;
height: 36px;
padding: 0 12px;
border-bottom: 1px solid var(--color-plain-1);
cursor: pointer;
&.lev-0 {
font-weight: bold;
}
&.lev-1 {
padding-left: 24px;
font-weight: bold;
}
&.lev-2 {
padding-left: 36px;
}
&.lev-3 {
padding-left: 48px;
}
&:hover {
color: var(--color-blue-1);
}
&.active {
color: #fff;
background: var(--color-blue-1);
}
&:last-child {
border-bottom: 0;
}
}
}
.chapter-box {
flex: 1;
height: 100%;
border-left: 1px solid var(--color-plain-2);
}
.chapter {
display: flex;
justify-content: center;
padding: 8px 24px;
.detail {
width: 768px;
line-height: 1.5;
font-size: 14px;
.cover {
display: block;
width: 100%;
height: calc(100vh - 16px);
object-fit: contain;
}
a {
text-decoration: underline;
color: var(--color-teal-2);
}
a:hover {
color: var(--color-teal-1);
text-decoration: none;
}
em,
del {
color: var(--color-grey-2);
}
strong,
strong em,
strong {
color: var(--color-dark-3);
}
a {
strong,
em {
color: inherit;
}
}
em,
strong,
del {
padding: 0 2px;
}
img {
max-width: 100%;
}
blockquote {
margin: 10px 0;
padding: 5px 10px;
line-height: 1.5;
border-left: 5px solid var(--color-teal-1);
background: #f2faf7;
color: var(--color-grey-2);
p {
margin: 0;
}
}
code {
display: inline;
margin: 0 2px;
padding: 0 2px;
color: var(--color-orange-3);
background: var(--color-plain-1);
border-radius: 2px;
font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;
}
> p {
margin: 12px 0;
// text-indent: 2em;
}
ol {
margin-left: 1em;
list-style: decimal outside none;
}
ul {
margin-left: 1em;
list-style: disc outside none;
}
li {
margin: 0.5em 0;
}
li ol {
margin-left: 1em;
}
li ul {
margin-left: 1em;
list-style-type: circle;
}
li ol ul,
li ul ul {
list-style-type: square;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 15px 0;
line-height: 2;
font-weight: bold;
font-size: 16px;
code {
background: none;
}
a {
text-decoration: none;
color: #333;
}
}
h3,
h4,
h5,
h6 {
a {
&::before {
content: '';
color: var(--color-teal-1);
font-weight: normal;
}
}
}
h1 {
margin: 0 0 30px;
font-size: 24px;
text-align: center;
}
h2 {
margin: 20px 0;
font-size: 22px;
border-bottom: 1px solid var(--color-plain-2);
}
h3 {
margin: 20px 0 15px;
font-size: 20px;
}
h4 {
font-size: 18px;
}
table {
width: 100%;
border-spacing: 0;
border-collapse: collapse;
tr {
background-color: #fff;
}
thead tr {
background: var(--color-plain-1);
}
th,
td {
padding: 6px 13px;
border: 1px solid var(--color-plain-2);
}
th {
font-weight: bold;
}
tr:nth-child(2n) {
background-color: #fcfdff;
}
}
}
}
}

View File

@ -16,6 +16,8 @@
<wc-scroll class="category"> <wc-scroll class="category">
<item <item
class="item" class="item"
@contextmenu="pickCtx1(it, $event)"
@click="view(it)"
:class="{active: curr === it.name}" :class="{active: curr === it.name}"
:for="it in cates"> :for="it in cates">
<strong :text="it.name"></strong> <strong :text="it.name"></strong>
@ -25,26 +27,49 @@
<div class="detail" :class="{blur: !curr.code}">
<book :for="it in books"> <wc-scroll class="books-scroll">
<img :src="'book://cache/' + it.title + '/' + it.cover"> <list class="books">
{{it.title}} <book
class="book"
:for="it in books"
@dblclick="read(it)"
@contextmenu="pickCtx2(it, $event)"
>
<img
:attr-alt="it.title"
:src="it.c ? it.c : 'book://cache/' + it.title + '/' + it.cover"
>
</book> </book>
</list>
</wc-scroll>
</div>
<div class="drag-mask" ref="mask" :visible="isDragIn"></div> <div class="drag-mask" ref="mask" :visible="isDragIn"></div>
<div class="book-loading" ref="books" :visible="loading"> <div class="book-loading" :visible="loading">
<div class="loading"> <div class="loading">
<span>共 {{load.num}} 本书</span> <span>共 {{load.num}} 本书</span>
<span>当前正在解析第 {{load.curr}} 本</span> <span>当前正在解析第 {{load.curr}} 本</span>
</div> </div>
</div> </div>
<wc-layer ref="ctx1" left="100px" top="0" radius="0">
<ul class="context-menu noselect">
<li class="item" @click="deleteCate">删除</li>
<li class="item" @click="renameCate">重命名</li>
<li class="item" @click="createCate">新建分类</li>
</ul>
</wc-layer>
<wc-layer ref="ctx2" left="100px" top="0" radius="0">
<ul class="context-menu noselect">
<li class="item" @click="deleteBook">删除</li>
<li class="item diabled">移动到</li>
</ul>
</wc-layer>
</div> </div>

View File

@ -7,14 +7,11 @@
*/ */
import '/lib/anot.js' import '/lib/anot.js'
import '/lib/form/button.js'
import '/lib/form/switch.js'
import '/lib/scroll/index.js' import '/lib/scroll/index.js'
import '/lib/chart/rank.js'
import '/lib/chart/line.js'
import layer from '/lib/layer/index.js' import '/lib/layer/index.js'
import Utils from '/lib/utils.js' import Utils from '/lib/utils.js'
import { md5 } from '/lib/md5.js'
import app from '/lib/socket.js' import app from '/lib/socket.js'
@ -30,21 +27,30 @@ Anot({
state: { state: {
input: '', input: '',
curr: '默认分类', curr: '默认分类',
cates: [{ name: '默认分类', num: 12 }], cates: [],
books: [], books: [],
loading: false, loading: false,
isDragIn: false, isDragIn: false,
load: { load: {
num: 0, num: 0,
curr: 0 curr: 0
} },
$db: {},
$ctx1: null,
$ctx2: null
}, },
watch: {},
mounted() { mounted() {
Utils.outside(this.$refs.ctx1, ev => {
this.$refs.ctx1.close()
})
Utils.outside(this.$refs.ctx2, ev => {
this.$refs.ctx2.close()
})
/* --------------------- */
$doc.bind('dragover', ev => { $doc.bind('dragover', ev => {
ev.stopPropagation()
ev.preventDefault() ev.preventDefault()
this.isDragIn = true this.isDragIn = true
@ -55,10 +61,9 @@ Anot({
this.isDragIn = false this.isDragIn = false
}) })
$doc.bind('drop', ev => { $doc.bind('drop', async ev => {
ev.stopPropagation()
ev.preventDefault() ev.preventDefault()
// clearTimeout(this.timer)
this.isDragIn = false this.isDragIn = false
let files = Array.from(ev.dataTransfer.files) let files = Array.from(ev.dataTransfer.files)
@ -73,20 +78,255 @@ Anot({
this.load.curr = 0 this.load.curr = 0
this.loading = true this.loading = true
console.time(1)
while (this.load.curr < this.load.num) { while (this.load.curr < this.load.num) {
this.load.curr++ this.load.curr++
let book = files.pop() let book = files.pop()
let res = app.dispatch('parse-book', { book, cate: this.curr }) let res = app.dispatch('parse-book', { book, cate: this.curr })
console.log(res)
await sleep(500)
if (res) { if (res) {
this.books.push(res) this.books.push(res)
} }
} }
console.timeEnd(1)
for (let it of this.cates) {
if (it.name === this.curr) {
it.num = this.books.length
break
}
}
this.loading = false this.loading = false
}) })
},
methods: {} /* --------------------- */
let db = app.dispatch('get-books')
let cates = [],
books
if (Object.keys(db).length < 1) {
db = { 默认分类: [] }
}
for (let k in db) {
cates.push({ name: k, num: db[k].length })
// 默认选中第一个
if (!books) {
this.curr = k
books = db[k]
}
}
this.$db = db
this.cates = cates
this.books = books || []
app.on('draw-cover', title => {
this.drawCover(title)
})
},
methods: {
view(item) {
this.books = this.$db[item.name]
},
read(item) {
var params = { title: item.title }
var readCache = Anot.ls(md5(item.title))
if (readCache) {
params.chapter = readCache
}
app.dispatch(
'read',
Buffer.from(JSON.stringify(params)).toString('base64')
)
},
pickCtx1(item, ev) {
this.$ctx1 = item
ev.stopPropagation()
let { pageX, pageY } = ev
if (pageY + 70 > 600) {
pageY -= 70
}
this.$refs.ctx1.close()
Anot.nextTick(_ => {
this.$refs.ctx1.moveTo({ left: pageX + 'px', top: pageY + 'px' })
this.$refs.ctx1.show()
})
},
pickCtx2(item, ev) {
this.$ctx2 = item
ev.stopPropagation()
let { pageX, pageY } = ev
if (pageY + 70 > 600) {
pageY -= 70
}
this.$refs.ctx2.close()
Anot.nextTick(_ => {
this.$refs.ctx2.moveTo({ left: pageX + 'px', top: pageY + 'px' })
this.$refs.ctx2.show()
})
},
saveDB() {
app.dispatch('save-books', Anot.deepCopy(this.$db))
},
drawCover(name) {
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
var tmp = name.split('').map(s => (/[\w\s\(\)]/.test(s) ? 1 : 2))
canvas.width = 128
canvas.height = 160
ctx.fillStyle =
'#' +
Buffer.from(name)
.toString('hex')
.slice(-6)
ctx.fillRect(0, 0, 128, 160)
ctx.fillStyle = '#fff'
ctx.font = '14px menlo,Hiragino Sans GB'
ctx.textAlign = 'center'
let row = 0
let last = 0
tmp.reduce((sum, c, i) => {
sum += c
if (sum >= 14 && row === 0) {
ctx.fillText(name.slice(0, i + 1), 64, 60, 100)
last = i
row = 1
} else if (sum >= 28 && row === 1) {
ctx.fillText(name.slice(last, i + 1), 64, 60 + row * 26, 100)
row = 2
last = i
} else if (sum >= 42 && row === 2) {
ctx.fillText(name.slice(last, i + 1), 64, 60 + row * 26, 100)
}
return sum
}, 0)
if (last === 0) {
ctx.fillText(name, 64, 76, 100)
} else {
if (last < tmp.length) {
ctx.fillText(name.slice(last + 1), 64, 60 + row * 26, 100)
}
}
let base64 = canvas.toDataURL('image/webp', 1).split(',')[1]
app.dispatch('save-cover', { base64, name })
},
deleteCate() {
//
this.$refs.ctx1.close()
if (this.$ctx1) {
let { name, num } = this.$ctx1
if (num > 0) {
return layer.toast(`${name} 下有书籍, 不可删除!`, 'error')
}
delete this.$db[name]
this.cates.remove(this.$ctx1)
this.saveDB()
}
},
createCate() {
this.$ctx1 = null
this.$refs.ctx1.close()
layer
.prompt('请输入分类名', (val, done) => {
if (val.trim()) {
if (this.$db[val.trim()]) {
return layer.toast('分类已存在, 请换个名字', 'error')
}
done()
}
})
.then(v => {
v = v.trim()
this.$db[v] = []
this.cates.push({ name: v, num: 0 })
this.saveDB()
})
.catch(Anot.noop)
},
renameCate() {
//
this.$refs.ctx1.close()
if (this.$ctx1) {
let { name } = this.$ctx1
layer
.prompt(`请输入新的分类名(${name})`, (val, done) => {
val = val.trim()
if (val) {
if (this.$db[val] || val === name) {
return layer.toast('分类已存在, 请换个名字', 'error')
}
done()
}
})
.then(v => {
v = v.trim()
this.$db[v] = this.$db[name]
delete this.$db[name]
this.$ctx1.name = v
this.$ctx1 = null
this.saveDB()
})
.catch(Anot.noop)
}
},
deleteBook() {
this.$refs.ctx2.close()
if (this.$ctx2) {
let { title } = this.$ctx2
layer
.confirm(`是否要删除[${title}]? 该操作不可逆!`)
.then(r => {
this.books.remove(this.$ctx2)
this.$db[this.curr] = this.books
for (let it of this.cates) {
if (it.name === this.curr) {
it.num = this.books.length
break
}
}
this.saveDB()
app.dispatch('delete-book', title)
})
.catch(Anot.noop)
}
}
// moveBook() {
// this.$refs.ctx2.close()
// if (this.$ctx2) {
// let { title } = this.$ctx2
// }
// }
}
}) })

View File

@ -1,94 +0,0 @@
/**
*
* @author yutent<yutent.io@gmail.com>
* @date 2020/12/10 19:53:05
*/
import '/lib/anot.js'
import '/lib/scroll/index.js'
import layer from '/lib/layer/index.js'
import app from '/lib/socket.js'
function getJsonp(str) {
if (~str.indexOf('jsonpgz')) {
return new Function(`function jsonpgz(d){return d}; return ${str}`)()
}
return false
}
Anot({
$id: 'app',
state: {
list: []
},
mounted() {
this.reloadGays()
app.on('float-visible', data => {
var time = +Anot.ss('last_update') || 0
var now = Date.now()
// 有触发小窗口显示时, 更新通知提醒
if (Anot.ls('notify') === '1') {
app.dispatch('notify')
}
this.reloadGays()
setTimeout(() => {
// 如果离上次更新超过15分钟, 则自动更新
if (now - time > 15 * 60 * 1000) {
this.updateGays()
Anot.ss('last_update', now)
}
}, 500)
})
},
methods: {
reloadGays() {
var gays = Anot.ls('gays') || '{}'
var list = []
gays = JSON.parse(gays)
for (let code in gays) {
let { name, cm, cp, t } = gays[code]
list.push({ code, name, cm, cp, t })
}
list.sort((a, b) => b.cp - a.cp)
this.list = list
},
getGayStat(id) {
var res = app.dispatch(
'fetch',
`https://fundgz.1234567.com.cn/js/${id}.js`
)
return getJsonp(res)
},
updateGay(item) {
var info = this.getGayStat(item.code)
item.cm = +info.gsz
item.cp = +info.gszzl
},
updateGays() {
for (let it of this.list) {
this.updateGay(it)
}
this.list.sort((a, b) => b.cp - a.cp)
this.saveCache()
app.dispatch('data-reload')
},
saveCache() {
var dict = {}
for (let it of this.list) {
var { code, name, cm, cp, t } = it
dict[code] = { name, cm, cp, t }
}
Anot.ls('gays', dict)
}
}
})

116
src/js/view.js Normal file
View File

@ -0,0 +1,116 @@
/**
*
* @author yutent<yutent.io@gmail.com>
* @date 2020/12/10 19:53:05
*/
import '/lib/anot.js'
import '/lib/scroll/index.js'
import '/lib/code/index.js'
import { md5 } from '/lib/md5.js'
import fetch from '/lib/fetch/index.js'
import app from '/lib/socket.js'
const { dirname, join } = require('path')
Anot({
$id: 'app',
state: {
toc: [],
book: '', // 当前阅读的书名
curr: '', // 当前选中的章节名
file: '', // 章节所属的文件名
chapter: '' // 章节渲染html文本
},
mounted() {
var search = location.search
if (search) {
search = JSON.parse(Buffer.from(search.slice(1), 'base64'))
document.title = this.book = search.title
this.curr = search.chapter || ''
this.getToc()
}
},
methods: {
getToc() {
fetch(`book://cache/${this.book}/toc.json`)
.then(r => r.json())
.then(list => {
let chapter, idx
for (let i = -1, it; (it = list[++i]); ) {
delete it.id
delete it.order
it.href = it.href.replace('.xhtml', '.html')
if (it.title === this.curr) {
chapter = it
idx = i
}
}
if (!chapter) {
chapter = list[0]
idx = 0
}
this.toc = list
this.viewChapter(chapter)
setTimeout(() => {
this.$refs.toc.scrollTop = 36 * (idx - 10)
}, 100)
})
},
viewChapter(item) {
let pathes = item.href.split('#')
let file = pathes.shift()
let hash = pathes.shift()
this.curr = item.title
Anot.ls(md5(this.book), item.title)
if (this.file === file) {
if (hash) {
location.hash = hash
} else {
location.hash = ''
this.$refs.chapter.scrollTop = 0
}
} else {
this.file = file
fetch(`book://cache/${this.book}/${file}`)
.then(r => r.text())
.then(txt => {
this.chapter = txt
.replace(/<img[^>]*?src="(.*?)"[^>]*?\/?>/g, (m, s1) => {
s1 = join(dirname(file), s1)
return `<img src="book://cache/${this.book}/${s1}">`
})
.replace(/<image[^>]*?xlink:href="(.*?)"[^>]*?\/?>/g, (m, s1) => {
s1 = join(dirname(file), s1)
return `<img class="cover" src="book://cache/${
this.book
}/${s1}">`
})
.replace(/<\/?svg>/g, '')
setTimeout(() => {
if (hash) {
location.hash = hash
} else {
location.hash = ''
this.$refs.chapter.scrollTop = 0
}
}, 100)
})
}
}
}
})

File diff suppressed because one or more lines are too long

View File

@ -1,253 +0,0 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52
* @version v1.0.0
*
*/
import $ from '../utils.js'
import '../form/button.js'
const DARK = '#62778d'
const BLUE = '#64b5f6'
const PLAIN = '#f2f5fc'
export default class Line extends HTMLElement {
static get observedAttributes() {
return ['list']
}
props = {
list: []
}
state = {
key: 1,
list: []
}
constructor() {
super()
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
display: flex;
width: 680px; }
.container {
position: relative;
padding: 24px 0 0; }
canvas {
width: 680px;
height: 230px; }
section {
position: absolute;
right: 0;
top: 0; }
</style>
<div class="container">
<canvas></canvas>
<section>
<wc-button color="blue" data-key="1" size="mini">1</wc-button>
<wc-button data-key="3" size="mini">3</wc-button>
<wc-button data-key="6" size="mini">半年</wc-button>
<wc-button data-key="12" size="mini">1</wc-button>
<wc-button data-key="36" size="mini">3</wc-button>
<wc-button data-key="999" size="mini">所有</wc-button>
</section>
</div>
`
var elem = this.root.children[1]
this.__SCENE__ = elem.firstElementChild
this.__FILTER__ = elem.lastElementChild
this.__CTX__ = this.__SCENE__.getContext('2d')
this.__SCENE__.width = 680
this.__SCENE__.height = 230
}
_getTime(n) {
var now = new Date()
var time = { getTime: _ => 0 }
var Y = now.getFullYear()
var m = now.getMonth()
var d = now.getDate()
switch (n) {
case 1:
time = new Date(Y, m - 1, d, 0, 0, 0)
break
case 3:
time = new Date(Y, m - 3, d, 0, 0, 0)
break
case 6:
time = new Date(Y, m - 6, d, 0, 0, 0)
break
case 12:
time = new Date(Y - 1, m, d, 0, 0, 0)
break
case 36:
time = new Date(Y - 3, m, d, 0, 0, 0)
break
}
return time.getTime()
}
_filter(n) {
if (n < 999) {
var time = this._getTime(n)
this.state.list = this.props.list.filter(it => it.x >= time)
} else {
this.state.list = this.props.list.concat()
}
}
draw() {
var { list, key } = this.state
var ctx = this.__CTX__
var x = 36
var max = 0
var min = Number.MAX_SAFE_INTEGER
var step = 0 // 纵坐标间隔
var dis = +(640 / list.length).toFixed(2) || 1 // 横坐标间隔
var point
var p1, p2, p3, p4
var format = key > 12 ? 'Y/m' : 'm/d'
for (let it of list) {
if (max < it.y) {
max = it.y
}
if (min > it.y) {
min = it.y
}
}
min = ~~(min / 100)
max = Math.ceil(max / 100)
step = ~~((max - min) / 3)
p1 = Math.floor(list.length / 4)
p2 = Math.floor(list.length / 2)
p3 = Math.floor((list.length * 3) / 4)
p4 = list.length - 1
ctx.clearRect(0, 0, 680, 230)
// 纵坐标数值
ctx.font = '12px Arial'
ctx.textAlign = 'right'
ctx.fillStyle = DARK
ctx.fillText(min / 100, 32, 205)
ctx.fillText((min + step) / 100, 32, 155)
ctx.fillText((min + step + step) / 100, 32, 105)
ctx.fillText((min + step + step + step) / 100, 32, 55)
ctx.font = '10px Arial'
ctx.textAlign = 'left'
ctx.fillText(new Date(list[0].x).format(format), x - 12, 225)
ctx.fillText(new Date(list[p1].x).format(format), x + dis * p1 - 12, 225)
ctx.fillText(new Date(list[p2].x).format(format), x + dis * p2 - 12, 225)
ctx.fillText(new Date(list[p3].x).format(format), x + dis * p3 - 12, 225)
ctx.fillText(
new Date(list[p4].x).format(format),
x + dis * p4 - 12 - (key > 12 ? 24 : 4),
225
)
// x轴参考线
ctx.fillStyle = PLAIN
ctx.fillRect(x, 50, 648, 1)
ctx.fillRect(x, 100, 648, 1)
ctx.fillRect(x, 150, 648, 1)
ctx.fillRect(x, 200, 648, 1)
// y轴参考 线
ctx.fillRect(x, 0, 1, 210)
ctx.fillRect(x + dis * p1, 0, 1, 210)
ctx.fillRect(x + dis * p2, 0, 1, 210)
ctx.fillRect(x + dis * p3, 0, 1, 210)
ctx.fillRect(x + dis * p4, 0, 1, 210)
point = list.shift()
// 曲线
ctx.beginPath()
ctx.strokeStyle = BLUE
ctx.lineWidth = 1
ctx.moveTo(x, 200 - (((point.y / 100 - min) / step) * 50).toFixed(0))
while (list.length) {
let y
point = list.shift()
y = 200 - (((point.y / 100 - min) / step) * 50).toFixed(0)
x += dis
ctx.lineTo(x, y)
}
ctx.stroke()
}
connectedCallback() {
$.bind(this.__FILTER__, 'click', ev => {
var el = ev.target
if (this.props.list.length < 1) {
return
}
if (el.tagName === 'WC-BUTTON') {
var k = +el.dataset.key
$.each(this.__FILTER__.children, function(it) {
it.removeAttribute('color')
})
el.setAttribute('color', 'blue')
this.state.key = k
this._filter(k)
this.draw()
}
})
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {
return
}
switch (name) {
case 'list':
try {
var list = JSON.parse(val)
list.forEach(it => (it.x = it.x * 1000))
this.props.list = list
this._filter(this.state.key)
this.removeAttribute('list')
this.draw()
} catch (e) {}
break
}
}
}
if (!customElements.get('wc-line')) {
customElements.define('wc-line', Line)
}

View File

@ -1,141 +0,0 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52
* @version v1.0.0
*
*/
const RED = '#ff5061'
const GREEN = '#4caf50'
const BLUE = '#64b5f6'
const GREY = '#bdbdbd'
const PLAIN = '#f2f5fc'
const DARK = '#62778d'
export default class Rank extends HTMLElement {
static get observedAttributes() {
return ['stat']
}
props = {
stat: {}
}
constructor() {
super()
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
display: flex; }
canvas {
width: 680px;
height: 100px; }
</style>
<canvas></canvas>
`
this.__SCENE__ = this.root.children[1]
this.__CTX__ = this.__SCENE__.getContext('2d')
this.__SCENE__.width = 680
this.__SCENE__.height = 100
}
draw() {
var { rank, e1, e3, e6, e12, cm, cp } = this.props.stat
var ctx = this.__CTX__
var x = 32
while (rank.length < 60) {
rank.unshift(0)
}
ctx.clearRect(0, 0, 680, 101)
ctx.font = '10px Arial'
ctx.textAlign = 'right'
ctx.fillStyle = RED
ctx.fillText('10%', 28, 10)
ctx.fillText('5%', 28, 30)
ctx.fillStyle = GREEN
ctx.fillText('-5%', 28, 80)
ctx.fillText('-10%', 28, 100)
ctx.font = '10px menlo,Hiragino Sans GB'
ctx.textAlign = 'left'
ctx.fillStyle = DARK
ctx.fillText('60天红绿榜', 160, 10)
ctx.font = '12px menlo,Hiragino Sans GB'
ctx.fillText(`最近1个月收益: ${e1}%`, 360, 25)
ctx.fillText(`最近3个月收益: ${e3}%`, 360, 45)
ctx.fillText(`最近半年收益: ${e6}%`, 528, 25)
ctx.fillText(`最近一年收益: ${e12}%`, 528, 45)
ctx.fillStyle = cp > 0 ? RED : cp === 0 ? GREY : GREEN
ctx.fillRect(360, 65, 140, 20)
ctx.fillRect(526, 65, 140, 20)
ctx.fillStyle = '#fff'
ctx.font = 'bold 14px menlo,Hiragino Sans GB'
ctx.fillText(`实时净值: ¥${cm}`, 364, 80)
ctx.fillText(`实时涨跌: ${cp}%`, 532, 80)
ctx.fillStyle = PLAIN
ctx.fillRect(28, 25, 320, 1)
ctx.fillRect(28, 75, 320, 1)
ctx.fillStyle = GREY
ctx.fillRect(28, 0, 1, 140)
ctx.fillRect(0, 50, 348, 1)
while (rank.length) {
var n = rank.shift()
var y = Math.ceil(50 - (n / 10) * 50)
ctx.fillStyle = n > 0 ? RED : GREEN
if (y > 50) {
ctx.fillRect(x, 50, 3, y - 50)
} else {
ctx.fillRect(x, y, 3, 50 - y)
}
x += 5
}
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {
return
}
switch (name) {
case 'stat':
try {
var stat = JSON.parse(val)
this.props.stat = stat
this.removeAttribute('stat')
this.draw()
} catch (e) {}
break
}
}
}
if (!customElements.get('wc-rank')) {
customElements.define('wc-rank', Rank)
}

1
src/lib/code/colorful.js Normal file
View File

@ -0,0 +1 @@
const DOCTYPE_EXP=/<\!DOCTYPE html>/,TAG_START_EXP=/<([\w\-]+)([\w\W]*?)>/g,TAG_END_EXP=/<\/([\w\-]+)>/g,TAG_ATTR_EXP=/[@a-zA-Z\-.]+=(["'])[^"]+\1|[@a-zA-Z\-.]+=[a-zA-Z0-9]+|[@a-zA-Z\-.]+/g,TAG_CM_EXP=/<!--([\w\W]*?)-->/g;export function colorHtml(t){return(t=t.replace(DOCTYPE_EXP,"[tag]&lt;!DOCTYPE [attr]html[/attr]&gt;[/tag]").replace(TAG_START_EXP,(t,a,r)=>(r&&(r=r.replace(TAG_ATTR_EXP,(function(t){if(~t.indexOf("=")){return`[attr]${(t=t.split("=")).shift()}[/attr]=[str]${t.join("=")}[/str]`}return`[attr]${t}[/attr]`}))),`[tag]&lt;${a+r}&gt;[/tag]`)).replace(TAG_END_EXP,(t,a)=>`[tag]&lt;/${a}&gt;[/tag]`).replace(TAG_CM_EXP,'<i class="gr">&lt;!--$1--&gt;</i>')).replace(/\[(\/?)tag\]/g,(t,a)=>a?"</i>":'<i class="r">').replace(/\[(\/?)attr\]/g,(t,a)=>a?"</i>":'<i class="b">').replace(/\[(\/?)str\]/g,(t,a)=>a?"</i>":'<i class="g">')}export function colorCss(t){return t=t.replace(/:(hover|after|active|last\-child|first\-child)/g,'<i class="o">:$1</i>').replace(/([\.#])([\w\-]+)/g,'<i class="gr">$1</i><i class="o">$2</i>').replace(/([a-zA-Z\-]+):\s?([^;\n]+);?/g,'<b class="gr">$1: </b><i class="b">$2</i><i class="gr">;</i>').replace(/([,\{\}])/g,'<i class="gr">$1</i>').replace(/&/g,'<i class="r">&</i>')}

13
src/lib/code/index.js Normal file
View File

@ -0,0 +1,13 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2021-02-05 16:32:07
* @version v1.0.3
*
*/
import"../scroll/index.js";import"../layer/index.js";import $ from"../utils.js";import{colorHtml,colorCss}from"./colorful.js";export default class Code extends HTMLElement{static get observedAttributes(){return["dark","lang"]}props={dark:"",lang:""};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:flex}.code-box{overflow:hidden;display:flex;flex-direction:column;position:relative;width:100%;max-height:610px;margin:10px 0;padding-bottom:8px;border-radius:6px;background:#f7f8fb;color:var(--color-dark-1);box-shadow:0 0 8px rgba(0,0,0,.15)}.code-box .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:32px;padding:0 12px;line-height:1;font-size:14px;user-select:none}.code-box .title i{display:inline-block;width:12px;height:12px;margin-right:6px;border-radius:50%;background:var(--color-red-1)}.code-box .title i:nth-child(2){background:var(--color-orange-1)}.code-box .title i:nth-child(3){background:var(--color-green-1)}.code-box .title .act{--size: 18px;margin:0 6px;color:var(--color-grey-2);cursor:pointer}.code-box .title .act:hover{color:var(--color-grey-3)}.code-box .title .act.run{display:none}.code-box .scoll{flex:1;padding:5px 0;line-height:20px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:14px;color:var(--color-dark-1);cursor:text;counter-reset:code}.code-box .scoll code{display:block;position:relative;min-height:20px;padding:0 8px 0 45px;white-space:pre-wrap;word-break:break-word}.code-box .scoll code::before{position:absolute;left:0;width:40px;height:100%;padding-right:5px;text-align:right;color:var(--color-grey-1);content:counter(code);counter-increment:code}.code-box .scoll code i{font-style:normal}.code-box .scoll code .r{color:var(--color-red-1)}.code-box .scoll code .b{color:var(--color-blue-1)}.code-box .scoll code .g{color:var(--color-green-1)}.code-box .scoll code .gr{color:var(--color-grey-2)}.code-box .scoll code .o{color:var(--color-orange-2)}:host([exec]) .title .run{display:inline-block}:host([dark]) .code-box{border-color:var(--color-dark-2);background:var(--color-dark-1);color:var(--color-plain-3)}:host([dark]) .code-box .code{color:var(--color-plain-2)}:host([dark]) .code-box .code p::before{color:var(--color-grey-3)}</style> <div class="code-box"> <header class="title"> <span><i></i><i></i><i></i></span> <span></span> <span> <wc-icon title="运行" class="act run" is="live"></wc-icon> <wc-icon title="复制" class="act cp" is="doc"></wc-icon> </span> </header> <wc-scroll axis="y" class="scoll"></wc-scroll> </div> ';var o=this.root.children[1],e=o.children[0];this.__CODE__=o.children[1],this.__LANG__=e.children[1],this.__RUN__=e.children[2].firstElementChild,this.__CP__=e.children[2].lastElementChild}get value(){return this.props.content}set value(o){switch(o=o.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">"),this.props.content=o,this.props.lang){case"html":o=colorHtml(o);break;case"css":case"scss":case"less":o=colorCss(o);break;default:o=o.replace(/</g,"&lt;").replace(/>/g,"&gt;")}o=o.split("\n").map(o=>`<code>${o}</code>`).join(""),this.__CODE__.innerHTML=o}connectedCallback(){var o=this.innerHTML||this.textContent;(o=o.trim().replace(/^[\r\n]|\s{2,}$/g,"")).startsWith("<xmp>")&&o.endsWith("</xmp>")&&(o=o.slice(5,-6).trim()),this.value=o,this.textContent="",this._cpFN=$.bind(this.__CP__,"click",o=>{try{navigator.clipboard.writeText(this.value),layer.toast("复制到粘贴板成功","success")}catch(o){layer.toast("复制到粘贴板失败","error")}}),this._runFN=$.bind(this.__RUN__,"click",o=>{this.dispatchEvent(new CustomEvent("run",{detail:this.value}))})}unmounted(){$.unbind(this.__CP__,"click",this._cpFN),$.unbind(this.__RUN__,"click",this._runFN)}attributeChangedCallback(o,e,r){if(e!==r)switch(o){case"lang":this.props.lang=r.toLowerCase(),this.__LANG__.textContent=this.props.lang;break;case"value":this.value=r,this.removeAttribute("value")}}}
if(!customElements.get('wc-code')){
customElements.define('wc-code', Code)
}

View File

@ -4,14 +4,9 @@
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2014-10-10 00:45:09 * @date 2014-10-10 00:45:09
* *
* douiCSS * CSS
* *
* , * ,
* do-st-*
* do-fn-*
* do-mod-modname
* UIdo-uiname, .do-uiname
* .do-layer .body { ... }
* *
* *
* 1 display float position overflow z-index / * 1 display float position overflow z-index /
@ -22,7 +17,6 @@
* *
*/ */
* {margin: 0;padding: 0;vertical-align: baseline;box-sizing: border-box;} * {margin: 0;padding: 0;vertical-align: baseline;box-sizing: border-box;}
::before, ::after {box-sizing: border-box;} ::before, ::after {box-sizing: border-box;}
/* HTML5 display-role reset for older browsers */ /* HTML5 display-role reset for older browsers */
@ -30,49 +24,59 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
img {border: 0;display: inline-block;} img {border: 0;display: inline-block;}
ol,ul {list-style: none;} ol,ul {list-style: none;}
blockquote, q {quotes: none;} blockquote, q {quotes: none;}
blockquote::before, blockquote::after, blockquote::before, blockquote::after, q::before, q::after {content: '';content: none;}
q::before, q::after {content: '';content: none;}
table {border-collapse: collapse;border-spacing: 0;} table {border-collapse: collapse;border-spacing: 0;}
a:focus,input,textarea,button:focus,input:focus,textarea:focus {outline: none;} a:focus,input,textarea,button:focus,input:focus,textarea:focus {outline: none;}
::-moz-focus-inner { ::-moz-focus-inner {border: none;outline: none;}
border:none;outline:none;
}
body {font-family:"Helvetica Neue", Arial,"WenQuanYi Micro Hei","PingFang SC","Hiragino Sans GB","Segoe UI", "Microsoft Yahei", sans-serif;-webkit-font-smoothing: antialiased;text-size-adjust: 100%;-webkit-tap-highlight-color: transparent;}
code,pre,samp {font-family:Menlo,Monaco,Consolas,"Courier New",monospace;}
[anot],[\:repeat],[\:if] {visibility:hidden;}
body {font-family: 'Helvetica Neue', Arial, 'WenQuanYi Micro Hei', 'PingFang SC', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft Yahei', sans-serif;-webkit-font-smoothing: antialiased;text-size-adjust: 100%;-webkit-tap-highlight-color: transparent;}
code, pre, samp {font-family: Menlo, Monaco, Consolas, 'Courier New', monospace;}
[anot],[\:repeat],[\:if] {visibility: hidden;}
.noselect {-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;user-select: none;} .noselect {-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;user-select: none;}
.noselect img, .noselect a {-webkit-user-drag: none;} .noselect img, .noselect a {-webkit-user-drag: none;}
.text-ell {overflow:hidden; white-space:nowrap; text-overflow:ellipsis } .text-ell {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}
.osx-thin {-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} .text-thin {-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
:root { :root {
--color-teal-1: #4db6ac; /* primary */
--color-teal-2: #26a69a; --color-teal-a: rgba(72, 201, 176, 0.5);
--color-teal-3: #009688; --color-teal-1: rgb(72, 201, 176);
--color-green-1: #81c784; --color-teal-2: rgb(26, 188, 156);
--color-green-2: #66bb6a; --color-teal-3: rgb(22, 160, 133);
--color-green-3: #4caf50; /* success */
--color-purple-1: #9575cd; --color-green-a: rgba(88, 214, 141, 0.5);
--color-purple-2: #9575cd; --color-green-1: rgb(88, 214, 141);
--color-purple-3: #673ab7; --color-green-2: rgb(46, 204, 113);
--color-blue-1: #64b5f6; --color-green-3: rgb(39, 173, 96);
--color-blue-2: #42a5f5; /* info */
--color-blue-3: #2196f3; --color-blue-a: rgba(100, 181, 246, 0.5);
--color-red-1: #ff5061; --color-blue-1: rgb(100, 181, 246);
--color-red-2: #eb3b48; --color-blue-2: rgb(66, 165, 245);
--color-red-3: #ce3742; --color-blue-3: rgb(33, 150, 243);
--color-orange-1: #ffb618; /* danger */
--color-orange-2: #f39c12; --color-red-a: rgba(255, 107, 129, 0.5);
--color-orange-3: #e67e22; --color-red-1: rgb(255, 107, 129);
--color-plain-1: #f2f5fc; --color-red-2: rgb(255, 71, 87);
--color-plain-2: #e8ebf4; --color-red-3: rgb(230, 52, 67);
--color-plain-3: #dae1e9; /* warning */
--color-grey-1: #bdbdbd; --color-orange-a: rgba(244, 211, 19, 0.5);
--color-grey-2: #9e9e9e; --color-orange-1: rgb(244, 211, 19);
--color-grey-3: #757575; --color-orange-2: rgb(241, 196, 15);
--color-dark-1: #62778d; --color-orange-3: rgb(205, 167, 13);
--color-dark-2: #526273; /* default1 */
--color-dark-3: #425064; --color-plain-a: rgba(150, 204, 248, 0.5);
--color-plain-1: rgb(242, 245, 252);
--color-plain-2: rgb(232, 235, 244);
--color-plain-3: rgb(218, 225, 233);
/* default2 */
--color-grey-a: rgba(206, 214, 224, 0.5);
--color-grey-1: rgb(206, 214, 224);
--color-grey-2: rgb(164, 176, 190);
--color-grey-3: rgb(134, 144, 155);
/* inverse */
--color-dark-a: rgba(87, 96, 111, 0.5);
--color-dark-1: rgb(87, 96, 111);
--color-dark-2: rgb(52, 73, 94);
--color-dark-3: rgb(44, 62, 80);
} }

View File

@ -1 +1 @@
"use strict";import $ from"../utils.js";const DEF_OPT={axis:"",limit:!1,overflow:!0};export default class Drag{constructor(t){this.$elem=t,this._init()}_init(){this.$elem.style.transform="";var{x:t,y:s}=this.$elem.getBoundingClientRect();this.pos={x:t,y:s,_x:0,_y:0}}by(t,s={}){return this.$drag=t,this.opt=Object.assign(Object.create(null),DEF_OPT,s),!1!==this.opt.limit&&(this.opt.overflow=!1),t.style.cursor="move",this._handleResize=$.bind(window,"resize",this._init.bind(this)),this._handleMousedown=$.bind(t,"mousedown",t=>{if(this.disabled)return;var s=this.$elem.getBoundingClientRect();s.x-this.pos._x!==this.pos.x&&(this.pos.x=s.x-this.pos._x),s.y-this.pos._y!==this.pos.y&&(this.pos.y=s.y-this.pos._y);let e=t.pageX,i=t.pageY,o=document.documentElement.clientWidth,n=document.documentElement.clientHeight,h=s.width,p=s.height,d=[0,o-h,n-p,0];if("parent"===this.opt.limit){let t=this.$elem.parentNode.getBoundingClientRect();d=[t.top,t.right-h,t.bottom-p,t.left]}let l=$.bind(document,"mousemove",t=>{t.preventDefault();let o=t.pageX-e+(s.x-this.pos.x),n=t.pageY-i+(s.y-this.pos.y);"x"===this.opt.axis&&(n=0),"y"===this.opt.axis&&(o=0),!1===this.opt.overflow&&(o<d[3]-this.pos.x?o=d[3]-this.pos.x:o>d[1]-this.pos.x&&(o=d[1]-this.pos.x),n<d[0]-this.pos.y?n=d[0]-this.pos.y:n>d[2]-this.pos.y&&(n=d[2]-this.pos.y)),this.pos._x=o,this.pos._y=n,this.$elem.dispatchEvent(new CustomEvent("dragging",{detail:{offset:{x:this.pos.x+o,y:this.pos.y+n},move:{x:o,y:n}}})),this.$elem.style.transform=`translate(${o}px, ${n}px)`}),m=$.bind(document,"mouseup",t=>{this.$elem.dispatchEvent(new CustomEvent("dragged",{detail:{offset:{x:this.pos.x+this.pos._x,y:this.pos.y+this.pos._y},move:{x:this.pos._x,y:this.pos._y}}})),$.unbind(document,"mousemove",l),$.unbind(document,"mouseup",m)})}),this}on(t,s){if(t&&"function"==typeof s)return $.bind(this,t,s)}off(t,s){$.unbind(this,t,s)}destroy(){$.unbind(window,"resize",this._handleResize),$.unbind(this.$drag,"mousedown",this._handleMousedown),delete this.$elem,delete this.$drag}}; import $ from"../utils.js";const DEF_OPT={axis:"",limit:!1,overflow:!0};export default class Drag{constructor(t){this.$elem=t,this._init()}_init(){this.$elem.style.transform="";var{x:t,y:s}=this.$elem.getBoundingClientRect();this.pos={x:t,y:s,_x:0,_y:0}}by(t,s={}){return this.$drag=t,this.opt=Object.assign(Object.create(null),DEF_OPT,s),!1!==this.opt.limit&&(this.opt.overflow=!1),t.style.cursor="move",this._handleResize=$.bind(window,"resize",this._init.bind(this)),this._handleMousedown=$.bind(t,"mousedown",t=>{if(this.disabled)return;var s=this.$elem.getBoundingClientRect();s.x-this.pos._x!==this.pos.x&&(this.pos.x=s.x-this.pos._x),s.y-this.pos._y!==this.pos.y&&(this.pos.y=s.y-this.pos._y);let e=t.pageX,i=t.pageY,o=document.documentElement.clientWidth,n=document.documentElement.clientHeight,h=s.width,p=s.height,d=[0,o-h,n-p,0];if("parent"===this.opt.limit){let t=this.$elem.parentNode.getBoundingClientRect();d=[t.top,t.right-h,t.bottom-p,t.left]}let l=$.bind(document,"mousemove",t=>{t.preventDefault();let o=t.pageX-e+(s.x-this.pos.x),n=t.pageY-i+(s.y-this.pos.y);"x"===this.opt.axis&&(n=0),"y"===this.opt.axis&&(o=0),!1===this.opt.overflow&&(o<d[3]-this.pos.x?o=d[3]-this.pos.x:o>d[1]-this.pos.x&&(o=d[1]-this.pos.x),n<d[0]-this.pos.y?n=d[0]-this.pos.y:n>d[2]-this.pos.y&&(n=d[2]-this.pos.y)),this.pos._x=o,this.pos._y=n,this.$elem.dispatchEvent(new CustomEvent("dragging",{detail:{offset:{x:this.pos.x+o,y:this.pos.y+n},move:{x:o,y:n}}})),this.$elem.style.transform=`translate(${o}px, ${n}px)`}),m=$.bind(document,"mouseup",t=>{this.$elem.dispatchEvent(new CustomEvent("dragged",{detail:{offset:{x:this.pos.x+this.pos._x,y:this.pos.y+this.pos._y},move:{x:this.pos._x,y:this.pos._y}}})),$.unbind(document,"mousemove",l),$.unbind(document,"mouseup",m)})}),this}on(t,s){if(t&&"function"==typeof s)return $.bind(this,t,s)}off(t,s){$.unbind(this,t,s)}destroy(){$.unbind(window,"resize",this._handleResize),$.unbind(this.$drag,"mousedown",this._handleMousedown),delete this.$elem,delete this.$drag}}

View File

@ -1 +1 @@
"use strict";import Drag from"./core.js";Anot.directive("drag",{priority:1500,init:function(e){e.expr='"'+e.expr+'"',e.overflow=!0,e.axis="xy",e.element.dataset.axis&&(e.axis=e.element.dataset.axis,delete e.element.dataset.axis),e.limit=!1,e.element.dataset.limit&&(e.limit=e.element.dataset.limit,e.overflow=!1,delete e.element.dataset.limit)},update:function(e){var t=this.element;if(e)for(t=this.element.parentNode;t;){if(t.classList||Anot.error(`${this.name}=${this.expr}, 解析异常[元素不存在]`),"WC-LAYER"===t.tagName&&"layer"===e){t=t.root.children[1];break}if(t.classList.contains(e)||t.id===e)break;t=t.parentNode}new Drag(t).by(this.element,{limit:this.limit,axis:this.axis,overflow:this.overflow})}}); import Drag from"./core.js";Anot.directive("drag",{priority:1500,init:function(e){e.expr='"'+e.expr+'"',e.overflow=!0,e.axis="xy",e.element.dataset.axis&&(e.axis=e.element.dataset.axis,delete e.element.dataset.axis),e.limit=!1,e.element.dataset.limit&&(e.limit=e.element.dataset.limit,e.overflow=!1,delete e.element.dataset.limit)},update:function(e){var t=this.element;if(e)for(t=this.element.parentNode;t;){if(t.classList||Anot.error(`${this.name}=${this.expr}, 解析异常[元素不存在]`),"WC-LAYER"===t.tagName&&"layer"===e){t=t.root.children[1];break}if(t.classList.contains(e)||t.id===e)break;t=t.parentNode}new Drag(t).by(this.element,{limit:this.limit,axis:this.axis,overflow:this.overflow})}});

1
src/lib/fetch/index.js Normal file
View File

@ -0,0 +1 @@
import{Format,toS}from"./lib/format.js";const noop=function(e,t){this.defer.resolve(t)},NOBODY_METHODS=["GET","HEAD"],FORM_TYPES={form:"application/x-www-form-urlencoded; charset=UTF-8",json:"application/json; charset=UTF-8",text:"text/plain; charset=UTF-8"},ERRORS={10001:"Argument url is required",10012:"Parse error",10100:"Request canceled",10104:"Request pending...",10200:"Ok",10204:"No content",10304:"Not modified",10500:"Internal Server Error",10504:"Connected timeout"};Promise.defer=function(){var e={};return e.promise=new Promise(function(t,s){e.resolve=t,e.reject=s}),e};class _Request{constructor(e="",t={},{BASE_URL:s,__INIT__:r}){if(!e)throw new Error(ERRORS[10001]);if(e=e.replace(/#.*$/,""),s&&(/^([a-z]+:|\/\/)/.test(e)||(e=s+e)),t.method=(t.method||"get").toUpperCase(),this.xhr=new XMLHttpRequest,this.defer=Promise.defer(),this.options={headers:{"X-Requested-With":"XMLHttpRequest","content-type":FORM_TYPES.form},body:null,cache:"default",credentials:!1,signal:null,timeout:3e4},!t.signal){var o=new AbortController;t.signal=o.signal}this.defer.promise.abort=function(){o.abort()};var i=this.options.headers;return r.headers&&Object.assign(i,r.headers),t.headers&&(Object.assign(i,t.headers),delete t.headers),Object.assign(this.options,r,t,{url:e,headers:i}),this.__next__(),this.defer.promise}__next__(){var e=this.options,t=null,s=!1,r=!1,o=NOBODY_METHODS.includes(e.method);if(e.signal.onabort=(e=>{this.cancel=!0,this.xhr.abort()}),e.body)switch(typeof e.body){case"number":case"string":this.__type__("text"),t=e.body;break;case"object":if("FORM"===e.body.nodeName)e.method=e.body.method.toUpperCase()||"POST",s=(t=Format.parseForm(e.body)).constructor===FormData;else if(e.body.constructor===FormData)s=!0,o&&(e.method="POST"),t=e.body;else{for(let t in e.body)if("[object File]"===toS.call(e.body[t])){s=!0;break}s?(o&&(e.method="POST"),t=Format.mkFormData(e.body)):t=e.body}}s&&delete e.headers["content-type"];try{let t=document.createElement("a");t.href=e.url,r=location.protocol!==t.protocol||location.host!==t.host}catch(e){}r&&(e.credentials?this.xhr.withCredentials=!0:delete e.headers["X-Requested-With"]),o?((t=Format.param(t))&&(e.url+=(~e.url.indexOf("?")?"&":"?")+t),"no-store"===e.cache&&(e.url+=(~e.url.indexOf("?")?"&":"?")+"_t_="+Date.now())):s||(t=~e.headers["content-type"].indexOf("json")?JSON.stringify(t):Format.param(t)),this.xhr.responseType="blob",this.xhr.onreadystatechange=(t=>{e.timeout>0&&(e["time"+this.xhr.readyState]=t.timeStamp,4===this.xhr.readyState&&(e.isTimeout=e.time4-e.time1>e.timeout)),4===this.xhr.readyState&&this.__dispatch__(e.isTimeout)}),this.xhr.open(e.method,e.url);for(let t in e.headers)this.xhr.setRequestHeader(t,e.headers[t]);this.xhr.send(t),e.timeout&&e.timeout>0&&(this.xhr.timeout=e.timeout)}__type__(e){this.options.headers["content-type"]=FORM_TYPES[e]}__dispatch__(e){let t={status:200,statusText:"ok",body:"",headers:Object.create(null)};if(this.cancel)return this.__cancel__();if(e)return this.__timeout__();let s=this.xhr.status>=200&&this.xhr.status<400,r=this.xhr.getAllResponseHeaders().split("\n")||[];for(let e of r)if(e=e.trim()){let s=(e=e.split(":")).shift().toLowerCase();e=e.join(":").trim(),t.headers[s]=e}s?(t.status=this.xhr.status,204===t.status?t.statusText=ERRORS[10204]:304===t.status&&(t.statusText=ERRORS[10304])):(t.status=this.xhr.status||500,t.statusText=this.xhr.statusText||ERRORS[10500]),t.body=this.xhr.response,this.__success__(s,t)}__success__(e,t){var s=new _Response(t.status,t.statusText,t.body,t.headers);e?this.defer.resolve(s):this.defer.reject(s),delete this.xhr,delete this.options,delete this.defer}__cancel__(e){var t=new _Response(0,ERRORS[10100],Object.create(null));this.defer.reject(t),delete this.xhr,delete this.options,delete this.defer}__timeout__(e){var t=new _Response(504,ERRORS[10504],Object.create(null));this.defer.reject(t),delete this.xhr,delete this.options,delete this.defer}}class _Response{constructor(e=200,t="OK",s=null,r={}){this.status=e,this.statusText=t,this.ok=e>=200&&e<400,this.headers=r,Object.defineProperty(this,"__R__",{value:s,writable:!0,enumerable:!1,configurable:!0})}text(){return this.__R__.text()}json(){return this.__R__.text().then(e=>JSON.parse(e))}blob(){return this.__R__}arrayBuffer(){return this.__R__.arrayBuffer()}}const _fetch=function(e,t){return new _Request(e,t,{BASE_URL:_fetch.BASE_URL,__INIT__:_fetch.__INIT__||Object.create(null)})};_fetch.create=function(e,t=Object.create(null)){return function(s,r){return new _Request(s,r,{BASE_URL:e,__INIT__:t})}};export default _fetch;

View File

@ -0,0 +1 @@
export const toS=Object.prototype.toString;export const encode=encodeURIComponent;export const decode=decodeURIComponent;function serialize(e,t,o){var a;if(Array.isArray(t))t.forEach(function(t,r){a=e?`${e}[${Array.isArray(t)?r:""}]`:r,"object"==typeof t?serialize(a,t,o):o(a,t)});else for(let r in t)a=e?`${e}[${r}]`:r,"object"==typeof t[r]?serialize(a,t[r],o):o(a,t[r])}export const Format={parseForm(e){let t={},o=!1;for(let a,r=0;a=e.elements[r++];)switch(a.type){case"select-one":case"select-multiple":if(a.name.length&&!a.disabled)for(let e,o=0;e=a.options[o++];)e.selected&&(t[a.name]=e.value||e.text);break;case"file":a.name.length&&!a.disabled&&(t[a.name]=a.files[0],o=!0);break;case void 0:case"submit":case"reset":case"button":break;case"radio":case"checkbox":if(!a.checked)break;default:a.name.length&&!a.disabled&&(t[a.name]=a.value)}return o?this.mkFormData(t):t},mkFormData(e){let t=new FormData;for(let o in e){let a=e[o];Array.isArray(a)?a.forEach(function(e){t.append(o+"[]",e)}):t.append(o,e[o])}return t},param(e){if(!e||"string"==typeof e||"number"==typeof e)return e;let t=[];return"object"==typeof e&&serialize("",e,function(e,o){/native code/.test(o)||(o="function"==typeof o?o():o,o="[object File]"===toS.call(o)?o:encode(o),t.push(encode(e)+"="+o))}),t.join("&")}};

File diff suppressed because one or more lines are too long

13
src/lib/form/cascader.js Normal file
View File

@ -0,0 +1,13 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2021-02-05 16:32:07
* @version v1.0.3
*
*/
if(!customElements.get('wc-')){
customElements.define('wc-', )
}

View File

@ -1,310 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import"../icon/index.js";import $ from"../utils.js";export default class CheckboxItem extends HTMLElement{static get observedAttributes(){return["color","value","checked","readonly","disabled"]}props={color:"",value:"",checked:!1,readonly:!1,disabled:!1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-flex;line-height:1;font-size:14px}:host label{display:flex;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 5px;line-height:1;-moz-user-select:none;user-select:none;white-space:nowrap;cursor:inherit;color:var(--color-grey-3)}:host .dot{--size: 18px;padding:2px;margin-right:3px}:host([readonly]){opacity:.8}:host([disabled]){cursor:not-allowed;opacity:.6}:host([size=large]){font-size:16px}:host([size=large]) label{height:42px}:host([size=large]) .dot{--size: 22px}:host([size=medium]) label{height:38px}:host([size=medium]) .dot{--size: 20px}:host([size=mini]){font-size:12px}:host([size=mini]) label{height:20px}:host([size=mini]) .dot{--size: 14px}:host([type=danger]) label.checked{color:var(--color-red-1)}:host([type=danger]) label.checked .dot{border-color:var(--color-red-1)}:host([type=danger]) label.checked .dot::after{background:var(--color-red-1)}:host([type=info]) label.checked{color:var(--color-blue-1)}:host([type=info]) label.checked .dot{border-color:var(--color-blue-1)}:host([type=info]) label.checked .dot::after{background:var(--color-blue-1)}:host([type=success]) label.checked{color:var(--color-green-1)}:host([type=success]) label.checked .dot{border-color:var(--color-green-1)}:host([type=success]) label.checked .dot::after{background:var(--color-green-1)}:host([type=primary]) label.checked{color:var(--color-teal-1)}:host([type=primary]) label.checked .dot{border-color:var(--color-teal-1)}:host([type=primary]) label.checked .dot::after{background:var(--color-teal-1)}:host([type=warning]) label.checked{color:var(--color-orange-1)}:host([type=warning]) label.checked .dot{border-color:var(--color-orange-1)}:host([type=warning]) label.checked .dot::after{background:var(--color-orange-1)}:host([type=inverse]) label.checked{color:var(--color-dark-1)}:host([type=inverse]) label.checked .dot{border-color:var(--color-dark-1)}:host([type=inverse]) label.checked .dot::after{background:var(--color-dark-1)}:host([color=purple]) label.checked{color:var(--color-purple-1)}:host([color=purple]) label.checked .dot{border-color:var(--color-purple-1)}:host([color=purple]) label.checked .dot::after{background:var(--color-purple-1)}</style> <label> <wc-icon class="dot" is="checkbox-off"></wc-icon> <slot /> </label> ',this.__SWITCH__=this.root.lastElementChild,this.__ICO__=this.__SWITCH__.children[0],this._isInGroup=!1}_checkGroup(){this._isInGroup="WC-CHECKBOX"===this.parentNode.tagName,this._isInGroup&&this.parentNode.root&&this.parentNode.value.includes(this.value)&&(this.checked=!0)}get value(){return this.props.value}set value(e){this.props.value=e}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e;var{checked:o,color:t}=this.props;this.__SWITCH__.classList.toggle("checked",o),this.__ICO__.setAttribute("is","checkbox-"+(o?"on":"off")),o?this.__ICO__.setAttribute("color",t):this.__ICO__.removeAttribute("color")}get readOnly(){return this.props.readonly}set readOnly(e){var o=typeof e;e!==this.props.readonly&&("boolean"===o&&e||"boolean"!==o?(this.props.readonly=!0,this.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var o=typeof e;e!==this.props.disabled&&("boolean"===o&&e||"boolean"!==o?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this._checkGroup(),this._handlClick=$.bind(this,"click",e=>{e.preventDefault(),this.disabled||this.readOnly||(this.checked=!this.checked,this._isInGroup?this.parentNode.dispatchEvent(new CustomEvent("child-picked",{detail:{value:this.value,checked:this.checked}})):this.dispatchEvent(new CustomEvent("input")))})}disconnectedCallback(){$.unbind(this,"click",this._handlClick)}attributeChangedCallback(e,o,t){if(o!==t)switch(e){case"value":case"color":this.props[e]=t;break;case"checked":case"readonly":case"disabled":var r=e;"readonly"===r&&(r="readOnly"),this[r]=!0}}}
import "../icon/index.js"
import $ from "../utils.js"
export default class CheckboxItem extends HTMLElement {
static get observedAttributes() {
return ["color","value","checked","readonly","disabled"]
}
props = {
color: '',
value: '',
checked: false,
readonly: false,
disabled: false
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: inline-flex;
line-height: 1;
font-size: 14px; }
:host label {
display: flex;
justify-content: center;
align-items: center;
min-width: 32px;
height: 32px;
padding: 0 5px;
line-height: 0;
-moz-user-select: none;
user-select: none;
white-space: nowrap;
cursor: inherit;
color: var(--color-grey-3); }
:host .dot {
--size: 18px;
padding: 2px;
margin-right: 3px; }
:host([readonly]) {
opacity: 0.8; }
:host([disabled]) {
cursor: not-allowed;
opacity: 0.6; }
:host([size='large']) {
font-size: 16px; }
:host([size='large']) label {
height: 42px; }
:host([size='large']) .dot {
--size: 22px; }
:host([size='medium']) label {
height: 38px; }
:host([size='medium']) .dot {
--size: 20px; }
:host([size='mini']) {
font-size: 12px; }
:host([size='mini']) label {
height: 20px; }
:host([size='mini']) .dot {
--size: 14px; }
:host([color='red']) label.checked {
color: var(--color-red-1); }
:host([color='red']) label.checked .dot {
border-color: var(--color-red-1); }
:host([color='red']) label.checked .dot::after {
background: var(--color-red-1); }
:host([color='blue']) label.checked {
color: var(--color-blue-1); }
:host([color='blue']) label.checked .dot {
border-color: var(--color-blue-1); }
:host([color='blue']) label.checked .dot::after {
background: var(--color-blue-1); }
:host([color='green']) label.checked {
color: var(--color-green-1); }
:host([color='green']) label.checked .dot {
border-color: var(--color-green-1); }
:host([color='green']) label.checked .dot::after {
background: var(--color-green-1); }
:host([color='teal']) label.checked {
color: var(--color-teal-1); }
:host([color='teal']) label.checked .dot {
border-color: var(--color-teal-1); }
:host([color='teal']) label.checked .dot::after {
background: var(--color-teal-1); }
:host([color='orange']) label.checked {
color: var(--color-orange-1); }
:host([color='orange']) label.checked .dot {
border-color: var(--color-orange-1); }
:host([color='orange']) label.checked .dot::after {
background: var(--color-orange-1); }
:host([color='dark']) label.checked {
color: var(--color-dark-1); }
:host([color='dark']) label.checked .dot {
border-color: var(--color-dark-1); }
:host([color='dark']) label.checked .dot::after {
background: var(--color-dark-1); }
:host([color='purple']) label.checked {
color: var(--color-purple-1); }
:host([color='purple']) label.checked .dot {
border-color: var(--color-purple-1); }
:host([color='purple']) label.checked .dot::after {
background: var(--color-purple-1); }
</style>
<label>
<wc-icon class="dot" is="checkbox-off"></wc-icon>
<slot />
</label>
`
this.__SWITCH__ = this.root.lastElementChild
this.__ICO__ = this.__SWITCH__.children[0]
this._isInGroup = false
}
_checkGroup() {
this._isInGroup = this.parentNode.tagName === 'WC-CHECKBOX'
if (this._isInGroup && this.parentNode.root) {
if (this.parentNode.value.includes(this.value)) {
this.checked = true
}
}
}
get value() {
return this.props.value
}
set value(val) {
this.props.value = val
}
get checked() {
return this.props.checked
}
set checked(val) {
this.props.checked = !!val
var { checked, color } = this.props
this.__SWITCH__.classList.toggle('checked', checked)
this.__ICO__.setAttribute('is', 'checkbox-' + (checked ? 'on' : 'off'))
if (checked) {
this.__ICO__.setAttribute('color', color)
} else {
this.__ICO__.removeAttribute('color')
}
}
get readOnly() {
return this.props.readonly
}
set readOnly(val) {
var type = typeof val
if (val === this.props.readonly) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.readonly = true
this.setAttribute('readonly', '')
} else {
this.props.readonly = false
this.removeAttribute('readonly')
}
}
get disabled() {
return this.props.disabled
}
set disabled(val) {
var type = typeof val
if (val === this.props.disabled) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.disabled = true
this.setAttribute('disabled', '')
} else {
this.props.disabled = false
this.removeAttribute('disabled')
}
}
connectedCallback() {
this._checkGroup()
this._handlClick = $.bind(this, 'click', ev => {
ev.preventDefault()
if (this.disabled || this.readOnly) {
return
}
this.checked = !this.checked
if (this._isInGroup) {
this.parentNode.dispatchEvent(
new CustomEvent('child-picked', {
detail: { value: this.value, checked: this.checked }
})
)
} else {
this.dispatchEvent(new CustomEvent('input'))
}
})
}
disconnectedCallback() {
$.unbind(this, 'click', this._handlClick)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'value':
case 'color':
this.props[name] = val
break
case 'checked':
case 'readonly':
case 'disabled':
var k = name
if (k === 'readonly') {
k = 'readOnly'
}
this[k] = true
break
}
}
}
if(!customElements.get('wc-checkbox-item')){ if(!customElements.get('wc-checkbox-item')){
customElements.define('wc-checkbox-item', CheckboxItem) customElements.define('wc-checkbox-item', CheckboxItem)

View File

@ -1,141 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import $ from"../utils.js";import"./checkbox-item.js";export default class Checkbox extends HTMLElement{static get observedAttributes(){return["value"]}props={value:[]};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-flex}</style> <slot /> "}_updateChildrenStat(){Array.from(this.children).forEach(e=>{"WC-CHECKBOX-ITEM"===e.tagName&&e.root&&(this.value.includes(e.value)?e.checked=!0:e.checked=!1)})}get value(){return this.props.value}set value(e){e!==this.props.value&&(this.props.value=e,this._updateChildrenStat())}connectedCallback(){this._pickedFn=$.bind(this,"child-picked",e=>{var t=[...this.props.value],i=t.indexOf(e.detail.value);e.detail.checked?i<0&&t.push(e.detail.value):~i&&t.splice(i,1),this.props.value=t,this.dispatchEvent(new CustomEvent("input"))})}disconnectedCallback(){$.unbind(this,"child-picked",this._pickedFn)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"value":i&&(this.value=i.split(/,\s*?/))}}}
import $ from "../utils.js"
import "./checkbox-item.js"
export default class Checkbox extends HTMLElement {
static get observedAttributes() {
return ["value"]
}
props = {
value: []
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: inline-flex; }
</style>
<slot />
`
}
_updateChildrenStat() {
Array.from(this.children).forEach(it => {
if (it.tagName === 'WC-CHECKBOX-ITEM' && it.root) {
if (this.value.includes(it.value)) {
it.checked = true
} else {
it.checked = false
}
}
})
}
get value() {
return this.props.value
}
set value(val) {
if (val === this.props.value) {
return
}
this.props.value = val
this._updateChildrenStat()
}
connectedCallback() {
this._pickedFn = $.bind(this, 'child-picked', ev => {
var tmp = [...this.props.value]
var idx = tmp.indexOf(ev.detail.value)
if (ev.detail.checked) {
if (idx < 0) {
tmp.push(ev.detail.value)
}
} else {
if (~idx) {
tmp.splice(idx, 1)
}
}
this.props.value = tmp
this.dispatchEvent(new CustomEvent('input'))
})
}
disconnectedCallback() {
$.unbind(this, 'child-picked', this._pickedFn)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'value':
if (val) {
this.value = val.split(/,\s*?/)
}
break
}
}
}
if(!customElements.get('wc-checkbox')){ if(!customElements.get('wc-checkbox')){
customElements.define('wc-checkbox', Checkbox) customElements.define('wc-checkbox', Checkbox)

1
src/lib/form/index.js Normal file
View File

@ -0,0 +1 @@
import"./button.js";import"./link.js";import"./input.js";import"./textarea.js";import"./number.js";import"./radio.js";import"./checkbox.js";import"./switch.js";import"./select.js";import"./star.js";

File diff suppressed because one or more lines are too long

13
src/lib/form/link.js Normal file
View File

@ -0,0 +1,13 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2021-02-05 16:32:07
* @version v1.0.3
*
*/
import"../icon/index.js";import $ from"../utils.js";const IS_FIREFOX=!!window.sidebar;export default class Link extends HTMLElement{static get observedAttributes(){return["to","autofocus","disabled","lazy"]}props={to:null,autofocus:"",disabled:!1,lazy:0};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{position:relative;display:inline-flex;user-select:none;-moz-user-select:none;font-size:14px;cursor:pointer}:host .link{display:flex;justify-content:center;align-items:center;width:100%;padding:var(--padding, 0 2px);line-height:1;font-size:inherit;font-family:inherit;outline:none;color:inherit;cursor:inherit;text-decoration:none;transition:color .15s linear}:host .link::-moz-focus-inner{border:none}:host::after{position:absolute;bottom:-2px;left:0;width:100%;height:1px;border-bottom:1px dashed var(--color-plain-3);content:"";opacity:0;transition:opacity .15s linear}:host(:not([disabled]):focus-within)::after{height:2px;border-width:2px;opacity:1}:host(:not([disabled]):hover)::after,:host([underline])::after{opacity:1}:host([loading]),:host([disabled]){cursor:not-allowed;opacity:.6}:host([type=danger]){color:var(--color-red-2)}:host([type=danger])::after{border-color:var(--color-red-1)}:host([type=danger]:not([disabled]):hover){color:var(--color-red-1)}:host([type=danger]:not([disabled]):active){color:var(--color-red-3)}:host([type=info]){color:var(--color-blue-2)}:host([type=info])::after{border-color:var(--color-blue-1)}:host([type=info]:not([disabled]):hover){color:var(--color-blue-1)}:host([type=info]:not([disabled]):active){color:var(--color-blue-3)}:host([type=success]){color:var(--color-green-2)}:host([type=success])::after{border-color:var(--color-green-1)}:host([type=success]:not([disabled]):hover){color:var(--color-green-1)}:host([type=success]:not([disabled]):active){color:var(--color-green-3)}:host([type=primary]){color:var(--color-teal-2)}:host([type=primary])::after{border-color:var(--color-teal-1)}:host([type=primary]:not([disabled]):hover){color:var(--color-teal-1)}:host([type=primary]:not([disabled]):active){color:var(--color-teal-3)}:host([type=warning]){color:var(--color-orange-2)}:host([type=warning])::after{border-color:var(--color-orange-1)}:host([type=warning]:not([disabled]):hover){color:var(--color-orange-1)}:host([type=warning]:not([disabled]):active){color:var(--color-orange-3)}:host([type=inverse]){color:var(--color-dark-2)}:host([type=inverse])::after{border-color:var(--color-dark-1)}:host([type=inverse]:not([disabled]):hover){color:var(--color-dark-1)}:host([type=inverse]:not([disabled]):active){color:var(--color-dark-3)}:host([type=default]){color:var(--color-grey-2)}:host([type=default])::after{border-color:var(--color-grey-1)}:host([type=default]:not([disabled]):hover){color:var(--color-grey-1)}:host([type=default]:not([disabled]):active){color:var(--color-grey-3)}</style> <a tabindex="0" class="link"> <slot /> </a> ',this.__LINK__=this.root.children[1]}get disabled(){return this.props.disabled}set disabled(o){var e=typeof o;o!==this.props.disabled&&("boolean"===e&&o||"boolean"!==e?(this.props.disabled=!0,this.setAttribute("disabled",""),this.__LINK__.removeAttribute("tabindex")):(this.props.disabled=!1,this.removeAttribute("disabled"),this.__LINK__.setAttribute("tabindex",0)))}connectedCallback(){this.stamp=0,this._handleClick=$.bind(this.__LINK__,"click",o=>{var{disabled:e,lazy:t}=this.props,r=Date.now();return e?(o.stopPropagation(),void o.preventDefault()):t&&r-this.stamp<t?(o.preventDefault(),void o.stopPropagation()):void(this.stamp=r)})}disconnectedCallback(){$.unbind(this.__LINK__,"click",this._handleClick)}attributeChangedCallback(o,e,t){if(e!==t)switch(o){case"autofocus":this.__LINK__.setAttribute("autofocus",""),IS_FIREFOX&&setTimeout(o=>{this.__LINK__.focus()},10);break;case"to":null===t?this.__LINK__.removeAttribute("href"):this.__LINK__.setAttribute("href",t);break;case"lazy":this.props.lazy=t>>0;break;case"disabled":this[o]=null!==t}}}
if(!customElements.get('wc-link')){
customElements.define('wc-link', Link)
}

View File

@ -1,412 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import"../scroll/index.js";import"../icon/index.js";import $ from"../utils.js";export default class Number extends HTMLElement{static get observedAttributes(){return["value","max","min","step","autofocus","readonly","disabled"]}props={value:0,max:null,min:null,step:1,autofocus:!1,readonly:!1,disabled:!1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>undefined</style> <div class="label"> <span data-act="-">-</span> \x3c!-- <wc-icon class="icon" is="minus"></wc-icon> --\x3e <input value="0" maxlength="9" /> <span data-act="+">+</span> \x3c!-- <wc-icon class="icon" is="plus"></wc-icon> --\x3e </div> ',this.__OUTER__=this.root.children[1],this.__INPUT__=this.__OUTER__.children[1]}get readOnly(){return this.props.readonly}set readOnly(e){var t=typeof e;e!==this.props.readonly&&("boolean"===t&&e||"boolean"!==t?(this.props.readonly=!0,this.setAttribute("readonly",""),this.__INPUT__.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly"),this.__INPUT__.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled",""),this.__INPUT__.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled"),this.__INPUT__.removeAttribute("disabled")))}get value(){return this.props.value}set value(e){var t=+e;e=t==t?t:0,this.props.value=e,this.__INPUT__.value=e,this._checkActionEnable()}_checkActionEnable(){var{max:e,min:t,value:s}=this.props,i=s;null!==t&&(t>i&&(i=t),this.__OUTER__.children[0].classList.toggle("disabled",s<=t)),null!==e&&(e<i&&(i=e),this.__OUTER__.children[2].classList.toggle("disabled",s>=e)),i!==s&&(this.props.value=i,this.__INPUT__.value=i,this.dispatchEvent(new CustomEvent("input")))}_updateValue(e){var{max:t,min:s,value:i,step:a}=this.props;if("+"===e){if(null!==t&&t<i+a)return;i+=a}else{if(null!==s&&s>i-a)return;i-=a}this.props.value=+i.toFixed(2),this.__INPUT__.value=this.props.value,this._checkActionEnable(),this.dispatchEvent(new CustomEvent("input"))}connectedCallback(){this._handleSubmit=$.catch(this.__INPUT__,"keydown",e=>{if(!this.disabled&&!this.readOnly)return 38===e.keyCode||40===e.keyCode?(e.preventDefault(),this._updateValue(38===e.keyCode?"+":"-")):void(13===e.keyCode&&(e.preventDefault(),this.dispatchEvent(new CustomEvent("submit",{detail:this.value}))))}),this._handleChange=$.catch(this.__INPUT__,"change",e=>{isFinite(this.__INPUT__.value)?(this.props.value=+this.__INPUT__.value,this.__INPUT__.value.endsWith(".")||(this.__INPUT__.value=this.props.value)):this.__INPUT__.value=this.props.value=0,this.dispatchEvent(new CustomEvent("input"))}),this._handleAction=$.bind(this.__OUTER__,"click",e=>{if(!this.disabled&&!this.readOnly){var t=e.target;if("SPAN"===t.tagName||"SPAN"===t.parentNode){var s=t.dataset.act||t.parentNode.dataset.act;this._updateValue(s)}}})}disconnectedCallback(){$.unbind(this.__INPUT__,"keydown",this._handleSubmit)}attributeChangedCallback(e,t,s){if(t!==s)switch(e){case"autofocus":this.__INPUT__.setAttribute("autofocus",""),setTimeout(e=>{this.__INPUT__.focus()},10);break;case"value":this.value=s>>0;break;case"step":case"max":case"min":var i=+s;i==i&&(this.props[e]=i),this._checkActionEnable();break;case"readonly":case"disabled":var a=e;"readonly"===a&&(a="readOnly"),this[a]=!0}}}
import "../scroll/index.js"
import "../icon/index.js"
import $ from "../utils.js"
export default class Number extends HTMLElement {
static get observedAttributes() {
return ["value","max","min","step","autofocus","readonly","disabled"]
}
props = {
value: 0,
max: null,
min: null,
step: 1,
autofocus: false,
readonly: false,
disabled: false
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>@charset "UTF-8";
* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
overflow: hidden;
display: inline-block;
width: 128px;
height: 32px;
user-select: none;
-moz-user-select: none;
color: var(--color-dark-2);
border-radius: 2px; }
.label {
display: flex;
width: 100%;
height: 100%;
margin: 0 auto;
line-height: 0;
font-size: 14px;
border: 1px solid var(--color-plain-3);
border-radius: inherit;
background: var(--bg-color, #fff);
color: inherit;
cursor: text;
/* ----- */ }
.label span {
display: flex;
justify-content: center;
align-items: center;
width: 32px;
height: 100%;
background: var(--bg-color, --color-plain-1);
font-size: 18px;
cursor: pointer; }
.label span:first-child {
border-radius: 2px 0 0 2px;
border-right: 1px solid var(--color-plain-3); }
.label span:last-child {
border-radius: 0 2px 2px 0;
border-left: 1px solid var(--color-plain-3); }
.label span.disabled {
cursor: not-allowed;
opacity: 0.6; }
.label input {
flex: 1;
min-width: 0;
width: 0;
height: 100%;
padding: 0 5px;
border: 0;
border-radius: inherit;
color: inherit;
text-align: center;
font-size: inherit;
font-family: inherit;
background: none;
outline: none;
box-shadow: none;
cursor: inherit; }
.label input::placeholder {
color: var(--color-grey-1); }
.label .icon {
padding: 0 5px;
--size: 20px; }
/* --- */
:host([readonly]) .label {
cursor: default;
opacity: 0.8; }
:host([readonly]) .label span {
cursor: inherit; }
:host([disabled]) .label {
background: var(--color-plain-1);
cursor: not-allowed;
opacity: 0.6; }
:host([disabled]) .label span {
cursor: inherit; }
:host(:focus-within) {
box-shadow: 0 0 2px #88f7df; }
:host(:focus-within[readonly]) {
box-shadow: 0 0 2px #f3be4d; }
/* 额外样式 */
:host([round]) {
border-radius: 21px; }
:host([round]) .label span:first-child {
border-radius: 21px 0 0 21px; }
:host([round]) .label span:last-child {
border-radius: 0 21px 21px 0; }
:host([size='large']) {
width: 192px;
height: 42px; }
:host([size='large']) .label {
font-size: 16px; }
:host([size='large']) .label span {
width: 48px; }
:host([size='large']) .prepend,
:host([size='large']) .append {
height: 40px; }
:host([size='medium']) {
width: 144px;
height: 36px; }
:host([size='medium']) .label span {
width: 36px; }
:host([size='medium']) .prepend,
:host([size='medium']) .append {
height: 34px; }
:host([size='mini']) {
width: 96px;
height: 24px; }
:host([size='mini']) .label {
font-size: 12px; }
:host([size='mini']) .label span {
width: 28px; }
:host([size='mini']) .icon {
--size: 16px; }
:host([size='mini']) .prepend,
:host([size='mini']) .append {
height: 18px; }
</style>
<div class="label">
<span data-act="-">-</span>
<!-- <wc-icon class="icon" is="minus"></wc-icon> -->
<input value="0" maxlength="9" />
<span data-act="+">+</span>
<!-- <wc-icon class="icon" is="plus"></wc-icon> -->
</div>
`
this.__OUTER__ = this.root.children[1]
this.__INPUT__ = this.__OUTER__.children[1]
}
get readOnly() {
return this.props.readonly
}
set readOnly(val) {
var type = typeof val
if (val === this.props.readonly) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.readonly = true
this.setAttribute('readonly', '')
this.__INPUT__.setAttribute('readonly', '')
} else {
this.props.readonly = false
this.removeAttribute('readonly')
this.__INPUT__.removeAttribute('readonly')
}
}
get disabled() {
return this.props.disabled
}
set disabled(val) {
var type = typeof val
if (val === this.props.disabled) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.disabled = true
this.setAttribute('disabled', '')
this.__INPUT__.setAttribute('disabled', '')
} else {
this.props.disabled = false
this.removeAttribute('disabled')
this.__INPUT__.removeAttribute('disabled')
}
}
get value() {
return this.props.value
}
set value(val) {
var n = +val
if (n === n) {
val = n
} else {
val = 0
}
this.props.value = val
this.__INPUT__.value = val
this._checkActionEnable()
}
_checkActionEnable() {
var { max, min, value } = this.props
var n = value
if (min !== null) {
if (min > n) {
n = min
}
this.__OUTER__.children[0].classList.toggle('disabled', value <= min)
}
if (max !== null) {
if (max < n) {
n = max
}
this.__OUTER__.children[2].classList.toggle('disabled', value >= max)
}
if (n !== value) {
this.props.value = n
this.__INPUT__.value = n
this.dispatchEvent(new CustomEvent('input'))
}
}
_updateValue(act) {
var { max, min, value, step } = this.props
if (act === '+') {
if (max !== null && max < value + step) {
return
}
value += step
} else {
if (min !== null && min > value - step) {
return
}
value -= step
}
this.props.value = +value.toFixed(2)
this.__INPUT__.value = this.props.value
this._checkActionEnable()
this.dispatchEvent(new CustomEvent('input'))
}
connectedCallback() {
// 键盘事件
this._handleSubmit = $.catch(this.__INPUT__, 'keydown', ev => {
if (this.disabled || this.readOnly) {
return
}
// up: 38, down: 40
if (ev.keyCode === 38 || ev.keyCode === 40) {
ev.preventDefault()
return this._updateValue(ev.keyCode === 38 ? '+' : '-')
}
// 回车触发submit事件
if (ev.keyCode === 13) {
ev.preventDefault()
this.dispatchEvent(
new CustomEvent('submit', {
detail: this.value
})
)
}
})
this._handleChange = $.catch(this.__INPUT__, 'change', ev => {
if (isFinite(this.__INPUT__.value)) {
this.props.value = +this.__INPUT__.value
if (!this.__INPUT__.value.endsWith('.')) {
this.__INPUT__.value = this.props.value
}
} else {
this.__INPUT__.value = this.props.value = 0
}
this.dispatchEvent(new CustomEvent('input'))
})
this._handleAction = $.bind(this.__OUTER__, 'click', ev => {
if (this.disabled || this.readOnly) {
return
}
var target = ev.target
if (target.tagName === 'SPAN' || target.parentNode === 'SPAN') {
var act = target.dataset.act || target.parentNode.dataset.act
this._updateValue(act)
}
})
}
disconnectedCallback() {
$.unbind(this.__INPUT__, 'keydown', this._handleSubmit)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'autofocus':
this.__INPUT__.setAttribute('autofocus', '')
// 辣鸡火狐, 要触发一下focus, 才能聚焦
setTimeout(_ => {
this.__INPUT__.focus()
}, 10)
break
case 'value':
this.value = val >> 0
break
case 'step':
case 'max':
case 'min':
var n = +val
if (n === n) {
this.props[name] = n
}
this._checkActionEnable()
break
case 'readonly':
case 'disabled':
var k = name
if (k === 'readonly') {
k = 'readOnly'
}
this[k] = true
break
}
}
}
if(!customElements.get('wc-number')){ if(!customElements.get('wc-number')){
customElements.define('wc-number', Number) customElements.define('wc-number', Number)

View File

@ -1,162 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
export default class Progress extends HTMLElement{static get observedAttributes(){return["value","max"]}props={value:0,max:1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:flex;align-items:center}:host label{flex:1;height:var(--size, 10px);border-radius:9px;background:var(--color-plain-2)}:host label span{display:block;width:0;height:100%;border-radius:9px;background:var(--color-teal-1)}:host([size=large]) label{height:18px}:host([size=medium]) label{height:14px}:host([size=mini]) label{height:6px}:host([type=danger]) label span{background:var(--color-red-1)}:host([type=info]) label span{background:var(--color-blue-1)}:host([type=success]) label span{background:var(--color-green-1)}:host([type=warning]) label span{background:var(--color-orange-1)}:host([type=inverse]) label span{background:var(--color-dark-1)}:host([color=purple]) label span{background:var(--color-purple-1)}</style> <label><span></span></label> ",this.__THUMB__=this.root.children[1].lastElementChild}get value(){return this.props.value}set value(e){this.props.value=+e,this.calculate()}calculate(){var{max:e,value:a}=this.props;this.__THUMB__.style.width=100*a/e+"%"}connectedCallback(){this.calculate()}attributeChangedCallback(e,a,l){if(a!==l)switch(e){case"max":var r=+l;(r!=r||r<1)&&(r=1),this.props.max=r,this.calculate();break;case"value":var t=+l;t==t&&(this.props.value=t,this.calculate())}}}
export default class Progress extends HTMLElement {
static get observedAttributes() {
return ["value","max"]
}
props = {
value: 0,
max: 1
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: flex;
align-items: center; }
:host label {
flex: 1;
height: var(--size, 10px);
border-radius: 9px;
background: var(--color-plain-2); }
:host label span {
display: block;
width: 0;
height: 100%;
border-radius: 9px;
background: var(--color-teal-1); }
:host([size='large']) label {
height: 18px; }
:host([size='medium']) label {
height: 14px; }
:host([size='mini']) label {
height: 6px; }
:host([color='red']) label span {
background: var(--color-red-1); }
:host([color='blue']) label span {
background: var(--color-blue-1); }
:host([color='green']) label span {
background: var(--color-green-1); }
:host([color='orange']) label span {
background: var(--color-orange-1); }
:host([color='dark']) label span {
background: var(--color-dark-1); }
:host([color='purple']) label span {
background: var(--color-purple-1); }
</style>
<label><span></span></label>
`
this.__THUMB__ = this.root.children[1].lastElementChild
}
get value() {
return this.props.value
}
set value(val) {
this.props.value = +val
this.calculate()
}
calculate() {
var { max, value } = this.props
this.__THUMB__.style.width = `${(100 * value) / max}%`
}
connectedCallback() {
this.calculate()
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'max':
var max = +val
if (max !== max || max < 1) {
max = 1
}
this.props.max = max
this.calculate()
break
case 'value':
var v = +val
if (v === v) {
this.props.value = v
this.calculate()
}
break
}
}
}
if(!customElements.get('wc-progress')){ if(!customElements.get('wc-progress')){
customElements.define('wc-progress', Progress) customElements.define('wc-progress', Progress)

View File

@ -1,307 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import $ from"../utils.js";export default class RadioItem extends HTMLElement{static get observedAttributes(){return["value","checked","readonly","disabled"]}props={value:"",checked:!1,readonly:!1,disabled:!1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-flex;line-height:1;font-size:14px}:host label{display:flex;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 5px;line-height:1;-moz-user-select:none;user-select:none;white-space:nowrap;cursor:inherit;color:var(--color-grey-3)}:host label.checked .dot::after{visibility:visible}:host .dot{display:flex;justify-content:center;align-items:center;width:18px;height:18px;margin-right:3px;border:1px solid var(--color-grey-1);border-radius:50%;background:#fff}:host .dot::after{display:block;visibility:hidden;width:12px;height:12px;border-radius:50%;background:var(--color-grey-1);content:""}:host([readonly]){opacity:.8}:host([disabled]){cursor:not-allowed;opacity:.6}:host([size=large]) label{min-width:58px;height:32px}:host([size=large]) .dot{width:26px;height:26px}:host([size=large]) .dot::after{width:18px;height:18px}:host([size=medium]) label{min-width:50px;height:28px}:host([size=medium]) .dot{width:22px;height:22px}:host([size=medium]) .dot::after{width:14px;height:14px}:host([size=mini]) label{height:14px}:host([size=mini]) .dot{width:14px;height:14px}:host([size=mini]) .dot::after{width:8px;height:8px}:host([type=danger]) label.checked{color:var(--color-red-1)}:host([type=danger]) label.checked .dot{border-color:var(--color-red-1)}:host([type=danger]) label.checked .dot::after{background:var(--color-red-1)}:host([type=info]) label.checked{color:var(--color-blue-1)}:host([type=info]) label.checked .dot{border-color:var(--color-blue-1)}:host([type=info]) label.checked .dot::after{background:var(--color-blue-1)}:host([type=success]) label.checked{color:var(--color-green-1)}:host([type=success]) label.checked .dot{border-color:var(--color-green-1)}:host([type=success]) label.checked .dot::after{background:var(--color-green-1)}:host([type=primary]) label.checked{color:var(--color-teal-1)}:host([type=primary]) label.checked .dot{border-color:var(--color-teal-1)}:host([type=primary]) label.checked .dot::after{background:var(--color-teal-1)}:host([type=warning]) label.checked{color:var(--color-orange-1)}:host([type=warning]) label.checked .dot{border-color:var(--color-orange-1)}:host([type=warning]) label.checked .dot::after{background:var(--color-orange-1)}:host([type=inverse]) label.checked{color:var(--color-dark-1)}:host([type=inverse]) label.checked .dot{border-color:var(--color-dark-1)}:host([type=inverse]) label.checked .dot::after{background:var(--color-dark-1)}:host([color=purple]) label.checked{color:var(--color-purple-1)}:host([color=purple]) label.checked .dot{border-color:var(--color-purple-1)}:host([color=purple]) label.checked .dot::after{background:var(--color-purple-1)}</style> <label> <span class="dot"></span> <slot /> </label> ',this.__SWITCH__=this.root.lastElementChild}get value(){return this.props.value}set value(e){this.props.value=e}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e,this.__SWITCH__.classList.toggle("checked",this.props.checked)}get readOnly(){return this.props.readonly}set readOnly(e){var o=typeof e;e!==this.props.readonly&&("boolean"===o&&e||"boolean"!==o?(this.props.readonly=!0,this.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var o=typeof e;e!==this.props.disabled&&("boolean"===o&&e||"boolean"!==o?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this.value===this.parentNode.value&&(this.checked=!0),this._handleClick=$.catch(this,"click",e=>{this.disabled||this.readOnly||this.checked||this.parentNode.dispatchEvent(new CustomEvent("child-picked",{detail:this.value}))})}disconnectedCallback(){$.unbind(this,"click",this._handleClick)}attributeChangedCallback(e,o,t){if(o!==t)switch(e){case"value":this.value=t;break;case"checked":case"readonly":case"disabled":var r=e;"readonly"===r&&(r="readOnly"),this[r]=!0}}}
import $ from "../utils.js"
export default class RadioItem extends HTMLElement {
static get observedAttributes() {
return ["value","checked","readonly","disabled"]
}
props = {
value: '',
checked: false,
readonly: false,
disabled: false
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: inline-flex;
line-height: 1;
font-size: 14px; }
:host label {
display: flex;
justify-content: center;
align-items: center;
min-width: 32px;
height: 32px;
padding: 0 5px;
line-height: 1;
-moz-user-select: none;
user-select: none;
white-space: nowrap;
cursor: inherit;
color: var(--color-grey-3); }
:host label.checked .dot::after {
visibility: visible; }
:host .dot {
display: flex;
justify-content: center;
align-items: center;
width: 18px;
height: 18px;
margin-right: 3px;
border: 1px solid var(--color-grey-1);
border-radius: 50%;
background: #fff; }
:host .dot::after {
display: block;
visibility: hidden;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--color-grey-1);
content: ''; }
:host([readonly]) {
opacity: 0.8; }
:host([disabled]) {
cursor: not-allowed;
opacity: 0.6; }
:host([size='large']) label {
min-width: 58px;
height: 32px; }
:host([size='large']) .dot {
width: 26px;
height: 26px; }
:host([size='large']) .dot::after {
width: 18px;
height: 18px; }
:host([size='medium']) label {
min-width: 50px;
height: 28px; }
:host([size='medium']) .dot {
width: 22px;
height: 22px; }
:host([size='medium']) .dot::after {
width: 14px;
height: 14px; }
:host([size='mini']) label {
height: 14px; }
:host([size='mini']) .dot {
width: 14px;
height: 14px; }
:host([size='mini']) .dot::after {
width: 8px;
height: 8px; }
:host([color='red']) label.checked {
color: var(--color-red-1); }
:host([color='red']) label.checked .dot {
border-color: var(--color-red-1); }
:host([color='red']) label.checked .dot::after {
background: var(--color-red-1); }
:host([color='blue']) label.checked {
color: var(--color-blue-1); }
:host([color='blue']) label.checked .dot {
border-color: var(--color-blue-1); }
:host([color='blue']) label.checked .dot::after {
background: var(--color-blue-1); }
:host([color='green']) label.checked {
color: var(--color-green-1); }
:host([color='green']) label.checked .dot {
border-color: var(--color-green-1); }
:host([color='green']) label.checked .dot::after {
background: var(--color-green-1); }
:host([color='teal']) label.checked {
color: var(--color-teal-1); }
:host([color='teal']) label.checked .dot {
border-color: var(--color-teal-1); }
:host([color='teal']) label.checked .dot::after {
background: var(--color-teal-1); }
:host([color='orange']) label.checked {
color: var(--color-orange-1); }
:host([color='orange']) label.checked .dot {
border-color: var(--color-orange-1); }
:host([color='orange']) label.checked .dot::after {
background: var(--color-orange-1); }
:host([color='dark']) label.checked {
color: var(--color-dark-1); }
:host([color='dark']) label.checked .dot {
border-color: var(--color-dark-1); }
:host([color='dark']) label.checked .dot::after {
background: var(--color-dark-1); }
:host([color='purple']) label.checked {
color: var(--color-purple-1); }
:host([color='purple']) label.checked .dot {
border-color: var(--color-purple-1); }
:host([color='purple']) label.checked .dot::after {
background: var(--color-purple-1); }
</style>
<label>
<span class="dot"></span>
<slot />
</label>
`
this.__SWITCH__ = this.root.lastElementChild
}
get value() {
return this.props.value
}
set value(val) {
this.props.value = val
}
get checked() {
return this.props.checked
}
set checked(val) {
this.props.checked = !!val
this.__SWITCH__.classList.toggle('checked', this.props.checked)
}
get readOnly() {
return this.props.readonly
}
set readOnly(val) {
var type = typeof val
if (val === this.props.readonly) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.readonly = true
this.setAttribute('readonly', '')
} else {
this.props.readonly = false
this.removeAttribute('readonly')
}
}
get disabled() {
return this.props.disabled
}
set disabled(val) {
var type = typeof val
if (val === this.props.disabled) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.disabled = true
this.setAttribute('disabled', '')
} else {
this.props.disabled = false
this.removeAttribute('disabled')
}
}
connectedCallback() {
if (this.value === this.parentNode.value) {
this.checked = true
}
this._handleClick = $.catch(this, 'click', ev => {
if (this.disabled || this.readOnly || this.checked) {
return
}
this.parentNode.dispatchEvent(
new CustomEvent('child-picked', { detail: this.value })
)
})
}
disconnectedCallback() {
$.unbind(this, 'click', this._handleClick)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'value':
this.value = val
break
case 'checked':
case 'readonly':
case 'disabled':
var k = name
if (k === 'readonly') {
k = 'readOnly'
}
this[k] = true
break
}
}
}
if(!customElements.get('wc-radio-item')){ if(!customElements.get('wc-radio-item')){
customElements.define('wc-radio-item', RadioItem) customElements.define('wc-radio-item', RadioItem)

View File

@ -1,129 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import $ from"../utils.js";import"./radio-item.js";export default class Radio extends HTMLElement{static get observedAttributes(){return["value"]}props={value:null};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-flex}</style> <slot /> "}_updateChildrenStat(){Array.from(this.children).forEach(e=>{"WC-RADIO-ITEM"===e.tagName&&e.root&&(e.value===this.props.value?e.checked=!0:e.checked=!1)})}get value(){return this.props.value}set value(e){e!==this.props.value&&(this.props.value=e,this._updateChildrenStat())}connectedCallback(){this._pickedFn=$.bind(this,"child-picked",e=>{log("radio picked: ",e.detail),this.value=e.detail,this.dispatchEvent(new CustomEvent("input"))})}disconnectedCallback(){$.unbind(this,"child-picked",this._pickedFn)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"value":this.value=i}}}
import $ from "../utils.js"
import "./radio-item.js"
export default class Radio extends HTMLElement {
static get observedAttributes() {
return ["value"]
}
props = {
value: null
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: inline-flex; }
</style>
<slot />
`
}
_updateChildrenStat() {
Array.from(this.children).forEach(it => {
if (it.tagName === 'WC-RADIO-ITEM' && it.root) {
if (it.value === this.props.value) {
it.checked = true
} else {
it.checked = false
}
}
})
}
get value() {
return this.props.value
}
set value(val) {
if (val === this.props.value) {
return
}
this.props.value = val
this._updateChildrenStat()
}
connectedCallback() {
this._pickedFn = $.bind(this, 'child-picked', ev => {
log('radio picked: ', ev.detail)
this.value = ev.detail
this.dispatchEvent(new CustomEvent('input'))
})
}
disconnectedCallback() {
$.unbind(this, 'child-picked', this._pickedFn)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'value':
this.value = val
break
}
}
}
if(!customElements.get('wc-radio')){ if(!customElements.get('wc-radio')){
customElements.define('wc-radio', Radio) customElements.define('wc-radio', Radio)

File diff suppressed because one or more lines are too long

View File

@ -1,300 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import $ from"../utils.js";export default class Star extends HTMLElement{static get observedAttributes(){return["value","text","size","color","'allow-half'","'show-value'","starSize","disabled"]}props={value:0,text:[],size:"",color:"","allow-half":!1,"show-value":!1,starSize:32,disabled:!1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:flex;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;cursor:pointer;font-size:14px;--size: 24px}label{display:flex;align-items:center;line-height:1;cursor:inherit}label wc-icon{margin:0 3px;transition:transform .1s easein-out}label wc-icon:hover{transform:scale(1.05)}label span{padding:0 8px;margin:0 3px}:host([size=large]){font-size:16px;--size: 36px}:host([size=medium]){--size: 30px}:host([size=mini]){font-size:12px;--size: 20px}:host([type=danger]) label span{color:var(--color-red-1)}:host([type=primary]) label span{color:var(--color-teal-1)}:host([type=success]) label span{color:var(--color-green-1)}:host([type=default]) label span{color:var(--color-grey-1)}:host([type=info]) label span{color:var(--color-blue-1)}:host([color=purple]) label span{color:var(--color-purple-1)}:host([type=warning]) label span{color:var(--color-orange-1)}:host([disabled]){cursor:default;opacity:.6}:host([disabled]) label wc-icon:hover{transform:none}</style> <label> <wc-icon data-idx="0" is="star" color="grey"></wc-icon> <wc-icon data-idx="1" is="star" color="grey"></wc-icon> <wc-icon data-idx="2" is="star" color="grey"></wc-icon> <wc-icon data-idx="3" is="star" color="grey"></wc-icon> <wc-icon data-idx="4" is="star" color="grey"></wc-icon> <span class="text"></span> </label> ',this.__BOX__=this.root.children[1],this.__STARS__=Array.from(this.__BOX__.children),this.__TEXT__=this.__STARS__.pop()}get value(){return this.props.value}set value(t){var e=+t;(t=e==e&&e>0?e:0)>5&&(t=5),this.props.value=t,this._updateDraw(-1)}_updateDraw(t,e=0){var s="star-half",{value:o,tmp:a={i:0,f:0}}=this.props;-1===t&&(t=Math.floor(o),e=+(o%1).toFixed(1),t>0&&t===o&&(t--,e=1)),this.props["allow-half"]||(e=e>0?1:0),t===a.i&&e===a.f||(e>.5&&(s="star-full"),this.__STARS__.forEach((e,s)=>{e.setAttribute("is",s<t?"star-full":"star"),e.setAttribute("color",s<t?this.props.color:"grey")}),e>0&&(this.__STARS__[t].setAttribute("is",s),this.__STARS__[t].setAttribute("color",this.props.color)),this.props.tmp={i:t,f:e},0===t&&0===e?this.__TEXT__.textContent="":5===this.props.text.length?this.__TEXT__.textContent=this.props.text[t]:this.props["show-value"]&&(this.__TEXT__.textContent=t+e))}connectedCallback(){$.catch(this.__BOX__,"mousemove",t=>{if(!this.props.disabled&&"WC-ICON"===t.target.tagName){let e=+t.target.dataset.idx;this._updateDraw(e,+(t.offsetX/this.props.starSize).toFixed(1))}}),$.catch(this.__BOX__,"click",t=>{var{tmp:e,disabled:s}=this.props;s||"WC-ICON"===t.target.tagName&&(this.props.value=e.i+e.f,this.dispatchEvent(new CustomEvent("input")))}),$.catch(this.__BOX__,"mouseleave",t=>{this.props.disabled||this._updateDraw(-1)})}attributeChangedCallback(t,e,s){if(e!==s)switch(t){case"size":this.props.starSize=this.__STARS__[0].clientWidth;break;case"allow-half":case"show-value":case"disabled":this.props[t]=!0;break;case"color":s&&(this.props.color=s);break;case"text":s&&5===(s=s.split("|")).length&&(this.props.text=s.map(t=>t.trim()));break;case"value":this.value=s}}}
import $ from "../utils.js"
export default class Star extends HTMLElement {
static get observedAttributes() {
return ["value","text","size","color","'allow-half'","'show-value'","starSize","disabled"]
}
props = {
value: 0,
text: [],
size: '',
color: '',
'allow-half': false,
'show-value': false,
starSize: 32, // 星星的宽度, 用于实现半星
disabled: false
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: flex;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
cursor: pointer;
font-size: 14px;
--size: 24px; }
label {
display: flex;
align-items: center;
line-height: 0;
cursor: inherit; }
label wc-icon {
margin: 0 3px;
transition: transform 0.1s easein-out; }
label wc-icon:hover {
transform: scale(1.05); }
label span {
padding: 0 8px;
margin: 0 3px; }
:host([size='large']) {
font-size: 16px;
--size: 36px; }
:host([size='medium']) {
--size: 30px; }
:host([size='mini']) {
font-size: 12px;
--size: 20px; }
:host([color='red']) label span {
color: var(--color-red-1); }
:host([color='teal']) label span {
color: var(--color-teal-1); }
:host([color='green']) label span {
color: var(--color-green-1); }
:host([color='grey']) label span {
color: var(--color-grey-1); }
:host([color='blue']) label span {
color: var(--color-blue-1); }
:host([color='purple']) label span {
color: var(--color-purple-1); }
:host([color='orange']) label span {
color: var(--color-orange-1); }
:host([disabled]) {
cursor: default;
opacity: 0.6; }
:host([disabled]) label wc-icon:hover {
transform: none; }
</style>
<label>
<wc-icon data-idx="0" is="star" color="grey"></wc-icon>
<wc-icon data-idx="1" is="star" color="grey"></wc-icon>
<wc-icon data-idx="2" is="star" color="grey"></wc-icon>
<wc-icon data-idx="3" is="star" color="grey"></wc-icon>
<wc-icon data-idx="4" is="star" color="grey"></wc-icon>
<span class="text"></span>
</label>
`
this.__BOX__ = this.root.children[1]
this.__STARS__ = Array.from(this.__BOX__.children)
this.__TEXT__ = this.__STARS__.pop()
}
get value() {
return this.props.value
}
set value(val) {
var v = +val
var tmp = val >> 0
if (v === v && v > 0) {
val = v
} else {
val = 0
}
if (val > 5) {
val = 5
}
this.props.value = val
this._updateDraw(-1)
}
/**
* 更新图标渲染
* i: int
* f: float
*/
_updateDraw(i, f = 0) {
var _last = 'star-half'
var { value, tmp = { i: 0, f: 0 } } = this.props
if (i === -1) {
i = Math.floor(value)
f = +(value % 1).toFixed(1)
if (i > 0 && i === value) {
i--
f = 1
}
}
if (!this.props['allow-half']) {
f = f > 0 ? 1 : 0
}
// 减少DOM操作
if (i === tmp.i && f === tmp.f) {
return
}
if (f > 0.5) {
_last = 'star-full'
}
this.__STARS__.forEach((it, k) => {
it.setAttribute('is', k < i ? 'star-full' : 'star')
it.setAttribute('color', k < i ? this.props.color : 'grey')
})
if (f > 0) {
this.__STARS__[i].setAttribute('is', _last)
this.__STARS__[i].setAttribute('color', this.props.color)
}
// 缓存结果
this.props.tmp = { i, f }
if (i === 0 && f === 0) {
this.__TEXT__.textContent = ''
} else {
if (this.props.text.length === 5) {
this.__TEXT__.textContent = this.props.text[i]
} else {
if (this.props['show-value']) {
this.__TEXT__.textContent = i + f
}
}
}
}
connectedCallback() {
$.catch(this.__BOX__, 'mousemove', ev => {
if (this.props.disabled) {
return
}
if (ev.target.tagName === 'WC-ICON') {
let idx = +ev.target.dataset.idx
this._updateDraw(idx, +(ev.offsetX / this.props.starSize).toFixed(1))
}
})
$.catch(this.__BOX__, 'click', ev => {
var { tmp, disabled } = this.props
if (disabled) {
return
}
if (ev.target.tagName === 'WC-ICON') {
this.props.value = tmp.i + tmp.f
this.dispatchEvent(new CustomEvent('input'))
}
})
$.catch(this.__BOX__, 'mouseleave', ev => {
if (this.props.disabled) {
return
}
this._updateDraw(-1)
})
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'size':
this.props.starSize = this.__STARS__[0].clientWidth
break
case 'allow-half':
case 'show-value':
case 'disabled':
this.props[name] = true
break
case 'color':
if (val) {
this.props.color = val
}
break
case 'text':
if (val) {
val = val.split('|')
if (val.length === 5) {
this.props.text = val.map(it => it.trim())
}
}
break
case 'value':
this.value = val
break
}
}
}
if(!customElements.get('wc-star')){ if(!customElements.get('wc-star')){
customElements.define('wc-star', Star) customElements.define('wc-star', Star)

View File

@ -1,240 +1,12 @@
/** /**
* *
* @authors yutent (yutent.io@gmail.com) * @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52 * @date 2021-02-05 16:32:07
* @version v1.0.0 * @version v1.0.3
* *
*/ */
import $ from"../utils.js";export default class Switch extends HTMLElement{static get observedAttributes(){return["'active-text'","'inactive-text'","checked","disabled"]}props={"active-text":null,"inactive-text":null,checked:!1,disabled:!1};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block}:host section{display:flex;justify-content:center;align-items:center;line-height:1;white-space:nowrap}:host label{display:flex;align-items:center;width:32px;height:18px;padding:3px;margin:5px;border-radius:21px;background:var(--color-plain-3);cursor:inherit}:host label.checked{flex-direction:row-reverse;background:var(--color-grey-3)}:host .dot{width:12px;height:12px;border-radius:50%;background:#fff}:host([disabled]){cursor:not-allowed;opacity:.6}:host([size=large]) label{width:46px;height:26px;padding:3px 5px}:host([size=large]) .dot{width:18px;height:18px}:host([size=medium]) label{width:38px;height:22px;padding:3px 4px}:host([size=medium]) .dot{width:16px;height:16px}:host([size=mini]) label{width:22px;height:14px;padding:2px}:host([size=mini]) .dot{width:10px;height:10px}:host([type=danger]) label.checked{background:var(--color-red-1)}:host([type=info]) label.checked{background:var(--color-blue-1)}:host([type=success]) label.checked{background:var(--color-green-1)}:host([type=primary]) label.checked{background:var(--color-teal-1)}:host([type=warning]) label.checked{background:var(--color-orange-1)}:host([type=inverse]) label.checked{background:var(--color-dark-1)}:host([color=purple]) label.checked{background:var(--color-purple-1)}</style> <section> <label> <span class="dot"></span> </label> <slot></slot> </section> ',this.__SWITCH__=this.root.lastElementChild.firstElementChild}get value(){return this.props.checked}set value(e){this.checked=e}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e,this.__SWITCH__.classList.toggle("checked",this.props.checked)}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this._handleClick=$.bind(this,"click",e=>{this.disabled||(this.checked=!this.checked,this.checked?null!==this.props["active-text"]&&(this.textContent=this.props["active-text"]):null!==this.props["inactive-text"]&&(this.textContent=this.props["inactive-text"]),this.dispatchEvent(new CustomEvent("input")))})}disconnectedCallback(){$.unbind(this,"click",this._handleClick)}attributeChangedCallback(e,t,i){if(t!==i)switch(e){case"checked":case"disabled":this[e]=!0;break;case"active-text":case"inactive-text":this.props[e]=i+""}}}
import $ from "../utils.js"
export default class Switch extends HTMLElement {
static get observedAttributes() {
return ["'active-text'","'inactive-text'","checked","disabled"]
}
props = {
'active-text': null,
'inactive-text': null,
checked: false,
disabled: false
}
constructor() {
super();
Object.defineProperty(this, 'root', {
value: this.attachShadow({ mode: 'open' }),
writable: true,
enumerable: false,
configurable: true
})
this.root.innerHTML = `<style>* {
box-sizing: border-box;
margin: 0;
padding: 0; }
::before,
::after {
box-sizing: border-box; }
:host {
--color-teal-1: #4db6ac;
--color-teal-2: #26a69a;
--color-teal-3: #009688;
--color-green-1: #81c784;
--color-green-2: #66bb6a;
--color-green-3: #4caf50;
--color-purple-1: #9575cd;
--color-purple-2: #9575cd;
--color-purple-3: #673ab7;
--color-blue-1: #64b5f6;
--color-blue-2: #42a5f5;
--color-blue-3: #2196f3;
--color-red-1: #ff5061;
--color-red-2: #eb3b48;
--color-red-3: #ce3742;
--color-orange-1: #ffb618;
--color-orange-2: #f39c12;
--color-orange-3: #e67e22;
--color-plain-1: #f2f5fc;
--color-plain-2: #e8ebf4;
--color-plain-3: #dae1e9;
--color-grey-1: #bdbdbd;
--color-grey-2: #9e9e9e;
--color-grey-3: #757575;
--color-dark-1: #62778d;
--color-dark-2: #526273;
--color-dark-3: #425064; }
:host {
display: inline-block; }
:host section {
display: flex;
justify-content: center;
align-items: center;
line-height: 0;
white-space: nowrap; }
:host label {
display: flex;
align-items: center;
width: 32px;
height: 18px;
padding: 3px;
margin: 5px;
border-radius: 21px;
background: var(--color-plain-3);
cursor: inherit; }
:host label.checked {
flex-direction: row-reverse;
background: var(--color-grey-3); }
:host .dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: #fff; }
:host([disabled]) {
cursor: not-allowed;
opacity: 0.6; }
:host([size='large']) label {
width: 46px;
height: 26px;
padding: 3px 5px; }
:host([size='large']) .dot {
width: 18px;
height: 18px; }
:host([size='medium']) label {
width: 38px;
height: 22px;
padding: 3px 4px; }
:host([size='medium']) .dot {
width: 16px;
height: 16px; }
:host([size='mini']) label {
width: 22px;
height: 14px;
padding: 2px; }
:host([size='mini']) .dot {
width: 10px;
height: 10px; }
:host([color='red']) label.checked {
background: var(--color-red-1); }
:host([color='blue']) label.checked {
background: var(--color-blue-1); }
:host([color='green']) label.checked {
background: var(--color-green-1); }
:host([color='teal']) label.checked {
background: var(--color-teal-1); }
:host([color='orange']) label.checked {
background: var(--color-orange-1); }
:host([color='dark']) label.checked {
background: var(--color-dark-1); }
:host([color='purple']) label.checked {
background: var(--color-purple-1); }
</style>
<section>
<label>
<span class="dot"></span>
</label>
<slot></slot>
</section>
`
this.__SWITCH__ = this.root.lastElementChild.firstElementChild
}
get value() {
return this.props.checked
}
set value(val) {
this.checked = val
}
get checked() {
return this.props.checked
}
set checked(val) {
this.props.checked = !!val
this.__SWITCH__.classList.toggle('checked', this.props.checked)
}
get disabled() {
return this.props.disabled
}
set disabled(val) {
var type = typeof val
if (val === this.props.disabled) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.disabled = true
this.setAttribute('disabled', '')
} else {
this.props.disabled = false
this.removeAttribute('disabled')
}
}
connectedCallback() {
this._handleClick = $.bind(this, 'click', ev => {
if (this.disabled) {
return
}
this.checked = !this.checked
if (this.checked) {
if (this.props['active-text'] !== null) {
this.textContent = this.props['active-text']
}
} else {
if (this.props['inactive-text'] !== null) {
this.textContent = this.props['inactive-text']
}
}
this.dispatchEvent(new CustomEvent('input'))
})
}
disconnectedCallback() {
$.unbind(this, 'click', this._handleClick)
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {return}
switch (name) {
case 'checked':
case 'disabled':
this[name] = true
break
case 'active-text':
case 'inactive-text':
this.props[name] = val + ''
break
}
}
}
if(!customElements.get('wc-switch')){ if(!customElements.get('wc-switch')){
customElements.define('wc-switch', Switch) customElements.define('wc-switch', Switch)

13
src/lib/form/textarea.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,12 @@
/** /**
* *
* @authors yutent (yutent@doui.cc) * @authors yutent (yutent.io@gmail.com)
* @date 2020-07-07 16:27:17 * @date 2021-02-05 16:32:07
* @version v2.0.1 * @version v1.0.3
* *
*/ */
'use strict' import SVG_DICT from"./svg.js";let dict=SVG_DICT;window.EXT_SVG_DICT&&Object.assign(dict,EXT_SVG_DICT);export default class Icon extends HTMLElement{static get observedAttributes(){return["is"]}props={is:""};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-flex;width:var(--size, 32px);height:var(--size, 32px);color:inherit}:host(:not([is])){display:none}.icon{display:block;fill:currentColor}.icon.load{animation:load 1.5s linear infinite}.icon circle{stroke:currentColor;animation:circle 1.5s ease-in-out infinite}:host([size=large]){width:52px;height:52px}:host([size=medium]){width:36px;height:36px}:host([size=mini]){width:26px;height:26px}:host([red]){color:var(--color-red-1)}:host([blue]){color:var(--color-blue-1)}:host([green]){color:var(--color-green-1)}:host([orange]){color:var(--color-orange-1)}:host([grey]){color:var(--color-grey-1)}:host([dark]){color:var(--color-dark-1)}@keyframes circle{0%{stroke-dasharray:0,3812px;stroke-dashoffset:0}50%{stroke-dasharray:1906px,3812px;stroke-dashoffset:-287px}100%{stroke-dasharray:1906px,3812px;stroke-dashoffset:-2393px}}@keyframes load{to{transform:rotate(360deg)}}</style> <svg class="icon" viewBox="0 0 1024 1024"></svg> ',this.__ICO__=this.root.lastElementChild,this.drawPath()}get is(){return this.props.is}set is(t){t&&this.setAttribute("is",t)}drawPath(){var{is:t}=this.props,o=dict[t];this.__ICO__&&t&&o&&(this.__ICO__.innerHTML="loading"===t?o:`<path d="${o}" />`,this.__ICO__.classList.toggle("load","loading"===t))}attributeChangedCallback(t,o,e){if(o!==e)switch(t){case"is":this.props.is=e,e?this.drawPath():this.removeAttribute("is")}}}
import SVG_DICT from"./svg.js";let dict=SVG_DICT;window.EXT_SVG_DICT&&Object.assign(dict,EXT_SVG_DICT);export default class Icon extends HTMLElement{static get observedAttributes(){return["is"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{is:""},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block;color:inherit}:host(:not([is])){display:none}.icon{display:block;width:var(--size, 32px);height:var(--size, 32px);margin:var(--pad, auto);fill:currentColor}.icon.load{animation:load 1.5s linear infinite}.icon circle{stroke:currentColor;animation:circle 1.5s ease-in-out infinite}:host([size='large']) .icon{width:42px;height:42px}:host([size='medium']) .icon{width:38px;height:38px}:host([size='mini']) .icon{width:20px;height:20px}:host([color='red']){color:#ff5061}:host([color='blue']){color:#64b5f6}:host([color='green']){color:#81c784}:host([color='teal']){color:#4db6ac}:host([color='orange']){color:#ffb618}:host([color='dark']){color:#62778d}:host([color='purple']){color:#9575cd}:host([color='grey']){color:#bdbdbd}@keyframes circle{0%{stroke-dasharray:0, 3812px;stroke-dashoffset:0}50%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-287px}100%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-2393px}}@keyframes load{to{transform:rotate(360deg)}}</style> <svg class=\"icon\" viewBox=\"0 0 1024 1024\"></svg> ",this.__ICO__=this.root.lastElementChild,this.drawPath()}get is(){return this.props.is}set is(o){o&&this.setAttribute("is",o)}drawPath(){var{is:o}=this.props,t=dict[o];this.__ICO__&&o&&t&&(this.__ICO__.innerHTML="loading"===o?t:`<path d="${t}" />`,this.__ICO__.classList.toggle("load","loading"===o))}attributeChangedCallback(o,t,e){if(null!==e&&t!==e)switch(o){case"is":this.props.is=e,e?this.drawPath():this.removeAttribute("is")}}};
if(!customElements.get('wc-icon')){ if(!customElements.get('wc-icon')){
customElements.define('wc-icon', Icon) customElements.define('wc-icon', Icon)

File diff suppressed because one or more lines are too long

764
src/lib/md5.js Normal file
View File

@ -0,0 +1,764 @@
/*
* Fastest md5 implementation around (JKM md5).
* Credits: Joseph Myers
*
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
* @see http://jsperf.com/md5-shootout/7
*/
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause. */
var add32 = function(a, b) {
return (a + b) & 0xffffffff
},
hex_chr = [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'
]
function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t))
return add32((a << s) | (a >>> (32 - s)), b)
}
function md5cycle(x, k) {
var a = x[0],
b = x[1],
c = x[2],
d = x[3]
a += (((b & c) | (~b & d)) + k[0] - 680876936) | 0
a = (((a << 7) | (a >>> 25)) + b) | 0
d += (((a & b) | (~a & c)) + k[1] - 389564586) | 0
d = (((d << 12) | (d >>> 20)) + a) | 0
c += (((d & a) | (~d & b)) + k[2] + 606105819) | 0
c = (((c << 17) | (c >>> 15)) + d) | 0
b += (((c & d) | (~c & a)) + k[3] - 1044525330) | 0
b = (((b << 22) | (b >>> 10)) + c) | 0
a += (((b & c) | (~b & d)) + k[4] - 176418897) | 0
a = (((a << 7) | (a >>> 25)) + b) | 0
d += (((a & b) | (~a & c)) + k[5] + 1200080426) | 0
d = (((d << 12) | (d >>> 20)) + a) | 0
c += (((d & a) | (~d & b)) + k[6] - 1473231341) | 0
c = (((c << 17) | (c >>> 15)) + d) | 0
b += (((c & d) | (~c & a)) + k[7] - 45705983) | 0
b = (((b << 22) | (b >>> 10)) + c) | 0
a += (((b & c) | (~b & d)) + k[8] + 1770035416) | 0
a = (((a << 7) | (a >>> 25)) + b) | 0
d += (((a & b) | (~a & c)) + k[9] - 1958414417) | 0
d = (((d << 12) | (d >>> 20)) + a) | 0
c += (((d & a) | (~d & b)) + k[10] - 42063) | 0
c = (((c << 17) | (c >>> 15)) + d) | 0
b += (((c & d) | (~c & a)) + k[11] - 1990404162) | 0
b = (((b << 22) | (b >>> 10)) + c) | 0
a += (((b & c) | (~b & d)) + k[12] + 1804603682) | 0
a = (((a << 7) | (a >>> 25)) + b) | 0
d += (((a & b) | (~a & c)) + k[13] - 40341101) | 0
d = (((d << 12) | (d >>> 20)) + a) | 0
c += (((d & a) | (~d & b)) + k[14] - 1502002290) | 0
c = (((c << 17) | (c >>> 15)) + d) | 0
b += (((c & d) | (~c & a)) + k[15] + 1236535329) | 0
b = (((b << 22) | (b >>> 10)) + c) | 0
a += (((b & d) | (c & ~d)) + k[1] - 165796510) | 0
a = (((a << 5) | (a >>> 27)) + b) | 0
d += (((a & c) | (b & ~c)) + k[6] - 1069501632) | 0
d = (((d << 9) | (d >>> 23)) + a) | 0
c += (((d & b) | (a & ~b)) + k[11] + 643717713) | 0
c = (((c << 14) | (c >>> 18)) + d) | 0
b += (((c & a) | (d & ~a)) + k[0] - 373897302) | 0
b = (((b << 20) | (b >>> 12)) + c) | 0
a += (((b & d) | (c & ~d)) + k[5] - 701558691) | 0
a = (((a << 5) | (a >>> 27)) + b) | 0
d += (((a & c) | (b & ~c)) + k[10] + 38016083) | 0
d = (((d << 9) | (d >>> 23)) + a) | 0
c += (((d & b) | (a & ~b)) + k[15] - 660478335) | 0
c = (((c << 14) | (c >>> 18)) + d) | 0
b += (((c & a) | (d & ~a)) + k[4] - 405537848) | 0
b = (((b << 20) | (b >>> 12)) + c) | 0
a += (((b & d) | (c & ~d)) + k[9] + 568446438) | 0
a = (((a << 5) | (a >>> 27)) + b) | 0
d += (((a & c) | (b & ~c)) + k[14] - 1019803690) | 0
d = (((d << 9) | (d >>> 23)) + a) | 0
c += (((d & b) | (a & ~b)) + k[3] - 187363961) | 0
c = (((c << 14) | (c >>> 18)) + d) | 0
b += (((c & a) | (d & ~a)) + k[8] + 1163531501) | 0
b = (((b << 20) | (b >>> 12)) + c) | 0
a += (((b & d) | (c & ~d)) + k[13] - 1444681467) | 0
a = (((a << 5) | (a >>> 27)) + b) | 0
d += (((a & c) | (b & ~c)) + k[2] - 51403784) | 0
d = (((d << 9) | (d >>> 23)) + a) | 0
c += (((d & b) | (a & ~b)) + k[7] + 1735328473) | 0
c = (((c << 14) | (c >>> 18)) + d) | 0
b += (((c & a) | (d & ~a)) + k[12] - 1926607734) | 0
b = (((b << 20) | (b >>> 12)) + c) | 0
a += ((b ^ c ^ d) + k[5] - 378558) | 0
a = (((a << 4) | (a >>> 28)) + b) | 0
d += ((a ^ b ^ c) + k[8] - 2022574463) | 0
d = (((d << 11) | (d >>> 21)) + a) | 0
c += ((d ^ a ^ b) + k[11] + 1839030562) | 0
c = (((c << 16) | (c >>> 16)) + d) | 0
b += ((c ^ d ^ a) + k[14] - 35309556) | 0
b = (((b << 23) | (b >>> 9)) + c) | 0
a += ((b ^ c ^ d) + k[1] - 1530992060) | 0
a = (((a << 4) | (a >>> 28)) + b) | 0
d += ((a ^ b ^ c) + k[4] + 1272893353) | 0
d = (((d << 11) | (d >>> 21)) + a) | 0
c += ((d ^ a ^ b) + k[7] - 155497632) | 0
c = (((c << 16) | (c >>> 16)) + d) | 0
b += ((c ^ d ^ a) + k[10] - 1094730640) | 0
b = (((b << 23) | (b >>> 9)) + c) | 0
a += ((b ^ c ^ d) + k[13] + 681279174) | 0
a = (((a << 4) | (a >>> 28)) + b) | 0
d += ((a ^ b ^ c) + k[0] - 358537222) | 0
d = (((d << 11) | (d >>> 21)) + a) | 0
c += ((d ^ a ^ b) + k[3] - 722521979) | 0
c = (((c << 16) | (c >>> 16)) + d) | 0
b += ((c ^ d ^ a) + k[6] + 76029189) | 0
b = (((b << 23) | (b >>> 9)) + c) | 0
a += ((b ^ c ^ d) + k[9] - 640364487) | 0
a = (((a << 4) | (a >>> 28)) + b) | 0
d += ((a ^ b ^ c) + k[12] - 421815835) | 0
d = (((d << 11) | (d >>> 21)) + a) | 0
c += ((d ^ a ^ b) + k[15] + 530742520) | 0
c = (((c << 16) | (c >>> 16)) + d) | 0
b += ((c ^ d ^ a) + k[2] - 995338651) | 0
b = (((b << 23) | (b >>> 9)) + c) | 0
a += ((c ^ (b | ~d)) + k[0] - 198630844) | 0
a = (((a << 6) | (a >>> 26)) + b) | 0
d += ((b ^ (a | ~c)) + k[7] + 1126891415) | 0
d = (((d << 10) | (d >>> 22)) + a) | 0
c += ((a ^ (d | ~b)) + k[14] - 1416354905) | 0
c = (((c << 15) | (c >>> 17)) + d) | 0
b += ((d ^ (c | ~a)) + k[5] - 57434055) | 0
b = (((b << 21) | (b >>> 11)) + c) | 0
a += ((c ^ (b | ~d)) + k[12] + 1700485571) | 0
a = (((a << 6) | (a >>> 26)) + b) | 0
d += ((b ^ (a | ~c)) + k[3] - 1894986606) | 0
d = (((d << 10) | (d >>> 22)) + a) | 0
c += ((a ^ (d | ~b)) + k[10] - 1051523) | 0
c = (((c << 15) | (c >>> 17)) + d) | 0
b += ((d ^ (c | ~a)) + k[1] - 2054922799) | 0
b = (((b << 21) | (b >>> 11)) + c) | 0
a += ((c ^ (b | ~d)) + k[8] + 1873313359) | 0
a = (((a << 6) | (a >>> 26)) + b) | 0
d += ((b ^ (a | ~c)) + k[15] - 30611744) | 0
d = (((d << 10) | (d >>> 22)) + a) | 0
c += ((a ^ (d | ~b)) + k[6] - 1560198380) | 0
c = (((c << 15) | (c >>> 17)) + d) | 0
b += ((d ^ (c | ~a)) + k[13] + 1309151649) | 0
b = (((b << 21) | (b >>> 11)) + c) | 0
a += ((c ^ (b | ~d)) + k[4] - 145523070) | 0
a = (((a << 6) | (a >>> 26)) + b) | 0
d += ((b ^ (a | ~c)) + k[11] - 1120210379) | 0
d = (((d << 10) | (d >>> 22)) + a) | 0
c += ((a ^ (d | ~b)) + k[2] + 718787259) | 0
c = (((c << 15) | (c >>> 17)) + d) | 0
b += ((d ^ (c | ~a)) + k[9] - 343485551) | 0
b = (((b << 21) | (b >>> 11)) + c) | 0
x[0] = (a + x[0]) | 0
x[1] = (b + x[1]) | 0
x[2] = (c + x[2]) | 0
x[3] = (d + x[3]) | 0
}
function md5blk(s) {
var md5blks = [],
i /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] =
s.charCodeAt(i) +
(s.charCodeAt(i + 1) << 8) +
(s.charCodeAt(i + 2) << 16) +
(s.charCodeAt(i + 3) << 24)
}
return md5blks
}
function md5blk_array(a) {
var md5blks = [],
i /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] =
a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24)
}
return md5blks
}
function md51(s) {
var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)))
}
s = s.substring(i - 64)
length = s.length
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3)
}
tail[i >> 2] |= 0x80 << (i % 4 << 3)
if (i > 55) {
md5cycle(state, tail)
for (i = 0; i < 16; i += 1) {
tail[i] = 0
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
lo = parseInt(tmp[2], 16)
hi = parseInt(tmp[1], 16) || 0
tail[14] = lo
tail[15] = hi
md5cycle(state, tail)
return state
}
function md51_array(a) {
var n = a.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk_array(a.subarray(i - 64, i)))
}
// Not sure if it is a bug, however IE10 will always produce a sub array of length 1
// containing the last element of the parent array if the sub array specified starts
// beyond the length of the parent array - weird.
// https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0)
length = a.length
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= a[i] << (i % 4 << 3)
}
tail[i >> 2] |= 0x80 << (i % 4 << 3)
if (i > 55) {
md5cycle(state, tail)
for (i = 0; i < 16; i += 1) {
tail[i] = 0
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
lo = parseInt(tmp[2], 16)
hi = parseInt(tmp[1], 16) || 0
tail[14] = lo
tail[15] = hi
md5cycle(state, tail)
return state
}
function rhex(n) {
var s = '',
j
for (j = 0; j < 4; j += 1) {
s += hex_chr[(n >> (j * 8 + 4)) & 0x0f] + hex_chr[(n >> (j * 8)) & 0x0f]
}
return s
}
function hex(x) {
var i
for (i = 0; i < x.length; i += 1) {
x[i] = rhex(x[i])
}
return x.join('')
}
// In some cases the fast add32 function cannot be used..
if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
add32 = function(x, y) {
var lsw = (x & 0xffff) + (y & 0xffff),
msw = (x >> 16) + (y >> 16) + (lsw >> 16)
return (msw << 16) | (lsw & 0xffff)
}
}
// ---------------------------------------------------
/**
* ArrayBuffer slice polyfill.
*
* @see https://github.com/ttaubert/node-arraybuffer-slice
*/
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
;(function() {
function clamp(val, length) {
val = val | 0 || 0
if (val < 0) {
return Math.max(val + length, 0)
}
return Math.min(val, length)
}
ArrayBuffer.prototype.slice = function(from, to) {
var length = this.byteLength,
begin = clamp(from, length),
end = length,
num,
target,
targetArray,
sourceArray
if (to !== undefined) {
end = clamp(to, length)
}
if (begin > end) {
return new ArrayBuffer(0)
}
num = end - begin
target = new ArrayBuffer(num)
targetArray = new Uint8Array(target)
sourceArray = new Uint8Array(this, begin, num)
targetArray.set(sourceArray)
return target
}
})()
}
// ---------------------------------------------------
/**
* Helpers.
*/
function toUtf8(str) {
str += ''
if (/[\u0080-\uFFFF]/.test(str)) {
str = unescape(encodeURIComponent(str))
}
return str
}
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
var length = str.length,
buff = new ArrayBuffer(length),
arr = new Uint8Array(buff),
i
for (i = 0; i < length; i += 1) {
arr[i] = str.charCodeAt(i)
}
return returnUInt8Array ? arr : buff
}
function arrayBuffer2Utf8Str(buff) {
return String.fromCharCode.apply(null, new Uint8Array(buff))
}
function concatenateArrayBuffers(first, second, returnUInt8Array) {
var result = new Uint8Array(first.byteLength + second.byteLength)
result.set(new Uint8Array(first))
result.set(new Uint8Array(second), first.byteLength)
return returnUInt8Array ? result : result.buffer
}
function hexToBinaryString(hex) {
var bytes = [],
length = hex.length,
x
for (x = 0; x < length - 1; x += 2) {
bytes.push(parseInt(hex.substr(x, 2), 16))
}
return String.fromCharCode.apply(String, bytes)
}
// ---------------------------------------------------
/**
* SparkMD5 OOP implementation.
*
* Use this class to perform an incremental md5, otherwise use the
* static methods instead.
*/
function SparkMD5() {
// call reset to init the instance
this.reset()
}
/**
* Appends a string.
* A conversion will be applied if an utf8 string is detected.
*
* @param {String} str The string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.append = function(str) {
// Converts the string to utf8 bytes if necessary
// Then append as binary
this.appendBinary(toUtf8(str))
return this
}
/**
* Appends a binary string.
*
* @param {String} contents The binary string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.appendBinary = function(contents) {
this._buff += contents
this._length += contents.length
var length = this._buff.length,
i
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)))
}
this._buff = this._buff.substring(i - 64)
return this
}
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.prototype.end = function(raw) {
var buff = this._buff,
length = buff.length,
i,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
ret
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3)
}
this._finish(tail, length)
ret = hex(this._hash)
if (raw) {
ret = hexToBinaryString(ret)
}
this.reset()
return ret
}
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.reset = function() {
this._buff = ''
this._length = 0
this._hash = [1732584193, -271733879, -1732584194, 271733878]
return this
}
/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
SparkMD5.prototype.getState = function() {
return {
buff: this._buff,
length: this._length,
hash: this._hash
}
}
/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.setState = function(state) {
this._buff = state.buff
this._length = state.length
this._hash = state.hash
return this
}
/**
* Releases memory used by the incremental buffer and other additional
* resources. If you plan to use the instance again, use reset instead.
*/
SparkMD5.prototype.destroy = function() {
delete this._hash
delete this._buff
delete this._length
}
/**
* Finish the final calculation based on the tail.
*
* @param {Array} tail The tail (will be modified)
* @param {Number} length The length of the remaining buffer
*/
SparkMD5.prototype._finish = function(tail, length) {
var i = length,
tmp,
lo,
hi
tail[i >> 2] |= 0x80 << (i % 4 << 3)
if (i > 55) {
md5cycle(this._hash, tail)
for (i = 0; i < 16; i += 1) {
tail[i] = 0
}
}
// Do the final computation based on the tail and length
// Beware that the final length may not fit in 32 bits so we take care of that
tmp = this._length * 8
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
lo = parseInt(tmp[2], 16)
hi = parseInt(tmp[1], 16) || 0
tail[14] = lo
tail[15] = hi
md5cycle(this._hash, tail)
}
/**
* Performs the md5 hash on a string.
* A conversion will be applied if utf8 string is detected.
*
* @param {String} str The string
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.hash = function(str, raw) {
// Converts the string to utf8 bytes if necessary
// Then compute it using the binary function
return SparkMD5.hashBinary(toUtf8(str), raw)
}
/**
* Performs the md5 hash on a binary string.
*
* @param {String} content The binary string
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.hashBinary = function(content, raw) {
var hash = md51(content),
ret = hex(hash)
return raw ? hexToBinaryString(ret) : ret
}
// ---------------------------------------------------
/**
* SparkMD5 OOP implementation for array buffers.
*
* Use this class to perform an incremental md5 ONLY for array buffers.
*/
SparkMD5.ArrayBuffer = function() {
// call reset to init the instance
this.reset()
}
/**
* Appends an array buffer.
*
* @param {ArrayBuffer} arr The array to be appended
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.append = function(arr) {
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
length = buff.length,
i
this._length += arr.byteLength
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)))
}
this._buff =
i - 64 < length
? new Uint8Array(buff.buffer.slice(i - 64))
: new Uint8Array(0)
return this
}
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
*
* @param {Boolean} raw True to get the raw string, false to get the hex string
*
* @return {String} The result
*/
SparkMD5.ArrayBuffer.prototype.end = function(raw) {
var buff = this._buff,
length = buff.length,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
i,
ret
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff[i] << (i % 4 << 3)
}
this._finish(tail, length)
ret = hex(this._hash)
if (raw) {
ret = hexToBinaryString(ret)
}
this.reset()
return ret
}
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.reset = function() {
this._buff = new Uint8Array(0)
this._length = 0
this._hash = [1732584193, -271733879, -1732584194, 271733878]
return this
}
/**
* Gets the internal state of the computation.
*
* @return {Object} The state
*/
SparkMD5.ArrayBuffer.prototype.getState = function() {
var state = SparkMD5.prototype.getState.call(this)
// Convert buffer to a string
state.buff = arrayBuffer2Utf8Str(state.buff)
return state
}
/**
* Gets the internal state of the computation.
*
* @param {Object} state The state
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.setState = function(state) {
// Convert string to buffer
state.buff = utf8Str2ArrayBuffer(state.buff, true)
return SparkMD5.prototype.setState.call(this, state)
}
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish
/**
* Performs the md5 hash on an array buffer.
*
* @param {ArrayBuffer} arr The array buffer
* @param {Boolean} [raw] True to get the raw string, false to get the hex one
*
* @return {String} The result
*/
SparkMD5.ArrayBuffer.hash = function(arr, raw) {
var hash = md51_array(new Uint8Array(arr)),
ret = hex(hash)
return raw ? hexToBinaryString(ret) : ret
}
var _sparkIns = new SparkMD5()
export function md5(str) {
_sparkIns.append(str)
return _sparkIns.end()
}
export function md5Sum(binStr) {
_sparkIns.appendBinary(binStr)
return _sparkIns.end()
}
export default _sparkIns

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
function noop(){}export default{nextTick:function(){let t=[];let e=document.createTextNode("\x3c!-- --\x3e");new MutationObserver(function(){let e=t.length;for(let n=0;n<e;n++)t[n]();t=t.slice(e)}).observe(e,{characterData:!0});let n=!1;return function(i){t.push(i),n=!n,e.data=n}}(),each(t,e){if(t)if(Array.isArray(t))for(let n,i=0;(n=t[i++])&&!1!==e(n,i-1););else for(let n in t)if(t.hasOwnProperty(n)&&!1===e(t[n],n))break},bind(t,e,n=noop,i=!1){let o=e.split(",");return this.each(o,function(e){e=e.trim(),t.addEventListener(e,n,i)}),n},catch(t,e,n,i){return this.bind(t,e,function(t){t.stopPropagation(),n&&n(t)},i)},unbind(t,e,n=noop,i=!1){let o=e.split(",");this.each(o,function(e){e=e.trim(),t.removeEventListener(e,n,i)})},outside(t,e=noop){return this.bind(document,"mousedown",n=>{if(n)if(n.path){for(var i=n.path.concat();i.length>3;)if(i.shift()===t)return}else{var o=n.explicitOriginalTarget||n.target;if(t===o||t.contains(o)||t.root&&t.root.contains(o))return}e(n)})},clearOutside(t=noop){this.unbind(document,"mousedown",t)}}; function noop(){}export default{nextTick:function(){let t=[];let e=document.createTextNode("\x3c!-- --\x3e");new MutationObserver((function(){let e=t.length;for(let n=0;n<e;n++)t[n]();t=t.slice(e)})).observe(e,{characterData:!0});let n=!1;return function(i){t.push(i),n=!n,e.data=n}}(),offset(t){try{var e=t.getBoundingClientRect();if(e.width||e.height||t.getClientRects().length){var n=t.ownerDocument,i=n.documentElement,o=n.defaultView;return{top:e.top+o.pageYOffset-i.clientTop,left:e.left+o.pageXOffset-i.clientLeft}}}catch(t){return{left:0,top:0}}},each(t,e){if(t)if(Array.isArray(t))for(let n,i=0;(n=t[i++])&&!1!==e(n,i-1););else for(let n in t)if(t.hasOwnProperty(n)&&!1===e(t[n],n))break},bind(t,e,n=noop,i=!1){let o=e.split(",");return this.each(o,(function(e){e=e.trim(),t.addEventListener(e,n,i)})),n},catch(t,e,n,i){return this.bind(t,e,(function(t){t.stopPropagation(),n&&n(t)}),i)},unbind(t,e,n=noop,i=!1){let o=e.split(",");this.each(o,(function(e){e=e.trim(),t.removeEventListener(e,n,i)}))},outside(t,e=noop){return this.bind(document,"mousedown",n=>{if(n)if(n.path){for(var i=n.path.concat();i.length>3;)if(i.shift()===t)return}else{var o=n.explicitOriginalTarget||n.target;if(t===o||t.contains(o)||t.root&&t.root.contains(o))return}e(n)})},clearOutside(t=noop){this.unbind(document,"mousedown",t)}};

View File

@ -9,7 +9,7 @@ const path = require('path')
const fs = require('iofs') const fs = require('iofs')
require('./tools/init') require('./tools/init')
const { createMainWindow, createFloatWindow } = require('./tools/window') const { createMainWindow, createViewWindow } = require('./tools/window')
const createMenu = require('./tools/menu') const createMenu = require('./tools/menu')
const Socket = require('./tools/socket') const Socket = require('./tools/socket')
@ -44,13 +44,13 @@ protocol.registerSchemesAsPrivileged([
/* ----------------------------------------------------- */ /* ----------------------------------------------------- */
// app.dock.hide()
// 初始化应用 // 初始化应用
app.once('ready', () => { app.once('ready', () => {
// 注册协议 // 注册协议
protocol.registerStreamProtocol('app', function(req, cb) { protocol.registerStreamProtocol('app', function(req, cb) {
var file = decodeURIComponent(req.url.replace(/^app:\/\/local\//, '')) var file = decodeURIComponent(req.url.replace(/^app:\/\/local\//, ''))
.replace(/\#.*$/, '')
.replace(/\?.*$/, '')
var ext = path.extname(file) var ext = path.extname(file)
file = path.resolve(ROOT, file) file = path.resolve(ROOT, file)
@ -69,7 +69,7 @@ app.once('ready', () => {
var ext = path.extname(file) var ext = path.extname(file)
file = path.resolve(CACHE_DIR, file) file = path.resolve(CACHE_DIR, file)
console.log(file)
cb({ cb({
data: fs.origin.createReadStream(file), data: fs.origin.createReadStream(file),
mimeType: MIME_TYPES[ext] || MIME_TYPES.all, mimeType: MIME_TYPES[ext] || MIME_TYPES.all,
@ -81,14 +81,13 @@ app.once('ready', () => {
// 创建浏览器窗口 // 创建浏览器窗口
app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png')) app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png'))
// app.__float__ = createFloatWindow()
createMenu(app.__main__) createMenu(app.__main__)
Socket(app) Socket(app, createViewWindow)
app.__main__.on('closed', () => { app.__main__.on('closed', () => {
app.__main__ = null app.__main__ = null
app.__float__ = null app.__view__ = null
app.exit() app.exit()
}) })

View File

@ -4,7 +4,7 @@
* @date 2021/01/04 14:58:46 * @date 2021/01/04 14:58:46
*/ */
const { app, ipcMain, net } = require('electron') const { app, ipcMain } = require('electron')
const fs = require('iofs') const fs = require('iofs')
const path = require('path') const path = require('path')
const Epub = require('epub') const Epub = require('epub')
@ -13,36 +13,45 @@ const HOME = path.resolve(app.getPath('userData'))
const DB_FILE = path.join(HOME, 'app.cache') const DB_FILE = path.join(HOME, 'app.cache')
const CACHE_DIR = path.join(HOME, 'book_cache') const CACHE_DIR = path.join(HOME, 'book_cache')
function fetch(url) { module.exports = function(app, createViewWindow) {
return new Promise((y, n) => {
var conn = net.request(url)
var r = []
conn.on('response', res => {
res.on('data', c => {
r.push(c)
})
res.on('end', _ => {
y(Buffer.concat(r).toString())
})
})
conn.on('error', e => {
n(e)
})
conn.end()
})
}
module.exports = function(app) {
ipcMain.on('app', (ev, conn) => { ipcMain.on('app', (ev, conn) => {
switch (conn.type) { switch (conn.type) {
case 'fetch': case 'get-books':
fetch(conn.data).then(r => { ev.returnValue = JSON.parse(fs.cat(DB_FILE))
ev.returnValue = r break
})
case 'save-books':
fs.echo(JSON.stringify(conn.data), DB_FILE)
ev.returnValue = true
break
case 'read':
let params = JSON.parse(Buffer.from(conn.data, 'base64'))
if (app.__view__) {
// 打开同一个文档, 直接忽略
if (app.__view__.__title__ === params.title) {
app.__view__.focus()
ev.returnValue = true
return
}
app.__view__.destroy()
}
app.__view__ = createViewWindow(conn.data)
app.__view__.__title__ = params.title
ev.returnValue = true
break
case 'delete-book':
let dir = path.join(CACHE_DIR, conn.data)
fs.rm(dir, true)
ev.returnValue = true
break
case 'save-cover':
let file = path.join(CACHE_DIR, conn.data.name, 'cover.webp')
let buf = Buffer.from(conn.data.base64, 'base64')
fs.echo(buf, file)
ev.returnValue = true
break break
case 'parse-book': case 'parse-book':
@ -51,8 +60,11 @@ module.exports = function(app) {
let cache = JSON.parse(fs.cat(DB_FILE)) let cache = JSON.parse(fs.cat(DB_FILE))
eb.on('end', async _ => { eb.on('end', async _ => {
let { title, cover } = eb.metadata let { title } = eb.metadata
let cover = ''
let dir = path.join(CACHE_DIR, title) let dir = path.join(CACHE_DIR, title)
let dict = {}
let toc = []
function saveImage(id, name) { function saveImage(id, name) {
return new Promise(done => { return new Promise(done => {
@ -65,12 +77,32 @@ module.exports = function(app) {
function saveHtml(id, name) { function saveHtml(id, name) {
return new Promise(done => { return new Promise(done => {
eb.getChapter(id, (err, txt) => { eb.getChapterRaw(id, (err, txt) => {
// txt = (txt + '').replace( let m = (txt + '').match(/<body[^>]*?>([\w\W]+)<\/body>/)
// /<(?!img|image)([\w\-]+)[^>]*>/g, if (m) {
// '<$1>' let htm = m[1]
// ) .replace(
fs.echo(txt, path.join(dir, name.replace('.xhtml', '.html'))) /<(?!img|image)([\w\-]+)[^>]*?( id="[^\s]*?")?[^>]*?>/g,
'<$1$2>'
)
.replace(/<pre><code>/g, '<wc-code>')
.replace(/<\/code><\/pre>/g, '</wc-code>')
htm = htm
.replace(/<pre>/g, '<wc-code>')
.replace(/<\/pre>/g, '</wc-code>')
htm = htm
.replace(/<wc-code>([\w\W]*?)<\/wc-code>/g, function(m, s) {
s = s.replace(/<\/?\w+>/g, '')
return `<wc-code>${s}</wc-code>`
})
.trim()
fs.echo(htm, path.join(dir, name.replace('.xhtml', '.html')))
} else {
console.log(id, name, txt)
}
done() done()
}) })
}) })
@ -85,7 +117,10 @@ module.exports = function(app) {
break break
case 'application/x-dtbncx+xml': case 'application/x-dtbncx+xml':
fs.echo(JSON.stringify(eb.toc), path.join(dir, 'toc.json')) eb.toc.forEach(_ => {
dict[_.id] = _
})
break break
case 'application/xhtml+xml': case 'application/xhtml+xml':
@ -95,7 +130,7 @@ module.exports = function(app) {
default: default:
if (it['media-type'].startsWith('image')) { if (it['media-type'].startsWith('image')) {
saveImage(it.id, it.href) saveImage(it.id, it.href)
if (it.href.includes(cover)) { if (it.href.includes('cover')) {
cover = it.href cover = it.href
} }
} }
@ -103,7 +138,48 @@ module.exports = function(app) {
} }
} }
toc = eb.flow.map((it, i) => {
let tmp = dict[it.id] || { level: i === 0 ? i : undefined }
if (tmp.level === undefined) {
tmp.level = 1
}
if (it.id === 'titlepage') {
it.level = 0
it.title = '封面'
} else {
it.level = tmp.level
let cp
if (it.title) {
cp = it.title
} else {
cp = fs
.cat(path.join(dir, it.href.replace('.xhtml', '.html')))
.toString()
cp = cp.split(/[\r\n]/).shift()
cp = cp.replace(/<\/?[\w\-]+[^>]*?>/g, '').trim()
}
it.title = cp
.slice(0, 20)
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
}
return it
})
fs.echo(JSON.stringify(toc), path.join(dir, 'toc.json'))
if (!cover) {
cover = 'cover.webp'
app.__main__.webContents.send('app', {
type: 'draw-cover',
data: title
})
}
let info = { title, cover } let info = { title, cover }
if (cache[cate]) { if (cache[cate]) {
if (!cache[cate].some(it => it.title === title)) { if (!cache[cate].some(it => it.title === title)) {
cache[cate].push(info) cache[cate].push(info)

View File

@ -4,7 +4,7 @@
* @date 2020/12/10 14:57:49 * @date 2020/12/10 14:57:49
*/ */
const { BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
/** /**
* 应用主窗口 * 应用主窗口
@ -29,28 +29,28 @@ exports.createMainWindow = function(icon) {
win.on('ready-to-show', _ => { win.on('ready-to-show', _ => {
win.show() win.show()
win.openDevTools() // win.openDevTools()
}) })
win.on('close', ev => { win.on('close', ev => {
if (app.__view__) {
ev.preventDefault() ev.preventDefault()
win.hide() win.hide()
}
}) })
return win return win
} }
// 创建悬浮窗口 // 创建悬浮窗口
exports.createFloatWindow = function() { exports.createViewWindow = function(params) {
var win = new BrowserWindow({ var win = new BrowserWindow({
width: 280, width: 1136,
height: 360, height: 768,
resizable: false, minWidth: 1136,
maximizable: false, minHeight: 768,
frame: false, // show: false,
show: false, title: 'E-pub Reader',
vibrancy: 'hud',
visualEffectState: 'active',
webPreferences: { webPreferences: {
experimentalFeatures: true, experimentalFeatures: true,
nodeIntegration: true, nodeIntegration: true,
@ -60,11 +60,11 @@ exports.createFloatWindow = function() {
// win.openDevTools() // win.openDevTools()
win.on('blur', ev => { win.loadURL('app://local/view.html?' + params)
win.hide()
})
win.loadURL('app://local/float.html') win.on('closed', ev => {
app.__view__ = null
})
return win return win
} }

View File

@ -6,29 +6,26 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title></title> <title></title>
<link href="/lib/css/reset-basic.css" rel="stylesheet"> <link href="/lib/css/reset-basic.css" rel="stylesheet">
<link href="/css/float.css" rel="stylesheet"> <link href="/css/view.css" rel="stylesheet">
<script src="/js/float.js" type="module"></script> <script src="/js/view.js" type="module"></script>
</head> </head>
<body class="noselect"> <body>
<div class="app" anot="app"> <div class="app" anot="app">
<wc-scroll class="list"> <wc-scroll class="toc noselect" ref="toc">
<section class="item" :for="it in list"> <item
<div class="info"> :for="it in toc"
<h3 class="text-ell" :text="it.name"></h3> :class="{['lev-' + it.level]: 1, active: it.title === curr}"
<cite :text="it.code"></cite> @click="viewChapter(it)"
</div> >
<span class="text-ell" :attr-title="it.title" :text="it.title"></span>
</item>
</wc-scroll>
<div class="today"> <wc-scroll class="chapter-box" ref="chapter">
<span class="money" :text="'¥' + it.cm"></span> <div class="chapter">
<span <article class="detail" :html="chapter"></article>
class="percent"
:class="{red: it.cp > 0, green: it.cp < 0}"
:text="it.cp + '%'">
</span>
</div> </div>
</section>
<section :if="list.length === 0" class="item">啥基都没有...</section>
</wc-scroll> </wc-scroll>
</div> </div>

View File

@ -1 +0,0 @@
/Users/yutent/Library/Application Support/org.bytedo.epub/app.cache