diff --git a/README.md b/README.md index fa27b1d..7b3d442 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,6 @@ This can be used for bot embed commands commands, although I understand that not You can look into the [project boards](https://github.com/Glitchii/embedbuilder/projects/3) if you want to see what is being worked on or want to contribute.

-![Layout image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/layout.png) +![GUI image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/gui.png) ![JSON image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/json.png) [To Do](https://github.com/Glitchii/embedbuilder/projects/3) | [Discussions](https://github.com/Glitchii/embedbuilder/discussions/1) \ No newline at end of file diff --git a/assets/css/index.css b/assets/css/index.css index 16f419c..1317609 100644 --- a/assets/css/index.css +++ b/assets/css/index.css @@ -89,21 +89,20 @@ body { overflow: auto; } -.bottom { - height: 30%; - display: none; -} - .side1 .item.top { background-color: #292b2f; width: 100%; - height: 100%; + height: 94%; border-radius: 5px; - margin: auto; + transform: translateY(10px); } -.item~.item { - margin-top: 15px; +body.gui .side1 .item.top { + transform: translateY(20px); +} + +.top, .bottom { + margin: auto; } .main .side2 { @@ -218,12 +217,16 @@ img[alt] { .msgEmbed { min-height: 2.75rem; - padding: 0.125rem 0 20px 72px; position: absolute; overflow-wrap: break-word; user-select: text; - width: 96%; - margin: 10px 20px 0 20px; + width: 100%; + margin: 10px 0 0 0; + padding: calc(0.125rem + 10px) 20px 20px 92px; +} + +.msgEmbed:hover { + background-color: #04040512; } .embedTitle>* { @@ -239,7 +242,7 @@ img[alt] { .avatar { position: absolute; - left: 16px; + left: 36px; margin-top: calc(4px - 0.125rem); width: 40px; height: 40px; @@ -685,7 +688,7 @@ u { color: #f45711; font-size: 20px; position: relative; - left: -2px; + left: 10px; top: -3px; } @@ -715,6 +718,19 @@ u { .CodeMirror-gutters { background: #292b2f!important; + display: none; +} + +.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like { + padding: 0 12px; +} + +.CodeMirror-lint-marker.CodeMirror-lint-marker-error { + left: 15px!important; +} + +.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like { + padding: 0 15px!important; } .CodeMirror-foldmarker { @@ -797,17 +813,798 @@ u { z-index: 5; } -@media screen and (max-width: 1015px) { - .main { - display: flex; - flex-direction: column; +.col.cm-string.cm-property::before { + content: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512 512' xml:space='preserve'%3E%3Cpath style='fill:%23D8D8DA;' d='M256,0C114.615,0,0,114.615,0,256s114.615,256,256,256s256-114.615,256-256S397.385,0,256,0z M256,336.842c-44.648,0-80.842-36.194-80.842-80.842s36.194-80.842,80.842-80.842s80.842,36.194,80.842,80.842 S300.648,336.842,256,336.842z'/%3E%3Cpath style='fill:%23D4B6E6;' d='M282.947,188.632h220.076C485.09,122.726,441.507,67.394,383.64,34.044L229.053,188.632H282.947z'/%3E%3Cpath style='fill:%23EBAFD1;/*! fill: %23e592bf; */' d='M229.053,188.632L383.639,34.044C346.068,12.39,302.482,0,256,0c-23.319,0-45.899,3.135-67.368,8.978 v220.075L229.053,188.632z'/%3E%3Cpath style='fill:%23E07188;' d='M188.632,229.053V8.978C122.726,26.91,67.394,70.493,34.045,128.36l154.586,154.588V229.053z'/%3E%3Cg%3E%3Cpolygon style='fill:%23D8D8DA;' points='188.632,229.053 229.053,188.633 282.947,188.633 282.947,188.632 229.053,188.632 '/%3E%3Cpolygon style='fill:%23D8D8DA;' points='229.053,323.367 188.632,282.947 229.053,323.368 282.947,323.368 323.368,282.947 282.947,323.367 '/%3E%3C/g%3E%3Cpath style='fill:%23B4D8F1;' d='M503.024,188.632H282.947v0.001h0.958l39.463,40.42L477.955,383.64 C499.611,346.068,512,302.482,512,256C512,232.681,508.865,210.099,503.024,188.632z'/%3E%3Cpath style='fill:%23ACFFF4;' d='M323.368,282.947v220.075c65.905-17.932,121.238-61.517,154.586-119.382L323.368,229.053V282.947z'/%3E%3Cpath style='fill:%2395D5A7;' d='M282.947,323.368L128.361,477.956C165.932,499.61,209.518,512,256,512 c23.319,0,45.899-3.135,67.368-8.977V282.947L282.947,323.368z'/%3E%3Cpath style='fill:%23F8E99B;' d='M229.053,323.368H8.976C26.91,389.274,70.493,444.606,128.36,477.956l154.588-154.588H229.053z'/%3E%3Cpath style='fill:%23EFC27B;' d='M188.632,282.947L34.045,128.36C12.389,165.932,0,209.518,0,256c0,23.319,3.135,45.901,8.976,67.368 h220.076L188.632,282.947z'/%3E%3Cpolygon style='fill:%23E3E3E3;' points='283.905,188.633 282.947,188.633 323.368,229.053 '/%3E%3Cpath style='fill:%23B681D5;' d='M503.024,188.632C485.09,122.726,441.507,67.394,383.64,34.044L256,161.684v26.947h26.947H503.024z'/%3E%3Cpath style='fill:%23E592BF;' d='M383.639,34.044C346.068,12.39,302.482,0,256,0v161.684L383.639,34.044z'/%3E%3Cpath style='fill:%2380CB93;' d='M256,350.316V512c23.319,0,45.899-3.135,67.368-8.977V282.947l-40.421,40.421L256,350.316z'/%3E%3Cpolygon style='fill:%23F6E27D;' points='282.947,323.368 256,323.368 256,350.316 '/%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E"); + width: 15px; + height: 100px; + display: block; + background-repeat: no-repeat; + position: absolute; + top: 0; + left: 40px; + cursor: pointer; + opacity: .5; + transition: 1s ease; +} + +.CodeMirror:hover .col.cm-string.cm-property::before { + opacity: 1; +} + +body.gui .side1 .item.top { + max-width: 90%; + height: 70%; + border-radius: 15px; +} + +body.gui .top>.CodeMirror { + display: none; +} + +.top>.gui { + height: 100px; + height: 100%; + width: 100%; + background: #292b2f; + border-radius: 5px; + overflow-y: scroll; + overflow-x: hidden; + scrollbar-color: #202225 #292b2f; + scrollbar-width: thin; +} + +body:not(.gui) .top>.gui, body:not(.gui) .bottom, body:not(.gui) .pickerToggle { + display: none; +} + +.chooser { + display: flex; + height: 40px; + width: 100px; + border-radius: 5px; + margin-bottom: 10px; + padding: 7px; + background: #1b1c2061; + box-shadow: -2px -2px 10px 0px #0000; +} + +.chooser>.opt { + width: 50px; + cursor: pointer; + background: #292b2f; + border-radius: 4px; +} + +body.gui .chooser>.gui { + background: #41444a; +} + +body:not(.gui) .chooser>.json { + background: #41444a; +} + +.chooser>.back { + position: absolute; + height: 26px; + width: 43px; + border-radius: 4px; + background: #41444a; + transition: .5s ease-out; + pointer-events: none; +} + +body:not(.gui) .chooser>.back { + transform: translateX(43px); +} + +.chooser>.opt p { + display: flex; + justify-content: center; + font-size: 10px; + position: relative; + top: 50%; + transform: translateY(-50%); + pointer-events: none; +} + +.bottom { + height: 40%; + margin: 40px auto auto auto!important; + max-width: 90%; +} + +@keyframes colrsAn { + 0% { + transform: translateX(-200px); + opacity: 0; } - .side1 .item.top { - height: 100%; +} + +.bottom .colrs { + animation: colrsAn .5s ease-out; + background: #212226; + border-radius: 10px; + width: 250px; + height: 130px; + position: absolute; + bottom: 20px; + box-shadow: -3px 3px 5px 0px #00000029; + display: grid; + grid-template-columns: 27% 73%; + grid-template-columns: 5% 27.5% 67.5%; +} + +.bottom .colrs .colr { + background: #41f097; +} + +.bottom .colrs.display { + display: grid; +} + +.colLeft { + border-radius: 15px; +} + +.colLeft .picker { + background: #292b2f; + border: 1px solid #ffffff24; +} + +.colLeft .picker>svg { + top: 7px; + right: 10px; + width: 16px; + height: 16px; + position: absolute; +} + +.col.colLeft>* { + border-radius: 8px; + cursor: pointer; +} + +.colRight { + margin: 0 10px; +} + +.cTop { + width: 100%; +} + +.cTop>h2 { + font-weight: 900; + margin-top: 10px; +} + +.cTop .desc { + font-size: 12px; + opacity: .6; + margin-top: 5px; +} + +.col { + display: grid; + grid-template-rows: 45% 45%; + gap: 10px; + height: 80%; + transform: translateY(-50%); + top: 50%; + position: relative; +} + +.pallets { + width: 100%; + display: grid; + /* grid-template-columns: repeat(8, 1fr); */ + grid-template-columns: repeat(6, minmax(25px, 1fr)); + gap: 5px 0px; + /* opacity: .7; */ + transition: .5s; +} + +.colrs:hover .pallets { + opacity: 1; +} + +.pallets>* { + background: black; + width: 17px; + height: 17px; + margin-left: 5px; + border-radius: 2px; + cursor: pointer; +} + +.color-picker { + transform: none; + width: 100%; + height: 100%; + top: 0!important; + left: 0!important; + border-radius: 10px; + overflow: hidden; +} + +.color-picker>div { + height: 100%!important; +} + +.colRight.picking .cTop>*:not(.color-picker), .colRight.picking .pallets, .colRight:not(.picking) .colBack { + display: none; +} + +.color-picker\:a { + display: none!important; +} + +@keyframes colBackAn { + from { + right: 50px; } - .notification .inline { - display: block; - margin-top: 5px; +} + +.colBack { + animation: colBackAn .2s ease-out; + position: absolute; + right: 0; + transform: translateX(40px); + z-index: 1000; + cursor: pointer; +} + +.colBack svg { + width: 20px; + height: 20px; + opacity: .6; +} + +.top { + scrollbar-color: #202225 #292b2f; + scrollbar-width: thin; + overflow: hidden; +} + +.top>.gui>.item { + cursor: pointer; + background: #212226; + height: 40px; + width: 90%; + margin: 8px auto; + border-radius: 7px; + background: linear-gradient(90deg, #212226, #21222600); + position: relative; + z-index: 2; +} + +.top>.gui>.item.active .ttle::after { + transform: scale(.8) rotate(180deg); +} + +.top>.gui>.item.active .ttle::after { + transform: scale(.8) rotate(180deg); +} + +.top>.gui>.item.inlineField.active .ttle, .top>.gui>.item:not(.active) .ttle~input { + display: none; +} + +.ttle, .ttle~input { + font-size: 12px; + font-weight: 900; + text-transform: uppercase; + position: relative; + top: 50%; + transform: translateY(-50%); + margin-left: 15px; +} + +.top>.gui>.item.active .ttle~input:not(:placeholder-shown) { + font-weight: normal; + text-transform: none; + font-size: 12px; +} + +input, textarea { + background: transparent; + border: none; + color: inherit; +} + +.ttle~input { + width: 100%; +} + +.ttle::after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' viewBox='0 0 24 24' height='30'%3E%3Cpath clip-rule='evenodd' fill='%23fff' d='M16.59 8.59004L12 13.17L7.41 8.59004L6 10L12 16L18 10L16.59 8.59004Z'%3E%3C/path%3E%3C/svg%3E"); + position: absolute; + right: 0; + top: -12px; + transform: scale(.8); + opacity: .1; + pointer-events: none; + transition: .2s ease; +} + +@keyframes editAn { + from { + opacity: 0; + transform: translateY(-40px); + } +} + +.top>.gui>.item~.edit { + animation: editAn .3s ease; + height: 40px; + width: 90%; + margin: 8px auto; + position: relative; + border-bottom-left-radius: 7px; + border-bottom-right-radius: 7px; + margin-top: 0; + background: #212226; +} + +.top>.gui>.item~.edit input { + align-self: start; + font-size: 13px; + position: relative; + margin-left: 15px; + transform: translateY(4px); +} + +.top>.gui>.item:not(.active)+.edit { + display: none; +} + +.top>.gui>.item:not(.inlineField).active { + margin-bottom: 0; + background: #212226; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.edit { + padding-left: 15px; +} + +.item:not(.rows2)+.edit { + display: flex; +} + +.editIcon { + display: flex; +} + +.editIcon, .editName, .editIcon input, .editName input { + width: 100%; + overflow: hidden; +} + +.editIcon .imgParent { + width: 24px; + height: 24px; + object-fit: contain; + border-radius: 50%; +} + +.editIcon>* { + display: inline-flex; +} + +.pickerToggle { + display: none; + bottom: 15px; + left: 15px; + position: absolute; + cursor: pointer; + z-index: 5; +} + +.pickerToggle>svg { + width: 20px; + height: 100%; +} + +textarea { + font-size: 13px; + min-width: 100%; + max-width: 100%!important; + height: 75px; + max-height: 200px; +} + +.top>.gui>.item.description+.edit, .top>.gui>.item.content+.edit { + height: auto; +} + +.top>.gui>.item.content+.edit textarea { + height: 80px; +} + +.browse { + margin-top: 25px; + font-size: 13px; + display: flex; + cursor: pointer; + position: absolute; + opacity: .5; +} + +.browse:hover { + opacity: 1; +} + +.browse>svg { + width: 20px; + position: relative; + z-index: 6; + height: 20px; + transform: translateY(-5px); + margin-right: 5px; +} + +.browse>p::after { + content: "Browse"; +} + +.browse.loading>svg:first-of-type, .browse:not(.loading)>svg:last-of-type, .browse.error>svg { + display: none; +} + +.browse.loading>p::after { + content: "Loading..."; +} + +.browse.error>p::after { + color: #ee9191; + content: "Request failed. (Check dev-tools)"; +} + +.linkName { + display: flex; +} + +.linkName, .linkName .txtCol, .linkName .txtCol>input[type="text"] { + width: 100%; + text-overflow: ellipsis; +} + +.txtCol>input[type="text"] { + overflow: auto; +} + +.top>.gui>.item.rows2+.edit { + height: 80px; +} + +input[type="file"], button[type="submit"] { + display: none; +} + +.largeImg+.edit .editIcon .imgParent { + width: 80px; + height: 80px; + border-radius: 4px; + object-fit: fill; + margin-top: 0; + margin-bottom: 15px; +} + +.top>.gui>.largeImg+.edit input { + transform: none; +} + +.largeImg+.edit .browse { + margin-top: 40px; + font-size: 13px; + display: flex; + cursor: pointer; + position: relative; + opacity: .5; + margin-left: 15px; +} + +.largeImg.image+.edit .browse { + margin-top: 35px; +} + +.largeImg+.edit .editIcon>* { + display: block; +} + +.largeImg+.edit { + height: auto!important; +} + +.largeImg.image+.edit .editIcon .imgParent { + width: 130px; + object-fit: contain; + border-radius: 4px; + object-fit: cover; +} + +.top>.gui>.item.fields+.edit input { + margin-left: 0; +} + +.top>.gui>.item.fields+.edit input[type="text"] { + width: 100%; +} + +.top>.gui>.item.fields+.edit { + height: auto; + padding-bottom: 15px; +} + +.top>.gui>.item.fields.active+.edit { + display: block; +} + +.designerFieldName { + width: 95%; + min-height: 30px; + border-radius: 5px; +} + +.designerFieldValue textarea { + padding: 5px 10px; +} + +.designerFieldName { + width: 100%; + min-height: 30px; + padding: 5px 10px; + margin-bottom: 2px; +} + +.designerFieldName>input[type="text"] { + font-weight: 700; +} + +.field~.field { + margin-top: 10px; +} + +.field .fieldInner { + width: 95%; + height: 100%; + border-radius: 4px; + background: #292b2f; + border-radius: 5px; + margin-bottom: 2px; + transition: .3s ease; +} + +@keyframes lastFieldSlide { + from { + opacity: 0; + transform: translateY(100px); + } +} + +.gui>.item.fields+.edit>.field { + animation: lastFieldSlide .5s ease; +} + +.fields+.edit .fieldInner .designerFieldName { + background: #2d2e33; +} + +body { + counter-reset: fieldCount; +} + +.fieldNumber { + position: absolute; +} + +.fields+.edit { + z-index: 2; +} + +@keyframes fieldNumberFadeInAn { + from { + opacity: 0; + transition: opacity 1s ease; + } +} + +.fieldNumber::before { + animation: fieldNumberFadeInAn .2s ease-in; + counter-increment: fieldCount; + content: counter(fieldCount); + position: relative; + font-size: 20px; + right: 41px; + top: 22px; + z-index: -2; + opacity: .15; +} + +.inlineCheck, .removeBtn { + font-size: 11px; + font-weight: bold; + text-transform: uppercase; + cursor: pointer; + display: inline-block; + margin-top: 3px; +} + +#inlineCheck, [for="inlineCheck"] { + cursor: pointer; +} + +.removeBtn { + margin-left: 20PX; +} + +.removeBtn>svg { + width: 10px; + height: 10px; + transition: .5s ease; +} + +.removeBtn>span { + margin-left: 3px; + position: relative; + top: -1px; + transition: .5s ease; +} + +.removeBtn:hover>span, .removeBtn:hover>svg path { + color: #ff9191; + fill: #ff9191; +} + +.inlineCheck input[type="checkbox"] { + scale: .8; + cursor: pointer; +} + +.inlineCheck input[type="checkbox"]+span { + cursor: pointer; +} + +.sep { + width: 100%; + height: 2px; + background: linear-gradient(to right, #2f313600, #2f3136, #2f313600); +} + +.imgParent { + border-radius: 4px; + object-fit: fill; + margin-top: 0; + content: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0' y='0' width='1400' height='780' viewBox='0, 0, 1400, 780'%3E%3Cg id='Background'%3E%3Crect x='0' y='0' width='1400' height='780' style='fill: %23212226;' fill='%23363A3E'/%3E%3C/g%3E%3Cg id='Background'/%3E%3Cg id='Background'%3E%3Cg%3E%3Cpath d='M463.326,212.495 L936.674,212.495 L936.674,567.505 L463.326,567.505 z' fill-opacity='0' stroke='%2343474B' stroke-width='30' stroke-miterlimit='10' style='stroke: %23888789;fill: %23888789;'/%3E%3Cpath d='M605.33,309.136 C605.33,328.961 589.259,345.032 569.435,345.032 C549.61,345.032 533.539,328.961 533.539,309.136 C533.539,289.312 549.61,273.241 569.435,273.241 C589.259,273.241 605.33,289.312 605.33,309.136 z' fill='%2343474B' style='fill: %23888789;'/%3E%3Cpath d='M878.689,507.548 L523.284,507.548 L570.618,406.173 L600.597,450.352 L700.789,298.092 L772.58,405.778 L806.503,368.699 z' fill='%2343474B' style='fill: %23888789;'/%3E%3C/g%3E%3C/g%3E%3Cstyle xmlns='http://www.w3.org/1999/xhtml' type='text/css'%3E%3C/style%3E%3C/svg%3E"); +} + +.largeImg+.edit .imgParent { + margin-bottom: 15px; +} + +.item:not(.largeImg)+.edit .imgParent[style*="content"] { + transform: scale(1); +} + +.item:not(.largeImg)+.edit .imgParent { + transform: scale(2); +} + +@keyframes addFieldFade { + from { + opacity: 0; + } +} + +.addField { + animation: addFieldFade .5s ease; + font-size: 13px; + display: flex; + cursor: pointer; + opacity: .5; + padding-top: 15px; + transition: .5s ease; +} + +.field+.addField { + margin-top: 5px; +} + +.addField>svg { + width: 16px; + position: relative; + z-index: 6; + height: 100%; + transform: translateY(-3px); + margin-left: 5px; + opacity: .8; +} + +.addField:hover, .addField:hover>svg { + opacity: 1; +} + +.clear { + left: 140px; + position: absolute; + cursor: pointer; + z-index: 5; + transform: translate(0, -5px); + padding: 8.5px; + border-radius: 100%; + background: #27282e; + width: 35px; + height: 35px; + transition: .5s ease; +} + +@keyframes emptyTxtAn { + from { + opacity: 0; + } +} + +.emptyTxt { + animation: emptyTxtAn 1s ease; + font-weight: 600; + text-transform: uppercase; + font-size: 30px; + line-height: 16px; + color: #41444a; + font-family: var(--font2); + padding: 10px 0; + top: 50%; + position: absolute; + left: 50%; + transform: translate(-50%, -50%); + pointer-events: none; +} + +@keyframes clearAn { + 0% { + transform: rotate(10deg); + } + 25% { + transform: rotate(-10deg); + } + 50% { + transform: rotate(10deg); + } + 75% { + transform: rotate(-13deg); + } +} + +.clear:hover>svg { + animation: clearAn 1s ease-in-out forwards; + transform-origin: top right; +} + +.side2:not(.empty) .emptyTxt { + display: none; +} + +.clear>svg { + width: 20px; + height: 100%; + position: relative; + left: -2.5px; + top: -2px; +} + +::-webkit-scrollbar { + width: 7px; + background: #292b2f00; +} + +::-webkit-scrollbar-thumb { + background: #202225; +} + +@media screen and (max-width: 1270px) { + .fieldNumber::before { + right: 300%; } } @@ -822,4 +1619,79 @@ u { .main .side1 { padding: 10px; } +} + +@media screen and (max-height: 760px) { + .bottom .colrs { + bottom: 10px; + } + body.gui .side1 .item.top { + height: 65%; + max-width: 100%; + width: 100%; + } + .bottom { + margin: 40px 0 0 0 !important; + } +} + +@media screen and (max-width: 1015px) { + .clear { + position: absolute; + cursor: pointer; + z-index: 5; + left: 135px; + } + .main { + display: flex; + flex-direction: column; + } + .side1 .item.top { + height: 100%; + } + .notification .inline { + display: block; + margin-top: 5px; + } + .bottom .colrs { + bottom: 40px; + left: 200px; + display: none; + top: 0; + animation: colrsAn .1s ease-out; + box-shadow: 0px 5px 15px 0px #0000004f; + } + body.gui .side1 .item.top { + height: 85%; + max-width: 100%; + width: 100%; + } + .bottom { + margin: 40px 0 0 0 !important; + } + .pickerToggle { + display: block; + position: absolute; + cursor: pointer; + z-index: 5; + left: 170px; + border-left: 2px solid #4c5057; + padding-left: 15px; + bottom: auto; + margin-left: 15px; + } + .pickerToggle>svg { + width: 17px; + } + .side1 .item.top { + padding-top: 10px; + transform: translateY(10px); + } +} + +@media screen and (max-width: 460px) { + .bottom .colrs { + top: 70px; + left: 10px; + } } \ No newline at end of file diff --git a/assets/js/components.js b/assets/js/components.js index 29b6276..12ad854 100644 --- a/assets/js/components.js +++ b/assets/js/components.js @@ -2910,6 +2910,7 @@ var emojis = { "sob": "😭", "smiling_imp": "😈", "slight_smile": "🙂", + "pensive": "😔", "angry": "😠", "blush": "😊", "confused": "😕", diff --git a/assets/js/index.js b/assets/js/index.js index b45eb22..fb1bbe0 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -2,23 +2,86 @@ // Want to use or contribute to this? https://github.com/Glitchii/embedbuilder // If you found an issue, please report it, make a P.R, or use the discussion page. Thanks -var colNum = 1, num = 0; +var activeFields, colNum = 1, num = 0, + toRGB = (hex, reversed, integer) => { + if (reversed) return '#' + hex.match(/[\d]+/g).map(x => parseInt(x).toString(16).padStart(2, '0')).join(''); + if (integer) return parseInt(hex.match(/[\d]+/g).map(x => parseInt(x).toString(16).padStart(2, '0')).join(''), 16); + if (hex.includes(',')) return hex.match(/[\d]+/g); + hex = hex.replace('#', '').match(/.{1,2}/g) + return [parseInt(hex[0], 16), parseInt(hex[1], 16), parseInt(hex[2], 16), 1]; + }, json = { + content: "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~", + embed: { + title: "Hello ~~people~~ world :wave:", + description: "You can use [links](https://discord.com) or emojis :smile: 😎\n```\nAnd also code blocks\n```", + color: 4321431, + timestamp: "2020-12-08T13:37:35.401Z", + url: "https://discord.com", + author: { + name: "Author name", + url: "https://discord.com", + icon_url: "https://unsplash.it/100" + }, + thumbnail: { + url: "https://unsplash.it/200" + }, + image: { + url: "https://unsplash.it/380/200" + }, + footer: { + text: "Footer text", + icon_url: "https://unsplash.it/100" + }, + fields: [ + { + name: "Field 1, *lorem* **ipsum**, ~~dolor~~", + value: "Field value" + }, + { + name: "Field 2", + value: "You can use custom emojis <:Kekwlaugh:722088222766923847>. <:GangstaBlob:742256196295065661>", + inline: false + }, + { + name: "Inline field", + value: "Fields can be inline", + inline: true + }, + { + name: "Inline field", + value: "*Lorem ipsum*", + inline: true + }, + { + name: "Inline field", + value: "value", + inline: true + }, + { + name: "Another field", + value: "> Nope, didn't forget about code blocks", + inline: false + } + ] + } + }; + window.onload = () => { document.querySelectorAll('img.clickable') .forEach(e => e.addEventListener('click', el => window.open(el.target.src))); - let textarea = document.querySelector('textarea'); - window.editor = CodeMirror(elt => textarea.parentNode.replaceChild(elt, textarea), { - value: textarea.value, - theme: 'material-darker', + let editorHolder = document.querySelector('.editorHolder'), + guiParent = document.querySelector('.top'), + gui = guiParent.querySelector('.gui:first-of-type'); + window.editor = CodeMirror(elt => editorHolder.parentNode.replaceChild(elt, editorHolder), { + value: JSON.stringify(json, null, 4), + extraKeys: { Tab: cm => cm.replaceSelection(" ", "end") }, + gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"], scrollbarStyle: "overlay", mode: "application/json", - foldGutter: true, - gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"], + theme: 'material-darker', matchBrackets: true, + foldGutter: true, lint: true, - extraKeys: { - "Tab": cm => cm.replaceSelection(" ", "end") - } }); editor.focus(); @@ -57,7 +120,7 @@ window.onload = () => { .replace(/\n/g, '
'); return txt; }, - content = document.querySelector('.messageContent'), + embedContent = document.querySelector('.messageContent'), embed = document.querySelector('.embedGrid'), msgEmbed = document.querySelector('.msgEmbed'), embedTitle = document.querySelector('.embedTitle'), @@ -66,7 +129,7 @@ window.onload = () => { embedFooter = document.querySelector('.embedFooter'), embedImage = document.querySelector('.embedImage'), embedThumbnail = document.querySelector('.embedThumbnail'), - fields = embed.querySelector('.embedFields'), + embedFields = embed.querySelector('.embedFields'), tstamp = stringISO => { let date = stringISO ? new Date(stringISO) : new Date(), dateArray = date.toLocaleString('en-US', { hour: 'numeric', hour12: true, minute: 'numeric' }), @@ -79,84 +142,516 @@ window.onload = () => { if (data) el.innerHTML = data; el.style.display = displayType || "unset"; }, hide = el => el.style.removeProperty('display'), - toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)), - update = data => { - try { - content.innerHTML = data.content ? markup(data.content, { replaceEmojis: true }) : ''; - if (data.embed) { - let e = data.embed; - if (!allGood(e)) return; - if (e.title) display(embedTitle, markup(`${e.url ? '' + e.title + '' : e.title}`, { replaceEmojis: true, inlineBlock: true })); - else hide(embedTitle); - if (e.description) display(embedDescription, markup(e.description, { inEmbed: true, replaceEmojis: true })); - else hide(embedDescription); - if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16) : e.color); - else embed.closest('.embed').style.removeProperty('border-color'); - if (e.author && e.author.name) display(embedAuthor, ` - ${e.author.icon_url ? '' : ''} - ${e.author.url ? '' + e.author.name + '' : '' + e.author.name + ''}`, 'flex'); - else hide(embedAuthor); - if (e.thumbnail && e.thumbnail.url) embedThumbnail.src = e.thumbnail.url, embedThumbnail.style.display = 'block'; - else hide(embedThumbnail); - if (e.image && e.image.url) embedImage.src = e.image.url, embedImage.style.display = 'block'; - else hide(embedImage); - if (e.footer && e.footer.text) display(embedFooter, ` - ${e.footer.icon_url ? '' : ''} - ${e.footer.text} - ${e.timestamp ? '•' + tstamp(e.timestamp) : ''}`, 'flex'); - else if (e.timestamp) display(embedFooter, `${tstamp(e.timestamp)}`, 'flex'); - else hide(embedFooter); - if (e.fields) { - fields.innerHTML = ''; - e.fields.forEach(f => { + imgSrc = (elm, src, remove) => remove ? elm.style.removeProperty('content') : elm.style.content = `url(${src})`, + toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)); + buildGui = (object, opts) => { + gui.innerHTML = ` +

Message content

+
+ +
+

Author

+
+
+
+ + +
+
+ +
+
+
+ + + +
+
+
+

Title

+ +
+

Description

+
+ +
+

Fields

+
+

Thumbnail

+
+
+
+ +
+ +
+ + + +
+
+
+
+
+

Image

+
+
+
+ +
+ +
+ + + +
+
+
+
+
+ +
+
+
+ + +
+
+ +
+
+
+ + + +
+
`; + + let fieldsEditor = gui.querySelector('.fields ~ .edit'), addField = ` +
+

New Field

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
`; + if (object.embed?.fields) fieldsEditor.innerHTML = object.embed.fields.filter(f => f && typeof f === 'object').map(f => ` +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ + + + + + Remove +
+
`).join('\n') + addField; + else fieldsEditor.innerHTML = addField; + + gui.querySelectorAll('.removeBtn').forEach(e => { + e.addEventListener('click', el => { + fields = gui.querySelector('.fields ~ .edit'); + let field = el.target.closest('.field'); + if (field) { + let i = Array.from(fields.children).indexOf(field), jsonField = object.embed.fields[i]; + if (jsonField) { + object.embed.fields.splice(i, 1); + field.remove(); + update(object); + } + } + }) + }) + + document.querySelectorAll('.gui > .item').forEach(e => { + e.addEventListener('click', el => { + let elm = (el.target.closest('.top>.gui>.item') || el.target); + if (elm.classList.contains('active')) window.getSelection().anchorNode !== elm && elm.classList.remove('active'); + else { + let inlineField = elm.closest('.inlineField'), + input = elm.nextElementSibling.querySelector('input[type="text"]'), + txt = elm.nextElementSibling.querySelector('textarea'); + elm.classList.add('active'); + if (inlineField) inlineField.querySelector('.ttle~input').focus(); + else if (input) { + input.focus(); + input.selectionStart = input.selectionEnd = input.value.length; + } else if (txt) txt.focus(); + elm.classList.contains('fields') && elm.scrollIntoView({ behavior: "smooth", block: "center" }); + } + }) + }) + + content = gui.querySelector('.editContent'); + title = gui.querySelector('.editTitle'); + authorName = gui.querySelector('.editAuthorName'); + authorLink = gui.querySelector('.editAuthorLink'); + desc = gui.querySelector('.editDescription'); + thumbLink = gui.querySelector('.editThumbnailLink'); + imgLink = gui.querySelector('.editImageLink'); + footerText = gui.querySelector('.editFooterText'); + footerLink = gui.querySelector('.editFooterLink'); + fields = gui.querySelector('.fields ~ .edit'); + + document.querySelector('.addField').addEventListener('click', () => { + !json.embed && (json.embed = {}); + let arr = json.embed.fields || []; + arr.push({ name: "Field name", value: "Field value", inline: false }); + json.embed.fields = arr; + update(json); + buildGui(json, { newField: true, activate: document.querySelectorAll('.gui > .item.active') }); + }) + + gui.querySelectorAll('textarea, input').forEach(e => e.addEventListener('input', el => { + let v = el.target.value, field = el.target.closest('.field'); + if (field) { + let jsonField = json.embed.fields[Array.from(fields.children).indexOf(field)]; + if (jsonField) { + if (el.target.type === 'text') jsonField.name = v; + else if (el.target.type === 'textarea') jsonField.value = v; + else jsonField.inline = el.target.checked; + } else { + let obj = {} + if (el.target.type === 'text') obj.name = v; + else if (el.target.type === 'textarea') obj.value = v; + else obj.inline = el.target.checked; + json.embed.fields.push(obj); + } + } else { + json.embed ??= {}; + switch (el.target) { + case content: json.content = v; break; + case title: json.embed.title = v; break; + case authorName: json.embed.author ??= {}, json.embed.author.name = v; break; + case authorLink: json.embed.author ??= {}, json.embed.author.icon_url = v, imgSrc(el.target.previousElementSibling, v); break; + case desc: json.embed.description = v; break; + case thumbLink: json.embed.thumbnail ??= {}, json.embed.thumbnail.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break; + case imgLink: json.embed.image ??= {}, json.embed.image.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break; + case footerText: json.embed.footer ??= {}, json.embed.footer.text = v; break; + case footerLink: json.embed.footer ??= {}, json.embed.footer.icon_url = v, imgSrc(el.target.previousElementSibling, v); break; + } + } + update(json); + })) + + if (opts?.activate) { + let elements = opts.activate; + Array.from(elements).map(el => el.className).map(clss => '.' + clss.split(' ').slice(0, 2).join('.')) + .forEach(clss => document.querySelectorAll(clss) + .forEach(e => e.classList.add('active'))) + } else['.item.author', '.item.description'].forEach(clss => document.querySelector(clss).classList.add('active')); + + if (opts?.newField) { + let last = fields.children[fields.childElementCount - 2], el = last.querySelector('.designerFieldName > input'); + el.setSelectionRange(el.value.length, el.value.length); el.focus(); + last.scrollIntoView({ behavior: "smooth", block: "center" }); + // setTimeout(() => last.animate([ + // { opacity: '.2', offset: .25 }, + // { opacity: '1', offset: .5 }, + // { opacity: '.2', offset: .75 }, + // { opacity: '1', offset: 1 } + // ], { easing: 'ease', duration: 1500 }), 250); + } + + let files = document.querySelectorAll('input[type="file"]'); + files.forEach(f => f.addEventListener('change', e => { + if (f.files) { + e.target.nextElementSibling.click(); + e.target.closest('.edit').querySelector('.browse').classList.add('loading'); + } + })) + + document.querySelectorAll('form').forEach(form => form.addEventListener('submit', e => { + e.preventDefault(); + let formData = new FormData(e.target); + formData.append('file', files.files); + formData.append('datetime', '10m'); + fetch('https://tempfile.site/api/files', { + method: 'POST', + body: formData, + }) + .then(res => res.json()) + .then(res => { + let browse = e.target.closest('.edit').querySelector('.browse'); + browse.classList.remove('loading'); + if (!res.ok) { + console.log(res.error); + browse.classList.add('error'); + return setTimeout(() => browse.classList.remove('error'), 5000) + } + imgSrc(e.target.previousElementSibling.querySelector('.editIcon > .imgParent') || e.target.closest('.editIcon').querySelector('.imgParent'), res.link); + let input = e.target.previousElementSibling.querySelector('.editIcon > input') || e.target.previousElementSibling; + input.value = res.link; + if (input === authorLink) json.embed.author.icon_url = res.link; + else if (input === thumbLink) json.embed.thumbnail.url = res.link; + else if (input === imgLink) json.embed.image.url = res.link; + else json.embed.footer.icon_url = res.link; + update(json); + console.info(`Image (${res.link}) will be deleted in 5 minutes. To delete it now got to ${res.link.replace('/files', '/del')} and enter this code: ${res.authkey}`); + }).catch(err => `Request to tempfile.site failed with error: ${err}`) + })) + } + + buildGui(json); + fields = gui.querySelector('.fields ~ .edit'); + update = data => { + try { + embedContent.innerHTML = data.content ? markup(data.content, { replaceEmojis: true }) : ''; + if (data.embed && Object.keys(data.embed).length) { + let e = data.embed; + if (!allGood(e)) return; + if (e.title) display(embedTitle, markup(`${e.url ? '' + e.title + '' : e.title}`, { replaceEmojis: true, inlineBlock: true })); + else hide(embedTitle); + if (e.description) display(embedDescription, markup(e.description, { inEmbed: true, replaceEmojis: true })); + else hide(embedDescription); + if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16).padStart(6, "0") : e.color); + else embed.closest('.embed').style.removeProperty('border-color'); + if (e.author && e.author.name) display(embedAuthor, ` + ${e.author.icon_url ? '' : ''} + ${e.author.url ? '' + e.author.name + '' : '' + e.author.name + ''}`, 'flex'); + else hide(embedAuthor); + if (e.thumbnail && e.thumbnail.url) embedThumbnail.src = e.thumbnail.url, embedThumbnail.style.display = 'block'; + else hide(embedThumbnail); + if (e.image && e.image.url) embedImage.src = e.image.url, embedImage.style.display = 'block'; + else hide(embedImage); + if (e.footer && e.footer.text) display(embedFooter, ` + ${e.footer.icon_url ? '' : ''} + ${e.footer.text} + ${e.timestamp ? '•' + tstamp(e.timestamp) : ''}`, 'flex'); + else if (e.timestamp) display(embedFooter, `${tstamp(e.timestamp)}`, 'flex'); + else hide(embedFooter); + if (e.fields) { + embedFields.innerHTML = ''; + e.fields.forEach(f => { + if (f.name && f.value) { if (!f.inline) { - let el = fields.insertBefore(document.createElement('div'), null); + let el = embedFields.insertBefore(document.createElement('div'), null); el.outerHTML = ` -
-
${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}
-
${markup(f.value, { inEmbed: true, replaceEmojis: true })}
-
`; +
+
${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}
+
${markup(f.value, { inEmbed: true, replaceEmojis: true })}
+
`; } else { - el = fields.insertBefore(document.createElement('div'), null); + el = embedFields.insertBefore(document.createElement('div'), null); el.outerHTML = ` -
-
${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}
-
${markup(f.value, { inEmbed: true, replaceEmojis: true })}
-
`; +
+
${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}
+
${markup(f.value, { inEmbed: true, replaceEmojis: true })}
+
`; colNum = (colNum === 9 ? 1 : colNum + 4); num++; } - }); - colNum = 1; - let len = e.fields.filter(f => f.inline).length; - if (len === 2 || (len > 3 && len % 2 !== 0)) { - let children = Array.from(fields.children), arr = children.filter(x => x === children[len] || x === children[len - 1]); - arr[0].style.gridColumn = '1 / 7', arr[1].style.gridColumn = '7 / 13'; } - display(fields, undefined, 'grid'); - } else hide(fields); - embed.classList.remove('empty'); - notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display'); - twemoji.parse(msgEmbed); - } else embed.classList.add('empty'); - } catch (e) { - error(e); - } + }); + colNum = 1; + let len = e.fields.filter(f => f.inline).length; + if (len === 2 || (len > 3 && len % 2 !== 0)) { + let children = Array.from(embedFields.children), arr = children.filter(x => x === children[len] || x === children[len - 1]); + arr[0] && (arr[0].style.gridColumn = '1 / 7'); + arr[1] && (arr[1].style.gridColumn = '7 / 13'); + } + display(embedFields, undefined, 'grid'); + } else hide(embedFields); + embed.classList.remove('empty'); + document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block)); + notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display'); + twemoji.parse(msgEmbed); + } else embed.classList.add('empty'); + } catch (e) { + error(e); } + } editor.on('change', editor => { try { update(toObj(editor.getValue())); } catch (e) { if (editor.getValue()) return; embed.classList.add('empty'); - content.innerHTML = ''; + embedContent.innerHTML = ''; } - document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block)); }); - update(toObj(editor.getValue())); + let picker = new CP(document.querySelector('.picker'), state = { parent: document.querySelector('.cTop') }); + picker.fire('change', toRGB('#41f097')); + + let colRight = document.querySelector('.colRight'), removePicker = () => colRight.classList.remove('picking'); + document.querySelector('.colBack').addEventListener('click', e => { + picker.self.remove(); removePicker(); + }) + + picker.on('enter', () => colRight.classList.add('picking')) + picker.on('exit', removePicker); + + document.querySelectorAll('.colr').forEach(e => e.addEventListener('click', el => { + el = el.target.closest('.colr') || el.target; + embed.closest('.embed').style.borderColor = el.style.backgroundColor; + json.embed.color = toRGB(el.style.backgroundColor, false, true); + picker.source.style.removeProperty('background'); + })) + + setTimeout(() => { + picker.on('change', function (r, g, b, a) { + embed.closest('.embed').style.borderColor = this.color(r, g, b); + json.embed.color = parseInt(this.color(r, g, b).slice(1), 16); + picker.source.style.background = this.color(r, g, b); + }) + }, 1000) + document.querySelector('.timeText').innerText = tstamp(); document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block)); !window.navigator.userAgent.match(/Firefox\/[\d\.]+$/g) && // Firefox pushes the text up a little document.querySelector('.botText').style.removeProperty('top'); + + document.querySelector('.opt.gui').addEventListener('click', () => { + json = toObj(editor.getValue() || '{}'); + buildGui(json, { activate: activeFields }); + document.body.classList.add('gui'); + activeFields = null; + }) + + document.querySelector('.opt.json').addEventListener('click', () => { + editor.setValue(JSON.stringify(json, null, 4)); + editor.refresh(); + document.body.classList.remove('gui'); + editor.focus(); + activeFields = document.querySelectorAll('.gui > .item.active'); + }) + + document.querySelector('.clear').addEventListener('click', () => { + json = {} + embed.style.removeProperty('border-color'); + picker.source.style.removeProperty('background'); + update(json); buildGui(json); editor.setValue('{}'); + document.querySelectorAll('.gui>.item').forEach(e => e.classList.add('active')); + content.focus(); + }) + + let colrs = document.querySelector('.colrs'); + document.querySelector('.pickerToggle').addEventListener('click', () => colrs.classList.toggle('display')); + update(json); }; \ No newline at end of file diff --git a/assets/libs/color-picker/LICENSE b/assets/libs/color-picker/LICENSE new file mode 100644 index 0000000..143f490 --- /dev/null +++ b/assets/libs/color-picker/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2020 Taufik Nurrohman + + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets/libs/color-picker/color-picker.min.css b/assets/libs/color-picker/color-picker.min.css new file mode 100644 index 0000000..96c8682 --- /dev/null +++ b/assets/libs/color-picker/color-picker.min.css @@ -0,0 +1,129 @@ +.color-picker, +.color-picker *, +.color-picker ::after, +.color-picker ::before, +.color-picker::after, +.color-picker::before { + box-sizing: border-box; +} +.color-picker { + position: absolute; + top: 0; + left: 0; + z-index: 9999; + box-shadow: 1px 3px 6px rgba(0, 0, 0, 0.5); +} +.color-picker > div { + display: flex; + height: 10em; + border: 1px solid #000; + color: #000; +} +.color-picker > div * { + border-color: inherit; + color: inherit; +} +.color-picker i { + font: inherit; + font-size: 12px; +} +.color-picker\:a, +.color-picker\:h, +.color-picker\:sv { + background-size: 100% 100%; + position: relative; +} +.color-picker\:a, +.color-picker\:h { + width: 1.5em; + border-left: 1px solid; + cursor: ns-resize; + overflow: hidden; +} +.color-picker\:a div, +.color-picker\:h div, +.color-picker\:sv div { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} +.color-picker\:a i, +.color-picker\:h i { + display: block; + height: 0.5em; + position: absolute; + top: -0.25em; + right: 0; + left: 0; + z-index: 2; +} +.color-picker\:a i::before, +.color-picker\:h i::before { + display: block; + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + border: 0.25em solid; + border-top-color: transparent; + border-bottom-color: transparent; +} +.color-picker\:sv { + width: 10em; + cursor: crosshair; + overflow: hidden; +} +.color-picker\:sv i { + display: block; + width: 0.75em; + height: 0.75em; + position: absolute; + top: -0.375em; + right: -0.375em; + z-index: 2; +} +.color-picker\:sv i::before { + display: block; + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + border: 1px solid #fff; + border-radius: 100%; + box-shadow: 0 0 2px #000; +} +.color-picker\:a div { + z-index: 2; +} +.color-picker\:a div + div { + background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%, #ddd 100%), linear-gradient(45deg, #ddd 25%, #fff 25%, #fff 75%, #ddd 75%, #ddd 100%); + background-size: 0.5em 0.5em; + background-position: 0 0, 0.25em 0.25em; + z-index: 1; +} +.color-picker\:h div { + background-image: linear-gradient(to top, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red 100%); +} +.color-picker\:sv div + div { + background-image: linear-gradient(to right, #fff, rgba(255, 255, 255, 0)); +} +.color-picker\:sv div + div + div { + background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0)); +} +.color-picker\:a, +.color-picker\:h, +.color-picker\:sv { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; +} \ No newline at end of file diff --git a/assets/libs/color-picker/color-picker.min.js b/assets/libs/color-picker/color-picker.min.js new file mode 100644 index 0000000..134c53e --- /dev/null +++ b/assets/libs/color-picker/color-picker.min.js @@ -0,0 +1,323 @@ +/*! + * ============================================================== + * COLOR PICKER 2.1.6 + * ============================================================== + * Author: Taufik Nurrohman + * License: MIT + * -------------------------------------------------------------- + */ +((e, t, n) => { + let r = t.documentElement, + i = "HEX", + o = "top", + u = "right", + c = "left", + l = "px", + f = e.setTimeout, + s = ["touchstart", "mousedown"], + a = ["touchmove", "mousemove"], + d = ["orientationchange", "resize"], + h = ["touchend", "mouseup"]; + function p(e) { + let t, + n, + r, + i, + o, + u, + c, + l, + f = +e[0], + s = +e[1], + a = +e[2]; + switch (((u = a * (1 - s)), (c = a * (1 - (o = 6 * f - (i = Math.floor(6 * f))) * s)), (l = a * (1 - (1 - o) * s)), (i = i || 0), (c = c || 0), (l = l || 0), i % 6)) { + case 0: + (t = a), (n = l), (r = u); + break; + case 1: + (t = c), (n = a), (r = u); + break; + case 2: + (t = u), (n = a), (r = l); + break; + case 3: + (t = u), (n = c), (r = a); + break; + case 4: + (t = l), (n = u), (r = a); + break; + case 5: + (t = a), (n = u), (r = c); + } + return [L(255 * t), L(255 * n), L(255 * r), w(e[3]) ? +e[3] : 1]; + } + function g(e) { + let t, + n, + r = +e[0] / 255, + i = +e[1] / 255, + o = +e[2] / 255, + u = Math.max(r, i, o), + c = Math.min(r, i, o), + l = u, + f = u - c; + if (((n = 0 === u ? 0 : f / u), u === c)) t = 0; + else { + switch (u) { + case r: + t = (i - o) / f + (i < o ? 6 : 0); + break; + case i: + t = (o - r) / f + 2; + break; + case o: + t = (r - i) / f + 4; + } + t /= 6; + } + return [t, n, l, w(e[3]) ? +e[3] : 1]; + } + function v(e, t) { + let n = t.touches ? t.touches[0].clientX : t.clientX, + r = t.touches ? t.touches[0].clientY : t.clientY, + i = E(e); + return [n - i[0], r - i[1]]; + } + function b(e, t) { + if (e === t) return e; + for (; (e = e.parentElement) && e !== t; ); + return e; + } + function m(e) { + e && e.preventDefault(); + } + function C(e, t, n) { + for (let r = 0, i = t.length; r < i; ++r) e.removeEventListener(t[r], n, !1); + } + function k(e, t, n) { + for (let r = 0, i = t.length; r < i; ++r) e.addEventListener(t[r], n, !1); + } + function y(e) { + return "function" == typeof e; + } + function w(e) { + return void 0 !== e && null !== e; + } + function x(e) { + return "string" == typeof e; + } + function E(t) { + let n, i, o; + return t === e ? ((n = e.pageXOffset || r.scrollLeft), (i = e.pageYOffset || r.scrollTop)) : ((n = (o = t.getBoundingClientRect()).left), (i = o.top)), [n, i]; + } + function P(t) { + return t === e ? [e.innerWidth, e.innerHeight] : [t.offsetWidth, t.offsetHeight]; + } + function H(e, t, n) { + e.style[t] = n; + } + function M(e, t) { + return e < t[0] ? t[0] : e > t[1] ? t[1] : e; + } + function O(e, t) { + return parseInt(e, t || 10); + } + function X(e, n, r) { + return (e = t.createElement(e)), n && n.appendChild(e), r && (e.className = r), e; + } + function L(e) { + return Math.round(e); + } + function Y(e, t) { + return e.toString(t); + } + ((e) => { + (e[i] = (e) => { + if (x(e)) { + let t = (e = e.trim()).length; + if ((4 !== t && 7 !== t) || "#" !== e[0]) { + if ((5 === t || 9 === t) && "#" === e[0] && /^#([a-f\d]{3,4}){1,2}$/i.test(e)) + return 5 === t ? [O(e[1] + e[1], 16), O(e[2] + e[2], 16), O(e[3] + e[3], 16), O(e[4] + e[4], 16) / 255] : [O(e[1] + e[2], 16), O(e[3] + e[4], 16), O(e[5] + e[6], 16), O(e[7] + e[8], 16) / 255]; + } else if (/^#([a-f\d]{3}){1,2}$/i.test(e)) return 4 === t ? [O(e[1] + e[1], 16), O(e[2] + e[2], 16), O(e[3] + e[3], 16), 1] : [O(e[1] + e[2], 16), O(e[3] + e[4], 16), O(e[5] + e[6], 16), 1]; + return [0, 0, 0, 1]; + } + return "#" + ("000000" + Y(+e[2] | (+e[1] << 8) | (+e[0] << 16), 16)).slice(-6) + (w(e[3]) && e[3] < 1 ? Y(L(255 * e[3]) + 65536, 16).substr(-2) : ""); + }), + (e.instances = {}), + (e.state = { class: "color-picker", color: i, parent: null }), + (e.version = "2.1.6"); + })( + (e.CP = function (n, O) { + if (!n) return; + let L = this, + Y = e.CP, + I = {}, + N = Object.assign({}, Y.state, x(O) ? { color: O } : O || {}), + T = N.class, + W = X("div", 0, T); + if (n.CP) return L; + if (!(L instanceof Y)) return new Y(n, O); + (Y.instances[n.id || n.name || Object.keys(Y.instances).length] = L), (n.CP = 1), (L.visible = !1); + let $, + z, + B, + D, + R = t.body, + S = le(), + q = g(S), + A = X("div", W), + F = X("div", A, T + ":sv"), + G = X("div", A, T + ":h"), + J = X("div", A, T + ":a"), + K = X("div", F), + Q = (X("div", F), X("div", F), X("i", F)), + U = (X("div", G), X("i", G)), + V = X("div", J), + Z = (X("div", J), X("i", J)), + _ = 0, + ee = 0, + te = 0, + ne = 0, + re = 0, + ie = 0; + function oe(e) { + if (I.focus) ue("focus", S); + else { + let t = e.target; + n === b(t, n) ? !ce() && $(N.parent) : z(); + } + } + function ue(e, t) { + if (!w(I[e])) return L; + for (let n = 0, r = I[e].length; n < r; ++n) I[e][n].apply(L, t); + return L; + } + function ce() { + return W.parentNode; + } + function le(e) { + let t, + r = Y[y(Y[N.color]) ? N.color : i]; + return (t = n.dataset.color) ? (w(e) ? (n.dataset.color = r(t)) : r(t)) : (t = n.value) ? (w(e) ? (n.value = r(t)) : r(t)) : (t = n.textContent) ? (w(e) ? (n.textContent = r(t)) : r(t)) : w(e) ? void 0 : [0, 0, 0, 1]; + } + !(function i(y, x) { + (q = g((S = le()))), + y || ((x || N.parent || R).appendChild(W), (L.visible = !0)), + ($ = (e) => (i(0, e), ue("enter", S), L)), + (z = () => { + let n = ce(); + return n && (n.removeChild(W), (L.current = null), (L.visible = !1)), C(F, s, ge), C(G, s, ve), C(J, s, be), C(t, a, he), C(t, h, pe), C(e, d, D), ue("exit", S), L; + }), + (B = (t) => { + let i = P(e), + u = P(r), + f = i[0] - u[0], + s = i[1] - r.clientHeight, + a = E(e), + d = E(n), + h = P(W), + p = h[0], + g = h[1], + v = d[0] + a[0], + b = d[1] + a[1] + P(n)[1]; + if ("object" == typeof t) w(t[0]) && (v = t[0]), w(t[1]) && (b = t[1]); + else { + let e = a[0], + t = a[1], + n = a[0] + i[0] - p - f, + r = a[1] + i[1] - g - s; + (v = M(v, [e, n]) >> 0), (b = M(b, [t, r]) >> 0); + } + return H(W, c, v + l), H(W, o, b + l), ue("fit", S), L; + }), + (D = () => B()); + let j = P(F), + O = j[0], + X = j[1], + Y = P(Q), + T = Y[0], + A = Y[1], + fe = P(G)[1], + se = P(U)[1], + ae = P(J)[1], + de = P(Z)[1]; + function he(e) { + ne && + (function (e) { + let t = v(F, e), + n = M(t[0], [0, O]), + r = M(t[1], [0, X]); + (q[1] = 1 - (O - n) / O), (q[2] = (X - r) / X), me(); + })(e), + re && + (function (e) { + (q[0] = (fe - M(v(G, e)[1], [0, fe])) / fe), me(); + })(e), + ie && + (function (e) { + (q[3] = (ae - M(v(J, e)[1], [0, ae])) / ae), me(); + })(e), + (S = p(q)), + (ne || re || ie) && (ue(_ || ee || te ? "start" : "drag", S), ue("change", S)), + (_ = ee = te = 0); + } + function pe(e) { + S = p(q); + let t = e.target, + r = n === b(t, n), + i = W === b(t, W); + (L.current = null), r || i ? i && (ne || re || ie) && ue("stop", S) : I.blur ? ue("blur", S) : ce() && z(), (ne = re = ie = 0); + } + function ge(e) { + (L.current = F), (_ = ne = 1), he(e), m(e); + } + function ve(e) { + (L.current = G), (ee = re = 1), he(e), m(e); + } + function be(e) { + (L.current = J), (te = ie = 1), he(e), m(e); + } + function me() { + var e; + w((e = q)[1]) && H(Q, u, O - T / 2 - O * +e[1] + l), w(e[2]) && H(Q, o, X - A / 2 - X * +e[2] + l), w(e[0]) && H(U, o, fe - se / 2 - fe * +e[0] + l), w(e[3]) && H(Z, o, ae - de / 2 - ae * +e[3] + l); + let t = p(q), + n = p([q[0], 1, 1]); + H(K, "backgroundColor", "rgb(" + n[0] + "," + n[1] + "," + n[2] + ")"), H(V, "backgroundImage", "linear-gradient(rgb(" + t[0] + "," + t[1] + "," + t[2] + "),transparent)"); + } + y + ? (k(n, s, oe), + f(() => { + ue("change", S); + }, 1)) + : (k(F, s, ge), k(G, s, ve), k(J, s, be), k(t, a, he), k(t, h, pe), k(e, d, D), B()), + (L.get = () => le()), + (L.set = (e, t, n, r) => ((q = g([e, t, n, r])), me(), L)), + me(); + })(1), + (L.color = (e, t, n, r) => Y[y(Y[N.color]) ? N.color : i]([e, t, n, r])), + (L.current = null), + (L.enter = $), + (L.exit = z), + (L.fire = ue), + (L.fit = B), + (L.hooks = I), + (L.off = function (e, t) { + if (!w(e)) return (I = {}), L; + if (w(I[e])) + if (w(t)) { + for (let n = 0, r = I[e].length; n < r; ++n) t === I[e][n] && I[e].splice(n, 1); + 0 === j && delete I[e]; + } else delete I[e]; + return L; + }), + (L.on = function (e, t) { + return w(I[e]) || (I[e] = []), w(t) && I[e].push(t), L; + }), + (L.pop = () => (n.CP ? (delete n.CP, C(n, s, oe), z(), ue("pop", S)) : L)), + (L.self = W), + (L.source = n), + (L.state = N), + (L.value = (e, t, n, r) => (L.set(e, t, n, r), ue("change", [e, t, n, r]))); + }) + ); +})(window, document); \ No newline at end of file diff --git a/assets/media/gui.png b/assets/media/gui.png new file mode 100644 index 0000000..122a317 Binary files /dev/null and b/assets/media/gui.png differ diff --git a/assets/media/json.png b/assets/media/json.png new file mode 100644 index 0000000..52f60d2 Binary files /dev/null and b/assets/media/json.png differ diff --git a/index.html b/index.html index 31bcf8c..c0cc1ab 100644 --- a/index.html +++ b/index.html @@ -23,73 +23,146 @@ - + + + - +
-
- +
+
+
+

GUI

+
+
+

JSON

+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+

Embed Colour

+

Pick the embed colour

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -118,6 +191,7 @@
There is an error
+
Nothing here