SolidJS Build Infrastructure (#1919)

* backport changes from #1913

* Make ESLint play nice

* eslint fix

---------

Co-authored-by: Brendan Allan <brendonovich@outlook.com>
This commit is contained in:
Oscar Beaumont 2024-01-08 14:20:20 +08:00 committed by GitHub
parent b6ea70b8d0
commit 49bdbc4b60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 852 additions and 205 deletions

1
.gitignore vendored
View file

@ -81,3 +81,4 @@ spacedrive
.cargo/config
.cargo/config.toml
.github/scripts/deps
.vite-inspect

View file

@ -25,7 +25,7 @@ export function Footer() {
style={{ width: '100%', height: '400px' }}
sizes="100vw"
/>
<div className="min-h-64 m-auto grid max-w-[100rem] grid-cols-2 gap-6 p-8 pb-20 pt-10 text-white sm:grid-cols-2 lg:grid-cols-6">
<div className="m-auto grid min-h-64 max-w-[100rem] grid-cols-2 gap-6 p-8 pb-20 pt-10 text-white sm:grid-cols-2 lg:grid-cols-6">
<div className="col-span-2">
<Image alt="Spacedrive logo" src={Logo} className="mb-5 h-10 w-10" />

View file

@ -43,7 +43,7 @@ export function Footer() {
style={{ width: '100%', height: '400px' }}
sizes="100vw"
/>
<div className="min-h-64 m-auto grid max-w-[100rem] grid-cols-2 gap-6 p-8 pb-20 pt-10 text-white sm:grid-cols-2 lg:grid-cols-6">
<div className="m-auto grid min-h-64 max-w-[100rem] grid-cols-2 gap-6 p-8 pb-20 pt-10 text-white sm:grid-cols-2 lg:grid-cols-6">
<div className="col-span-2">
<Image alt="Spacedrive logo" src={Logo} className="mb-5 h-10 w-10" />

View file

@ -41,7 +41,7 @@ const BrowseLocationItem: React.FC<BrowseLocationItemProps> = ({
<View
style={tw`h-fit w-[100px] flex-col justify-center gap-3 rounded-md border border-sidebar-line/50 bg-sidebar-box p-2`}
>
<View style={tw`flex-col justify-between w-full gap-1`}>
<View style={tw`w-full flex-col justify-between gap-1`}>
<View style={tw`flex-row items-center justify-between`}>
<View style={tw`relative`}>
<FolderIcon size={42} />
@ -97,17 +97,17 @@ const BrowseLocations = () => {
return (
<View style={tw`gap-5`}>
<View style={tw`flex-row items-center justify-between w-full px-7`}>
<View style={tw`w-full flex-row items-center justify-between px-7`}>
<Text style={tw`text-xl font-bold text-white`}>Locations</Text>
<View style={tw`flex-row gap-3`}>
<Pressable>
<View style={tw`items-center justify-center w-8 h-8 rounded-md bg-accent`}>
<View style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent`}>
<Eye weight="bold" size={18} style={tw`text-white`} />
</View>
</Pressable>
<Pressable onPress={() => modalRef.current?.present()}>
<View
style={tw`items-center justify-center w-8 h-8 bg-transparent border border-dashed rounded-md border-ink-faint`}
style={tw`h-8 w-8 items-center justify-center rounded-md border border-dashed border-ink-faint bg-transparent`}
>
<Plus weight="bold" size={18} style={tw`text-ink-faint`} />
</View>

View file

@ -62,17 +62,17 @@ const BrowseTags = () => {
return (
<View style={tw`gap-5`}>
<View style={tw`flex-row items-center justify-between w-full px-7`}>
<View style={tw`w-full flex-row items-center justify-between px-7`}>
<Text style={tw`text-xl font-bold text-white`}>Tags</Text>
<View style={tw`flex-row gap-3`}>
<Pressable>
<View style={tw`items-center justify-center w-8 h-8 rounded-md bg-accent`}>
<View style={tw`h-8 w-8 items-center justify-center rounded-md bg-accent`}>
<Eye weight="bold" size={18} style={tw`text-white`} />
</View>
</Pressable>
<Pressable testID="add-tag" onPress={() => modalRef.current?.present()}>
<View
style={tw`items-center justify-center w-8 h-8 bg-transparent border border-dashed rounded-md border-ink-faint`}
style={tw`h-8 w-8 items-center justify-center rounded-md border border-dashed border-ink-faint bg-transparent`}
>
<Plus weight="bold" size={18} style={tw`text-ink-faint`} />
</View>

View file

@ -29,7 +29,7 @@ const CATEGORIES_LIST = [
const Categories = () => {
return (
<View style={tw`relative gap-5`}>
<Text style={tw`text-xl font-bold text-white px-7`}>Library</Text>
<Text style={tw`px-7 text-xl font-bold text-white`}>Library</Text>
<Fade width={30} height="100%" color="mobile-screen">
<ScrollView showsHorizontalScrollIndicator={false} horizontal>
<View style={tw`flex-row gap-2 px-7`}>

View file

@ -10,7 +10,7 @@ import Fade from '../layout/Fade';
const Jobs = () => {
return (
<View style={tw`gap-5`}>
<View style={tw`flex-row items-center justify-between w-full px-7`}>
<View style={tw`w-full flex-row items-center justify-between px-7`}>
<Text style={tw`text-xl font-bold text-white`}>Jobs</Text>
</View>
<Fade color="mobile-screen" height="100%" width={30}>
@ -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`}
>
<View
style={tw`flex-row items-center justify-between w-full px-5 py-2 border-b rounded-t-md border-sidebar-line/80 bg-mobile-header/50`}
style={tw`w-full flex-row items-center justify-between rounded-t-md border-b border-sidebar-line/80 bg-mobile-header/50 px-5 py-2`}
>
<View style={tw`flex-row items-center gap-2`}>
<FolderIcon size={36} />
<Text style={tw`font-bold text-white text-md`}>Added Memories</Text>
<Text style={tw`text-md font-bold text-white`}>Added Memories</Text>
</View>
<DotsThreeOutlineVertical weight="fill" size={20} color={tw.color('ink-faint')} />
</View>
<View style={tw`flex-row items-center justify-between flex-1 gap-5 px-5 py-2 mx-auto`}>
<View style={tw`mx-auto flex-1 flex-row items-center justify-between gap-5 px-5 py-2`}>
<AnimatedCircularProgress
size={80}
width={7}

View file

@ -0,0 +1,19 @@
/** @jsxImportSource solid-js */
import { createSignal } from 'solid-js';
import { render } from 'solid-js/web';
function Demo() {
const [count, setCount] = createSignal(0);
return (
<div class="absolute top-0 z-[99999] bg-red-500">
<button onClick={() => setCount(count() + 1)}>Click me</button>
<div>Hello from Solid: {count()}</div>
</div>
);
}
export function renderDemo(element: HTMLDivElement): () => void {
return render(Demo, element);
}

View file

@ -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<HTMLDivElement>(null);
useEffect(() => {
let cleanup = () => {};
if (ref.current) cleanup = renderDemo(ref.current);
return cleanup;
}, []);
return <div ref={ref} />;
}
// 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 (
<RootContext.Provider value={{ rawPath }}>
{useFeatureFlag('solidJsDemo') ? <RenderSolid /> : null}
<Outlet />
<Dialogs />
<Toaster position="bottom-right" expand={true} />

View file

@ -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",

View file

@ -10,6 +10,7 @@ export const features = [
'p2pPairing',
'backups',
'debugRoutes',
'solidJsDemo',
'hostedLocations'
] as const;

View file

@ -3,7 +3,7 @@
"display": "Default",
"compilerOptions": {
"strict": true,
"jsx": "react-jsx",
"jsx": "preserve",
"esModuleInterop": true,
"skipLibCheck": true,
"preserveWatchOutput": true,

View file

@ -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']
};

23
packages/config/eslint/react.js vendored Normal file
View file

@ -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'
}
}
};

View file

@ -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'
}
}
]
};

View file

@ -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"
}
}

View file

@ -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

View file

@ -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<Options> {
include?: string | RegExp | Array<string> | Array<RegExp>;
exclude?: string | RegExp | Array<string> | Array<RegExp>;
}
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;
}

View file

@ -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';

File diff suppressed because it is too large Load diff