create-reactivite 1.4.0 → 1.6.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.
- package/README.md +326 -290
- package/index.js +1 -1
- package/package.json +4 -2
- package/template/package.json +22 -22
- package/template/pnpm-lock.yaml +3274 -3274
- package/template/src/components/author-credit.tsx +25 -25
- package/template2/.env.example +8 -8
- package/template2/.husky/pre-commit +4 -4
- package/template2/.prettierrc +5 -5
- package/template2/README.md +73 -73
- package/template2/__tests__/example.test.ts +20 -20
- package/template2/_gitignore +37 -37
- package/template2/app/[locale]/(private)/dashboard/page.tsx +52 -52
- package/template2/app/[locale]/(public)/login/page.tsx +83 -83
- package/template2/app/[locale]/layout.tsx +58 -58
- package/template2/app/[locale]/locales.ts +10 -10
- package/template2/app/[locale]/page.tsx +38 -38
- package/template2/app/api/clear-session/route.ts +10 -10
- package/template2/app/globals.css +127 -127
- package/template2/app/layout.tsx +7 -7
- package/template2/app/page.tsx +6 -6
- package/template2/components/AuthEventListener.tsx +22 -22
- package/template2/components/author-credit.tsx +25 -25
- package/template2/components/theme-provider.tsx +78 -78
- package/template2/components/ui/button.tsx +60 -60
- package/template2/components/ui/card.tsx +92 -92
- package/template2/components/ui/input.tsx +21 -21
- package/template2/components/ui/label.tsx +24 -24
- package/template2/components/ui/sonner.tsx +40 -40
- package/template2/components.json +22 -22
- package/template2/config/constants.ts +7 -7
- package/template2/config/env.ts +5 -5
- package/template2/contexts/translation-context.tsx +70 -70
- package/template2/eslint.config.mjs +18 -18
- package/template2/hoc/provider.tsx +27 -27
- package/template2/lib/paramsSerializer.ts +40 -40
- package/template2/lib/utils.ts +6 -6
- package/template2/locales/az.json +20 -20
- package/template2/locales/en.json +20 -20
- package/template2/next-env.d.ts +1 -1
- package/template2/next.config.ts +17 -17
- package/template2/orval.config.ts +66 -66
- package/template2/package.json +62 -62
- package/template2/postcss.config.mjs +7 -7
- package/template2/scripts/fix-generated-types.mjs +13 -13
- package/template2/services/generated/.gitkeep +2 -2
- package/template2/services/httpClient/httpClient.ts +70 -70
- package/template2/services/httpClient/orvalMutator.ts +10 -10
- package/template2/store/example-store.tsx +16 -16
- package/template2/store/user-store.tsx +29 -29
- package/template2/testing/msw/handlers/index.ts +6 -6
- package/template2/testing/msw/server.ts +4 -4
- package/template2/tsconfig.json +34 -34
- package/template2/vitest.config.ts +17 -17
- package/template2/vitest.setup.ts +7 -7
- package/template3/README.md +34 -34
- package/template3/_gitignore +16 -16
- package/template3/components.json +21 -0
- package/template3/index.html +8 -2
- package/template3/package-lock.json +3934 -0
- package/template3/package.json +48 -22
- package/template3/postcss.config.mjs +5 -0
- package/template3/rspack.config.mjs +59 -51
- package/template3/src/App.tsx +16 -11
- package/template3/src/components/author-credit.tsx +42 -42
- package/template3/src/components/layout.tsx +59 -0
- package/template3/src/components/matrix-rain.tsx +71 -0
- package/template3/src/components/ui/accordion.tsx +64 -0
- package/template3/src/components/ui/alert-dialog.tsx +196 -0
- package/template3/src/components/ui/alert.tsx +66 -0
- package/template3/src/components/ui/aspect-ratio.tsx +11 -0
- package/template3/src/components/ui/avatar.tsx +107 -0
- package/template3/src/components/ui/badge.tsx +48 -0
- package/template3/src/components/ui/breadcrumb.tsx +109 -0
- package/template3/src/components/ui/button-group.tsx +83 -0
- package/template3/src/components/ui/button.tsx +64 -0
- package/template3/src/components/ui/calendar.tsx +218 -0
- package/template3/src/components/ui/card.tsx +92 -0
- package/template3/src/components/ui/carousel.tsx +241 -0
- package/template3/src/components/ui/chart.tsx +372 -0
- package/template3/src/components/ui/checkbox.tsx +32 -0
- package/template3/src/components/ui/collapsible.tsx +31 -0
- package/template3/src/components/ui/combobox.tsx +310 -0
- package/template3/src/components/ui/command.tsx +184 -0
- package/template3/src/components/ui/context-menu.tsx +252 -0
- package/template3/src/components/ui/dialog.tsx +156 -0
- package/template3/src/components/ui/direction.tsx +22 -0
- package/template3/src/components/ui/drawer.tsx +133 -0
- package/template3/src/components/ui/dropdown-menu.tsx +257 -0
- package/template3/src/components/ui/empty.tsx +104 -0
- package/template3/src/components/ui/field.tsx +248 -0
- package/template3/src/components/ui/form.tsx +165 -0
- package/template3/src/components/ui/hover-card.tsx +42 -0
- package/template3/src/components/ui/input-group.tsx +168 -0
- package/template3/src/components/ui/input-otp.tsx +77 -0
- package/template3/src/components/ui/input.tsx +21 -0
- package/template3/src/components/ui/item.tsx +193 -0
- package/template3/src/components/ui/kbd.tsx +28 -0
- package/template3/src/components/ui/label.tsx +22 -0
- package/template3/src/components/ui/menubar.tsx +276 -0
- package/template3/src/components/ui/native-select.tsx +62 -0
- package/template3/src/components/ui/navigation-menu.tsx +168 -0
- package/template3/src/components/ui/pagination.tsx +127 -0
- package/template3/src/components/ui/popover.tsx +87 -0
- package/template3/src/components/ui/progress.tsx +31 -0
- package/template3/src/components/ui/radio-group.tsx +43 -0
- package/template3/src/components/ui/resizable.tsx +53 -0
- package/template3/src/components/ui/scroll-area.tsx +56 -0
- package/template3/src/components/ui/select.tsx +190 -0
- package/template3/src/components/ui/separator.tsx +26 -0
- package/template3/src/components/ui/sheet.tsx +143 -0
- package/template3/src/components/ui/sidebar.tsx +724 -0
- package/template3/src/components/ui/skeleton.tsx +13 -0
- package/template3/src/components/ui/slider.tsx +61 -0
- package/template3/src/components/ui/sonner.tsx +40 -0
- package/template3/src/components/ui/spinner.tsx +16 -0
- package/template3/src/components/ui/switch.tsx +33 -0
- package/template3/src/components/ui/table.tsx +116 -0
- package/template3/src/components/ui/tabs.tsx +89 -0
- package/template3/src/components/ui/textarea.tsx +18 -0
- package/template3/src/components/ui/toggle-group.tsx +83 -0
- package/template3/src/components/ui/toggle.tsx +47 -0
- package/template3/src/components/ui/tooltip.tsx +55 -0
- package/template3/src/hooks/use-mobile.ts +19 -0
- package/template3/src/index.css +175 -32
- package/template3/src/lib/utils.ts +6 -0
- package/template3/src/main.tsx +10 -10
- package/template3/src/pages/about.tsx +113 -0
- package/template3/src/pages/contact.tsx +111 -0
- package/template3/src/pages/home.tsx +81 -0
- package/template3/tsconfig.json +24 -20
- package/template2/tsconfig.tsbuildinfo +0 -1
package/template3/src/index.css
CHANGED
|
@@ -1,46 +1,189 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
@import 'tw-animate-css';
|
|
3
|
+
|
|
4
|
+
@custom-variant dark (&:is(.dark *));
|
|
5
|
+
|
|
1
6
|
:root {
|
|
2
|
-
--
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
|
|
7
|
+
--radius: 0.625rem;
|
|
8
|
+
--background: oklch(1 0 0);
|
|
9
|
+
--foreground: oklch(0.145 0 0);
|
|
10
|
+
--card: oklch(1 0 0);
|
|
11
|
+
--card-foreground: oklch(0.145 0 0);
|
|
12
|
+
--popover: oklch(1 0 0);
|
|
13
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
14
|
+
--primary: oklch(0.205 0 0);
|
|
15
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
16
|
+
--secondary: oklch(0.97 0 0);
|
|
17
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
18
|
+
--muted: oklch(0.97 0 0);
|
|
19
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
20
|
+
--accent: oklch(0.97 0 0);
|
|
21
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
22
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
23
|
+
--border: oklch(0.922 0 0);
|
|
24
|
+
--input: oklch(0.922 0 0);
|
|
25
|
+
--ring: oklch(0.708 0 0);
|
|
26
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
27
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
28
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
29
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
30
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
31
|
+
--sidebar: oklch(0.985 0 0);
|
|
32
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
33
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
34
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
35
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
36
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
37
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
38
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
7
39
|
}
|
|
8
40
|
|
|
9
|
-
|
|
10
|
-
|
|
41
|
+
.dark {
|
|
42
|
+
--background: oklch(0.145 0 0);
|
|
43
|
+
--foreground: oklch(0.985 0 0);
|
|
44
|
+
--card: oklch(0.205 0 0);
|
|
45
|
+
--card-foreground: oklch(0.985 0 0);
|
|
46
|
+
--popover: oklch(0.205 0 0);
|
|
47
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
48
|
+
--primary: oklch(0.922 0 0);
|
|
49
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
50
|
+
--secondary: oklch(0.269 0 0);
|
|
51
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
52
|
+
--muted: oklch(0.269 0 0);
|
|
53
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
54
|
+
--accent: oklch(0.269 0 0);
|
|
55
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
56
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
57
|
+
--border: oklch(1 0 0 / 10%);
|
|
58
|
+
--input: oklch(1 0 0 / 15%);
|
|
59
|
+
--ring: oklch(0.556 0 0);
|
|
60
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
61
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
62
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
63
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
64
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
65
|
+
--sidebar: oklch(0.205 0 0);
|
|
66
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
67
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
68
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
69
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
70
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
71
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
72
|
+
--sidebar-ring: oklch(0.556 0 0);
|
|
11
73
|
}
|
|
12
74
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
75
|
+
@theme inline {
|
|
76
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
77
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
78
|
+
--radius-lg: var(--radius);
|
|
79
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
80
|
+
--color-background: var(--background);
|
|
81
|
+
--color-foreground: var(--foreground);
|
|
82
|
+
--color-card: var(--card);
|
|
83
|
+
--color-card-foreground: var(--card-foreground);
|
|
84
|
+
--color-popover: var(--popover);
|
|
85
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
86
|
+
--color-primary: var(--primary);
|
|
87
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
88
|
+
--color-secondary: var(--secondary);
|
|
89
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
90
|
+
--color-muted: var(--muted);
|
|
91
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
92
|
+
--color-accent: var(--accent);
|
|
93
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
94
|
+
--color-destructive: var(--destructive);
|
|
95
|
+
--color-border: var(--border);
|
|
96
|
+
--color-input: var(--input);
|
|
97
|
+
--color-ring: var(--ring);
|
|
98
|
+
--color-chart-1: var(--chart-1);
|
|
99
|
+
--color-chart-2: var(--chart-2);
|
|
100
|
+
--color-chart-3: var(--chart-3);
|
|
101
|
+
--color-chart-4: var(--chart-4);
|
|
102
|
+
--color-chart-5: var(--chart-5);
|
|
103
|
+
--color-sidebar: var(--sidebar);
|
|
104
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
105
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
106
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
107
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
108
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
109
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
110
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
18
111
|
}
|
|
19
112
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
113
|
+
/* ── Matrix theme override ───────────────────────────────── */
|
|
114
|
+
.dark {
|
|
115
|
+
--background: oklch(0.13 0.012 160);
|
|
116
|
+
--foreground: oklch(0.9 0.16 150);
|
|
117
|
+
--card: oklch(0.16 0.02 160 / 70%);
|
|
118
|
+
--card-foreground: oklch(0.92 0.15 150);
|
|
119
|
+
--popover: oklch(0.12 0.015 160);
|
|
120
|
+
--popover-foreground: oklch(0.92 0.15 150);
|
|
121
|
+
--primary: oklch(0.85 0.24 148);
|
|
122
|
+
--primary-foreground: oklch(0.12 0.02 160);
|
|
123
|
+
--secondary: oklch(0.22 0.03 160);
|
|
124
|
+
--secondary-foreground: oklch(0.9 0.15 150);
|
|
125
|
+
--muted: oklch(0.2 0.02 160);
|
|
126
|
+
--muted-foreground: oklch(0.62 0.1 150);
|
|
127
|
+
--accent: oklch(0.28 0.06 150);
|
|
128
|
+
--accent-foreground: oklch(0.92 0.18 148);
|
|
129
|
+
--destructive: oklch(0.62 0.22 25);
|
|
130
|
+
--border: oklch(0.85 0.24 148 / 22%);
|
|
131
|
+
--input: oklch(0.85 0.24 148 / 18%);
|
|
132
|
+
--ring: oklch(0.85 0.24 148 / 70%);
|
|
26
133
|
}
|
|
27
134
|
|
|
28
|
-
|
|
29
|
-
font-
|
|
30
|
-
|
|
135
|
+
@theme inline {
|
|
136
|
+
--font-display: 'Orbitron', sans-serif;
|
|
137
|
+
--font-mono: 'Share Tech Mono', ui-monospace, monospace;
|
|
31
138
|
}
|
|
32
139
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
140
|
+
@layer base {
|
|
141
|
+
* {
|
|
142
|
+
@apply border-border outline-ring/50;
|
|
143
|
+
}
|
|
144
|
+
body {
|
|
145
|
+
@apply bg-background text-foreground;
|
|
146
|
+
font-family: 'Share Tech Mono', ui-monospace, monospace;
|
|
147
|
+
background-color: #04070a;
|
|
148
|
+
}
|
|
36
149
|
}
|
|
37
150
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
151
|
+
@layer utilities {
|
|
152
|
+
.text-glow {
|
|
153
|
+
text-shadow:
|
|
154
|
+
0 0 4px oklch(0.85 0.24 148 / 70%),
|
|
155
|
+
0 0 18px oklch(0.85 0.24 148 / 45%);
|
|
156
|
+
}
|
|
157
|
+
.box-glow {
|
|
158
|
+
box-shadow:
|
|
159
|
+
0 0 0 1px oklch(0.85 0.24 148 / 25%),
|
|
160
|
+
0 0 24px oklch(0.85 0.24 148 / 14%),
|
|
161
|
+
inset 0 0 32px oklch(0.85 0.24 148 / 6%);
|
|
162
|
+
}
|
|
163
|
+
/* CRT scanline overlay */
|
|
164
|
+
.scanlines::after {
|
|
165
|
+
content: '';
|
|
166
|
+
position: fixed;
|
|
167
|
+
inset: 0;
|
|
168
|
+
pointer-events: none;
|
|
169
|
+
z-index: 30;
|
|
170
|
+
background: repeating-linear-gradient(
|
|
171
|
+
to bottom,
|
|
172
|
+
transparent 0,
|
|
173
|
+
transparent 2px,
|
|
174
|
+
oklch(0 0 0 / 28%) 3px,
|
|
175
|
+
transparent 4px
|
|
176
|
+
);
|
|
177
|
+
mix-blend-mode: multiply;
|
|
178
|
+
}
|
|
179
|
+
@keyframes flicker {
|
|
180
|
+
0%, 19%, 21%, 55%, 57%, 100% { opacity: 1; }
|
|
181
|
+
20%, 56% { opacity: 0.78; }
|
|
182
|
+
}
|
|
183
|
+
.flicker { animation: flicker 4.5s infinite steps(1); }
|
|
184
|
+
@keyframes rise {
|
|
185
|
+
from { opacity: 0; transform: translateY(18px); }
|
|
186
|
+
to { opacity: 1; transform: translateY(0); }
|
|
187
|
+
}
|
|
188
|
+
.rise { animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
|
|
46
189
|
}
|
package/template3/src/main.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { StrictMode } from 'react';
|
|
2
|
-
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import App from './App';
|
|
4
|
-
import './index.css';
|
|
5
|
-
|
|
6
|
-
createRoot(document.getElementById('root')!).render(
|
|
7
|
-
<StrictMode>
|
|
8
|
-
<App />
|
|
9
|
-
</StrictMode>,
|
|
10
|
-
);
|
|
1
|
+
import { StrictMode } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import App from './App';
|
|
4
|
+
import './index.css';
|
|
5
|
+
|
|
6
|
+
createRoot(document.getElementById('root')!).render(
|
|
7
|
+
<StrictMode>
|
|
8
|
+
<App />
|
|
9
|
+
</StrictMode>,
|
|
10
|
+
);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
|
2
|
+
import { Badge } from '@/components/ui/badge';
|
|
3
|
+
import { Progress } from '@/components/ui/progress';
|
|
4
|
+
import { Separator } from '@/components/ui/separator';
|
|
5
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
6
|
+
import { Card, CardContent } from '@/components/ui/card';
|
|
7
|
+
|
|
8
|
+
const SKILLS = [
|
|
9
|
+
{ name: 'React / Next.js', level: 95 },
|
|
10
|
+
{ name: 'TypeScript', level: 92 },
|
|
11
|
+
{ name: 'Tailwind / shadcn', level: 90 },
|
|
12
|
+
{ name: 'Rspack / Vite', level: 84 },
|
|
13
|
+
{ name: 'Node / APIs', level: 78 },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const STACK = [
|
|
17
|
+
'React', 'TypeScript', 'Next.js', 'Rspack', 'Tailwind v4',
|
|
18
|
+
'shadcn/ui', 'TanStack Query', 'Zustand', 'Zod', 'Vitest',
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const TIMELINE = [
|
|
22
|
+
{ year: '2024', text: 'Building design-system-grade UIs & dev tooling.' },
|
|
23
|
+
{ year: '2022', text: 'Shipped large-scale Next.js platforms, i18n + SSR.' },
|
|
24
|
+
{ year: '2020', text: 'Went full frontend — React, state, performance.' },
|
|
25
|
+
{ year: '2018', text: 'First lines of code entered the Matrix.' },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export default function About() {
|
|
29
|
+
return (
|
|
30
|
+
<section className="space-y-10">
|
|
31
|
+
<div className="rise flex items-center gap-5">
|
|
32
|
+
<Avatar className="size-20 box-glow border border-primary/40">
|
|
33
|
+
<AvatarFallback className="bg-secondary font-display text-2xl text-primary">
|
|
34
|
+
JS
|
|
35
|
+
</AvatarFallback>
|
|
36
|
+
</Avatar>
|
|
37
|
+
<div>
|
|
38
|
+
<h1 className="font-display text-3xl font-bold text-primary text-glow sm:text-4xl">
|
|
39
|
+
./about
|
|
40
|
+
</h1>
|
|
41
|
+
<p className="font-mono text-sm text-muted-foreground">
|
|
42
|
+
operator profile — clearance: green
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<Tabs defaultValue="bio" className="rise" style={{ animationDelay: '120ms' }}>
|
|
48
|
+
<TabsList className="font-mono">
|
|
49
|
+
<TabsTrigger value="bio">bio</TabsTrigger>
|
|
50
|
+
<TabsTrigger value="skills">skills</TabsTrigger>
|
|
51
|
+
<TabsTrigger value="log">log</TabsTrigger>
|
|
52
|
+
</TabsList>
|
|
53
|
+
|
|
54
|
+
<TabsContent value="bio" className="pt-4">
|
|
55
|
+
<Card className="box-glow border-primary/20 bg-card/60 backdrop-blur-sm">
|
|
56
|
+
<CardContent className="space-y-4 pt-6 text-sm leading-relaxed text-muted-foreground sm:text-base">
|
|
57
|
+
<p>
|
|
58
|
+
<span className="text-primary">></span> I'm{' '}
|
|
59
|
+
<span className="text-primary text-glow">Javid Salimov</span>, a
|
|
60
|
+
frontend engineer who treats the browser like a programmable
|
|
61
|
+
reality. I care about typed contracts, fast bundles and
|
|
62
|
+
interfaces that feel inevitable.
|
|
63
|
+
</p>
|
|
64
|
+
<p>
|
|
65
|
+
<span className="text-primary">></span> Daily I architect
|
|
66
|
+
component systems, squeeze build pipelines, and turn fuzzy
|
|
67
|
+
product ideas into crisp, accessible UI.
|
|
68
|
+
</p>
|
|
69
|
+
<Separator className="bg-primary/15" />
|
|
70
|
+
<div className="flex flex-wrap gap-2">
|
|
71
|
+
{STACK.map((t) => (
|
|
72
|
+
<Badge
|
|
73
|
+
key={t}
|
|
74
|
+
variant="secondary"
|
|
75
|
+
className="font-mono text-xs text-primary/90"
|
|
76
|
+
>
|
|
77
|
+
{t}
|
|
78
|
+
</Badge>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
</CardContent>
|
|
82
|
+
</Card>
|
|
83
|
+
</TabsContent>
|
|
84
|
+
|
|
85
|
+
<TabsContent value="skills" className="space-y-5 pt-6">
|
|
86
|
+
{SKILLS.map((s) => (
|
|
87
|
+
<div key={s.name} className="space-y-2">
|
|
88
|
+
<div className="flex justify-between font-mono text-xs sm:text-sm">
|
|
89
|
+
<span className="text-foreground">{s.name}</span>
|
|
90
|
+
<span className="text-primary text-glow">{s.level}%</span>
|
|
91
|
+
</div>
|
|
92
|
+
<Progress value={s.level} className="h-2 bg-secondary" />
|
|
93
|
+
</div>
|
|
94
|
+
))}
|
|
95
|
+
</TabsContent>
|
|
96
|
+
|
|
97
|
+
<TabsContent value="log" className="pt-6">
|
|
98
|
+
<ol className="relative space-y-6 border-l border-primary/25 pl-6">
|
|
99
|
+
{TIMELINE.map((t) => (
|
|
100
|
+
<li key={t.year} className="relative">
|
|
101
|
+
<span className="absolute -left-[31px] top-1 size-3 rounded-full bg-primary box-glow" />
|
|
102
|
+
<div className="font-display text-lg text-primary text-glow">
|
|
103
|
+
{t.year}
|
|
104
|
+
</div>
|
|
105
|
+
<p className="font-mono text-sm text-muted-foreground">{t.text}</p>
|
|
106
|
+
</li>
|
|
107
|
+
))}
|
|
108
|
+
</ol>
|
|
109
|
+
</TabsContent>
|
|
110
|
+
</Tabs>
|
|
111
|
+
</section>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { Briefcase, Code2, Package, Send } from 'lucide-react';
|
|
3
|
+
import { toast } from 'sonner';
|
|
4
|
+
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { Input } from '@/components/ui/input';
|
|
6
|
+
import { Label } from '@/components/ui/label';
|
|
7
|
+
import { Textarea } from '@/components/ui/textarea';
|
|
8
|
+
import {
|
|
9
|
+
Card,
|
|
10
|
+
CardContent,
|
|
11
|
+
CardDescription,
|
|
12
|
+
CardHeader,
|
|
13
|
+
CardTitle,
|
|
14
|
+
} from '@/components/ui/card';
|
|
15
|
+
|
|
16
|
+
const CHANNELS = [
|
|
17
|
+
{ icon: Code2, label: 'github', href: 'https://github.com/javidselimov' },
|
|
18
|
+
{ icon: Briefcase, label: 'linkedin', href: 'https://www.linkedin.com/in/javidsalim/' },
|
|
19
|
+
{ icon: Package, label: 'npm', href: 'https://www.npmjs.com/~ubuligan' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export default function Contact() {
|
|
23
|
+
const [sending, setSending] = useState(false);
|
|
24
|
+
|
|
25
|
+
const onSubmit = (e: React.FormEvent) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
setSending(true);
|
|
28
|
+
toast.loading('Encrypting transmission...', { id: 'tx' });
|
|
29
|
+
window.setTimeout(() => {
|
|
30
|
+
setSending(false);
|
|
31
|
+
toast.success('Message routed through the construct.', {
|
|
32
|
+
id: 'tx',
|
|
33
|
+
description: 'Javid will decode it shortly.',
|
|
34
|
+
});
|
|
35
|
+
}, 1200);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<section className="grid gap-8 lg:grid-cols-[1fr_0.8fr]">
|
|
40
|
+
<Card className="rise box-glow border-primary/20 bg-card/60 backdrop-blur-sm">
|
|
41
|
+
<CardHeader>
|
|
42
|
+
<CardTitle className="font-display text-2xl text-primary text-glow">
|
|
43
|
+
./contact --secure
|
|
44
|
+
</CardTitle>
|
|
45
|
+
<CardDescription className="font-mono">
|
|
46
|
+
Open an encrypted channel to the operator.
|
|
47
|
+
</CardDescription>
|
|
48
|
+
</CardHeader>
|
|
49
|
+
<CardContent>
|
|
50
|
+
<form onSubmit={onSubmit} className="space-y-4">
|
|
51
|
+
<div className="space-y-2">
|
|
52
|
+
<Label htmlFor="name" className="font-mono text-xs text-primary/80">
|
|
53
|
+
ALIAS
|
|
54
|
+
</Label>
|
|
55
|
+
<Input id="name" required placeholder="neo" className="font-mono" />
|
|
56
|
+
</div>
|
|
57
|
+
<div className="space-y-2">
|
|
58
|
+
<Label htmlFor="email" className="font-mono text-xs text-primary/80">
|
|
59
|
+
NODE_ADDRESS
|
|
60
|
+
</Label>
|
|
61
|
+
<Input
|
|
62
|
+
id="email"
|
|
63
|
+
type="email"
|
|
64
|
+
required
|
|
65
|
+
placeholder="you@zion.io"
|
|
66
|
+
className="font-mono"
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
<div className="space-y-2">
|
|
70
|
+
<Label htmlFor="msg" className="font-mono text-xs text-primary/80">
|
|
71
|
+
PAYLOAD
|
|
72
|
+
</Label>
|
|
73
|
+
<Textarea
|
|
74
|
+
id="msg"
|
|
75
|
+
required
|
|
76
|
+
rows={4}
|
|
77
|
+
placeholder="Knock, knock..."
|
|
78
|
+
className="font-mono"
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
81
|
+
<Button type="submit" disabled={sending} className="box-glow w-full font-mono">
|
|
82
|
+
<Send className="size-4" />
|
|
83
|
+
{sending ? 'TRANSMITTING...' : 'TRANSMIT'}
|
|
84
|
+
</Button>
|
|
85
|
+
</form>
|
|
86
|
+
</CardContent>
|
|
87
|
+
</Card>
|
|
88
|
+
|
|
89
|
+
<div className="rise space-y-3" style={{ animationDelay: '120ms' }}>
|
|
90
|
+
<p className="font-mono text-xs tracking-widest text-muted-foreground">
|
|
91
|
+
// DIRECT CHANNELS
|
|
92
|
+
</p>
|
|
93
|
+
{CHANNELS.map((c) => (
|
|
94
|
+
<a
|
|
95
|
+
key={c.label}
|
|
96
|
+
href={c.href}
|
|
97
|
+
target="_blank"
|
|
98
|
+
rel="noreferrer"
|
|
99
|
+
className="group flex items-center gap-3 rounded-md border border-primary/20 bg-card/50 px-4 py-3 font-mono text-sm text-muted-foreground transition-colors hover:border-primary/60 hover:text-primary hover:text-glow"
|
|
100
|
+
>
|
|
101
|
+
<c.icon className="size-4 text-primary" />
|
|
102
|
+
<span className="flex-1">{c.label}</span>
|
|
103
|
+
<span className="text-primary opacity-0 transition-opacity group-hover:opacity-100">
|
|
104
|
+
↗
|
|
105
|
+
</span>
|
|
106
|
+
</a>
|
|
107
|
+
))}
|
|
108
|
+
</div>
|
|
109
|
+
</section>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Link } from 'react-router-dom';
|
|
2
|
+
import { ArrowRight, Terminal } from 'lucide-react';
|
|
3
|
+
import { Button } from '@/components/ui/button';
|
|
4
|
+
import { Badge } from '@/components/ui/badge';
|
|
5
|
+
import {
|
|
6
|
+
Card,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from '@/components/ui/card';
|
|
11
|
+
|
|
12
|
+
const STATS = [
|
|
13
|
+
{ label: 'YEARS_ONLINE', value: '6+' },
|
|
14
|
+
{ label: 'REPOS_DECRYPTED', value: '120+' },
|
|
15
|
+
{ label: 'STACK', value: 'FRONTEND' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export default function Home() {
|
|
19
|
+
return (
|
|
20
|
+
<section className="space-y-12">
|
|
21
|
+
<div className="space-y-6">
|
|
22
|
+
<div className="rise" style={{ animationDelay: '40ms' }}>
|
|
23
|
+
<Badge variant="outline" className="border-primary/40 font-mono tracking-widest">
|
|
24
|
+
<span className="mr-1 inline-block size-1.5 animate-pulse rounded-full bg-primary" />
|
|
25
|
+
WAKE UP, NEO...
|
|
26
|
+
</Badge>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<h1
|
|
30
|
+
className="rise font-display text-5xl font-black leading-[0.95] tracking-tight text-primary text-glow sm:text-7xl"
|
|
31
|
+
style={{ animationDelay: '120ms' }}
|
|
32
|
+
>
|
|
33
|
+
JAVID
|
|
34
|
+
<br />
|
|
35
|
+
SALIMOV
|
|
36
|
+
</h1>
|
|
37
|
+
|
|
38
|
+
<p
|
|
39
|
+
className="rise max-w-xl text-base leading-relaxed text-muted-foreground sm:text-lg"
|
|
40
|
+
style={{ animationDelay: '200ms' }}
|
|
41
|
+
>
|
|
42
|
+
<span className="text-primary">$</span> Frontend engineer operating
|
|
43
|
+
inside the construct. I bend React, TypeScript and pixels until the
|
|
44
|
+
interface obeys. There is no spoon — only well-typed components.
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<div className="rise flex flex-wrap gap-3" style={{ animationDelay: '280ms' }}>
|
|
48
|
+
<Button asChild className="box-glow font-mono">
|
|
49
|
+
<Link to="/about">
|
|
50
|
+
Enter the construct <ArrowRight className="size-4" />
|
|
51
|
+
</Link>
|
|
52
|
+
</Button>
|
|
53
|
+
<Button asChild variant="outline" className="font-mono border-primary/40">
|
|
54
|
+
<Link to="/contact">
|
|
55
|
+
<Terminal className="size-4" /> Open channel
|
|
56
|
+
</Link>
|
|
57
|
+
</Button>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div className="grid gap-4 sm:grid-cols-3">
|
|
62
|
+
{STATS.map((s, i) => (
|
|
63
|
+
<Card
|
|
64
|
+
key={s.label}
|
|
65
|
+
className="rise box-glow border-primary/20 bg-card/60 backdrop-blur-sm"
|
|
66
|
+
style={{ animationDelay: `${360 + i * 90}ms` }}
|
|
67
|
+
>
|
|
68
|
+
<CardHeader className="pb-2">
|
|
69
|
+
<CardTitle className="font-display text-4xl text-primary text-glow">
|
|
70
|
+
{s.value}
|
|
71
|
+
</CardTitle>
|
|
72
|
+
</CardHeader>
|
|
73
|
+
<CardContent className="font-mono text-xs tracking-widest text-muted-foreground">
|
|
74
|
+
{s.label}
|
|
75
|
+
</CardContent>
|
|
76
|
+
</Card>
|
|
77
|
+
))}
|
|
78
|
+
</div>
|
|
79
|
+
</section>
|
|
80
|
+
);
|
|
81
|
+
}
|
package/template3/tsconfig.json
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"baseUrl": ".",
|
|
8
|
+
"paths": {
|
|
9
|
+
"@/*": ["./src/*"]
|
|
10
|
+
},
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["src"]
|
|
24
|
+
}
|