beercss 3.2.3 → 3.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -110,19 +110,19 @@ From jsdelivr.net.
110
110
 
111
111
  ```html
112
112
  // with html
113
- <link href="https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.css" rel="stylesheet" />
114
- <script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.js"></script>
113
+ <link href="https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.css" rel="stylesheet" />
114
+ <script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.js"></script>
115
115
  <script type="module" src="https://cdn.jsdelivr.net/npm/material-dynamic-colors@0.1.7/dist/cdn/material-dynamic-colors.min.js"></script>
116
116
  ```
117
117
 
118
118
  ```css
119
119
  // with css
120
- @import "https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.css";
120
+ @import "https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.css";
121
121
  ```
122
122
 
123
123
  ```js
124
124
  // with javascript
125
- import "https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.js";
125
+ import "https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.js";
126
126
  import "https://cdn.jsdelivr.net/npm/material-dynamic-colors@0.1.7/dist/cdn/material-dynamic-colors.min.js";
127
127
  ```
128
128
 
@@ -180,8 +180,8 @@ You can use this html to setup your project. See on [Codepen](https://codepen.io
180
180
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
181
181
  <meta name="google" content="notranslate">
182
182
  <title>Hello world</title>
183
- <link href="https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.css" rel="stylesheet">
184
- <script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.2.3/dist/cdn/beer.min.js"></script>
183
+ <link href="https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.css" rel="stylesheet">
184
+ <script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.2.5/dist/cdn/beer.min.js"></script>
185
185
  <script type="module" src="https://cdn.jsdelivr.net/npm/material-dynamic-colors@0.1.7/dist/cdn/material-dynamic-colors.min.js"></script>
186
186
  </head>
187
187
  <body class="light">
@@ -1 +1 @@
1
- export default(()=>{const p=globalThis;let m=null,$=null,w=null;const u={light:"",dark:""},_=async t=>await new Promise(e=>setTimeout(e,t)),q=()=>"fxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)}),g=(t,e)=>{try{return typeof t=="string"?(e!=null?e:document).querySelector(t):t}catch{}},f=(t,e)=>{try{return typeof t=="string"?(e!=null?e:document).querySelectorAll(t):t}catch{}},c=(t,e)=>t==null?void 0:t.classList.contains(e),x=(t,e)=>(t==null?void 0:t.tagName.toLowerCase())===e,k=(t,e)=>(t==null?void 0:t.type.toLowerCase())===e,y=(t,e)=>{t==null||t.classList.add(e)},s=(t,e)=>{t==null||t.classList.remove(e)},v=(t,e,n)=>{t.addEventListener(e,n,!0)},B=(t,e,n)=>{t.removeEventListener(e,n,!0)},I=(t,e)=>e==null?void 0:e.parentNode.insertBefore(t,e),M=t=>t==null?void 0:t.previousElementSibling,O=t=>t==null?void 0:t.nextElementSibling,h=t=>t==null?void 0:t.parentElement,R=t=>{const e=document.createElement("div");for(const n in t)e[n]=t[n];return e},L=t=>{const e=t;k(e,"number")&&!e.value&&(e.value="");const n=h(t),r=g("label",n),o=c(n,"border")&&!c(n,"fill");if(document.activeElement===t||e.value||g("[selected]",e)||k(e,"date")||k(e,"time")){if(o&&r){let l=c(r,"active")?r.offsetWidth:Math.round(r.offsetWidth/1.33);l=l/16;const a=c(n,"round")?1.25:.75,d=l+a+.5;e.style.clipPath=`polygon(0% 0%, ${a}rem 0%, ${a}rem 0.5rem, ${d}rem 0.5rem, ${d}rem 0%, 100% 0%, 100% 100%, 0% 100%)`}else e.style.clipPath="";y(r,"active")}else s(r,"active"),e.style.clipPath="";t.getAttribute("data-ui")&&P(t)},V=t=>{const e=t.currentTarget;x(e,"input")||P(e)},W=t=>{const e=t.currentTarget,n=g("input:not([type=file]):not([type=checkbox]):not([type=radio]), select, textarea",h(e));n&&n.focus()},Z=t=>{const e=t.currentTarget;L(e)},j=t=>{const e=t.currentTarget;L(e)},N=t=>{const e=t.currentTarget;f("menu.active").forEach(r=>s(r,"active")),B(e,"click",N)},z=t=>{const e=t.currentTarget;s(e,"active"),m&&clearTimeout(m)},K=t=>{const e=t.currentTarget;A(e)},G=t=>{const e=t.currentTarget;A(e,t)},H=t=>{const e=t.currentTarget;F(e)},J=()=>{$&&clearTimeout($),$=setTimeout(()=>{E()},180)},A=(t,e)=>{if(e){if(e.key!=="Enter")return;const o=e.currentTarget,i=O(o);return!i||!k(i,"file")?void 0:i.click()}const n=t,r=M(t);!r||!k(r,"text")||(r.value=Array.from(n.files).map(o=>o.name).join(", "),r.readOnly=!0,r.addEventListener("keydown",G),L(r))},F=t=>{const e=h(t),n=g("span",e),r=f("input",e),o=g(".tooltip",e);if(!r.length||!n)return;const i=[],l=[];for(let C=0;C<r.length;C++){const S=parseFloat(r[C].min||"0"),it=parseFloat(r[C].max||"100"),D=parseFloat(r[C].value||"0"),ot=(D-S)*100/(it-S);i.push(ot),l.push(D)}o&&(o.textContent=l.join());let a=i[0],d=0,b=100-d-a;r.length>1&&(a=Math.abs(i[1]-i[0]),d=i[1]>i[0]?i[0]:i[1],b=100-d-a),n.style.left=`${d}%`,n.style.right=`${b}%`},P=(t,e,n)=>{if(e||(e=g(t.getAttribute("data-ui"))),x(e,"dialog"))return X(t,e);if(x(e,"menu"))return U(t,e);if(c(e,"toast"))return Y(t,e,n);if(c(e,"page"))return Q(t,e);if(c(e,"progress"))return tt(e,n);if(T(t),c(e,"active"))return s(e,"active");y(e,"active")},T=t=>{const e=h(t);if(!c(e,"tabs"))return;f("a",e).forEach(r=>s(r,"active")),y(t,"active")},Q=(t,e)=>{T(t);const n=h(e);for(let r=0;r<n.children.length;r++)c(n.children[r],"page")&&s(n.children[r],"active");y(e,"active")},U=(t,e)=>{if(T(t),c(e,"active"))return s(e,"active");f("menu.active").forEach(r=>s(r,"active")),y(e,"active"),v(document.body,"click",N)},X=async(t,e)=>{T(t);let n=M(e);const r=e,o=c(e,"active")||r.open,i=c(e,"modal"),l=h(e),a=x(l,"nav");c(n,"overlay")||(n=R({className:"overlay"}),I(n,e),await _(90)),n.onclick=()=>{i||(s(t,"active"),s(e,"active"),s(n,"active"),r.close())},a&&f("dialog, a, .overlay",l).forEach(b=>{s(b,"active"),b.open&&b.close()}),o?(s(t,"active"),s(n,"active"),s(e,"active"),r.close()):(!x(t,"button")&&!c(t,"button")&&!c(t,"chip")&&y(t,"active"),y(n,"active"),y(e,"active"),i?r.showModal():r.show())},Y=(t,e,n)=>{T(t),f(".toast.active").forEach(o=>s(o,"active")),y(e,"active"),v(e,"click",z),m&&clearTimeout(m),n!==-1&&(m=setTimeout(()=>{s(e,"active")},n!=null?n:6e3))},tt=(t,e)=>{const n=t;if(c(n,"left")){n.style.clipPath=`polygon(0% 0%, 0% 100%, ${e}% 100%, ${e}% 0%)`;return}if(c(n,"top")){n.style.clipPath=`polygon(0% 0%, 100% 0%, 100% ${e}%, 0% ${e}%)`;return}if(c(n,"right")){n.style.clipPath=`polygon(100% 0%, 100% 100%, ${100-e}% 100%, ${100-e}% 0%)`;return}c(n,"bottom")&&(n.style.clipPath=`polygon(0% 100%, 100% 100%, 100% ${100-e}%, 0% ${100-e}%)`)},et=()=>{if(u.light&&u.dark)return u;const t=document.createElement("body");t.className="light",document.body.appendChild(t);const e=document.createElement("body");e.className="dark",document.body.appendChild(e);const n=getComputedStyle(t),r=getComputedStyle(e),o=["--primary","--on-primary","--primary-container","--on-primary-container","--secondary","--on-secondary","--secondary-container","--on-secondary-container","--tertiary","--on-tertiary","--tertiary-container","--on-tertiary-container","--error","--on-error","--error-container","--on-error-container","--background","--on-background","--surface","--on-surface","--outline","--surface-variant","--on-surface-variant","--inverse-surface","--inverse-on-surface","--inverse-primary","--inverse-on-primary"];for(let i=0;i<o.length;i++)u.light+=o[i]+":"+n.getPropertyValue(o[i])+";",u.dark+=o[i]+":"+r.getPropertyValue(o[i])+";";return document.body.removeChild(t),document.body.removeChild(e),u},nt=t=>{if(!t||!p.materialDynamicColors)return et();const e=/dark/i.test(document.body.className)?"dark":"light";return(t==null?void 0:t.light)&&(t==null?void 0:t.dark)?(u.light=t.light,u.dark=t.dark,document.body.setAttribute("style",t[e]),t):p.materialDynamicColors(t).then(n=>{const r=o=>{let i="";for(const l in o){const a=l.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),d=o[l];i+="--"+a+":"+d+";"}return i};return u.light=r(n.light),u.dark=r(n.dark),document.body.setAttribute("style",u[e]),u})},rt=t=>t?(document.body.classList.remove("light","dark"),document.body.classList.add(t),p.materialDynamicColors&&document.body.setAttribute("style",u[t]),t):/dark/i.test(document.body.className)?"dark":"light",at=()=>{if(!w)return w=new MutationObserver(J),w.observe(document.body,{childList:!0,subtree:!0}),E()},E=(t,e)=>{if(t){if(t==="setup")return at();if(t==="guid")return q();if(t==="mode")return rt(e);if(t==="theme")return nt(e);const a=g(t),d=g("[data-ui='#"+a.id+"']");P(d,a,e)}f("[data-ui]").forEach(a=>v(a,"click",V)),f(".field > label").forEach(a=>v(a,"click",W)),f(".field > input:not([type=file]):not([type=checkbox]):not([type=radio]), .field > select, .field > textarea").forEach(a=>{v(a,"focus",Z),v(a,"blur",j),L(a)}),f(".field > input[type=file]").forEach(a=>{v(a,"change",K),A(a)}),f(".slider > input[type=range]").forEach(a=>{v(a,"input",H),F(a)})};return p.addEventListener&&p.addEventListener("load",()=>E("setup")),p.beercss=E,p.ui=E,p.ui})();
1
+ export default(()=>{const v=globalThis;let m=null,A=null,$=null,E;const l={light:"",dark:""};async function I(t){return await new Promise(n=>setTimeout(n,t))}function W(){return"fxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const n=Math.random()*16|0;return(t==="x"?n:n&3|8).toString(16)})}function y(t,n){try{return typeof t=="string"?(n!=null?n:document).querySelector(t):t}catch{}}function d(t,n){try{return typeof t=="string"?(n!=null?n:document).querySelectorAll(t):t}catch{}}function c(t,n){return t==null?void 0:t.classList.contains(n)}function C(t,n){return(t==null?void 0:t.tagName.toLowerCase())===n}function x(t,n){return(t==null?void 0:t.type.toLowerCase())===n}function p(t,n){t==null||t.classList.add(n)}function u(t,n){t==null||t.classList.remove(n)}function h(t,n,e){t.addEventListener(n,e,!0)}function j(t,n,e){t.removeEventListener(n,e,!0)}function O(t,n){return n==null?void 0:n.parentNode.insertBefore(t,n)}function N(t){return t==null?void 0:t.previousElementSibling}function R(t){return t==null?void 0:t.nextElementSibling}function b(t){return t==null?void 0:t.parentElement}function V(t){const n=document.createElement("div");for(const e in t)n[e]=t[e];return n}function Z(t,n){if(t.offsetWidth>0)return t.offsetWidth;if(!E){const e=document.createElement("canvas");e.style.display="none",document.body.append(e),E=e.getContext("2d")}return E.font=n,E.measureText(t.textContent).width}function L(t){const n=t;x(n,"number")&&!n.value&&(n.value="");const e=b(t),r=y("label",e),a=c(e,"border")&&!c(e,"fill");if(document.activeElement===t||n.value||y("[selected]",n)||x(n,"date")||x(n,"time")){if(a&&r){const s=Z(r,"0.75rem Arial");let o=c(r,"active")?s:Math.round(s/1.33);o=o/16;const f=c(e,"round")?1.25:.75,g=o+f+.5;n.style.clipPath=`polygon(0% 0%, ${f}rem 0%, ${f}rem 0.5rem, ${g}rem 0.5rem, ${g}rem 0%, 100% 0%, 100% 100%, 0% 100%)`}else n.style.clipPath="";p(r,"active")}else u(r,"active"),n.style.clipPath="";t.getAttribute("data-ui")&&M(t)}function z(t){const n=t.currentTarget;M(n,null,null,t)}function H(t){const n=t.currentTarget,e=y("input:not([type=file], [type=checkbox], [type=radio]), select, textarea",b(n));e&&e.focus()}function K(t){const n=t.currentTarget;L(n)}function G(t){const n=t.currentTarget;L(n)}function S(t){j(document.body,"click",S);const n=t.target;d("menu.active").forEach(r=>F(n,r,t))}function J(t){const n=t.currentTarget;u(n,"active"),m&&clearTimeout(m)}function Q(t){const n=t.currentTarget;P(n)}function U(t){const n=t.currentTarget;P(n,t)}function X(t){const n=t.currentTarget;D(n)}function _(){A&&clearTimeout(A),A=setTimeout(()=>{w()},180)}function P(t,n){if(n){if(n.key!=="Enter")return;const a=n.currentTarget,i=R(a);return!i||!x(i,"file")?void 0:i.click()}const e=t,r=N(t);!r||!x(r,"text")||(r.value=Array.from(e.files).map(a=>a.name).join(", "),r.readOnly=!0,r.addEventListener("keydown",U),L(r))}function D(t){const n=b(t),e=y("span",n),r=d("input",n),a=y(".tooltip",n);if(!r.length||!e)return;const i=[],s=[];for(let T=0;T<r.length;T++){const q=parseFloat(r[T].min||"0"),ct=parseFloat(r[T].max||"100"),B=parseFloat(r[T].value||"0"),ut=(B-q)*100/(ct-q);i.push(ut),s.push(B)}a&&a.textContent!==s.join()&&(a.innerHTML=s.join());let o=i[0],f=0,g=100-f-o;r.length>1&&(o=Math.abs(i[1]-i[0]),f=i[1]>i[0]?i[0]:i[1],g=100-f-o),e.style.left=`${f}%`,e.style.right=`${g}%`}function M(t,n,e,r){if(n||(n=y(t.getAttribute("data-ui"))),C(n,"dialog"))return tt(t,n);if(C(n,"menu"))return F(t,n,r);if(c(n,"toast"))return nt(t,n,e);if(c(n,"page"))return Y(t,n);if(c(n,"progress"))return et(n,e);if(k(t),c(n,"active"))return u(n,"active");p(n,"active")}function k(t){const n=b(t);if(!c(n,"tabs"))return;d("a",n).forEach(r=>u(r,"active")),p(t,"active")}function Y(t,n){k(t);const e=b(n);for(let r=0;r<e.children.length;r++)c(e.children[r],"page")&&u(e.children[r],"active");p(n,"active")}function F(t,n,e){if(h(document.body,"click",S),e==null||e.stopPropagation(),k(t),c(n,"active")){if(!e)return u(n,"active");const a=e.target,i=y(a.getAttribute("data-ui")),s=a.closest("menu"),o=!y("menu",a.closest("[data-ui]"));return i&&i!==s?F(a,i):!i&&!o&&s?!1:u(n,"active")}d("menu.active").forEach(a=>u(a,"active")),p(n,"active")}async function tt(t,n){k(t);let e=N(n);const r=n,a=c(n,"active")||r.open,i=c(n,"modal"),s=b(n),o=C(s,"nav");c(e,"overlay")||(e=V({className:"overlay"}),O(e,n),await I(90)),e.onclick=()=>{i||(u(t,"active"),u(n,"active"),u(e,"active"),r.close())},o&&d("dialog, a, .overlay",s).forEach(g=>{u(g,"active"),g.open&&g.close()}),a?(u(t,"active"),u(e,"active"),u(n,"active"),r.close()):(!C(t,"button")&&!c(t,"button")&&!c(t,"chip")&&p(t,"active"),p(e,"active"),p(n,"active"),i?r.showModal():r.show())}function nt(t,n,e){k(t),d(".toast.active").forEach(a=>u(a,"active")),p(n,"active"),h(n,"click",J),m&&clearTimeout(m),e!==-1&&(m=setTimeout(()=>{u(n,"active")},e!=null?e:6e3))}function et(t,n){const e=t;if(c(e,"left")){e.style.clipPath=`polygon(0% 0%, 0% 100%, ${n}% 100%, ${n}% 0%)`;return}if(c(e,"top")){e.style.clipPath=`polygon(0% 0%, 100% 0%, 100% ${n}%, 0% ${n}%)`;return}if(c(e,"right")){e.style.clipPath=`polygon(100% 0%, 100% 100%, ${100-n}% 100%, ${100-n}% 0%)`;return}c(e,"bottom")&&(e.style.clipPath=`polygon(0% 100%, 100% 100%, 100% ${100-n}%, 0% ${100-n}%)`)}function rt(){if(l.light&&l.dark)return l;const t=document.createElement("body");t.className="light",document.body.appendChild(t);const n=document.createElement("body");n.className="dark",document.body.appendChild(n);const e=getComputedStyle(t),r=getComputedStyle(n),a=["--primary","--on-primary","--primary-container","--on-primary-container","--secondary","--on-secondary","--secondary-container","--on-secondary-container","--tertiary","--on-tertiary","--tertiary-container","--on-tertiary-container","--error","--on-error","--error-container","--on-error-container","--background","--on-background","--surface","--on-surface","--outline","--surface-variant","--on-surface-variant","--inverse-surface","--inverse-on-surface","--inverse-primary","--inverse-on-primary"];for(let i=0;i<a.length;i++)l.light+=a[i]+":"+e.getPropertyValue(a[i])+";",l.dark+=a[i]+":"+r.getPropertyValue(a[i])+";";return document.body.removeChild(t),document.body.removeChild(n),l}function it(t){if(!t||!v.materialDynamicColors)return rt();const n=/dark/i.test(document.body.className)?"dark":"light";return(t==null?void 0:t.light)&&(t==null?void 0:t.dark)?(l.light=t.light,l.dark=t.dark,document.body.setAttribute("style",t[n]),t):v.materialDynamicColors(t).then(e=>{const r=a=>{let i="";for(const s in a){const o=s.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase(),f=a[s];i+="--"+o+":"+f+";"}return i};return l.light=r(e.light),l.dark=r(e.dark),document.body.setAttribute("style",l[n]),l})}function at(t){return t?(document.body.classList.remove("light","dark"),document.body.classList.add(t),v.materialDynamicColors&&document.body.setAttribute("style",l[t]),t):/dark/i.test(document.body.className)?"dark":"light"}function ot(){$||($=new MutationObserver(_),$.observe(document.body,{childList:!0,subtree:!0}),_())}function w(t,n){if(t){if(t==="setup")return ot();if(t==="guid")return W();if(t==="mode")return at(n);if(t==="theme")return it(n);const o=y(t),f=y("[data-ui='#"+o.id+"']");M(f,o,n)}d("[data-ui]").forEach(o=>h(o,"click",z)),d(".field > label").forEach(o=>h(o,"click",H)),d(".field > input:not([type=file], [type=checkbox], [type=radio]), .field > select, .field > textarea").forEach(o=>{h(o,"focus",K),h(o,"blur",G),L(o)}),d(".field > input[type=file]").forEach(o=>{h(o,"change",Q),P(o)}),d(".slider > input[type=range]").forEach(o=>{h(o,"input",X),D(o)})}return v.addEventListener&&v.addEventListener("load",()=>w("setup")),v.beercss=w,v.ui=w,v.ui})();
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "Everton and Leonardo",
3
3
  "description": "Build material design interfaces in record time... without stress for devs.",
4
4
  "homepage": "https://www.beercss.com/",
5
- "version": "3.2.3",
5
+ "version": "3.2.5",
6
6
  "name": "beercss",
7
7
  "license": "MIT",
8
8
  "type": "module",
package/src/cdn/beer.ts CHANGED
@@ -3,92 +3,107 @@ export default (() => {
3
3
  let _timeoutToast: ReturnType<typeof setTimeout> = null;
4
4
  let _timeoutMutation: ReturnType<typeof setTimeout> = null;
5
5
  let _mutation: MutationObserver = null;
6
+ let _canvas: CanvasRenderingContext2D;
6
7
  const _lastTheme: IBeerCssTheme = {
7
8
  light: "",
8
9
  dark: "",
9
10
  };
10
11
 
11
- const wait = async (milliseconds: number) => {
12
+ async function wait (milliseconds: number) {
12
13
  return await new Promise((resolve: Function) => setTimeout(resolve, milliseconds));
13
- };
14
+ }
14
15
 
15
- const guid = (): string => {
16
+ function guid (): string {
16
17
  return "fxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c: string) => {
17
18
  const r = (Math.random() * 16) | 0;
18
19
  const v = c === "x" ? r : (r & 0x3) | 0x8;
19
20
  return v.toString(16);
20
21
  });
21
- };
22
+ }
22
23
 
23
- const query = (selector: string | Element, element?: Element): Element => {
24
+ function query (selector: string | Element, element?: Element): Element {
24
25
  try {
25
26
  return typeof selector === "string"
26
27
  ? (element ?? document).querySelector(selector)
27
28
  : selector;
28
29
  } catch {}
29
- };
30
+ }
30
31
 
31
- const queryAll = (selector: string | NodeListOf<Element>, element?: Element) => {
32
+ function queryAll (selector: string | NodeListOf<Element>, element?: Element) {
32
33
  try {
33
34
  return typeof selector === "string"
34
35
  ? (element ?? document).querySelectorAll(selector)
35
36
  : selector;
36
37
  } catch {}
37
- };
38
+ }
38
39
 
39
- const hasClass = (element: Element, name: string): boolean => {
40
+ function hasClass (element: Element, name: string): boolean {
40
41
  return element?.classList.contains(name);
41
- };
42
+ }
42
43
 
43
- const hasTag = (element: Element, name: string): boolean => {
44
+ function hasTag (element: Element, name: string): boolean {
44
45
  return element?.tagName.toLowerCase() === name;
45
- };
46
+ }
46
47
 
47
- const hasType = (element: HTMLInputElement, name: string): boolean => {
48
+ function hasType (element: HTMLInputElement, name: string): boolean {
48
49
  return element?.type.toLowerCase() === name;
49
- };
50
+ }
50
51
 
51
- const addClass = (element: Element, name: string) => {
52
+ function addClass (element: Element, name: string) {
52
53
  element?.classList.add(name);
53
- };
54
+ }
54
55
 
55
- const removeClass = (element: Element, name: string) => {
56
+ function removeClass (element: Element, name: string) {
56
57
  element?.classList.remove(name);
57
- };
58
+ }
58
59
 
59
- const on = (element: Element, name: string, callback: any) => {
60
+ function on (element: Element, name: string, callback: any) {
60
61
  element.addEventListener(name, callback, true);
61
- };
62
+ }
62
63
 
63
- const off = (element: Element, name: string, callback: any) => {
64
+ function off (element: Element, name: string, callback: any) {
64
65
  element.removeEventListener(name, callback, true);
65
- };
66
+ }
66
67
 
67
- const insertBefore = (newElement: Element, element: Element): Element => {
68
+ function insertBefore (newElement: Element, element: Element): Element {
68
69
  return element?.parentNode.insertBefore(newElement, element);
69
- };
70
+ }
70
71
 
71
- const prev = (element: Element): Element => {
72
+ function prev (element: Element): Element {
72
73
  return element?.previousElementSibling;
73
- };
74
+ }
74
75
 
75
- const next = (element: Element): Element => {
76
+ function next (element: Element): Element {
76
77
  return element?.nextElementSibling;
77
- };
78
+ }
78
79
 
79
- const parent = (element: Element): Element => {
80
+ function parent (element: Element): Element {
80
81
  return element?.parentElement;
81
- };
82
+ }
82
83
 
83
- const create = (json: any): HTMLElement => {
84
+ function create (json: any): HTMLElement {
84
85
  const element = document.createElement("div");
85
86
 
86
87
  for (const i in json) { element[i] = json[i]; }
87
88
 
88
89
  return element;
89
- };
90
+ }
90
91
 
91
- const updateInput = (target: Element) => {
92
+ function textWidth (element: HTMLElement, font: string): number {
93
+ if (element.offsetWidth > 0) return element.offsetWidth;
94
+
95
+ if (!_canvas) {
96
+ const canvasElement = document.createElement("canvas");
97
+ canvasElement.style.display = "none";
98
+ document.body.append(canvasElement);
99
+ _canvas = canvasElement.getContext("2d");
100
+ }
101
+
102
+ _canvas.font = font;
103
+ return _canvas.measureText(element.textContent).width;
104
+ }
105
+
106
+ function updateInput (target: Element) {
92
107
  const input = target as HTMLInputElement;
93
108
  if (hasType(input, "number") && !input.value) input.value = "";
94
109
 
@@ -99,7 +114,8 @@ export default (() => {
99
114
 
100
115
  if (toActive) {
101
116
  if (isBorder && label) {
102
- let width = hasClass(label, "active") ? label.offsetWidth : Math.round(label.offsetWidth / 1.33);
117
+ const labelWidth = textWidth(label, "0.75rem Arial");
118
+ let width = hasClass(label, "active") ? labelWidth : Math.round(labelWidth / 1.33);
103
119
  width = width / 16;
104
120
  const start = hasClass(parentTarget, "round") ? 1.25 : 0.75;
105
121
  const end = width + start + 0.5;
@@ -112,65 +128,64 @@ export default (() => {
112
128
  }
113
129
 
114
130
  if (target.getAttribute("data-ui")) open(target);
115
- };
131
+ }
116
132
 
117
- const onClickElement = (e: Event) => {
133
+ function onClickElement (e: Event) {
118
134
  const target = e.currentTarget as HTMLElement;
119
- if (hasTag(target, "input")) return;
120
- open(target);
121
- };
135
+ open(target, null, null, e);
136
+ }
122
137
 
123
- const onClickLabel = (e: Event) => {
138
+ function onClickLabel (e: Event) {
124
139
  const target = e.currentTarget as Element;
125
- const input = query("input:not([type=file]):not([type=checkbox]):not([type=radio]), select, textarea", parent(target)) as HTMLElement;
140
+ const input = query("input:not([type=file], [type=checkbox], [type=radio]), select, textarea", parent(target)) as HTMLElement;
126
141
  if (input) input.focus();
127
- };
142
+ }
128
143
 
129
- const onFocusInput = (e: Event) => {
144
+ function onFocusInput (e: Event) {
130
145
  const target = e.currentTarget as Element;
131
146
  updateInput(target);
132
- };
147
+ }
133
148
 
134
- const onBlurInput = (e: Event) => {
149
+ function onBlurInput (e: Event) {
135
150
  const target = e.currentTarget as Element;
136
151
  updateInput(target);
137
- };
152
+ }
138
153
 
139
- const onClickDocument = (e: Event) => {
140
- const target = e.currentTarget as Element;
154
+ function onClickDocument (e: Event) {
155
+ off(document.body, "click", onClickDocument);
156
+ const target = e.target as Element;
141
157
  const menus = queryAll("menu.active");
142
- menus.forEach((x: Element) => removeClass(x, "active"));
143
- off(target, "click", onClickDocument);
144
- };
158
+ menus.forEach((x: Element) => menu(target, x, e));
159
+ }
145
160
 
146
- const onClickToast = (e: Event) => {
161
+ function onClickToast (e: Event) {
147
162
  const target = e.currentTarget as Element;
148
163
  removeClass(target, "active");
149
164
 
150
165
  if (_timeoutToast) clearTimeout(_timeoutToast);
151
- };
166
+ }
152
167
 
153
- const onChangeFile = (e: Event) => {
168
+ function onChangeFile (e: Event) {
154
169
  const target = e.currentTarget as HTMLInputElement;
155
170
  updateFile(target);
156
- };
171
+ }
157
172
 
158
- const onKeydownFile = (e: KeyboardEvent) => {
173
+ function onKeydownFile (e: KeyboardEvent) {
159
174
  const target = e.currentTarget as HTMLInputElement;
160
175
  updateFile(target, e);
161
- };
176
+ }
162
177
 
163
- const onInputRange = (e: Event) => {
178
+ function onInputRange (e: Event) {
164
179
  const target = e.currentTarget as HTMLInputElement;
165
180
  updateRange(target);
166
- };
181
+ }
167
182
 
168
- const onMutation = () => {
183
+ function onMutation () {
169
184
  if (_timeoutMutation) clearTimeout(_timeoutMutation);
170
185
  _timeoutMutation = setTimeout(() => { void ui(); }, 180);
171
- };
186
+ }
172
187
 
173
- const updateFile = (target: Element, e?: KeyboardEvent) => {
188
+ function updateFile (target: Element, e?: KeyboardEvent) {
174
189
  if (e) {
175
190
  if (e.key !== "Enter") return;
176
191
 
@@ -187,9 +202,9 @@ export default (() => {
187
202
  previousTarget.readOnly = true;
188
203
  previousTarget.addEventListener("keydown", onKeydownFile);
189
204
  updateInput(previousTarget);
190
- };
205
+ }
191
206
 
192
- const updateRange = (target: Element) => {
207
+ function updateRange (target: Element) {
193
208
  const parentTarget = parent(target) as HTMLElement;
194
209
  const bar = query("span", parentTarget) as HTMLElement;
195
210
  const inputs = queryAll("input", parentTarget) as NodeListOf<HTMLInputElement>;
@@ -207,7 +222,7 @@ export default (() => {
207
222
  values.push(value);
208
223
  }
209
224
 
210
- if (tooltip) tooltip.textContent = values.join();
225
+ if (tooltip && tooltip.textContent !== values.join()) tooltip.innerHTML = values.join();
211
226
 
212
227
  let percent = percents[0];
213
228
  let left = 0;
@@ -220,12 +235,12 @@ export default (() => {
220
235
 
221
236
  bar.style.left = `${left}%`;
222
237
  bar.style.right = `${right}%`;
223
- };
238
+ }
224
239
 
225
- const open = (from?: Element, to?: Element, options?: any): any => {
240
+ function open (from?: Element, to?: Element, options?: any, e?: Event): any {
226
241
  if (!to) to = query(from.getAttribute("data-ui"));
227
242
  if (hasTag(to, "dialog")) return dialog(from, to);
228
- if (hasTag(to, "menu")) return menu(from, to);
243
+ if (hasTag(to, "menu")) return menu(from, to, e);
229
244
  if (hasClass(to, "toast")) return toast(from, to, options);
230
245
  if (hasClass(to, "page")) return page(from, to);
231
246
  if (hasClass(to, "progress")) return progress(to, options);
@@ -235,9 +250,9 @@ export default (() => {
235
250
  if (hasClass(to, "active")) return removeClass(to, "active");
236
251
 
237
252
  addClass(to, "active");
238
- };
253
+ }
239
254
 
240
- const tab = (from: Element) => {
255
+ function tab (from: Element) {
241
256
  const container = parent(from);
242
257
  if (!hasClass(container, "tabs")) return;
243
258
 
@@ -245,30 +260,41 @@ export default (() => {
245
260
  tabs.forEach((x: Element) => removeClass(x, "active"));
246
261
 
247
262
  addClass(from, "active");
248
- };
263
+ }
249
264
 
250
- const page = (from: Element, to: Element) => {
265
+ function page (from: Element, to: Element) {
251
266
  tab(from);
252
267
 
253
268
  const container = parent(to);
254
269
  for (let i = 0; i < container.children.length; i++) { if (hasClass(container.children[i], "page")) removeClass(container.children[i], "active"); }
255
270
 
256
271
  addClass(to, "active");
257
- };
272
+ }
258
273
 
259
- const menu = (from: Element, to: Element) => {
274
+ function menu (from: Element, to: Element, e?: Event) {
275
+ on(document.body, "click", onClickDocument);
276
+ e?.stopPropagation();
260
277
  tab(from);
261
278
 
262
- if (hasClass(to, "active")) return removeClass(to, "active");
279
+ if (hasClass(to, "active")) {
280
+ if (!e) return removeClass(to, "active");
281
+
282
+ const trustedFrom = e.target as Element;
283
+ const trustedTo = query(trustedFrom.getAttribute("data-ui"));
284
+ const trustedMenu = trustedFrom.closest("menu");
285
+ const trustedActive = !query("menu", trustedFrom.closest("[data-ui]"));
286
+
287
+ if (trustedTo && trustedTo !== trustedMenu) return menu(trustedFrom, trustedTo);
288
+ if (!trustedTo && !trustedActive && trustedMenu) return false;
289
+ return removeClass(to, "active");
290
+ }
263
291
 
264
292
  const menus = queryAll("menu.active");
265
293
  menus.forEach((x: Element) => removeClass(x, "active"));
266
-
267
294
  addClass(to, "active");
268
- on(document.body, "click", onClickDocument);
269
- };
295
+ }
270
296
 
271
- const dialog = async (from: Element, to: Element) => {
297
+ async function dialog (from: Element, to: Element) {
272
298
  tab(from);
273
299
 
274
300
  let overlay = prev(to) as HTMLElement;
@@ -314,9 +340,9 @@ export default (() => {
314
340
  if (isModal) target.showModal();
315
341
  else target.show();
316
342
  }
317
- };
343
+ }
318
344
 
319
- const toast = (from: Element, to: Element, milliseconds?: number) => {
345
+ function toast (from: Element, to: Element, milliseconds?: number) {
320
346
  tab(from);
321
347
 
322
348
  const elements = queryAll(".toast.active");
@@ -331,9 +357,9 @@ export default (() => {
331
357
  _timeoutToast = setTimeout(() => {
332
358
  removeClass(to, "active");
333
359
  }, milliseconds ?? 6000);
334
- };
360
+ }
335
361
 
336
- const progress = (to: Element, percentage: number) => {
362
+ function progress (to: Element, percentage: number) {
337
363
  const element = to as HTMLElement;
338
364
 
339
365
  if (hasClass(element, "left")) {
@@ -352,9 +378,9 @@ export default (() => {
352
378
  }
353
379
 
354
380
  if (hasClass(element, "bottom")) element.style.clipPath = `polygon(0% 100%, 100% 100%, 100% ${100 - percentage}%, 0% ${100 - percentage}%)`;
355
- };
381
+ }
356
382
 
357
- const lastTheme = (): IBeerCssTheme => {
383
+ function lastTheme (): IBeerCssTheme {
358
384
  if (_lastTheme.light && _lastTheme.dark) return _lastTheme;
359
385
 
360
386
  const light = document.createElement("body");
@@ -376,9 +402,9 @@ export default (() => {
376
402
  document.body.removeChild(light);
377
403
  document.body.removeChild(dark);
378
404
  return _lastTheme;
379
- };
405
+ }
380
406
 
381
- const theme = (source?: IBeerCssTheme | any): IBeerCssTheme | Promise<IBeerCssTheme> => {
407
+ function theme (source?: IBeerCssTheme | any): IBeerCssTheme | Promise<IBeerCssTheme> {
382
408
  if (!source || !_window.materialDynamicColors) return lastTheme();
383
409
 
384
410
  const mode = /dark/i.test(document.body.className) ? "dark" : "light";
@@ -405,26 +431,26 @@ export default (() => {
405
431
  document.body.setAttribute("style", _lastTheme[mode]);
406
432
  return _lastTheme;
407
433
  });
408
- };
434
+ }
409
435
 
410
- const mode = (value: string | any): string => {
436
+ function mode (value: string | any): string {
411
437
  if (!value) return /dark/i.test(document.body.className) ? "dark" : "light";
412
438
  document.body.classList.remove("light", "dark");
413
439
  document.body.classList.add(value);
414
440
  if (_window.materialDynamicColors) document.body.setAttribute("style", _lastTheme[value]);
415
441
  return value;
416
- };
442
+ }
417
443
 
418
- const setup = () => {
444
+ function setup () {
419
445
  if (_mutation) return;
420
446
  _mutation = new MutationObserver(onMutation);
421
447
  _mutation.observe(document.body, { childList: true, subtree: true });
422
- return ui();
423
- };
448
+ onMutation();
449
+ }
424
450
 
425
- const ui = (selector?: string | Element, options?: string | number | IBeerCssTheme): string | IBeerCssTheme | Promise<IBeerCssTheme> => {
451
+ function ui (selector?: string | Element, options?: string | number | IBeerCssTheme): string | IBeerCssTheme | Promise<IBeerCssTheme> {
426
452
  if (selector) {
427
- if (selector === "setup") return setup();
453
+ if (selector === "setup") return setup() as undefined;
428
454
  if (selector === "guid") return guid();
429
455
  if (selector === "mode") return mode(options);
430
456
  if (selector === "theme") return theme(options);
@@ -440,7 +466,7 @@ export default (() => {
440
466
  const labels = queryAll(".field > label");
441
467
  labels.forEach((x: HTMLLabelElement) => on(x, "click", onClickLabel));
442
468
 
443
- const inputs = queryAll(".field > input:not([type=file]):not([type=checkbox]):not([type=radio]), .field > select, .field > textarea");
469
+ const inputs = queryAll(".field > input:not([type=file], [type=checkbox], [type=radio]), .field > select, .field > textarea");
444
470
  inputs.forEach((x: Element) => {
445
471
  on(x, "focus", onFocusInput);
446
472
  on(x, "blur", onBlurInput);
@@ -458,7 +484,7 @@ export default (() => {
458
484
  on(x, "input", onInputRange);
459
485
  updateRange(x);
460
486
  });
461
- };
487
+ }
462
488
 
463
489
  if (_window.addEventListener) _window.addEventListener("load", () => ui("setup"));
464
490
  _window.beercss = ui;