diff --git a/apps/mobile/src/components/browse/BrowseLocations.tsx b/apps/mobile/src/components/browse/BrowseLocations.tsx
index b6e33c039..658939ddb 100644
--- a/apps/mobile/src/components/browse/BrowseLocations.tsx
+++ b/apps/mobile/src/components/browse/BrowseLocations.tsx
@@ -41,7 +41,7 @@ const BrowseLocationItem: React.FC
= ({
-
+
@@ -97,17 +97,17 @@ const BrowseLocations = () => {
return (
-
+
Locations
-
+
modalRef.current?.present()}>
diff --git a/apps/mobile/src/components/browse/BrowseTags.tsx b/apps/mobile/src/components/browse/BrowseTags.tsx
index bbb07c0a1..d5b3553af 100644
--- a/apps/mobile/src/components/browse/BrowseTags.tsx
+++ b/apps/mobile/src/components/browse/BrowseTags.tsx
@@ -62,17 +62,17 @@ const BrowseTags = () => {
return (
-
+
Tags
-
+
modalRef.current?.present()}>
diff --git a/apps/mobile/src/components/browse/Categories.tsx b/apps/mobile/src/components/browse/Categories.tsx
index 717f6e605..1b08da4c8 100644
--- a/apps/mobile/src/components/browse/Categories.tsx
+++ b/apps/mobile/src/components/browse/Categories.tsx
@@ -29,7 +29,7 @@ const CATEGORIES_LIST = [
const Categories = () => {
return (
- Library
+ Library
diff --git a/apps/mobile/src/components/browse/Jobs.tsx b/apps/mobile/src/components/browse/Jobs.tsx
index a4a5cf990..627e5cd35 100644
--- a/apps/mobile/src/components/browse/Jobs.tsx
+++ b/apps/mobile/src/components/browse/Jobs.tsx
@@ -10,7 +10,7 @@ import Fade from '../layout/Fade';
const Jobs = () => {
return (
-
+
Jobs
@@ -48,15 +48,15 @@ const Job = ({ progress, message, error }: JobProps) => {
style={tw`h-fit w-[310px] flex-col rounded-md border border-sidebar-line/50 bg-sidebar-box`}
>
- Added Memories
+ Added Memories
-
+
+
+ Hello from Solid: {count()}
+
+ );
+}
+
+export function renderDemo(element: HTMLDivElement): () => void {
+ return render(Demo, element);
+}
diff --git a/interface/app/index.tsx b/interface/app/index.tsx
index 48c1022c9..5794d8400 100644
--- a/interface/app/index.tsx
+++ b/interface/app/index.tsx
@@ -1,10 +1,11 @@
-import { useMemo } from 'react';
+import { useEffect, useMemo, useRef } from 'react';
import { Navigate, Outlet, redirect, useMatches, type RouteObject } from 'react-router-dom';
import {
currentLibraryCache,
getCachedLibraries,
NormalisedCache,
- useCachedLibraries
+ useCachedLibraries,
+ useFeatureFlag
} from '@sd/client';
import { Dialogs, Toaster } from '@sd/ui';
import { RouterErrorBoundary } from '~/ErrorFallback';
@@ -12,11 +13,24 @@ import { useRoutingContext } from '~/RoutingContext';
import { Platform } from '..';
import libraryRoutes from './$libraryId';
+import { renderDemo } from './demo.solid';
import onboardingRoutes from './onboarding';
import { RootContext } from './RootContext';
import './style.scss';
+function RenderSolid() {
+ const ref = useRef
(null);
+
+ useEffect(() => {
+ let cleanup = () => {};
+ if (ref.current) cleanup = renderDemo(ref.current);
+ return cleanup;
+ }, []);
+
+ return ;
+}
+
// NOTE: all route `Layout`s below should contain
// the `usePlausiblePageViewMonitor` hook, as early as possible (ideally within the layout itself).
// the hook should only be included if there's a valid `ClientContext` (so not onboarding)
@@ -29,6 +43,7 @@ export const createRoutes = (platform: Platform, cache: NormalisedCache) =>
return (
+ {useFeatureFlag('solidJsDemo') ? : null}
diff --git a/interface/package.json b/interface/package.json
index 60436017a..e4eba1e33 100644
--- a/interface/package.json
+++ b/interface/package.json
@@ -58,6 +58,7 @@
"react-use-draggable-scroll": "^0.4.7",
"remix-params-helper": "^0.4.10",
"rooks": "^7.14.1",
+ "solid-js": "^1.8.8",
"use-count-up": "^3.0.1",
"use-debounce": "^9.0.4",
"use-resize-observer": "^9.1.0",
diff --git a/packages/client/src/hooks/useFeatureFlag.tsx b/packages/client/src/hooks/useFeatureFlag.tsx
index 0890885e0..cd352490a 100644
--- a/packages/client/src/hooks/useFeatureFlag.tsx
+++ b/packages/client/src/hooks/useFeatureFlag.tsx
@@ -10,6 +10,7 @@ export const features = [
'p2pPairing',
'backups',
'debugRoutes',
+ 'solidJsDemo',
'hostedLocations'
] as const;
diff --git a/packages/config/base.tsconfig.json b/packages/config/base.tsconfig.json
index be3ed9350..a7ea1783c 100644
--- a/packages/config/base.tsconfig.json
+++ b/packages/config/base.tsconfig.json
@@ -3,7 +3,7 @@
"display": "Default",
"compilerOptions": {
"strict": true,
- "jsx": "react-jsx",
+ "jsx": "preserve",
"esModuleInterop": true,
"skipLibCheck": true,
"preserveWatchOutput": true,
diff --git a/packages/config/eslint/base.js b/packages/config/eslint/base.js
index c6bfcf360..1d4f11eac 100644
--- a/packages/config/eslint/base.js
+++ b/packages/config/eslint/base.js
@@ -10,20 +10,13 @@ module.exports = {
},
extends: [
'eslint:recommended',
- 'plugin:react/recommended',
- 'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/recommended',
'turbo',
- 'prettier'
+ 'prettier',
+ require.resolve('./react.js'),
+ require.resolve('./solid.js')
],
- plugins: ['react'],
rules: {
- 'react/display-name': 'off',
- 'react/prop-types': 'off',
- 'react/no-unescaped-entities': 'off',
- 'react/react-in-jsx-scope': 'off',
- 'react-hooks/rules-of-hooks': 'warn',
- 'react-hooks/exhaustive-deps': 'warn',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-explicit-any': 'off',
@@ -42,10 +35,5 @@ module.exports = {
}
]
},
- ignorePatterns: ['dist', '**/*.js', '**/*.cjs', '**/*.json', 'node_modules'],
- settings: {
- react: {
- version: 'detect'
- }
- }
+ ignorePatterns: ['dist', '**/*.js', '**/*.json', 'node_modules']
};
diff --git a/packages/config/eslint/react.js b/packages/config/eslint/react.js
new file mode 100644
index 000000000..87a85ddc3
--- /dev/null
+++ b/packages/config/eslint/react.js
@@ -0,0 +1,23 @@
+module.exports = {
+ plugins: ['react'],
+ overrides: [
+ {
+ files: ['**/*.tsx'],
+ excludedFiles: '*.solid.tsx',
+ extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
+ rules: {
+ 'react/display-name': 'off',
+ 'react/prop-types': 'off',
+ 'react/no-unescaped-entities': 'off',
+ 'react/react-in-jsx-scope': 'off',
+ 'react-hooks/rules-of-hooks': 'warn',
+ 'react-hooks/exhaustive-deps': 'warn'
+ }
+ }
+ ],
+ settings: {
+ react: {
+ version: 'detect'
+ }
+ }
+};
diff --git a/packages/config/eslint/solid.js b/packages/config/eslint/solid.js
new file mode 100644
index 000000000..519b2fd59
--- /dev/null
+++ b/packages/config/eslint/solid.js
@@ -0,0 +1,14 @@
+module.exports = {
+ plugins: ['solid'],
+ overrides: [
+ {
+ files: ['**/*.solid.tsx'],
+ extends: ['plugin:solid/recommended'],
+ rules: {
+ 'solid/reactivity': 'warn',
+ 'solid/no-destructure': 'warn',
+ 'solid/jsx-no-undef': 'error'
+ }
+ }
+ ]
+};
diff --git a/packages/config/package.json b/packages/config/package.json
index 37d9fa3e2..62ccad256 100644
--- a/packages/config/package.json
+++ b/packages/config/package.json
@@ -13,6 +13,7 @@
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1",
+ "@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^8.53.0",
"eslint-config-next": "^13.5.6",
"eslint-config-prettier": "^9.0.0",
@@ -20,11 +21,13 @@
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-solid": "^0.13.1",
"eslint-plugin-tailwindcss": "^3.13.0",
"eslint-utils": "^3.0.0",
"regexpp": "^3.2.0",
"vite-plugin-html": "^3.2.1",
- "vite-plugin-svgr": "^3.3.0",
- "@vitejs/plugin-react-swc": "^3.5.0"
+ "vite-plugin-inspect": "^0.8.1",
+ "vite-plugin-solid": "^2.8.0",
+ "vite-plugin-svgr": "^3.3.0"
}
}
diff --git a/packages/config/vite/index.ts b/packages/config/vite/index.ts
index e231a2115..24d59934f 100644
--- a/packages/config/vite/index.ts
+++ b/packages/config/vite/index.ts
@@ -4,11 +4,13 @@ import { createHtmlPlugin } from 'vite-plugin-html';
import svg from 'vite-plugin-svgr';
import tsconfigPaths from 'vite-tsconfig-paths';
+import { narrowSolidPlugin } from './narrowSolidPlugin';
+
export default defineConfig({
plugins: [
tsconfigPaths(),
- // @ts-expect-error
react(),
+ narrowSolidPlugin({ include: '**/*.solid.tsx' }),
svg({ svgrOptions: { icon: true } }),
createHtmlPlugin({
minify: true
diff --git a/packages/config/vite/narrowSolidPlugin.ts b/packages/config/vite/narrowSolidPlugin.ts
new file mode 100644
index 000000000..425970ff5
--- /dev/null
+++ b/packages/config/vite/narrowSolidPlugin.ts
@@ -0,0 +1,39 @@
+// Source: https://github.com/merged-js/react-solid/blob/master/src/narrowSolidPlugin.ts
+//
+// We vendor it due to: https://github.com/merged-js/react-solid/issues/1
+//
+
+import { createFilter } from '@rollup/pluginutils';
+import solidPlugin, { Options } from 'vite-plugin-solid';
+
+export interface NarrowSolidPluginOptions extends Partial {
+ include?: string | RegExp | Array | Array;
+ exclude?: string | RegExp | Array | Array;
+}
+
+export function narrowSolidPlugin({ include, exclude, ...rest }: NarrowSolidPluginOptions = {}) {
+ const plugin = solidPlugin(rest);
+ const originalConfig = plugin.config!.bind(plugin);
+ const filter = createFilter(include, exclude);
+ plugin.config = (...args) => {
+ const baseConfig = originalConfig(...args);
+ return {
+ ...baseConfig,
+ esbuild: {
+ include: exclude,
+ exclude: include
+ }
+ };
+ };
+
+ const originalTransform = (plugin.transform! as any).bind(plugin);
+ plugin.transform = (source, id, ssr) => {
+ if (!filter(id)) {
+ return null;
+ }
+
+ return originalTransform(source, id, ssr);
+ };
+
+ return plugin;
+}
diff --git a/packages/config/vite/relativeAliasResolver.ts b/packages/config/vite/relativeAliasResolver.ts
index bd22ed89d..4af71d5a9 100644
--- a/packages/config/vite/relativeAliasResolver.ts
+++ b/packages/config/vite/relativeAliasResolver.ts
@@ -1,3 +1,4 @@
+/* eslint-disable */
// BE REALLY DAMN CAREFUL MODIFYING THIS FILE: https://github.com/spacedriveapp/spacedrive/pull/1353
import fs from 'fs/promises';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7984aa0c6..e109bc3aa 100644
Binary files a/pnpm-lock.yaml and b/pnpm-lock.yaml differ