@cavulsqa/create 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/bin/create.mjs +142 -0
- package/lib/scaffold.mjs +124 -0
- package/package.json +60 -0
- package/templates/f7-app/.claude/rules/data-fetching.md +67 -0
- package/templates/f7-app/.claude/rules/database.md +65 -0
- package/templates/f7-app/.claude/rules/framework7-ui.md +79 -0
- package/templates/f7-app/.claude/rules/modules.md +43 -0
- package/templates/f7-app/.claude/rules/native.md +47 -0
- package/templates/f7-app/.claude/skills/f7-design/SKILL.md +67 -0
- package/templates/f7-app/.claude/skills/f7-design/components.md +49 -0
- package/templates/f7-app/.claude/skills/f7-design/icons.md +52 -0
- package/templates/f7-app/.claude/skills/module-architecture/SKILL.md +65 -0
- package/templates/f7-app/.claude/skills/module-architecture/file-templates.md +183 -0
- package/templates/f7-app/.claude/skills/reactive-data/SKILL.md +89 -0
- package/templates/f7-app/.claude/skills/reactive-data/testing.md +55 -0
- package/templates/f7-app/CLAUDE.md +105 -0
- package/templates/f7-app/auto-imports.d.ts +667 -0
- package/templates/f7-app/capacitor.config.ts +14 -0
- package/templates/f7-app/components.d.ts +59 -0
- package/templates/f7-app/index.html +15 -0
- package/templates/f7-app/package.json +51 -0
- package/templates/f7-app/src/App.vue +72 -0
- package/templates/f7-app/src/app/tabs.ts +25 -0
- package/templates/f7-app/src/assets/css/app.css +1 -0
- package/templates/f7-app/src/assets/css/icons.css +50 -0
- package/templates/f7-app/src/assets/fonts/material-icons-outlined.woff2 +0 -0
- package/templates/f7-app/src/assets/fonts/material-icons-round.woff2 +0 -0
- package/templates/f7-app/src/domains/sales/sales.repository.ts +458 -0
- package/templates/f7-app/src/env.d.ts +23 -0
- package/templates/f7-app/src/locales/en.json +179 -0
- package/templates/f7-app/src/locales/fr.json +179 -0
- package/templates/f7-app/src/main.ts +50 -0
- package/templates/f7-app/src/modules/demo/components/DemoBusLog.vue +26 -0
- package/templates/f7-app/src/modules/demo/components/DemoCreateOrderSheet.vue +160 -0
- package/templates/f7-app/src/modules/demo/components/DemoOrderList.vue +73 -0
- package/templates/f7-app/src/modules/demo/components/DemoPipelineBenchmark.vue +52 -0
- package/templates/f7-app/src/modules/demo/components/DemoStatCards.vue +63 -0
- package/templates/f7-app/src/modules/demo/composables/useReactiveDemo.ts +168 -0
- package/templates/f7-app/src/modules/demo/router/routes/demo.routes.ts +34 -0
- package/templates/f7-app/src/modules/demo/views/DemoView.vue +126 -0
- package/templates/f7-app/src/modules/demo/views/OrderDetailView.vue +131 -0
- package/templates/f7-app/src/modules/demo/views/OrderSearchView.vue +106 -0
- package/templates/f7-app/src/modules/home/composables/useHomeFeatures.ts +133 -0
- package/templates/f7-app/src/modules/home/router/routes/home.routes.ts +29 -0
- package/templates/f7-app/src/modules/home/views/FeatureDetailView.vue +108 -0
- package/templates/f7-app/src/modules/home/views/HomeView.vue +53 -0
- package/templates/f7-app/src/modules/settings/router/routes/settings.routes.ts +16 -0
- package/templates/f7-app/src/modules/settings/views/SettingsView.vue +126 -0
- package/templates/f7-app/src/plugins/capacitor/index.ts +14 -0
- package/templates/f7-app/src/plugins/capacitor/useAndroidBackButton.ts +68 -0
- package/templates/f7-app/src/plugins/capacitor/useKeyboard.ts +61 -0
- package/templates/f7-app/src/plugins/capacitor/useSplashScreen.ts +11 -0
- package/templates/f7-app/src/plugins/capacitor/useStatusBar.ts +15 -0
- package/templates/f7-app/src/plugins/framework7.plugin.ts +41 -0
- package/templates/f7-app/src/plugins/i18n.plugin.ts +10 -0
- package/templates/f7-app/src/plugins/seed.plugin.ts +17 -0
- package/templates/f7-app/src/plugins/sqlite.plugin.ts +21 -0
- package/templates/f7-app/src/router/global/global.routes.ts +16 -0
- package/templates/f7-app/src/router/index.ts +18 -0
- package/templates/f7-app/src/shared/components/error/404.vue +12 -0
- package/templates/f7-app/src/shared/components/metrics/MetricsPanel.vue +79 -0
- package/templates/f7-app/src/shared/composables/theme/useAppTheme.ts +68 -0
- package/templates/f7-app/src/shared/composables/useTabbarVisibility.ts +50 -0
- package/templates/f7-app/src/shared/database/database.ts +86 -0
- package/templates/f7-app/src/shared/database/index.ts +3 -0
- package/templates/f7-app/src/shared/database/migrations.ts +81 -0
- package/templates/f7-app/src/shared/database/queries.ts +22 -0
- package/templates/f7-app/src/shared/database/schema.ts +59 -0
- package/templates/f7-app/src/shared/utils/resolvers/resolvers.ts +152 -0
- package/templates/f7-app/tests/icons.test.ts +81 -0
- package/templates/f7-app/tests/sales.repository.test.ts +329 -0
- package/templates/f7-app/tsconfig.json +21 -0
- package/templates/f7-app/tsconfig.node.json +14 -0
- package/templates/f7-app/vite.config.ts +95 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CapacitorConfig } from "@capacitor/cli";
|
|
2
|
+
|
|
3
|
+
const config: CapacitorConfig = {
|
|
4
|
+
appId: "com.example.app",
|
|
5
|
+
appName: "App",
|
|
6
|
+
webDir: "dist",
|
|
7
|
+
plugins: {
|
|
8
|
+
SplashScreen: { launchAutoHide: false },
|
|
9
|
+
Keyboard: { resizeOnFullScreen: true },
|
|
10
|
+
CapacitorSQLite: { androidIsEncryption: false },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default config;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
// biome-ignore lint: disable
|
|
4
|
+
// oxlint-disable
|
|
5
|
+
// ------
|
|
6
|
+
// Generated by unplugin-vue-components
|
|
7
|
+
// Read more: https://github.com/vuejs/core/pull/3399
|
|
8
|
+
|
|
9
|
+
export {}
|
|
10
|
+
|
|
11
|
+
/* prettier-ignore */
|
|
12
|
+
declare module 'vue' {
|
|
13
|
+
export interface GlobalComponents {
|
|
14
|
+
404: typeof import('./src/shared/components/error/404.vue')['default']
|
|
15
|
+
DemoBusLog: typeof import('./src/modules/demo/components/DemoBusLog.vue')['default']
|
|
16
|
+
DemoCreateOrderSheet: typeof import('./src/modules/demo/components/DemoCreateOrderSheet.vue')['default']
|
|
17
|
+
DemoOrderList: typeof import('./src/modules/demo/components/DemoOrderList.vue')['default']
|
|
18
|
+
DemoPipelineBenchmark: typeof import('./src/modules/demo/components/DemoPipelineBenchmark.vue')['default']
|
|
19
|
+
DemoStatCards: typeof import('./src/modules/demo/components/DemoStatCards.vue')['default']
|
|
20
|
+
DemoView: typeof import('./src/modules/demo/views/DemoView.vue')['default']
|
|
21
|
+
F7App: typeof import('framework7-vue')['f7App']
|
|
22
|
+
F7Block: typeof import('framework7-vue')['f7Block']
|
|
23
|
+
F7BlockTitle: typeof import('framework7-vue')['f7BlockTitle']
|
|
24
|
+
F7Button: typeof import('framework7-vue')['f7Button']
|
|
25
|
+
F7Chip: typeof import('framework7-vue')['f7Chip']
|
|
26
|
+
F7Fab: typeof import('framework7-vue')['f7Fab']
|
|
27
|
+
F7FabButton: typeof import('framework7-vue')['f7FabButton']
|
|
28
|
+
F7FabButtons: typeof import('framework7-vue')['f7FabButtons']
|
|
29
|
+
F7Icon: typeof import('framework7-vue')['f7Icon']
|
|
30
|
+
F7Link: typeof import('framework7-vue')['f7Link']
|
|
31
|
+
F7List: typeof import('framework7-vue')['f7List']
|
|
32
|
+
F7ListInput: typeof import('framework7-vue')['f7ListInput']
|
|
33
|
+
F7ListItem: typeof import('framework7-vue')['f7ListItem']
|
|
34
|
+
F7Navbar: typeof import('framework7-vue')['f7Navbar']
|
|
35
|
+
F7NavRight: typeof import('framework7-vue')['f7NavRight']
|
|
36
|
+
F7Page: typeof import('framework7-vue')['f7Page']
|
|
37
|
+
F7PageContent: typeof import('framework7-vue')['f7PageContent']
|
|
38
|
+
F7Panel: typeof import('framework7-vue')['f7Panel']
|
|
39
|
+
F7Searchbar: typeof import('framework7-vue')['f7Searchbar']
|
|
40
|
+
F7Segmented: typeof import('framework7-vue')['f7Segmented']
|
|
41
|
+
F7Sheet: typeof import('framework7-vue')['f7Sheet']
|
|
42
|
+
F7Stepper: typeof import('framework7-vue')['f7Stepper']
|
|
43
|
+
F7Subnavbar: typeof import('framework7-vue')['f7Subnavbar']
|
|
44
|
+
F7SwipeoutActions: typeof import('framework7-vue')['f7SwipeoutActions']
|
|
45
|
+
F7SwipeoutButton: typeof import('framework7-vue')['f7SwipeoutButton']
|
|
46
|
+
F7Tab: typeof import('framework7-vue')['f7Tab']
|
|
47
|
+
F7Tabs: typeof import('framework7-vue')['f7Tabs']
|
|
48
|
+
F7Toggle: typeof import('framework7-vue')['f7Toggle']
|
|
49
|
+
F7Toolbar: typeof import('framework7-vue')['f7Toolbar']
|
|
50
|
+
F7View: typeof import('framework7-vue')['f7View']
|
|
51
|
+
F7Views: typeof import('framework7-vue')['f7Views']
|
|
52
|
+
FeatureDetailView: typeof import('./src/modules/home/views/FeatureDetailView.vue')['default']
|
|
53
|
+
HomeView: typeof import('./src/modules/home/views/HomeView.vue')['default']
|
|
54
|
+
MetricsPanel: typeof import('./src/shared/components/metrics/MetricsPanel.vue')['default']
|
|
55
|
+
OrderDetailView: typeof import('./src/modules/demo/views/OrderDetailView.vue')['default']
|
|
56
|
+
OrderSearchView: typeof import('./src/modules/demo/views/OrderSearchView.vue')['default']
|
|
57
|
+
SettingsView: typeof import('./src/modules/settings/views/SettingsView.vue')['default']
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta
|
|
6
|
+
name="viewport"
|
|
7
|
+
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, viewport-fit=cover"
|
|
8
|
+
/>
|
|
9
|
+
<title>App</title>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="app"></div>
|
|
13
|
+
<script type="module" src="/src/main.ts"></script>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cavulsqa/template-f7-app",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Vue 3 + Framework7 + Capacitor + SQLite starter: tabbed shell, domains/modules/shared layout, native keyboard and back-button handling.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vp dev",
|
|
9
|
+
"build": "vue-tsc --noEmit && vp build",
|
|
10
|
+
"type-check": "vue-tsc --noEmit",
|
|
11
|
+
"test": "vp test",
|
|
12
|
+
"check": "vp check"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@capacitor-community/sqlite": "^7.0.2",
|
|
16
|
+
"@capacitor/android": "^8.5.0",
|
|
17
|
+
"@capacitor/app": "^8.0.0",
|
|
18
|
+
"@capacitor/core": "^8.0.0",
|
|
19
|
+
"@capacitor/keyboard": "^8.0.0",
|
|
20
|
+
"@capacitor/preferences": "^8.0.0",
|
|
21
|
+
"@capacitor/splash-screen": "^8.0.0",
|
|
22
|
+
"@capacitor/status-bar": "^8.0.0",
|
|
23
|
+
"@cavulsqa/mobile-db": "^0.3.0",
|
|
24
|
+
"@cavulsqa/reactive-db": "^0.2.0",
|
|
25
|
+
"@cavulsqa/reactive-vue": "^0.2.0",
|
|
26
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
27
|
+
"@vueuse/core": "^14.4.0",
|
|
28
|
+
"framework7": "^9.0.2",
|
|
29
|
+
"framework7-icons": "^5.0.5",
|
|
30
|
+
"framework7-vue": "^8.3.4",
|
|
31
|
+
"kysely": "^0.29.5",
|
|
32
|
+
"sql.js": "1.13.0",
|
|
33
|
+
"tailwindcss": "^4.3.3",
|
|
34
|
+
"vue": "^3.5.0",
|
|
35
|
+
"vue-i18n": "^11.2.2"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@capacitor/cli": "^8.0.0",
|
|
39
|
+
"@intlify/unplugin-vue-i18n": "^11.2.5",
|
|
40
|
+
"@types/node": "^24",
|
|
41
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
42
|
+
"sql.js": "1.13.0",
|
|
43
|
+
"typescript": "^5.9.3",
|
|
44
|
+
"unplugin-auto-import": "^21.1.0",
|
|
45
|
+
"unplugin-icons": "^23.0.1",
|
|
46
|
+
"unplugin-vue-components": "^32.1.0",
|
|
47
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
|
|
48
|
+
"vite-plus": "0.3.0",
|
|
49
|
+
"vue-tsc": "^3.2.4"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<F7App v-bind="parameters">
|
|
3
|
+
<!-- Right panel: the query metrics, reachable from anywhere instead of owning a screen. -->
|
|
4
|
+
<F7Panel right cover>
|
|
5
|
+
<F7View>
|
|
6
|
+
<MetricsPanel />
|
|
7
|
+
</F7View>
|
|
8
|
+
</F7Panel>
|
|
9
|
+
|
|
10
|
+
<F7Views tabs class="safe-areas">
|
|
11
|
+
<F7Toolbar tabbar icons bottom :class="{ 'tabbar-hidden': !isVisible }">
|
|
12
|
+
<!--
|
|
13
|
+
`toolbar-pane` is a Framework7 9 class that framework7-vue 8 does not wrap as a
|
|
14
|
+
component, so it is written as a plain div. The CSS is what produces the floating pane.
|
|
15
|
+
-->
|
|
16
|
+
<div class="toolbar-pane">
|
|
17
|
+
<F7Link
|
|
18
|
+
v-for="(tab, index) in tabs"
|
|
19
|
+
:key="tab.id"
|
|
20
|
+
:tab-link="`#view-${tab.id}`"
|
|
21
|
+
:tab-link-active="index === 0"
|
|
22
|
+
:icon-ios="`f7:${tab.iconIos}`"
|
|
23
|
+
:icon-md="`material:${tab.iconMd}`"
|
|
24
|
+
:text="t(tab.labelKey)"
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
</F7Toolbar>
|
|
28
|
+
|
|
29
|
+
<F7View
|
|
30
|
+
v-for="(tab, index) in tabs"
|
|
31
|
+
:id="`view-${tab.id}`"
|
|
32
|
+
:key="tab.id"
|
|
33
|
+
:main="index === 0"
|
|
34
|
+
:tab="true"
|
|
35
|
+
:tab-active="index === 0"
|
|
36
|
+
:url="`/${tab.id}/`"
|
|
37
|
+
/>
|
|
38
|
+
</F7Views>
|
|
39
|
+
</F7App>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup lang="ts">
|
|
43
|
+
import { tabs } from "@/app/tabs";
|
|
44
|
+
import { initCapacitor } from "@/plugins/capacitor";
|
|
45
|
+
import { hideSplashScreen } from "@/plugins/capacitor/useSplashScreen";
|
|
46
|
+
import { framework7Parameters } from "@/plugins/framework7.plugin";
|
|
47
|
+
import { useAppThemeProvider } from "@/shared/composables/theme/useAppTheme";
|
|
48
|
+
import MetricsPanel from "@/shared/components/metrics/MetricsPanel.vue";
|
|
49
|
+
|
|
50
|
+
const { t } = useI18n();
|
|
51
|
+
const { isVisible } = useTabbarVisibility();
|
|
52
|
+
|
|
53
|
+
// Provided here so any screen can read or change it through useAppTheme().
|
|
54
|
+
const appTheme = useAppThemeProvider();
|
|
55
|
+
const parameters = framework7Parameters(appTheme.value.theme, appTheme.value.darkMode === "dark");
|
|
56
|
+
|
|
57
|
+
onMounted(() => {
|
|
58
|
+
// The native handlers need the Framework7 instance, which exists only once the shell is mounted.
|
|
59
|
+
f7ready(async (instance) => {
|
|
60
|
+
await initCapacitor(instance);
|
|
61
|
+
hideSplashScreen();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<style>
|
|
67
|
+
/* The tab bar gets out of the way while the keyboard is open; see useKeyboard. */
|
|
68
|
+
.tabbar-hidden {
|
|
69
|
+
transform: translateY(100%);
|
|
70
|
+
transition: transform 200ms ease;
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface TabDefinition {
|
|
2
|
+
/** Also the tab's DOM id and the first segment of its route. */
|
|
3
|
+
id: string;
|
|
4
|
+
/** i18n key, resolved in the shell so the label follows the active locale. */
|
|
5
|
+
labelKey: string;
|
|
6
|
+
/** Framework7 icon name, used when the iOS theme is active. */
|
|
7
|
+
iconIos: string;
|
|
8
|
+
/** Material icon name, used when the Material theme is active. */
|
|
9
|
+
iconMd: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The tab bar is data: add an entry, add a route file in the matching module, and the shell, the bar
|
|
14
|
+
* and the navigation all follow. Each tab is a Framework7 view with its own history, so switching
|
|
15
|
+
* away and back returns to the same screen.
|
|
16
|
+
*
|
|
17
|
+
* Icons are given per theme rather than once. Framework7 picks `icon-ios` or `icon-md` from the
|
|
18
|
+
* active theme, which is what makes the bar look native on both platforms instead of iOS glyphs on
|
|
19
|
+
* Android.
|
|
20
|
+
*/
|
|
21
|
+
export const tabs: TabDefinition[] = [
|
|
22
|
+
{ id: "home", labelKey: "tabs.home", iconIos: "house_fill", iconMd: "home" },
|
|
23
|
+
{ id: "demo", labelKey: "tabs.demo", iconIos: "bolt_fill", iconMd: "bolt" },
|
|
24
|
+
{ id: "settings", labelKey: "tabs.settings", iconIos: "gear_alt_fill", iconMd: "settings" },
|
|
25
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework7 renders `icon-md="material:home"` as the ligature text "home" unless a Material Icons
|
|
3
|
+
* font with `liga` enabled is present. The npm `framework7-icons` package only ships the iOS glyphs,
|
|
4
|
+
* so the Material font is bundled here rather than pulled from a CDN - an offline-first app should
|
|
5
|
+
* not lose its icons with the network.
|
|
6
|
+
*/
|
|
7
|
+
@font-face {
|
|
8
|
+
font-family: "Material Icons";
|
|
9
|
+
font-style: normal;
|
|
10
|
+
font-weight: 400;
|
|
11
|
+
font-display: block;
|
|
12
|
+
src:
|
|
13
|
+
local("Material Icons"),
|
|
14
|
+
url(../fonts/material-icons-round.woff2) format("woff2");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: "Material Icons Outlined";
|
|
19
|
+
font-style: normal;
|
|
20
|
+
font-weight: 400;
|
|
21
|
+
font-display: block;
|
|
22
|
+
src: url(../fonts/material-icons-outlined.woff2) format("woff2");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.material-icons,
|
|
26
|
+
.material-icons-outlined {
|
|
27
|
+
font-weight: normal;
|
|
28
|
+
font-style: normal;
|
|
29
|
+
font-size: 24px;
|
|
30
|
+
display: inline-block;
|
|
31
|
+
line-height: 1;
|
|
32
|
+
text-transform: none;
|
|
33
|
+
letter-spacing: normal;
|
|
34
|
+
word-wrap: normal;
|
|
35
|
+
white-space: nowrap;
|
|
36
|
+
direction: ltr;
|
|
37
|
+
-webkit-font-smoothing: antialiased;
|
|
38
|
+
text-rendering: optimizeLegibility;
|
|
39
|
+
-moz-osx-font-smoothing: grayscale;
|
|
40
|
+
/* Without this the icon name renders as text instead of a glyph. */
|
|
41
|
+
font-feature-settings: "liga";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.material-icons {
|
|
45
|
+
font-family: "Material Icons";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.material-icons-outlined {
|
|
49
|
+
font-family: "Material Icons Outlined";
|
|
50
|
+
}
|
|
Binary file
|
|
Binary file
|