{"id":30821114,"url":"https://github.com/tram-one/shadowroot-injector","last_synced_at":"2025-09-06T10:15:06.665Z","repository":{"id":301882435,"uuid":"1009952158","full_name":"Tram-One/shadowroot-injector","owner":"Tram-One","description":"🪡 declaratively define shadowroots to repeat in HTML templates","archived":false,"fork":false,"pushed_at":"2025-08-02T20:52:01.000Z","size":95,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-29T00:51:37.321Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tram-One.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null}},"created_at":"2025-06-28T03:17:56.000Z","updated_at":"2025-08-02T20:52:05.000Z","dependencies_parsed_at":"2025-06-29T11:50:36.068Z","dependency_job_id":"4aad15b5-917a-4c91-a699-94a48e26ce65","html_url":"https://github.com/Tram-One/shadowroot-injector","commit_stats":null,"previous_names":["tram-one/shadowroot-injector"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Tram-One/shadowroot-injector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tram-One%2Fshadowroot-injector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tram-One%2Fshadowroot-injector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tram-One%2Fshadowroot-injector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tram-One%2Fshadowroot-injector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tram-One","download_url":"https://codeload.github.com/Tram-One/shadowroot-injector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tram-One%2Fshadowroot-injector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273888692,"owners_count":25185930,"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","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2025-09-06T10:15:01.411Z","updated_at":"2025-09-06T10:15:06.635Z","avatar_url":"https://github.com/Tram-One.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ShadowRoot Injector\n\n_🪡 declaratively define shadowroots to repeat in HTML templates_\n\n## What is ShadowRoot Injector?\n\nShadowRoot Injector lets you define templates for elements using HTML. When those elements appear in the DOM, the\nlibrary will automatically insert a template into the element. You can then, optionally, upgrade the element using\nnative web-component definitions (either inline in a script tag, or imported as a separate component definition).\n\n### Example\n\nThe example below shows a markdown callout. You can see a running example live on\n[codepen](https://codepen.io/JRJurman/pen/MYaKErE).\n\n```html\n\u003c!-- 1. Auto-start the injector --\u003e\n\u003cscript src=\"https://unpkg.com/shadowroot-injector@2\"\u003e\u003c/script\u003e\n\n\u003c!-- 2. Define a generic \u003clinked-header\u003e --\u003e\n\u003cshadowroot-for selector=\"callout-alert\" mode=\"open\"\u003e\n  \u003ctemplate\u003e\n    \u003cstyle\u003e\n      :host,\n      slot {\n        display: block;\n      }\n\n      details {\n        display: block;\n        border-left: solid 3px rgb(var(--callout-color));\n        background: rgba(var(--callout-color), 0.1);\n        padding: 0.5em;\n      }\n\n      summary {\n        font-weight: bold;\n        color: rgb(var(--callout-color));\n        list-style: none;\n      }\n    \u003c/style\u003e\n\n    \u003cdetails open\u003e\n      \u003csummary\u003e\u003cslot name=\"title\"\u003e\u003c/slot\u003e\u003c/summary\u003e\n      \u003cslot\u003e\u003c/slot\u003e\n    \u003c/details\u003e\n  \u003c/template\u003e\n\n  \u003c!-- 3. Use it anywhere --\u003e\n  \u003cp\u003eShadowRoot Injector lets you repeat templates easily, no JS required!\u003c/p\u003e\n\n  \u003ccallout-alert style=\"--callout-color: 160, 40, 40;\"\u003e\n    \u003cspan slot=\"title\"\u003ePro Tip!\u003c/span\u003e\n    If you want to add more behavior, you can upgrade custom-elements into web-components any time with JavaScript!\n  \u003c/callout-alert\u003e\n\n  \u003cp\u003eYou can check out the repository on Github.\u003c/p\u003e\n\n  \u003ccallout-alert style=\"--callout-color: 40, 40, 160;\"\u003e\n    \u003cspan slot=\"title\"\u003ePRs Welcome!\u003c/span\u003e\n    You can make git issues or pull requests for any issues you find.\n  \u003c/callout-alert\u003e\u003c/shadowroot-for\n\u003e\n```\n\n### Why?\n\nToday, there isn't a native or elegant way to repeat HTML content across the document without building a javascript\ncomponent definition. For many simple authoring use-cases, just having a template that should appear is all that web\nauthors need. This library gives you an easy and elegant way to do that, without the boilerplate or complexities\nassociated with building javascript class definitions.\n\n## How to use\n\nYou can include ShadowRoot Injector by using a CDN of your choice.\n\n```html\n\u003cscript src=\"https://unpkg.com/shadowroot-injector@2\"\u003e\u003c/script\u003e\n```\n\nYou can also use the minified version by pointing to the minified asset\n\n```html\n\u003cscript src=\"https://unpkg.com/shadowroot-injector@2/shadowroot-injector.min.js\"\u003e\u003c/script\u003e\n```\n\n### HTML API\n\nThe HTML API is completely driven by attributes on the `\u003cshadowroot-for\u003e` web component. When you include both of the\nfollowing attributes, ShadowRoot Injector will automatically kick off and register a child template node to be used for\nnew and existing elements in the document.\n\n\u003cdl\u003e\n  \u003cdt\u003e\u003ccode\u003eselector\u003c/code\u003e\u003c/dt\u003e\n  \u003cdd\u003eThe CSS selector to look for to attach shadow roots on. When these elements appear in the DOM, we'll automatically inject a template into them. The selector must point to an element that can accept shadow roots (see \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#elements_you_can_attach_a_shadow_to\"\u003eElements you can attach a shadow root to\u003c/a\u003e).\u003c/dd\u003e\n\n  \u003cdt\u003e\u003ccode\u003emode\u003c/code\u003e\u003c/dt\u003e\n  \u003cdd\u003eThe \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/mode\"\u003eShadowRoot mode property\u003c/a\u003e. This must be defined as a valid value for ShadowRoot modes, either \u003ccode\u003eopen\u003c/code\u003e or \u003ccode\u003eclosed\u003c/code\u003e.\u003c/dd\u003e\n\u003c/dl\u003e\n\nYou may also include any valid\n[ShadowRoot template properties](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/template#attributes)\non the child template element. This includes `shadowrootdelegatesfocus`, `shadowrootclonable`, or even\n`shadowrootcustomelementregistry`.\n\n### JS API\n\nWhile not required, you can use the JavaScript API to interface directly with a ShadowRoot Injector instance. This can\nalso be useful when you need to control when the shadow root is injected in defined web components.\n\nAll the API methods below are method calls you can make on an instance of the `ShadowRootInjector` class.\n\n```html\n\u003cshadowroot-for id=\"injector\" mode=\"open\"\u003e ... \u003c/shadowroot-for\u003e\n\u003cdiv id=\"myTestNode\"\u003e\u003c/div\u003e\n\n\u003cscript\u003e\n  injector.injectRegisteredTemplate(myTestNode);\n\u003c/script\u003e\n```\n\n\u003cdl\u003e\n  \u003cdt\u003e\u003ccode\u003eshadowRootInjector.injectRegisteredTemplate(node: HTMLElement)\u003c/code\u003e\u003c/dt\u003e\n  \u003cdd\u003eThis function takes in an HTML Element, and injects the ShadowRoot template associated with the existing instance of the shadow root injector.\u003c/dd\u003e\n\u003c/dl\u003e\n\n## Task List Example\n\nTo see these APIs come together, lets look at a more complex Task List example, step by step (you can see the entire\nfile in `example/task-list.html`). You can see it live on [codepen](https://codepen.io/JRJurman/pen/JoYGrpe).\n\nFirst, we'll import the library and build a template definition for a single `task-item`. It has some styles, and some\nbasic markup.\n\n```html\n\u003cscript src=\"https://unpkg.com/shadowroot-injector@2\"\u003e\u003c/script\u003e\n\n\u003cshadowroot-for selector=\"task-item\" mode=\"open\"\u003e\n  \u003ctemplate\u003e\n    \u003cstyle\u003e\n      :host {\n        display: list-item;\n      }\n      li {\n        display: flex;\n        gap: 12px;\n      }\n    \u003c/style\u003e\n    \u003cli\u003e\n      \u003cslot\u003e\u003c/slot\u003e\n      \u003cbutton\u003eremove\u003c/button\u003e\n    \u003c/li\u003e\n  \u003c/template\u003e\n\u003c/shadowroot-for\u003e\n```\n\nWe'll create a list to hold some hard-coded task items.\n\n```html\n\u003cul id=\"taskList\"\u003e\n  \u003ctask-item\u003eAdd Items\u003c/task-item\u003e\n  \u003ctask-item\u003eRemove Items\u003c/task-item\u003e\n\u003c/ul\u003e\n```\n\nIf we stopped here, the task items would present as we'd expect, but wouldn't be interactive. To make it interactive,\nwe'll upgrade our `task-item` custom element into a web component, with event listeners and all. Any existing\n`task-item` elements in the page will upgrade automatically.\n\n\u003c!-- prettier-ignore --\u003e\n\u003e [!important]\n\u003e In the `connectedCallback`, we call `shadowRootInjector.injectRegisteredTemplate(this);`. By doing this,\n\u003e we'll ensure that we have access to shadowRoot elements for the rest of the function.\n\n```html\n\u003cscript\u003e\n  const taskItemShadowRootInjector = document.querySelector('shadowroot-for[selector=\"task-item\"]');\n\n  customElements.define(\n    'task-item',\n    class extends HTMLElement {\n      connectedCallback() {\n        taskItemShadowRootInjector.injectRegisteredTemplate(this);\n        this.shadowRoot.querySelector('button').addEventListener('click', () =\u003e {\n          this.remove();\n        });\n      }\n    },\n  );\n\u003c/script\u003e\n```\n\nFinally we add a control to create new `task-item` elements. Any new `task-items` created will be defined by the class\ndefinition above.\n\n\u003c!-- prettier-ignore --\u003e\n\u003e [!note]\n\u003e If we hadn't called `taskItemShadowRootInjector.injectRegisteredTemplate` directly, the ShadowRootInjector library would still\n\u003e inject shadowRoot templates after the element was attached to the page.\n\n```html\n\u003clabel\u003e\n  Add Task\n  \u003cinput id=\"addTaskInput\" type=\"text\" /\u003e\n\u003c/label\u003e\n\n\u003cscript\u003e\n  addTaskInput.addEventListener('keyup', (event) =\u003e {\n    if (event.code === 'Enter') {\n      const newListItem = document.createElement('task-item');\n      newListItem.textContent = addTaskInput.value;\n      addTaskInput.value = '';\n      taskList.append(newListItem);\n    }\n  });\n\u003c/script\u003e\n```\n\n## Contributions / Discussions\n\nIf you think this is useful or interesting, I'd love to hear your thoughts! Feel free to\n[reach out to me on mastodon](https://fosstodon.org/@jrjurman), or join the\n[Tram-One discord](https://discord.gg/dpBXAQC).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftram-one%2Fshadowroot-injector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftram-one%2Fshadowroot-injector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftram-one%2Fshadowroot-injector/lists"}