feat: inline chrome-extension-toolkit (#744)

* feat(build): inline chrome-extension-toolkit

fix: tsconfig

docs: add chrome-extension-toolkit README.md

chore: update imports

fix: stores

fix: chrome-extension-toolkit ForegroundMessenger

fix: calendarBackgroundHandler

fix: format and lint

fix: path alias

fix: add jsdom env and fix imports

Co-authored-by: Sriram Hariharan <sghsri@gmail.com>

* build: vite storybook config crx toolkit line

---------

Co-authored-by: Sriram Hariharan <sghsri@gmail.com>
Co-authored-by: Derek <derex1987@gmail.com>
This commit is contained in:
Diego Perez
2026-02-11 00:50:27 -06:00
committed by GitHub
parent d5954410a7
commit a537d17a2f
67 changed files with 1833 additions and 92 deletions

View File

@@ -0,0 +1,55 @@
/**
* An extension of HTMLDivElement that represents a shadow root for use within an Extension Content Script.
*/
interface HTMLShadowDOMElement extends HTMLDivElement {
shadowRoot: ShadowRoot & {
INJECTION_POINT: HTMLDivElement;
};
/**
* Adds a style sheet to the shadow root.
* @param path the path to the style sheet relative to the extension's root directory. uses chrome.runtime.getURL to get the absolute path.
*/
addStyle(path: string): Promise<void>;
}
/**
* In extension content scripts, often times the parent site's styles will override the styles of the extension.
* To get around this, we create a shadow DOM and isolate the extension's html and styles in the shadow DOM.
* from the parent site's styles to prevent conflicts.
* @param id the id of the shadow root.
* @param options the optional options for the shadow root.
* @param isolate whether or not to isolate the extension's document flow from the parent site's document flow.
* @returns A Div that represents the shadow root with some additional methods added to it.
*/
export function createShadowDOM(id: string, options?: ShadowRootInit, isolate = false): HTMLShadowDOMElement {
const html = document.querySelector('html');
if (!html) {
throw new Error('Could not find html element');
}
const div = document.createElement('div') as HTMLShadowDOMElement;
div.id = id;
div.style.all = 'initial';
div.attachShadow({
mode: 'open',
...(options || {}),
});
const INJECTION_POINT = document.createElement('div');
INJECTION_POINT.id = 'INJECTION_POINT';
div.shadowRoot.appendChild(INJECTION_POINT);
div.shadowRoot.INJECTION_POINT = INJECTION_POINT;
div.addStyle = async (path: string) => {
const style = await fetch(chrome.runtime.getURL(path));
const styleNode = document.createElement('style');
const parsedStyle = await style.text();
styleNode.textContent = parsedStyle;
div.shadowRoot.appendChild(styleNode);
};
html.appendChild(div);
if (isolate) document.body.style.isolation = 'isolate';
return div as HTMLShadowDOMElement;
}

View File

@@ -0,0 +1 @@
export * from './createShadowRoot';