Skip to content

Latest commit

 

History

History
164 lines (119 loc) · 4.41 KB

README.md

File metadata and controls

164 lines (119 loc) · 4.41 KB

µce starter with TypeScript and Rollup

µce is a tiny helper library to create Custom Elements. This starter kit helps to set up a project using µce together with TypeScript.

Features

  • Written in TypeScript
  • Bundled by Rollup
  • Optionally use PostCSS for styling
  • Includes polyfills to support older browsers
  • Tested on Internet Explorer 11

Examples

Live examples on CodeSandbox (which is using Parcel instead of Rollup).

Use with SPA libraries

React

Typed Custom Elements can simply be used in a React project. For example:

import React from "react";
// Import the uce Custom Element (which activates it with tag "my-counter")
import  "./my-counter";

export const App = () => {
  return (
    <>
      <my-counter />
      <my-counter count="99" />
    </>
  );
};

In order to preserve typing, "my-counter" is listed in globals.d.ts (which is included in tsconfig.json). This also solves the TS error "Property 'my-counter' does not exist on type 'JSX.IntrinsicElements'" (raised because React JSX elements must be written in PascalCase).

To include "my-counter" to the accepted tags (and to add the types), take these steps:

  1. Create a type definition file globals.d.ts in the root of your project:
// globals.d.ts
import type { MyCounterProps } from "./src/my-counter";

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'my-counter': MyCounterProps;
    }
  }
}
  1. Include the type definition file in tsconfig.json:
{
  "include": [
    "./src/*",
    "./globals.d.ts"
  ],
  "compilerOptions": {}
}

Mithril

For Mithril, you can preserve typing by using a thin wrapper component around the Custom Element:

import m from "mithril";
import { MyCounterProps } from "./my-counter";
// Import the uce Custom Element (which activates it with tag "my-counter")
import "./my-counter";

export const MyCounter: m.Component<MyCounterProps> = {
  view: (vnode) => m("my-counter", vnode.attrs)
};

and then use the wrapper component:

import m from "mithril";
import { MyCounter } from "./MyCounter";

export const App = {
  view: () => {
    return [
      m(MyCounter),
      m(MyCounter, { count: "99" })
    ];
  }
};

Alternatively, use a wrapper function:

const customElement =
  <Attrs>(tag: string) =>
  (attrs?: Attrs) =>
    m(tag, attrs);

const myCounter = customElement<MyCounterProps>("my-counter");

export const App = {
  view: () => {
    return [
      myCounter(),
      myCounter({ count: "12" }),
    ];
  },
};

CSS

my-counter-postcss is styled with CSS Variables that are defined in the element's CSS definition. However, this does not work for IE 11, that only accepts CSS Variables that are defined in :root - see my-counter-postcss-ie11.

If you must support Internet Explorer 11, you have two choices:

  1. Always define CSS Variables in :root (which is the document root). If you're not careful, variables may be overwritten - alternatively use a single root file for all definitions.
  2. Use PostCSS plugin postcss-cssnext (deprecated) to process all CSS Variables to static values. However, as expected, this does remove the option for theming by simply changing CSS Variable values.

Repo setup

The example component is a simple (and slightly modified) counter that is used on webcomponents.dev to compare Web Component libraries.

  1. Clone this repository
  2. cd uce-starter-typescript-rollup
  3. npm install

Run and build

  • npm run dev - runs the dev server on port 3000
  • npm run build - creates bundle.js in dist
  • npm run serve - runs a server on dist

See also