diff --git a/packages/module-react/build.config.ts b/packages/module-react/build.config.ts
new file mode 100644
index 00000000..e4a0fd75
--- /dev/null
+++ b/packages/module-react/build.config.ts
@@ -0,0 +1,12 @@
+import { defineBuildConfig } from 'unbuild';
+import { resolve } from 'node:path';
+
+export default defineBuildConfig({
+ rootDir: 'modules',
+ outDir: resolve(__dirname, 'dist'),
+ entries: [{ input: 'react.ts', name: 'index' }],
+ rollup: {
+ emitCJS: true,
+ },
+ declaration: true,
+});
diff --git a/packages/module-react/components/App.tsx b/packages/module-react/components/App.tsx
new file mode 100644
index 00000000..2124b612
--- /dev/null
+++ b/packages/module-react/components/App.tsx
@@ -0,0 +1,5 @@
+export default function () {
+ const [count, setCount] = useState(0);
+ const increment = () => setCount((count) => count + 1);
+ return ;
+}
diff --git a/packages/module-react/entrypoints/content/index.tsx b/packages/module-react/entrypoints/content/index.tsx
new file mode 100644
index 00000000..34f4ae19
--- /dev/null
+++ b/packages/module-react/entrypoints/content/index.tsx
@@ -0,0 +1,33 @@
+import { defineContentScript } from 'wxt/sandbox';
+import { ContentScriptContext, createShadowRootUi } from 'wxt/client';
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+
+export default defineContentScript({
+ matches: ['*://*/*'],
+
+ async main(ctx) {
+ const ui = await createUi(ctx);
+ ui.mount();
+ },
+});
+
+function createUi(ctx: ContentScriptContext) {
+ return createShadowRootUi(ctx, {
+ name: 'react-ui',
+ position: 'inline',
+ append: 'first',
+ onMount(container) {
+ const root = ReactDOM.createRoot(container);
+ root.render(
+
+
+ ,
+ );
+ return root;
+ },
+ onRemove(root) {
+ root?.unmount();
+ },
+ });
+}
diff --git a/packages/module-react/entrypoints/popup/index.html b/packages/module-react/entrypoints/popup/index.html
new file mode 100644
index 00000000..cc7ec196
--- /dev/null
+++ b/packages/module-react/entrypoints/popup/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
diff --git a/packages/module-react/entrypoints/popup/main.tsx b/packages/module-react/entrypoints/popup/main.tsx
new file mode 100644
index 00000000..227f35e4
--- /dev/null
+++ b/packages/module-react/entrypoints/popup/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+
+const root = document.getElementById('app')!;
+
+ReactDOM.createRoot(root).render(
+
+
+ ,
+);
diff --git a/packages/module-react/src/index.ts b/packages/module-react/modules/react.ts
similarity index 64%
rename from packages/module-react/src/index.ts
rename to packages/module-react/modules/react.ts
index 5ed81587..111db775 100644
--- a/packages/module-react/src/index.ts
+++ b/packages/module-react/modules/react.ts
@@ -13,6 +13,17 @@ export default defineWxtModule({
}));
addImportPreset(wxt, 'react');
+
+ // Enable auto-imports for JSX files
+ wxt.hooks.hook('ready', (wxt) => {
+ if (wxt.config.imports === false) return;
+
+ wxt.config.imports.dirsScanOptions ??= {};
+ wxt.config.imports.dirsScanOptions.filePatterns = [
+ // Default plus JSX/TSX
+ '*.{ts,js,mjs,cjs,mts,cts,jsx,tsx}',
+ ];
+ });
},
});
diff --git a/packages/module-react/package.json b/packages/module-react/package.json
index bdf716a7..81160ef5 100644
--- a/packages/module-react/package.json
+++ b/packages/module-react/package.json
@@ -21,8 +21,10 @@
"dist"
],
"scripts": {
+ "dev": "wxt",
+ "check": "buildc --deps-only -- check",
"build": "buildc -- unbuild",
- "check": "buildc --deps-only -- check"
+ "postinstall": "buildc --deps-only -- wxt prepare"
},
"peerDependencies": {
"wxt": ">=0.18.6"
@@ -32,7 +34,11 @@
},
"devDependencies": {
"@aklinker1/check": "^1.3.1",
+ "@types/react": "^18.3.0",
+ "@types/react-dom": "^18.3.0",
"publint": "^0.2.8",
+ "react": "^18.3.0",
+ "react-dom": "^18.3.0",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
diff --git a/packages/module-react/public/.keep b/packages/module-react/public/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/module-react/tsconfig.json b/packages/module-react/tsconfig.json
index 9b2dc061..a3ad2c35 100644
--- a/packages/module-react/tsconfig.json
+++ b/packages/module-react/tsconfig.json
@@ -1,4 +1,8 @@
{
- "extends": "../../tsconfig.base.json",
+ "extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
+ "compilerOptions": {
+ "allowImportingTsExtensions": true,
+ "jsx": "react-jsx"
+ },
"exclude": ["node_modules/**", "dist/**"]
}
diff --git a/packages/module-solid/build.config.ts b/packages/module-solid/build.config.ts
new file mode 100644
index 00000000..72314998
--- /dev/null
+++ b/packages/module-solid/build.config.ts
@@ -0,0 +1,12 @@
+import { defineBuildConfig } from 'unbuild';
+import { resolve } from 'node:path';
+
+export default defineBuildConfig({
+ rootDir: 'modules',
+ outDir: resolve(__dirname, 'dist'),
+ entries: [{ input: 'solid.ts', name: 'index' }],
+ rollup: {
+ emitCJS: true,
+ },
+ declaration: true,
+});
diff --git a/packages/module-solid/components/App.tsx b/packages/module-solid/components/App.tsx
new file mode 100644
index 00000000..c7c50c6c
--- /dev/null
+++ b/packages/module-solid/components/App.tsx
@@ -0,0 +1,7 @@
+import { Component } from 'solid-js';
+
+export const App: Component = () => {
+ const [count, setCount] = createSignal(0);
+ const increment = () => setCount((count) => count + 1);
+ return ;
+};
diff --git a/packages/module-solid/entrypoints/content/index.tsx b/packages/module-solid/entrypoints/content/index.tsx
new file mode 100644
index 00000000..7c2f0e7c
--- /dev/null
+++ b/packages/module-solid/entrypoints/content/index.tsx
@@ -0,0 +1,26 @@
+import { defineContentScript } from 'wxt/sandbox';
+import { ContentScriptContext, createShadowRootUi } from 'wxt/client';
+import { render } from 'solid-js/web';
+
+export default defineContentScript({
+ matches: ['*://*/*'],
+
+ async main(ctx) {
+ const ui = await createUi(ctx);
+ ui.mount();
+ },
+});
+
+function createUi(ctx: ContentScriptContext) {
+ return createShadowRootUi(ctx, {
+ name: 'solid-ui',
+ position: 'inline',
+ append: 'first',
+ onMount(container) {
+ return render(() => , container);
+ },
+ onRemove(unmount) {
+ unmount?.();
+ },
+ });
+}
diff --git a/packages/module-solid/entrypoints/popup/index.html b/packages/module-solid/entrypoints/popup/index.html
new file mode 100644
index 00000000..cc7ec196
--- /dev/null
+++ b/packages/module-solid/entrypoints/popup/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
diff --git a/packages/module-solid/entrypoints/popup/main.tsx b/packages/module-solid/entrypoints/popup/main.tsx
new file mode 100644
index 00000000..b01fabf5
--- /dev/null
+++ b/packages/module-solid/entrypoints/popup/main.tsx
@@ -0,0 +1,5 @@
+import { render } from 'solid-js/web';
+
+const root = document.getElementById('app')!;
+
+render(() => , root);
diff --git a/packages/module-solid/src/index.ts b/packages/module-solid/modules/solid.ts
similarity index 66%
rename from packages/module-solid/src/index.ts
rename to packages/module-solid/modules/solid.ts
index 0a60e295..0309054c 100644
--- a/packages/module-solid/src/index.ts
+++ b/packages/module-solid/modules/solid.ts
@@ -16,6 +16,17 @@ export default defineWxtModule({
}));
addImportPreset(wxt, 'solid-js');
+
+ // Enable auto-imports for JSX files
+ wxt.hooks.hook('ready', (wxt) => {
+ if (wxt.config.imports === false) return;
+
+ wxt.config.imports.dirsScanOptions ??= {};
+ wxt.config.imports.dirsScanOptions.filePatterns = [
+ // Default plus JSX/TSX
+ '*.{ts,js,mjs,cjs,mts,cts,jsx,tsx}',
+ ];
+ });
},
});
diff --git a/packages/module-solid/package.json b/packages/module-solid/package.json
index edf4a06d..b1b11f31 100644
--- a/packages/module-solid/package.json
+++ b/packages/module-solid/package.json
@@ -21,8 +21,10 @@
"dist"
],
"scripts": {
+ "dev": "wxt",
+ "check": "buildc --deps-only -- check",
"build": "buildc -- unbuild",
- "check": "buildc --deps-only -- check"
+ "postinstall": "buildc --deps-only -- wxt prepare"
},
"peerDependencies": {
"wxt": ">=0.18.6"
@@ -33,6 +35,7 @@
"devDependencies": {
"@aklinker1/check": "^1.3.1",
"publint": "^0.2.8",
+ "solid-js": "^1.8.17",
"typescript": "^5.4.5",
"unbuild": "^2.0.0",
"wxt": "workspace:*"
diff --git a/packages/module-solid/public/.keep b/packages/module-solid/public/.keep
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/module-solid/tsconfig.json b/packages/module-solid/tsconfig.json
index 9b2dc061..add4a7d4 100644
--- a/packages/module-solid/tsconfig.json
+++ b/packages/module-solid/tsconfig.json
@@ -1,4 +1,8 @@
{
- "extends": "../../tsconfig.base.json",
+ "extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
+ "compilerOptions": {
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js"
+ },
"exclude": ["node_modules/**", "dist/**"]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f239151a..51ab3da0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -99,9 +99,21 @@ importers:
'@aklinker1/check':
specifier: ^1.3.1
version: 1.3.1(typescript@5.4.5)
+ '@types/react':
+ specifier: ^18.3.0
+ version: 18.3.3
+ '@types/react-dom':
+ specifier: ^18.3.0
+ version: 18.3.0
publint:
specifier: ^0.2.8
version: 0.2.8
+ react:
+ specifier: ^18.3.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.0
+ version: 18.3.1(react@18.3.1)
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -124,6 +136,9 @@ importers:
publint:
specifier: ^0.2.8
version: 0.2.8
+ solid-js:
+ specifier: ^1.8.17
+ version: 1.8.17
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -4700,7 +4715,6 @@ packages:
hasBin: true
dependencies:
js-tokens: 4.0.0
- dev: false
/loupe@2.3.7:
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
@@ -5887,7 +5901,6 @@ packages:
loose-envify: 1.4.0
react: 18.3.1
scheduler: 0.23.2
- dev: false
/react-is@18.2.0:
resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==}
@@ -5903,7 +5916,6 @@ packages:
engines: {node: '>=0.10.0'}
dependencies:
loose-envify: 1.4.0
- dev: false
/read-pkg@3.0.0:
resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}
@@ -6136,7 +6148,6 @@ packages:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
dependencies:
loose-envify: 1.4.0
- dev: false
/scule@1.3.0:
resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
@@ -6176,12 +6187,10 @@ packages:
seroval: ^1.0
dependencies:
seroval: 1.0.7
- dev: false
/seroval@1.0.7:
resolution: {integrity: sha512-n6ZMQX5q0Vn19Zq7CIKNIo7E75gPkGCFUEqDpa8jgwpYr/vScjqnQ6H09t1uIiZ0ZSK0ypEGvrYK2bhBGWsGdw==}
engines: {node: '>=10'}
- dev: false
/set-value@4.1.0:
resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==}
@@ -6308,7 +6317,6 @@ packages:
csstype: 3.1.3
seroval: 1.0.7
seroval-plugins: 1.0.7(seroval@1.0.7)
- dev: false
/solid-refresh@0.6.3(solid-js@1.8.17):
resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==}