diff --git a/css/main.css b/css/main.css
new file mode 100644
index 0000000..3b88c01
--- /dev/null
+++ b/css/main.css
@@ -0,0 +1,397 @@
+* {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ font-family: "Roboto", sans-serif;
+}
+
+:root {
+ font-size: clamp(1rem, 1.2vmax, 3rem);
+}
+
+html, body {
+ height: 100%;
+ scroll-behavior: smooth;
+}
+
+body {
+ color: rgba(var(--text-color), 1);
+ background: rgba(var(--background-color), 1);
+}
+body,
+body * {
+ --accent-color: #0D7377;
+ --text-color: 17, 17, 17;
+ --background-color: 255, 255, 255;
+ --danger-color: red;
+}
+
+body[data-theme=dark],
+body[data-theme=dark] * {
+ --accent-color: #32E0C4;
+ --text-color: 240, 240, 240;
+ --text-color-light: 170, 170, 170;
+ --background-color: 10, 10, 10;
+ --danger-color: rgb(255, 106, 106);
+}
+
+p {
+ font-size: 0.8;
+ max-width: 65ch;
+ line-height: 1.7;
+ margin-bottom: 1.5rem;
+ color: rgba(var(--text-color), 0.8);
+}
+p:not(:last-of-type) {
+ margin-bottom: 1rem;
+}
+
+img {
+ object-fit: cover;
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+a:focus-visible {
+ box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
+}
+
+button {
+ display: inline-flex;
+ border: none;
+ background-color: inherit;
+}
+
+a:any-link:focus-visible {
+ outline: rgba(var(--text-color), 1) 0.1rem solid;
+}
+
+sm-button {
+ --border-radius: 0.3rem;
+}
+
+ul {
+ list-style: none;
+}
+
+.flex {
+ display: flex;
+}
+
+.grid {
+ display: grid;
+}
+
+.hide {
+ opacity: 0;
+ pointer-events: none;
+}
+
+.hide-completely {
+ display: none !important;
+}
+
+.no-transformations {
+ transform: none !important;
+}
+
+.overflow-ellipsis {
+ width: 100%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+.breakable {
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ -ms-word-break: break-all;
+ word-break: break-word;
+ -ms-hyphens: auto;
+ -moz-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+.full-bleed {
+ grid-column: 1/4;
+}
+
+.h1 {
+ font-size: 2.5rem;
+}
+
+.h2 {
+ font-size: 2rem;
+}
+
+.h3 {
+ font-size: 1.4rem;
+}
+
+.h4 {
+ font-size: 1rem;
+}
+
+.h5 {
+ font-size: 0.8rem;
+}
+
+.uppercase {
+ text-transform: uppercase;
+}
+
+.capitalize {
+ text-transform: capitalize;
+}
+
+.flex {
+ display: flex;
+}
+
+.grid {
+ display: grid;
+}
+
+.grid-3 {
+ grid-template-columns: 1fr auto auto;
+}
+
+.flow-column {
+ grid-auto-flow: column;
+}
+
+.gap-0-5 {
+ gap: 0.5rem;
+}
+
+.gap-1 {
+ gap: 1rem;
+}
+
+.gap-1-5 {
+ gap: 1.5rem;
+}
+
+.gap-2 {
+ gap: 2rem;
+}
+
+.gap-3 {
+ gap: 3rem;
+}
+
+.text-align-right {
+ text-align: right;
+}
+
+.align-start {
+ align-items: flex-start;
+}
+
+.align-center {
+ align-items: center;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.justify-start {
+ justify-content: start;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-right {
+ margin-left: auto;
+}
+
+.align-self-center {
+ align-self: center;
+}
+
+.justify-self-center {
+ justify-self: center;
+}
+
+.justify-self-start {
+ justify-self: start;
+}
+
+.justify-self-end {
+ justify-self: end;
+}
+
+.direction-column {
+ flex-direction: column;
+}
+
+.space-between {
+ justify-content: space-between;
+}
+
+.w-100 {
+ width: 100%;
+}
+
+.color-0-8 {
+ color: rgba(var(--text-color), 0.8);
+}
+
+.weight-400 {
+ font-weight: 400;
+}
+
+.weight-500 {
+ font-weight: 500;
+}
+
+.ripple {
+ position: absolute;
+ border-radius: 50%;
+ transform: scale(0);
+ background: rgba(var(--text-color), 0.16);
+ pointer-events: none;
+}
+
+.interact {
+ position: relative;
+ overflow: hidden;
+ cursor: pointer;
+ -webkit-tap-highlight-color: transparent;
+}
+
+.observe-empty-state:empty {
+ display: none;
+}
+
+.observe-empty-state:not(:empty) ~ .empty-state {
+ display: none;
+}
+
+.icon {
+ width: 1.5rem;
+ height: 1.5rem;
+ fill: rgba(var(--text-color), 0.9);
+}
+
+.button__icon {
+ height: 1.2rem;
+ width: 1.2rem;
+}
+.button__icon--left {
+ margin-right: 0.5rem;
+}
+.button__icon--right {
+ margin-left: 0.5rem;
+}
+
+#confirmation_popup,
+#prompt_popup {
+ flex-direction: column;
+}
+#confirmation_popup h4,
+#prompt_popup h4 {
+ font-weight: 500;
+ margin-bottom: 0.5rem;
+}
+#confirmation_popup sm-button,
+#prompt_popup sm-button {
+ margin: 0;
+}
+#confirmation_popup .flex,
+#prompt_popup .flex {
+ padding: 0;
+ margin-top: 1rem;
+}
+#confirmation_popup .flex sm-button:first-of-type,
+#prompt_popup .flex sm-button:first-of-type {
+ margin-right: 0.6rem;
+ margin-left: auto;
+}
+
+#main_header {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ position: sticky;
+ padding: 1rem 1.5rem;
+ background: rgba(var(--background-color), 1);
+ border-bottom: solid 1px rgba(var(--text-color), 0.16);
+ z-index: 2;
+}
+
+#logo {
+ display: grid;
+ align-items: center;
+ width: 100%;
+ grid-template-columns: auto 1fr;
+ gap: 0 0.5rem;
+ margin-right: 1rem;
+}
+#logo h4 {
+ text-transform: capitalize;
+ font-size: 1rem;
+ font-weight: 600;
+ margin-top: 0.2rem;
+}
+#logo h5 {
+ font-size: 0.8rem;
+ font-family: "Roboto", sans-serif;
+ font-weight: 400;
+}
+#logo #main_logo {
+ height: 1.4rem;
+ width: 1.4rem;
+ fill: rgba(var(--text-color), 1);
+ stroke: none;
+}
+
+sm-tab-header {
+ padding: 0 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+}
+
+sm-tab {
+ padding: 0.5rem 0.8rem;
+}
+
+.section {
+ display: flex;
+ flex-direction: column;
+ margin-top: 3rem;
+ padding: 0 1.5rem;
+}
+.section:first-of-type {
+ margin-top: 0;
+}
+
+.section__header {
+ display: flex;
+ padding: 1rem 0;
+ justify-content: space-between;
+}
+
+.card {
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ min-width: 20rem;
+ border-radius: 0.5rem;
+ margin-right: 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+}
+.card h3 {
+ font-weight: 500;
+}
+
+@media screen and (min-width: 640px) {
+ sm-popup {
+ --width: 24rem;
+ }
+}
\ No newline at end of file
diff --git a/css/main.css.map b/css/main.css.map
new file mode 100644
index 0000000..df4b6bc
--- /dev/null
+++ b/css/main.css.map
@@ -0,0 +1,9 @@
+{
+ "version": 3,
+ "mappings": "AAAA,OAAO,CAAC,oHAAI;AACZ,AAAA,CAAC,CAAA;EACG,UAAU,EAAE,UAAU;EACtB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,oBAAoB;CACpC;;AACD,AAAA,KAAK,CAAA;EACD,eAAe,EAAE,MAAM;CAC1B;;AACD,AAAA,IAAI,CAAA;EACA,cAAc,CAAA,QAAC;EACf,YAAY,CAAA,WAAC;EACb,kBAAkB,CAAA,cAAC;EACnB,UAAU,EAAE,gCAAgC;EAC5C,KAAK,EAAE,0BAA0B;EACjC,SAAS,EAAE,IAAI;CAClB;;AACD,AAAA,IAAI,CAAA,AAAA,UAAC,CAAW,MAAM,AAAjB,EAAkB;EACnB,cAAc,CAAA,QAAC;EACf,kBAAkB,CAAA,WAAC;EACnB,YAAY,CAAA,cAAC;CAChB;;AACD,AAAA,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAA;EACd,WAAW,EAAE,qBAAqB;EAClC,cAAc,EAAE,UAAU;CAC7B;;AACD,AAAA,EAAE,CAAA;EACE,SAAS,EAAE,IAAI;CAClB;;AACD,AAAA,EAAE,CAAA;EACE,SAAS,EAAE,IAAI;CAClB;;AACD,AAAA,EAAE,CAAA;EACE,SAAS,EAAE,MAAM;CACpB;;AACD,AAAA,EAAE,CAAA;EACE,SAAS,EAAE,IAAI;CAClB;;AACD,AAAA,EAAE,CAAA;EACE,SAAS,EAAE,MAAM;CACpB;;AACD,AAAA,CAAC,CAAA;EACG,MAAM,EAAE,QAAQ;EAChB,WAAW,EAAE,GAAG;EAChB,KAAK,EAAE,4BAA4B;CACtC;;AACD,AAAA,KAAK,CAAA;EACD,OAAO,EAAE,CAAC;EACV,cAAc,EAAE,IAAI;CACvB;;AACD,AAAA,gBAAgB,CAAA;EACZ,OAAO,EAAE,eAAe;CAC3B;;AACD,AAAA,KAAK,CAAA;EACD,MAAM,EAAE,MAAM;EACd,KAAK,EAAE,MAAM;EACb,IAAI,EAAE,IAAI;EACV,MAAM,EAAE,4BAA4B;EACpC,YAAY,EAAE,CAAC;EACf,QAAQ,EAAE,OAAO;EACjB,cAAc,EAAE,KAAK;EACrB,eAAe,EAAE,KAAK;CACzB;;AACD,AAAA,OAAO,CAAA;EACH,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,CAAC;CAoCb;;AAxCD,AAKI,OALG,CAKH,KAAK,CAAA,AAAA,IAAC,CAAK,UAAU,AAAf,EAAgB;EAClB,OAAO,EAAE,IAAI;CAChB;;AAPL,AAQI,OARG,CAQH,OAAO,CAAA;EACH,QAAQ,EAAE,MAAM;EAChB,OAAO,EAAE,WAAW;EACpB,cAAc,EAAE,MAAM;EACtB,aAAa,EAAE,MAAM;EACrB,OAAO,EAAE,MAAM;EACf,UAAU,EAAE,MAAM;EAClB,UAAU,EAAE,MAAM;EAClB,aAAa,EAAE,MAAM;EACrB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,CAAC;CACZ;;AAnBL,AAoBI,OApBG,CAoBH,OAAO,CAAA;EACH,aAAa,EAAE,MAAM;EACrB,UAAU,EAAE,cAAc;EAI1B,IAAI,EAAE,4BAA4B;EAClC,QAAQ,EAAE,OAAO;EACjB,cAAc,EAAE,KAAK;EACrB,eAAe,EAAE,KAAK;EACtB,MAAM,EAAE,MAAM;EACd,KAAK,EAAE,MAAM;CAKhB;;AApCL,AAuBQ,OAvBD,CAoBH,OAAO,AAGF,cAAc,CAAA;EACX,aAAa,EAAE,MAAM;CACxB;;AAzBT,AAgCQ,OAhCD,CAoBH,OAAO,CAYH,IAAI,CAAA;EACA,MAAM,EAAE,4BAA4B;EACpC,YAAY,EAAE,CAAC;CAClB;;AAnCT,AAqCI,OArCG,CAqCH,KAAK,AAAA,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAA;EAC3B,SAAS,EAAE,mBAAmB;CACjC;;AAEL,AAAA,OAAO,CAAA;EACH,aAAa,EAAE,IAAI;CAStB;;AAVD,AAEI,OAFG,AAEF,MAAO,CAAA,UAAU,EAAC;EACf,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,4BAA4B;EACrD,OAAO,EAAE,QAAQ;EACjB,aAAa,EAAE,IAAI;CACtB;;AANL,AAOI,OAPG,AAOF,MAAO,CAAA,eAAe,EAAC;EACpB,OAAO,EAAE,QAAQ;CACpB;;AAEL,AAAA,OAAO,CAAA;EACH,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,OAAO,EAAE,WAAW;EACpB,UAAU,EAAE,gCAAgC;EAC5C,OAAO,EAAE,CAAC;CACb;;AACD,AAAA,KAAK,CAAA;EACD,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,KAAK,EAAE,IAAI;EACX,qBAAqB,EAAE,QAAQ;EAC/B,GAAG,EAAE,aAAa;EAClB,YAAY,EAAE,IAAI;CAgBrB;;AAtBD,AAOI,KAPC,CAOD,EAAE,CAAA;EACE,cAAc,EAAE,UAAU;EAC1B,SAAS,EAAE,MAAM;EACjB,WAAW,EAAE,GAAG;CACnB;;AAXL,AAYI,KAZC,CAYD,EAAE,CAAA;EACE,WAAW,EAAE,oBAAoB;EACjC,WAAW,EAAE,GAAG;CACnB;;AAfL,AAgBI,KAhBC,CAgBD,UAAU,CAAA;EACN,MAAM,EAAE,MAAM;EACd,KAAK,EAAE,MAAM;EACb,IAAI,EAAE,0BAA0B;EAChC,MAAM,EAAE,IAAI;CACf;;AAEL,AAAA,QAAQ,CAAA;EACJ,UAAU,EAAE,IAAI;CAOnB;;AARD,AAEI,QAFI,CAEJ,EAAE,GAAG,CAAC,CAAA;EACF,UAAU,EAAE,IAAI;CACnB;;AAJL,AAKI,QALI,AAKH,cAAc,CAAA;EACX,UAAU,EAAE,CAAC;CAChB;;AAEL,AAAA,KAAK,CAAA;EACD,OAAO,EAAE,MAAM;EACf,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,MAAM;EACtB,KAAK,EAAE,KAAK;EACZ,aAAa,EAAE,MAAM;EACrB,YAAY,EAAE,MAAM;EACpB,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,4BAA4B;CAIjD;;AAXD,AAQI,KARC,CAQD,EAAE,CAAA;EACE,WAAW,EAAE,GAAG;CACnB;;AAEL,MAAM,MAAM,MAAM,MAAM,SAAS,EAAE,KAAK;EACpC,AACI,OADG,AACF,MAAO,CAAA,UAAU,GADtB,OAAO,AAEF,MAAO,CAAA,eAAe,EAAC;IACpB,OAAO,EAAE,KAAK;GACjB;EAEL,AAAA,CAAC,CAAA;IACG,SAAS,EAAE,KAAK;GACnB",
+ "sources": [
+ "main.scss"
+ ],
+ "names": [],
+ "file": "main.css"
+}
\ No newline at end of file
diff --git a/css/main.min.css b/css/main.min.css
new file mode 100644
index 0000000..4553462
--- /dev/null
+++ b/css/main.min.css
@@ -0,0 +1 @@
+#logo h5,*{font-family:Roboto,sans-serif}*{padding:0;margin:0;box-sizing:border-box}:root{font-size:clamp(1rem,1.2vmax,3rem)}body,html{height:100%;scroll-behavior:smooth}body{color:rgba(var(--text-color),1);background:rgba(var(--background-color),1)}body,body *{--accent-color:#0D7377;--text-color:17,17,17;--background-color:255,255,255;--danger-color:red}body[data-theme=dark],body[data-theme=dark] *{--accent-color:#32E0C4;--text-color:240,240,240;--text-color-light:170,170,170;--background-color:10,10,10;--danger-color:rgb(255, 106, 106)}p{font-size:.8;max-width:65ch;line-height:1.7;margin-bottom:1.5rem;color:rgba(var(--text-color),.8)}p:not(:last-of-type){margin-bottom:1rem}img{object-fit:cover}a{color:inherit;text-decoration:none}a:focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color),1) inset}button{display:inline-flex;border:none;background-color:inherit}a:any-link:focus-visible{outline:solid rgba(var(--text-color),1)}sm-button{--border-radius:0.3rem}ul{list-style:none}.hide{opacity:0;pointer-events:none}.hide-completely{display:none!important}#main_header,.flex{display:flex}.no-transformations{transform:none!important}.overflow-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.breakable{overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.full-bleed{grid-column:1/4}.h1{font-size:2.5rem}.h2{font-size:2rem}.h3{font-size:1.4rem}.h4{font-size:1rem}.h5{font-size:.8rem}.uppercase{text-transform:uppercase}#logo h4,.capitalize{text-transform:capitalize}.grid{display:grid}.grid-3{grid-template-columns:1fr auto auto}.flow-column{grid-auto-flow:column}.gap-0-5{gap:.5rem}.gap-1{gap:1rem}.gap-1-5{gap:1.5rem}.gap-2{gap:2rem}.gap-3{gap:3rem}.text-align-right{text-align:right}.align-start{align-items:flex-start}#main_header,.align-center{align-items:center}.text-center{text-align:center}.justify-start{justify-content:start}.justify-center{justify-content:center}.justify-right{margin-left:auto}.align-self-center{align-self:center}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.direction-column{flex-direction:column}.space-between{justify-content:space-between}.w-100{width:100%}.color-0-8{color:rgba(var(--text-color),.8)}.weight-400{font-weight:400}.weight-500{font-weight:500}.ripple{position:absolute;border-radius:50%;transform:scale(0);background:rgba(var(--text-color),.16);pointer-events:none}.interact{position:relative;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:transparent}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.icon{width:1.5rem;height:1.5rem;fill:rgba(var(--text-color),.9)}.button__icon{height:1.2rem;width:1.2rem}.button__icon--left{margin-right:.5rem}.button__icon--right{margin-left:.5rem}#confirmation_popup,#prompt_popup{flex-direction:column}#confirmation_popup h4,#prompt_popup h4{font-weight:500;margin-bottom:.5rem}#confirmation_popup sm-button,#prompt_popup sm-button{margin:0}#confirmation_popup .flex,#prompt_popup .flex{padding:0;margin-top:1rem}#confirmation_popup .flex sm-button:first-of-type,#prompt_popup .flex sm-button:first-of-type{margin-right:.6rem;margin-left:auto}#main_header{gap:1rem;position:sticky;padding:1rem 1.5rem;background:rgba(var(--background-color),1);border-bottom:solid 1px rgba(var(--text-color),.16);z-index:2}#logo{display:grid;align-items:center;width:100%;grid-template-columns:auto 1fr;gap:0 .5rem;margin-right:1rem}#logo h4{font-size:1rem;font-weight:600;margin-top:.2rem}#logo h5{font-size:.8rem;font-weight:400}#logo #main_logo{height:1.4rem;width:1.4rem;fill:rgba(var(--text-color),1);stroke:none}sm-tab-header{padding:0 1.5rem;background-color:rgba(var(--text-color),.06)}sm-tab{padding:.5rem .8rem}.section{display:flex;flex-direction:column;margin-top:3rem;padding:0 1.5rem}.section:first-of-type{margin-top:0}.section__header{display:flex;padding:1rem 0;justify-content:space-between}.card{padding:1.5rem;display:flex;flex-direction:column;min-width:20rem;border-radius:.5rem;margin-right:1.5rem;background-color:rgba(var(--text-color),.06)}.card h3{font-weight:500}@media screen and (min-width:640px){sm-popup{--width:24rem}}
\ No newline at end of file
diff --git a/css/main.scss b/css/main.scss
new file mode 100644
index 0000000..29733c0
--- /dev/null
+++ b/css/main.scss
@@ -0,0 +1,334 @@
+*{
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ font-family: 'Roboto', sans-serif;
+}
+:root{
+ font-size: clamp(1rem, 1.2vmax, 3rem);
+}
+html, body{
+ height: 100%;
+ scroll-behavior: smooth;
+}
+body {
+ &,
+ *{
+ --accent-color: #0D7377;
+ --text-color: 17, 17, 17;
+ --background-color: 255, 255, 255;
+ --danger-color: red;
+ }
+ color: rgba(var(--text-color), 1);
+ background: rgba(var(--background-color), 1);
+}
+body[data-theme='dark']{
+ &,
+ *{
+ --accent-color: #32E0C4;
+ --text-color: 240, 240, 240;
+ --text-color-light: 170, 170, 170;
+ --background-color: 10, 10, 10;
+ --danger-color: rgb(255, 106, 106);
+ }
+}
+p {
+ font-size: 0.8;
+ max-width: 65ch;
+ line-height: 1.7;
+ margin-bottom: 1.5rem;
+ color: rgba(var(--text-color), 0.8);
+ &:not(:last-of-type){
+ margin-bottom: 1rem;
+ }
+}
+img{
+ object-fit: cover;
+}
+
+a{
+ color: inherit;
+ text-decoration: none;
+ &:focus-visible{
+ box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
+ }
+}
+
+button{
+ display: inline-flex;
+ border: none;
+ background-color: inherit;
+}
+
+a:any-link:focus-visible{
+ outline: rgba(var(--text-color), 1) 0.1rem solid;
+}
+sm-button{
+ --border-radius: 0.3rem;
+}
+ul{
+ list-style: none;
+}
+.flex{
+ display: flex;
+}
+.grid{
+ display: grid;
+}
+.hide{
+ opacity: 0;
+ pointer-events: none;
+}
+.hide-completely{
+ display: none !important;
+}
+.no-transformations{
+ transform: none !important;
+}
+.overflow-ellipsis{
+ width: 100%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.breakable{
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ -ms-word-break: break-all;
+ word-break: break-word;
+ -ms-hyphens: auto;
+ -moz-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+.full-bleed{
+ grid-column: 1/4;
+}
+.h1{
+ font-size: 2.5rem;
+}
+.h2{
+ font-size: 2rem;
+}
+.h3{
+ font-size: 1.4rem;
+}
+.h4{
+ font-size: 1rem;
+}
+.h5{
+ font-size: 0.8rem;
+}
+
+.uppercase{
+ text-transform: uppercase;
+}
+.capitalize{
+ text-transform: capitalize;
+}
+.flex{
+ display: flex;
+}
+.grid{
+ display: grid;
+}
+.grid-3{
+ grid-template-columns: 1fr auto auto;
+}
+.flow-column{
+ grid-auto-flow: column;
+}
+.gap-0-5{
+ gap: 0.5rem;
+}
+.gap-1{
+ gap: 1rem;
+}
+.gap-1-5{
+ gap: 1.5rem;
+}
+.gap-2{
+ gap: 2rem;
+}
+.gap-3{
+ gap: 3rem;
+}
+.text-align-right{
+ text-align: right;
+}
+.align-start{
+ align-items: flex-start;
+}
+.align-center{
+ align-items: center;
+}
+.text-center{
+ text-align: center;
+}
+.justify-start{
+ justify-content: start;
+}
+.justify-center{
+ justify-content: center;
+}
+.justify-right{
+ margin-left: auto;
+}
+.align-self-center{
+ align-self: center;
+}
+.justify-self-center{
+ justify-self: center;
+}
+.justify-self-start{
+ justify-self: start;
+}
+.justify-self-end{
+ justify-self: end;
+}
+.direction-column{
+ flex-direction: column;
+}
+.space-between{
+ justify-content: space-between;
+}
+.w-100{
+ width: 100%;
+}
+.color-0-8{
+ color: rgba(var(--text-color), 0.8);
+}
+.weight-400{
+ font-weight: 400;
+}
+.weight-500{
+ font-weight: 500;
+}
+.ripple{
+ position: absolute;
+ border-radius: 50%;
+ transform: scale(0);
+ background: rgba(var(--text-color), 0.16);
+ pointer-events: none;
+}
+.interact{
+ position: relative;
+ overflow: hidden;
+ cursor: pointer;
+ -webkit-tap-highlight-color: transparent;
+}
+.observe-empty-state:empty{
+ display: none;
+}
+.observe-empty-state:not(:empty) ~ .empty-state{
+ display: none;
+}
+.icon{
+ width: 1.5rem;
+ height: 1.5rem;
+ fill: rgba(var(--text-color), 0.9);
+}
+.button__icon{
+ height: 1.2rem;
+ width: 1.2rem;
+ &--left{
+ margin-right: 0.5rem;
+ }
+ &--right{
+ margin-left: 0.5rem;
+ }
+}
+#confirmation_popup,
+#prompt_popup {
+ flex-direction: column;
+ h4 {
+ font-weight: 500;
+ margin-bottom: 0.5rem;
+ }
+ sm-button{
+ margin: 0;
+ }
+ .flex {
+ padding: 0;
+ margin-top: 1rem;
+ sm-button:first-of-type {
+ margin-right: 0.6rem;
+ margin-left: auto;
+ }
+ }
+}
+#main_header{
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ position: sticky;
+ padding: 1rem 1.5rem;
+ background: rgba(var(--background-color), 1);
+ border-bottom: solid 1px rgba(var(--text-color), 0.16);
+ z-index: 2;
+}
+#logo{
+ display: grid;
+ align-items: center;
+ width: 100%;
+ grid-template-columns: auto 1fr;
+ gap: 0 0.5rem;
+ margin-right: 1rem;
+ h4{
+ text-transform: capitalize;
+ font-size: 1rem;
+ font-weight: 600;
+ margin-top: 0.2rem;
+ }
+ h5{
+ font-size: 0.8rem;
+ font-family: 'Roboto', sans-serif;
+ font-weight: 400;
+ }
+ #main_logo{
+ height: 1.4rem;
+ width: 1.4rem;
+ fill: rgba(var(--text-color), 1);
+ stroke: none;
+ }
+}
+sm-tab-header{
+ padding: 0 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+}
+sm-tab{
+ padding: 0.5rem 0.8rem;
+}
+.section{
+ display: flex;
+ flex-direction: column;
+ margin-top: 3rem;
+ padding: 0 1.5rem;
+ &:first-of-type{
+ margin-top: 0;
+ }
+}
+.section__header{
+ display: flex;
+ padding: 1rem 0;
+ justify-content: space-between;
+}
+.card{
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ min-width: 20rem;
+ border-radius: 0.5rem;
+ margin-right: 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+ h3{
+ font-weight: 500;
+ }
+}
+
+@media screen and (min-width: 640px) {
+ // for tablet and desktop
+ sm-popup{
+ --width: 24rem;
+ }
+}
\ No newline at end of file
diff --git a/css/mainnn.css b/css/mainnn.css
new file mode 100644
index 0000000..3fffd2a
--- /dev/null
+++ b/css/mainnn.css
@@ -0,0 +1,66 @@
+
+h3{text-decoration:underline;}
+
+.generate{
+ font-size: large;
+ text-align:left;
+
+ justify-content: left;
+}
+
+.print
+{
+ text-align:center;
+ font-weight: bold;
+}
+
+.innerhtml
+{
+ font-weight: bold;
+ text-align: center;
+ contain: content;
+ margin-left:10px;
+ margin-right: 10px;
+ margin-bottom:20px;
+ }
+
+sm-button{
+ width: 20%;
+ margin-left: 40%;
+}
+
+sm-input{
+ width: 50%;
+ margin-left: 25%;
+contain:content;
+}
+
+sm-popup
+{
+ font-family: sans-serif;
+ font-style: italic;
+ scroll-behavior: smooth;
+}
+.readmore{cursor: pointer;
+color:var(--accent-color);
+text-decoration: underline;
+}
+ul{margin-left: 20px;
+}
+.h53{font-weight: bold;}
+@media screen and (min-width:200px) and (max-width:900px)
+{
+ sm-input{
+ width: 100%;
+ margin-left:0px;
+ display:block;
+ }
+}
+@media screen and (max-width:480px)
+{
+ sm-button{
+ width:70%;
+ margin-left: 0px;
+ align-items: center;
+ }
+}
\ No newline at end of file
diff --git a/css/style.css b/css/style.css
new file mode 100644
index 0000000..3b549f9
--- /dev/null
+++ b/css/style.css
@@ -0,0 +1,61 @@
+.h3{text-decoration: underline;
+font-size:large;}
+
+sm-select{
+ max-width: 50%;
+ margin-left: 25%;
+}
+
+sm-input{
+ width: 50%;
+ margin-left: 25%;
+}
+sm-button{
+ width: 25%;
+ margin-left: 38%;
+}
+
+.innerhtml{
+ width: 100%;
+ scroll-behavior: smooth;
+ contain: content;
+ font-weight: bold;
+}
+
+.popup{
+ color:var(--accent-color);
+ text-decoration: underline;
+ cursor: pointer;
+}
+.h{
+ color: gray;
+ font-size: medium;
+ text-decoration: underline;
+}
+@media screen and (min-width:200px) and (max-width:900px)
+{
+ sm-input{
+ width: 100%;
+ margin-left:0px;
+ display:block;
+ }
+}
+@media screen and (max-width:480px)
+{
+ sm-button{
+ width:70%;
+ margin-left: 35px;
+ align-items: center;
+ }
+ .option{
+ margin-left: auto;
+ }
+}
+.al1{
+ color: gray;
+ font-weight: lighter;
+ font-style: italic;
+}
+.option{
+ margin-left: 25%;
+}
diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..59ada16
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,149 @@
+
+sm-input {
+ margin-bottom: 1em;
+}
+
+sm-button {
+ margin-top: 1rem;
+}
+
+
+.scroll {
+ overflow-x: scroll;
+}
+
+.keyValuePairs {
+ margin-top: 1em;
+}
+.value111{
+ margin-left: 2%;
+ width: 20%;
+}
+.key{
+ width: 20%;
+}
+
+.pairs {
+ display: flex;
+ align-items: center;
+ margin-top: 1em;
+
+}
+
+.object-inner-blocks {
+ margin-right: 1em;
+}
+
+.plus {
+ font-size: 2rem;
+ background-color: rgba(var(--text-color), 0.06);
+ color: #696969;
+ width: 1em;
+ height: 1em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 100%;
+ cursor: pointer;
+ margin-top: -15px;
+}
+
+h1 {
+ border-bottom: 1px solid #000;
+ padding-bottom: 0.5em;
+ font-size: 2.5rem;
+}
+
+.read{
+ color: var(--accent-color);
+ cursor:pointer;
+ text-decoration: underline;
+}
+.line {
+ width: 100%;
+ height: 0.5px;
+ background-color: #000;
+ margin-top: -0.75em;
+ margin-left: 25%;
+}
+
+.optionsHeading {
+ text-align: center;
+ margin-left: 25%;
+}
+@media (max-width: 320px) {
+ .plus {
+ font-size: 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+ color: #696969;
+ width: 3em;
+ height: 1em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 50%;
+ cursor: pointer;
+ }
+ h1 {
+ border-bottom: 1px solid #000;
+ padding-bottom: 0.5em;
+ font-size: 1.5rem;
+ }
+}
+
+@media (min-width: 321px) and (max-width: 376px) {
+ .plus {
+ font-size: 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+ color: #696969;
+ width: 2.5em;
+ height: 1em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 50%;
+ cursor: pointer;
+ }
+
+ h1 {
+ border-bottom: 1px solid #000;
+ padding-bottom: 0.5em;
+ font-size: 1.75rem;
+ }
+}
+
+@media (min-width: 376px) and (max-width: 576px) {
+ .plus {
+ font-size: 1.5rem;
+ background-color: rgba(var(--text-color), 0.06);
+ color: #696969;
+ width: 2em;
+ height: 1em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 50%;
+ cursor: pointer;
+ }
+
+ h1 {
+ border-bottom: 1px solid #000;
+ padding-bottom: 0.5em;
+ font-size: 2rem;
+ }
+}
+
+.demo-inner-blocks1{
+ font-weight: bold;
+ margin-left: 20%;
+ margin-right: 20%;
+}
+@media screen and (max-width:900px){
+ .demo-inner-blocks1{
+ margin-left: 10%;
+ margin-right: 10%;
+ }
+}
+.otpr{
+ margin-left: 40%;
+}
\ No newline at end of file
diff --git a/js/components.min.js b/js/components.min.js
new file mode 100644
index 0000000..7d07ca6
--- /dev/null
+++ b/js/components.min.js
@@ -0,0 +1,11 @@
+const smButton=document.createElement("template");smButton.innerHTML="\n\n
\n \n
",customElements.define("sm-button",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smButton.content.cloneNode(!0))}static get observedAttributes(){return["disabled"]}get disabled(){return this.hasAttribute("disabled")}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}handleKeyDown(e){this.hasAttribute("disabled")||"Enter"!==e.key&&"Space"!==e.code||(e.preventDefault(),this.click())}connectedCallback(){this.hasAttribute("disabled")||this.setAttribute("tabindex","0"),this.setAttribute("role","button"),this.addEventListener("keydown",this.handleKeyDown)}attributeChangedCallback(e,t,n){"disabled"===e?(this.removeAttribute("tabindex"),this.setAttribute("aria-disabled","true")):(this.setAttribute("tabindex","0"),this.setAttribute("aria-disabled","false"))}});
+const smCarousel=document.createElement("template");smCarousel.innerHTML='\n\n\n
\n
\n \n
\n
\n
\n
\n',customElements.define("sm-carousel",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smCarousel.content.cloneNode(!0)),this.isAutoPlaying=!1,this.autoPlayInterval=5e3,this.autoPlayTimeout,this.initialTimeout,this.activeSlideNum=0,this.carouselItems,this.indicators,this.showIndicator=!1,this.carousel=this.shadowRoot.querySelector(".carousel"),this.carouselContainer=this.shadowRoot.querySelector(".carousel-container"),this.carouselSlot=this.shadowRoot.querySelector("slot"),this.navButtonRight=this.shadowRoot.querySelector(".carousel__button--right"),this.navButtonLeft=this.shadowRoot.querySelector(".carousel__button--left"),this.indicatorsContainer=this.shadowRoot.querySelector(".indicators"),this.scrollLeft=this.scrollLeft.bind(this),this.scrollRight=this.scrollRight.bind(this),this.handleIndicatorClick=this.handleIndicatorClick.bind(this),this.showSlide=this.showSlide.bind(this),this.nextSlide=this.nextSlide.bind(this),this.autoPlay=this.autoPlay.bind(this),this.startAutoPlay=this.startAutoPlay.bind(this),this.stopAutoPlay=this.stopAutoPlay.bind(this)}static get observedAttributes(){return["indicator","autoplay","interval"]}scrollLeft(){this.carousel.scrollBy({left:-this.scrollDistance,behavior:"smooth"})}scrollRight(){this.carousel.scrollBy({left:this.scrollDistance,behavior:"smooth"})}showSlide(t){this.carousel.scrollTo({left:this.carouselItems[t].getBoundingClientRect().left-this.carousel.getBoundingClientRect().left+this.carousel.scrollLeft,behavior:"smooth"})}nextSlide(){if(!this.carouselItems)return;let t=this.activeSlideNum+1{this.autoPlay()},this.autoPlayInterval))}startAutoPlay(){this.setAttribute("autoplay","")}stopAutoPlay(){this.removeAttribute("autoplay")}createIndicator(t){let n=document.createElement("div");return n.classList.add("indicator"),n.dataset.rank=t,n}handleIndicatorClick(t){if(t.target.closest(".indicator")){const n=parseInt(t.target.closest(".indicator").dataset.rank);this.activeSlideNum!==n&&this.showSlide(n)}}handleKeyDown(t){"ArrowLeft"===t.code?this.scrollRight():"ArrowRight"===t.code&&this.scrollRight()}connectedCallback(){let t=document.createDocumentFragment();this.carouselSlot.addEventListener("slotchange",n=>{this.carouselItems=this.carouselSlot.assignedElements(),this.carouselItems.forEach(t=>i.observe(t)),this.carouselItems.length>0?(o.observe(this.carouselItems[0]),e.observe(this.carouselItems[this.carouselItems.length-1])):(navButtonLeft.classList.add("hide"),navButtonRight.classList.add("hide"),o.disconnect(),e.disconnect()),this.showIndicator&&(this.indicatorsContainer.innerHTML="",this.carouselItems.forEach((n,i)=>{t.append(this.createIndicator(i)),n.dataset.rank=i}),this.indicatorsContainer.append(t),this.indicators=this.indicatorsContainer.children)});const n={threshold:.9,root:this},i=new IntersectionObserver(t=>{t.forEach(t=>{if(this.showIndicator){const n=parseInt(t.target.dataset.rank);t.isIntersecting?(this.indicators[n].classList.add("active"),this.activeSlideNum=n):this.indicators[n].classList.remove("active")}})},n),o=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting?this.navButtonLeft.classList.add("hide"):this.navButtonLeft.classList.remove("hide")})},n),e=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting?this.navButtonRight.classList.add("hide"):this.navButtonRight.classList.remove("hide")})},n),s=new ResizeObserver(t=>{t.forEach(t=>{if(t.contentBoxSize){const n=Array.isArray(t.contentBoxSize)?t.contentBoxSize[0]:t.contentBoxSize;this.scrollDistance=.6*n.inlineSize}else this.scrollDistance=.6*t.contentRect.width})});s.observe(this),this.addEventListener("keydown",this.handleKeyDown),this.navButtonRight.addEventListener("click",this.scrollRight),this.navButtonLeft.addEventListener("click",this.scrollLeft),this.indicatorsContainer.addEventListener("click",this.handleIndicatorClick)}attributeChangedCallback(t,n,i){n!==i&&("indicator"===t&&(this.showIndicator=this.hasAttribute("indicator")),"autoplay"===t&&(this.hasAttribute("autoplay")?this.initialTimeout=setTimeout(()=>{this.isAutoPlaying=!0,this.autoPlay()},this.autoPlayInterval):(this.isAutoPlaying=!1,clearTimeout(this.autoPlayTimeout),clearTimeout(this.initialTimeout))),"interval"===t&&(this.hasAttribute("interval")&&""!==this.getAttribute("interval").trim()?this.autoPlayInterval=Math.abs(parseInt(this.getAttribute("interval").trim())):this.autoPlayInterval=5e3))}disconnectedCallback(){this.navButtonRight.removeEventListener("click",this.scrollRight),this.navButtonLeft.removeEventListener("click",this.scrollLeft),this.indicatorsContainer.removeEventListener("click",this.handleIndicatorClick)}});
+const smForm=document.createElement("template");smForm.innerHTML='\n \n\t\n',customElements.define("sm-form",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smForm.content.cloneNode(!0)),this.form=this.shadowRoot.querySelector("form"),this.formElements,this.requiredElements,this.submitButton,this.resetButton,this.allRequiredValid=!1,this.debounce=this.debounce.bind(this),this.handleInput=this.handleInput.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.reset=this.reset.bind(this)}debounce(t,e){let n=null;return(...s)=>{window.clearTimeout(n),n=window.setTimeout(()=>{t.apply(null,s)},e)}}handleInput(t){this.allRequiredValid=this.requiredElements.every(t=>t.isValid),this.submitButton&&(this.allRequiredValid?this.submitButton.disabled=!1:this.submitButton.disabled=!0)}handleKeydown(t){"Enter"===t.key&&this.allRequiredValid&&this.submitButton.click()}reset(){this.formElements.forEach(t=>t.reset())}connectedCallback(){const t=this.shadowRoot.querySelector("slot");t.addEventListener("slotchange",t=>{this.formElements=[...this.querySelectorAll("sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio")],this.requiredElements=this.formElements.filter(t=>t.hasAttribute("required")),this.submitButton=t.target.assignedElements().find(t=>"primary"===t.getAttribute("variant")||"submit"===t.getAttribute("type")),this.resetButton=t.target.assignedElements().find(t=>"reset"===t.getAttribute("type")),this.resetButton&&this.resetButton.addEventListener("click",this.reset)}),this.addEventListener("input",this.debounce(this.handleInput,100)),this.addEventListener("keydown",this.debounce(this.handleKeydown,100))}disconnectedCallback(){this.removeEventListener("input",this.debounce(this.handleInput,100)),this.removeEventListener("keydown",this.debounce(this.handleKeydown,100))}});
+const smInput=document.createElement("template");smInput.innerHTML='\n\n\n',customElements.define("sm-input",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smInput.content.cloneNode(!0)),this.inputParent=this.shadowRoot.querySelector(".input"),this.input=this.shadowRoot.querySelector("input"),this.clearBtn=this.shadowRoot.querySelector(".clear"),this.label=this.shadowRoot.querySelector(".label"),this.feedbackText=this.shadowRoot.querySelector(".feedback-text"),this._helperText,this._errorText,this.isRequired=!1,this.validationFunction,this.reflectedAttributes=["value","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step"],this.reset=this.reset.bind(this),this.focusIn=this.focusIn.bind(this),this.focusOut=this.focusOut.bind(this),this.fireEvent=this.fireEvent.bind(this),this.checkInput=this.checkInput.bind(this)}static get observedAttributes(){return["value","placeholder","required","disabled","type","inputmode","readonly","min","max","pattern","minlength","maxlength","step","helper-text","error-text"]}get value(){return this.input.value}set value(t){this.input.value=t,this.checkInput(),this.fireEvent()}get placeholder(){return this.getAttribute("placeholder")}set placeholder(t){this.setAttribute("placeholder",t)}get type(){return this.getAttribute("type")}set type(t){this.setAttribute("type",t)}get isValid(){const t=this.input.checkValidity();let e=!0;return this.customValidation&&(e=this.validationFunction(this.input.value)),t&&e}get validity(){return this.input.validity}set disabled(t){t?this.inputParent.classList.add("disabled"):this.inputParent.classList.remove("disabled")}set readOnly(t){t?this.setAttribute("readonly",""):this.removeAttribute("readonly")}set customValidation(t){this.validationFunction=t}set errorText(t){this._errorText=t}set helperText(t){this._helperText=t}reset(){this.value=""}focusIn(){this.input.focus()}focusOut(){this.input.blur()}fireEvent(){let t=new Event("input",{bubbles:!0,cancelable:!0,composed:!0});this.dispatchEvent(t)}checkInput(t){this.hasAttribute("readonly")||(""!==this.input.value?this.clearBtn.classList.remove("hide"):(this.clearBtn.classList.add("hide"),this.isRequired&&(this.feedbackText.textContent="* required")),this.isValid?(this.feedbackText.classList.remove("error"),this.feedbackText.classList.add("success"),this.feedbackText.textContent=""):this._errorText&&(this.feedbackText.classList.add("error"),this.feedbackText.classList.remove("success"),this.feedbackText.innerHTML=`\n \n ${this._errorText}\n `)),this.hasAttribute("placeholder")&&""!==this.getAttribute("placeholder").trim()&&(""!==this.input.value?this.animate?this.inputParent.classList.add("animate-label"):this.label.classList.add("hide"):this.animate?this.inputParent.classList.remove("animate-label"):this.label.classList.remove("hide"))}connectedCallback(){this.animate=this.hasAttribute("animate"),this.input.addEventListener("input",this.checkInput),this.clearBtn.addEventListener("click",this.reset)}attributeChangedCallback(t,e,n){e!==n&&(this.reflectedAttributes.includes(t)&&(this.hasAttribute(t)?this.input.setAttribute(t,this.getAttribute(t)?this.getAttribute(t):""):this.input.removeAttribute(t)),"placeholder"===t?(this.label.textContent=n,this.setAttribute("aria-label",n)):this.hasAttribute("value")?this.checkInput():"type"===t?this.hasAttribute("type")&&"number"===this.getAttribute("type")&&this.input.setAttribute("inputmode","numeric"):"helper-text"===t?this._helperText=this.getAttribute("helper-text"):"error-text"===t?this._errorText=this.getAttribute("error-text"):"required"===t?(this.isRequired=this.hasAttribute("required"),this.feedbackText.textContent="* required"):"readonly"===t?this.hasAttribute("readonly")?this.inputParent.classList.add("readonly"):this.inputParent.classList.remove("readonly"):"disabled"===t&&(this.hasAttribute("disabled")?this.inputParent.classList.add("disabled"):this.inputParent.classList.remove("disabled")))}disconnectedCallback(){this.input.removeEventListener("input",this.checkInput),this.clearBtn.removeEventListener("click",this.reset)}});
+const smMenu=document.createElement("template");smMenu.innerHTML='\n\n',customElements.define("sm-menu",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenu.content.cloneNode(!0)),this.isOpen=!1,this.availableOptions,this.containerDimensions,this.animOptions={duration:200,easing:"ease"},this.optionList=this.shadowRoot.querySelector(".options"),this.menu=this.shadowRoot.querySelector(".menu"),this.icon=this.shadowRoot.querySelector(".icon"),this.expand=this.expand.bind(this),this.collapse=this.collapse.bind(this),this.toggle=this.toggle.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleClickoutSide=this.handleClickoutSide.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.isOpen||(this.optionList.classList.remove("hide"),this.optionList.animate([{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animOptions).onfinish=(()=>{this.isOpen=!0,this.icon.classList.add("focused")}))}collapse(){this.isOpen&&(this.optionList.animate([{transform:"none",opacity:"1"},{transform:window.innerWidth<640?"translateY(1.5rem)":"translateY(-1rem)",opacity:"0"}],this.animOptions).onfinish=(()=>{this.isOpen=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide")}))}toggle(){this.isOpen?this.collapse():this.expand()}handleKeyDown(n){n.target===this?"ArrowDown"===n.code?(n.preventDefault(),this.availableOptions[0].focus()):"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.toggle()):"ArrowUp"===n.code?(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"===n.code?(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus()):"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),n.target.click())}handleClickoutSide(n){this.contains(n.target)||2===n.button||this.collapse()}connectedCallback(){this.setAttribute("role","listbox"),this.setAttribute("aria-label","dropdown menu");const n=this.shadowRoot.querySelector(".options slot");n.addEventListener("slotchange",n=>{this.availableOptions=n.target.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),this.addEventListener("click",this.toggle),this.addEventListener("keydown",this.handleKeyDown),document.addEventListener("mousedown",this.handleClickoutSide)}disconnectedCallback(){this.removeEventListener("click",this.toggle),this.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("mousedown",this.handleClickoutSide)}});const menuOption=document.createElement("template");menuOption.innerHTML='\n\n\n \n
',customElements.define("menu-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(menuOption.content.cloneNode(!0))}connectedCallback(){this.setAttribute("role","option"),this.addEventListener("keyup",n=>{"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.click())})}});
+const smNotifications=document.createElement("template");smNotifications.innerHTML='\n\n\n',customElements.define("sm-notifications",class extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"}).append(smNotifications.content.cloneNode(!0)),this.notificationPanel=this.shadowRoot.querySelector(".notification-panel"),this.animationOptions={duration:300,fill:"forwards",easing:"cubic-bezier(0.175, 0.885, 0.32, 1.275)"},this.push=this.push.bind(this),this.createNotification=this.createNotification.bind(this),this.removeNotification=this.removeNotification.bind(this),this.clearAll=this.clearAll.bind(this)}randString(n){let t="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let o=0;o${o}\n ${n}
\n `,i&&(e.classList.add("pinned"),a+='\n \n '),e.innerHTML=a,e}push(n,t={}){const i=this.createNotification(n,t);return this.notificationPanel.append(i),i.animate([{transform:"translateY(1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animationOptions),i.id}removeNotification(n){n.animate([{transform:"none",opacity:"1"},{transform:"translateY(0.5rem)",opacity:"0"}],this.animationOptions).onfinish=(()=>{n.remove()})}clearAll(){Array.from(this.notificationPanel.children).forEach(n=>{this.removeNotification(n)})}connectedCallback(){this.notificationPanel.addEventListener("click",n=>{n.target.closest(".close")&&this.removeNotification(n.target.closest(".notification"))});const n=new MutationObserver(n=>{n.forEach(n=>{"childList"===n.type&&n.addedNodes.length&&!n.addedNodes[0].classList.contains("pinned")&&setTimeout(()=>{this.removeNotification(n.addedNodes[0])},5e3)})});n.observe(this.notificationPanel,{childList:!0})}});
+const smPopup=document.createElement("template");smPopup.innerHTML='\n\n\n',customElements.define("sm-popup",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smPopup.content.cloneNode(!0)),this.allowClosing=!1,this.isOpen=!1,this.pinned=!1,this.popupStack,this.offset,this.touchStartY=0,this.touchEndY=0,this.touchStartTime=0,this.touchEndTime=0,this.touchEndAnimataion,this.popupContainer=this.shadowRoot.querySelector(".popup-container"),this.popup=this.shadowRoot.querySelector(".popup"),this.popupBodySlot=this.shadowRoot.querySelector(".popup-body slot"),this.popupHeader=this.shadowRoot.querySelector(".popup-top"),this.resumeScrolling=this.resumeScrolling.bind(this),this.show=this.show.bind(this),this.hide=this.hide.bind(this),this.handleTouchStart=this.handleTouchStart.bind(this),this.handleTouchMove=this.handleTouchMove.bind(this),this.handleTouchEnd=this.handleTouchEnd.bind(this),this.movePopup=this.movePopup.bind(this)}static get observedAttributes(){return["open"]}get open(){return this.isOpen}resumeScrolling(){const t=document.body.style.top;window.scrollTo(0,-1*parseInt(t||"0")),setTimeout(()=>{document.body.style.overflow="auto",document.body.style.top="initial"},300)}show(t={}){const{pinned:e=!1,popupStack:n}=t;return n&&(this.popupStack=n),this.popupStack&&!this.hasAttribute("open")&&(this.popupStack.push({popup:this,permission:e}),this.popupStack.items.length>1&&this.popupStack.items[this.popupStack.items.length-2].popup.classList.add("stacked"),this.dispatchEvent(new CustomEvent("popupopened",{bubbles:!0,detail:{popup:this,popupStack:this.popupStack}})),this.setAttribute("open",""),this.pinned=e,this.isOpen=!0),this.popupContainer.classList.remove("hide"),this.popup.style.transform="none",document.body.style.overflow="hidden",document.body.style.top=`-${window.scrollY}px`,this.popupStack}hide(){window.innerWidth<640?this.popup.style.transform="translateY(100%)":this.popup.style.transform="translateY(3rem)",this.popupContainer.classList.add("hide"),this.removeAttribute("open"),void 0!==this.popupStack?(this.popupStack.pop(),this.popupStack.items.length?this.popupStack.items[this.popupStack.items.length-1].popup.classList.remove("stacked"):this.resumeScrolling()):this.resumeScrolling(),this.forms.length&&setTimeout(()=>{this.forms.forEach(t=>t.reset())},300),setTimeout(()=>{this.dispatchEvent(new CustomEvent("popupclosed",{bubbles:!0,detail:{popup:this,popupStack:this.popupStack}})),this.isOpen=!1},300)}handleTouchStart(t){this.touchStartY=t.changedTouches[0].clientY,this.popup.style.transition="transform 0.1s",this.touchStartTime=t.timeStamp}handleTouchMove(t){this.touchStartYthis.movePopup()))}handleTouchEnd(t){if(this.touchEndTime=t.timeStamp,cancelAnimationFrame(this.touchEndAnimataion),this.touchEndY=t.changedTouches[0].clientY,this.popup.style.transition="transform 0.3s",this.threshold=.3*this.popup.getBoundingClientRect().height,this.touchEndTime-this.touchStartTime>200)if(this.touchEndY-this.touchStartY>this.threshold){if(this.pinned)return void this.show();this.hide()}else this.show();else if(this.touchEndY>this.touchStartY){if(this.pinned)return void this.show();this.hide()}}movePopup(){this.popup.style.transform=`translateY(${this.offset}px)`}connectedCallback(){this.popupBodySlot.addEventListener("slotchange",()=>{this.forms=this.querySelectorAll("sm-form")}),this.popupContainer.addEventListener("mousedown",t=>{t.target!==this.popupContainer||this.pinned||(this.pinned?this.show():this.hide())});const t=new ResizeObserver(t=>{for(let e of t)if(e.contentBoxSize){Array.isArray(e.contentBoxSize)?e.contentBoxSize[0]:e.contentBoxSize;this.threshold=.3*e.blockSize.height}else this.threshold=.3*e.contentRect.height});t.observe(this),this.popupHeader.addEventListener("touchstart",t=>{this.handleTouchStart(t)},{passive:!0}),this.popupHeader.addEventListener("touchmove",t=>{this.handleTouchMove(t)},{passive:!0}),this.popupHeader.addEventListener("touchend",t=>{this.handleTouchEnd(t)},{passive:!0})}disconnectedCallback(){this.popupHeader.removeEventListener("touchstart",this.handleTouchStart,{passive:!0}),this.popupHeader.removeEventListener("touchmove",this.handleTouchMove,{passive:!0}),this.popupHeader.removeEventListener("touchend",this.handleTouchEnd,{passive:!0}),resizeObserver.unobserve()}attributeChangedCallback(t,e,n){"open"===t&&this.hasAttribute("open")&&this.show()}});
+const smTabHeader=document.createElement("template");smTabHeader.innerHTML='\n\n\n \n
\n',customElements.define("sm-tab-header",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smTabHeader.content.cloneNode(!0)),this.prevTab,this.allTabs,this.activeTab,this.indicator=this.shadowRoot.querySelector(".indicator"),this.tabSlot=this.shadowRoot.querySelector("slot"),this.tabHeader=this.shadowRoot.querySelector(".tab-header"),this.changeTab=this.changeTab.bind(this),this.handleClick=this.handleClick.bind(this),this.handlePanelChange=this.handlePanelChange.bind(this)}fireEvent(t){this.dispatchEvent(new CustomEvent(`switchedtab${this.target}`,{bubbles:!0,detail:{index:parseInt(t)}}))}moveIndiactor(t){this.indicator.setAttribute("style",`width: ${t.width}px; transform: translateX(${t.left-this.tabHeader.getBoundingClientRect().left+this.tabHeader.scrollLeft}px)`)}changeTab(t){t!==this.prevTab&&t.closest("sm-tab")&&(this.prevTab&&this.prevTab.classList.remove("active"),t.classList.add("active"),t.scrollIntoView({behavior:"smooth",block:"nearest",inline:"center"}),this.moveIndiactor(t.getBoundingClientRect()),this.prevTab=t,this.activeTab=t)}handleClick(t){t.target.closest("sm-tab")&&(this.changeTab(t.target),this.fireEvent(t.target.dataset.index))}handlePanelChange(t){this.changeTab(this.allTabs[t.detail.index])}connectedCallback(){if(!this.hasAttribute("target")||""===this.getAttribute("target").value)return;this.target=this.getAttribute("target"),this.tabSlot.addEventListener("slotchange",()=>{this.allTabs=this.tabSlot.assignedElements(),this.allTabs.forEach((t,n)=>{t.dataset.index=n})}),this.addEventListener("click",this.handleClick),document.addEventListener(`switchedpanel${this.target}`,this.handlePanelChange);let t=new ResizeObserver(t=>{t.forEach(t=>{if(this.prevTab){let t=this.activeTab.getBoundingClientRect();this.moveIndiactor(t)}})});t.observe(this);let n=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting)if(this.indicator.style.transition="none",this.activeTab){let t=this.activeTab.getBoundingClientRect();this.moveIndiactor(t)}else{this.allTabs[0].classList.add("active");let t=this.allTabs[0].getBoundingClientRect();this.moveIndiactor(t),this.fireEvent(0),this.prevTab=this.tabSlot.assignedElements()[0],this.activeTab=this.prevTab}})},{threshold:1});n.observe(this)}disconnectedCallback(){this.removeEventListener("click",this.handleClick),document.removeEventListener(`switchedpanel${this.target}`,this.handlePanelChange)}});const smTab=document.createElement("template");smTab.innerHTML='\n\n\n\n
\n',customElements.define("sm-tab",class extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"}).append(smTab.content.cloneNode(!0))}});const smTabPanels=document.createElement("template");smTabPanels.innerHTML='\n\n\n Nothing to see here.\n
\n',customElements.define("sm-tab-panels",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smTabPanels.content.cloneNode(!0)),this.isTransitioning=!1,this.panelContainer=this.shadowRoot.querySelector(".panel-container"),this.panelSlot=this.shadowRoot.querySelector("slot"),this.handleTabChange=this.handleTabChange.bind(this)}handleTabChange(t){this.isTransitioning=!0,this.panelContainer.scrollTo({left:this.allPanels[t.detail.index].getBoundingClientRect().left-this.panelContainer.getBoundingClientRect().left+this.panelContainer.scrollLeft,behavior:"smooth"}),setTimeout(()=>{this.isTransitioning=!1},300)}fireEvent(t){this.dispatchEvent(new CustomEvent(`switchedpanel${this.id}`,{bubbles:!0,detail:{index:parseInt(t)}}))}connectedCallback(){this.panelSlot.addEventListener("slotchange",()=>{this.allPanels=this.panelSlot.assignedElements(),this.allPanels.forEach((n,e)=>{n.dataset.index=e,t.observe(n)})}),document.addEventListener(`switchedtab${this.id}`,this.handleTabChange);const t=new IntersectionObserver(t=>{t.forEach(t=>{!this.isTransitioning&&t.isIntersecting&&this.fireEvent(t.target.dataset.index)})},{threshold:.6})}disconnectedCallback(){intersectionObserver.disconnect(),document.removeEventListener(`switchedtab${this.id}`,this.handleTabChange)}});
+const themeToggle=document.createElement("template");themeToggle.innerHTML='\n \n \n';class ThemeToggle extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(themeToggle.content.cloneNode(!0)),this.isChecked=!1,this.hasTheme="light",this.toggleState=this.toggleState.bind(this),this.fireEvent=this.fireEvent.bind(this),this.handleThemeChange=this.handleThemeChange.bind(this)}static get observedAttributes(){return["checked"]}daylight(){this.hasTheme="light",document.body.dataset.theme="light",this.setAttribute("aria-checked","false")}nightlight(){this.hasTheme="dark",document.body.dataset.theme="dark",this.setAttribute("aria-checked","true")}toggleState(){this.toggleAttribute("checked"),this.fireEvent()}handleKeyDown(e){"Space"===e.code&&this.toggleState()}handleThemeChange(e){e.detail.theme!==this.hasTheme&&("dark"===e.detail.theme?this.setAttribute("checked",""):this.removeAttribute("checked"))}fireEvent(){this.dispatchEvent(new CustomEvent("themechange",{bubbles:!0,composed:!0,detail:{theme:this.hasTheme}}))}connectedCallback(){this.setAttribute("role","switch"),this.setAttribute("aria-label","theme toggle"),"dark"===localStorage.theme?(this.nightlight(),this.setAttribute("checked","")):"light"===localStorage.theme?(this.daylight(),this.removeAttribute("checked")):window.matchMedia("(prefers-color-scheme: dark)").matches?(this.nightlight(),this.setAttribute("checked","")):(this.daylight(),this.removeAttribute("checked")),this.addEventListener("click",this.toggleState),this.addEventListener("keydown",this.handleKeyDown),document.addEventListener("themechange",this.handleThemeChange)}disconnectedCallback(){this.removeEventListener("click",this.toggleState),this.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("themechange",this.handleThemeChange)}attributeChangedCallback(e,t,n){"checked"===e&&(this.hasAttribute("checked")?(this.nightlight(),localStorage.setItem("theme","dark")):(this.daylight(),localStorage.setItem("theme","light")))}}window.customElements.define("theme-toggle",ThemeToggle);
+const smSelect=document.createElement("template");smSelect.innerHTML='\n\n',customElements.define("sm-select",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smSelect.content.cloneNode(!0)),this.reset=this.reset.bind(this),this.open=this.open.bind(this),this.collapse=this.collapse.bind(this),this.toggle=this.toggle.bind(this),this.handleOptionsNavigation=this.handleOptionsNavigation.bind(this),this.handleOptionSelection=this.handleOptionSelection.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.handleClickOutside=this.handleClickOutside.bind(this),this.availableOptions,this.previousOption,this.isOpen=!1,this.slideDown=[{transform:"translateY(-0.5rem)",opacity:0},{transform:"translateY(0)",opacity:1}],this.slideUp=[{transform:"translateY(0)",opacity:1},{transform:"translateY(-0.5rem)",opacity:0}],this.animationOptions={duration:300,fill:"forwards",easing:"ease"},this.optionList=this.shadowRoot.querySelector(".options"),this.chevron=this.shadowRoot.querySelector(".toggle"),this.selection=this.shadowRoot.querySelector(".selection"),this.selectedOptionText=this.shadowRoot.querySelector(".selected-option-text")}static get observedAttributes(){return["value","disabled"]}get value(){return this.getAttribute("value")}set value(e){this.setAttribute("value",e)}reset(e=!0){if(this.availableOptions[0]&&this.previousOption!==this.availableOptions[0]){const t=this.availableOptions[0];this.previousOption&&this.previousOption.classList.remove("check-selected"),t.classList.add("check-selected"),this.value=t.getAttribute("value"),this.selectedOptionText.textContent=t.textContent,this.previousOption=t,e&&this.fireEvent()}}open(){this.optionList.classList.remove("hide"),this.optionList.animate(this.slideDown,this.animationOptions),this.chevron.classList.add("rotate"),this.isOpen=!0}collapse(){this.chevron.classList.remove("rotate"),this.optionList.animate(this.slideUp,this.animationOptions).onfinish=(()=>{this.optionList.classList.add("hide"),this.isOpen=!1})}toggle(){this.isOpen||this.hasAttribute("disabled")?this.collapse():this.open()}fireEvent(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this.value}}))}handleOptionsNavigation(e){"ArrowUp"===e.code?(e.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"===e.code&&(e.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}handleOptionSelection(e){this.previousOption!==document.activeElement&&(this.value=document.activeElement.getAttribute("value"),this.selectedOptionText.textContent=document.activeElement.textContent,this.fireEvent(),this.previousOption&&this.previousOption.classList.remove("check-selected"),document.activeElement.classList.add("check-selected"),this.previousOption=document.activeElement)}handleClick(e){e.target===this?this.toggle():(this.handleOptionSelection(),this.collapse())}handleKeydown(e){e.target===this?this.isOpen&&"ArrowDown"===e.code?(e.preventDefault(),this.availableOptions[0].focus(),this.handleOptionSelection(e)):"Enter"!==e.code&&"Space"!==e.code||(e.preventDefault(),this.toggle()):(this.handleOptionsNavigation(e),this.handleOptionSelection(e),"Enter"!==e.code&&"Space"!==e.code||(e.preventDefault(),this.collapse()))}handleClickOutside(e){this.isOpen&&!this.contains(e.target)&&this.collapse()}connectedCallback(){this.setAttribute("role","listbox"),this.hasAttribute("disabled")||this.selection.setAttribute("tabindex","0");let e=this.shadowRoot.querySelector("slot");e.addEventListener("slotchange",t=>{this.availableOptions=e.assignedElements(),this.reset(!1)}),this.addEventListener("click",this.handleClick),this.addEventListener("keydown",this.handleKeydown),document.addEventListener("mousedown",this.handleClickOutside)}disconnectedCallback(){this.removeEventListener("click",this.toggle),this.removeEventListener("keydown",this.handleKeydown),document.removeEventListener("mousedown",this.handleClickOutside)}attributeChangedCallback(e){"disabled"===e&&(this.hasAttribute("disabled")?this.selection.removeAttribute("tabindex"):this.selection.setAttribute("tabindex","0"))}});const smOption=document.createElement("template");smOption.innerHTML='\n\n',customElements.define("sm-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smOption.content.cloneNode(!0))}connectedCallback(){this.setAttribute("role","option"),this.setAttribute("tabindex","0")}});
+const smCopy=document.createElement("template");smCopy.innerHTML='\n\n\n\n',customElements.define("sm-copy",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smCopy.content.cloneNode(!0)),this.copyContent=this.shadowRoot.querySelector(".copy-content"),this.copyButton=this.shadowRoot.querySelector(".copy-button"),this.copy=this.copy.bind(this)}static get observedAttributes(){return["value"]}set value(n){this.setAttribute("value",n)}get value(){return this.getAttribute("value")}fireEvent(){this.dispatchEvent(new CustomEvent("copy",{composed:!0,bubbles:!0,cancelable:!0}))}copy(){navigator.clipboard.writeText(this.copyContent.textContent).then(n=>this.fireEvent()).catch(n=>console.error(n))}connectedCallback(){this.copyButton.addEventListener("click",this.copy)}attributeChangedCallback(n,t,o){"value"===n&&(this.copyContent.textContent=o)}disconnectedCallback(){this.copyButton.removeEventListener("click",this.copy)}});
diff --git a/js/main_UI.js b/js/main_UI.js
new file mode 100644
index 0000000..9057041
--- /dev/null
+++ b/js/main_UI.js
@@ -0,0 +1,305 @@
+// Global variables
+const appPages = ['dashboard', 'settings'];
+const domRefs = {};
+let timerId;
+const currentYear = new Date().getFullYear();
+
+//Checks for internet connection status
+if (!navigator.onLine)
+ notify(
+ "There seems to be a problem connecting to the internet, Please check you internet connection.",
+ "error",
+ { sound: true }
+ );
+window.addEventListener("offline", () => {
+ notify(
+ "There seems to be a problem connecting to the internet, Please check you internet connection.",
+ "error",
+ { pinned: true, sound: true }
+ );
+});
+window.addEventListener("online", () => {
+ getRef("notification_drawer").clearAll();
+ notify("We are back online.", "success");
+});
+
+// Use instead of document.getElementById
+function getRef(elementId) {
+ if (!domRefs.hasOwnProperty(elementId)) {
+ domRefs[elementId] = {
+ count: 1,
+ ref: null,
+ };
+ return document.getElementById(elementId);
+ } else {
+ if (domRefs[elementId].count < 3) {
+ domRefs[elementId].count = domRefs[elementId].count + 1;
+ return document.getElementById(elementId);
+ } else {
+ if (!domRefs[elementId].ref)
+ domRefs[elementId].ref = document.getElementById(elementId);
+ return domRefs[elementId].ref;
+ }
+ }
+}
+
+// returns dom with specified element
+function createElement(tagName, options) {
+ const { className, textContent, innerHTML, attributes = {} } = options
+ const elem = document.createElement(tagName)
+ for (let attribute in attributes) {
+ elem.setAttribute(attribute, attributes[attribute])
+ }
+ if (className)
+ elem.className = className
+ if (textContent)
+ elem.textContent = textContent
+ if (innerHTML)
+ elem.innerHTML = innerHTML
+ return elem
+}
+
+// Use when a function needs to be executed after user finishes changes
+const debounce = (callback, wait) => {
+ let timeoutId = null;
+ return (...args) => {
+ window.clearTimeout(timeoutId);
+ timeoutId = window.setTimeout(() => {
+ callback.apply(null, args);
+ }, wait);
+ };
+}
+
+// Limits the rate of function execution
+function throttle(func, delay) {
+ // If setTimeout is already scheduled, no need to do anything
+ if (timerId) {
+ return;
+ }
+
+ // Schedule a setTimeout after delay seconds
+ timerId = setTimeout(function () {
+ func();
+
+ // Once setTimeout function execution is finished, timerId = undefined so that in
+ // the next scroll event function execution can be scheduled by the setTimeout
+ timerId = undefined;
+ }, delay);
+}
+
+class Stack {
+ constructor() {
+ this.items = [];
+ }
+ push(element) {
+ this.items.push(element);
+ }
+ pop() {
+ if (this.items.length == 0)
+ return "Underflow";
+ return this.items.pop();
+ }
+ peek() {
+ return this.items[this.items.length - 1];
+ }
+}
+
+// function required for popups or modals to appear
+function showPopup(popupId, pinned) {
+ zIndex++
+ getRef(popupId).setAttribute('style', `z-index: ${zIndex}`)
+ popupStack = getRef(popupId).show({ pinned, popupStack })
+ return getRef(popupId);
+}
+
+// hides the popup or modal
+function hidePopup() {
+ if (popupStack.peek() === undefined)
+ return;
+ popupStack.peek().popup.hide()
+}
+
+// displays a popup for asking permission. Use this instead of JS confirm
+const getConfirmation = (title, message, cancelText = 'Cancel', confirmText = 'OK') => {
+ return new Promise(resolve => {
+ showPopup('confirmation_popup', true)
+ getRef('confirm_title').textContent = title;
+ getRef('confirm_message').textContent = message;
+ let cancelButton = getRef('confirmation_popup').children[2].children[0],
+ submitButton = getRef('confirmation_popup').children[2].children[1]
+ submitButton.textContent = confirmText
+ cancelButton.textContent = cancelText
+ submitButton.onclick = () => {
+ hidePopup()
+ resolve(true);
+ }
+ cancelButton.onclick = () => {
+ hidePopup()
+ resolve(false);
+ }
+ })
+}
+
+// displays a popup for asking user input. Use this instead of JS prompt
+async function getPromptInput(title, message = '', isPassword = true, cancelText = 'Cancel', confirmText = 'OK') {
+ showPopup('prompt_popup', true)
+ getRef('prompt_title').textContent = title;
+ let input = getRef('prompt_input');
+ input.setAttribute("placeholder", message)
+ let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
+ if (isPassword)
+ input.setAttribute("type", "text")
+ else
+ input.setAttribute("type", "password")
+ input.focusIn()
+ buttons[0].textContent = cancelText;
+ buttons[1].textContent = confirmText;
+ return new Promise((resolve, reject) => {
+ buttons[0].onclick = () => {
+ hidePopup()
+ return;
+ }
+ buttons[1].onclick = () => {
+ let value = input.value;
+ hidePopup()
+ resolve(value)
+ }
+ })
+}
+
+//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
+function notify(message, mode, options = {}) {
+ const { pinned = false, sound = false } = options
+ let icon
+ switch (mode) {
+ case 'success':
+ icon = ``
+ break;
+ case 'error':
+ icon = ``
+ break;
+ }
+ getRef("notification_drawer").push(message, { pinned, icon });
+ if (navigator.onLine && sound) {
+ getRef("notification_sound").currentTime = 0;
+ getRef("notification_sound").play();
+ }
+}
+
+function getFormatedTime(time, relative) {
+ try {
+ if (String(time).indexOf("_")) time = String(time).split("_")[0];
+ const intTime = parseInt(time);
+ if (String(intTime).length < 13) time *= 1000;
+ let timeFrag = new Date(intTime).toString().split(" "),
+ day = timeFrag[0],
+ month = timeFrag[1],
+ date = timeFrag[2],
+ year = timeFrag[3],
+ minutes = new Date(intTime).getMinutes(),
+ hours = new Date(intTime).getHours(),
+ currentTime = new Date().toString().split(" ");
+
+ minutes = minutes < 10 ? `0${minutes}` : minutes;
+ let finalHours = ``;
+ if (hours > 12) finalHours = `${hours - 12}:${minutes}`;
+ else if (hours === 0) finalHours = `12:${minutes}`;
+ else finalHours = `${hours}:${minutes}`;
+
+ finalHours = hours >= 12 ? `${finalHours} PM` : `${finalHours} AM`;
+ if (relative) {
+ return `${date} ${month} ${year}`;
+ } else return `${finalHours} ${month} ${date} ${year}`;
+ } catch (e) {
+ console.error(e);
+ return time;
+ }
+}
+
+window.addEventListener('hashchange', e => showPage(window.location.hash))
+window.addEventListener("load", () => {
+ document.body.classList.remove('hide-completely')
+ showPage(window.location.hash)
+ // document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = validateAddr)
+ document.addEventListener('keyup', (e) => {
+ if (e.code === 'Escape') {
+ hidePopup()
+ }
+ })
+ document.addEventListener("pointerdown", (e) => {
+ if (e.target.closest("button, sm-button:not([disabled]), .interact")) {
+ createRipple(e, e.target.closest("button, sm-button, .interact"));
+ }
+ });
+ document.addEventListener('copy', () => {
+ notify('copied', 'success')
+ })
+});
+
+function createRipple(event, target) {
+ const circle = document.createElement("span");
+ const diameter = Math.max(target.clientWidth, target.clientHeight);
+ const radius = diameter / 2;
+ const targetDimensions = target.getBoundingClientRect();
+ circle.style.width = circle.style.height = `${diameter}px`;
+ circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
+ circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
+ circle.classList.add("ripple");
+ const rippleAnimation = circle.animate(
+ [
+ {
+ transform: "scale(3)",
+ opacity: 0,
+ },
+ ],
+ {
+ duration: 1000,
+ fill: "forwards",
+ easing: "ease-out",
+ }
+ );
+ target.append(circle);
+ rippleAnimation.onfinish = () => {
+ circle.remove();
+ };
+}
+
+function showPage(targetPage, options = {}) {
+ const { firstLoad, hashChange } = options
+ let pageId
+ if (targetPage === '') {
+ pageId = 'overview_page'
+ }
+ else {
+ pageId = targetPage.includes('#') ? targetPage.split('#')[1] : targetPage
+ }
+ if(!appPages.includes(pageId)) return
+ document.querySelector('.page:not(.hide-completely)').classList.add('hide-completely')
+ document.querySelector('.nav-list__item--active').classList.remove('nav-list__item--active')
+ getRef(pageId).classList.remove('hide-completely')
+ getRef(pageId).animate([
+ {
+ opacity: 0,
+ transform: 'translateX(-1rem)'
+ },
+ {
+ opacity: 1,
+ transform: 'none'
+ },
+ ],
+ {
+ duration: 300,
+ easing: 'ease'
+ })
+ const targetListItem = document.querySelector(`.nav-list__item[href="#${pageId}"]`)
+ targetListItem.classList.add('nav-list__item--active')
+ if (firstLoad && window.innerWidth > 640 && targetListItem.getBoundingClientRect().top > getRef('side_nav').getBoundingClientRect().height) {
+ getRef('side_nav').scrollTo({
+ top: (targetListItem.getBoundingClientRect().top - getRef('side_nav').getBoundingClientRect().top + getRef('side_nav').scrollTop),
+ behavior: 'smooth'
+ })
+ }
+ if (hashChange && window.innerWidth < 640) {
+ getRef('side_nav').close()
+ }
+}
\ No newline at end of file
diff --git a/js/plus.js b/js/plus.js
new file mode 100644
index 0000000..8c0cc6a
--- /dev/null
+++ b/js/plus.js
@@ -0,0 +1,267 @@
+
+document.getElementById("genbtn").addEventListener('click',()=>{
+ let flo =floCrypto.generateNewID()
+ document.getElementById("private").innerHTML="Private key: ";
+ document.getElementById("pub").innerHTML="Public key: ";
+ document.getElementById("flocrypto").innerHTML="FLO ID: ";
+ var id=document.querySelector("#pub");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=flo.pubKey;
+ id.appendChild(newdiv);
+ var id1=document.querySelector("#private");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=flo.privKey;
+ id1.appendChild(newdiv);
+ var id2=document.querySelector("#flocrypto");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=flo.floID;
+ id2.appendChild(newdiv);
+})
+
+ function publickeyhex()
+ {
+ let privatekey = document.getElementById("idprivate").value;
+ var pubkey=floCrypto.getPubKeyHex(privatekey)
+ document.getElementById("publickeyhex").innerHTML="Public Key: ";
+ var id=document.querySelector("#publickeyhex");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=pubkey;
+ id.appendChild(newdiv);
+
+ }
+
+ function calcfloid()
+ {
+ let keyy= document.getElementById("key").value;
+ var floid =floCrypto.getFloID(keyy)
+ document.getElementById("floo").innerHTML="FLO ID: ";
+ var id=document.querySelector("#floo");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=floid;
+ id.appendChild(newdiv);
+ }
+
+ function verifyprivatekey()
+ {
+ let privatekey=document.getElementById("privatek").value;
+ let pubKey_floID= document.getElementById("keey").value;
+ var ver= Boolean (floCrypto.verifyPrivKey(privatekey, pubKey_floID))
+
+ if(ver==true)
+ {
+ document.getElementById("verify").innerHTML="TRUE, The private-key is verified for the given public-key or flo-ID."
+ }
+ else
+ {
+ document.getElementById("verify").innerHTML="FALSE, The private-key is not verified for the given public-key or flo-ID. "
+
+ }
+
+ }
+
+ function signdata()
+ {
+ let data=document.getElementById("msg5").value;
+ let privKey=document.getElementById("type5").value;
+ var signature =floCrypto.signData(data, privKey)
+ document.getElementById("signed").innerHTML="Signed data is,";
+ var id=document.querySelector("#signed");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=signature;
+ id.appendChild(newdiv);
+ }
+
+ function verification()
+ {
+ let data=document.getElementById("d").value;
+ let sigg=document.getElementById("s").value;
+ let val=document.getElementById("p").value;
+ var r=(floCrypto.verifySign(data,sigg,val))
+ if(r==true)
+ {
+ document.getElementById("v1").innerHTML="TRUE, Signature is verified!!";
+ }
+ else
+ {
+ document.getElementById("v1").innerHTML="FALSE, Signature is not verified!!";
+ }
+ }
+ function validateflo()
+ {
+ let floid=document.getElementById("flo1").value;
+ var res=Boolean(floCrypto.validateAddr(floid))
+ if(res==true)
+ {
+ document.getElementById("write1").innerHTML="TRUE, FLO ID is validated.";
+ }
+ else
+ {
+ document.getElementById("write1").innerHTML="FALSE, FLO ID is not validated.";
+
+ }
+ }
+ function genrandomint()
+ {
+ let minval=document.getElementById("genrandom1").value;
+ let maxval=document.getElementById("genrandom2").value;
+ var result= floCrypto.randInt(minval, maxval)
+ document.getElementById("write41").innerHTML="The random integer is : ";
+ var id=document.querySelector("#write41");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=result;
+ id.appendChild(newdiv);
+ }
+ function genrandomstr()
+ {
+ let str=document.getElementById("randomstr").value;
+ let val=document.getElementById("val3").value;
+ var randstring= floCrypto.randString(str, val)
+ document.getElementById("write7").innerHTML="Random string is:
"
+ var id=document.querySelector("#write7");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=randstring;
+ id.appendChild(newdiv);
+ }
+
+ function createshare()
+ {
+ let data=document.getElementById("shdata").value;
+ let numshare=parseInt( document.getElementById("shshare").value);
+ let limit =parseInt( document.getElementById("shnumber").value);
+ const x=[];
+ const v=[];
+ var i=0;
+ // x.push(floCrypto.createShamirsSecretShares(data,numshare,limit));
+ const h=x.concat(floCrypto.createShamirsSecretShares(data,numshare,limit));
+ document.getElementById("write2").innerHTML="The shares are,";
+ //document.getElementById("write3").innerHTML=h;
+ var id=document.querySelector("#write3");
+ for(i=0;i"+shresult;
+ }
+
+ const m=[];
+ function button1()
+ {
+ m.push(document.getElementById("ar9").value);
+ document.getElementById("ar9").value='';
+
+ //alert("pushed!!");
+ }
+ function verifysecret()
+ {
+ let c=document.getElementById("ar8").value
+ var z1= Boolean( floCrypto.verifyShamirsSecret(m,c))
+ if(z1==true)
+ {
+ document.getElementById("write21").innerHTML="TRUE,The shares are verified!!";
+ }
+ else
+ {
+ document.getElementById("write21").innerHTML="FALSE,The shares are not verified!!";
+
+ }
+ }
+
+ function resetbtn()
+ {
+ var con= confirm("Do you really want to clear the array?");
+
+ if(con==true)
+ {
+ y.length=0;
+ document.getElementById("write11").innerHTML="";
+ document.getElementById("ar1").value="";
+ }
+
+ }
+ function resetbtn1()
+ {
+ var con1= confirm("Do you really want to clear the array?");
+ if(con1==true)
+ {
+ m.length=0;
+ document.getElementById("write21").innerHTML="";
+ document.getElementById("ar9").value="";
+ document.getElementById("ar8").value="";
+
+
+
+ }
+ }
+
+ function crypto()
+ {
+ let s1=document.getElementById("t1").value;
+ let s2=document.getElementById("t2").value;
+ let s3=document.getElementById("t3").value;
+
+ var ob=floCrypto.encryptData(s1,s2)
+ var sender=ob.senderPublicKeyString;
+ document.getElementById("w1").innerHTML="Encrypted Data: ";
+ document.getElementById("w2").innerHTML="XPublic Key: ";
+ document.getElementById("w3").innerHTML="YPublic Key: ";
+ var id=document.querySelector("#w1");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=ob.secret;
+ id.appendChild(newdiv);
+ var id=document.querySelector("#w2");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=sender.XValuePublicString;
+ id.appendChild(newdiv);
+ var id=document.querySelector("#w3");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=sender.YValuePublicString;
+ id.appendChild(newdiv); }
+
+
+ function crypto1()
+ {
+ var a=document.getElementById("t6").value;//xvalue
+ var b=document.getElementById("t7").value;//yvalue
+ var c=document.getElementById("t8").value;//encrypted data
+ var d=document.getElementById("t3").value;//privkey
+ var q={XValuePublicString:a,
+ YValuePublicString:b}
+ var s={secret:c,
+ senderPublicKeyString:q}
+ var obs=floCrypto.decryptData(s,d)
+ document.getElementById("q2").innerHTML="The decrypted data is,
";
+ var id=document.querySelector("#q2");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=obs;
+ id.appendChild(newdiv);
+ }
+
+ function ppp(id)
+ {
+ const mypop=document.getElementById(id);
+ mypop.show();
+ }
diff --git a/js/rscript.js b/js/rscript.js
new file mode 100644
index 0000000..722c773
--- /dev/null
+++ b/js/rscript.js
@@ -0,0 +1,329 @@
+let type;
+
+let userMessage;
+let objectName;
+let demo = [
+ "demoSendGeneralData",
+ "demoRequestGeneralData",
+ "demoSendApplicationData",
+ "demoRequestApplicationData",
+ "demoResetObjectData",
+ "demoUpdateObjectData",
+ "demoRequestObjectData",
+];
+
+// buttons
+let sendUserMessage = document.getElementById("sendUserMessage");
+let requestUserMessage = document.getElementById("requestUserMessage");
+let resetObjectData = document.getElementById("resetObjectData");
+let updateObjectData = document.getElementById("updateObjectData");
+let requestObjectData = document.getElementById("requestObjectData");
+let sendApplicationMessage = document.getElementById(
+ "sendApplicationMessage"
+);
+let requestApplicationMessage = document.getElementById(
+ "requestApplicationMessage"
+);
+
+resetObjectData.addEventListener("click", () => {
+ console.log("sending message");
+
+ resetData(demo[4]);
+ setObjectName(demo[4]);
+ let optionsObj = setOptions(demo[4]);
+
+ let objName = generateObject("resetKeyValueBlock");
+
+ floCloudAPI.resetObjectData(objName, optionsObj).then(
+ function (value) {
+ displayCode(value, 4);
+ },
+ function (error) {
+ displaycode1("errreset");
+ }
+ )
+});
+
+updateObjectData.addEventListener("click", () => {
+ console.log("sending message");
+
+ resetData(demo[5]);
+ setObjectName(demo[5]);
+ let optionsObj = setOptions(demo[5]);
+
+ let objName = generateObject("updateKeyValueBlock");
+
+ floCloudAPI.updateObjectData(objName, optionsObj).then(
+ function (value) {
+ displayCode(value, 5);
+ },
+ function (error) {
+ displaycode1("errobjupd");
+ }
+ );
+});
+
+
+requestObjectData.addEventListener("click", () => {
+ console.log("sending message");
+
+ resetData(demo[6]);
+ setObjectName(demo[6]);
+
+ let optionsObj = setOptions(demo[6]);
+
+ floCloudAPI.requestObjectData(objectName, optionsObj).then(
+ function (value) {
+ let result = floGlobals.appObjects[objectName];
+ displayCode(result, 6);
+ },
+ function (error) {
+ displaycode1("reqerrobj")
+ }
+ );
+});
+
+ sendApplicationMessage.addEventListener("click", () => {
+ console.log("sending message");
+
+ resetData(demo[2]);
+
+ setType(demo[2]);
+ setMessage(demo[2]);
+ let optionsObj = setOptions(demo[2]);
+
+ floCloudAPI.sendApplicationData(userMessage, type, optionsObj).then(
+ function (value) {
+ displayCode(value, 2);
+ },
+ function (error) {
+ displaycode1("demo-inner-blocks12")
+ }
+ );
+});
+
+requestApplicationMessage.addEventListener("click", () => {
+ console.log("requesting message");
+
+ resetData(demo[3]);
+ let optionsObj = setOptions(demo[3]);
+
+ floCloudAPI.requestApplicationData(optionsObj).then(
+ function (value) {
+ displayCode(value, 3);
+ },
+ function (error) {
+ displaycode1("errrequest")
+ }
+ );
+});
+
+sendUserMessage.addEventListener("click", () => {
+ console.log("sending message");
+ resetData(demo[0]);
+ setType(demo[0]);
+ setMessage(demo[0]);
+ let optionsObj = setOptions(demo[0]);
+
+ floCloudAPI.sendGeneralData(userMessage, type, optionsObj).then(
+ function (value) {
+ displayCode(value, 0);
+ },
+ function (error) {
+ displaycode1("errsendgen")
+ }
+ );
+});
+
+requestUserMessage.addEventListener("click", () => {
+ console.log("requesting message");
+ resetData(demo[1]);
+ setType(demo[1]);
+
+ let optionsObj = setOptions(demo[1]);
+
+ floCloudAPI.requestGeneralData(type, optionsObj).then(
+ function (value) {
+ displayCode(value, 1);
+ },
+ function (error) {
+ displaycode1("errreqgen");
+ }
+ );
+});
+
+function displayCode(value, index) {
+ let demoBlock = document.querySelector("." + demo[index]);
+ let frag = document.createDocumentFragment();
+ let codeLabel = document.createElement("p");
+ let outputLabel = document.createElement("p");
+ let codeBlock = document.createElement("pre");
+ let outputBlock = document.createElement("pre");
+
+ outputBlock.classList.add("scroll");
+ codeBlock.classList.add("scroll");
+ outputBlock.classList.add("demo-inner-blocks1");
+ codeBlock.classList.add("demo-inner-blocks1");
+
+ codeLabel.innerHTML = "Code:";
+ outputLabel.innerHTML = "Output:";
+ outputBlock.innerHTML = JSON.stringify(value, undefined, 4);
+
+ if (index == 0) {
+ codeBlock.innerHTML = `floCloudAPI.sendGeneralData("${userMessage}", "${type}")`;
+ } else if (index == 1) {
+ codeBlock.innerHTML = `floCloudAPI.requestGeneralData("${type}"")`;
+ } else if (index == 2) {
+ codeBlock.innerHTML = `floCloudAPI.sendApplicationData("${userMessage}", "${type}")`;
+ } else if (index == 3) {
+ codeBlock.innerHTML = `floCloudAPI.requestApplicationData()`;
+ } else if (index == 4) {
+ codeBlock.innerHTML = `floCloudAPI.resetObjectData("${objectName}")`;
+ } else if (index == 5) {
+ codeBlock.innerHTML = `floCloudAPI.updateObjectData("${objectName}")`;
+ } else if (index == 6) {
+ codeBlock.innerHTML = `floCloudAPI.requestObjectData("${objectName}")`;
+ }
+
+ frag.appendChild(codeLabel);
+ frag.appendChild(codeBlock);
+ frag.appendChild(outputLabel);
+ frag.appendChild(outputBlock);
+
+ demoBlock.appendChild(frag);
+}
+function displaycode1(id6){
+ document.getElementById(id6).innerHTML = "
Unsuccessfull!!
Kindly check if all the inputs are correct!
Also try restarting the page!";
+}
+
+function addKeyValuePairs(id, pairId, index) {
+ let keyValueBlock = document.getElementById(id);
+ let pairBlock = keyValueBlock.querySelector("#" + pairId);
+ let pairClone = pairBlock.cloneNode(true);
+ let plusBtn = pairBlock.querySelector(".plus");
+ let plusBtnNew = pairClone.querySelector(".plus");
+
+ pairBlock.removeChild(plusBtn);
+ pairClone.setAttribute("id", "pair" + index);
+ plusBtnNew.setAttribute(
+ "onclick",
+ `addKeyValuePairs('${id}' ,'pair${index}', ${index + 1})`
+ );
+
+ keyValueBlock.appendChild(pairClone);
+}
+
+function generateObject(id) {
+ let keyValueBlock = document.getElementById(id);
+ let pairs = keyValueBlock.querySelectorAll(".pairs");
+ let objUser = objectName;
+ let obj = {};
+
+ pairs.forEach((pair) => {
+ let key = pair.querySelector(".key").value;
+ let value = pair.querySelector(".value111").value;
+
+ obj[key] = value;
+ });
+
+ floGlobals.appObjects[objUser] = obj;
+
+ return objUser;
+}
+
+
+function setType(blockID) {
+ let block = document.querySelector("." + blockID);
+ let messageType = block.querySelector(".messageType").value;
+
+ console.log("type is ", messageType);
+
+ if (!messageType) {
+ type = "type2";
+ } else {
+ type = messageType;
+ }
+}
+
+function setMessage(blockID) {
+ let block = document.querySelector("." + blockID);
+ let message = block.querySelector(".message").value;
+
+ if (!message) {
+ userMessage = "test message";
+ } else {
+ userMessage = message;
+ }
+}
+
+function setObjectName(blockID) {
+ let block = document.querySelector("." + blockID);
+ let obj = block.querySelector(".objectName").value;
+
+ if (!obj) {
+ objectName = "objTest";
+ } else {
+ objectName = obj;
+ }
+}
+
+function setOptions(blockID) {
+ let block = document.querySelector("." + blockID);
+ let comment = block.querySelector(".comment").value;
+ let applicationName = block.querySelector(".applicationName").value;
+ let receiverID = block.querySelector(".receiverID").value;
+ let optionsType;
+ let atVectorClock, lowerVectorClock, upperVectorClock;
+ let optionsObj = {};
+
+ if (
+ blockID == "demoRequestApplicationData" ||
+ blockID == "demoRequestGeneralData" ||
+ blockID == "demoRequestObjectData"
+ ) {
+ optionsType = block.querySelector(".typeName").value;
+ atVectorClock = block.querySelector(".atVectorClock").value;
+ lowerVectorClock = block.querySelector(".lowerVectorClock").value;
+ upperVectorClock = block.querySelector(".upperVectorClock").value;
+ }
+
+ if (comment) {
+ optionsObj["comment"] = comment;
+ }
+
+ if (applicationName) {
+ optionsObj["application"] = applicationName;
+ }
+
+ if (receiverID) {
+ optionsObj["receiverID"] = applicationName;
+ }
+
+ if (optionsType) {
+ optionsObj["Type"] = optionsType;
+ }
+
+ return optionsObj;
+}
+
+function resetData(blockID) {
+ let block = document.querySelector("." + blockID);
+ let p = block.querySelectorAll("p");
+ let pre = block.querySelectorAll("pre");
+
+ if (p && pre) {
+ p.forEach((ele) => {
+ ele.innerHTML = "";
+ });
+
+ pre.forEach((ele) => {
+ ele.innerHTML = "";
+ });
+ }
+}
+
+function displayPopUp(id) {
+ let popUp = document.getElementById(id);
+
+ popUp.show();
+}
diff --git a/js/script.js b/js/script.js
new file mode 100644
index 0000000..15c8e1f
--- /dev/null
+++ b/js/script.js
@@ -0,0 +1,384 @@
+//sendtx
+document.getElementById("sendtx").addEventListener('click',()=>{
+ let receiverAddr=document.getElementById("rfloi").value;
+ let senderAddr=document.getElementById("sfloi").value;
+ let PrivKey=document.getElementById("sprivi").value;
+ let sendAmt=parseFloat (document.getElementById("floc").value);
+ let floData=document.getElementById("datai").value;
+ floBlockchainAPI.sendTx(senderAddr, receiverAddr, sendAmt, PrivKey, floData = '').then(
+ function (value) {
+ if(floCrypto.validateAddr(recieverAddr)&& floCrypto.validateAddr(senderAddr)){
+ document.getElementById("sendtxotp").innerHTML="Transaction Failed!! This might be the problem,
Invalid FLO Id";
+
+ }
+
+ let tid=value;
+ document.getElementById("sendtxotp").innerHTML="Transaction Successful!!"+"
"+"Transaction ID: "
+ var id1=document.querySelector("#sendtxotp");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=tid;
+ id1.appendChild(newdiv);
+ },
+ function (error) {
+ document.getElementById("sendtxotp").innerHTML="Transaction Failed!! This might be the problem, "+error;
+ }
+ );
+});
+//readtx
+document.getElementById("readtx"). addEventListener('click',()=>{
+ let addr=document.getElementById("floidd").value;
+ let from=document.getElementById("fromi").value;
+ let to= document.getElementById("endi").value;
+ if(floCrypto.validateAddr(addr)){
+ floBlockchainAPI.readTxs(addr,from,to).then(
+ function (value) {
+ if(value.totalItems>0){
+ let len=to-from;
+ // document.getElementById("readtxotp1").innerHtml="The Transaction ID from: "+from+" to: "+to+",
";
+ document.getElementById("readtxotp").innerHTML="The Transaction ID from "+from+" to "+to+" is listed below,"+"
";
+ for(let i=0;i<=len;i++)
+ {
+ var id1=document.querySelector("#readtxotp");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=value.items[i].txid;
+ id1.appendChild(newdiv);
+ }}
+ else{
+ document.getElementById("readtxotp").innerHTML='There are no Transactions for FLO ID "'+addr+'"';
+ }
+ },
+ function (error) {
+ document.getElementById("readtxotp").innerHTML="Failed to fetch Transaction details!! This might be the problem, "+error;
+ }
+ ); }
+ else{
+ document.getElementById("readtxotp").innerHTML="Failed to fetch Transaction details!! This might be the problem,
Invalid FLO ID...";
+
+ }
+})
+//readalltxs
+document.getElementById("readtxall").addEventListener('click',()=> {
+ let addr=document.getElementById("flo").value;
+ if(floCrypto.validateAddr(addr)){
+ floBlockchainAPI.readTxs(addr).then(
+ function (value) {
+ if(value.totalItems>0){
+ document.getElementById("readalltxotp").innerHTML="The transaction details are,
"
+ for(let i=0;i<=value.to;i++)
+ {
+ let outputreadalltx=value;
+ var id1=document.querySelector("#readalltxotp");
+ var newdiv= document.createElement('sm-copy')
+ newdiv.value=outputreadalltx.items[i].txid;
+ id1.appendChild(newdiv);
+ }}
+ else{
+ document.getElementById("readalltxotp").innerHTML='There are no Transactions for FLO ID "'+addr+'"';
+ }
+ },
+ function (error) {
+ document.getElementById("readalltxotp").innerHTML="Failed to fetch Transaction details!! This might be the reason, "+error;
+ }
+ ); }
+ else{
+ document.getElementById("readalltxotp").innerHTML="Failed to fetch Transaction details!! This might be the reason,
Invalid FLO ID";
+ }
+});
+//mergeutxo
+document.getElementById("mergeutxo").addEventListener('click',()=>{
+ let floID=document.getElementById("mflom").value;
+ let privKey=document.getElementById("privkm").value;
+ let floData=document.getElementById("datam").value;
+ if(floCrypto.validateAddr(floID)){
+ floBlockchainAPI.mergeUTXOs(floID,privKey, floData = '').then(
+ function (value) {
+ var id1=document.querySelector("#mergeotp");
+ var newdiv= document.createElement('sm-copy')
+ document.getElementById("mergeotp").innerHTML="Merge Successful!!
Transaction ID: ";
+ newdiv.value=value;
+ id1.appendChild(newdiv);
+ },
+ function (error) {
+ document.getElementById("mergeotp").innerHTML="Merge Unsuccessful!! This might be the problem, "+error;
+ }
+ ); }
+ else{
+ document.getElementById("mergeotp").innerHTML="Merge Unsuccessful!! This might be the problem,
Invalid FLO ID";
+ }
+});
+
+//sentx multiple
+
+//for sender priv key
+let aa=new Array();
+document.getElementById("add1").addEventListener('click',()=>{
+ aa.push(document.getElementById("rflo").value);
+ document.getElementById("rflo").value="";
+})
+document.getElementById("clear1").addEventListener('click',()=>{
+var r= confirm("Do you really want to clear the array?");
+{
+ if(r==true){
+ aa.length=0;
+ document.getElementById("rflo").value="";
+ document.getElementById("sendtxmultotp").innerHTML="";
+ }
+ }
+})
+let obj={}
+//for reciever floid and amnt
+document.getElementById("add2").addEventListener('click',()=>{
+ if(floCrypto.validateAddr(document.getElementById("sflo").value)){
+ if(document.getElementById("ramt").value=="" || parseFloat( document.getElementById("ramt").value)==0 ){
+ document.getElementById("eralert").innerHTML="Couldn't complete action ,This might be the problem,
Amount cannot be 0";
+ return;
+ }
+let key1=document.getElementById("sflo").value;
+let value3=parseFloat(document.getElementById("ramt").value);
+obj[key1]=value3;
+document.getElementById("sflo").value="";
+document.getElementById("ramt").value="";
+document.getElementById("eralert").innerHTML="";
+}
+else{
+ document.getElementById("eralert").innerHTML="Couldn't complete action ,This might be the problem,
Invalid FLO ID";
+}
+})
+document.getElementById("clear2").addEventListener('click',()=>{
+ var r=confirm("Do you really want to clear the array?");
+ if(r==true)
+ {
+ document.getElementById("sflo").value="";
+ document.getElementById("ramt").value="";
+ document.getElementById("sendtxmultotp").innerHTML="";
+ document.getElementById("eralert").innerHTML="";
+ }
+})
+document.getElementById("sendtxmulti").addEventListener('click',()=>{
+ let data=document.getElementById("data").value;
+ document.getElementById("eralert").innerHTML="";
+ floBlockchainAPI.sendTxMultiple(aa, obj, data = '').then(
+function (value) {
+
+var id1=document.querySelector("#sendtxmultotp");
+var newdiv= document.createElement('sm-copy')
+document.getElementById("sendtxmultotp").innerHTML="Transaction Successful!!
Transaction ID: ";
+newdiv.value=value;
+id1.appendChild(newdiv);
+},
+function (error) {
+ // alert(Object.getOwnPropertyNames(error));
+ document.getElementById("sendtxmultotp").innerHTML="Transaction Failed!!";
+}
+);
+})
+//writedata
+document.getElementById("writedata").addEventListener('click',()=>{
+ let senderAddr=document.getElementById("sfloid").value;
+let Data=document.getElementById("datawrite").value;
+let Privkey = document.getElementById("privwrite").value;
+let receiverAddr= document.getElementById("rflowrite").value;
+floBlockchainAPI.writeData(senderAddr, Data, Privkey, receiverAddr = floGlobals.adminID).then(
+function (value) {
+ for(i=0;i<=value.length;i++){
+
+var id1=document.querySelector("#writedataotp");
+var newdiv= document.createElement('sm-copy')
+document.getElementById("writedataotp").innerHTML="Successful!!
Transaction ID: ";
+newdiv.value=value;
+id1.appendChild(newdiv);
+ }
+ //alert(value[i]);
+//alert("successful");
+},
+function (error) {
+ document.getElementById("writedataotp").innerHTML="Not able to complete the action!!
This might be the problem, "+error;
+}
+);
+})
+
+//writedata multiple
+let sprivkey=new Array();
+let rfloid= new Array();
+
+//for sender priv key
+document.getElementById("wdmpush1").addEventListener('click',()=>{
+ let senderPrivKeys=document.getElementById("priv1").value;
+ sprivkey.push(senderPrivKeys);
+ document.getElementById("priv1").value="";
+})
+document.getElementById('wdmclear1').addEventListener('click',()=>{
+ let r1=confirm("Do you really want to clear the array?");
+ if(r1==true)
+ {
+ sprivkey.length=0;
+ document.getElementById("writedatamultiotp").innerHTML="";
+ document.getElementById("priv1").value="";
+ }
+})
+//for reciever flo id
+document.getElementById("wdmpush2").addEventListener("click",()=>{
+ if( floCrypto.validateAddr(document.getElementById("recflo").value)){
+ let receivers=document.getElementById("recflo").value;
+ rfloid.push(receivers);
+ document.getElementById("recflo").value="";
+ document.getElementById("errwrite11").innerHTML="";
+ }
+ else{
+ document.getElementById("errwrite11").innerHTML="Couldn't complete action , This might be the problem,
Invalid FLO ID";
+ }
+})
+document.getElementById('wdmclear2').addEventListener('click',()=>{
+ let r1=confirm("Do you really want to clear the array?");
+ if(r1==true)
+ {
+ rfloid.length=0;
+ document.getElementById("writedatamultiotp").innerHTML="";
+ document.getElementById("recflo").value="";
+ document.getElementById("errwrite11").innerHTML="";
+ }
+});
+ document.getElementById("writedatamultiple").addEventListener('click',()=>{
+ if(sprivkey.length!=0){
+ if(rfloid.length==0){
+ document.getElementById("writedatamultiotp").innerHTML="Not able to complete the action!!
This might be the problem,
Invalid FLO ID";
+ return;
+ }
+ let data=document.getElementById("data1").value;
+ let preserveRatio=document.getElementById("pratio").value;
+ floBlockchainAPI.writeDataMultiple(sprivkey, data, rfloid = [floGlobals.adminID], preserveRatio = true).then(
+ function (value) {
+ var id1=document.querySelector("#writedatamultiotp");
+ var newdiv= document.createElement('sm-copy')
+ document.getElementById("writedatamultiotp").innerHTML="Successful!!
Transaction ID: ";
+ newdiv.value=value;
+ id1.appendChild(newdiv);
+ },
+ function (error) {
+ document.getElementById("writedatamultiotp").innerHTML="Not able to complete the action!!
This might be the problem,"+ error.problem;
+ }
+ );}
+ else{
+ document.getElementById("writedatamultiotp").innerHTML="Not able to complete the action!!
This might be the problem,
No sender private key entered!!";
+ }
+ })
+
+//get balance
+document.getElementById("getbalance").addEventListener('click',()=>{
+ if(floCrypto.validateAddr(document.getElementById("floidbal").value)){
+ let id=document.getElementById("floidbal").value;
+floBlockchainAPI.getBalance(id).then(
+ function (value) {
+ var id1=document.querySelector("#getbalanceotp");
+ var newdiv= document.createElement('sm-copy')
+ document.getElementById("getbalanceotp").innerHTML="Your Balance is: ";
+ newdiv.value=value;
+ id1.appendChild(newdiv);
+},
+function (error) {
+document.getElementById("getbalanceotp").innerHTML="Not able to fetch the Balance!!
This might be the problem, "+error;
+}
+);}
+else{
+ document.getElementById("getbalanceotp").innerHTML="Not able to fetch the Balance!!
This might be the problem,
Invalid FLO ID!!";
+}
+})
+
+//read data
+let z={};
+document.getElementById("readdata").addEventListener("click",()=>{
+ if(floCrypto.validateAddr(document.getElementById("readflo").value)){
+ let readflo1=document.getElementById("readflo").value;
+ z.limit=(document.getElementById("readlim").value);
+ z.ignoreOld=(document.getElementById("readold").value);
+ z.sentOnly=(document.getElementById("readsentonly").value);
+ z.pattern=(document.getElementById("readpattern").value);
+ z.filter=(document.getElementById("readfilter").value);
+ let flag=0;
+ floBlockchainAPI.readData(readflo1, z = {}).then(
+ function (value) {
+ document.getElementById("readdataotp").innerHTML='
Total transactions of "'+readflo1+'" : "'+value.totalTxs+'"
';
+ document.getElementById("readdataotp1").innerHTML="Messages :
";
+ for(let i=0;iTransaction Failed!! This might be the problem, "+error;
+ document.getElementById("readdataotp1").innerHTML="";
+ }
+ )}
+ else{
+ document.getElementById("readdataotp").innerHTML="Transaction Failed!! This might be the problem,
Invalid FLO ID!!";
+ document.getElementById("readdataotp1").innerHTML="";
+ }
+
+});
+
+//popup
+
+
+function pp(id)
+{
+ const mypop=document.getElementById(id);
+ mypop.show();
+}
+
+//sendtx constructing
+document.getElementById("sendtx").addEventListener('click',()=>{
+ document.getElementById("al1").innerHTML="
Constructing Send Tx : floBlockchainAPI.sendTx("+document.getElementById("sfloi").value+","+ document.getElementById("rfloi").value+","+ parseFloat (document.getElementById("floc").value)+","+ document.getElementById("sprivi").value+","+ document.getElementById("datai").value+")";
+ settime("al1");
+})
+//sendtx multiple constructing
+document.getElementById("sendtxmulti").addEventListener('click',()=>{
+ document.getElementById("al2").innerHTML="
Constructing Send Tx Multiple : floBlockchainAPI.sendTxMultiple(senderPrivKeys["+aa.length+"],"+ obj+ ","+document.getElementById("data").value+")";
+ settime("al2");
+})
+//mergeutxo
+document.getElementById("mergeutxo").addEventListener('click',()=>{
+ document.getElementById("al3").innerHTML="
Constructing Merge UTXOs : floBlockchainAPI.mergeUTXOs("+document.getElementById("mflom").value+","+document.getElementById("privkm").value+","+ document.getElementById("datam").value+")";
+ settime("al3");
+})
+//read tx
+document.getElementById("readtx").addEventListener('click',()=>{
+ document.getElementById("al4").innerHTML="
Constructing Read Tx : floBlockchainAPI.readTxs("+document.getElementById("floidd").value+","+ document.getElementById("fromi").value+","+ document.getElementById("endi").value+")";
+ settime("al4");
+})
+//readtxall
+document.getElementById("readtxall").addEventListener('click',()=>{
+ document.getElementById("al5").innerHTML="
Constructing Read all Tx : floBlockchainAPI.readTxs('"+document.getElementById("flo").value+"')";
+ settime("al5");
+})
+//getbalance
+document.getElementById("getbalance").addEventListener('click',()=>{
+ document.getElementById("al6").innerHTML="
Constructing Get Balance : floBlockchainAPI.getBalance('"+document.getElementById("floidbal").value+"')";
+ settime("al6");
+})
+//readdata
+document.getElementById("readdata").addEventListener('click',()=>{
+ document.getElementById("al7").innerHTML="
Constructing Read Data : floBlockchainAPI.readData("+document.getElementById("readflo").value+",{options"+"})";
+ settime("al7");
+})
+//writedata
+document.getElementById("writedata").addEventListener('click',()=>{
+ document.getElementById("al8").innerHTML="
Constructing Write Data : floBlockchainAPI.writeData("+document.getElementById("sfloid").value+","+ document.getElementById("datawrite").value+","+ document.getElementById("privwrite").value+","+ document.getElementById("rflowrite").value+")
";
+ settime("al8");
+})
+//write data multiple
+document.getElementById("writedatamultiple").addEventListener('click',()=>{
+ document.getElementById("al9").innerHTML="
Constructing Write Data Multiple : floBlockchainAPI.writeDataMultiple(senderPrivKeys["+sprivkey.length+"],"+ document.getElementById("data1").value+",receivers["+rfloid.length+"],"+ document.getElementById("pratio").value+")";
+ settime("al9");
+})
+//set time constructor
+function settime(id){
+ setInterval(()=>{document.getElementById(id).innerHTML=""},20000)
+}
\ No newline at end of file