icons
|
@ -1,10 +1,18 @@
|
|||
LESS := $(shell npm bin)/lessc
|
||||
APP := app.css
|
||||
ICONS := js/lib/icons.js
|
||||
|
||||
all: $(APP)
|
||||
|
||||
icons: $(ICONS)
|
||||
|
||||
$(ICONS): icons/*
|
||||
./svg2js.sh icons > $@
|
||||
|
||||
$(APP): css/*
|
||||
$(LESS) css/app.less > $@
|
||||
|
||||
watch: all
|
||||
while inotifywait -e MODIFY -r css js ; do make $^ ; done
|
||||
|
||||
.PHONY: all watch icons
|
||||
|
|
76
app/app.css
|
@ -1,9 +1,10 @@
|
|||
html {
|
||||
background-color: #fff;
|
||||
font-family: lato, sans-serif;
|
||||
}
|
||||
body {
|
||||
background-color: #888;
|
||||
font-family: lato, sans-serif;
|
||||
line-height: 1.3;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px #000;
|
||||
max-width: 800px;
|
||||
|
@ -17,6 +18,29 @@ body > header,
|
|||
body > footer {
|
||||
box-shadow: 0 0 3px #000;
|
||||
}
|
||||
input,
|
||||
select,
|
||||
button {
|
||||
color: inherit;
|
||||
}
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon {
|
||||
width: 24px;
|
||||
}
|
||||
.icon path:not([fill]),
|
||||
.icon polygon:not([fill]),
|
||||
.icon circle:not([fill]) {
|
||||
fill: currentColor;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Lato';
|
||||
src: url('font/LatoLatin-Regular.woff2') format('woff2');
|
||||
|
@ -71,6 +95,10 @@ nav ul li.active {
|
|||
#player:not([data-flags~=repeat]) .repeat {
|
||||
opacity: 0.5;
|
||||
}
|
||||
#player button {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.component {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
@ -86,16 +114,25 @@ nav ul li.active {
|
|||
.component .grid li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.component .grid li h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.component .grid li:nth-child(odd) {
|
||||
background-color: #666;
|
||||
background-color: #555;
|
||||
}
|
||||
.component .grid button {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
#queue {
|
||||
height: 100%;
|
||||
|
@ -112,16 +149,25 @@ nav ul li.active {
|
|||
#queue .grid li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
#queue .grid li h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#queue .grid li:nth-child(odd) {
|
||||
background-color: #666;
|
||||
background-color: #555;
|
||||
}
|
||||
#queue .grid button {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
#queue li {
|
||||
display: flex;
|
||||
|
@ -148,16 +194,25 @@ nav ul li.active {
|
|||
#library .grid li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
#library .grid li h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#library .grid li:nth-child(odd) {
|
||||
background-color: #666;
|
||||
background-color: #555;
|
||||
}
|
||||
#library .grid button {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
#fs {
|
||||
height: 100%;
|
||||
|
@ -174,14 +229,23 @@ nav ul li.active {
|
|||
#fs .grid li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
#fs .grid li h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#fs .grid li:nth-child(odd) {
|
||||
background-color: #666;
|
||||
background-color: #555;
|
||||
}
|
||||
#fs .grid button {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
html {
|
||||
background-color: #fff;
|
||||
font-family: lato, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #888;
|
||||
font-family: lato, sans-serif;
|
||||
line-height: 1.3;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 1px #000;
|
||||
max-width: 800px;
|
||||
|
@ -19,6 +20,32 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
input, select, button {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
|
||||
path, polygon, circle {
|
||||
&:not([fill]) {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@import "font.less";
|
||||
@import "main.less";
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
h2 {
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
@ -26,7 +29,14 @@
|
|||
}
|
||||
|
||||
li:nth-child(odd) {
|
||||
background-color: #666;
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
button {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,4 +8,9 @@
|
|||
&:not([data-state=play]) .pause { display: none; }
|
||||
&[data-state=play] .play { display: none; }
|
||||
&:not([data-flags~=random]) .random, &:not([data-flags~=repeat]) .repeat { opacity: 0.5; }
|
||||
|
||||
button {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
1
app/icons/close-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M14.59,8L12,10.59L9.41,8L8,9.41L10.59,12L8,14.59L9.41,16L12,13.41L14.59,16L16,14.59L13.41,12L16,9.41L14.59,8Z" /></svg>
|
After Width: | Height: | Size: 587 B |
1
app/icons/close-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z" /></svg>
|
After Width: | Height: | Size: 495 B |
1
app/icons/close.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" /></svg>
|
After Width: | Height: | Size: 404 B |
1
app/icons/fast-forward.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,6V18L21.5,12M4,18L12.5,12L4,6V18Z" /></svg>
|
After Width: | Height: | Size: 332 B |
1
app/icons/minus-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7,13H17V11H7" /></svg>
|
After Width: | Height: | Size: 475 B |
1
app/icons/minus-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17,13H7V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>
|
After Width: | Height: | Size: 385 B |
1
app/icons/minus.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,13H5V11H19V13Z" /></svg>
|
After Width: | Height: | Size: 313 B |
1
app/icons/pause-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,16V8H15V16H13M9,16V8H11V16H9M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" /></svg>
|
After Width: | Height: | Size: 470 B |
1
app/icons/pause-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M15,16H13V8H15M11,16H9V8H11M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>
|
After Width: | Height: | Size: 398 B |
1
app/icons/pause.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M14,19H18V5H14M6,19H10V5H6V19Z" /></svg>
|
After Width: | Height: | Size: 325 B |
1
app/icons/play-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z" /></svg>
|
After Width: | Height: | Size: 489 B |
1
app/icons/play-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M10,16.5V7.5L16,12M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>
|
After Width: | Height: | Size: 389 B |
1
app/icons/play.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M8,5.14V19.14L19,12.14L8,5.14Z" /></svg>
|
After Width: | Height: | Size: 325 B |
1
app/icons/plus-circle-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,7H11V11H7V13H11V17H13V13H17V11H13V7Z" /></svg>
|
After Width: | Height: | Size: 502 B |
1
app/icons/plus-circle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17,13H13V17H11V13H7V11H11V7H13V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg>
|
After Width: | Height: | Size: 408 B |
1
app/icons/plus.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" /></svg>
|
After Width: | Height: | Size: 336 B |
1
app/icons/repeat.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17,17H7V14L3,18L7,22V19H19V13H17M7,7H17V10L21,6L17,2V5H5V11H7V7Z" /></svg>
|
After Width: | Height: | Size: 360 B |
1
app/icons/rewind.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M11.5,12L20,18V6M11,18V6L2.5,12L11,18Z" /></svg>
|
After Width: | Height: | Size: 333 B |
1
app/icons/shuffle.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M14.83,13.41L13.42,14.82L16.55,17.95L14.5,20H20V14.5L17.96,16.54L14.83,13.41M14.5,4L16.54,6.04L4,18.59L5.41,20L17.96,7.46L20,9.5V4M10.59,9.17L5.41,4L4,5.41L9.17,10.58L10.59,9.17Z" /></svg>
|
After Width: | Height: | Size: 473 B |
|
@ -15,12 +15,12 @@
|
|||
<span class="artist-album"></span>
|
||||
</div>
|
||||
<span class="elapsed"></span>/<span class="duration"></span>
|
||||
<button class="play">⏯️▶</button>
|
||||
<button class="pause">⏸️</button>
|
||||
<button class="prev">⏮ ⏮️</button>
|
||||
<button class="next">⏭️</button>
|
||||
<button class="repeat">🔁</button>
|
||||
<button class="random">🔀</button>
|
||||
<button class="play"></button>
|
||||
<button class="pause"></button>
|
||||
<button class="prev"></button>
|
||||
<button class="next"></button>
|
||||
<button class="repeat"></button>
|
||||
<button class="random"></button>
|
||||
</section>
|
||||
</header>
|
||||
<main>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import icons from "./icons.js";
|
||||
|
||||
export function node(name, attrs, content, parent) {
|
||||
let n = document.createElement(name);
|
||||
Object.assign(n, attrs);
|
||||
|
@ -9,8 +11,32 @@ export function node(name, attrs, content, parent) {
|
|||
return n;
|
||||
}
|
||||
|
||||
export function icon(type, parent) {
|
||||
let str = icons[type];
|
||||
if (!str) {
|
||||
console.error("Bad icon type '%s'", type);
|
||||
return node("span", {}, "‽");
|
||||
}
|
||||
|
||||
let tmp = node("div");
|
||||
tmp.innerHTML = str;
|
||||
let s = tmp.querySelector("svg");
|
||||
if (!s) { throw new Error(`Bad icon source for type '${type}'`); }
|
||||
|
||||
s.classList.add("icon");
|
||||
s.classList.add(`icon-${type}`);
|
||||
|
||||
parent && parent.appendChild(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
export function button(attrs, content, parent) {
|
||||
return node("button", attrs, content, parent);
|
||||
let result = node("button", attrs, content, parent);
|
||||
if (attrs && attrs.icon) {
|
||||
let i = icon(attrs.icon);
|
||||
result.insertBefore(i, result.firstChild);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function clear(node) {
|
||||
|
|
59
app/js/lib/icons.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
let ICONS={};
|
||||
ICONS["play-circle-outline"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M10,16.5L16,12L10,7.5V16.5Z"/>
|
||||
</svg>`;
|
||||
ICONS["shuffle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M14.83,13.41L13.42,14.82L16.55,17.95L14.5,20H20V14.5L17.96,16.54L14.83,13.41M14.5,4L16.54,6.04L4,18.59L5.41,20L17.96,7.46L20,9.5V4M10.59,9.17L5.41,4L4,5.41L9.17,10.58L10.59,9.17Z"/>
|
||||
</svg>`;
|
||||
ICONS["minus-circle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M17,13H7V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"/>
|
||||
</svg>`;
|
||||
ICONS["rewind"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M11.5,12L20,18V6M11,18V6L2.5,12L11,18Z"/>
|
||||
</svg>`;
|
||||
ICONS["pause"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M14,19H18V5H14M6,19H10V5H6V19Z"/>
|
||||
</svg>`;
|
||||
ICONS["pause-circle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M15,16H13V8H15M11,16H9V8H11M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"/>
|
||||
</svg>`;
|
||||
ICONS["close-circle-outline"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M14.59,8L12,10.59L9.41,8L8,9.41L10.59,12L8,14.59L9.41,16L12,13.41L14.59,16L16,14.59L13.41,12L16,9.41L14.59,8Z"/>
|
||||
</svg>`;
|
||||
ICONS["close"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"/>
|
||||
</svg>`;
|
||||
ICONS["minus"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M19,13H5V11H19V13Z"/>
|
||||
</svg>`;
|
||||
ICONS["close-circle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z"/>
|
||||
</svg>`;
|
||||
ICONS["repeat"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M17,17H7V14L3,18L7,22V19H19V13H17M7,7H17V10L21,6L17,2V5H5V11H7V7Z"/>
|
||||
</svg>`;
|
||||
ICONS["play"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M8,5.14V19.14L19,12.14L8,5.14Z"/>
|
||||
</svg>`;
|
||||
ICONS["pause-circle-outline"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M13,16V8H15V16H13M9,16V8H11V16H9M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z"/>
|
||||
</svg>`;
|
||||
ICONS["plus"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"/>
|
||||
</svg>`;
|
||||
ICONS["fast-forward"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M13,6V18L21.5,12M4,18L12.5,12L4,6V18Z"/>
|
||||
</svg>`;
|
||||
ICONS["minus-circle-outline"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7,13H17V11H7"/>
|
||||
</svg>`;
|
||||
ICONS["plus-circle-outline"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,7H11V11H7V13H11V17H13V13H17V11H13V7Z"/>
|
||||
</svg>`;
|
||||
ICONS["plus-circle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M17,13H13V17H11V13H7V11H11V7H13V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"/>
|
||||
</svg>`;
|
||||
ICONS["play-circle"] = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 24 24">
|
||||
<path d="M10,16.5V7.5L16,12M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z"/>
|
||||
</svg>`;
|
||||
export default ICONS;
|
|
@ -37,7 +37,7 @@ function formatTitle(type, data) {
|
|||
}
|
||||
|
||||
function playButton(id, parent) {
|
||||
let button = html.button({className:"play"}, "▶", parent);
|
||||
let button = html.button({icon:"play", title:"Play"}, "", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
await mpd.command(`playid ${id}`);
|
||||
player.update();
|
||||
|
@ -45,7 +45,7 @@ function playButton(id, parent) {
|
|||
}
|
||||
|
||||
function deleteButton(id, parent) {
|
||||
let button = html.button({className:"delete"}, "🗙", parent);
|
||||
let button = html.button({icon:"close"}, "", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
await mpd.command(`deleteid ${id}`);
|
||||
pubsub.publish("queue-change");
|
||||
|
@ -54,7 +54,7 @@ function deleteButton(id, parent) {
|
|||
}
|
||||
|
||||
function addAndPlayButton(urlOrFilter, parent) {
|
||||
let button = html.button({}, "▶", parent);
|
||||
let button = html.button({icon:"play", title:"Play"}, "", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
e.stopPropagation();
|
||||
await mpd.command("clear");
|
||||
|
@ -67,7 +67,7 @@ function addAndPlayButton(urlOrFilter, parent) {
|
|||
}
|
||||
|
||||
function addButton(urlOrFilter, parent) {
|
||||
let button = html.button({}, "+", parent);
|
||||
let button = html.button({icon:"plus"}, "", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
e.stopPropagation();
|
||||
await mpd.enqueue(urlOrFilter, SORT);
|
||||
|
|
|
@ -76,5 +76,12 @@ export function init(n) {
|
|||
DOM.random.addEventListener("click", e => command(`random ${current["random"] == "1" ? "0" : "1"}`));
|
||||
DOM.repeat.addEventListener("click", e => command(`repeat ${current["repeat"] == "1" ? "0" : "1"}`));
|
||||
|
||||
DOM.play.appendChild(html.icon("play"));
|
||||
DOM.pause.appendChild(html.icon("pause"));
|
||||
DOM.prev.appendChild(html.icon("rewind"));
|
||||
DOM.next.appendChild(html.icon("fast-forward"));
|
||||
DOM.random.appendChild(html.icon("shuffle"));
|
||||
DOM.repeat.appendChild(html.icon("repeat"));
|
||||
|
||||
update();
|
||||
}
|
||||
|
|
25
app/svg2js.sh
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
ARGS="ed -O -N svg=http://www.w3.org/2000/svg"
|
||||
DELETE="-d //comment() -d //svg:defs -d //svg:title -d //svg:desc -d //@fill -d //@stroke -d //@stroke-width -d //@fill-rule -d //@width -d //@height"
|
||||
|
||||
process_svg () {
|
||||
NAME=$1
|
||||
ID=$(basename $NAME | sed -e 's/.svg//')
|
||||
|
||||
DATA=$(cat $NAME | xmlstarlet fo -D -N | xmlstarlet $ARGS $DELETE)
|
||||
printf "ICONS[\"$ID\"] = \`$DATA\`;\n"
|
||||
}
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 svg_directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGES=$(find "$1" -name "*.svg")
|
||||
|
||||
printf "let ICONS={};\n"
|
||||
for i in $IMAGES; do
|
||||
process_svg $i
|
||||
done
|
||||
printf "export default ICONS;\n"
|