diff --git a/components/css/main.css b/components/css/main.css
index 5f5ae53..2bba927 100644
--- a/components/css/main.css
+++ b/components/css/main.css
@@ -15,6 +15,7 @@ html, body {
}
body {
+ color: rgba(var(--text-color), 1);
background: rgba(var(--background-color), 1);
}
body,
@@ -23,7 +24,6 @@ body * {
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--danger-color: red;
- color: rgba(var(--text-color), 1);
}
body[data-theme=dark],
@@ -326,13 +326,10 @@ ul {
.token.prolog,
.token.doctype,
.token.cdata {
- color: #AEAEAE;
-}
-
-.token.punctuation {
- color: #9789ee;
+ color: #50CB93;
}
+.token.punctuation,
.token.tag {
color: #29B6F6;
}
@@ -365,7 +362,7 @@ ul {
.token.atrule,
.token.keyword,
.token.builtin {
- color: #cc99cd;
+ color: #FF6767;
}
.token.string,
@@ -406,7 +403,7 @@ pre {
overflow-x: auto;
font-size: 0.9rem;
font-weight: 500;
- white-space: pre-line;
+ white-space: pre;
border-radius: 0.5rem;
background: rgba(0, 0, 0, 0.9);
line-height: 1.7;
@@ -416,11 +413,11 @@ code {
border-radius: 0.3rem;
font-weight: 400;
padding: 0.2rem 0.4rem;
- color: rgba(255, 255, 255, 0.9);
background: rgba(var(--text-color), 0.1);
}
code * {
+ color: rgba(255, 255, 255, 0.9);
font-family: "Roboto Mono", monospace;
}
@@ -439,9 +436,6 @@ h2 {
margin: 3rem 0 1rem 0;
text-transform: capitalize;
}
-h2:first-of-type {
- margin-top: 1rem;
-}
main {
display: grid;
diff --git a/components/css/main.min.css b/components/css/main.min.css
index 98df5aa..bc8ed7c 100644
--- a/components/css/main.min.css
+++ b/components/css/main.min.css
@@ -1 +1 @@
-p,pre{line-height:1.7}.list,ul{list-style:none}p,strong{max-width:65ch}*{padding:0;margin:0;box-sizing:border-box;font-family:Roboto,sans-serif}:root{font-size:clamp(1rem,1.2vmax,3rem)}body,html{height:100%;scroll-behavior:smooth}body{background:rgba(var(--background-color),1)}body,body *{--accent-color:#0D7377;--text-color:17,17,17;--background-color:255,255,255;--danger-color:red;color:rgba(var(--text-color),1)}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;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}.table{display:grid;gap:.5rem;margin:1rem 0;position:relative;text-align:left;overflow-x:auto;border-radius:.3rem;border-collapse:separate;border-spacing:1rem 1.5rem;background-color:rgba(var(--text-color),.04)}.table p:only-of-type{margin-bottom:0}.tr{display:grid;gap:1rem;padding:1rem;grid-template-columns:12rem 1fr;width:100%}.tr:nth-of-type(odd){background-color:rgba(var(--text-color),.04)}.tr p{min-width:30ch}.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:.8rem}#side_nav h4,.highlight,pre{font-size:.9rem}.uppercase{text-transform:uppercase}.capitalize,.list__item,h2,ol li::first-letter{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:.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}.button__icon--right,.comp-checkbox__title{margin-left:.5rem}.align-self-center{align-self:center}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.card,.direction-column,.list{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}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#AEAEAE}.token.punctuation{color:#9789ee}.token.tag{color:#29B6F6}.token.attr-name,.token.deleted,.token.namespace{color:#1DE9B6}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#84FFFF}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}pre{max-width:100%;margin:1rem 0;padding:0 1.5rem;overflow-x:auto;font-weight:500;white-space:pre-line;border-radius:.5rem;background:rgba(0,0,0,.9)}code{border-radius:.3rem;font-weight:400;padding:.2rem .4rem;color:rgba(255,255,255,.9);background:rgba(var(--text-color),.1)}code *{font-family:"Roboto Mono",monospace}pre code{line-height:1.4;border-radius:none;background:0 0;width:100%}h1,h2,h3,h4.h5{font-family:Poppins,sans-serif}h2{margin:3rem 0 1rem}h2:first-of-type{margin-top:1rem}main{display:grid;height:100%}.card,.list,.list__item,.page,strong.important{display:flex}#main_header{padding:.5rem 1.5rem;border-bottom:1px solid rgba(var(--text-color),.1)}#side_nav_button{padding:.5rem;margin-left:-.5rem}#side_nav>:last-child{padding-bottom:3rem}#side_nav h4{letter-spacing:.08em;text-transform:uppercase;padding:1.5rem}.right{max-height:100%;overflow-y:auto;padding:1.5rem}.right h1{margin-bottom:1.5rem}.list{margin-bottom:.8rem}ol li,sm-carousel{margin-bottom:1rem}.list__item{padding:.8rem 1.5rem}.list__item--active{color:var(--accent-color);background:rgba(var(--text-color),.06)}.card{margin-right:1rem;border-radius:.4rem;padding:1.5rem;min-width:min(24rem,80%);background-color:rgba(var(--text-color),.06)}sm-tab-header{margin-bottom:1.5rem}.page{flex-direction:column;padding-bottom:3rem}ol{padding:.6rem 1rem;max-width:75ch;margin-bottom:3rem}ol li:last-of-type{margin-bottom:0}strong.important{padding:.5rem;margin:.5rem 0;border-radius:.3rem;color:rgba(0,0,0,.8);background-color:khaki}.highlight{display:inline-flex;font-family:"Roboto Mono",monospace;background-color:rgba(var(--text-color),.1);border-radius:.2rem;padding:.1rem .5rem;line-height:1.6}#total_components_count{font-size:4rem}#components_selection_list{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr));padding:1.5rem 0 3rem}@media screen and (max-width:640px){main{grid-template-rows:auto 1fr;grid-template-columns:1fr}}@media screen and (min-width:640px){#main_header{padding:1rem 1.5rem;grid-area:main-header}#side_nav_button{display:none}main{grid-template-columns:14rem minmax(0,1fr);grid-template-areas:"main-header main-header" ". ."}.right{display:grid;grid-template-columns:1fr 90% 1fr}.right>*{grid-column:2/3}.page__title{font-size:2.5rem}#overview_page{display:grid;gap:1.5rem;grid-template-columns:1fr auto}#overview_page>div:first-of-type{grid-column:2/3;text-align:right}#overview_page>div:nth-of-type(2){grid-row:1/2}}@media (any-hover:hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color),.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color),.5)}.list__item:hover{background:rgba(var(--text-color),.1);cursor:pointer}}
\ No newline at end of file
+p,pre{line-height:1.7}.list,ul{list-style:none}p,strong{max-width:65ch}*{padding:0;margin:0;box-sizing:border-box;font-family:Roboto,sans-serif}: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;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}.table,.tr{display:grid}a:any-link:focus-visible{outline:solid rgba(var(--text-color),1)}sm-button{--border-radius:0.3rem}.table{gap:.5rem;margin:1rem 0;position:relative;text-align:left;overflow-x:auto;border-radius:.3rem;border-collapse:separate;border-spacing:1rem 1.5rem;background-color:rgba(var(--text-color),.04)}.table p:only-of-type{margin-bottom:0}.tr{gap:1rem;padding:1rem;grid-template-columns:12rem 1fr;width:100%}.tr:nth-of-type(odd){background-color:rgba(var(--text-color),.04)}.tr p{min-width:30ch}.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:.8rem}#side_nav h4,.highlight,pre{font-size:.9rem}.uppercase{text-transform:uppercase}.capitalize,.list__item,h2,ol li::first-letter{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:.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}.button__icon--right,.comp-checkbox__title{margin-left:.5rem}.align-self-center{align-self:center}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.card,.direction-column,.list{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}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#50CB93}.token.punctuation,.token.tag{color:#29B6F6}.token.attr-name,.token.deleted,.token.namespace{color:#1DE9B6}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#FF6767}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#84FFFF}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}pre{max-width:100%;margin:1rem 0;padding:0 1.5rem;overflow-x:auto;font-weight:500;white-space:pre;border-radius:.5rem;background:rgba(0,0,0,.9)}code{border-radius:.3rem;font-weight:400;padding:.2rem .4rem;background:rgba(var(--text-color),.1)}code *{color:rgba(255,255,255,.9);font-family:"Roboto Mono",monospace}pre code{line-height:1.4;border-radius:none;background:0 0;width:100%}h1,h2,h3,h4.h5{font-family:Poppins,sans-serif}h2{margin:3rem 0 1rem}main{display:grid;height:100%}.card,.list,.list__item,.page,strong.important{display:flex}#main_header{padding:.5rem 1.5rem;border-bottom:1px solid rgba(var(--text-color),.1)}#side_nav_button{padding:.5rem;margin-left:-.5rem}#side_nav>:last-child{padding-bottom:3rem}#side_nav h4{letter-spacing:.08em;text-transform:uppercase;padding:1.5rem}.right{max-height:100%;overflow-y:auto;padding:1.5rem}.right h1{margin-bottom:1.5rem}.list{margin-bottom:.8rem}ol li,sm-carousel{margin-bottom:1rem}.list__item{padding:.8rem 1.5rem}.list__item--active{color:var(--accent-color);background:rgba(var(--text-color),.06)}.card{margin-right:1rem;border-radius:.4rem;padding:1.5rem;min-width:min(24rem,80%);background-color:rgba(var(--text-color),.06)}sm-tab-header{margin-bottom:1.5rem}.page{flex-direction:column;padding-bottom:3rem}ol{padding:.6rem 1rem;max-width:75ch;margin-bottom:3rem}ol li:last-of-type{margin-bottom:0}strong.important{padding:.5rem;margin:.5rem 0;border-radius:.3rem;color:rgba(0,0,0,.8);background-color:khaki}.highlight{display:inline-flex;font-family:"Roboto Mono",monospace;background-color:rgba(var(--text-color),.1);border-radius:.2rem;padding:.1rem .5rem;line-height:1.6}#total_components_count{font-size:4rem}#components_selection_list{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr));padding:1.5rem 0 3rem}@media screen and (max-width:640px){main{grid-template-rows:auto 1fr;grid-template-columns:1fr}}@media screen and (min-width:640px){#main_header{padding:1rem 1.5rem;grid-area:main-header}#side_nav_button{display:none}main{grid-template-columns:14rem minmax(0,1fr);grid-template-areas:"main-header main-header" ". ."}.right{display:grid;grid-template-columns:1fr 90% 1fr}.right>*{grid-column:2/3}.page__title{font-size:2.5rem}#overview_page{display:grid;gap:1.5rem;grid-template-columns:1fr auto}#overview_page>div:first-of-type{grid-column:2/3;text-align:right}#overview_page>div:nth-of-type(2){grid-row:1/2}}@media (any-hover:hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color),.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color),.5)}.list__item:hover{background:rgba(var(--text-color),.1);cursor:pointer}}
\ No newline at end of file
diff --git a/components/css/main.scss b/components/css/main.scss
index 0970ca5..fcaa51f 100644
--- a/components/css/main.scss
+++ b/components/css/main.scss
@@ -12,15 +12,15 @@ html, body{
scroll-behavior: smooth;
}
body {
+ color: rgba(var(--text-color), 1);
+ background: rgba(var(--background-color), 1);
&,
*{
--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']{
@@ -276,13 +276,10 @@ ul{
.token.prolog,
.token.doctype,
.token.cdata {
- color: #AEAEAE;
-}
-
-.token.punctuation {
- color: rgb(151, 137, 238);
+ color: #50CB93;
}
+.token.punctuation,
.token.tag{
color: #29B6F6;
}
@@ -314,7 +311,7 @@ ul{
.token.atrule,
.token.keyword,
.token.builtin {
- color: #cc99cd;
+ color: #FF6767;
}
.token.string,
@@ -353,7 +350,7 @@ pre{
overflow-x: auto;
font-size: 0.9rem;
font-weight: 500;
- white-space: pre-line;
+ white-space: pre;
border-radius: 0.5rem;
background: rgba(0,0,0, 0.9);
line-height: 1.7;
@@ -362,10 +359,10 @@ code{
border-radius: 0.3rem;
font-weight: 400;
padding: 0.2rem 0.4rem;
- color: rgba(255, 255, 255, 0.9);
background: rgba(var(--text-color), .1);
}
code *{
+ color: rgba(255, 255, 255, 0.9);
font-family: 'Roboto Mono', monospace;
}
pre code{
@@ -382,9 +379,6 @@ h1,h2,h3,h4.h5{
h2{
margin: 3rem 0 1rem 0;
text-transform: capitalize;
- &:first-of-type{
- margin-top: 1rem;
- }
}
main{
display: grid;
diff --git a/components/dist/button.js b/components/dist/button.js
index 4aeebff..a6c5ad8 100644
--- a/components/dist/button.js
+++ b/components/dist/button.js
@@ -115,11 +115,19 @@ customElements.define('sm-button',
}
}
+ handleKeyDown(e) {
+ if (!this.hasAttribute('disabled') && (e.key === 'Enter' || e.code === 'Space')) {
+ e.preventDefault()
+ this.click()
+ }
+ }
+
connectedCallback() {
if (!this.hasAttribute('disabled')) {
this.setAttribute('tabindex', '0')
}
this.setAttribute('role', 'button')
+ this.addEventListener('keydown', this.handleKeyDown)
}
attributeChangedCallback(name, oldVal, newVal) {
if (name === 'disabled') {
diff --git a/components/dist/button.min.js b/components/dist/button.min.js
index 71dbcc3..b4daf45 100644
--- a/components/dist/button.min.js
+++ b/components/dist/button.min.js
@@ -1 +1 @@
-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(t){t?this.setAttribute("disabled",""):this.removeAttribute("disabled")}connectedCallback(){this.hasAttribute("disabled")||this.setAttribute("tabindex","0"),this.setAttribute("role","button")}attributeChangedCallback(t,n,e){"disabled"===t?(this.removeAttribute("tabindex"),this.setAttribute("aria-disabled","true")):(this.setAttribute("tabindex","0"),this.setAttribute("aria-disabled","false"))}});
\ No newline at end of file
+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"))}});
\ No newline at end of file
diff --git a/components/dist/checkbox.js b/components/dist/checkbox.js
index eef1608..b60fa82 100644
--- a/components/dist/checkbox.js
+++ b/components/dist/checkbox.js
@@ -62,21 +62,16 @@ smCheckbox.innerHTML = `
stroke: rgba(var(--background-color), 1);
}
:host([checked]) .icon {
- stroke-width: 8;
- stroke: var(--accent-color);
background: var(--accent-color);
- }
- :host(:not([checked])) .icon {
- box-shadow: 0 0 0 0.1rem var(--border-color) inset;
- }
-
+ box-shadow: 0 0 0 0.1rem var(--accent-color) inset;
+ }
.icon {
fill: none;
height: var(--height);
width: var(--width);
padding: 0.1rem;
- stroke: rgba(var(--text-color), 0.7);
- stroke-width: 6;
+ stroke-width: 8;
+ stroke: var(--border-color);
overflow: visible;
stroke-linecap: round;
stroke-linejoin: round;
@@ -84,6 +79,7 @@ smCheckbox.innerHTML = `
-o-transition: background 0.3s;
transition: background 0.3s;
border-radius: var(--border-radius);
+ box-shadow: 0 0 0 0.1rem var(--border-color) inset;
}
@@ -104,7 +100,7 @@ customElements.define('sm-checkbox', class extends HTMLElement {
this.reset = this.reset.bind(this)
this.dispatch = this.dispatch.bind(this)
- this.handleKeyup = this.handleKeyup.bind(this)
+ this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleClick = this.handleClick.bind(this)
}
@@ -155,8 +151,9 @@ customElements.define('sm-checkbox', class extends HTMLElement {
composed: true
}))
}
- handleKeyup(e){
+ handleKeyDown(e){
if (e.code === "Space") {
+ e.preventDefault()
this.click()
}
}
@@ -172,7 +169,7 @@ customElements.define('sm-checkbox', class extends HTMLElement {
if (!this.hasAttribute('checked')) {
this.setAttribute('aria-checked', 'false')
}
- this.addEventListener('keyup', this.handleKeyup)
+ this.addEventListener('keydown', this.handleKeyDown)
this.addEventListener('click', this.handleClick)
}
attributeChangedCallback(name, oldValue, newValue) {
@@ -192,7 +189,7 @@ customElements.define('sm-checkbox', class extends HTMLElement {
}
}
disconnectedCallback() {
- this.removeEventListener('keyup', this.handleKeyup)
+ this.removeEventListener('keydown', this.handleKeyDown)
this.removeEventListener('change', this.handleClick)
}
})
\ No newline at end of file
diff --git a/components/dist/checkbox.min.js b/components/dist/checkbox.min.js
index 8a053cf..b5e513e 100644
--- a/components/dist/checkbox.min.js
+++ b/components/dist/checkbox.min.js
@@ -1 +1 @@
-const smCheckbox=document.createElement("template");smCheckbox.innerHTML='\n\n\n \n checkbox \n \n \n \n ',customElements.define("sm-checkbox",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smCheckbox.content.cloneNode(!0)),this.checkbox=this.shadowRoot.querySelector(".checkbox"),this.reset=this.reset.bind(this),this.dispatch=this.dispatch.bind(this),this.handleKeyup=this.handleKeyup.bind(this),this.handleClick=this.handleClick.bind(this)}static get observedAttributes(){return["value","disabled","checked"]}get disabled(){return this.hasAttribute("disabled")}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.hasAttribute("checked")}set checked(e){e?this.setAttribute("checked",""):this.removeAttribute("checked")}set value(e){this.setAttribute("value",e)}get value(){return this.getAttribute("value")}reset(){this.removeAttribute("checked")}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0}))}handleKeyup(e){"Space"===e.code&&this.click()}handleClick(e){this.toggleAttribute("checked")}connectedCallback(){this.hasAttribute("disabled")||this.setAttribute("tabindex","0"),this.setAttribute("role","checkbox"),this.hasAttribute("checked")||this.setAttribute("aria-checked","false"),this.addEventListener("keyup",this.handleKeyup),this.addEventListener("click",this.handleClick)}attributeChangedCallback(e,t,n){t!==n&&("checked"===e?(this.setAttribute("aria-checked",this.hasAttribute("checked")),this.dispatch()):"disabled"===e&&(this.hasAttribute("disabled")?this.removeAttribute("tabindex"):this.setAttribute("tabindex","0")))}disconnectedCallback(){this.removeEventListener("keyup",this.handleKeyup),this.removeEventListener("change",this.handleClick)}});
\ No newline at end of file
+const smCheckbox=document.createElement("template");smCheckbox.innerHTML='\n\n\n \n checkbox \n \n \n \n ',customElements.define("sm-checkbox",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smCheckbox.content.cloneNode(!0)),this.checkbox=this.shadowRoot.querySelector(".checkbox"),this.reset=this.reset.bind(this),this.dispatch=this.dispatch.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleClick=this.handleClick.bind(this)}static get observedAttributes(){return["value","disabled","checked"]}get disabled(){return this.hasAttribute("disabled")}set disabled(e){e?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.hasAttribute("checked")}set checked(e){e?this.setAttribute("checked",""):this.removeAttribute("checked")}set value(e){this.setAttribute("value",e)}get value(){return this.getAttribute("value")}reset(){this.removeAttribute("checked")}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0}))}handleKeyDown(e){"Space"===e.code&&(e.preventDefault(),this.click())}handleClick(e){this.toggleAttribute("checked")}connectedCallback(){this.hasAttribute("disabled")||this.setAttribute("tabindex","0"),this.setAttribute("role","checkbox"),this.hasAttribute("checked")||this.setAttribute("aria-checked","false"),this.addEventListener("keydown",this.handleKeyDown),this.addEventListener("click",this.handleClick)}attributeChangedCallback(e,t,n){t!==n&&("checked"===e?(this.setAttribute("aria-checked",this.hasAttribute("checked")),this.dispatch()):"disabled"===e&&(this.hasAttribute("disabled")?this.removeAttribute("tabindex"):this.setAttribute("tabindex","0")))}disconnectedCallback(){this.removeEventListener("keydown",this.handleKeyDown),this.removeEventListener("change",this.handleClick)}});
\ No newline at end of file
diff --git a/components/dist/hamburger-menu.js b/components/dist/hamburger-menu.js
index 077337f..97ae949 100644
--- a/components/dist/hamburger-menu.js
+++ b/components/dist/hamburger-menu.js
@@ -13,6 +13,7 @@ hamburgerMenu.innerHTML = `
width: 100%;
height: 100%;
overflow-y: auto;
+ scrollbar-width: thin;
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
@@ -70,7 +71,6 @@ hamburgerMenu.innerHTML = `
::-webkit-scrollbar{
width: 0.5rem;
}
-
::-webkit-scrollbar-thumb{
border-radius: 1rem;
background: rgba(var(--text-color), 0.3);
diff --git a/components/dist/hamburger-menu.min.js b/components/dist/hamburger-menu.min.js
index dc783f2..6ab8766 100644
--- a/components/dist/hamburger-menu.min.js
+++ b/components/dist/hamburger-menu.min.js
@@ -1 +1 @@
-const hamburgerMenu=document.createElement("template");hamburgerMenu.innerHTML='\n\n\n\n \n \n';class HamburgerMenu extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(hamburgerMenu.content.cloneNode(!0)),this.resumeScrolling=this.resumeScrolling.bind(this),this.open=this.open.bind(this),this.close=this.close.bind(this),this.sideNav=this.shadowRoot.querySelector(".side-nav"),this.backdrop=this.shadowRoot.querySelector(".backdrop"),this.isOpen=!1,this.animeOptions={duration:300,easing:"ease"}}static get observedAttributes(){return["open"]}resumeScrolling(){const n=document.body.style.top;window.scrollTo(0,-1*parseInt(n||"0")),setTimeout(()=>{document.body.style.overflow="auto",document.body.style.top="initial"},300)}open(){this.isOpen||(document.body.style.overflow="hidden",document.body.style.top=`-${window.scrollY}px`,this.classList.remove("hide"),this.sideNav.classList.add("reveal"),this.backdrop.classList.remove("hide"),this.backdrop.animate([{opacity:0},{opacity:1}],this.animeOptions).onfinish=(()=>{this.isOpen=!0,this.setAttribute("open","")}))}close(){this.isOpen&&(this.sideNav.classList.remove("reveal"),this.backdrop.animate([{opacity:1},{opacity:0}],this.animeOptions).onfinish=(()=>{this.backdrop.classList.add("hide"),this.classList.add("hide"),this.isOpen=!1,this.removeAttribute("open")}))}connectedCallback(){this.backdrop.addEventListener("click",this.close);const n=new ResizeObserver(n=>{window.innerWidth<640&&this.isOpen?this.classList.remove("hide"):this.classList.add("hide"),window.innerWidth>640&&this.classList.remove("hide")});n.observe(this)}disconnectedCallback(){this.backdrop.removeEventListener("click",this.close)}attributeChangedCallback(n,e,t){"open"===n&&this.hasAttribute("open")&&this.open()}}window.customElements.define("hamburger-menu",HamburgerMenu);
\ No newline at end of file
+const hamburgerMenu=document.createElement("template");hamburgerMenu.innerHTML='\n\n\n\n \n \n';class HamburgerMenu extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(hamburgerMenu.content.cloneNode(!0)),this.resumeScrolling=this.resumeScrolling.bind(this),this.open=this.open.bind(this),this.close=this.close.bind(this),this.sideNav=this.shadowRoot.querySelector(".side-nav"),this.backdrop=this.shadowRoot.querySelector(".backdrop"),this.isOpen=!1,this.animeOptions={duration:300,easing:"ease"}}static get observedAttributes(){return["open"]}resumeScrolling(){const n=document.body.style.top;window.scrollTo(0,-1*parseInt(n||"0")),setTimeout(()=>{document.body.style.overflow="auto",document.body.style.top="initial"},300)}open(){this.isOpen||(document.body.style.overflow="hidden",document.body.style.top=`-${window.scrollY}px`,this.classList.remove("hide"),this.sideNav.classList.add("reveal"),this.backdrop.classList.remove("hide"),this.backdrop.animate([{opacity:0},{opacity:1}],this.animeOptions).onfinish=(()=>{this.isOpen=!0,this.setAttribute("open","")}))}close(){this.isOpen&&(this.sideNav.classList.remove("reveal"),this.backdrop.animate([{opacity:1},{opacity:0}],this.animeOptions).onfinish=(()=>{this.backdrop.classList.add("hide"),this.classList.add("hide"),this.isOpen=!1,this.removeAttribute("open")}))}connectedCallback(){this.backdrop.addEventListener("click",this.close);const n=new ResizeObserver(n=>{window.innerWidth<640&&this.isOpen?this.classList.remove("hide"):this.classList.add("hide"),window.innerWidth>640&&this.classList.remove("hide")});n.observe(this)}disconnectedCallback(){this.backdrop.removeEventListener("click",this.close)}attributeChangedCallback(n,e,t){"open"===n&&this.hasAttribute("open")&&this.open()}}window.customElements.define("hamburger-menu",HamburgerMenu);
\ No newline at end of file
diff --git a/components/dist/menu.js b/components/dist/menu.js
index 7b2725d..e9b8ee1 100644
--- a/components/dist/menu.js
+++ b/components/dist/menu.js
@@ -21,12 +21,7 @@ smMenu.innerHTML = `
fill: rgba(var(--text-color), 0.7);
height: 2.4rem;
width: 2.4rem;
- padding: 0.7rem;
- stroke: rgba(var(--text-color), 0.7);
- stroke-width: 6;
- overflow: visible;
- stroke-linecap: round;
- stroke-linejoin: round;
+ padding: 0.5rem;
border-radius: 2rem;
-webkit-transition: background 0.3s;
-o-transition: background 0.3s;
@@ -90,7 +85,7 @@ smMenu.innerHTML = `
transition: opacity 0.3s, transform 0.3s, -webkit-transform 0.3s;
border: solid 1px rgba(var(--text-color), 0.2);
border-radius: 0.3rem;
- z-index: 2;
+ z-index: 1;
-webkit-box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
top: 100%;
@@ -120,12 +115,7 @@ smMenu.innerHTML = `
@@ -137,7 +127,16 @@ customElements.define('sm-menu', class extends HTMLElement {
this.attachShadow({
mode: 'open'
}).append(smMenu.content.cloneNode(true))
+
+ this.open = false;
+ this.availableOptions
+ this.containerDimensions
+ this.optionList = this.shadowRoot.querySelector('.options')
+ this.menu = this.shadowRoot.querySelector('.menu')
+ this.icon = this.shadowRoot.querySelector('.icon')
+
this.expand = this.expand.bind(this)
+
}
static get observedAttributes() {
return ['value']
@@ -171,26 +170,20 @@ customElements.define('sm-menu', class extends HTMLElement {
}
}
connectedCallback() {
- this.availableOptions
- this.containerDimensions
- this.optionList = this.shadowRoot.querySelector('.options')
- let slot = this.shadowRoot.querySelector('.options slot'),
- menu = this.shadowRoot.querySelector('.menu')
- this.icon = this.shadowRoot.querySelector('.icon')
- this.open = false;
-
+ this.setAttribute('role', 'listbox')
+ const slot = this.shadowRoot.querySelector('.options slot')
slot.addEventListener('slotchange', e => {
this.availableOptions = slot.assignedElements()
this.containerDimensions = this.optionList.getBoundingClientRect()
});
- menu.addEventListener('click', e => {
+ this.menu.addEventListener('click', e => {
if (!this.open) {
this.expand()
} else {
this.collapse()
}
})
- menu.addEventListener('keydown', e => {
+ this.menu.addEventListener('keydown', e => {
if (e.code === 'ArrowDown' || e.code === 'ArrowRight') {
e.preventDefault()
this.availableOptions[0].focus()
@@ -234,8 +227,8 @@ customElements.define('sm-menu', class extends HTMLElement {
})
// option
-const smMenuOption = document.createElement('template')
-smMenuOption.innerHTML = `
+const menuOption = document.createElement('template')
+menuOption.innerHTML = `
\n
',customElements.define("sm-menu",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenu.content.cloneNode(!0)),this.expand=this.expand.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.open||(this.optionList.classList.remove("hide"),this.optionList.classList.add("no-transformations"),this.open=!0,this.icon.classList.add("focused"),this.availableOptions.forEach(n=>{n.setAttribute("tabindex","0")}))}collapse(){this.open&&(this.open=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide"),this.optionList.classList.remove("no-transformations"),this.availableOptions.forEach(n=>{n.removeAttribute("tabindex")}))}connectedCallback(){this.availableOptions,this.containerDimensions,this.optionList=this.shadowRoot.querySelector(".options");let n=this.shadowRoot.querySelector(".options slot"),t=this.shadowRoot.querySelector(".menu");this.icon=this.shadowRoot.querySelector(".icon"),this.open=!1,n.addEventListener("slotchange",t=>{this.availableOptions=n.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),t.addEventListener("click",n=>{this.open?this.collapse():this.expand()}),t.addEventListener("keydown",n=>{"ArrowDown"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),this.availableOptions[0].focus()),"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.open?this.collapse():this.expand())}),this.optionList.addEventListener("keydown",n=>{"ArrowUp"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()),"ArrowDown"!==n.code&&"ArrowLeft"!==n.code||(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}),this.optionList.addEventListener("click",n=>{this.collapse()}),window.addEventListener("mousedown",n=>{this.contains(n.target)||2===n.button||this.collapse()})}});const smMenuOption=document.createElement("template");smMenuOption.innerHTML='\n\n
\n \n
',customElements.define("sm-menu-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenuOption.content.cloneNode(!0))}connectedCallback(){this.addEventListener("keyup",n=>{"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.click())})}});
\ No newline at end of file
+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.open=!1,this.availableOptions,this.containerDimensions,this.optionList=this.shadowRoot.querySelector(".options"),this.menu=this.shadowRoot.querySelector(".menu"),this.icon=this.shadowRoot.querySelector(".icon"),this.expand=this.expand.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.open||(this.optionList.classList.remove("hide"),this.optionList.classList.add("no-transformations"),this.open=!0,this.icon.classList.add("focused"),this.availableOptions.forEach(n=>{n.setAttribute("tabindex","0")}))}collapse(){this.open&&(this.open=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide"),this.optionList.classList.remove("no-transformations"),this.availableOptions.forEach(n=>{n.removeAttribute("tabindex")}))}connectedCallback(){this.setAttribute("role","listbox");const n=this.shadowRoot.querySelector(".options slot");n.addEventListener("slotchange",t=>{this.availableOptions=n.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),this.menu.addEventListener("click",n=>{this.open?this.collapse():this.expand()}),this.menu.addEventListener("keydown",n=>{"ArrowDown"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),this.availableOptions[0].focus()),"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.open?this.collapse():this.expand())}),this.optionList.addEventListener("keydown",n=>{"ArrowUp"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()),"ArrowDown"!==n.code&&"ArrowLeft"!==n.code||(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}),this.optionList.addEventListener("click",n=>{this.collapse()}),window.addEventListener("mousedown",n=>{this.contains(n.target)||2===n.button||this.collapse()})}});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())})}});
\ No newline at end of file
diff --git a/components/dist/notifications.js b/components/dist/notifications.js
index e1de534..6d34332 100644
--- a/components/dist/notifications.js
+++ b/components/dist/notifications.js
@@ -57,6 +57,7 @@ smNotifications.innerHTML = `
hyphens: auto;
max-width: 100%;
padding: 1rem;
+ align-items: center;
}
.icon-container:not(:empty){
margin-right: 0.5rem;
@@ -86,7 +87,6 @@ smNotifications.innerHTML = `
-webkit-hyphens: auto;
hyphens: auto;
max-width: 100%;
- align-self: center;
}
.notification:last-of-type{
margin-bottom: 0;
@@ -161,9 +161,18 @@ customElements.define('sm-notifications', class extends HTMLElement {
}
+ randString(length) {
+ let result = '';
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ for (let i = 0; i < length; i++)
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
+ return result;
+ }
+
createNotification(message, options) {
const { pinned = false, icon = '' } = options
const notification = document.createElement('div')
+ notification.id = this.randString(8)
notification.classList.add('notification')
let composition = ``
composition += `
@@ -195,6 +204,7 @@ customElements.define('sm-notifications', class extends HTMLElement {
opacity: '1'
},
], this.animationOptions)
+ return notification.id
}
removeNotification(notification) {
diff --git a/components/dist/notifications.min.js b/components/dist/notifications.min.js
index cb9ddb4..0971a8c 100644
--- a/components/dist/notifications.min.js
+++ b/components/dist/notifications.min.js
@@ -1 +1 @@
-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)}createNotification(n,t){const{pinned:i=!1,icon:o=""}=t,e=document.createElement("div");e.classList.add("notification");let a="";return a+=`\n
${o}
\n
${n}
\n `,i&&(e.classList.add("pinned"),a+='\n
\n \n \n '),e.innerHTML=a,e}push(n,t={}){const i=this.createNotification(n,t);this.notificationPanel.append(i),i.animate([{transform:"translateY(1rem)",opacity:"0"},{transform:"none",opacity:"1"}],this.animationOptions)}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})}});
\ No newline at end of file
+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 \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})}});
\ No newline at end of file
diff --git a/components/dist/popup.js b/components/dist/popup.js
index b29e06a..59dcb8e 100644
--- a/components/dist/popup.js
+++ b/components/dist/popup.js
@@ -174,6 +174,19 @@ customElements.define('sm-popup', class extends HTMLElement {
this.allowClosing = false
this.isOpen = false
+ this.pinned = false
+ 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)
@@ -184,20 +197,24 @@ customElements.define('sm-popup', class extends HTMLElement {
this.movePopup = this.movePopup.bind(this)
}
+ static get observedAttributes() {
+ return ['open'];
+ }
+
get open() {
return this.isOpen
}
- resumeScrolling(){
+ resumeScrolling() {
const scrollY = document.body.style.top;
window.scrollTo(0, parseInt(scrollY || '0') * -1);
setTimeout(() => {
document.body.style.overflow = 'auto';
- document.body.style.top= 'initial'
+ document.body.style.top = 'initial'
}, 300);
}
- show(pinned, popupStack){
+ show(pinned, popupStack) {
if (popupStack)
this.popupStack = popupStack
if (this.popupStack && !this.hasAttribute('open')) {
@@ -224,10 +241,10 @@ customElements.define('sm-popup', class extends HTMLElement {
this.popupContainer.classList.remove('hide')
this.popup.style.transform = 'none';
document.body.style.overflow = 'hidden';
- document.body.style.top= `-${window.scrollY}px`
+ document.body.style.top = `-${window.scrollY}px`
return this.popupStack
}
- hide(){
+ hide() {
if (window.innerWidth < 640)
this.popup.style.transform = 'translateY(100%)';
else
@@ -245,17 +262,12 @@ customElements.define('sm-popup', class extends HTMLElement {
this.resumeScrolling()
}
- if (this.inputFields.length) {
+ if (this.forms.length) {
setTimeout(() => {
- this.inputFields.forEach(field => {
- if (field.type === 'radio' || field.tagName === 'SM-CHECKBOX')
- field.checked = false
- if (field.tagName === 'SM-INPUT' || field.tagName === 'TEXTAREA'|| field.tagName === 'SM-TEXTAREA')
- field.value = ''
- })
+ this.forms.forEach(form => form.reset())
}, 300);
}
- setTimeout(() => {
+ setTimeout(() => {
this.dispatchEvent(
new CustomEvent("popupclosed", {
bubbles: true,
@@ -269,13 +281,13 @@ customElements.define('sm-popup', class extends HTMLElement {
}, 300);
}
- handleTouchStart(e){
+ handleTouchStart(e) {
this.touchStartY = e.changedTouches[0].clientY
this.popup.style.transition = 'transform 0.1s'
this.touchStartTime = e.timeStamp
}
- handleTouchMove(e){
+ handleTouchMove(e) {
if (this.touchStartY < e.changedTouches[0].clientY) {
this.offset = e.changedTouches[0].clientY - this.touchStartY;
this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup())
@@ -286,7 +298,7 @@ customElements.define('sm-popup', class extends HTMLElement {
}*/
}
- handleTouchEnd(e){
+ handleTouchEnd(e) {
this.touchEndTime = e.timeStamp
cancelAnimationFrame(this.touchEndAnimataion)
this.touchEndY = e.changedTouches[0].clientY
@@ -308,56 +320,58 @@ customElements.define('sm-popup', class extends HTMLElement {
this.show()
return
}
- else
- this.hide()
+ else
+ this.hide()
}
}
- movePopup(){
+ movePopup() {
this.popup.style.transform = `translateY(${this.offset}px)`
}
connectedCallback() {
- this.pinned = false
- this.popupStack
- this.popupContainer = this.shadowRoot.querySelector('.popup-container')
- this.popup = this.shadowRoot.querySelector('.popup')
- this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot')
- this.offset
- this.popupHeader = this.shadowRoot.querySelector('.popup-top')
- this.touchStartY = 0
- this.touchEndY = 0
- this.touchStartTime = 0
- this.touchEndTime = 0
- this.touchEndAnimataion;
- this.threshold = this.popup.getBoundingClientRect().height * 0.3
- if (this.hasAttribute('open'))
- this.show()
+ this.popupBodySlot.addEventListener('slotchange', () => {
+ this.forms = this.querySelectorAll('sm-form')
+ })
this.popupContainer.addEventListener('mousedown', e => {
if (e.target === this.popupContainer && !this.pinned) {
if (this.pinned) {
this.show()
- return
} else
this.hide()
}
})
- this.popupBodySlot.addEventListener('slotchange', () => {
- setTimeout(() => {
- this.threshold = this.popup.getBoundingClientRect().height * 0.3
- }, 200);
- this.inputFields = this.querySelectorAll('sm-input', 'sm-checkbox', 'textarea', 'sm-textarea', 'radio')
- })
-
- this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, {passive: true})
- this.popupHeader.addEventListener('touchmove', (e) => {this.handleTouchMove(e)}, {passive: true})
- this.popupHeader.addEventListener('touchend', (e) => {this.handleTouchEnd(e)}, {passive: true})
+ const resizeObserver = new ResizeObserver(entries => {
+ for (let entry of entries) {
+ if (entry.contentBoxSize) {
+ // Firefox implements `contentBoxSize` as a single content rect, rather than an array
+ const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize;
+ this.threshold = entry.blockSize.height * 0.3
+ } else {
+ this.threshold = entry.contentRect.height * 0.3
+ }
+ }
+ });
+ resizeObserver.observe(this)
+
+
+ this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, { passive: true })
+ this.popupHeader.addEventListener('touchmove', (e) => { this.handleTouchMove(e) }, { passive: true })
+ this.popupHeader.addEventListener('touchend', (e) => { this.handleTouchEnd(e) }, { passive: true })
}
disconnectedCallback() {
- this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, {passive: true})
- this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, {passive: true})
- this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, {passive: true})
+ this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, { passive: true })
+ this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, { passive: true })
+ this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, { passive: true })
+ resizeObserver.unobserve()
+ }
+ attributeChangedCallback(name, oldVal, newVal) {
+ if (name === 'open') {
+ if (this.hasAttribute('open')) {
+ this.show()
+ }
+ }
}
})
diff --git a/components/dist/popup.min.js b/components/dist/popup.min.js
index 54587e8..ff271b0 100644
--- a/components/dist/popup.min.js
+++ b/components/dist/popup.min.js
@@ -1 +1 @@
-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.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)}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,e){return e&&(this.popupStack=e),this.popupStack&&!this.hasAttribute("open")&&(this.popupStack.push({popup:this,permission:t}),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=t,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.inputFields.length&&setTimeout(()=>{this.inputFields.forEach(t=>{"radio"!==t.type&&"SM-CHECKBOX"!==t.tagName||(t.checked=!1),"SM-INPUT"!==t.tagName&&"TEXTAREA"!==t.tagName&&"SM-TEXTAREA"!==t.tagName||(t.value="")})},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.touchStartY
this.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.pinned=!1,this.popupStack,this.popupContainer=this.shadowRoot.querySelector(".popup-container"),this.popup=this.shadowRoot.querySelector(".popup"),this.popupBodySlot=this.shadowRoot.querySelector(".popup-body slot"),this.offset,this.popupHeader=this.shadowRoot.querySelector(".popup-top"),this.touchStartY=0,this.touchEndY=0,this.touchStartTime=0,this.touchEndTime=0,this.touchEndAnimataion,this.threshold=.3*this.popup.getBoundingClientRect().height,this.hasAttribute("open")&&this.show(),this.popupContainer.addEventListener("mousedown",t=>{if(t.target===this.popupContainer&&!this.pinned){if(this.pinned)return void this.show();this.hide()}}),this.popupBodySlot.addEventListener("slotchange",()=>{setTimeout(()=>{this.threshold=.3*this.popup.getBoundingClientRect().height},200),this.inputFields=this.querySelectorAll("sm-input","sm-checkbox","textarea","sm-textarea","radio")}),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})}});
\ No newline at end of file
+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,e){return e&&(this.popupStack=e),this.popupStack&&!this.hasAttribute("open")&&(this.popupStack.push({popup:this,permission:t}),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=t,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()}});
\ No newline at end of file
diff --git a/components/dist/radio.js b/components/dist/radio.js
index 65a29c8..4588e18 100644
--- a/components/dist/radio.js
+++ b/components/dist/radio.js
@@ -72,17 +72,12 @@ window.customElements.define('sm-radio', class extends HTMLElement {
this.reset = this.reset.bind(this)
this.dispatchChangeEvent = this.dispatchChangeEvent.bind(this)
this.dispatchGroupEvent = this.dispatchGroupEvent.bind(this)
- this.handleKeyup = this.handleKeyup.bind(this)
+ this.handleKeyDown = this.handleKeyDown.bind(this)
this.handleClick = this.handleClick.bind(this)
this.handleRadioGroup = this.handleRadioGroup.bind(this)
- this.options = {
- bubbles: true,
- composed: true,
- detail: {
- value: this.value,
- }
- }
+ this.uniqueId
+ this.options
}
static get observedAttributes() {
return ['value', 'disabled', 'checked']
@@ -133,8 +128,9 @@ window.customElements.define('sm-radio', class extends HTMLElement {
this.dispatchEvent(new CustomEvent(`changed${this.getAttribute('name')}`, this.options))
}
}
- handleKeyup(e){
+ handleKeyDown(e){
if (e.code === "Space") {
+ e.preventDefault()
this.handleClick()
}
}
@@ -146,12 +142,28 @@ window.customElements.define('sm-radio', class extends HTMLElement {
}
handleRadioGroup(e) {
- if (e.detail.value !== this.getAttribute('value')) {
+ if (e.detail.uid !== this.uniqueId) {
this.reset()
}
}
+ randString(length) {
+ let result = '';
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ for (let i = 0; i < length; i++)
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
+ return result;
+ }
connectedCallback() {
+ this.uniqueId = this.randString(8)
+ this.options = {
+ bubbles: true,
+ composed: true,
+ detail: {
+ uid: this.uniqueId,
+ value: this.value,
+ }
+ }
if (!this.hasAttribute('disabled')) {
this.setAttribute('tabindex', '0')
}
@@ -159,7 +171,7 @@ window.customElements.define('sm-radio', class extends HTMLElement {
if (!this.hasAttribute('checked')) {
this.setAttribute('aria-checked', 'false')
}
- this.addEventListener('keyup', this.handleKeyup)
+ this.addEventListener('keydown', this.handleKeyDown)
this.addEventListener('click', this.handleClick)
if (this.hasAttribute('name') && this.getAttribute('name').trim() !== '') {
document.addEventListener(`changed${this.getAttribute('name')}`, this.handleRadioGroup)
@@ -182,7 +194,7 @@ window.customElements.define('sm-radio', class extends HTMLElement {
}
}
disconnectedCallback() {
- this.removeEventListener('keyup', this.handleKeyup)
+ this.removeEventListener('keydown', this.handleKeyDown)
this.removeEventListener('change', this.handleClick)
}
});
\ No newline at end of file
diff --git a/components/dist/radio.min.js b/components/dist/radio.min.js
index f9609a1..88d676a 100644
--- a/components/dist/radio.min.js
+++ b/components/dist/radio.min.js
@@ -1 +1 @@
-const smRadio=document.createElement("template");smRadio.innerHTML='\n\n\n \n \n \n
\n',window.customElements.define("sm-radio",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smRadio.content.cloneNode(!0)),this.radio=this.shadowRoot.querySelector(".radio"),this.reset=this.reset.bind(this),this.dispatchChangeEvent=this.dispatchChangeEvent.bind(this),this.dispatchGroupEvent=this.dispatchGroupEvent.bind(this),this.handleKeyup=this.handleKeyup.bind(this),this.handleClick=this.handleClick.bind(this),this.handleRadioGroup=this.handleRadioGroup.bind(this),this.options={bubbles:!0,composed:!0,detail:{value:this.value}}}static get observedAttributes(){return["value","disabled","checked"]}get disabled(){return this.hasAttribute("disabled")}set disabled(t){t?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.hasAttribute("checked")}set checked(t){t?this.setAttribute("checked",""):this.removeAttribute("checked")}set value(t){this.setAttribute("value",t)}get value(){return this.getAttribute("value")}reset(){this.removeAttribute("checked")}dispatchChangeEvent(){this.dispatchEvent(new CustomEvent("change",this.options))}dispatchGroupEvent(){this.hasAttribute("name")&&""!==this.getAttribute("name").trim()&&this.dispatchEvent(new CustomEvent(`changed${this.getAttribute("name")}`,this.options))}handleKeyup(t){"Space"===t.code&&this.handleClick()}handleClick(){this.hasAttribute("checked")||(this.setAttribute("checked",""),this.dispatchGroupEvent())}handleRadioGroup(t){t.detail.value!==this.getAttribute("value")&&this.reset()}connectedCallback(){this.hasAttribute("disabled")||this.setAttribute("tabindex","0"),this.setAttribute("role","radio"),this.hasAttribute("checked")||this.setAttribute("aria-checked","false"),this.addEventListener("keyup",this.handleKeyup),this.addEventListener("click",this.handleClick),this.hasAttribute("name")&&""!==this.getAttribute("name").trim()&&document.addEventListener(`changed${this.getAttribute("name")}`,this.handleRadioGroup)}attributeChangedCallback(t,e,i){e!==i&&("checked"===t?this.dispatchChangeEvent():"disabled"===t&&(this.hasAttribute("disabled")?this.removeAttribute("tabindex"):this.setAttribute("tabindex","0")))}disconnectedCallback(){this.removeEventListener("keyup",this.handleKeyup),this.removeEventListener("change",this.handleClick)}});
\ No newline at end of file
+const smRadio=document.createElement("template");smRadio.innerHTML='\n\n\n \n \n \n
\n',window.customElements.define("sm-radio",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smRadio.content.cloneNode(!0)),this.radio=this.shadowRoot.querySelector(".radio"),this.reset=this.reset.bind(this),this.dispatchChangeEvent=this.dispatchChangeEvent.bind(this),this.dispatchGroupEvent=this.dispatchGroupEvent.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleClick=this.handleClick.bind(this),this.handleRadioGroup=this.handleRadioGroup.bind(this),this.uniqueId,this.options}static get observedAttributes(){return["value","disabled","checked"]}get disabled(){return this.hasAttribute("disabled")}set disabled(t){t?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.hasAttribute("checked")}set checked(t){t?this.setAttribute("checked",""):this.removeAttribute("checked")}set value(t){this.setAttribute("value",t)}get value(){return this.getAttribute("value")}reset(){this.removeAttribute("checked")}dispatchChangeEvent(){this.dispatchEvent(new CustomEvent("change",this.options))}dispatchGroupEvent(){this.hasAttribute("name")&&""!==this.getAttribute("name").trim()&&this.dispatchEvent(new CustomEvent(`changed${this.getAttribute("name")}`,this.options))}handleKeyDown(t){"Space"===t.code&&(t.preventDefault(),this.handleClick())}handleClick(){this.hasAttribute("checked")||(this.setAttribute("checked",""),this.dispatchGroupEvent())}handleRadioGroup(t){t.detail.uid!==this.uniqueId&&this.reset()}randString(t){let e="";const i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n {
- if (this.previousOption !== e.target) {
- this.setAttribute('value', e.detail.value)
- this.shadowRoot.querySelector('.option-text').textContent = e.detail.text;
- this.dispatchEvent(new CustomEvent('change', {
- bubbles: true,
- composed: true,
- detail: {
- value: e.detail.value
- }
- }))
- if (this.previousOption) {
- this.previousOption.classList.remove('check-selected')
- }
- this.previousOption = e.target;
- }
- if (!e.detail.switching)
- this.collapse()
-
- e.target.classList.add('check-selected')
- })
+ this.addEventListener('optionSelected', this.handleOptionSelected)
document.addEventListener('mousedown', e => {
if (this.isOpen && !this.contains(e.target)) {
this.collapse()
@@ -390,7 +392,7 @@ customElements.define('sm-option', class extends HTMLElement {
detail: {
text: this.textContent,
value: this.getAttribute('value'),
- switching: switching
+ switching
}
})
this.dispatchEvent(optionSelected)
@@ -404,8 +406,8 @@ customElements.define('sm-option', class extends HTMLElement {
'ArrowLeft',
'ArrowRight'
]
- this.addEventListener('click', this.sendDetails)
- this.addEventListener('keyup', e => {
+ this.addEventListener('click', this.sendDetails(false))
+ this.addEventListener('keydown', e => {
if (e.code === 'Enter' || e.code === 'Space') {
e.preventDefault()
this.sendDetails(false)
diff --git a/components/dist/select.min.js b/components/dist/select.min.js
index 49995b6..24d6784 100644
--- a/components/dist/select.min.js
+++ b/components/dist/select.min.js
@@ -1 +1 @@
-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.handleSelectKeyDown=this.handleSelectKeyDown.bind(this),this.handleOptionsKeyDown=this.handleOptionsKeyDown.bind(this),this.handleOptionsKeyDown=this.handleOptionsKeyDown.bind(this),this.availableOptions,this.optionList=this.shadowRoot.querySelector(".options"),this.chevron=this.shadowRoot.querySelector(".toggle"),this.selection=this.shadowRoot.querySelector(".selection"),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"}}static get observedAttributes(){return["value","disabled"]}get value(){return this.getAttribute("value")}set value(t){this.setAttribute("value",t)}reset(){}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()}handleSelectKeyDown(t){"ArrowDown"===t.code||"ArrowRight"===t.code?(t.preventDefault(),this.availableOptions[0].focus()):"Enter"!==t.code&&"Space"!==t.code||(this.isOpen?this.collapse():(this.optionList.classList.remove("hide"),this.optionList.animate(this.slideDown,this.animationOptions),this.chevron.classList.add("rotate"),this.isOpen=!0))}handleOptionsKeyDown(t){"ArrowUp"===t.code||"ArrowRight"===t.code?(t.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"!==t.code&&"ArrowLeft"!==t.code||(t.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}connectedCallback(){this.setAttribute("role","listbox"),this.hasAttribute("disabled")||this.selection.setAttribute("tabindex","0");let t=this.shadowRoot.querySelector("slot");t.addEventListener("slotchange",e=>{if(this.availableOptions=t.assignedElements(),this.availableOptions[0]){let t=this.availableOptions[0];this.previousOption=t,t.classList.add("check-selected"),this.setAttribute("value",t.getAttribute("value")),this.shadowRoot.querySelector(".option-text").textContent=t.textContent,this.availableOptions.forEach((t,e)=>{t.setAttribute("tabindex","0")})}}),this.selection.addEventListener("click",this.toggle),this.selection.addEventListener("keydown",this.handleSelectKeyDown),this.optionList.addEventListener("keydown",this.handleOptionsKeyDown),this.addEventListener("optionSelected",t=>{this.previousOption!==t.target&&(this.setAttribute("value",t.detail.value),this.shadowRoot.querySelector(".option-text").textContent=t.detail.text,this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:t.detail.value}})),this.previousOption&&this.previousOption.classList.remove("check-selected"),this.previousOption=t.target),t.detail.switching||this.collapse(),t.target.classList.add("check-selected")}),document.addEventListener("mousedown",t=>{this.isOpen&&!this.contains(t.target)&&this.collapse()})}attributeChangedCallback(t,e,n){"disabled"===t&&(this.hasAttribute("disabled")?this.selection.removeAttribute("tabindex"):this.selection.setAttribute("tabindex","0"))}disconnectedCallback(){this.selection.removeEventListener("click",this.toggle),this.selection.removeEventListener("keydown",this.handleSelectKeyDown),this.optionList.removeEventListener("keydown",this.handleOptionsKeyDown)}});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)),this.sendDetails=this.sendDetails.bind(this)}sendDetails(t){let e=new CustomEvent("optionSelected",{bubbles:!0,composed:!0,detail:{text:this.textContent,value:this.getAttribute("value"),switching:t}});this.dispatchEvent(e)}connectedCallback(){this.setAttribute("role","option");let t=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"];this.addEventListener("click",this.sendDetails),this.addEventListener("keyup",e=>{"Enter"!==e.code&&"Space"!==e.code||(e.preventDefault(),this.sendDetails(!1)),t.includes(e.code)&&(e.preventDefault(),this.sendDetails(!0))}),this.hasAttribute("default")&&setTimeout(()=>{this.sendDetails()},0)}});
\ No newline at end of file
+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.handleSelectKeyDown=this.handleSelectKeyDown.bind(this),this.handleOptionsKeyDown=this.handleOptionsKeyDown.bind(this),this.handleOptionsKeyDown=this.handleOptionsKeyDown.bind(this),this.handleOptionSelected=this.handleOptionSelected.bind(this),this.availableOptions,this.optionList=this.shadowRoot.querySelector(".options"),this.chevron=this.shadowRoot.querySelector(".toggle"),this.selection=this.shadowRoot.querySelector(".selection"),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"}}static get observedAttributes(){return["value","disabled"]}get value(){return this.getAttribute("value")}set value(e){this.setAttribute("value",e)}reset(){}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()}handleSelectKeyDown(e){"ArrowDown"===e.code||"ArrowRight"===e.code?(e.preventDefault(),this.availableOptions[0].focus()):"Enter"!==e.code&&"Space"!==e.code||(this.isOpen?this.collapse():(this.optionList.classList.remove("hide"),this.optionList.animate(this.slideDown,this.animationOptions),this.chevron.classList.add("rotate"),this.isOpen=!0))}handleOptionsKeyDown(e){"ArrowUp"===e.code||"ArrowRight"===e.code?(e.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()):"ArrowDown"!==e.code&&"ArrowLeft"!==e.code||(e.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}handleOptionSelected(e){this.previousOption!==e.target&&(this.setAttribute("value",e.detail.value),this.shadowRoot.querySelector(".option-text").textContent=e.detail.text,this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:e.detail.value}})),this.previousOption&&this.previousOption.classList.remove("check-selected"),this.previousOption=e.target),e.detail.switching||this.collapse(),e.target.classList.add("check-selected")}connectedCallback(){this.setAttribute("role","listbox"),this.hasAttribute("disabled")||this.selection.setAttribute("tabindex","0");let e=this.shadowRoot.querySelector("slot");e.addEventListener("slotchange",t=>{if(this.availableOptions=e.assignedElements(),this.availableOptions[0]){let e=this.availableOptions[0];this.previousOption=e,e.classList.add("check-selected"),this.setAttribute("value",e.getAttribute("value")),this.shadowRoot.querySelector(".option-text").textContent=e.textContent,this.availableOptions.forEach((e,t)=>{e.setAttribute("tabindex","0")})}}),this.selection.addEventListener("click",this.toggle),this.selection.addEventListener("keydown",this.handleSelectKeyDown),this.optionList.addEventListener("keydown",this.handleOptionsKeyDown),this.addEventListener("optionSelected",this.handleOptionSelected),document.addEventListener("mousedown",e=>{this.isOpen&&!this.contains(e.target)&&this.collapse()})}attributeChangedCallback(e,t,n){"disabled"===e&&(this.hasAttribute("disabled")?this.selection.removeAttribute("tabindex"):this.selection.setAttribute("tabindex","0"))}disconnectedCallback(){this.selection.removeEventListener("click",this.toggle),this.selection.removeEventListener("keydown",this.handleSelectKeyDown),this.optionList.removeEventListener("keydown",this.handleOptionsKeyDown)}});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)),this.sendDetails=this.sendDetails.bind(this)}sendDetails(e){let t=new CustomEvent("optionSelected",{bubbles:!0,composed:!0,detail:{text:this.textContent,value:this.getAttribute("value"),switching:e}});this.dispatchEvent(t)}connectedCallback(){this.setAttribute("role","option");let e=["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"];this.addEventListener("click",this.sendDetails(!1)),this.addEventListener("keydown",t=>{"Enter"!==t.code&&"Space"!==t.code||(t.preventDefault(),this.sendDetails(!1)),e.includes(t.code)&&(t.preventDefault(),this.sendDetails(!0))}),this.hasAttribute("default")&&setTimeout(()=>{this.sendDetails()},0)}});
\ No newline at end of file
diff --git a/components/dist/switch.js b/components/dist/switch.js
index 00a4736..b09b788 100644
--- a/components/dist/switch.js
+++ b/components/dist/switch.js
@@ -192,8 +192,9 @@ customElements.define('sm-switch', class extends HTMLElement {
}
connectedCallback() {
- this.addEventListener('keyup', e => {
- if ((e.code === "Enter" || e.code === "Space") && !this.isDisabled) {
+ this.addEventListener('keydown', e => {
+ if (e.code === "Space" && !this.isDisabled) {
+ e.preventDefault()
this.input.click()
}
})
diff --git a/components/dist/switch.min.js b/components/dist/switch.min.js
index bf86326..166df6a 100644
--- a/components/dist/switch.min.js
+++ b/components/dist/switch.min.js
@@ -1 +1 @@
-const smSwitch=document.createElement("template");smSwitch.innerHTML='\t\n\n\n \n \n \n ',customElements.define("sm-switch",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smSwitch.content.cloneNode(!0)),this.switch=this.shadowRoot.querySelector(".switch"),this.input=this.shadowRoot.querySelector("input"),this.isChecked=!1,this.isDisabled=!1,this.dispatch=this.dispatch.bind(this)}static get observedAttributes(){return["disabled","checked"]}get disabled(){return this.isDisabled}set disabled(n){n?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.isChecked}set checked(n){n?this.setAttribute("checked",""):this.removeAttribute("checked")}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this.isChecked}}))}connectedCallback(){this.addEventListener("keyup",n=>{"Enter"!==n.code&&"Space"!==n.code||this.isDisabled||this.input.click()}),this.input.addEventListener("click",n=>{this.input.checked?this.checked=!0:this.checked=!1,this.dispatch()})}attributeChangedCallback(n,t,e){t!==e&&("disabled"===n?this.hasAttribute("disabled")?this.disabled=!0:this.disabled=!1:"checked"===n&&(this.hasAttribute("checked")?(this.isChecked=!0,this.input.checked=!0):(this.isChecked=!1,this.input.checked=!1)))}});
\ No newline at end of file
+const smSwitch=document.createElement("template");smSwitch.innerHTML='\t\n\n\n \n \n \n ',customElements.define("sm-switch",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smSwitch.content.cloneNode(!0)),this.switch=this.shadowRoot.querySelector(".switch"),this.input=this.shadowRoot.querySelector("input"),this.isChecked=!1,this.isDisabled=!1,this.dispatch=this.dispatch.bind(this)}static get observedAttributes(){return["disabled","checked"]}get disabled(){return this.isDisabled}set disabled(n){n?this.setAttribute("disabled",""):this.removeAttribute("disabled")}get checked(){return this.isChecked}set checked(n){n?this.setAttribute("checked",""):this.removeAttribute("checked")}dispatch(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this.isChecked}}))}connectedCallback(){this.addEventListener("keydown",n=>{"Space"!==n.code||this.isDisabled||(n.preventDefault(),this.input.click())}),this.input.addEventListener("click",n=>{this.input.checked?this.checked=!0:this.checked=!1,this.dispatch()})}attributeChangedCallback(n,t,e){t!==e&&("disabled"===n?this.hasAttribute("disabled")?this.disabled=!0:this.disabled=!1:"checked"===n&&(this.hasAttribute("checked")?(this.isChecked=!0,this.input.checked=!0):(this.isChecked=!1,this.input.checked=!1)))}});
\ No newline at end of file
diff --git a/components/dist/theme-toggle.js b/components/dist/theme-toggle.js
index c0fe31c..64d03f0 100644
--- a/components/dist/theme-toggle.js
+++ b/components/dist/theme-toggle.js
@@ -7,6 +7,9 @@ themeToggle.innerHTML = `
box-sizing: border-box;
}
:host{
+ cursor: pointer;
+ --height: 2.5rem;
+ --width: 2.5rem;
}
.theme-toggle {
display: flex;
@@ -19,8 +22,8 @@ themeToggle.innerHTML = `
.theme-toggle::after{
content: '';
position: absolute;
- width: 2.5rem;
- height: 2.5rem;
+ height: var(--height);
+ width: var(--width);
top: 50%;
left: 50%;
opacity: 0;
@@ -56,18 +59,21 @@ themeToggle.innerHTML = `
}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
+
`
diff --git a/components/dist/theme-toggle.min.js b/components/dist/theme-toggle.min.js
index 792a7ce..b91a9af 100644
--- a/components/dist/theme-toggle.min.js
+++ b/components/dist/theme-toggle.min.js
@@ -1 +1 @@
-const themeToggle=document.createElement("template");themeToggle.innerHTML='\n \n \n \n \n \n \n \n \n \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"}nightlight(){this.hasTheme="dark",document.body.dataset.theme="dark"}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);
\ No newline at end of file
+const themeToggle=document.createElement("template");themeToggle.innerHTML='\n \n \n \n \n \n \n \n \n \n \n \n \n \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"}nightlight(){this.hasTheme="dark",document.body.dataset.theme="dark"}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);
\ No newline at end of file
diff --git a/components/index.html b/components/index.html
index 0bffbf4..57a11dd 100644
--- a/components/index.html
+++ b/components/index.html
@@ -53,7 +53,7 @@
-
+
Total components
@@ -71,9 +71,6 @@
use at RanchiMall, especially since we are a framework-less development environment so this was
a logical choice.
-
- Just download the components you like, link them with a script tag and drop it in HTML done!
-
Features
Native and Cross framework support
@@ -102,10 +99,10 @@
Link the downloaded js before </body>
-
- <script src=".../components.js"></script>
-
-
+
+<script src=".../components.js"></script>
+
+
@@ -192,22 +189,22 @@
How to define variant
-
- <sm-button variant="primary">primary</sm-button>
- <sm-button variant="outlined">outlined</sm-button>
- <sm-button variant="no-outline">no-outline</sm-button>
-
-
+
+<sm-button variant="primary">primary</sm-button>
+<sm-button variant="outlined">outlined</sm-button>
+<sm-button variant="no-outline">no-outline</sm-button>
+
+
States
Disabled
To disable the button add disabled attribute.
Disabled
-
- <sm-button disabled>Disabled</sm-button>
-
-
+
+<sm-button disabled>Disabled</sm-button>
+
+
Attributes
All the native HTML checkbox attributes are valid
-
- <sm-carousel align-items="start" indicator> ...carousel items... </sm-carousel>
-
-
+
+<sm-carousel align-items="start" indicator> ...carousel items... </sm-carousel>
+
+
Custom attributes
These attributes cane used to customize carousel behaviour and features
@@ -363,21 +360,6 @@
States
- Disabled
- To disable the checkbox add disabled attribute.
-
-
- Disabled checkbox
-
-
-
-
- <sm-checkbox disabled>
- <div style="margin-left: 0.5rem;">Disabled checkbox</div>
- </sm-checkbox>
-
-
-
Checked
To make checkbox checked by default add checked attribute.
@@ -386,12 +368,27 @@
-
- <sm-checkbox checked>
- <div style="margin-left: 0.5rem;">Checked checkbox</div>
- </sm-checkbox>
-
-
+
+<sm-checkbox checked>
+ <div style="margin-left: 0.5rem;">Checked checkbox</div>
+</sm-checkbox>
+
+
+
+ Disabled
+ To disable the checkbox add disabled attribute.
+
+
+ Disabled checkbox
+
+
+
+
+<sm-checkbox disabled>
+ <div style="margin-left: 0.5rem;">Disabled checkbox</div>
+</sm-checkbox>
+
+
Attributes
All the native HTML checkbox attributes are valid
@@ -403,13 +400,13 @@
checked (boolean)
- Sets checked state as default if added
+ If present, checkbox is set to checked state as default.
disabled (boolean)
- Checkbox is disabled by default. all the interactions are disabled
+ If present checkbox is set to disabled state. all the interactions are disabled
@@ -427,6 +424,12 @@
Variable
Description
+
+
--border-color
+
+ Defines color of un-checked checkbox border
+
+
--border-radius
@@ -459,17 +462,18 @@
File input
- <file-input> is essentially native <input type="file"/>
+ <file-input> is essentially native <input type="file"/>
with added style.
So every attribute supported by native file input is supported as can be used in exactly same way.
Interactive demo
Select multiple files
-
- <file-input multiple>Select multiple files</file-input>
-
-
+
+<file-input multiple>Select multiple files</file-input>
+
+
Attributes
@@ -505,12 +509,13 @@
Form
- Browser support for web components form validation or form submition is not perfect.
+ Browser support for web components form validation or form submition is not perfect.
so to circumvent this problem <sm-form> can be used.
Interactive demo
-
+
+
Login
@@ -523,7 +528,8 @@
reset()
- When this function is called upon form element. all the form elements (sm- form elements only) will be reset to default state.
+ When this function is called upon form element. all the form elements (sm- form elements
+ only) will be reset to default state.
@@ -543,20 +549,22 @@
-
- <sm-input id="my_input" placeholder="Email" type="email" value="john@doe" animate></sm-input>
-
-
+
+<sm-input id="my_input" placeholder="Email" type="email" value="john@doe" animate></sm-input>
+
+
Variants
-
outlined is only one styled variation. Default is filled which doesn't require variant specified.
+
outlined is only one styled variation. Default is filled which doesn't
+ require variant specified.
-
- <sm-input placeholder="Name" variant="outlined" animate></sm-input>
-
-
+
+<sm-input placeholder="Name" variant="outlined" animate></sm-input>
+
+
Custom Attributes
-
All the native HTML input attributes are valid. These are additional attributes which can be used to add more functionality
+
All the native HTML input attributes are valid. These are additional attributes which can be used to
+ add more functionality
Attribute
@@ -565,13 +573,14 @@
animate (boolean)
- If present, placeholder of input will be animated to occupy space above enterned text instead of vanishing.
+ If present, placeholder of input will be animated to occupy space above enterned text
+ instead of vanishing.
error-text (string)
- Message specified as value of this attribute will be shown if validation fails.
+ Message specified as value of this attribute will be shown if validation fails.
@@ -584,13 +593,14 @@
focusIn()
- To give focus to this component use this function instead of focus()
+ To give focus to this component use this function instead of focus()
reset()
- When this function is called upon form element. all the form elements (sm- form elements only) will be reset to default state.
+ When this function is called value will be set to empty string.
@@ -604,45 +614,134 @@
customValidation
- If you want to perform custom validation on input value, set the desired validation function.
+ If you want to perform custom validation on input value, set the desired validation
+ function.
-
- /* Setting custom validation function */
- document.getElelementById('my_input').customValidation = myValidation
-
-
+
+<script>
+ /* Setting custom validation function */
+ document.getElelementById('my_input').customValidation = myValidation
+
+ function myValidation(inputValue) {
+ /* Custom validation logic */
+ return Boolean; /* Must return Boolean ( true/ false ) */
+ }
+</script>
+
+
Notifications
- To start using SM Components
+ To start using notifications add the <sm-notifications>
+ at top level of markup like just below starting <body> tag.
- Example
+ Supported functions
+
+
+
Function
+ Description
+
+
+
push()
+
+ Used to display notifications with two parameters.
+ Notification text and notification options.
+
+
+
+
clearAll()
+
+ Removes all the notifications present in notification drawer.
+
+
+
-
- push success notification
-
- push error notification
-
+ Push() options
+
+
+
Property
+ Description
+
+
+
icon (svg)
+
+ To display custom icon with notification icon option can be used.
+
+
+
+
pinned (Boolean)
+
+ If set true notifications won't disappear after some time.
+ they need to be dismissed by user
+ manually.
+
+
+
+ Interactive demo
+
push pinned notification
+
+
+<sm-notifications id="notification_drawer"></sm-notifications>
+<script>
+ const notificationDrawer = document.getElementById('notification_drawer')
+ notificationDrawer.push('This is a notification', { pinned: true })
+</script>
+
+
- Radio
+ Radio button
- Popups are used to show addition UI elements that you may want to hide at first and reveal them when
- needed.
+ Radio buttons are useful whenever only one option needs to be selected from mutiple options. this
+ functionality can be
+ achieved by assigning same name to the group of radio buttons.
+ sm-radio supports all the attributes of native HTML5 radio.
+
+ linking some HTML element with sm-radio using label tag won't work.
+ Add the element inside the opening and closing sm-radio tag.
+
+ Interactive demo
On
@@ -683,16 +784,244 @@
🤷
+
+
+<sm-radio name="abc" value="on" checked>
+ <div class="flex"> On</div>
+</sm-radio>
+<sm-radio name="abc" value="off">
+ <div class="flex"> Off</div>
+</sm-radio>
+<sm-radio name="abc" value="🤷">
+ <div class="flex"> 🤷</div>
+</sm-radio>
+
+
+ States
+ Checked
+ To make switch turned on by default add checked attribute.
+
+
+ Checked radio button
+
+
+
+
+<sm-radio checked>
+ <div>On switch</div>
+</sm-radio>
+
+
+
+ Disabled
+ To disable the radio button add disabled attribute.
+
+
+ Disabled radio button
+
+
+
+
+<sm-radio disabled>
+ <div>Disabled switch</div>
+</sm-radio>
+
+
+
+ Attributes
+ All the native HTML radio attributes are valid
+
+
+
Attribute
+ Description
+
+
+
checked (boolean)
+
+ If present, radio button is set to checked state as default.
+
+
+
+
disabled (boolean)
+
+ If present radio button is set to disabled state. all the interactions are disabled
+
+
+
+
name (string)
+
+ Can be used to group radio buttons with same name. only one radio button will be active in a
+ group.
+
+
+
+
value (string)
+
+ Sets value of radio button which can be accessed by value property with JS
+
+
+
+
+
+
+ Select
+
+ <sm-select> is very similar to starndatd HTML5 select and it's
+ markup stucture is
+ also identical.
+
+ Interactive demo
+
+ option1
+ option2
+ option3
+
+
+
+<sm-select>
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+
+
+ States
+ Disabled
+ To disable the select add disabled attribute.
+
+ option1
+ option2
+ option3
+
+
+
+<sm-select disabled>
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+
+
+ Supported events
+ These are the events that will be fired when component state changes
+
+
+
Event
+ Description
+
+
+
change
+
+ Whenever a different options is selected by user the this event is
+ fired.
+ You can listen to this event and access the current value with event object event.detail.value
+
+
+
+
+
+<sm-select id="my_select">
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+<script>
+ const mySelect = document.getElementById('my_select')
+ mySelect.addEventListener('change', event => {
+ console.log(event.detail.value) // logs out value of selected option
+ })
+</script>
+
+
+
+
+ Spinner
+
+ Just drop the sm-spinner in markup where you want to show the spinner
+
+
+
+
+<sm-spinner></sm-spinner>
+
+
Switch
-
- To start using SM Components
-
-
-
-
+ sm-switch supports all the attributes of native HTML5 checkbox
+
+ linking some HTML element with sm-switch using label tag won't work.
+ Add the element inside the opening and closing sm-switch tag.
+
+ Interactive demo
+
+
+ Turn the switch
+
+
+ States
+ Checked
+ To make switch turned on by default add checked attribute.
+
+
+ On switch
+
+
+
+
+<sm-switch checked>
+ <div slot="left">
+ On switch
+ </div>
+</sm-switch>
+
+
+ Disabled
+ To disable the switch add disabled attribute.
+
+
+ Disabled checkbox
+
+
+
+
+<sm-switch disabled>
+ <div slot="left">
+ Disabled switch
+ </div>
+</sm-switch>
+
+
+
+ Attributes
+ All the native HTML checkbox attributes are valid
+
+
+
Attribute
+ Description
+
+
+
checked (boolean)
+
+ If present, switch is set to checked state as default.
+
+
+
+
disabled (boolean)
+
+ If present switch is set to disabled state. all the interactions are disabled
+
+
+
+
value (string)
+
+ Sets value of switch which can be accessed by value property with JS
+
+
+
@@ -711,11 +1040,14 @@
Spinner
- <sm-select> is very similar to starndatd HTML5 select and it's
- markup stucture is
- also identical.
+ Just drop the sm-spinner in markup where you want to show the spinner
+
+
+<sm-spinner></sm-spinner>
+
+
Theme toggle
+
+ Use theme-toggle to create light/dark theme easily with CSS
+ variables.
+
+ When this is toggled by user the component changes the custom data attribute data-theme="" on HTML body tag
+ to either light or dark
+
+
+ By default theme is set to OS level preferred-color-scheme ( supported by Android, iOS, Windows and
+ MacOS ).
+
+ Interactive demo
+ HTML
+
+
+<theme-toggle></theme-toggle>
+
+
+
+ CSS
+
+
+<style>
+ body ,
+ body *{
+ /* Set CSS variables according to light theme or default theme*/
+ --accent-color: #0D7377;
+ --text-color: 17, 17, 17;
+ --background-color: 255, 255, 255;
+ --danger-color: red;
+ }
+ body[data-theme='dark'],
+ body[data-theme='dark'] *{
+ /* Set CSS variables according to dark theme */
+ --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);
+ }
+ body{
+ color: rgba(var(--text-color), 1);
+ background: rgba(var(--background-color), 1);
+ }
+</style>
+
+
+
+
+ Styling
+ CSS variables used to style this component
+
+
+
Variable
+ Description
+
+
+
--height
+
+ Defines height of toggle button
+
+
+
+
--width
+
+ Defines width of toggle button
+
+
+
+ Custom events
+ These are the events that will be fired when component state changes
+
+
+
Event
+ Description
+
+
+
themechange
+
+ Whenever theme is toggled by user the themechange event is
+ fired.
+ You can listen to this event and access the current value of toggle with event object event.detail.theme
+
+
+
+
+
+<theme-toggle id="my_theme_toggle"></theme-toggle>
+<script>
+ const myThemeToggle = document.getElementById('my_theme_toggle')
+ myThemeToggle.addEventListener('themechange', event => {
+ console.log(event.detail.theme) // logs out current theme ( light / dark )
+ })
+</script>
+
+
-
+
@@ -858,7 +1288,7 @@
}
if (className)
elem.className = className
- if(textContent)
+ if (textContent)
elem.textContent = textContent
if (innerHTML)
elem.innerHTML = innerHTML
diff --git a/components/index.min.html b/components/index.min.html
new file mode 100644
index 0000000..054837b
--- /dev/null
+++ b/components/index.min.html
@@ -0,0 +1,674 @@
+SM Components Getting Started Components
Total components Overview Component-based design is the cornerstone of the modern UI development process. With rise of more UI frameworks every day, the web platform has a serious issue of fragmentation and portability.
Web components to the rescue! This is the collection of web components (WC here forward) that we use at RanchiMall, especially since we are a framework-less development environment so this was a logical choice.
Features Native and Cross framework support Encapsulated style and functionality Easy styling Adaptive scaling Quick Start To start using these components, Select the ones you want to add to your project. You can un-check 'get minified' to get the readable code. Now you can download or copy the source code for selected components. You might get a warning while downloading like this file is not safe, please allow the download as this is caused when downloading files with '.js' extension. These components are 100% safe to use. Link the downloaded js before </body>
+
+<script src=".../components.js"></script>
+
+ Get minified Select all Clear all
Copy source code Download JS file
Global styling These components use CSS variables to customize styling. they share some CSS variables that make global styling easier. Of course you can set these variables at individual component CSS rule set level.
Some common CSS variables and their use
Variable Use --accent-color
Color which will be used for denoting active state
--text-color
default text color for all components. ( Use comma separated rgb values. e.g 17, 17, 17 )
--background-color
default background color for all components. ( Use comma separated rgb values. e.g 255, 255, 255 )
--danger-color
Used for error/invalid state
Buttons Default button Variants These are styled variations of base component
How to define variant
+
+<sm-button variant="primary">primary</sm-button>
+<sm-button variant="outlined">outlined</sm-button>
+<sm-button variant="no-outline">no-outline</sm-button>
+
+ States Disabled To disable the button add disabled attribute.
Disabled
+
+<sm-button disabled>Disabled</sm-button>
+
+ Attributes All the native HTML checkbox attributes are valid
Attribute Description disabled (boolean)
Button is disabled by default. all the interactions are disabled
type (string)
Has values submit reset Can only used withingsm-form to submit or reset the form.
Styling CSS variables used to style this component
Variable Description --background
Define background of button. accepts all values of CSS background property
--border-radius
Set curvature at button corners
--padding
Specify padding of button
Carousel Carousel is a very common UI component primarily used to display images or slides. This carousel switches user interactions based on type of input devices present. For hover capable devices slides can be scrolled with buttons and on touch enabled devices swipe can be used.
Interactive demo Title Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.
Title Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.
Title Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.
Title Lorem ipsum dolor sit amet, consectetur adipisicing elit. Provident, optio.
+
+<sm-carousel align-items="start" indicator> ...carousel items... </sm-carousel>
+
+ Custom attributes These attributes cane used to customize carousel behaviour and features
Attribute Description align-items
Has values start center end Specifies how carousel items should align. default is center .
indicator (boolean)
if added carousel shows dot indicators of carousel items.
Styling CSS variables used to style this component
Variable Description --active-indicator-color
Defines background color of active slide indicator
--nav-background-color
Defines background color of carousel navigation buttons
--nav-box-shadow
Defines box shadow of carousel navigation buttons
--nav-icon-fill
Defines fill of arrow icon on carousel navigation buttons
Checkbox sm-checkbox supports all the attributes of native HTML5 checkbox
linking some HTML element with sm-checbox using label tag won't work. Add the element inside the opening and closing checkbox tag. Interactive demo Check this box
States Checked To make checkbox checked by default add checked attribute.
Checked checkbox
+
+<sm-checkbox checked>
+ <div style="margin-left: 0.5rem;">Checked checkbox</div>
+</sm-checkbox>
+
+ Disabled To disable the checkbox add disabled attribute.
Disabled checkbox
+
+<sm-checkbox disabled>
+ <div style="margin-left: 0.5rem;">Disabled checkbox</div>
+</sm-checkbox>
+
+ Attributes All the native HTML checkbox attributes are valid
Attribute Description checked (boolean)
If present, checkbox is set to checked state as default.
disabled (boolean)
If present checkbox is set to disabled state. all the interactions are disabled
value (string)
Sets value of checkbox which can be accessed by value property with JS
Styling CSS variables used to style this component
Variable Description --border-color
Defines color of un-checked checkbox border
--border-radius
Defines border-radius of checkbox square
--height
Defines height of checkbox
--width
Defines width of checkbox
Copy To start using SM Components
File input <file-input> is essentially native <input type="file"/> with added style. So every attribute supported by native file input is supported as can be used in exactly same way.
Interactive demo Select multiple files
+
+<file-input multiple>Select multiple files</file-input>
+
+ Attributes
Attribute Description accept
One or more unique file type specifiers describing file types to allow
capture
What source to use for capturing image or video data
files
A FileList listing the chosen files
multiple
A Boolean which, if present, indicates that the user may choose more than one file
Form Browser support for web components form validation or form submition is not perfect. so to circumvent this problem <sm-form> can be used.
Interactive demo Login Supported functions
Function Description reset()
When this function is called upon form element. all the form elements (sm- form elements only) will be reset to default state.
Nested element behaviour
Input Interactive demo
+
+<sm-input id="my_input" placeholder="Email" type="email" value="john@doe" animate></sm-input>
+
+ Variants outlined is only one styled variation. Default is filled which doesn't require variant specified.
+
+<sm-input placeholder="Name" variant="outlined" animate></sm-input>
+
+ Custom Attributes All the native HTML input attributes are valid. These are additional attributes which can be used to add more functionality
Attribute Description animate (boolean)
If present, placeholder of input will be animated to occupy space above enterned text instead of vanishing.
error-text (string)
Message specified as value of this attribute will be shown if validation fails.
Supported functions
Function Description focusIn()
To give focus to this component use this function instead of focus()
reset()
When this function is called value will be set to empty string.
Custom Setters
Function Description customValidation
If you want to perform custom validation on input value, set the desired validation function.
+
+<script>
+ /* Setting custom validation function */
+ document.getElelementById('my_input').customValidation = myValidation
+
+ function myValidation(inputValue) {
+ /* Custom validation logic */
+ return Boolean; /* Must return Boolean ( true/ false ) */
+ }
+</script>
+
+ Notifications To start using notifications add the <sm-notifications> at top level of markup like just below starting <body> tag.
Supported functions
Function Description push()
Used to display notifications with two parameters. Notification text and notification options.
clearAll()
Removes all the notifications present in notification drawer.
Push() options
Property Description icon (svg)
To display custom icon with notification icon option can be used.
pinned (Boolean)
If set true notifications won't disappear after some time. they need to be dismissed by user manually.
Interactive demo push pinned notification
+
+<sm-notifications id="notification_drawer"></sm-notifications>
+<script>
+ const notificationDrawer = document.getElementById('notification_drawer')
+ notificationDrawer.push('This is a notification', { pinned: true })
+</script>
+
+ Radio button Radio buttons are useful whenever only one option needs to be selected from mutiple options. this functionality can be achieved by assigning same name to the group of radio buttons.sm-radio supports all the attributes of native HTML5 radio.
linking some HTML element with sm-radio using label tag won't work. Add the element inside the opening and closing sm-radio tag. Interactive demo
+
+<sm-radio name="abc" value="on" checked>
+ <div class="flex"> On</div>
+</sm-radio>
+<sm-radio name="abc" value="off">
+ <div class="flex"> Off</div>
+</sm-radio>
+<sm-radio name="abc" value="🤷">
+ <div class="flex"> 🤷</div>
+</sm-radio>
+
+ States Checked To make switch turned on by default add checked attribute.
Checked radio button
+
+<sm-radio checked>
+ <div>On switch</div>
+</sm-radio>
+
+ Disabled To disable the radio button add disabled attribute.
Disabled radio button
+
+<sm-radio disabled>
+ <div>Disabled switch</div>
+</sm-radio>
+
+ Attributes All the native HTML radio attributes are valid
Attribute Description checked (boolean)
If present, radio button is set to checked state as default.
disabled (boolean)
If present radio button is set to disabled state. all the interactions are disabled
name (string)
Can be used to group radio buttons with same name. only one radio button will be active in a group.
value (string)
Sets value of radio button which can be accessed by value property with JS
Select <sm-select> is very similar to starndatd HTML5 select and it's markup stucture is also identical.
Interactive demo option1 option2 option3
+
+<sm-select>
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+
+ States Disabled To disable the select add disabled attribute.
option1 option2 option3
+
+<sm-select disabled>
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+
+ Supported events These are the events that will be fired when component state changes
Event Description change
Whenever a different options is selected by user the this event is fired. You can listen to this event and access the current value with event object event.detail.value
+
+<sm-select id="my_select">
+ <sm-option value="1">option1</sm-option>
+ <sm-option value="2">option2</sm-option>
+ <sm-option value="3">option3</sm-option>
+</sm-select>
+<script>
+ const mySelect = document.getElementById('my_select')
+ mySelect.addEventListener('change', event => {
+ console.log(event.detail.value) // logs out value of selected option
+ })
+</script>
+
+ Spinner Just drop the sm-spinner in markup where you want to show the spinner
+
+<sm-spinner></sm-spinner>
+
+ Switch sm-switch supports all the attributes of native HTML5 checkbox
linking some HTML element with sm-switch using label tag won't work. Add the element inside the opening and closing sm-switch tag. Interactive demo Turn the switch
States Checked To make switch turned on by default add checked attribute.
On switch
+
+<sm-switch checked>
+ <div slot="left">
+ On switch
+ </div>
+</sm-switch>
+
+ Disabled To disable the switch add disabled attribute.
Disabled checkbox
+
+<sm-switch disabled>
+ <div slot="left">
+ Disabled switch
+ </div>
+</sm-switch>
+
+ Attributes All the native HTML checkbox attributes are valid
Attribute Description checked (boolean)
If present, switch is set to checked state as default.
disabled (boolean)
If present switch is set to disabled state. all the interactions are disabled
value (string)
Sets value of switch which can be accessed by value property with JS
Select <sm-select> is very similar to starndatd HTML5 select and it's markup stucture is also identical.
option1 option2 something option3 Spinner Just drop the sm-spinner in markup where you want to show the spinner
+
+<sm-spinner></sm-spinner>
+
+ Strip select To start using SM Components
Movie TV series Video Music Tabs To start using SM Components
inbox sent draft spam gjdhnsrfijbgn bdfjnbj jadifjoaijdiajdo dosfighjoi flkmgklfmzkl hbdsfhb Lorem ipsum dolor, sit amet consectetur adipisicing elit. Facere neque incidunt aut laudantium, quam id, molestiae vero blanditiis nisi alias in magnam autem quasi cumque eveniet qui cupiditate nam corrupti? Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis fuga ipsam, explicabo, eius accusamus consectetur ex sunt soluta voluptatem iure totam nulla expedita suscipit minus molestiae similique odio optio quibusdam. Tags input To start using SM Components
Textarea To start using SM Components
Text field To start using SM Components
Theme toggle Use theme-toggle to create light/dark theme easily with CSS variables.
When this is toggled by user the component changes the custom data attribute data-theme="" on HTML body tag to either light or dark
By default theme is set to OS level preferred-color-scheme ( supported by Android, iOS, Windows and MacOS ).
Interactive demo HTML
+
+<theme-toggle></theme-toggle>
+
+ CSS
+
+<style>
+ body ,
+ body *{
+ /* Set CSS variables according to light theme or default theme*/
+ --accent-color: #0D7377;
+ --text-color: 17, 17, 17;
+ --background-color: 255, 255, 255;
+ --danger-color: red;
+ }
+ body[data-theme='dark'],
+ body[data-theme='dark'] *{
+ /* Set CSS variables according to dark theme */
+ --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);
+ }
+ body{
+ color: rgba(var(--text-color), 1);
+ background: rgba(var(--background-color), 1);
+ }
+</style>
+
+ Styling CSS variables used to style this component
Variable Description --height
Defines height of toggle button
--width
Defines width of toggle button
Custom events These are the events that will be fired when component state changes
Event Description themechange
Whenever theme is toggled by user the themechange event is fired. You can listen to this event and access the current value of toggle with event object event.detail.theme
+
+<theme-toggle id="my_theme_toggle"></theme-toggle>
+<script>
+ const myThemeToggle = document.getElementById('my_theme_toggle')
+ myThemeToggle.addEventListener('themechange', event => {
+ console.log(event.detail.theme) // logs out current theme ( light / dark )
+ })
+</script>
+
+
\ No newline at end of file