serve-my-md 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +52 -0
  2. package/bin/index.js +487 -0
  3. package/index.html +70 -0
  4. package/package.json +111 -0
  5. package/shared/constants.json +3 -0
  6. package/shared/index.d.ts +34 -0
  7. package/web/.cta.json +12 -0
  8. package/web/.cursorrules +7 -0
  9. package/web/.prettierignore +3 -0
  10. package/web/.vscode/settings.json +11 -0
  11. package/web/README.md +489 -0
  12. package/web/components.json +21 -0
  13. package/web/eslint.config.js +5 -0
  14. package/web/index.html +66 -0
  15. package/web/prettier.config.js +10 -0
  16. package/web/public/og-image.png +0 -0
  17. package/web/src/.generated/output.json +1 -0
  18. package/web/src/.generated/paths.json +1 -0
  19. package/web/src/App.tsx +15 -0
  20. package/web/src/article.css +199 -0
  21. package/web/src/components/Bettercrumb.tsx +86 -0
  22. package/web/src/components/Fonts.tsx +13 -0
  23. package/web/src/components/Header.tsx +10 -0
  24. package/web/src/components/IntentLink.tsx +20 -0
  25. package/web/src/components/Rendrer.tsx +140 -0
  26. package/web/src/components/Search.tsx +275 -0
  27. package/web/src/components/Sidebar.tsx +89 -0
  28. package/web/src/components/ThemeSwitcher.tsx +46 -0
  29. package/web/src/components/ui/breadcrumb.tsx +122 -0
  30. package/web/src/components/ui/button.tsx +60 -0
  31. package/web/src/components/ui/collapsible.tsx +33 -0
  32. package/web/src/components/ui/dropdown-menu.tsx +255 -0
  33. package/web/src/components/ui/input.tsx +21 -0
  34. package/web/src/components/ui/kbd.tsx +28 -0
  35. package/web/src/components/ui/separator.tsx +26 -0
  36. package/web/src/components/ui/sheet.tsx +139 -0
  37. package/web/src/components/ui/sidebar.tsx +727 -0
  38. package/web/src/components/ui/skeleton.tsx +13 -0
  39. package/web/src/components/ui/tooltip.tsx +59 -0
  40. package/web/src/contexts.ts +10 -0
  41. package/web/src/hooks/useMobile.ts +19 -0
  42. package/web/src/lib/utils.tsx +89 -0
  43. package/web/src/main.tsx +100 -0
  44. package/web/src/reportWebVitals.ts +13 -0
  45. package/web/src/styles.css +196 -0
  46. package/web/src/types/index.ts +3 -0
  47. package/web/tsconfig.json +35 -0
  48. package/web/vite.config.ts +31 -0
  49. package/web/vitest.config.ts +16 -0
@@ -0,0 +1,13 @@
1
+ import { cn } from "@/lib/utils"
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("bg-accent animate-pulse rounded-md", className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ export { Skeleton }
@@ -0,0 +1,59 @@
1
+ import * as React from "react"
2
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ function TooltipProvider({
7
+ delayDuration = 0,
8
+ ...props
9
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
10
+ return (
11
+ <TooltipPrimitive.Provider
12
+ data-slot="tooltip-provider"
13
+ delayDuration={delayDuration}
14
+ {...props}
15
+ />
16
+ )
17
+ }
18
+
19
+ function Tooltip({
20
+ ...props
21
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
22
+ return (
23
+ <TooltipProvider>
24
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ </TooltipProvider>
26
+ )
27
+ }
28
+
29
+ function TooltipTrigger({
30
+ ...props
31
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
32
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
33
+ }
34
+
35
+ function TooltipContent({
36
+ className,
37
+ sideOffset = 0,
38
+ children,
39
+ ...props
40
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
41
+ return (
42
+ <TooltipPrimitive.Portal>
43
+ <TooltipPrimitive.Content
44
+ data-slot="tooltip-content"
45
+ sideOffset={sideOffset}
46
+ className={cn(
47
+ "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
48
+ className
49
+ )}
50
+ {...props}
51
+ >
52
+ {children}
53
+ <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
54
+ </TooltipPrimitive.Content>
55
+ </TooltipPrimitive.Portal>
56
+ )
57
+ }
58
+
59
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,10 @@
1
+ import { createContext } from 'react'
2
+ import type { RouteTree } from '@shared/index'
3
+ import paths from "@/.generated/paths.json" with { type: "json" };
4
+
5
+ export const pageContext = createContext({
6
+ path: '',
7
+ id: '',
8
+ })
9
+
10
+ export const pathsContext = createContext<Array<RouteTree>>(paths as Array<RouteTree>);
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 769;
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,89 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import type { ClassValue } from 'clsx';
4
+ import type React from 'react';
5
+
6
+ export function cn(...inputs: Array<ClassValue>) {
7
+ return twMerge(clsx(inputs));
8
+ }
9
+
10
+ export function extractText(
11
+ html: string
12
+ ): { targetElement: HTMLElement; text: string }[] {
13
+ const template = document.createElement('div');
14
+ template.classList.add('template');
15
+ template.innerHTML = html;
16
+
17
+ const flattened = flatDom([template]);
18
+ markElementsFromExtraction(flattened);
19
+
20
+ return flattened.map((el) => ({ targetElement: el, text: el.textContent }));
21
+ }
22
+
23
+ export function flatDom(elements: HTMLElement[]): HTMLElement[] {
24
+ return elements.reduce((acc, el) => {
25
+ if (el.children.length === 0) return [...acc, el];
26
+
27
+ return [...acc, ...flatDom(Array.from(el.children) as HTMLElement[])];
28
+ }, [] as HTMLElement[]);
29
+ }
30
+
31
+ export function getTitleFromExtraction(
32
+ extraction: ReturnType<typeof extractText>
33
+ ): string {
34
+ const title = extraction.find(
35
+ ({ targetElement }) => targetElement.tagName === 'H1'
36
+ );
37
+
38
+ return title?.text || '';
39
+ }
40
+
41
+ export function slugify(text: string): string {
42
+ return text
43
+ .toString()
44
+ .toLowerCase()
45
+ .trim()
46
+ .replace(/\s+/g, '-')
47
+ .replace(/[^\w\-]+/g, '')
48
+ .replace(/\-\-+/g, '-');
49
+ }
50
+
51
+ const headings = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
52
+
53
+ export function markElements(root: HTMLElement) {
54
+ markElementsFromExtraction(flatDom([root]));
55
+ }
56
+
57
+ export function markElementsFromExtraction(
58
+ extraction: ReturnType<typeof extractText> | ReturnType<typeof flatDom>
59
+ ) {
60
+ extraction.forEach((el, index) => {
61
+ const element = 'targetElement' in el ? el.targetElement : el;
62
+ if (element.textContent) {
63
+ element.setAttribute('data-label', index.toString());
64
+ }
65
+ });
66
+ }
67
+
68
+ export function highlightSubstring(
69
+ text: string,
70
+ substring: string
71
+ ): React.ReactNode[] {
72
+ if (!substring) return [text];
73
+
74
+ const result: React.ReactNode[] = [];
75
+ let occurrence = -1,
76
+ prev = 0;
77
+
78
+ const lowercaseText = text.toLowerCase(),
79
+ lowercaseSubstring = substring.toLowerCase();
80
+
81
+ while ((occurrence = lowercaseText.indexOf(lowercaseSubstring, prev)) + 1) {
82
+ result.push(text.slice(prev, occurrence));
83
+ prev = occurrence + substring.length;
84
+ result.push(<mark key={occurrence}>{text.slice(occurrence, prev)}</mark>);
85
+ }
86
+ result.push(text.slice(prev));
87
+
88
+ return result;
89
+ }
@@ -0,0 +1,100 @@
1
+ import { StrictMode } from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import {
4
+ Outlet,
5
+ RouterProvider,
6
+ createRootRoute,
7
+ createRoute,
8
+ createRouter
9
+ } from '@tanstack/react-router';
10
+ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
11
+ import '@/styles.css';
12
+ import type { AppRoute } from '@/types';
13
+ import type { RouteTree } from '@shared/index';
14
+ import reportWebVitals from '@/reportWebVitals';
15
+ import App from '@/App.tsx';
16
+ import Rendrer from '@/components/Rendrer';
17
+ import { SidebarProvider } from '@/components/ui/sidebar';
18
+ import { pathsContext } from '@/contexts';
19
+ import Fonts from '@/components/Fonts';
20
+ import constants from "@shared/constants.json" with { type: "json" };
21
+
22
+ const STATIC_TEMP_CONTENT_PREFIX = constants.STATIC_TEMP_CONTENT_PREFIX;
23
+
24
+ import out from '@/.generated/output.json' with { type: 'json' };
25
+ import paths from '@/.generated/paths.json' with { type: 'json' };
26
+
27
+ const rootRoute = createRootRoute({
28
+ component: () => (
29
+ <>
30
+ <pathsContext.Provider value={paths as Array<RouteTree>}>
31
+ <SidebarProvider>
32
+ <App>
33
+ <Outlet />
34
+ <Fonts />
35
+ </App>
36
+ </SidebarProvider>
37
+ </pathsContext.Provider>
38
+ <TanStackRouterDevtools />
39
+ </>
40
+ )
41
+ });
42
+
43
+ const routes: Array<AppRoute> = [];
44
+
45
+ out.routes.forEach((route, i) => {
46
+ const newRoute = createRoute({
47
+ getParentRoute: () => rootRoute,
48
+ path: route.path || '/',
49
+ component: () => (
50
+ <Rendrer
51
+ path={route.path}
52
+ content={route.content}
53
+ title={''}
54
+ next={out.routes[i + 1]?.path}
55
+ prev={out.routes[i - 1]?.path}
56
+ />
57
+ )
58
+ });
59
+ routes.push(newRoute);
60
+ });
61
+
62
+ const routeTree = rootRoute.addChildren(routes);
63
+
64
+ const router = createRouter({
65
+ routeTree,
66
+ context: {},
67
+ defaultPreload: 'intent',
68
+ scrollRestoration: true,
69
+ defaultStructuralSharing: true,
70
+ defaultPreloadStaleTime: 0
71
+ });
72
+
73
+ declare module '@tanstack/react-router' {
74
+ interface Register {
75
+ router: typeof router;
76
+ }
77
+ }
78
+
79
+ // Just a safe side in case the code below this one doesn't run;
80
+ setTimeout(() => {
81
+ document.body.classList.remove("loading");
82
+ }, 10000);
83
+
84
+ const rootElement = document.getElementById('app');
85
+ if (rootElement && (!rootElement.innerHTML || rootElement.innerText.startsWith(STATIC_TEMP_CONTENT_PREFIX))) {
86
+ const root = ReactDOM.createRoot(rootElement);
87
+ root.render(
88
+ <StrictMode>
89
+ <RouterProvider router={router} />
90
+ </StrictMode>
91
+ );
92
+
93
+ document.body.classList.remove("loading");
94
+ }
95
+
96
+
97
+ // If you want to start measuring performance in your app, pass a function
98
+ // to log results (for example: reportWebVitals(console.log))
99
+ // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
100
+ reportWebVitals();
@@ -0,0 +1,13 @@
1
+ const reportWebVitals = (onPerfEntry?: () => void) => {
2
+ if (onPerfEntry && onPerfEntry instanceof Function) {
3
+ import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => {
4
+ onCLS(onPerfEntry)
5
+ onINP(onPerfEntry)
6
+ onFCP(onPerfEntry)
7
+ onLCP(onPerfEntry)
8
+ onTTFB(onPerfEntry)
9
+ })
10
+ }
11
+ }
12
+
13
+ export default reportWebVitals
@@ -0,0 +1,196 @@
1
+ @import 'tailwindcss';
2
+ @import 'tw-animate-css';
3
+
4
+ body {
5
+ @apply m-0;
6
+ font-family: var(--font-body);
7
+ -webkit-font-smoothing: antialiased;
8
+ -moz-osx-font-smoothing: grayscale;
9
+ }
10
+
11
+ * {
12
+ transition: outline .1s;
13
+ scroll-behavior: smooth;
14
+
15
+ &:focus {
16
+ outline: 3px solid rgb(46, 119, 229);
17
+ border-radius: 3px;
18
+ }
19
+ }
20
+
21
+ code {
22
+ font-family: var(--font-mono);
23
+ }
24
+
25
+ @custom-variant dark (&:is(.dark *));
26
+
27
+ :root {
28
+ --background: oklch(0.9551 0 0);
29
+ --foreground: oklch(0.3211 0 0);
30
+ --card: oklch(0.9702 0 0);
31
+ --card-foreground: oklch(0.3211 0 0);
32
+ --popover: oklch(0.9702 0 0);
33
+ --popover-foreground: oklch(0.3211 0 0);
34
+ --primary: oklch(0.4891 0 0);
35
+ --primary-foreground: oklch(1.0000 0 0);
36
+ --secondary: oklch(0.9067 0 0);
37
+ --secondary-foreground: oklch(0.3211 0 0);
38
+ --muted: oklch(0.8853 0 0);
39
+ --muted-foreground: oklch(0.5103 0 0);
40
+ --accent: oklch(0.8078 0 0);
41
+ --accent-foreground: oklch(0.3211 0 0);
42
+ --destructive: oklch(0.5594 0.1900 25.8625);
43
+ --destructive-foreground: oklch(1.0000 0 0);
44
+ --border: oklch(0.8576 0 0);
45
+ --input: oklch(0.9067 0 0);
46
+ --ring: oklch(0.4891 0 0);
47
+ --chart-1: oklch(0.4891 0 0);
48
+ --chart-2: oklch(0.4863 0.0361 196.0278);
49
+ --chart-3: oklch(0.6534 0 0);
50
+ --chart-4: oklch(0.7316 0 0);
51
+ --chart-5: oklch(0.8078 0 0);
52
+ --sidebar: oklch(0.9370 0 0);
53
+ --sidebar-foreground: oklch(0.3211 0 0);
54
+ --sidebar-primary: oklch(0.4891 0 0);
55
+ --sidebar-primary-foreground: oklch(1.0000 0 0);
56
+ --sidebar-accent: oklch(0.8078 0 0);
57
+ --sidebar-accent-foreground: oklch(0.3211 0 0);
58
+ --sidebar-border: oklch(0.8576 0 0);
59
+ --sidebar-ring: oklch(0.4891 0 0);
60
+ --font-body: var(--font-out-body);
61
+ --font-title: var(--font-out-heading);
62
+ --font-mono: var(--font-out-mono);
63
+ --radius: 0.35rem;
64
+ --shadow-x: 0px;
65
+ --shadow-y: 2px;
66
+ --shadow-blur: 0px;
67
+ --shadow-spread: 0px;
68
+ --shadow-opacity: 0.15;
69
+ --shadow-color: hsl(0 0% 20% / 0.1);
70
+ --shadow-2xs: 0px 2px 0px 0px hsl(0 0% 20% / 0.07);
71
+ --shadow-xs: 0px 2px 0px 0px hsl(0 0% 20% / 0.07);
72
+ --shadow-sm: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 1px 2px -1px hsl(0 0% 20% / 0.15);
73
+ --shadow: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 1px 2px -1px hsl(0 0% 20% / 0.15);
74
+ --shadow-md: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 2px 4px -1px hsl(0 0% 20% / 0.15);
75
+ --shadow-lg: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 4px 6px -1px hsl(0 0% 20% / 0.15);
76
+ --shadow-xl: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 8px 10px -1px hsl(0 0% 20% / 0.15);
77
+ --shadow-2xl: 0px 2px 0px 0px hsl(0 0% 20% / 0.38);
78
+ --tracking-normal: 0em;
79
+ --spacing: 0.25rem;
80
+ }
81
+
82
+ .dark {
83
+ --background: oklch(0.2178 0 0);
84
+ --foreground: oklch(0.8853 0 0);
85
+ --card: oklch(0.2435 0 0);
86
+ --card-foreground: oklch(0.8853 0 0);
87
+ --popover: oklch(0.2435 0 0);
88
+ --popover-foreground: oklch(0.8853 0 0);
89
+ --primary: oklch(0.7058 0 0);
90
+ --primary-foreground: oklch(0.2178 0 0);
91
+ --secondary: oklch(0.3092 0 0);
92
+ --secondary-foreground: oklch(0.8853 0 0);
93
+ --muted: oklch(0.2850 0 0);
94
+ --muted-foreground: oklch(0.5999 0 0);
95
+ --accent: oklch(0.3715 0 0);
96
+ --accent-foreground: oklch(0.8853 0 0);
97
+ --destructive: oklch(0.6591 0.1530 22.1703);
98
+ --destructive-foreground: oklch(1.0000 0 0);
99
+ --border: oklch(0.3290 0 0);
100
+ --input: oklch(0.3092 0 0);
101
+ --ring: oklch(0.7058 0 0);
102
+ --chart-1: oklch(0.7058 0 0);
103
+ --chart-2: oklch(0.6714 0.0339 206.3482);
104
+ --chart-3: oklch(0.5452 0 0);
105
+ --chart-4: oklch(0.4604 0 0);
106
+ --chart-5: oklch(0.3715 0 0);
107
+ --sidebar: oklch(0.2393 0 0);
108
+ --sidebar-foreground: oklch(0.8853 0 0);
109
+ --sidebar-primary: oklch(0.7058 0 0);
110
+ --sidebar-primary-foreground: oklch(0.2178 0 0);
111
+ --sidebar-accent: oklch(0.3715 0 0);
112
+ --sidebar-accent-foreground: oklch(0.8853 0 0);
113
+ --sidebar-border: oklch(0.3290 0 0);
114
+ --sidebar-ring: oklch(0.7058 0 0);
115
+ --radius: 0.35rem;
116
+ --shadow-x: 0px;
117
+ --shadow-y: 2px;
118
+ --shadow-blur: 0px;
119
+ --shadow-spread: 0px;
120
+ --shadow-opacity: 0.15;
121
+ --shadow-color: hsl(0 0% 20% / 0.1);
122
+ --shadow-2xs: 0px 2px 0px 0px hsl(0 0% 20% / 0.07);
123
+ --shadow-xs: 0px 2px 0px 0px hsl(0 0% 20% / 0.07);
124
+ --shadow-sm: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 1px 2px -1px hsl(0 0% 20% / 0.15);
125
+ --shadow: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 1px 2px -1px hsl(0 0% 20% / 0.15);
126
+ --shadow-md: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 2px 4px -1px hsl(0 0% 20% / 0.15);
127
+ --shadow-lg: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 4px 6px -1px hsl(0 0% 20% / 0.15);
128
+ --shadow-xl: 0px 2px 0px 0px hsl(0 0% 20% / 0.15), 0px 8px 10px -1px hsl(0 0% 20% / 0.15);
129
+ --shadow-2xl: 0px 2px 0px 0px hsl(0 0% 20% / 0.38);
130
+ }
131
+
132
+ @theme inline {
133
+ --color-background: var(--background);
134
+ --color-foreground: var(--foreground);
135
+ --color-card: var(--card);
136
+ --color-card-foreground: var(--card-foreground);
137
+ --color-popover: var(--popover);
138
+ --color-popover-foreground: var(--popover-foreground);
139
+ --color-primary: var(--primary);
140
+ --color-primary-foreground: var(--primary-foreground);
141
+ --color-secondary: var(--secondary);
142
+ --color-secondary-foreground: var(--secondary-foreground);
143
+ --color-muted: var(--muted);
144
+ --color-muted-foreground: var(--muted-foreground);
145
+ --color-accent: var(--accent);
146
+ --color-accent-foreground: var(--accent-foreground);
147
+ --color-destructive: var(--destructive);
148
+ --color-destructive-foreground: var(--destructive-foreground);
149
+ --color-border: var(--border);
150
+ --color-input: var(--input);
151
+ --color-ring: var(--ring);
152
+ --color-chart-1: var(--chart-1);
153
+ --color-chart-2: var(--chart-2);
154
+ --color-chart-3: var(--chart-3);
155
+ --color-chart-4: var(--chart-4);
156
+ --color-chart-5: var(--chart-5);
157
+ --color-sidebar: var(--sidebar);
158
+ --color-sidebar-foreground: var(--sidebar-foreground);
159
+ --color-sidebar-primary: var(--sidebar-primary);
160
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
161
+ --color-sidebar-accent: var(--sidebar-accent);
162
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
163
+ --color-sidebar-border: var(--sidebar-border);
164
+ --color-sidebar-ring: var(--sidebar-ring);
165
+
166
+ --radius-sm: calc(var(--radius) - 4px);
167
+ --radius-md: calc(var(--radius) - 2px);
168
+ --radius-lg: var(--radius);
169
+ --radius-xl: calc(var(--radius) + 4px);
170
+
171
+ --shadow-2xs: var(--shadow-2xs);
172
+ --shadow-xs: var(--shadow-xs);
173
+ --shadow-sm: var(--shadow-sm);
174
+ --shadow: var(--shadow);
175
+ --shadow-md: var(--shadow-md);
176
+ --shadow-lg: var(--shadow-lg);
177
+ --shadow-xl: var(--shadow-xl);
178
+ --shadow-2xl: var(--shadow-2xl);
179
+ }
180
+
181
+ @layer base {
182
+ * {
183
+ @apply border-border outline-ring/50;
184
+ }
185
+ body {
186
+ @apply bg-background text-foreground;
187
+ }
188
+ }
189
+ @layer base {
190
+ * {
191
+ @apply border-border outline-ring/50;
192
+ }
193
+ body {
194
+ @apply bg-background text-foreground;
195
+ }
196
+ }
@@ -0,0 +1,3 @@
1
+ import type { AnyContext, Register, ResolveParams, RootRoute, Route as rt } from "@tanstack/react-router";
2
+
3
+ export type AppRoute = rt<unknown, RootRoute<Register, undefined, {}, AnyContext, AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>, string, "/", string, "__root__", undefined, ResolveParams<string>, AnyContext, AnyContext, AnyContext, {}, undefined, unknown, unknown, unknown, unknown, undefined>;
@@ -0,0 +1,35 @@
1
+ {
2
+ "include": [
3
+ "**/*.ts",
4
+ "**/*.tsx",
5
+ "eslint.config.js",
6
+ "prettier.config.js",
7
+ "vite.config.js"
8
+ ],
9
+
10
+ "compilerOptions": {
11
+ "target": "ES2022",
12
+ "jsx": "react-jsx",
13
+ "module": "ESNext",
14
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
15
+ "types": ["vite/client"],
16
+
17
+ /* Bundler mode */
18
+ "moduleResolution": "bundler",
19
+ "allowImportingTsExtensions": true,
20
+ "verbatimModuleSyntax": true,
21
+ "noEmit": true,
22
+
23
+ /* Linting */
24
+ "skipLibCheck": true,
25
+ "strict": true,
26
+ "noUnusedLocals": true,
27
+ "noUnusedParameters": true,
28
+ "noFallthroughCasesInSwitch": true,
29
+ "noUncheckedSideEffectImports": true,
30
+ "paths": {
31
+ "@/*": ["./src/*"],
32
+ "@shared/*": ["../shared/*"]
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,31 @@
1
+ import { URL, fileURLToPath } from 'node:url';
2
+ import { defineConfig } from 'vite';
3
+ import { devtools } from '@tanstack/devtools-vite';
4
+ import viteReact from '@vitejs/plugin-react';
5
+ import tailwindcss from '@tailwindcss/vite';
6
+ import tsconfigPaths from "vite-tsconfig-paths";
7
+ import out from './src/.generated/output.json' with { type: 'json' };
8
+
9
+ // https://vitejs.dev/config/
10
+ export default defineConfig({
11
+ base: out.baseRoute,
12
+ plugins: [
13
+ devtools(),
14
+ viteReact({
15
+ babel: {
16
+ plugins: ['babel-plugin-react-compiler']
17
+ }
18
+ }),
19
+ tailwindcss(),
20
+ tsconfigPaths()
21
+ ],
22
+ root: fileURLToPath(new URL('.', import.meta.url)),
23
+ build: {
24
+ outDir: out.outDir || "dist"
25
+ },
26
+ resolve: {
27
+ alias: {
28
+ '@': fileURLToPath(new URL('./src', import.meta.url))
29
+ }
30
+ }
31
+ });
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from "vitest/config";
2
+ import path from "node:path";
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ environment: "jsdom",
7
+ globals: true,
8
+ include: ["src/**/*.{test,spec}.{ts,tsx}"]
9
+ },
10
+
11
+ resolve: {
12
+ alias: {
13
+ "@": path.resolve(import.meta.url, "./src")
14
+ }
15
+ }
16
+ });