UNPKG

@zeix/ui-element

Version:

UIElement - minimal reactive framework based on Web Components

99 lines (96 loc) 14.1 kB
<tab-list> <menu> <li><button type="button" aria-pressed="false">HTML</button></li> <li><button type="button" aria-pressed="true">TypeScript</button></li> </menu> <details> <summary> <div class="summary">HTML</div> </summary> <code-block language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!"> <p class="meta"> <span class="file">lazy-load.html</span> <span class="language">html</span> </p> <pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F8F8F2">&#x3C;</span><span style="color:#F92672">lazy-load</span><span style="color:#A6E22E"> src</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"./examples/snippets/snippet.html"</span><span style="color:#F8F8F2">></span></span> <span class="line"><span style="color:#F8F8F2"> &#x3C;</span><span style="color:#F92672">p</span><span style="color:#A6E22E"> class</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"loading"</span><span style="color:#F8F8F2">>Loading...&#x3C;/</span><span style="color:#F92672">p</span><span style="color:#F8F8F2">></span></span> <span class="line"><span style="color:#F8F8F2"> &#x3C;</span><span style="color:#F92672">p</span><span style="color:#A6E22E"> class</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"error"</span><span style="color:#F8F8F2">>&#x3C;/</span><span style="color:#F92672">p</span><span style="color:#F8F8F2">></span></span> <span class="line"><span style="color:#F8F8F2">&#x3C;/</span><span style="color:#F92672">lazy-load</span><span style="color:#F8F8F2">></span></span></code></pre> <input-button class="copy"> <button type="button" class="secondary small"> <span class="label">Copy</span> </button> </input-button> </code-block> </details> <details open> <summary> <div class="summary">TS</div> </summary> <code-block language="ts" copy-success="Copied!" copy-error="Error trying to copy to clipboard!"> <p class="meta"> <span class="file">lazy-load.ts</span> <span class="language">ts</span> </p> <pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">import</span><span style="color:#F8F8F2"> { UIElement, setProperty, setText, dangerouslySetInnerHTML } </span><span style="color:#F92672">from</span><span style="color:#E6DB74"> '../../../'</span></span> <span class="line"></span> <span class="line"><span style="color:#F92672">export</span><span style="color:#66D9EF;font-style:italic"> class</span><span> </span><span style="color:#A6E22E;text-decoration:underline">LazyLoad</span><span style="color:#F92672"> extends</span><span style="color:#A6E22E"> UIElement</span><span style="color:#F8F8F2">&#x3C;{</span></span> <span class="line"><span style="color:#F8F8F2"> src</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span><span style="color:#F8F8F2">,</span></span> <span class="line"><span style="color:#F8F8F2"> content</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span><span style="color:#F8F8F2">,</span></span> <span class="line"><span style="color:#F8F8F2"> error</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span><span style="color:#F8F8F2">,</span></span> <span class="line"><span style="color:#F8F8F2">}> {</span></span> <span class="line"><span style="color:#F92672"> static</span><span style="color:#F8F8F2"> localName </span><span style="color:#F92672">=</span><span style="color:#E6DB74"> 'lazy-load'</span></span> <span class="line"></span> <span class="line"><span style="color:#F8F8F2"> init </span><span style="color:#F92672">=</span><span style="color:#F8F8F2"> {</span></span> <span class="line"><span style="color:#A6E22E"> src</span><span style="color:#F8F8F2">: (</span><span style="color:#FD971F;font-style:italic">v</span><span style="color:#F92672">:</span><span style="color:#66D9EF;font-style:italic"> string</span><span style="color:#F92672"> |</span><span style="color:#66D9EF;font-style:italic"> null</span><span style="color:#F8F8F2">) </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> { </span><span style="color:#88846F">// Custom attribute parser</span></span> <span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (</span><span style="color:#F92672">!</span><span style="color:#F8F8F2">v) {</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'No URL provided in src attribute'</span><span style="color:#F8F8F2">)</span></span> <span class="line"><span style="color:#F92672"> return</span><span style="color:#E6DB74"> ''</span></span> <span class="line"><span style="color:#F8F8F2"> } </span><span style="color:#F92672">else</span><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> ((</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.parentElement </span><span style="color:#F92672">||</span><span style="color:#F8F8F2"> (</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">getRootNode</span><span style="color:#F8F8F2">() </span><span style="color:#F92672">as</span><span> </span><span style="color:#A6E22E;text-decoration:underline">ShadowRoot</span><span style="color:#F8F8F2">).host)?.</span><span style="color:#A6E22E">closest</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">`</span><span style="color:#F92672">${</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.localName</span><span style="color:#F92672">}</span><span style="color:#E6DB74">[src="</span><span style="color:#F92672">${</span><span style="color:#F8F8F2">v</span><span style="color:#F92672">}</span><span style="color:#E6DB74">"]`</span><span style="color:#F8F8F2">)) {</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'Recursive loading detected'</span><span style="color:#F8F8F2">)</span></span> <span class="line"><span style="color:#F92672"> return</span><span style="color:#E6DB74"> ''</span></span> <span class="line"><span style="color:#F8F8F2"> }</span></span> <span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> url </span><span style="color:#F92672">=</span><span style="color:#F92672"> new</span><span style="color:#A6E22E"> URL</span><span style="color:#F8F8F2">(v, location.href) </span><span style="color:#88846F">// Ensure 'src' attribute is a valid URL</span></span> <span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (url.origin </span><span style="color:#F92672">===</span><span style="color:#F8F8F2"> location.origin) </span><span style="color:#88846F">// Sanity check for cross-origin URLs</span></span> <span class="line"><span style="color:#F92672"> return</span><span style="color:#F8F8F2"> url.</span><span style="color:#A6E22E">toString</span><span style="color:#F8F8F2">()</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">, </span><span style="color:#E6DB74">'Invalid URL origin'</span><span style="color:#F8F8F2">)</span></span> <span class="line"><span style="color:#F92672"> return</span><span style="color:#E6DB74"> ''</span></span> <span class="line"><span style="color:#F8F8F2"> },</span></span> <span class="line"><span style="color:#A6E22E"> content</span><span style="color:#F8F8F2">: </span><span style="color:#F92672">async</span><span style="color:#F8F8F2"> () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F8F8F2"> { </span><span style="color:#88846F">// Async Computed callback</span></span> <span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> url </span><span style="color:#F92672">=</span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'src'</span><span style="color:#F8F8F2">)</span></span> <span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (</span><span style="color:#F92672">!</span><span style="color:#F8F8F2">url) </span><span style="color:#F92672">return</span><span style="color:#E6DB74"> ''</span></span> <span class="line"><span style="color:#F92672"> try</span><span style="color:#F8F8F2"> {</span></span> <span class="line"><span style="color:#66D9EF;font-style:italic"> const</span><span style="color:#F8F8F2"> response </span><span style="color:#F92672">=</span><span style="color:#F92672"> await</span><span style="color:#A6E22E"> fetch</span><span style="color:#F8F8F2">(</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'src'</span><span style="color:#F8F8F2">))</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">querySelector</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'.loading'</span><span style="color:#F8F8F2">)?.</span><span style="color:#A6E22E">remove</span><span style="color:#F8F8F2">()</span></span> <span class="line"><span style="color:#F92672"> if</span><span style="color:#F8F8F2"> (response.ok) </span><span style="color:#F92672">return</span><span style="color:#F8F8F2"> response.</span><span style="color:#A6E22E">text</span><span style="color:#F8F8F2">()</span></span> <span class="line"><span style="color:#F92672"> else</span><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">, response.statusText)</span></span> <span class="line"><span style="color:#F8F8F2"> } </span><span style="color:#F92672">catch</span><span style="color:#F8F8F2"> (error) {</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">set</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">, error.message)</span></span> <span class="line"><span style="color:#F8F8F2"> }</span></span> <span class="line"><span style="color:#F92672"> return</span><span style="color:#E6DB74"> ''</span></span> <span class="line"><span style="color:#F8F8F2"> },</span></span> <span class="line"><span style="color:#F8F8F2"> error: </span><span style="color:#E6DB74">''</span><span style="color:#F8F8F2">,</span></span> <span class="line"><span style="color:#F8F8F2"> }</span></span> <span class="line"></span> <span class="line"><span style="color:#A6E22E"> connectedCallback</span><span style="color:#F8F8F2">() {</span></span> <span class="line"><span style="color:#FD971F"> super</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">connectedCallback</span><span style="color:#F8F8F2">()</span></span> <span class="line"></span> <span class="line"><span style="color:#88846F"> // Effect to set error message</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">first</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'.error'</span><span style="color:#F8F8F2">).</span><span style="color:#A6E22E">sync</span><span style="color:#F8F8F2">(</span></span> <span class="line"><span style="color:#A6E22E"> setProperty</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'hidden'</span><span style="color:#F8F8F2">, () </span><span style="color:#66D9EF;font-style:italic">=></span><span style="color:#F92672"> !</span><span style="color:#FD971F">this</span><span style="color:#F8F8F2">.</span><span style="color:#A6E22E">get</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">)),</span></span> <span class="line"><span style="color:#A6E22E"> setText</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'error'</span><span style="color:#F8F8F2">),</span></span> <span class="line"><span style="color:#F8F8F2"> )</span></span> <span class="line"></span> <span class="line"><span style="color:#88846F"> // Effect to set innerHTML to result of Computed 'content'</span></span> <span class="line"><span style="color:#FD971F"> this</span><span style="color:#F8F8F2">.self.</span><span style="color:#A6E22E">sync</span><span style="color:#F8F8F2">(</span><span style="color:#A6E22E">dangerouslySetInnerHTML</span><span style="color:#F8F8F2">(</span><span style="color:#E6DB74">'content'</span><span style="color:#F8F8F2">))</span></span> <span class="line"><span style="color:#F8F8F2"> }</span></span> <span class="line"><span style="color:#F8F8F2">}</span></span> <span class="line"><span style="color:#F8F8F2">LazyLoad.</span><span style="color:#A6E22E">define</span><span style="color:#F8F8F2">()</span></span></code></pre> <input-button class="copy"> <button type="button" class="secondary small"> <span class="label">Copy</span> </button> </input-button> </code-block> </details> </tab-list>