{"id":18751147,"url":"https://github.com/substrate-system/web-component","last_synced_at":"2025-04-13T00:10:18.701Z","repository":{"id":247479217,"uuid":"825534679","full_name":"substrate-system/web-component","owner":"substrate-system","description":"Minimal parent web component to inherit from","archived":false,"fork":false,"pushed_at":"2025-03-26T05:02:01.000Z","size":87,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T00:09:31.119Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://substrate-system.github.io/web-component/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/substrate-system.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-08T03:04:44.000Z","updated_at":"2025-03-26T05:01:58.000Z","dependencies_parsed_at":"2024-07-18T23:59:09.269Z","dependency_job_id":"8d023984-9f46-415a-b5fc-004517167050","html_url":"https://github.com/substrate-system/web-component","commit_stats":null,"previous_names":["substrate-system/web-component"],"tags_count":11,"template":false,"template_full_name":"substrate-system/template-web-component","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fweb-component","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fweb-component/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fweb-component/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fweb-component/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/substrate-system","download_url":"https://codeload.github.com/substrate-system/web-component/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647299,"owners_count":21139086,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T17:14:40.274Z","updated_at":"2025-04-13T00:10:18.692Z","avatar_url":"https://github.com/substrate-system.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# web component\n![tests](https://github.com/substrate-system/web-component/actions/workflows/nodejs.yml/badge.svg)\n[![types](https://img.shields.io/npm/types/@substrate-system/web-component?style=flat-square)](README.md)\n[![module](https://img.shields.io/badge/module-ESM%2FCJS-blue?style=flat-square)](README.md)\n[![semantic versioning](https://img.shields.io/badge/semver-2.0.0-blue?logo=semver\u0026style=flat-square)](https://semver.org/)\n[![dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen.svg?style=flat-square)](package.json#L33)\n[![install size](https://flat.badgen.net/packagephobia/install/@substrate-system/web-component?cache-control=no-cache)](https://packagephobia.com/result?p=@substrate-system/web-component)\n[![Common Changelog](https://nichoth.github.io/badge/common-changelog.svg)](https://common-changelog.org)\n[![license](https://img.shields.io/badge/license-Polyform_Non_Commercial-26bc71?style=flat-square)](LICENSE)\n\n\n\nAn extra minimal parent class for [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components).\n\nThis extends the native `HTMLElement`, adding some methods to help with events.\n\n[See a live demonstration](https://substrate-system.github.io/web-component/)\n\n\u003c!-- toc --\u003e\n\n- [install](#install)\n- [tl;dr](#tldr)\n- [Example](#example)\n  * [Create a component](#create-a-component)\n  * [Add the component to the DOM](#add-the-component-to-the-dom)\n  * [Listen for events](#listen-for-events)\n  * [Emit a namespaced event from the instance](#emit-a-namespaced-event-from-the-instance)\n  * [Emit a plain string (not namespaced) event](#emit-a-plain-string-not-namespaced-event)\n- [API](#api)\n  * [Modules](#modules)\n  * [Common JS](#common-js)\n- [methods](#methods)\n  * [`emit(name:string, opts:{ bubbles?, cancelable?, detail? }):boolean`](#emitnamestring-opts-bubbles-cancelable-detail-boolean)\n  * [`dispatch (type, opts)`](#dispatch-type-opts)\n  * [`event (name:string):string`](#event-namestringstring)\n  * [`qs`](#qs)\n  * [`qsa`](#qsa)\n- [Misc](#misc)\n  * [`isRegistered`](#isregistered)\n- [Develop](#develop)\n- [Test](#test)\n- [See also](#see-also)\n\n\u003c!-- tocstop --\u003e\n\n## install\n\n```bash\nnpm i -S @substrate-system/web-component\n```\n\n## tl;dr\n\n* [use `.emit` to emit a namepsaced event](#emit-a-namespaced-event-from-the-instance)\n* [use `.dispatch` to emit a non-namespaced event](#emit-a-plain-string-not-namespaced-event)\n* [use `.event(name)` to get the namespaced event type](#listen-for-events)\n* [extend the factory function's return value to create a web component](#create-a-component)\n\n## Example\n\n### Create a component\nUse the factory function to create a new web component.\n\n```js\nimport { WebComponent } from '@substrate-system/web-component'\n\nclass AnotherElement extends WebComponent.create('another-element') {\n    constructor () {\n        super()\n    }\n\n    connectedCallback () {\n        this.innerHTML = `\u003cdiv\u003e\n            hello again\n        \u003c/div\u003e`\n    }\n}\n\ncustomElements.define(AnotherElement.NAME, AnotherElement)\n```\n\nThe new component will have a property `NAME` on the class that is equal to [the name you passed in](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names). The component name should be [kebab case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case).\n\n### Add the component to the DOM\n```js\ndocument.body.innerHTML += '\u003canother-element\u003e\u003c/another-element\u003e'\n```\n\n### Listen for events\n\nUse a helper method, `WebComponent.event(name:string)`, to get a\nnamespaced event name.\n\n```js\n// find the instance\nconst el = document.querySelector('my-element')\n\n// listen for namespaced events\nel?.addEventListener(MyElement.event('hello'), ev =\u003e {\n    console.log(ev.detail)  // =\u003e 'some data'\n})\n\n// listen for non-namespaced events\nel?.addEventListener('hello', ev =\u003e {\n    console.log(ev.detail)  // =\u003e 'some data again'\n})\n```\n\n### Emit a namespaced event from the instance\n\n```js\n// find the instance\nconst el = document.querySelector('my-element')\n\n// dispatch an event\nel?.emit('hello', { detail: 'some data' })  // =\u003e `my-element:hello`\n```\n\n### Emit a plain string (not namespaced) event\nDon't namespace the event name, just emit the literal string.\n\n```js\nconst el = document.querySelector('my-element')\n\n// dispatch an event as plain string, not namespaced\nel?.dispatch('hello', { detail: 'some data again' })  // =\u003e `hello`\n```\n\n## API\n\n### Modules\n\nThis exposes ESM and common JS via [package.json `exports` field](https://nodejs.org/api/packages.html#exports).\n\n```js\nconst { WebComponent } = import '@substrate-system/web-component'\n```\n\n### Common JS\n```js\nconst { WebCompponent } = require('@substrate-system/web-component')\n```\n\n## methods\n\n### `emit(name:string, opts:{ bubbles?, cancelable?, detail? }):boolean`\n\nThis will emit a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events), namespaced according to a convention.\n\nThe return value is [the same as the native `.dispatchEvent` method](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent),\n\n\u003e returns `true` if either event's `cancelable` attribute value is false or its `preventDefault()` method was not invoked, and `false` otherwise.\n\nBecause the event is namespaced, we can use event bubbling while minimizing event name collisions.\n\nThe naming convention is to take the `NAME` property of the class, and append a string `:event-name`.\n\nSo `emit('test')` dispatches an event like `my-element:test`.\n\n```js\nclass MyElement {\n    NAME = 'my-element'  // \u003c-- for event namespace\n    // ...\n}\n\n// ... then use the element in markup ...\n\nconst el = document.querySelector('my-element')\n\n// 'my-element:test' event\nel.addEventListener(MyElement.event('test'), ev =\u003e {\n    console.log(ev.detail)  // =\u003e 'some data'\n})\n\n// ... in the future ...\n\nel.emit('test', 'some data')  // dispatch `my-element:test` event\n```\n\nSee also, [Custom events in Web Components](https://gomakethings.com/custom-events-in-web-components/)\n\n-------------------------------------------------------------------\n\n### `dispatch (type, opts)`\nCreate and emit an event, no namespacing. The return value is the same as the\nnative `.dispatchEvent` method,\n\n\u003e returns `true` if either event's `cancelable` attribute value is false or its `preventDefault()` method was not invoked, and `false` otherwise.\n\nThat is, it returns true if it was not `preventDetault`ed.\n\n```ts\ndispatch (type:string, opts:Partial\u003c{\n    bubbles,\n    cancelable,\n    detail\n}\u003e):boolean\n```\n\n#### `dispatch` example\n```js\nconst el = document.querySelector('my-element')\nel.dispatch('change')  // =\u003e 'change' event\n```\n\n-------------------------------------------------------------------\n\n### `event (name:string):string`\nReturn the namespaced event name.\n\n#### `event` example\n\n```js\nMyElement.event('change')  // =\u003e 'my-element:change'\n```\n\n### `qs`\nA convenient shortcut to `element.querySelector`.\n\n```ts\nqs (selector:string):HTMLElement|null\n```\n\n### `qsa`\nShortcut to `element.querySelectorAll`\n\n```ts\nqsa (selector:string):ReturnType\u003ctypeof document.querySelectorAll\u003e\n```\n\n#### example\n```js\nconst myElement = document.querySelector('my-element')\ndebug('the namespaced event...', MyElement.event('aaa'))\n\n// query inside the element \nconst buttons = myElement?.qsa('button')\n```\n\n---------------------------------------------------------------------\n\n## Misc\n\n### `isRegistered`\nCheck if an element name has been used already.\n\n```ts\nfunction isRegistered (elName:string):boolean\n```\n\n#### example\n```js\nimport { isRegistered } from '@substrate-system/web-component'\n\nif (!isRegistered('example-component')) {\n    customElements.define('example-component', ExampleComponent)\n}\n```\n\n---------------------------------------------------------------------\n\n## Develop\nStart a localhost server:\n\n```bash\nnpm start\n```\n\n------------------------------------------------------------------------\n\n## Test\n\n```bash\nnpm test\n```\n\n-------------------------------------------------\n\n\n## See also\n\n* [Custom events in Web Components](https://gomakethings.com/custom-events-in-web-components/)\n* [Web Component lifecycle methods](https://gomakethings.com/the-web-component-lifecycle-methods/)\n* [How to detect when attributes change on a Web Component](https://gomakethings.com/how-to-detect-when-attributes-change-on-a-web-component/)\n* [Handling asychronous rendering in Web Components](https://gomakethings.com/handling-asychronous-rendering-in-web-components/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubstrate-system%2Fweb-component","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsubstrate-system%2Fweb-component","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubstrate-system%2Fweb-component/lists"}