sh-ui-cli 0.22.2 → 0.23.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 +19 -2
- package/bin/sh-ui.mjs +7 -0
- package/data/changelog/versions.json +14 -0
- package/package.json +13 -2
- package/src/create/cli-args.js +63 -0
- package/src/create/generator.js +542 -0
- package/src/create/index.mjs +68 -0
- package/src/create/plugins/index.js +17 -0
- package/src/create/plugins/nextIntl.js +197 -0
- package/src/create/plugins/sentry.js +689 -0
- package/src/create/theme/decode.js +66 -0
- package/src/create/theme/inject.js +111 -0
- package/src/mcp.mjs +81 -27
- package/src/paths.mjs +5 -0
- package/templates/flutter-standalone/README.md +34 -0
- package/templates/flutter-standalone/analysis_options.yaml +1 -0
- package/templates/flutter-standalone/lib/main.dart +103 -0
- package/templates/flutter-standalone/lib/sh_ui/foundation/sh_ui_tokens.dart +389 -0
- package/templates/flutter-standalone/pubspec.yaml +20 -0
- package/templates/flutter-standalone/sh-ui.config.json +15 -0
- package/templates/monorepo/.dockerignore +7 -0
- package/templates/monorepo/.eslintrc.js +8 -0
- package/templates/monorepo/.prettierrc +17 -0
- package/templates/monorepo/README.md +103 -0
- package/templates/monorepo/package.json +24 -0
- package/templates/monorepo/packages/eslint-config/base.js +31 -0
- package/templates/monorepo/packages/eslint-config/fsd.js +119 -0
- package/templates/monorepo/packages/eslint-config/next.js +65 -0
- package/templates/monorepo/packages/eslint-config/package.json +31 -0
- package/templates/monorepo/packages/eslint-config/react-internal.js +36 -0
- package/templates/monorepo/packages/typescript-config/base.json +20 -0
- package/templates/monorepo/packages/typescript-config/nextjs.json +13 -0
- package/templates/monorepo/packages/typescript-config/package.json +5 -0
- package/templates/monorepo/packages/typescript-config/react-library.json +8 -0
- package/templates/monorepo/packages/ui/ui-apps/.gitkeep +0 -0
- package/templates/monorepo/packages/ui/ui-core/eslint.config.js +3 -0
- package/templates/monorepo/packages/ui/ui-core/package.json +23 -0
- package/templates/monorepo/packages/ui/ui-core/src/lib/utils.ts +6 -0
- package/templates/monorepo/packages/ui/ui-core/tsconfig.json +11 -0
- package/templates/monorepo/pnpm-workspace.yaml +5 -0
- package/templates/monorepo/tsconfig.json +3 -0
- package/templates/monorepo/turbo.json +26 -0
- package/templates/nextjs-app/.env.example +2 -0
- package/templates/nextjs-app/Dockerfile +11 -0
- package/templates/nextjs-app/README.md +64 -0
- package/templates/nextjs-app/app/layout.tsx +22 -0
- package/templates/nextjs-app/app/page.tsx +7 -0
- package/templates/nextjs-app/eslint.config.js +10 -0
- package/templates/nextjs-app/next.config.ts +12 -0
- package/templates/nextjs-app/package.json +45 -0
- package/templates/nextjs-app/postcss.config.mjs +1 -0
- package/templates/nextjs-app/src/app/layouts/.gitkeep +0 -0
- package/templates/nextjs-app/src/app/providers/GlobalProvider/index.tsx +23 -0
- package/templates/nextjs-app/src/app/providers/index.tsx +1 -0
- package/templates/nextjs-app/src/app/providers/tanstack/QueryClientProvider.tsx +27 -0
- package/templates/nextjs-app/src/app/providers/tanstack/TanstackDevtoolsProvider.tsx +13 -0
- package/templates/nextjs-app/src/app/providers/theme/ThemeProviders.tsx +12 -0
- package/templates/nextjs-app/src/entities/.gitkeep +0 -0
- package/templates/nextjs-app/src/features/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/api/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/config/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/hooks/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/lib/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/model/.gitkeep +0 -0
- package/templates/nextjs-app/src/shared/ui/.gitkeep +0 -0
- package/templates/nextjs-app/src/views/.gitkeep +0 -0
- package/templates/nextjs-app/src/widgets/.gitkeep +0 -0
- package/templates/nextjs-app/tsconfig.json +23 -0
- package/templates/nextjs-app/vitest.config.ts +15 -0
- package/templates/nextjs-app/vitest.setup.ts +1 -0
- package/templates/nextjs-standalone/.env.example +2 -0
- package/templates/nextjs-standalone/.prettierrc +17 -0
- package/templates/nextjs-standalone/README.md +77 -0
- package/templates/nextjs-standalone/app/globals.css +33 -0
- package/templates/nextjs-standalone/app/layout.tsx +22 -0
- package/templates/nextjs-standalone/app/page.tsx +7 -0
- package/templates/nextjs-standalone/eslint.config.js +162 -0
- package/templates/nextjs-standalone/next.config.ts +10 -0
- package/templates/nextjs-standalone/package.json +66 -0
- package/templates/nextjs-standalone/postcss.config.mjs +5 -0
- package/templates/nextjs-standalone/sh-ui.config.json +19 -0
- package/templates/nextjs-standalone/src/app/layouts/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/app/providers/GlobalProvider/index.tsx +23 -0
- package/templates/nextjs-standalone/src/app/providers/index.tsx +1 -0
- package/templates/nextjs-standalone/src/app/providers/tanstack/QueryClientProvider.tsx +27 -0
- package/templates/nextjs-standalone/src/app/providers/tanstack/TanstackDevtoolsProvider.tsx +13 -0
- package/templates/nextjs-standalone/src/app/providers/theme/ThemeProviders.tsx +12 -0
- package/templates/nextjs-standalone/src/entities/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/features/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/shared/api/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/shared/config/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/shared/hooks/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/shared/lib/utils.ts +6 -0
- package/templates/nextjs-standalone/src/shared/model/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/shared/styles/tokens.css +95 -0
- package/templates/nextjs-standalone/src/shared/ui/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/views/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/widgets/.gitkeep +0 -0
- package/templates/nextjs-standalone/tsconfig.json +39 -0
- package/templates/nextjs-standalone/vitest.config.ts +15 -0
- package/templates/nextjs-standalone/vitest.setup.ts +1 -0
- package/templates/ui-app-template/eslint.config.js +3 -0
- package/templates/ui-app-template/package.json +38 -0
- package/templates/ui-app-template/postcss.config.mjs +5 -0
- package/templates/ui-app-template/sh-ui.config.json +14 -0
- package/templates/ui-app-template/src/components/.gitkeep +0 -0
- package/templates/ui-app-template/src/hooks/.gitkeep +0 -0
- package/templates/ui-app-template/src/lib/.gitkeep +0 -0
- package/templates/ui-app-template/src/styles/globals.css +37 -0
- package/templates/ui-app-template/src/styles/tokens.css +95 -0
- package/templates/ui-app-template/tsconfig.json +11 -0
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@workspace/typescript-config/nextjs.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"paths": {
|
|
6
|
+
"@/*": ["./*"],
|
|
7
|
+
"@workspace/ui-app-name/*": ["../../packages/ui/ui-apps/ui-app-name/src/*"]
|
|
8
|
+
},
|
|
9
|
+
"plugins": [
|
|
10
|
+
{
|
|
11
|
+
"name": "next"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"next-env.d.ts",
|
|
17
|
+
"next.config.ts",
|
|
18
|
+
"**/*.ts",
|
|
19
|
+
"**/*.tsx",
|
|
20
|
+
".next/types/**/*.ts"
|
|
21
|
+
],
|
|
22
|
+
"exclude": ["node_modules"]
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { defineConfig } from 'vitest/config';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
resolve: {
|
|
6
|
+
alias: {
|
|
7
|
+
'@': path.resolve(__dirname, '.'),
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
test: {
|
|
11
|
+
globals: true,
|
|
12
|
+
environment: 'jsdom',
|
|
13
|
+
setupFiles: ['./vitest.setup.ts'],
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"arrowParens": "always",
|
|
3
|
+
"bracketSpacing": true,
|
|
4
|
+
"endOfLine": "auto",
|
|
5
|
+
"htmlWhitespaceSensitivity": "css",
|
|
6
|
+
"bracketSameLine": true,
|
|
7
|
+
"jsxSingleQuote": true,
|
|
8
|
+
"printWidth": 80,
|
|
9
|
+
"proseWrap": "always",
|
|
10
|
+
"quoteProps": "as-needed",
|
|
11
|
+
"semi": true,
|
|
12
|
+
"singleQuote": true,
|
|
13
|
+
"tabWidth": 2,
|
|
14
|
+
"trailingComma": "all",
|
|
15
|
+
"useTabs": false,
|
|
16
|
+
"plugins": ["prettier-plugin-tailwindcss"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Next.js Standalone Template
|
|
2
|
+
|
|
3
|
+
단독 실행 가능한 Next.js 프로젝트 템플릿 (sh-ui 기반).
|
|
4
|
+
|
|
5
|
+
## 기술 스택
|
|
6
|
+
|
|
7
|
+
- **Next.js 16** (App Router, React Compiler)
|
|
8
|
+
- **React 19**
|
|
9
|
+
- **TypeScript 5.9**
|
|
10
|
+
- **Tailwind CSS 4** + **sh-ui** (neutral, radius=md, light-dark)
|
|
11
|
+
- **@base-ui-components/react** (sh-ui가 의존하는 언스타일드 primitive)
|
|
12
|
+
- **TanStack React Query** + **Axios** (데이터 페칭)
|
|
13
|
+
- **Zustand** (상태 관리)
|
|
14
|
+
- **next-themes** (다크 모드)
|
|
15
|
+
- **Sonner** (토스트)
|
|
16
|
+
- **Zod** (유효성 검증)
|
|
17
|
+
- **ESLint 9** (flat config, FSD 규칙 포함)
|
|
18
|
+
- **Prettier** (tailwind 플러그인)
|
|
19
|
+
- **Vitest** + **Testing Library**
|
|
20
|
+
|
|
21
|
+
## 프로젝트 구조
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
├── app/ # Next.js App Router
|
|
25
|
+
│ ├── layout.tsx # 루트 레이아웃
|
|
26
|
+
│ ├── page.tsx # 홈 페이지
|
|
27
|
+
│ └── globals.css # Tailwind + sh-ui tokens import
|
|
28
|
+
├── src/
|
|
29
|
+
│ ├── app/
|
|
30
|
+
│ │ └── providers/ # QueryClient, Theme, Toaster
|
|
31
|
+
│ ├── shared/ # FSD: 공유 유틸/설정/UI
|
|
32
|
+
│ │ ├── ui/ # ← sh-ui 컴포넌트가 여기로 복사됨
|
|
33
|
+
│ │ ├── lib/
|
|
34
|
+
│ │ │ └── utils.ts # cn() 유틸
|
|
35
|
+
│ │ ├── styles/
|
|
36
|
+
│ │ │ └── tokens.css # sh-ui 디자인 토큰
|
|
37
|
+
│ │ ├── hooks/
|
|
38
|
+
│ │ ├── api/
|
|
39
|
+
│ │ ├── config/
|
|
40
|
+
│ │ └── model/
|
|
41
|
+
│ ├── views/ # FSD: 페이지 단위 뷰
|
|
42
|
+
│ ├── widgets/ # FSD: 조합형 UI 블록
|
|
43
|
+
│ ├── features/ # FSD: 기능 단위
|
|
44
|
+
│ └── entities/ # FSD: 비즈니스 엔티티
|
|
45
|
+
├── sh-ui.config.json # sh-ui 설정 (platform, theme, paths)
|
|
46
|
+
├── eslint.config.js # ESLint flat config (FSD boundaries 포함)
|
|
47
|
+
├── next.config.ts
|
|
48
|
+
├── tsconfig.json
|
|
49
|
+
├── vitest.config.ts
|
|
50
|
+
├── .prettierrc
|
|
51
|
+
└── .env.example
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## FSD (Feature-Sliced Design) 레이어 규칙
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
app → view → widget → feature → entity → shared
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
상위 레이어는 하위 레이어만 import 가능. ESLint `boundaries` 플러그인으로 강제됨.
|
|
61
|
+
|
|
62
|
+
## 시작하기
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm install
|
|
66
|
+
pnpm dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## sh-ui 컴포넌트 추가
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx sh-ui add button
|
|
73
|
+
npx sh-ui add dialog
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`sh-ui.config.json` 의 `paths.components` 설정에 따라 `src/shared/ui/` 에 복사됩니다.
|
|
77
|
+
토큰을 커스텀하려면 `sh-ui.config.json` 의 `theme` 값을 바꾸고 `npx sh-ui add tokens` 로 재생성.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
@import '../src/shared/styles/tokens.css';
|
|
3
|
+
|
|
4
|
+
@custom-variant dark (&:is(.dark *));
|
|
5
|
+
|
|
6
|
+
@theme inline {
|
|
7
|
+
--color-background: var(--background);
|
|
8
|
+
--color-background-subtle: var(--background-subtle);
|
|
9
|
+
--color-background-muted: var(--background-muted);
|
|
10
|
+
--color-background-inverse: var(--background-inverse);
|
|
11
|
+
--color-foreground: var(--foreground);
|
|
12
|
+
--color-foreground-muted: var(--foreground-muted);
|
|
13
|
+
--color-foreground-subtle: var(--foreground-subtle);
|
|
14
|
+
--color-foreground-inverse: var(--foreground-inverse);
|
|
15
|
+
--color-border: var(--border);
|
|
16
|
+
--color-border-strong: var(--border-strong);
|
|
17
|
+
--color-primary: var(--primary);
|
|
18
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
19
|
+
--color-primary-hover: var(--primary-hover);
|
|
20
|
+
--color-danger: var(--danger);
|
|
21
|
+
--color-danger-foreground: var(--danger-foreground);
|
|
22
|
+
--radius-sm: calc(var(--radius) - 2px);
|
|
23
|
+
--radius-md: var(--radius);
|
|
24
|
+
--radius-lg: calc(var(--radius) + 2px);
|
|
25
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@layer base {
|
|
29
|
+
body {
|
|
30
|
+
background: var(--background);
|
|
31
|
+
color: var(--foreground);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import { GlobalProvider } from '@/src/app/providers';
|
|
3
|
+
import './globals.css';
|
|
4
|
+
|
|
5
|
+
export const metadata: Metadata = {
|
|
6
|
+
title: 'My App',
|
|
7
|
+
description: 'My App Description',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({
|
|
11
|
+
children,
|
|
12
|
+
}: {
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}) {
|
|
15
|
+
return (
|
|
16
|
+
<html lang='ko' suppressHydrationWarning>
|
|
17
|
+
<body>
|
|
18
|
+
<GlobalProvider>{children}</GlobalProvider>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import js from "@eslint/js"
|
|
2
|
+
import pluginNext from "@next/eslint-plugin-next"
|
|
3
|
+
import eslintConfigPrettier from "eslint-config-prettier"
|
|
4
|
+
import boundaries from "eslint-plugin-boundaries"
|
|
5
|
+
import checkFile from "eslint-plugin-check-file"
|
|
6
|
+
import importX from "eslint-plugin-import-x"
|
|
7
|
+
import onlyWarn from "eslint-plugin-only-warn"
|
|
8
|
+
import pluginReact from "eslint-plugin-react"
|
|
9
|
+
import pluginReactHooks from "eslint-plugin-react-hooks"
|
|
10
|
+
import globals from "globals"
|
|
11
|
+
import tseslint from "typescript-eslint"
|
|
12
|
+
import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript"
|
|
13
|
+
|
|
14
|
+
export default [
|
|
15
|
+
{
|
|
16
|
+
ignores: [".next/**", "dist/**", "node_modules/**"],
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
// ── Base ──
|
|
20
|
+
js.configs.recommended,
|
|
21
|
+
eslintConfigPrettier,
|
|
22
|
+
...tseslint.configs.recommended,
|
|
23
|
+
{
|
|
24
|
+
plugins: { onlyWarn },
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
rules: {
|
|
28
|
+
"@typescript-eslint/no-unused-vars": [
|
|
29
|
+
"warn",
|
|
30
|
+
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// ── React + Next.js ──
|
|
36
|
+
{
|
|
37
|
+
...pluginReact.configs.flat.recommended,
|
|
38
|
+
languageOptions: {
|
|
39
|
+
...pluginReact.configs.flat.recommended.languageOptions,
|
|
40
|
+
globals: {
|
|
41
|
+
...globals.serviceworker,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
plugins: {
|
|
47
|
+
"@next/next": pluginNext,
|
|
48
|
+
},
|
|
49
|
+
rules: {
|
|
50
|
+
...pluginNext.configs.recommended.rules,
|
|
51
|
+
...pluginNext.configs["core-web-vitals"].rules,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
plugins: {
|
|
56
|
+
"react-hooks": pluginReactHooks,
|
|
57
|
+
},
|
|
58
|
+
settings: { react: { version: "detect" } },
|
|
59
|
+
rules: {
|
|
60
|
+
...pluginReactHooks.configs.recommended.rules,
|
|
61
|
+
"react/react-in-jsx-scope": "off",
|
|
62
|
+
"react/prop-types": "off",
|
|
63
|
+
"react/function-component-definition": [
|
|
64
|
+
"warn",
|
|
65
|
+
{
|
|
66
|
+
namedComponents: "function-declaration",
|
|
67
|
+
unnamedComponents: "arrow-function",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// ── FSD boundaries ──
|
|
74
|
+
{
|
|
75
|
+
plugins: { boundaries },
|
|
76
|
+
settings: {
|
|
77
|
+
"boundaries/elements": [
|
|
78
|
+
{ type: "app", pattern: ["src/app"], mode: "folder" },
|
|
79
|
+
{ type: "shared", pattern: ["src/shared/*"], mode: "folder" },
|
|
80
|
+
{ type: "entity", pattern: ["src/entities/*"], mode: "folder" },
|
|
81
|
+
{ type: "feature", pattern: ["src/features/*"], mode: "folder" },
|
|
82
|
+
{ type: "widget", pattern: ["src/widgets/*"], mode: "folder" },
|
|
83
|
+
{ type: "view", pattern: ["src/views/*"], mode: "folder" },
|
|
84
|
+
],
|
|
85
|
+
"boundaries/ignore": ["**/*.test.*", "**/*.spec.*"],
|
|
86
|
+
},
|
|
87
|
+
rules: {
|
|
88
|
+
"boundaries/element-types": [
|
|
89
|
+
"warn",
|
|
90
|
+
{
|
|
91
|
+
default: "disallow",
|
|
92
|
+
rules: [
|
|
93
|
+
{ from: "app", allow: ["view", "widget", "feature", "entity", "shared"] },
|
|
94
|
+
{ from: "view", allow: ["widget", "feature", "entity", "shared"] },
|
|
95
|
+
{ from: "widget", allow: ["feature", "entity", "shared"] },
|
|
96
|
+
{ from: "feature", allow: ["entity", "shared"] },
|
|
97
|
+
{ from: "entity", allow: ["shared"] },
|
|
98
|
+
{ from: "shared", allow: ["shared"] },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
"boundaries/entry-point": [
|
|
103
|
+
"warn",
|
|
104
|
+
{
|
|
105
|
+
default: "disallow",
|
|
106
|
+
rules: [
|
|
107
|
+
{ target: "shared", allow: "**" },
|
|
108
|
+
{ target: "app", allow: "**" },
|
|
109
|
+
{
|
|
110
|
+
target: ["entity", "widget", "view"],
|
|
111
|
+
allow: "index.{ts,tsx}",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
target: ["feature"],
|
|
115
|
+
allow: ["index.{ts,tsx}", "*/index.{ts,tsx}"],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// ── File naming ──
|
|
124
|
+
{
|
|
125
|
+
plugins: { "check-file": checkFile },
|
|
126
|
+
rules: {
|
|
127
|
+
"check-file/filename-naming-convention": [
|
|
128
|
+
"error",
|
|
129
|
+
{
|
|
130
|
+
"**/src/**/*.tsx": "PASCAL_CASE",
|
|
131
|
+
"**/src/**/*.ts": "CAMEL_CASE",
|
|
132
|
+
},
|
|
133
|
+
{ ignoreMiddleExtensions: true },
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
files: [
|
|
139
|
+
"**/index.tsx", "**/index.ts",
|
|
140
|
+
"**/layout.tsx", "**/page.tsx",
|
|
141
|
+
"**/error.tsx", "**/not-found.tsx",
|
|
142
|
+
"**/routing.ts", "**/navigation.ts", "**/request.ts",
|
|
143
|
+
],
|
|
144
|
+
rules: {
|
|
145
|
+
"check-file/filename-naming-convention": "off",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
// ── import-x ──
|
|
150
|
+
{
|
|
151
|
+
plugins: { "import-x": importX },
|
|
152
|
+
settings: {
|
|
153
|
+
"import-x/resolver-next": [
|
|
154
|
+
createTypeScriptImportResolver({ alwaysTryTypes: true }),
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
rules: {
|
|
158
|
+
"import-x/order": "off",
|
|
159
|
+
"import-x/no-unresolved": "off",
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-app",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"private": true,
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev --turbopack",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start",
|
|
10
|
+
"lint": "eslint .",
|
|
11
|
+
"lint:fix": "eslint . --fix",
|
|
12
|
+
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@base-ui-components/react": "latest",
|
|
19
|
+
"@tanstack/react-query": "^5.90.21",
|
|
20
|
+
"axios": "^1.13.6",
|
|
21
|
+
"class-variance-authority": "^0.7.1",
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
|
+
"lucide-react": "^0.563.0",
|
|
24
|
+
"next": "16.1.6",
|
|
25
|
+
"next-themes": "^0.4.6",
|
|
26
|
+
"react": "^19.2.4",
|
|
27
|
+
"react-dom": "^19.2.4",
|
|
28
|
+
"sonner": "^2.0.7",
|
|
29
|
+
"tailwind-merge": "^3.5.0",
|
|
30
|
+
"zod": "^4.3.6",
|
|
31
|
+
"zustand": "^5.0.11"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@eslint/js": "^9.39.2",
|
|
35
|
+
"@next/eslint-plugin-next": "^16.1.6",
|
|
36
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
37
|
+
"@tanstack/react-query-devtools": "^5.91.3",
|
|
38
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
39
|
+
"@types/node": "^25.1.0",
|
|
40
|
+
"@types/react": "^19.2.10",
|
|
41
|
+
"@types/react-dom": "^19.2.3",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
43
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
44
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
45
|
+
"eslint": "^9.39.2",
|
|
46
|
+
"eslint-config-prettier": "^10.1.8",
|
|
47
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
48
|
+
"eslint-plugin-boundaries": "^5.4.0",
|
|
49
|
+
"eslint-plugin-check-file": "^3.3.1",
|
|
50
|
+
"eslint-plugin-import-x": "^4.16.1",
|
|
51
|
+
"eslint-plugin-only-warn": "^1.1.0",
|
|
52
|
+
"eslint-plugin-react": "^7.37.5",
|
|
53
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
54
|
+
"jsdom": "^29.0.0",
|
|
55
|
+
"prettier": "^3.8.1",
|
|
56
|
+
"prettier-plugin-tailwindcss": "^0.6.13",
|
|
57
|
+
"tailwindcss": "^4.1.18",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"typescript-eslint": "^8.54.0",
|
|
60
|
+
"vitest": "^4.1.0"
|
|
61
|
+
},
|
|
62
|
+
"packageManager": "pnpm@10.4.1",
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=20"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"platform": "react",
|
|
3
|
+
"style": "default",
|
|
4
|
+
"theme": {
|
|
5
|
+
"base": "neutral",
|
|
6
|
+
"radius": "md",
|
|
7
|
+
"mode": "light-dark"
|
|
8
|
+
},
|
|
9
|
+
"paths": {
|
|
10
|
+
"tokens": "src/shared/styles/tokens.css",
|
|
11
|
+
"components": "src/shared/ui",
|
|
12
|
+
"utils": "src/shared/lib/utils.ts"
|
|
13
|
+
},
|
|
14
|
+
"aliases": {
|
|
15
|
+
"components": "@/src/shared/ui",
|
|
16
|
+
"utils": "@/src/shared/lib/utils",
|
|
17
|
+
"ui": "@/src/shared/ui"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { Toaster } from 'sonner';
|
|
3
|
+
|
|
4
|
+
import { QueryClientProvider } from '../tanstack/QueryClientProvider';
|
|
5
|
+
import { TanstackDevtoolsProvider } from '../tanstack/TanstackDevtoolsProvider';
|
|
6
|
+
import { ThemeProviders } from '../theme/ThemeProviders';
|
|
7
|
+
|
|
8
|
+
interface GlobalProviderProps {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function GlobalProvider({ children }: GlobalProviderProps) {
|
|
13
|
+
return (
|
|
14
|
+
<ThemeProviders>
|
|
15
|
+
<QueryClientProvider>
|
|
16
|
+
<TanstackDevtoolsProvider>
|
|
17
|
+
<Toaster />
|
|
18
|
+
{children}
|
|
19
|
+
</TanstackDevtoolsProvider>
|
|
20
|
+
</QueryClientProvider>
|
|
21
|
+
</ThemeProviders>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GlobalProvider } from './GlobalProvider';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
QueryClient,
|
|
5
|
+
QueryClientProvider as TanstackQueryClientProvider,
|
|
6
|
+
} from '@tanstack/react-query';
|
|
7
|
+
import { useState, type ReactNode } from 'react';
|
|
8
|
+
|
|
9
|
+
export function QueryClientProvider({ children }: { children: ReactNode }) {
|
|
10
|
+
const [queryClient] = useState(
|
|
11
|
+
() =>
|
|
12
|
+
new QueryClient({
|
|
13
|
+
defaultOptions: {
|
|
14
|
+
queries: {
|
|
15
|
+
staleTime: 60 * 1000,
|
|
16
|
+
retry: 1,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<TanstackQueryClientProvider client={queryClient}>
|
|
24
|
+
{children}
|
|
25
|
+
</TanstackQueryClientProvider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
export function TanstackDevtoolsProvider({ children }: { children: ReactNode }) {
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
{children}
|
|
10
|
+
<ReactQueryDevtools initialIsOpen={false} />
|
|
11
|
+
</>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ThemeProvider } from 'next-themes';
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
export function ThemeProviders({ children }: { children: ReactNode }) {
|
|
7
|
+
return (
|
|
8
|
+
<ThemeProvider attribute='class' defaultTheme='system' enableSystem>
|
|
9
|
+
{children}
|
|
10
|
+
</ThemeProvider>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|