@component-hook/create-app 1.5.1 → 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.
Files changed (105) hide show
  1. package/README.md +1 -0
  2. package/package.json +10 -10
  3. package/template-react/.vscode/extensions.json +9 -0
  4. package/template-react/.vscode/settings.json +18 -0
  5. package/template-react/README.md.art +85 -0
  6. package/template-react/e2e/home.spec.ts +40 -0
  7. package/template-react/eslint.config.js +18 -0
  8. package/template-react/index.html.art +13 -0
  9. package/template-react/lint-staged.config.js +6 -0
  10. package/template-react/package.json +70 -0
  11. package/template-react/public/vite.svg +1 -0
  12. package/template-react/src/App.tsx +6 -0
  13. package/template-react/src/assets/svg-icons/react.svg +1 -0
  14. package/template-react/src/components/common/index.ts +1 -0
  15. package/template-react/src/components/common/svg-icon/index.ts +1 -0
  16. package/template-react/src/components/common/svg-icon/src/index.tsx +23 -0
  17. package/template-react/src/main.tsx +26 -0
  18. package/template-react/src/mocks/browser.ts +4 -0
  19. package/template-react/src/mocks/handlers/index.ts +1 -0
  20. package/template-react/src/mocks/server.ts +4 -0
  21. package/template-react/src/pages/home/components/hello-world/index.test.tsx +45 -0
  22. package/template-react/src/pages/home/components/hello-world/index.tsx +49 -0
  23. package/template-react/src/pages/home/index.module.css +8 -0
  24. package/template-react/src/pages/home/index.test.tsx +19 -0
  25. package/template-react/src/pages/home/index.tsx +37 -0
  26. package/template-react/src/plugins/i18n/index.ts +19 -0
  27. package/template-react/src/plugins/i18n/locales/en-US.json +3 -0
  28. package/template-react/src/plugins/i18n/locales/zh-TW.json +3 -0
  29. package/template-react/src/router/index.tsx +22 -0
  30. package/template-react/src/stores/constants.ts +1 -0
  31. package/template-react/src/stores/index.ts +1 -0
  32. package/template-react/src/stores/middleware.ts +17 -0
  33. package/template-react/src/stores/modules/config.ts +27 -0
  34. package/template-react/src/styles/base.css +68 -0
  35. package/template-react/src/styles/common/all.css +1 -0
  36. package/template-react/src/styles/common/button.css +26 -0
  37. package/template-react/src/styles/index.css +3 -0
  38. package/template-react/src/styles/tailwind.css +14 -0
  39. package/template-react/src/test-utils/index.tsx +15 -0
  40. package/template-react/src/vite-env.d.ts +9 -0
  41. package/template-react/tsconfig.app.json +32 -0
  42. package/template-react/tsconfig.vitest.json +10 -0
  43. package/template-react/vite.config.ts +40 -0
  44. package/template-react/vitest.config.ts +18 -0
  45. package/template-react/vitest.setup.ts +13 -0
  46. package/template-shared/.browserslistrc +10 -0
  47. package/template-shared/.github/actions/setup-environment/action.yml +21 -0
  48. package/template-shared/.github/renovate.json +14 -0
  49. package/template-shared/.github/workflows/ci.yml +22 -0
  50. package/template-shared/.github/workflows/deploy.yml +27 -0
  51. package/template-shared/.github/workflows/preview.yml +17 -0
  52. package/template-shared/.gitlab/setup.yml +18 -0
  53. package/template-shared/.husky/commit-msg +1 -0
  54. package/template-shared/.husky/pre-commit +1 -0
  55. package/{LICENSE → template-shared/LICENSE} +1 -1
  56. package/template-shared/_gitignore +32 -0
  57. package/template-shared/_gitlab-ci.yml +22 -0
  58. package/template-shared/commitlint.config.js +3 -0
  59. package/template-shared/playwright.config.ts +49 -0
  60. package/template-shared/postcss.config.js +15 -0
  61. package/template-shared/prettier.config.js +13 -0
  62. package/template-shared/scripts/build-info/index.ts +21 -0
  63. package/template-shared/tsconfig.json +14 -0
  64. package/template-shared/tsconfig.node.json +12 -0
  65. package/template-vue/.vscode/extensions.json +10 -0
  66. package/template-vue/.vscode/settings.json +18 -0
  67. package/template-vue/README.md.art +81 -0
  68. package/template-vue/e2e/home.spec.ts +59 -0
  69. package/template-vue/eslint.config.js +18 -0
  70. package/template-vue/index.html.art +28 -0
  71. package/template-vue/lint-staged.config.js +6 -0
  72. package/template-vue/package.json +69 -0
  73. package/template-vue/public/vite.svg +1 -0
  74. package/template-vue/src/App.vue +7 -0
  75. package/template-vue/src/assets/svg-icons/vue.svg +1 -0
  76. package/template-vue/src/components/common/index.ts +1 -0
  77. package/template-vue/src/components/common/svg-icon/index.ts +1 -0
  78. package/template-vue/src/components/common/svg-icon/src/index.vue +29 -0
  79. package/template-vue/src/locales/en-US.json +3 -0
  80. package/template-vue/src/locales/zh-TW.json +3 -0
  81. package/template-vue/src/main.ts +21 -0
  82. package/template-vue/src/mocks/browser.ts +4 -0
  83. package/template-vue/src/mocks/handlers/index.ts +1 -0
  84. package/template-vue/src/mocks/server.ts +4 -0
  85. package/template-vue/src/pages/home/components/HelloWorld.test.ts +57 -0
  86. package/template-vue/src/pages/home/components/HelloWorld.vue +54 -0
  87. package/template-vue/src/pages/home/index.test.ts +17 -0
  88. package/template-vue/src/pages/home/index.vue +46 -0
  89. package/template-vue/src/plugins/i18n.ts +11 -0
  90. package/template-vue/src/router/index.ts +23 -0
  91. package/template-vue/src/stores/constants.ts.art +1 -0
  92. package/template-vue/src/stores/index.ts +15 -0
  93. package/template-vue/src/stores/modules/config.ts +20 -0
  94. package/template-vue/src/styles/base.css +59 -0
  95. package/template-vue/src/styles/common/all.css +1 -0
  96. package/template-vue/src/styles/common/button.css +15 -0
  97. package/template-vue/src/styles/index.css +3 -0
  98. package/template-vue/src/styles/tailwind.css +1 -0
  99. package/template-vue/src/test-utils/index.ts +33 -0
  100. package/template-vue/src/vite-env.d.ts +9 -0
  101. package/template-vue/tsconfig.app.json +12 -0
  102. package/template-vue/tsconfig.vitest.json +10 -0
  103. package/template-vue/vite.config.ts +46 -0
  104. package/template-vue/vitest.config.ts +18 -0
  105. package/template-vue/vitest.setup.ts +12 -0
@@ -0,0 +1,17 @@
1
+ import { create, type StateCreator } from 'zustand';
2
+ import { createJSONStorage, persist, type PersistOptions } from 'zustand/middleware';
3
+ import { STORAGE_PREFIX } from './constants';
4
+
5
+ export function createPersistedStore<T, S = Partial<T>>(
6
+ id: string,
7
+ initializer: StateCreator<T>,
8
+ persistOptions?: Partial<PersistOptions<T, S>>,
9
+ ) {
10
+ return create(
11
+ persist<T, [], [], S>(initializer, {
12
+ name: `${STORAGE_PREFIX}-${id}`,
13
+ storage: createJSONStorage(() => localStorage),
14
+ ...persistOptions,
15
+ }),
16
+ );
17
+ }
@@ -0,0 +1,27 @@
1
+ import { createPersistedStore } from '../middleware';
2
+
3
+ interface ConfigState {
4
+ appMeta: {
5
+ version: string;
6
+ builtAt: Date;
7
+ };
8
+ }
9
+
10
+ const versionString = `${import.meta.env.VITE_APP_VERSION}-${import.meta.env.VITE_APP_LAST_COMMIT_HASH}`;
11
+
12
+ const defaultState = {
13
+ appMeta: {
14
+ version: import.meta.env.MODE === 'development' ? `${versionString}-dev` : versionString,
15
+ builtAt: new Date(Number(import.meta.env.VITE_APP_BUILD_EPOCH)),
16
+ },
17
+ };
18
+
19
+ export const useConfigStore = createPersistedStore<ConfigState>(
20
+ 'config',
21
+ () => ({
22
+ ...defaultState,
23
+ }),
24
+ {
25
+ partialize: () => ({}),
26
+ },
27
+ );
@@ -0,0 +1,68 @@
1
+ :root {
2
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+
6
+ color-scheme: light dark;
7
+ color: rgba(255, 255, 255, 0.87);
8
+ background-color: #242424;
9
+
10
+ overscroll-behavior: none none;
11
+ touch-action: manipulation;
12
+ user-select: none;
13
+ text-rendering: optimizeLegibility;
14
+ -moz-osx-font-smoothing: grayscale;
15
+ -moz-touch-callout: none;
16
+ -ms-touch-callout: none;
17
+ -webkit-font-smoothing: antialiased;
18
+ -webkit-touch-callout: none;
19
+ -webkit-overflow-scrolling: touch;
20
+ }
21
+
22
+ a {
23
+ font-weight: 500;
24
+ color: #646cff;
25
+ text-decoration: inherit;
26
+
27
+ &:hover {
28
+ color: #535bf2;
29
+ }
30
+ }
31
+
32
+ body {
33
+ margin: 0;
34
+ display: flex;
35
+ place-items: center;
36
+ min-width: 320px;
37
+ min-height: 100vh;
38
+ }
39
+
40
+ img {
41
+ -webkit-touch-callout: none;
42
+ -webkit-user-drag: none;
43
+ user-select: none;
44
+ }
45
+
46
+ h1 {
47
+ font-size: 3.2em;
48
+ line-height: 1.1;
49
+ }
50
+
51
+ #root {
52
+ max-width: 1280px;
53
+ width: 100%;
54
+ margin: 0 auto;
55
+ padding: 2rem;
56
+ text-align: center;
57
+ }
58
+
59
+ @media (prefers-color-scheme: light) {
60
+ :root {
61
+ color: #213547;
62
+ background-color: #ffffff;
63
+ }
64
+
65
+ a:hover {
66
+ color: #747bff;
67
+ }
68
+ }
@@ -0,0 +1 @@
1
+ @import './button.css';
@@ -0,0 +1,26 @@
1
+ button {
2
+ border-radius: 8px;
3
+ border: 1px solid transparent;
4
+ padding: 0.6em 1.2em;
5
+ font-size: 1em;
6
+ font-weight: 500;
7
+ font-family: inherit;
8
+ background-color: #1a1a1a;
9
+ cursor: pointer;
10
+ transition: border-color 0.25s;
11
+
12
+ &:hover {
13
+ border-color: #646cff;
14
+ }
15
+
16
+ &:focus,
17
+ &:focus-visible {
18
+ outline: 4px auto -webkit-focus-ring-color;
19
+ }
20
+ }
21
+
22
+ @media (prefers-color-scheme: light) {
23
+ button {
24
+ background-color: #f9f9f9;
25
+ }
26
+ }
@@ -0,0 +1,3 @@
1
+ @import './tailwind.css';
2
+ @import './base.css';
3
+ @import './common/all.css';
@@ -0,0 +1,14 @@
1
+ @import 'tailwindcss';
2
+
3
+ @theme {
4
+ --animate-logo-spin: logo-spin infinite 20s linear;
5
+
6
+ @keyframes logo-spin {
7
+ from {
8
+ transform: rotate(0deg);
9
+ }
10
+ to {
11
+ transform: rotate(360deg);
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ import { render } from '@testing-library/react';
2
+ import { MemoryRouter } from 'react-router-dom';
3
+ import type { RenderOptions } from '@testing-library/react/types';
4
+ import type { ReactElement, ReactNode } from 'react';
5
+
6
+ function ProvidersWrapper({ children }: { children: ReactNode }) {
7
+ return <MemoryRouter>{children}</MemoryRouter>;
8
+ }
9
+
10
+ export function renderComponent(
11
+ component: ReactElement,
12
+ options?: Omit<RenderOptions, 'wrapper'>,
13
+ ): ReturnType<typeof render> {
14
+ return render(component, { wrapper: ProvidersWrapper, ...options });
15
+ }
@@ -0,0 +1,9 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare module 'virtual:svg-icons-register';
4
+
5
+ interface ImportMetaEnv extends Readonly<Record<string, string>> {
6
+ readonly VITE_APP_VERSION: string;
7
+ readonly VITE_APP_MOCK?: 'service-worker';
8
+ readonly VITE_APP_BUILD_EPOCH?: string;
9
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "target": "ES2020",
6
+ "jsx": "react-jsx",
7
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
+ "moduleDetection": "force",
9
+ "useDefineForClassFields": true,
10
+ "module": "ESNext",
11
+
12
+ /* Bundler mode */
13
+ "moduleResolution": "bundler",
14
+ "paths": {
15
+ "@/*": ["./src/*"]
16
+ },
17
+ "allowImportingTsExtensions": true,
18
+
19
+ /* Linting */
20
+ "strict": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "noUncheckedSideEffectImports": true,
23
+ "noUnusedLocals": true,
24
+ "noUnusedParameters": true,
25
+ "noEmit": true,
26
+ "verbatimModuleSyntax": true,
27
+ "erasableSyntaxOnly": true,
28
+ "skipLibCheck": true
29
+ },
30
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx"],
31
+ "exclude": ["src/**/*.test.*", "src/test-utils"]
32
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.app.json",
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
6
+ "types": ["vitest/globals"]
7
+ },
8
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "vitest.setup.ts"],
9
+ "exclude": []
10
+ }
@@ -0,0 +1,40 @@
1
+ import { resolve } from 'node:path';
2
+ import { fileURLToPath, URL } from 'node:url';
3
+ import tailwindcss from '@tailwindcss/vite';
4
+ import react from '@vitejs/plugin-react-swc';
5
+ import { defineConfig } from 'vite';
6
+ import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
7
+ import './scripts/build-info';
8
+
9
+ export default defineConfig({
10
+ base: './',
11
+ plugins: [
12
+ react(),
13
+ tailwindcss(),
14
+ createSvgIconsPlugin({
15
+ iconDirs: [resolve(process.cwd(), 'src/assets/svg-icons')],
16
+ }),
17
+ ],
18
+ esbuild: {
19
+ pure: ['console.log'],
20
+ drop: ['debugger'],
21
+ },
22
+ resolve: {
23
+ alias: {
24
+ '@': fileURLToPath(new URL('src', import.meta.url)),
25
+ },
26
+ },
27
+ build: {
28
+ rollupOptions: {
29
+ output: {
30
+ chunkFileNames: 'chunks/[name]-[hash].js',
31
+ assetFileNames: 'assets/[name].[hash].[ext]',
32
+ entryFileNames: 'entries/[name].[hash].js',
33
+ manualChunks: {
34
+ core: ['react', 'react-dom', 'react-i18next', 'react-router-dom', 'zustand', 'i18next'],
35
+ vender: ['axios'],
36
+ },
37
+ },
38
+ },
39
+ },
40
+ });
@@ -0,0 +1,18 @@
1
+ import { defineConfig, mergeConfig } from 'vitest/config';
2
+ import viteConfig from './vite.config';
3
+
4
+ export default mergeConfig(
5
+ viteConfig,
6
+ defineConfig({
7
+ test: {
8
+ globals: true,
9
+ environment: 'jsdom',
10
+ include: ['src/**/*.test.tsx'],
11
+ setupFiles: ['./vitest.setup.ts'],
12
+ coverage: {
13
+ provider: 'v8',
14
+ include: ['!src/main.tsx', 'src/**/*.tsx', 'src/**/*.ts'],
15
+ },
16
+ },
17
+ }),
18
+ );
@@ -0,0 +1,13 @@
1
+ import { cleanup } from '@testing-library/react';
2
+ import { mswServer } from '@/mocks/server';
3
+ import '@testing-library/jest-dom';
4
+ import '@/plugins/i18n';
5
+
6
+ beforeAll(() => mswServer.listen());
7
+
8
+ afterEach(() => {
9
+ cleanup();
10
+ mswServer.resetHandlers();
11
+ });
12
+
13
+ afterAll(() => mswServer.close());
@@ -0,0 +1,10 @@
1
+ # Click this link to view browser coverage https://browsersl.ist/#q=%3E+1.5%25%0Aios+%3E%3D+13%0Achrome+%3E%3D+60%0Anot+ie+%3C%3D+11%0Alast+2+versions%0Anot+dead
2
+
3
+ # Browsers that support
4
+
5
+ > 1.5%
6
+ ios >= 13
7
+ chrome >= 60
8
+ not ie <= 11
9
+ last 2 versions
10
+ not dead
@@ -0,0 +1,21 @@
1
+ name: Setup environment
2
+
3
+ description: Install dependencies
4
+
5
+ runs:
6
+ using: composite
7
+ steps:
8
+ - name: install pnpm
9
+ uses: pnpm/action-setup@v6
10
+ with:
11
+ run_install: false
12
+
13
+ - name: install Node.js
14
+ uses: actions/setup-node@v7
15
+ with:
16
+ node-version: 24.12.0
17
+ cache: pnpm
18
+
19
+ - name: install dependencies
20
+ shell: bash
21
+ run: pnpm install
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": ["config:recommended", "schedule:weekly", "group:allNonMajor"],
4
+ "labels": ["dependencies"],
5
+ "rangeStrategy": "bump",
6
+ "ignoreDeps": ["node"],
7
+ "packageRules": [
8
+ {
9
+ "matchDepTypes": ["peerDependencies"],
10
+ "enabled": false
11
+ }
12
+ ],
13
+ "postUpdateOptions": ["pnpmDedupe"]
14
+ }
@@ -0,0 +1,22 @@
1
+ name: CI Pipeline
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ CI:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v7
12
+ - name: setup environment
13
+ uses: ./.github/actions/setup-environment
14
+
15
+ - name: install Playwright browsers
16
+ run: npx playwright install --with-deps
17
+
18
+ - name: run unit test
19
+ run: pnpm test:unit
20
+
21
+ - name: run e2e test
22
+ run: pnpm test:ci-e2e
@@ -0,0 +1,27 @@
1
+ name: Deploy to Production
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - 'src/**'
8
+ - pnpm-lock.yaml
9
+ - package.json
10
+
11
+ jobs:
12
+ CI:
13
+ uses: ./.github/workflows/ci.yml
14
+
15
+ deploy:
16
+ runs-on: ubuntu-latest
17
+ needs: CI
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ # - name: setup environment
21
+ # uses: './.github/actions/setup-environment'
22
+
23
+ # - name: build production
24
+ # run: pnpm build:production
25
+
26
+ # - name: deploy to production
27
+ # run: pnpm deploy
@@ -0,0 +1,17 @@
1
+ name: Preview Pull Request
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
+
7
+ jobs:
8
+ CI:
9
+ uses: ./.github/workflows/ci.yml
10
+
11
+ preview:
12
+ runs-on: ubuntu-latest
13
+ needs: CI
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ # - name: setup environment
17
+ # uses: './.github/actions/setup-environment'
@@ -0,0 +1,18 @@
1
+ variables:
2
+ NODE_VERSION: '22'
3
+ CACHE_KEY: '${CI_PROJECT_PATH_SLUG}-${CI_COMMIT_REF_SLUG}'
4
+
5
+ image: node:${NODE_VERSION}-alpine
6
+
7
+ cache:
8
+ key: ${CACHE_KEY}
9
+ paths:
10
+ - .pnpm-store
11
+ - node_modules/
12
+ policy: pull-push
13
+
14
+ before_script:
15
+ - corepack enable
16
+ - corepack prepare --activate
17
+ - pnpm config set store-dir .pnpm-store
18
+ - pnpm install
@@ -0,0 +1 @@
1
+ npx --no -- commitlint --edit ${1}
@@ -0,0 +1 @@
1
+ npx lint-staged
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Tzuyi
3
+ Copyright (c)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,32 @@
1
+ # Logs
2
+ logs
3
+ *.log
4
+ npm-debug.log*
5
+ yarn-debug.log*
6
+ yarn-error.log*
7
+ pnpm-debug.log*
8
+ lerna-debug.log*
9
+
10
+ node_modules
11
+ dist
12
+ dist-ssr
13
+ *.local
14
+ .env
15
+
16
+ # Editor directories and files
17
+ .idea
18
+ .DS_Store
19
+ *.suo
20
+ *.ntvs*
21
+ *.njsproj
22
+ *.sln
23
+ *.sw?
24
+
25
+ # Test reports
26
+ coverage
27
+ /test-results/
28
+ /playwright-report/
29
+ /playwright/.cache/
30
+
31
+ # Visualizer
32
+ stats.html
@@ -0,0 +1,22 @@
1
+ stages:
2
+ - test
3
+ # - deploy
4
+
5
+ include:
6
+ - local: .gitlab/setup.yml
7
+
8
+ run_test:
9
+ stage: test
10
+ image: mcr.microsoft.com/playwright:focal
11
+ script:
12
+ - npx playwright install --with-deps
13
+ - pnpm test:unit
14
+ - pnpm test:ci-e2e
15
+ rules:
16
+ - if: $CI_COMMIT_BRANCH
17
+ changes:
18
+ - 'src/**'
19
+ - pnpm-lock.yaml
20
+ - package.json
21
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
22
+ - when: manual
@@ -0,0 +1,3 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ };
@@ -0,0 +1,49 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+
3
+ export default defineConfig({
4
+ testDir: './e2e',
5
+ /* If gets stuck during the test, it will fail if it exceeds the timeout time. */
6
+ timeout: 30 * 1000,
7
+ fullyParallel: true,
8
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
9
+ forbidOnly: !!process.env.CI,
10
+ /* Retry on CI only */
11
+ retries: process.env.CI ? 2 : 0,
12
+ /* Opt out of parallel tests on CI. */
13
+ workers: process.env.CI ? 1 : undefined,
14
+ reporter: 'html',
15
+ use: {
16
+ baseURL: 'http://localhost:5173',
17
+ trace: 'on-first-retry',
18
+ },
19
+ webServer: {
20
+ command: 'pnpm dev:mock',
21
+ port: 5173,
22
+ reuseExistingServer: !process.env.CI,
23
+ },
24
+ projects: [
25
+ {
26
+ name: 'chromium',
27
+ use: {
28
+ browserName: 'chromium',
29
+ ...devices['Macbook Pro'],
30
+ },
31
+ },
32
+
33
+ {
34
+ name: 'firefox',
35
+ use: {
36
+ browserName: 'firefox',
37
+ ...devices['Macbook 11'],
38
+ },
39
+ },
40
+
41
+ {
42
+ name: 'webkit',
43
+ use: {
44
+ browserName: 'webkit',
45
+ ...devices['iPhone SE'],
46
+ },
47
+ },
48
+ ],
49
+ });
@@ -0,0 +1,15 @@
1
+ import cssnano from 'cssnano';
2
+ import postcssPresetEnv from 'postcss-preset-env';
3
+ import postcssPxtorem from 'postcss-pxtorem';
4
+
5
+ export default {
6
+ plugins: [
7
+ postcssPresetEnv({ stage: 3 }),
8
+ postcssPxtorem({
9
+ rootValue: 16,
10
+ propList: ['*'],
11
+ selectorBlackList: ['norem'],
12
+ }),
13
+ ...(process.env.NODE_ENV === 'production' ? [cssnano({ preset: 'default' })] : []),
14
+ ],
15
+ };
@@ -0,0 +1,13 @@
1
+ /** @type {import('prettier').RequiredOptions} */
2
+
3
+ export default {
4
+ $schema: 'https://json.schemastore.org/prettierrc',
5
+ singleQuote: true,
6
+ semi: true,
7
+ endOfLine: 'lf',
8
+ printWidth: 120,
9
+ proseWrap: 'preserve',
10
+ arrowParens: 'avoid',
11
+ singleAttributePerLine: true,
12
+ plugins: ['prettier-plugin-tailwindcss'],
13
+ };
@@ -0,0 +1,21 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import os from 'node:os';
3
+ import packageJson from '../../package.json' with { type: 'json' };
4
+
5
+ const platform = os.platform();
6
+ const git = platform === 'win32' ? String.raw`C:\Program Files\Git\bin\git.exe` : '/usr/bin/git';
7
+ let hash = 'unknown';
8
+
9
+ try {
10
+ hash = execFileSync(git, ['rev-parse', 'HEAD']).toString().trim().slice(0, 7);
11
+ } catch {
12
+ hash = 'no-git-detected';
13
+ }
14
+
15
+ process.env.VITE_APP_VERSION = packageJson.version;
16
+ process.env.VITE_APP_LAST_COMMIT_HASH = hash;
17
+ process.env.VITE_APP_BUILD_EPOCH = Date.now().toString();
18
+
19
+ if (process.env.MOCK) {
20
+ process.env.VITE_APP_MOCK = 'service-worker';
21
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "references": [
3
+ {
4
+ "path": "./tsconfig.node.json"
5
+ },
6
+ {
7
+ "path": "./tsconfig.app.json"
8
+ },
9
+ {
10
+ "path": "./tsconfig.vitest.json"
11
+ }
12
+ ],
13
+ "files": []
14
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "@tsconfig/node24/tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "types": ["node"],
9
+ "noEmit": true
10
+ },
11
+ "include": ["vite.config.ts", "package.json", "vitest.config.ts", "playwright.config.ts", "scripts/**/*.ts"]
12
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "recommendations": [
3
+ "vue.volar",
4
+ "bradlc.vscode-tailwindcss",
5
+ "esbenp.prettier-vscode",
6
+ "csstools.postcss",
7
+ "cpylua.language-postcss",
8
+ "streetsidesoftware.code-spell-checker"
9
+ ]
10
+ }