diff --git a/ant-design/.eslintrc.cjs b/ant-design/.eslintrc.cjs new file mode 100644 index 00000000..4f6f59ee --- /dev/null +++ b/ant-design/.eslintrc.cjs @@ -0,0 +1,84 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + ignorePatterns: ["!**/.server", "!**/.client"], + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + "import/resolver": { + typescript: {}, + }, + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.cjs"], + env: { + node: true, + }, + }, + ], +}; diff --git a/ant-design/.gitignore b/ant-design/.gitignore new file mode 100644 index 00000000..80ec311f --- /dev/null +++ b/ant-design/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/.cache +/build +.env diff --git a/ant-design/README.md b/ant-design/README.md new file mode 100644 index 00000000..10d799b2 --- /dev/null +++ b/ant-design/README.md @@ -0,0 +1,19 @@ +# Ant Design Example + +Using [@ant-design/cssinjs](https://github.com/ant-design/cssinjs) to extract styles and inject them into the HTML can avoid page flicker. + +## Preview + +Open this example on [CodeSandbox](https://codesandbox.com): + +[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/remix-run/examples/tree/main/ant-design) + +## Example + +This example shows how to use Ant Desigin with Remix. + +Check the content of [./app/routes/_index.tsx](./app/routes/_index.tsx) and use `` to implement local theme changes. + +## Related Links + +[Ant Design](https://ant.design) diff --git a/ant-design/app/entry.server.tsx b/ant-design/app/entry.server.tsx new file mode 100644 index 00000000..a2e044a1 --- /dev/null +++ b/ant-design/app/entry.server.tsx @@ -0,0 +1,33 @@ +import { extractStyle, StyleProvider, createCache } from "@ant-design/cssinjs"; +import type { AppLoadContext, EntryContext } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import { renderToString } from "react-dom/server"; + + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + loadContext: AppLoadContext, +) { + + const cache = createCache(); + let markup = renderToString( + + + + ) + + markup = markup.replace("__ANTD__STYLES__", extractStyle(cache)); + + responseHeaders.set("Content-Type", "text/html"); + + return new Response(`${markup}`, { + status: responseStatusCode, + headers: responseHeaders, + }); +} diff --git a/ant-design/app/root.tsx b/ant-design/app/root.tsx new file mode 100644 index 00000000..792cec99 --- /dev/null +++ b/ant-design/app/root.tsx @@ -0,0 +1,30 @@ +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from "@remix-run/react"; + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + {typeof document === "undefined" ? "__ANTD__STYLES__" : null} + + + + + {children} + + + + + ); +} + +export default function App() { + return ; +} diff --git a/ant-design/app/routes/_index.tsx b/ant-design/app/routes/_index.tsx new file mode 100644 index 00000000..d02b4ad2 --- /dev/null +++ b/ant-design/app/routes/_index.tsx @@ -0,0 +1,60 @@ +import { Link } from '@remix-run/react'; +import { Button, Flex, ConfigProvider } from 'antd'; +import type { ThemeConfig } from "antd"; + +const links = [ + { + href: "https://remix.run/docs", + text: "Remix Docs", + }, + { + href: "https://github.com/ant-design/ant-design", + text: "Ant Design Repository" + }, + { + href: "https://ant.design/", + text: "Ant Design Docs", + }, +]; + +const theme: ThemeConfig = { + token: { + fontSize: 14, + colorPrimary: "#10b981", + }, + components: { + Button: { + fontWeight: 400, + }, + }, +}; + +const Demo = () => ( + + + + +) + +export default function Index() { + return ( + + + + + + + + + { + links.map(({ text, ...rest }) => ( + + )) + } + /About + + + ); +} diff --git a/ant-design/app/routes/about.tsx b/ant-design/app/routes/about.tsx new file mode 100644 index 00000000..64d3f87a --- /dev/null +++ b/ant-design/app/routes/about.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Alert } from 'antd'; + +const App: React.FC = () => ( + +) + +export default App; \ No newline at end of file diff --git a/ant-design/package.json b/ant-design/package.json new file mode 100644 index 00000000..70fc1d1e --- /dev/null +++ b/ant-design/package.json @@ -0,0 +1,42 @@ +{ + "name": "template", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "remix vite:build", + "dev": "remix vite:dev", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", + "start": "remix-serve ./build/server/index.js", + "typecheck": "tsc" + }, + "dependencies": { + "@ant-design/cssinjs": "^1.22.0", + "@remix-run/node": "^2.9.2", + "@remix-run/react": "^2.9.2", + "@remix-run/serve": "^2.9.2", + "antd": "^5.22.1", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@remix-run/dev": "^2.9.2", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "eslint": "^8.38.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/ant-design/public/favicon.ico b/ant-design/public/favicon.ico new file mode 100644 index 00000000..8830cf68 Binary files /dev/null and b/ant-design/public/favicon.ico differ diff --git a/ant-design/sandbox.config.json b/ant-design/sandbox.config.json new file mode 100644 index 00000000..f92e0250 --- /dev/null +++ b/ant-design/sandbox.config.json @@ -0,0 +1,7 @@ +{ + "hardReloadOnChange": true, + "template": "remix", + "container": { + "port": 3000 + } +} diff --git a/ant-design/tsconfig.json b/ant-design/tsconfig.json new file mode 100644 index 00000000..9d87dd37 --- /dev/null +++ b/ant-design/tsconfig.json @@ -0,0 +1,32 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "types": ["@remix-run/node", "vite/client"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} diff --git a/ant-design/vite.config.ts b/ant-design/vite.config.ts new file mode 100644 index 00000000..54066fb7 --- /dev/null +++ b/ant-design/vite.config.ts @@ -0,0 +1,16 @@ +import { vitePlugin as remix } from "@remix-run/dev"; +import { defineConfig } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; + +export default defineConfig({ + plugins: [ + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + }, + }), + tsconfigPaths(), + ], +});