Compare commits
No commits in common. "4627f4eb29f235602961b8767451366f2a7e6f7b" and "6e13ed40dafdd980361227462abb2f8c97369400" have entirely different histories.
4627f4eb29
...
6e13ed40da
15 changed files with 145 additions and 931 deletions
|
|
@ -22,7 +22,6 @@
|
||||||
"<all_urls>"
|
"<all_urls>"
|
||||||
],
|
],
|
||||||
"js": [
|
"js": [
|
||||||
"src/js/main.js"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,23 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
--base_bg_color: 10;
|
|
||||||
--base_bg_color_range: 10;
|
|
||||||
--base_bg_saturation: 10%;
|
|
||||||
|
|
||||||
--color_text_white: #fff;
|
|
||||||
--color_text_gray: #999;
|
|
||||||
--surface-000: var(--s000);
|
|
||||||
--surface-100: var(--s100);
|
|
||||||
--surface-200: color-mix(in srgb, var(--s200), transparent 95%);
|
|
||||||
--surface-300: color-mix(in srgb, var(--s300), transparent 85%);
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
overflow-y: 0;
|
overflow-y: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: var(--surface-000) !important;
|
background: #000;
|
||||||
}
|
}
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
/* background: #f002 !important; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
transition: opacity .15s;
|
|
||||||
--base_bg_color_tint_p: calc(var(--base_bg_color) + var(--base_bg_color_range));
|
|
||||||
--base_bg_color_tint_n: calc(var(--base_bg_color) - var(--base_bg_color_range));
|
|
||||||
|
|
||||||
--c-0-base: hsla(var(--base_bg_color), calc(var(--base_bg_saturation) - 9%), calc(var(--base_bg_brightness) + 2%), 1);
|
|
||||||
--c-1-base: hsla(var(--base_bg_color_tint_p), calc(var(--base_bg_saturation) - 8%), calc(var(--base_bg_brightness) + 2%), 1);
|
|
||||||
--c-3-base: hsla(var(--base_bg_color_tint_n), calc(var(--base_bg_saturation) - 6%), calc(var(--base_bg_brightness) + 26%), 1);
|
|
||||||
|
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
#background.changing {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://www.mshr.app/mesh/1727910717365 */
|
/* https://www.mshr.app/mesh/1727910717365 */
|
||||||
@keyframes hero-gradient-animation {
|
@keyframes hero-gradient-animation {
|
||||||
|
|
@ -50,10 +26,8 @@ body {
|
||||||
--s-start-0: 9%;
|
--s-start-0: 9%;
|
||||||
--s-end-0: 55%;
|
--s-end-0: 55%;
|
||||||
--y-0: 80%;
|
--y-0: 80%;
|
||||||
--c-0: var(--c-0-base);
|
--c-0: hsla(266.99999999999983, 1%, 12%, 1);
|
||||||
--c-1: var(--c-1-base);
|
--c-1: hsla(335.9999999999997, 2%, 22%, 1);
|
||||||
--c-2: hsla(0,0%, 0%, 0.49);
|
|
||||||
--c-3: var(--c-3-base);
|
|
||||||
--s-start-1: 5%;
|
--s-start-1: 5%;
|
||||||
--s-end-1: 72%;
|
--s-end-1: 72%;
|
||||||
--y-1: 24%;
|
--y-1: 24%;
|
||||||
|
|
@ -61,9 +35,11 @@ body {
|
||||||
--s-start-2: 5%;
|
--s-start-2: 5%;
|
||||||
--s-end-2: 52%;
|
--s-end-2: 52%;
|
||||||
--y-2: 82%;
|
--y-2: 82%;
|
||||||
|
--c-2: hsla(53.999999999999886, 0%, 0%, 0.49);
|
||||||
--x-2: 13%;
|
--x-2: 13%;
|
||||||
--s-start-3: 13%;
|
--s-start-3: 13%;
|
||||||
--s-end-3: 68%;
|
--s-end-3: 68%;
|
||||||
|
--c-3: hsla(299, 4%, 36%, 1);
|
||||||
--x-3: 24%;
|
--x-3: 24%;
|
||||||
--y-3: 7%;
|
--y-3: 7%;
|
||||||
}
|
}
|
||||||
|
|
@ -73,10 +49,8 @@ body {
|
||||||
--s-start-0: 9%;
|
--s-start-0: 9%;
|
||||||
--s-end-0: 55%;
|
--s-end-0: 55%;
|
||||||
--y-0: 94%;
|
--y-0: 94%;
|
||||||
--c-0: var(--c-0-base);
|
--c-0: hsla(266.99999999999943, 0%, 12%, 1);
|
||||||
--c-1: var(--c-1-base);
|
--c-1: hsla(0, 4%, 19%, 1);
|
||||||
--c-2: hsla(0,0%, 0%, 0.49);
|
|
||||||
--c-3: var(--c-3-base);
|
|
||||||
--s-start-1: 5%;
|
--s-start-1: 5%;
|
||||||
--s-end-1: 72%;
|
--s-end-1: 72%;
|
||||||
--y-1: 25%;
|
--y-1: 25%;
|
||||||
|
|
@ -84,9 +58,11 @@ body {
|
||||||
--s-start-2: 5%;
|
--s-start-2: 5%;
|
||||||
--s-end-2: 52%;
|
--s-end-2: 52%;
|
||||||
--y-2: 20%;
|
--y-2: 20%;
|
||||||
|
--c-2: hsla(54.000000000000036, 0%, 0%, 0.49);
|
||||||
--x-2: 98%;
|
--x-2: 98%;
|
||||||
--s-start-3: 13%;
|
--s-start-3: 13%;
|
||||||
--s-end-3: 68%;
|
--s-end-3: 68%;
|
||||||
|
--c-3: hsla(298.99999999999994, 3%, 41%, 1);
|
||||||
--x-3: 95%;
|
--x-3: 95%;
|
||||||
--y-3: 92%;
|
--y-3: 92%;
|
||||||
}
|
}
|
||||||
|
|
@ -119,13 +95,13 @@ body {
|
||||||
@property --c-0 {
|
@property --c-0 {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: hsla(0,0,0,0)
|
initial-value: hsla(266.99999999999983, 1%, 12%, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --c-1 {
|
@property --c-1 {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: hsla(0,0,0,0)
|
initial-value: hsla(335.9999999999997, 2%, 22%, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --s-start-1 {
|
@property --s-start-1 {
|
||||||
|
|
@ -173,7 +149,7 @@ body {
|
||||||
@property --c-2 {
|
@property --c-2 {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: hsla(0,0,0,0)
|
initial-value: hsla(53.999999999999886, 0%, 0%, 0.49)
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --x-2 {
|
@property --x-2 {
|
||||||
|
|
@ -197,7 +173,7 @@ body {
|
||||||
@property --c-3 {
|
@property --c-3 {
|
||||||
syntax: '<color>';
|
syntax: '<color>';
|
||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: hsla(0,0,0,0)
|
initial-value: hsla(299, 4%, 36%, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@property --x-3 {
|
@property --x-3 {
|
||||||
|
|
@ -213,40 +189,21 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
background-color: var(--surface-000);
|
|
||||||
}
|
|
||||||
#background.default {
|
|
||||||
--x-0: 85%;
|
--x-0: 85%;
|
||||||
--y-0: 80%;
|
--y-0: 80%;
|
||||||
--c-0: hsla(var(--base_bg_color), calc(var(--base_bg_saturation) - 9%), 12%, 1);
|
--c-0: hsla(266.99999999999983, 1%, 12%, 1);
|
||||||
--c-1: hsla(var(--base_bg_color_tint_p), calc(var(--base_bg_saturation) - 8%), 22%, 1);
|
--c-1: hsla(335.9999999999997, 2%, 22%, 1);
|
||||||
--y-1: 24%;
|
--y-1: 24%;
|
||||||
--x-1: 60%;
|
--x-1: 60%;
|
||||||
--y-2: 82%;
|
--y-2: 82%;
|
||||||
--c-2: hsla(0,0%, 0%, 0.49);
|
--c-2: hsla(53.999999999999886, 0%, 0%, 0.49);
|
||||||
--x-2: 13%;
|
--x-2: 13%;
|
||||||
--c-3: hsla(var(--base_bg_color_tint_n), calc(var(--base_bg_saturation) - 6%), 36%, 1);
|
--c-3: hsla(299, 4%, 36%, 1);
|
||||||
--x-3: 24%;
|
--x-3: 24%;
|
||||||
--y-3: 7%;
|
--y-3: 7%;
|
||||||
background-color: var(--surface-000);
|
|
||||||
background-image:
|
|
||||||
radial-gradient(
|
|
||||||
circle at var(--x-0) var(--y-0), var(--c-0) var(--s-start-0),
|
|
||||||
transparent var(--s-end-0)
|
|
||||||
),
|
|
||||||
radial-gradient(
|
|
||||||
circle at var(--x-1) var(--y-1), var(--c-1) var(--s-start-1),
|
|
||||||
transparent var(--s-end-1)
|
|
||||||
),
|
|
||||||
radial-gradient(
|
|
||||||
circle at var(--x-2) var(--y-2), var(--c-2) var(--s-start-2),
|
|
||||||
transparent var(--s-end-2)
|
|
||||||
),
|
|
||||||
radial-gradient(
|
|
||||||
circle at var(--x-3) var(--y-3), var(--c-3) var(--s-start-3),
|
|
||||||
transparent var(--s-end-3)
|
|
||||||
)
|
|
||||||
;
|
;
|
||||||
|
background-color: hsla(0, 0%, 0%, 1);
|
||||||
|
background-image: radial-gradient(circle at var(--x-0) var(--y-0), var(--c-0) var(--s-start-0), transparent var(--s-end-0)), radial-gradient(circle at var(--x-1) var(--y-1), var(--c-1) var(--s-start-1), transparent var(--s-end-1)), radial-gradient(circle at var(--x-2) var(--y-2), var(--c-2) var(--s-start-2), transparent var(--s-end-2)), radial-gradient(circle at var(--x-3) var(--y-3), var(--c-3) var(--s-start-3), transparent var(--s-end-3));
|
||||||
animation: hero-gradient-animation 10s linear infinite alternate;
|
animation: hero-gradient-animation 10s linear infinite alternate;
|
||||||
background-blend-mode: normal, normal, normal, normal;
|
background-blend-mode: normal, normal, normal, normal;
|
||||||
}
|
}
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: 'Material Symbols Rounded';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 100 700;
|
|
||||||
src: url(./icons.woff2) format('woff2');
|
|
||||||
}
|
|
||||||
|
|
||||||
.material-symbols-rounded {
|
|
||||||
font-family: 'Material Symbols Rounded';
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-size: 24px;
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 1;
|
|
||||||
letter-spacing: normal;
|
|
||||||
text-transform: none;
|
|
||||||
display: inline-block;
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
direction: ltr;
|
|
||||||
-webkit-font-feature-settings: 'liga';
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -26,11 +26,11 @@
|
||||||
#searcher > h1 {
|
#searcher > h1 {
|
||||||
font-family: 'Playfair Display';
|
font-family: 'Playfair Display';
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 60px;
|
font-size: 70px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
} #searcher > h1 > span {
|
} #searcher > h1 > span {
|
||||||
transition: background .2s;
|
transition: background .2s;
|
||||||
font-size: 23px;
|
font-size: 33px;
|
||||||
font-family: 'Fira Code';
|
font-family: 'Fira Code';
|
||||||
background: rgba(255,255,255,.1);
|
background: rgba(255,255,255,.1);
|
||||||
padding: 0 5px 0;
|
padding: 0 5px 0;
|
||||||
|
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
.settings_visual_help {
|
|
||||||
z-index: 11;
|
|
||||||
position: fixed;
|
|
||||||
top: 0px;
|
|
||||||
right: 0px;
|
|
||||||
cursor: pointer;
|
|
||||||
height: 100dvh;
|
|
||||||
width: 40px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: end;
|
|
||||||
padding-left: 50px;
|
|
||||||
cursor: default;
|
|
||||||
>div {
|
|
||||||
cursor: pointer;
|
|
||||||
rotate: -90deg;
|
|
||||||
transform: translateY(98px) scale(.9);
|
|
||||||
transition: transform .2s;
|
|
||||||
gap: 7px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: var(--surface-200);
|
|
||||||
padding: 5px 10px;
|
|
||||||
border-radius: 10px 10px 0 0;
|
|
||||||
border: solid 1px var(--surface-300);
|
|
||||||
border-bottom: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
>div:hover {
|
|
||||||
background: var(--surface-300);
|
|
||||||
}
|
|
||||||
>div:active {
|
|
||||||
background: var(--surface-300);
|
|
||||||
}
|
|
||||||
|
|
||||||
span:not(.icon) {
|
|
||||||
text-wrap: nowrap;
|
|
||||||
font-family: var(--sans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.settings_visual_help:hover {
|
|
||||||
>div {
|
|
||||||
transform: translateY(58px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings.ov {
|
|
||||||
transform: translateX(34vw);
|
|
||||||
}
|
|
||||||
#settings {
|
|
||||||
overflow-y: auto;
|
|
||||||
overflow-x: hidden;
|
|
||||||
z-index: 1001;
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 20px;
|
|
||||||
gap: 10px;
|
|
||||||
height: calc(100dvh - 40px);
|
|
||||||
width: 30vw;
|
|
||||||
/* background: var(--surface-100); */
|
|
||||||
/* border-left: solid 1px var(--surface-300); */
|
|
||||||
border: none;
|
|
||||||
scrollbar-color: var(--surface-300) transparent;
|
|
||||||
|
|
||||||
>* {
|
|
||||||
transition: transform .3s, opacity .3s;
|
|
||||||
}
|
|
||||||
>.ov {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(34vw);
|
|
||||||
}
|
|
||||||
>.back {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
align-items: center;
|
|
||||||
h2 {
|
|
||||||
font-family: var(--serif);
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
border-radius: 100px;
|
|
||||||
font-size: 25px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>.back:hover {
|
|
||||||
span {
|
|
||||||
background: var(--surface-300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>h2, >h3 {
|
|
||||||
font-family: var(--serif);
|
|
||||||
font-weight: normal;
|
|
||||||
/* margin-bottom: 5px; */
|
|
||||||
}
|
|
||||||
>p {
|
|
||||||
font-family: var(--sans);
|
|
||||||
/* margin-bottom: 10px; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: 10px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.action {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: fit-content;
|
|
||||||
background: var(--surface-200);
|
|
||||||
border: solid 1px var(--surface-300);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border-radius: 100px;
|
|
||||||
padding: 5px 5px;
|
|
||||||
gap: 3px;
|
|
||||||
.icon {
|
|
||||||
--size: 17px;
|
|
||||||
font-size: var(--size) !important;
|
|
||||||
height: var(--size) !important;
|
|
||||||
width: var(--size) !important;
|
|
||||||
}
|
|
||||||
:not(.icon) {
|
|
||||||
font-family: var(--sans);
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
padding: 2px 3px 3px;
|
|
||||||
background: var(--surface-200);
|
|
||||||
border: solid 1px var(--surface-300);
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
input, textarea {
|
|
||||||
border-radius: 20px;
|
|
||||||
background: var(--surface-200);
|
|
||||||
padding: 10px;
|
|
||||||
border: solid 1px var(--surface-300);
|
|
||||||
outline: none;
|
|
||||||
resize: vertical;
|
|
||||||
font-family: var(--monospace);
|
|
||||||
}
|
|
||||||
textarea {
|
|
||||||
border-radius: 15px !important;
|
|
||||||
height: 100dvh;
|
|
||||||
min-height: 180px;
|
|
||||||
scrollbar-color: var(--color_text_white) transparent;
|
|
||||||
text-wrap-mode: wrap;
|
|
||||||
word-wrap: break-word;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
input::placeholder, textarea::placeholder {
|
|
||||||
color: var(--color_text_gray);
|
|
||||||
}
|
|
||||||
|
|
||||||
.action:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background: var(--surface-300)
|
|
||||||
}
|
|
||||||
.surface {
|
|
||||||
background: var(--surface-200);
|
|
||||||
border: solid 1px var(--surface-300);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
/* padding: 10px; */
|
|
||||||
border-radius: 15px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.setting_entry:nth-child(n+2) {
|
|
||||||
border-top: solid 1px var(--surface-300);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setting_entry {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 6px 11px;
|
|
||||||
padding-right: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
.icon {
|
|
||||||
color: var(--color_text_gray);
|
|
||||||
}
|
|
||||||
:not(.icon) {
|
|
||||||
font-family: var(--sans);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.setting_entry:hover {
|
|
||||||
background: var(--surface-200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
24
src/css/update.css
Normal file
24
src/css/update.css
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#update {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: 'Nunito';
|
||||||
|
background: rgba(255,255,255,.1);
|
||||||
|
border-radius: 100px;
|
||||||
|
margin: 10px;
|
||||||
|
display: flex;
|
||||||
|
z-index: 20;
|
||||||
|
transition: transform .5s;
|
||||||
|
} #update > * {
|
||||||
|
padding: 5px 10px;
|
||||||
|
} #update > a {
|
||||||
|
text-decoration: none;
|
||||||
|
background: rgba(255,255,255,.1);
|
||||||
|
border-radius: 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#update.hidden {
|
||||||
|
transform: translateY(40px);
|
||||||
|
}
|
||||||
|
|
@ -5,9 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="shortcut icon" href="icon.svg" type="image/x-icon">
|
<link rel="shortcut icon" href="icon.svg" type="image/x-icon">
|
||||||
<link rel="stylesheet" href="css/icons.css">
|
|
||||||
<link rel="stylesheet" href="css/global.css">
|
<link rel="stylesheet" href="css/global.css">
|
||||||
<link rel="stylesheet" href="css/settings.css">
|
|
||||||
<link rel="stylesheet" href="css/clock.css">
|
<link rel="stylesheet" href="css/clock.css">
|
||||||
<link rel="stylesheet" href="css/search.css">
|
<link rel="stylesheet" href="css/search.css">
|
||||||
<link rel="stylesheet" href="css/update.css">
|
<link rel="stylesheet" href="css/update.css">
|
||||||
|
|
@ -19,15 +17,12 @@
|
||||||
<p>Search via Google</p>
|
<p>Search via Google</p>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" id="search_ddd" autocorrect="off" autocomplete="off" autofocus>
|
<input type="text" id="search_ddd" autocorrect="off" autocomplete="off" autofocus>
|
||||||
<div class="settings_visual_help">
|
<div id="update" class="hidden"><span>update available</span> <a href="https://github.com/ktnk-dev/LittleHome">download</a></div>
|
||||||
</div>
|
<script src="js/abstract.js"></script>
|
||||||
<script src="lib/sinya.lib.js"></script>
|
|
||||||
<script src="lib/gicons.lib.js"></script>
|
|
||||||
<script src="js/storage.js"></script>
|
<script src="js/storage.js"></script>
|
||||||
<script src="js/bang.js"></script>
|
<script src="js/bang.js"></script>
|
||||||
<script src="js/builtin.js"></script>
|
<script src="js/builtin.js"></script>
|
||||||
<script src="js/update.js"></script>
|
<script src="js/update.js"></script>
|
||||||
<script src="js/settings.js"></script>
|
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
67
src/js/abstract.js
Normal file
67
src/js/abstract.js
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
* @typedef {Object} $
|
||||||
|
* @property {function(object=, ...HTMLElement): HTMLElement} DOCS - creates element with this tagname
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### Create element
|
||||||
|
*
|
||||||
|
* @type {$}
|
||||||
|
*/
|
||||||
|
const $ = new Proxy(
|
||||||
|
class {
|
||||||
|
/**
|
||||||
|
* ### Creates `$` element
|
||||||
|
* @param {string} type element type
|
||||||
|
* @param {object} props element properties (onclick, class, ...)
|
||||||
|
* @param {...HTMLElement} children
|
||||||
|
* @returns {HTMLElement}
|
||||||
|
*/
|
||||||
|
static createElement(type, props, ...children) {
|
||||||
|
const element = document.createElement(type)
|
||||||
|
|
||||||
|
if (props) {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
props instanceof Node
|
||||||
|
|| typeof props === 'string'
|
||||||
|
|| typeof props === 'number'
|
||||||
|
) children = [props, ...children]
|
||||||
|
else {throw Error()}
|
||||||
|
} catch {
|
||||||
|
for (const [key, value] of Object.entries(props)) {
|
||||||
|
if (key.startsWith('on') && typeof value === 'function') {
|
||||||
|
element.addEventListener(key.slice(2).toLowerCase(), value)
|
||||||
|
} else if (key === 'className') {
|
||||||
|
element.className = value
|
||||||
|
} else {
|
||||||
|
element.setAttribute(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
children.flat().forEach(child => {
|
||||||
|
if (typeof child === 'string' || typeof child === 'number') {
|
||||||
|
element.innerHTML += child
|
||||||
|
} else if (child instanceof Node) {
|
||||||
|
element.appendChild(child)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element[Symbol.toPrimitive] = function(hint) {
|
||||||
|
if (hint === 'string') return this.outerHTML
|
||||||
|
return this
|
||||||
|
};
|
||||||
|
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
get(target, element) {
|
||||||
|
return function(props, ...children) {
|
||||||
|
return target.createElement(element, props, ...children)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
@ -64,8 +64,12 @@ searcher = () => {
|
||||||
const query = element.target.value.trim()
|
const query = element.target.value.trim()
|
||||||
const fb = findbang(query)
|
const fb = findbang(query)
|
||||||
const url = fb.valid ? fb.data.u : 'https://www.google.com/search?q={{{s}}}'
|
const url = fb.valid ? fb.data.u : 'https://www.google.com/search?q={{{s}}}'
|
||||||
window.location.href = url.replace('{{{s}}}', encodeURIComponent(fb.found ? query.replace('!'+fb.inputed, '').trim() : query.trim()))
|
window.location.href = url.replace('{{{s}}}', encodeURI(fb.found ? query.replace('!'+fb.inputed, '').trim() : query.trim()))
|
||||||
}
|
}
|
||||||
document.querySelector('#search_ddd').addEventListener('change', find)
|
document.querySelector('#search_ddd').addEventListener('change', find)
|
||||||
document.querySelector('#search_ddd').addEventListener('input', (e) => {proceed(e.target.value.trim())})
|
document.querySelector('#search_ddd').addEventListener('input', (e) => {proceed(e.target.value.trim())})
|
||||||
|
setInterval(() => {
|
||||||
|
document.querySelector('#search_ddd').focus()
|
||||||
|
proceed(document.querySelector('#search_ddd').value.trim())
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
window.addEventListener('DOMContentLoaded', async () => {
|
window.addEventListener('DOMContentLoaded', async () => {
|
||||||
search_focus.enable()
|
clock()
|
||||||
select('.settings_visual_help').overwrite(
|
|
||||||
$.div(
|
|
||||||
{onclick: () => settings.start()},
|
|
||||||
$.span('Open settings'),
|
|
||||||
Icons.settings({fill: true, size: 15}),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (storage.get('active')?.hide_clock == true) clock()
|
|
||||||
preset.load(storage.get('_active') || 'Default')
|
|
||||||
searcher()
|
searcher()
|
||||||
|
check_update()
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
const search_focus = {
|
|
||||||
id: null,
|
|
||||||
paused: false,
|
|
||||||
enable: () => {
|
|
||||||
search_focus.paused = false
|
|
||||||
if (search_focus.id) return
|
|
||||||
search_focus.id = setInterval(() => {
|
|
||||||
if (search_focus.paused) return
|
|
||||||
if (!search_focus.id) return
|
|
||||||
document.querySelector('#search_ddd').focus()
|
|
||||||
console.log(search_focus.id)
|
|
||||||
// proceed(document.querySelector('#search_ddd').value.trim())
|
|
||||||
}, 100)
|
|
||||||
},
|
|
||||||
disable: () => {
|
|
||||||
search_focus.paused = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const settings = {
|
|
||||||
views: [],
|
|
||||||
current: null,
|
|
||||||
|
|
||||||
back: async () => {
|
|
||||||
settings.current = settings.views.pop()
|
|
||||||
if (!settings.current) {
|
|
||||||
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
|
|
||||||
await sleep(.2)
|
|
||||||
settings.stop()
|
|
||||||
} else {
|
|
||||||
settings._open(settings.current())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_open: async elements => {
|
|
||||||
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
|
|
||||||
await sleep(.2)
|
|
||||||
select('#settings').overwrite(...elements)
|
|
||||||
selectAll('#settings > *').map(e => e.element.classList.add('ov'))
|
|
||||||
requestAnimationFrame(() => selectAll('#settings > *').map(e => e.element.classList.remove('ov')))
|
|
||||||
},
|
|
||||||
|
|
||||||
next: async fn => {
|
|
||||||
settings.views.push(settings.current)
|
|
||||||
settings.current = fn
|
|
||||||
settings._open(fn())
|
|
||||||
},
|
|
||||||
|
|
||||||
back_button: (title, icon = Icons.arrow_back) => $.div(
|
|
||||||
{onclick: settings.back, class: 'back'},
|
|
||||||
icon(),
|
|
||||||
$.h2(title),
|
|
||||||
),
|
|
||||||
start: () => {
|
|
||||||
settings.views = []
|
|
||||||
settings.current = null
|
|
||||||
select('body').append(
|
|
||||||
$.div({id: 'settings'})
|
|
||||||
)
|
|
||||||
search_focus.disable()
|
|
||||||
settings.next(settings.main)
|
|
||||||
},
|
|
||||||
stop: () => {
|
|
||||||
select('#settings').remove()
|
|
||||||
search_focus.enable()
|
|
||||||
},
|
|
||||||
main: () => [
|
|
||||||
settings.back_button('Settings', Icons.close),
|
|
||||||
$.div(
|
|
||||||
{class: 'surface'},
|
|
||||||
$.div(
|
|
||||||
{class: 'setting_entry', onclick: () => settings.next(settings.basic)},
|
|
||||||
$.span('Basic settings'),
|
|
||||||
Icons.arrow_right()
|
|
||||||
),
|
|
||||||
$.div(
|
|
||||||
{class: 'setting_entry', onclick: () => settings.next(settings.bangs)},
|
|
||||||
$.span('Bangs editor'),
|
|
||||||
Icons.arrow_right()
|
|
||||||
),
|
|
||||||
$.div(
|
|
||||||
{class: 'setting_entry', onclick: () => settings.next(settings.customization)},
|
|
||||||
$.span('Customization'),
|
|
||||||
Icons.arrow_right()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
basic: () => [
|
|
||||||
settings.back_button('Basic Settings'),
|
|
||||||
],
|
|
||||||
bangs: () => [
|
|
||||||
settings.back_button('Bangs editor'),
|
|
||||||
$.p('Here are your custom bangs, that will override default one from DuckDuckGo'),
|
|
||||||
$.div(
|
|
||||||
{class: 'list'},
|
|
||||||
$.div(
|
|
||||||
{class: 'action', onclick: () => settings.next(() => settings.edit_bang(false))},
|
|
||||||
Icons.add_2(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
$.div(
|
|
||||||
{class: 'surface'},
|
|
||||||
...bangs_override.toReversed().map(b => $.div(
|
|
||||||
{class: 'setting_entry', onclick: () => settings.next(() => settings.edit_bang(b))},
|
|
||||||
$.span(b.name),
|
|
||||||
Icons.arrow_right()
|
|
||||||
))
|
|
||||||
|
|
||||||
)
|
|
||||||
],
|
|
||||||
edit_bang: bang_data => {
|
|
||||||
const index = bangs_override.findIndex(b => b === bang_data)
|
|
||||||
/** @type {Bang} */
|
|
||||||
state.bang = bang_data || {
|
|
||||||
name: '',
|
|
||||||
keyword: '',
|
|
||||||
url: ''
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
settings.back_button('Edit Bang'),
|
|
||||||
$.h3('Name'),
|
|
||||||
$.input({value: state.bang.name, placeholder: 'Bang name', onchange: (e) => state.bang.name = e.target.value.trim()}),
|
|
||||||
$.div({style: 'height: 10px'}),
|
|
||||||
$.h3('Keyword'),
|
|
||||||
$.p('Add a short keyword for your bang, e.g. ', $.code('google')),
|
|
||||||
$.input({value: state.bang.keyword, placeholder: 'Bang keyword', onchange: (e) => state.bang.keyword = e.target.value.trim()}),
|
|
||||||
$.div({style: 'height: 10px'}),
|
|
||||||
$.h3('URL'),
|
|
||||||
$.p('Add a url for your bang with ', $.code('{{{s}}}'), ' string, that will be replaced with the search query'),
|
|
||||||
$.textarea({value: state.bang.url, placeholder: 'Bang URL', onchange: (e) => state.bang.url = e.target.value.trim()}, state.bang.url),
|
|
||||||
$.div(
|
|
||||||
{class: 'list'},
|
|
||||||
$.div(
|
|
||||||
{class: 'action', onclick: () => {
|
|
||||||
if (state.bang.name.length && state.bang.keyword.length && state.bang.url.length) {
|
|
||||||
index != -1 ? bangs_override[index] = state.bang : bangs_override.push(state.bang)
|
|
||||||
storage.set('_bangs', bangs_override)
|
|
||||||
settings.back()
|
|
||||||
} else {
|
|
||||||
alert('Please fill in all fields')
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
$.span('Save'),
|
|
||||||
),
|
|
||||||
bang_data ? $.div(
|
|
||||||
{class: 'action', onclick: () => {
|
|
||||||
if (confirm('Are you sure you want to delete this bang?')) {
|
|
||||||
bangs_override.splice(index, 1)
|
|
||||||
storage.set('_bangs', bangs_override)
|
|
||||||
settings.back()
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
$.span('Delete'),
|
|
||||||
) : null
|
|
||||||
),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
/** @type {Bang} */
|
|
||||||
bang: null,
|
|
||||||
/** @type {string} */
|
|
||||||
search_url: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
// debug
|
|
||||||
sleep(.3).then(() => settings.start())
|
|
||||||
|
|
@ -1,186 +1,33 @@
|
||||||
const storage = {
|
const CookieManager = {
|
||||||
get: (variable_name) => {
|
get: (cname) => {
|
||||||
const worker = (cname) => {
|
let name = cname + "=";
|
||||||
let name = cname + "=";
|
let decodedCookie = decodeURIComponent(document.cookie);
|
||||||
let decodedCookie = document.cookie;
|
let ca = decodedCookie.split(';');
|
||||||
let ca = decodedCookie.split(';');
|
for(let i = 0; i <ca.length; i++) {
|
||||||
for(let i = 0; i <ca.length; i++) {
|
let c = ca[i];
|
||||||
let c = ca[i];
|
while (c.charAt(0) == ' ') {
|
||||||
while (c.charAt(0) == ' ') {
|
c = c.substring(1);
|
||||||
c = c.substring(1);
|
}
|
||||||
}
|
if (c.indexOf(name) == 0) {
|
||||||
if (c.indexOf(name) == 0) {
|
return c.substring(name.length, c.length);
|
||||||
return c.substring(name.length, c.length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
const c = worker(variable_name)
|
return "";
|
||||||
return c === '' ? null : JSON.parse(c).data
|
|
||||||
},
|
},
|
||||||
set: (variable_name, value) => {
|
set: (cname, cvalue) => {
|
||||||
const worker = (cname, cvalue) => {
|
const d = new Date();
|
||||||
const d = new Date();
|
d.setTime(d.getTime() + (999*24*60*60*1000));
|
||||||
d.setTime(d.getTime() + (999*24*60*60*1000));
|
let expires = "expires="+ d.toUTCString();
|
||||||
let expires = "expires="+ d.toUTCString();
|
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
||||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
|
||||||
}
|
|
||||||
worker(variable_name, JSON.stringify({data: value}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
function getFromStorage(variable_name) {
|
||||||
* @typedef {Object} Preset
|
const c = CookieManager.get(variable_name)
|
||||||
* @prop {number} version
|
return c === '' ? null : JSON.parse(c).data
|
||||||
* @prop {string} name
|
|
||||||
* @prop {"default" | "url" | "color" | "gradient"} background_type // TODO: gradient
|
|
||||||
* @prop {number} base_bg_color
|
|
||||||
* @prop {number} base_bg_saturation
|
|
||||||
* @prop {number} base_bg_color_range
|
|
||||||
* @prop {string} font_sans
|
|
||||||
// * @prop {string} font_sans_size
|
|
||||||
* @prop {string} font_serif
|
|
||||||
// * @prop {string} font_serif_size
|
|
||||||
* @prop {string} font_monospace
|
|
||||||
// * @prop {string} font_monospace_size
|
|
||||||
* @prop {string} color_text_white
|
|
||||||
* @prop {string} color_text_gray
|
|
||||||
* @prop {string} s000
|
|
||||||
* @prop {string} s100
|
|
||||||
* @prop {string} s200
|
|
||||||
* @prop {string} s300
|
|
||||||
* @prop {bool} m
|
|
||||||
*/
|
|
||||||
|
|
||||||
const preset = {
|
|
||||||
/** @type {Preset} */
|
|
||||||
active: {},
|
|
||||||
current_version: 1,
|
|
||||||
migration: () => ([
|
|
||||||
['version', preset.current_version, 1],
|
|
||||||
['m', true, 1],
|
|
||||||
]).forEach(q => preset.active[q[0]] = q.length>2 ? q[1] : (preset.active[q[0]] || q[1])),
|
|
||||||
|
|
||||||
save: () => {
|
|
||||||
preset.migration()
|
|
||||||
storage.set(preset.active.name, preset.active)
|
|
||||||
storage.set('_active', preset.active.name)
|
|
||||||
var list = storage.get('_presets') ? storage.get('_presets') : []
|
|
||||||
if (!list.includes(preset.active.name)) {
|
|
||||||
list.push(preset.active.name)
|
|
||||||
storage.set('_presets', list)
|
|
||||||
}
|
|
||||||
preset.render()
|
|
||||||
},
|
|
||||||
delete: () => {
|
|
||||||
/**@type {string[]} */
|
|
||||||
var list = storage.get('_presets') ? storage.get('_presets') : []
|
|
||||||
|
|
||||||
list[list.indexOf(preset.active.name)] = false
|
|
||||||
list = list.filter(q => q != null)
|
|
||||||
storage.set('_presets', list)
|
|
||||||
preset.load(list.length > 0 ? list[0] : 'Default')
|
|
||||||
},
|
|
||||||
load: preset_name => {
|
|
||||||
if (!preset_name) preset_name = storage.get('_active') ? storage.get('_active') : 'Default'
|
|
||||||
|
|
||||||
var list = storage.get('_presets') ? storage.get('_presets') : []
|
|
||||||
if (!list.includes(preset_name)) {
|
|
||||||
preset.active = preset.default()
|
|
||||||
preset.active.name = preset_name
|
|
||||||
preset.save()
|
|
||||||
} else {
|
|
||||||
preset.active = storage.get(preset_name)
|
|
||||||
preset.save()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render: () => {
|
|
||||||
const force_redraw = (element) => {
|
|
||||||
if (!element) return
|
|
||||||
element.classList.toggle('twt')
|
|
||||||
var n = document.createTextNode(' ')
|
|
||||||
var disp = element.style.display || 'block'
|
|
||||||
element.appendChild(n)
|
|
||||||
element.style.display = 'none'
|
|
||||||
requestAnimationFrame(
|
|
||||||
() => {
|
|
||||||
element.style.display = disp
|
|
||||||
n.parentNode.removeChild(n)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
const style_override = {
|
|
||||||
// s000: 'surface-000',
|
|
||||||
// s100: 'surface-100',
|
|
||||||
// s200: 'surface-200',
|
|
||||||
// s300: 'surface-300',
|
|
||||||
font_sans: 'sans',
|
|
||||||
font_serif: 'serif',
|
|
||||||
font_monospace: 'monospace',
|
|
||||||
}
|
|
||||||
|
|
||||||
const set_style = (element, s) => {
|
|
||||||
s = s.replaceAll('-', '_')
|
|
||||||
const prop_name = Object.keys(style_override).includes(s) ? style_override[s] : s
|
|
||||||
element.style.setProperty('--'+prop_name, ['base_bg_saturation','base_bg_brightness'].includes(s) ? (preset.active[s]+'%') : preset.active[s])
|
|
||||||
}
|
|
||||||
|
|
||||||
select('#background').element.setAttribute('class', preset.active.background_type);
|
|
||||||
|
|
||||||
(['s000', 's100', 's200', 's300', 'font_sans', 'font_serif', 'font_monospace', 'color_text_white', 'color_text_gray',])
|
|
||||||
.forEach(s => set_style(select('body').element, s));
|
|
||||||
|
|
||||||
(['base_bg_color', 'base_bg_saturation', 'base_bg_color_range', 'base_bg_brightness'])
|
|
||||||
.forEach(s => set_style(select('#background').element, s));
|
|
||||||
force_redraw(select('#background').element)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Preset}
|
|
||||||
*/
|
|
||||||
default: () => { return {
|
|
||||||
name: 'Defualt',
|
|
||||||
version: preset.current_version,
|
|
||||||
// disable_clock: false,
|
|
||||||
// disable_animations: false,
|
|
||||||
background_type: 'default',
|
|
||||||
base_bg_color: 10,
|
|
||||||
base_bg_saturation: 10,
|
|
||||||
base_bg_brightness: 10,
|
|
||||||
base_bg_color_range: 10,
|
|
||||||
// search_url: 'https://www.google.com/search?q={{{s}}}',
|
|
||||||
// display_suggestions: false,
|
|
||||||
// display_history: false,
|
|
||||||
font_sans: 'Nunito',
|
|
||||||
font_serif: 'Playfair Display',
|
|
||||||
font_monospace: 'monospace',
|
|
||||||
color_text_white: '#fff',
|
|
||||||
color_text_gray: '#999',
|
|
||||||
s000: '#000',
|
|
||||||
s100: '#fff',
|
|
||||||
s200: '#fff',
|
|
||||||
s300: '#fff',
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaults = {
|
function setToStorage(variable_name, value) {
|
||||||
bangs: [
|
CookieManager.set(variable_name, JSON.stringify({data: value}))
|
||||||
{name: 'Test bang', keyword: 'test_bang', url: 'https://www.google.com/search?q={{{s}}}'},
|
|
||||||
{name: 'Google Search AI', keyword: 'ai', url: 'https://www.google.com/search?q={{{s}}}&sourceid=chrome&ie=UTF-8&amc=1&oq={{{s}}}&udm=50&aep=109&cud='}
|
|
||||||
],
|
|
||||||
search_engine: 'https://www.google.com/search?q={{{s}}}'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} Bang
|
|
||||||
* @prop {string} keyword
|
|
||||||
* @prop {string} name
|
|
||||||
* @prop {string} url
|
|
||||||
*/
|
|
||||||
/** @type {Bang[]} */
|
|
||||||
var bangs_override = storage.get('_bangs') || defaults.bangs
|
|
||||||
|
|
||||||
/** @type {string} */
|
|
||||||
var search_engine = storage.get('_search') || defaults.search_engine
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* @typedef {Object} IconOptions
|
|
||||||
* @prop {100|200|300|400|500|600|700} weight Symbol weight
|
|
||||||
* @prop {bool} fill
|
|
||||||
* @prop {'low' | 'default' | 'high'} grade Symbol thickness
|
|
||||||
* @prop {20|48} optical_size (from 20 to 48) For the image to look the same at different sizes in dp
|
|
||||||
* @prop {number} size Icon size in px
|
|
||||||
* @prop {string} color Any css-supported color variant (names, rgb, hex)
|
|
||||||
*/
|
|
||||||
|
|
||||||
var DEFAULT_ICON_COLOR = '#000'
|
|
||||||
var DEFAULT_ICON_SIZE = 24
|
|
||||||
/** @type {IconOptions} */
|
|
||||||
var DEFAULT_ICON_OPTIONS = {}
|
|
||||||
|
|
||||||
/** @type {Record<string, (options: IconOptions) => HTMLSpanElement} */
|
|
||||||
const Icons = new Proxy(
|
|
||||||
class {
|
|
||||||
/**
|
|
||||||
* @param {string} name
|
|
||||||
* @param {IconOptions} options
|
|
||||||
* @returns {HTMLSpanElement}
|
|
||||||
*/
|
|
||||||
static getIcon(name, {fill, weight, grade, optical_size, size, color}) {
|
|
||||||
const gr = ({
|
|
||||||
'low': -25,
|
|
||||||
'default': 0,
|
|
||||||
'high': 200
|
|
||||||
})[grade]
|
|
||||||
const data = `
|
|
||||||
'FILL' ${fill !== undefined ? fill?1:0 : 1},
|
|
||||||
'wdth' ${weight || 400},
|
|
||||||
'GRAD' ${gr || 0},
|
|
||||||
'opsz' ${optical_size || 20}`
|
|
||||||
const fz = size ? typeof size != Number ? `${size}px`:size : (DEFAULT_ICON_SIZE+'px')
|
|
||||||
return $.span(
|
|
||||||
{class: 'material-symbols-rounded icon', style: `font-size: ${fz}; width: ${fz}; height: ${fz}; ${color ? `color: ${color};` : ''}font-variation-settings: ${data}`},
|
|
||||||
name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
get(target, name) {
|
|
||||||
/**
|
|
||||||
* @argument {IconOptions} options
|
|
||||||
*/
|
|
||||||
return function(options) {
|
|
||||||
return target.getIcon(name, options || DEFAULT_ICON_OPTIONS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const gIconsInit = () => document.head.innerHTML += `
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200">
|
|
||||||
`
|
|
||||||
|
|
@ -1,226 +0,0 @@
|
||||||
/**
|
|
||||||
* @typedef {Object} $
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} div - creates div element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} p - creates p element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} span - creates span element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} button - creates button element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} input - creates input element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} a - creates a element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} img - creates img element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h1 - creates h1 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h2 - creates h2 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h3 - creates h3 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h4 - creates h4 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h5 - creates h5 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} h6 - creates h6 element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} ul - creates ul element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} li - creates li element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} form - creates form element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} table - creates table element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} tr - creates tr element
|
|
||||||
* @property {function(object=, ...HTMLElement): HTMLElement} td - creates td element
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ### Create element
|
|
||||||
*
|
|
||||||
* @type {$}
|
|
||||||
*/
|
|
||||||
const $ = new Proxy(
|
|
||||||
class {
|
|
||||||
/**
|
|
||||||
* ### Creates `$` element
|
|
||||||
* @param {string} type element type
|
|
||||||
* @param {object} props element properties (onclick, class, ...)
|
|
||||||
* @param {...HTMLElement} children
|
|
||||||
* @returns {HTMLElement}
|
|
||||||
*/
|
|
||||||
static createElement(type, props, ...children) {
|
|
||||||
const element = document.createElement(type)
|
|
||||||
|
|
||||||
if (props) {
|
|
||||||
try {
|
|
||||||
if (
|
|
||||||
props instanceof Node
|
|
||||||
|| typeof props === 'string'
|
|
||||||
|| typeof props === 'number'
|
|
||||||
) children = [props, ...children]
|
|
||||||
else {throw Error()}
|
|
||||||
} catch {
|
|
||||||
for (const [key, value] of Object.entries(props)) {
|
|
||||||
if (key.startsWith('on') && typeof value === 'function') {
|
|
||||||
element.addEventListener(key.slice(2).toLowerCase(), value)
|
|
||||||
} else if (key === 'className') {
|
|
||||||
element.className = value
|
|
||||||
} else {
|
|
||||||
element.setAttribute(key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
children.flat().forEach(child => {
|
|
||||||
if (typeof child === 'string' || typeof child === 'number') {
|
|
||||||
element.innerHTML += child
|
|
||||||
} else if (child instanceof Node) {
|
|
||||||
element.appendChild(child)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
element[Symbol.toPrimitive] = function(hint) {
|
|
||||||
if (hint === 'string') return this.outerHTML
|
|
||||||
return this
|
|
||||||
};
|
|
||||||
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
get(target, element) {
|
|
||||||
return function(props, ...children) {
|
|
||||||
return target.createElement(element, props, ...children)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select single DOM element and wrap them
|
|
||||||
* @param {string} selector
|
|
||||||
* @returns {WrappedElement}
|
|
||||||
*/
|
|
||||||
const select = (selector, _target = document) => wrap(_target.querySelector(selector))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select multiple DOM element and wrap them
|
|
||||||
* @param {string} selector
|
|
||||||
* @returns {Array.<WrappedElement>}
|
|
||||||
*/
|
|
||||||
const selectAll = (selector, _target = document) => [..._target.querySelectorAll(selector)].map(_ => wrap(_))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap existing DOM element
|
|
||||||
* @param {HTMLElement} element
|
|
||||||
* @returns {WrappedElement}
|
|
||||||
*/
|
|
||||||
const wrap = element => new WrappedElement(element)
|
|
||||||
|
|
||||||
const sleep = s => new Promise(r => setTimeout(r, s*1000))
|
|
||||||
|
|
||||||
|
|
||||||
class WrappedElement {
|
|
||||||
/**
|
|
||||||
* @type {HTMLElement}
|
|
||||||
*/
|
|
||||||
element
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create element wrapper
|
|
||||||
* @param {HTMLElement} element
|
|
||||||
*/
|
|
||||||
constructor(element) {
|
|
||||||
this.element = element
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override element classes
|
|
||||||
* @param {...string} list
|
|
||||||
* @returns {WrappedElement} this element for chaining
|
|
||||||
*/
|
|
||||||
classes(...list) {
|
|
||||||
this.element.classList = list.join(' ')
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get elements styles to edit them
|
|
||||||
* @returns {CSSStyleDeclaration}
|
|
||||||
*/
|
|
||||||
styles () {
|
|
||||||
return this.element.style
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get element nodes
|
|
||||||
* @returns {Array.<WrappedElement>}
|
|
||||||
*/
|
|
||||||
nodes () {
|
|
||||||
return [...this.element.childNodes].map(e => wrap(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply animation to element (async)
|
|
||||||
* @param {string} animation_name
|
|
||||||
* @param {number} animation_duration
|
|
||||||
* @param {string} animation_function_name
|
|
||||||
* @returns {WrappedElement} this element for chaining
|
|
||||||
*/
|
|
||||||
async animate (animation_name, animation_duration, animation_function_name = '') {
|
|
||||||
this.styles().animation = `${animation_name} ${animation_duration}s ${animation_function_name}`
|
|
||||||
await sleep(animation_duration - (animation_duration / 20))
|
|
||||||
this.styles().animation = ``
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear element content (async)
|
|
||||||
* @returns {WrappedElement} this element for chaining
|
|
||||||
*/
|
|
||||||
async clear () {
|
|
||||||
this.element.innerHTML = ''
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwrite element content (async)
|
|
||||||
* @param {...HTMLElement} children
|
|
||||||
* @returns {WrappedElement} this element for chaining
|
|
||||||
*/
|
|
||||||
async overwrite (...children) {
|
|
||||||
this.clear()
|
|
||||||
this.append(...children)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Add content to element (async)
|
|
||||||
* @param {...HTMLElement} children
|
|
||||||
* @returns {WrappedElement} this element for chaining
|
|
||||||
*/
|
|
||||||
async append (...children) {
|
|
||||||
children.forEach(child => {
|
|
||||||
if (typeof child === 'string' || typeof child === 'number') {
|
|
||||||
this.element.innerHTML += child
|
|
||||||
} else if (child instanceof Node) {
|
|
||||||
this.element.appendChild(child)
|
|
||||||
} else if (child instanceof WrappedElement) {
|
|
||||||
this.element.appendChild(child.element)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Removes element (async)
|
|
||||||
*/
|
|
||||||
async remove() {
|
|
||||||
this.element.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return element node by selector
|
|
||||||
* @param {string} selector
|
|
||||||
* @returns {WrappedElement}
|
|
||||||
*/
|
|
||||||
select (selector) {
|
|
||||||
return select(selector, this.element)
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Return element nodes by selector
|
|
||||||
* @param {string} selector
|
|
||||||
* @returns {Array.<WrappedElement>}
|
|
||||||
*/
|
|
||||||
selectAll (selector) {
|
|
||||||
return selectAll(selector, this.element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Body = select('body')
|
|
||||||
Loading…
Add table
Reference in a new issue