svelte-webcomponents

Svelte Webcomponents

A ready-to-use project template to build custom elements (web components) with Svelte 3 with support and examples for web components, jest, sass, nested components with props, eslinting, stylelinting, Github actions, propagating custom events from shadow-DOM to real-DOM etc.

svelte logo

svelte-webcomponents

Tweet

If you’re using web-components or if you like the project, please β˜… this repository to show your support! 🀩

The world's most easiest, ready to use template for web-components.

About πŸ“š

A ready to use project template to build custom elements (web components) with Svelte 3 with support and examples for web components, jest, sass, nested components with props, eslinting, stylelinting, Github actions and custom events from shadow-DOM to real-DOM etc.

Installation πŸš€

Run below command inside the working folder

$ git clone https://github.com/tal1992/svelte-webcomponents.git
** or **
$ npx degit tal1992/svelte-webcomponents

Installation and build πŸ“Œ

πŸ“¦ $ npm install 

πŸ”¨ developer mode -> $ npm run dev
πŸ”¨  production mode -> $ npm run build

Using web-components in HTML πŸ“Œ

  <component-name propOne="Lorem" propTwo="Ipsum"></component-name>

Using web-components as a widget πŸ“Œ

function addScript(src) {
  var s = document.createElement("script");
  s.setAttribute("src", src);
  document.querySelector("body").appendChild(s);
}
//replace the url with your hosted path of bundle.js
addScript("https://loremipsumdolarsir/build/bundle.js", "", "");

Now that your bundle.js file is included in the html , we can use the web components.

      let foo = document.createElement('component-foo');
      let header = document.getElementByTagName('header');
      foo.setAttribute('propOne', "lorem");
      foo.setAttribute('propTwo', "Ipsum");
      // please replace header with the element where you want to add your custom element.
      header.parentNode.replaceChild(foo, header);

Nested Custom Elements πŸ“Œ

Register your custom-element inside App.svelte

App.svelte
 import foo from './foo.svelte';
 import bar from './bar.svelte';

No need to import the custom element inside parent declared component, use custom tag names while nesting.

Parent.svelte
<svelte:options tag="component-parent"></svelte:options>

<div class="parent">
    <component-foo name="John" background="orange"></component-foo>
    <component-bar name="Doe" background="lightgreen"></component-bar>
</div>

Writing SCSS inside svelte πŸ“Œ

This template comes with in-built support for scss.

foo.svelte
<style lang="scss">
    h2 {
        padding: 20px;
    }
</style>

Test cases πŸ“Œ

Write test cases inside __tests __ folder

Note : Dont treat webcomponents as a special case for testing, they should be tested as normal svelte components.

import { render } from "@testing-library/svelte";
import App from "../src/App.svelte";

describe("App component", () => {
  test("should render component correctly", () => {
    const { container } = render(App);

    expect(container).toContainHTML("<body><div><h1>Hello from svelte</h1></div></body>");
  });
});

Use normal component name and not the webcomponent name in the test case.

$ npm run test

ESLINT πŸ“Œ

$ npm run lintjs

Style lint πŸ“Œ

$ npm run lintcss

Event propagation from Shadow DOM to Real DOM πŸ“Œ

Foo.svelte (web component)

<script>
    import { get_current_component } from "svelte/internal";
    const thisComponent = get_current_component();

    const dispatchEvent = (name, detail) => {
        thisComponent.dispatchEvent(new CustomEvent(name, {
        detail,
        composed: true, // propagate to the Real DOM, handled in index.html
        }));
    };

    function handleClick(event) {
       event.preventDefault();
       dispatchEvent("customclick", name)
    }    
</script>

<svelte:options tag="component-foo"></svelte:options>

<button on:click={event => handleClick(event)}>Click me</button>

Inside Real DOM

<script>
    window.onload = function () {
      let myelem = document.querySelectorAll('component-foo');

      myelem.forEach(function (elem) {
        elem.addEventListener('customclick', (e) => {
          alert(e.detail + ' clicked');
        });
      });
    };
</script>

Developer

Linkedin Twitter Email

License

MIT

Top categories

Loading Svelte Themes