diff --git a/.gitignore b/.gitignore index 2fba6111f..443c90e76 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ spacedrive .cargo/config .cargo/config.toml .github/scripts/deps +.vite-inspect diff --git a/apps/landing/src/app/Footer.tsx b/apps/landing/src/app/Footer.tsx index 4f3dd5efe..3c865d5ae 100644 --- a/apps/landing/src/app/Footer.tsx +++ b/apps/landing/src/app/Footer.tsx @@ -25,7 +25,7 @@ export function Footer() { style={{ width: '100%', height: '400px' }} sizes="100vw" /> -
+
Spacedrive logo diff --git a/apps/landing/src/components/Footer.tsx b/apps/landing/src/components/Footer.tsx index a1e882b9a..e270dba29 100644 --- a/apps/landing/src/components/Footer.tsx +++ b/apps/landing/src/components/Footer.tsx @@ -43,7 +43,7 @@ export function Footer() { style={{ width: '100%', height: '400px' }} sizes="100vw" /> -
+
Spacedrive logo 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