Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,12 @@ target/
# mdBook
book/book/

# React Router
.react-router/
build/

# SeaORM
packages/storage/shield-sea-orm/src/entities_template/

# Turborepo
.turbo/
1 change: 0 additions & 1 deletion .prettierignore

This file was deleted.

8 changes: 6 additions & 2 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"bracketSpacing": false,
"importOrder": ["^~", "^[.]"],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"jsonRecursiveSort": true,
"plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-sort-json", "prettier-plugin-tailwindcss"],
"printWidth": 120,
"singleQuote": true,
"tabWidth": 4,
"trailingComma": "none"
"tailwindStylesheet": "./examples/react-router/assets/css/index.css"
}
2 changes: 1 addition & 1 deletion book/theme/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ document.addEventListener('DOMContentLoaded', () => {
localStorage.setItem(`mdbook-tabs-${global}`, name);

const globalContainers = document.querySelectorAll(
`.mdbook-tabs-container[data-tabglobal="${global}"]`
`.mdbook-tabs-container[data-tabglobal="${global}"]`,
);
for (const globalContainer of globalContainers) {
changeTab(globalContainer, name);
Expand Down
4 changes: 4 additions & 0 deletions examples/react-router/app/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));
64 changes: 64 additions & 0 deletions examples/react-router/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Links, Meta, Outlet, Scripts, ScrollRestoration, isRouteErrorResponse } from 'react-router';

import '~assets/css/index.css';

import type { Route } from './+types/root';

export const Layout = ({ children }: React.PropsWithChildren) => {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<title>Shield React Router Example</title>

<Meta />
<Links />
</head>
<body>
{children}

<ScrollRestoration />
<Scripts />
</body>
</html>
);
};

const queryClient = new QueryClient();

const App = () => (
<QueryClientProvider client={queryClient}>
<Outlet />
</QueryClientProvider>
);

export default App;

export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
let message = 'Oops!';
let details = 'An unexpected error occurred.';
let stack: string | undefined;

if (isRouteErrorResponse(error)) {
message = error.status === 404 ? '404' : 'Error';
details = error.status === 404 ? 'The requested page could not be found.' : error.statusText || details;
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message;
stack = error.stack;
}

return (
<main className="container mx-auto p-4 pt-16">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full overflow-x-auto p-4">
<code>{stack}</code>
</pre>
)}
</main>
);
};
12 changes: 12 additions & 0 deletions examples/react-router/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type RouteConfig, index, prefix, route } from '@react-router/dev/routes';

export default [
index('routes/home.tsx'),

...prefix('auth', [
index('routes/auth/action.tsx', {
id: 'routes/auth/action-index',
}),
route(':actionId', 'routes/auth/action.tsx'),
]),
] satisfies RouteConfig;
10 changes: 10 additions & 0 deletions examples/react-router/app/routes/auth/action.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Action } from '@rustforweb/shield-react-router';
import { ShadcnUiStyle } from '@rustforweb/shield-react-shadcn-ui';

import type { Route } from './+types/action';

const ActionRoute = (props: Route.ComponentProps) => {
return <Action style={ShadcnUiStyle} {...props} />;
};

export default ActionRoute;
3 changes: 3 additions & 0 deletions examples/react-router/app/routes/home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const HomeRoute = () => <h1>Shield React Router Example</h1>;

export default HomeRoute;
124 changes: 124 additions & 0 deletions examples/react-router/assets/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
@import 'tailwindcss';
@import 'tw-animate-css';

@source "../../../../node_modules/@rustforweb/shield-react-shadcn-ui";

@custom-variant dark (&:is(.dark *));

:root {
--radius: 0.65rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--radius: 0.625rem;
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}

.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}

@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}

@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
21 changes: 21 additions & 0 deletions examples/react-router/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"aliases": {
"components": "~/components",
"hooks": "~/hooks",
"lib": "~/lib",
"ui": "~/components/ui",
"utils": "~/lib/utils"
},
"iconLibrary": "lucide",
"rsc": false,
"style": "new-york",
"tailwind": {
"baseColor": "neutral",
"config": "",
"css": "assets/css/index.css",
"cssVariables": true,
"prefix": ""
},
"tsx": true
}
41 changes: 41 additions & 0 deletions examples/react-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@rustforweb/shield-examples-react-router",
"description": "Example with React Router.",
"author": "Rust for Web <info@rustforweb.org>",
"repository": "github:RustForWeb/shield",
"license": "MIT",
"private": true,
"type": "module",
"scripts": {
"build": "react-router build",
"dev": "react-router dev",
"start": "react-router-serve ./build/server/index.js",
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
"@react-router/node": "^7.9.2",
"@react-router/serve": "^7.9.2",
"@rustforweb/shield-react-router": "^0.1.0",
"@rustforweb/shield-react-shadcn-ui": "^0.1.0",
"@tanstack/react-query": "^5.90.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"isbot": "^5.1.31",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-router": "^7.9.2",
"tailwind-merge": "^3.3.1"
},
"devDependencies": {
"@react-router/dev": "^7.9.2",
"@tailwindcss/vite": "^4.1.13",
"@types/node": "^22",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"tailwindcss": "^4.1.14",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.2",
"vite": "^7.1.7",
"vite-tsconfig-paths": "^5.1.4"
}
}
5 changes: 5 additions & 0 deletions examples/react-router/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Config } from '@react-router/dev/config';

export default {
ssr: false,
} satisfies Config;
19 changes: 19 additions & 0 deletions examples/react-router/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"jsx": "react-jsx",
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true,
"paths": {
"~/*": ["./app/*"],
"~assets/*": ["./assets/*"]
},
"rootDirs": [".", "./.react-router/types"],
"types": ["vite/client"]
},
"extends": "../../tsconfig.base.json",
"include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"]
}
13 changes: 13 additions & 0 deletions examples/react-router/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { reactRouter } from '@react-router/dev/vite';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
plugins: [reactRouter(), tailwindcss(), tsconfigPaths()],
server: {
proxy: {
'/api': 'http://localhost:8080',
},
},
});
Loading