@component-hook/create-app 1.5.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.
Files changed (107) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.mts +1 -1
  3. package/dist/index.mjs +86 -80
  4. package/package.json +12 -12
  5. package/template-react/.vscode/extensions.json +9 -0
  6. package/template-react/.vscode/settings.json +18 -0
  7. package/template-react/README.md.art +85 -0
  8. package/template-react/e2e/home.spec.ts +40 -0
  9. package/template-react/eslint.config.js +18 -0
  10. package/template-react/index.html.art +13 -0
  11. package/template-react/lint-staged.config.js +6 -0
  12. package/template-react/package.json +70 -0
  13. package/template-react/public/vite.svg +1 -0
  14. package/template-react/src/App.tsx +6 -0
  15. package/template-react/src/assets/svg-icons/react.svg +1 -0
  16. package/template-react/src/components/common/index.ts +1 -0
  17. package/template-react/src/components/common/svg-icon/index.ts +1 -0
  18. package/template-react/src/components/common/svg-icon/src/index.tsx +23 -0
  19. package/template-react/src/main.tsx +26 -0
  20. package/template-react/src/mocks/browser.ts +4 -0
  21. package/template-react/src/mocks/handlers/index.ts +1 -0
  22. package/template-react/src/mocks/server.ts +4 -0
  23. package/template-react/src/pages/home/components/hello-world/index.test.tsx +45 -0
  24. package/template-react/src/pages/home/components/hello-world/index.tsx +49 -0
  25. package/template-react/src/pages/home/index.module.css +8 -0
  26. package/template-react/src/pages/home/index.test.tsx +19 -0
  27. package/template-react/src/pages/home/index.tsx +37 -0
  28. package/template-react/src/plugins/i18n/index.ts +19 -0
  29. package/template-react/src/plugins/i18n/locales/en-US.json +3 -0
  30. package/template-react/src/plugins/i18n/locales/zh-TW.json +3 -0
  31. package/template-react/src/router/index.tsx +22 -0
  32. package/template-react/src/stores/constants.ts +1 -0
  33. package/template-react/src/stores/index.ts +1 -0
  34. package/template-react/src/stores/middleware.ts +17 -0
  35. package/template-react/src/stores/modules/config.ts +27 -0
  36. package/template-react/src/styles/base.css +68 -0
  37. package/template-react/src/styles/common/all.css +1 -0
  38. package/template-react/src/styles/common/button.css +26 -0
  39. package/template-react/src/styles/index.css +3 -0
  40. package/template-react/src/styles/tailwind.css +14 -0
  41. package/template-react/src/test-utils/index.tsx +15 -0
  42. package/template-react/src/vite-env.d.ts +9 -0
  43. package/template-react/tsconfig.app.json +32 -0
  44. package/template-react/tsconfig.vitest.json +10 -0
  45. package/template-react/vite.config.ts +40 -0
  46. package/template-react/vitest.config.ts +18 -0
  47. package/template-react/vitest.setup.ts +13 -0
  48. package/template-shared/.browserslistrc +10 -0
  49. package/template-shared/.github/actions/setup-environment/action.yml +21 -0
  50. package/template-shared/.github/renovate.json +14 -0
  51. package/template-shared/.github/workflows/ci.yml +22 -0
  52. package/template-shared/.github/workflows/deploy.yml +27 -0
  53. package/template-shared/.github/workflows/preview.yml +17 -0
  54. package/template-shared/.gitlab/setup.yml +18 -0
  55. package/template-shared/.husky/commit-msg +1 -0
  56. package/template-shared/.husky/pre-commit +1 -0
  57. package/{LICENSE → template-shared/LICENSE} +1 -1
  58. package/template-shared/_gitignore +32 -0
  59. package/template-shared/_gitlab-ci.yml +22 -0
  60. package/template-shared/commitlint.config.js +3 -0
  61. package/template-shared/playwright.config.ts +49 -0
  62. package/template-shared/postcss.config.js +15 -0
  63. package/template-shared/prettier.config.js +13 -0
  64. package/template-shared/scripts/build-info/index.ts +21 -0
  65. package/template-shared/tsconfig.json +14 -0
  66. package/template-shared/tsconfig.node.json +12 -0
  67. package/template-vue/.vscode/extensions.json +10 -0
  68. package/template-vue/.vscode/settings.json +18 -0
  69. package/template-vue/README.md.art +81 -0
  70. package/template-vue/e2e/home.spec.ts +59 -0
  71. package/template-vue/eslint.config.js +18 -0
  72. package/template-vue/index.html.art +28 -0
  73. package/template-vue/lint-staged.config.js +6 -0
  74. package/template-vue/package.json +69 -0
  75. package/template-vue/public/vite.svg +1 -0
  76. package/template-vue/src/App.vue +7 -0
  77. package/template-vue/src/assets/svg-icons/vue.svg +1 -0
  78. package/template-vue/src/components/common/index.ts +1 -0
  79. package/template-vue/src/components/common/svg-icon/index.ts +1 -0
  80. package/template-vue/src/components/common/svg-icon/src/index.vue +29 -0
  81. package/template-vue/src/locales/en-US.json +3 -0
  82. package/template-vue/src/locales/zh-TW.json +3 -0
  83. package/template-vue/src/main.ts +21 -0
  84. package/template-vue/src/mocks/browser.ts +4 -0
  85. package/template-vue/src/mocks/handlers/index.ts +1 -0
  86. package/template-vue/src/mocks/server.ts +4 -0
  87. package/template-vue/src/pages/home/components/HelloWorld.test.ts +57 -0
  88. package/template-vue/src/pages/home/components/HelloWorld.vue +54 -0
  89. package/template-vue/src/pages/home/index.test.ts +17 -0
  90. package/template-vue/src/pages/home/index.vue +46 -0
  91. package/template-vue/src/plugins/i18n.ts +11 -0
  92. package/template-vue/src/router/index.ts +23 -0
  93. package/template-vue/src/stores/constants.ts.art +1 -0
  94. package/template-vue/src/stores/index.ts +15 -0
  95. package/template-vue/src/stores/modules/config.ts +20 -0
  96. package/template-vue/src/styles/base.css +59 -0
  97. package/template-vue/src/styles/common/all.css +1 -0
  98. package/template-vue/src/styles/common/button.css +15 -0
  99. package/template-vue/src/styles/index.css +3 -0
  100. package/template-vue/src/styles/tailwind.css +1 -0
  101. package/template-vue/src/test-utils/index.ts +33 -0
  102. package/template-vue/src/vite-env.d.ts +9 -0
  103. package/template-vue/tsconfig.app.json +12 -0
  104. package/template-vue/tsconfig.vitest.json +10 -0
  105. package/template-vue/vite.config.ts +46 -0
  106. package/template-vue/vitest.config.ts +18 -0
  107. package/template-vue/vitest.setup.ts +12 -0
@@ -0,0 +1,57 @@
1
+ import userEvent from '@testing-library/user-event';
2
+ import { screen } from '@testing-library/vue';
3
+ import HelloWorld from '@/pages/home/components/HelloWorld.vue';
4
+ import i18n from '@/plugins/i18n';
5
+ import { useConfigStore } from '@/stores';
6
+ import { renderComponent } from '@/test-utils';
7
+
8
+ describe('home page HelloWorld component', () => {
9
+ const { t } = i18n.global;
10
+
11
+ it('renders the correct content', () => {
12
+ const msg = 'Hello World!';
13
+ const { version } = useConfigStore();
14
+
15
+ renderComponent(HelloWorld, { props: { msg } });
16
+ expect(screen.getByRole('heading', { name: msg })).toBeInTheDocument();
17
+ expect(screen.getByRole('button', { name: /count is 0/i })).toBeInTheDocument();
18
+ expect(screen.getByText(/check out , the official vue \+ vite starter/i)).toBeInTheDocument();
19
+ expect(screen.getByRole('link', { name: /create-vue/i })).toBeInTheDocument();
20
+ expect(screen.getByText(/install in your ide for a better dx/i)).toBeInTheDocument();
21
+ expect(screen.getByRole('link', { name: /volar/i })).toBeInTheDocument();
22
+ expect(screen.getByText(/click on the vite and vue logos to learn more/i)).toBeInTheDocument();
23
+ expect(screen.getByText(version)).toBeInTheDocument();
24
+ expect(screen.getByRole('button', { name: t('language') })).toBeInTheDocument();
25
+ });
26
+
27
+ it('count button interact', async () => {
28
+ renderComponent(HelloWorld, { props: { msg: '' } });
29
+ const countButton = screen.getByRole('button', { name: /count is 0/i });
30
+
31
+ await userEvent.click(countButton);
32
+ expect(countButton).toHaveTextContent(/count is 1/i);
33
+ await userEvent.click(countButton);
34
+ await userEvent.click(countButton);
35
+ expect(countButton).toHaveTextContent(/count is 3/i);
36
+ });
37
+
38
+ it('link correct attribute', () => {
39
+ renderComponent(HelloWorld, { props: { msg: '' } });
40
+ const createVueLink = screen.getByRole('link', { name: /create-vue/i });
41
+ const volarLink = screen.getByRole('link', { name: /volar/i });
42
+
43
+ expect(createVueLink).toHaveAttribute('href', 'https://vuejs.org/guide/quick-start.html#local');
44
+ expect(createVueLink).toHaveAttribute('target', '_blank');
45
+ expect(volarLink).toHaveAttribute('href', 'https://github.com/vuejs/language-tools');
46
+ expect(volarLink).toHaveAttribute('target', '_blank');
47
+ });
48
+
49
+ it('locale change interact', async () => {
50
+ renderComponent(HelloWorld, { props: { msg: '' } });
51
+ const localeButton = screen.getByRole('button', { name: t('language') });
52
+
53
+ expect(localeButton).toHaveTextContent('English');
54
+ await userEvent.click(localeButton);
55
+ expect(localeButton).toHaveTextContent('中文');
56
+ });
57
+ });
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue';
3
+ import { useI18n } from 'vue-i18n';
4
+ import { useConfigStore } from '@/stores';
5
+
6
+ defineProps<{ msg: string }>();
7
+
8
+ const { locale } = useI18n();
9
+ const { version } = useConfigStore();
10
+ const count = ref(0);
11
+
12
+ function changeLocale() {
13
+ locale.value = locale.value === 'en-US' ? 'zh-TW' : 'en-US';
14
+ }
15
+ </script>
16
+
17
+ <template>
18
+ <h1>{{ msg }}</h1>
19
+
20
+ <div class="p-8">
21
+ <button @click="count++">count is {{ count }}</button>
22
+ </div>
23
+
24
+ <p>
25
+ Check out
26
+ <a
27
+ href="https://vuejs.org/guide/quick-start.html#local"
28
+ target="_blank"
29
+ >create-vue</a
30
+ >, the official Vue + Vite starter
31
+ </p>
32
+ <p>
33
+ Install
34
+ <a
35
+ href="https://github.com/vuejs/language-tools"
36
+ target="_blank"
37
+ >Volar</a
38
+ >
39
+ in your IDE for a better DX
40
+ </p>
41
+ <p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
42
+ <p class="read-the-docs">
43
+ {{ version }}
44
+ </p>
45
+ <button @click="changeLocale">
46
+ {{ $t('language') }}
47
+ </button>
48
+ </template>
49
+
50
+ <style lang="css" scoped>
51
+ .read-the-docs {
52
+ color: #888;
53
+ }
54
+ </style>
@@ -0,0 +1,17 @@
1
+ import { screen } from '@testing-library/vue';
2
+ import Home from '@/pages/home/index.vue';
3
+ import { renderComponent } from '@/test-utils';
4
+
5
+ describe('home page', () => {
6
+ it('renders the correct content', () => {
7
+ renderComponent(Home);
8
+ const viteLink = screen.getByRole('link', { name: /vite logo/i });
9
+ const vueLink = screen.getByLabelText(/vue link/i);
10
+
11
+ expect(viteLink).toHaveAttribute('href', 'https://vitejs.dev');
12
+ expect(viteLink).toHaveAttribute('target', '_blank');
13
+
14
+ expect(vueLink).toHaveAttribute('href', 'https://vuejs.org/');
15
+ expect(vueLink).toHaveAttribute('target', '_blank');
16
+ });
17
+ });
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import { SvgIcon } from '@/components/common';
3
+ import HelloWorld from './components/HelloWorld.vue';
4
+ </script>
5
+
6
+ <template>
7
+ <div>
8
+ <a
9
+ href="https://vitejs.dev"
10
+ target="_blank"
11
+ >
12
+ <img
13
+ src="/vite.svg"
14
+ class="logo"
15
+ alt="Vite logo"
16
+ />
17
+ </a>
18
+ <a
19
+ href="https://vuejs.org/"
20
+ target="_blank"
21
+ aria-label="Vue link"
22
+ >
23
+ <svg-icon
24
+ name="vue"
25
+ class="logo hover:drop-shadow-[0_0_2em_#42b883aa]"
26
+ />
27
+ </a>
28
+ </div>
29
+
30
+ <hello-world msg="Vite + Vue" />
31
+ </template>
32
+
33
+ <style lang="css" scoped>
34
+ .logo {
35
+ width: 96px;
36
+ height: 96px;
37
+ margin: 0 auto;
38
+ padding: 24px;
39
+ will-change: filter;
40
+ transition: filter 300ms;
41
+
42
+ &:hover {
43
+ filter: drop-shadow(0 0 2em #646cffaa);
44
+ }
45
+ }
46
+ </style>
@@ -0,0 +1,11 @@
1
+ import messages from '@intlify/unplugin-vue-i18n/messages';
2
+ import { createI18n } from 'vue-i18n';
3
+
4
+ const i18n = createI18n({
5
+ legacy: import.meta.env.MODE === 'test',
6
+ locale: navigator.language,
7
+ fallbackLocale: 'en-US',
8
+ messages,
9
+ });
10
+
11
+ export default i18n;
@@ -0,0 +1,23 @@
1
+ import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
2
+ import HomePage from '@/pages/home/index.vue';
3
+
4
+ export const routes: Array<RouteRecordRaw> = [
5
+ {
6
+ path: '/:catchAll(.*)',
7
+ redirect: '/',
8
+ },
9
+ {
10
+ path: '/',
11
+ component: HomePage,
12
+ meta: {
13
+ title: 'Vue3 Coding Standards',
14
+ },
15
+ },
16
+ ];
17
+
18
+ const router = createRouter({
19
+ history: createWebHistory(),
20
+ routes,
21
+ });
22
+
23
+ export default router;
@@ -0,0 +1 @@
1
+ export const STORAGE_PREFIX = '{{projectName}}';
@@ -0,0 +1,15 @@
1
+ import { createPinia as create } from 'pinia';
2
+ import { createPersistedState } from 'pinia-plugin-persistedstate';
3
+ import { STORAGE_PREFIX } from './constants';
4
+ export { useConfigStore } from './modules/config';
5
+
6
+ export function createPinia() {
7
+ const pinia = create();
8
+ const persistedState = createPersistedState({
9
+ key: storeKey => `${STORAGE_PREFIX}-${storeKey}`,
10
+ });
11
+
12
+ pinia.use(persistedState);
13
+
14
+ return pinia;
15
+ }
@@ -0,0 +1,20 @@
1
+ import { defineStore } from 'pinia';
2
+
3
+ const versionString = import.meta.env.DEV
4
+ ? `${import.meta.env.VITE_APP_VERSION}-dev`
5
+ : import.meta.env.VITE_APP_VERSION;
6
+
7
+ const defaultState = {
8
+ isDev: import.meta.env.DEV,
9
+ version: versionString,
10
+ };
11
+
12
+ export const useConfigStore = defineStore('config', {
13
+ state: () => defaultState,
14
+ getters: {},
15
+ actions: {},
16
+ persist: {
17
+ storage: localStorage,
18
+ pick: [],
19
+ },
20
+ });
@@ -0,0 +1,59 @@
1
+ :root {
2
+ font-family: Inter, 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
+ @media (prefers-color-scheme: light) {
23
+ :root {
24
+ background-color: #ffffff;
25
+ color: #213547;
26
+ }
27
+ }
28
+
29
+ body {
30
+ margin: 0;
31
+ display: flex;
32
+ place-items: center;
33
+ min-width: 320px;
34
+ min-height: 100vh;
35
+ }
36
+
37
+ img {
38
+ -webkit-touch-callout: none;
39
+ -webkit-user-drag: none;
40
+ user-select: none;
41
+ }
42
+
43
+ #app {
44
+ max-width: 80rem;
45
+ margin: auto;
46
+ padding: 32px;
47
+ text-align: center;
48
+ }
49
+
50
+ a {
51
+ font-weight: 500;
52
+ text-decoration-color: inherit;
53
+ color: #646cff;
54
+ transition: color 150ms;
55
+
56
+ &:hover {
57
+ color: #535bf2;
58
+ }
59
+ }
@@ -0,0 +1 @@
1
+ @import './button.css';
@@ -0,0 +1,15 @@
1
+ button {
2
+ border-radius: 8px;
3
+ padding: 8px;
4
+ border-width: 1px;
5
+ border-color: transparent;
6
+ transition-property: border-color;
7
+ transition-duration: 300ms;
8
+ &:hover {
9
+ border-color: #646cff;
10
+ }
11
+ &:focus {
12
+ outline-width: 4px;
13
+ outline-color: -webkit-focus-ring-color;
14
+ }
15
+ }
@@ -0,0 +1,3 @@
1
+ @import './tailwind.css';
2
+ @import './base.css';
3
+ @import './common/all.css';
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -0,0 +1,33 @@
1
+ import { render } from '@testing-library/vue';
2
+ import { createPinia, setActivePinia } from 'pinia';
3
+ import { createMemoryHistory, createRouter } from 'vue-router';
4
+ import i18n from '@/plugins/i18n';
5
+ import { routes } from '@/router';
6
+ import type { RenderOptions } from '@testing-library/vue/types';
7
+ import type { Component } from 'vue';
8
+
9
+ interface RenderComponentOptions extends RenderOptions<unknown> {
10
+ provide?: Record<PropertyKey, unknown>;
11
+ }
12
+
13
+ const pinia = createTestPinia();
14
+ const router = createRouter({ history: createMemoryHistory(), routes });
15
+
16
+ function createTestPinia() {
17
+ const testPinia = createPinia();
18
+
19
+ setActivePinia(testPinia);
20
+ return testPinia;
21
+ }
22
+
23
+ export function renderComponent(testComponent: Component, options?: RenderComponentOptions) {
24
+ const { provide, ...componentOptions } = options ?? {};
25
+
26
+ return render(testComponent, {
27
+ ...componentOptions,
28
+ global: {
29
+ plugins: [pinia, i18n, router],
30
+ provide,
31
+ },
32
+ });
33
+ }
@@ -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_BUILD_EPOCH?: string;
8
+ readonly VITE_APP_MOCK?: string;
9
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "compilerOptions": {
4
+ "composite": true,
5
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
6
+ "paths": {
7
+ "@/*": ["./src/*"]
8
+ }
9
+ },
10
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
11
+ "exclude": ["src/**/*.test.*", "src/test-utils"]
12
+ }
@@ -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", "src/**/*.vue", "vitest.setup.ts"],
9
+ "exclude": []
10
+ }
@@ -0,0 +1,46 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { fileURLToPath, URL } from 'node:url';
3
+ import vueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
4
+ import tailwindcss from '@tailwindcss/vite';
5
+ import vue from '@vitejs/plugin-vue';
6
+ import { visualizer } from 'rollup-plugin-visualizer';
7
+ import { defineConfig } from 'vite';
8
+ import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
9
+ import './scripts/build-info';
10
+
11
+ export default defineConfig({
12
+ base: './',
13
+ plugins: [
14
+ vue(),
15
+ tailwindcss(),
16
+ vueI18nPlugin({
17
+ include: resolve(dirname(fileURLToPath(import.meta.url)), 'src/locales/**'),
18
+ }),
19
+ createSvgIconsPlugin({
20
+ iconDirs: [resolve(process.cwd(), 'src/assets/svg-icons')],
21
+ }),
22
+ visualizer({ gzipSize: true }),
23
+ ],
24
+ esbuild: {
25
+ pure: ['console.log'],
26
+ drop: ['debugger'],
27
+ },
28
+ resolve: {
29
+ alias: {
30
+ '@': fileURLToPath(new URL('src', import.meta.url)),
31
+ },
32
+ },
33
+ build: {
34
+ rollupOptions: {
35
+ output: {
36
+ chunkFileNames: 'chunks/[name]-[hash].js',
37
+ assetFileNames: 'assets/[name].[hash].[ext]',
38
+ entryFileNames: 'entries/[name].[hash].js',
39
+ manualChunks: {
40
+ core: ['vue', 'vue-router', 'pinia', 'pinia-plugin-persistedstate', 'vue-i18n'],
41
+ vender: ['axios', '@intlify/unplugin-vue-i18n/messages'],
42
+ },
43
+ },
44
+ },
45
+ },
46
+ });
@@ -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.ts'],
11
+ setupFiles: ['./vitest.setup.ts'],
12
+ coverage: {
13
+ provider: 'v8',
14
+ include: ['!src/main.ts', 'src/**/*.ts', 'src/**/*.vue'],
15
+ },
16
+ },
17
+ }),
18
+ );
@@ -0,0 +1,12 @@
1
+ import { cleanup } from '@testing-library/vue';
2
+ import { mswServer } from '@/mocks/server';
3
+ import '@testing-library/jest-dom';
4
+
5
+ beforeAll(() => mswServer.listen());
6
+
7
+ afterEach(() => {
8
+ cleanup();
9
+ mswServer.resetHandlers();
10
+ });
11
+
12
+ afterAll(() => mswServer.close());