@cavulsqa/create 2.9.3 → 2.10.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 (199) hide show
  1. package/README.md +12 -1
  2. package/bin/create.mjs +18 -25
  3. package/lib/templates.mjs +56 -0
  4. package/package.json +13 -5
  5. package/templates/f7-app/auto-imports.d.ts +9 -0
  6. package/templates/f7-app/package.json +6 -3
  7. package/templates/f7-app/src/env.d.ts +1 -0
  8. package/templates/f7-app/src/main.ts +3 -0
  9. package/templates/f7-app/src/plugins/bootstrapError.ts +2 -0
  10. package/templates/f7-app/src/plugins/recorder.plugin.ts +155 -0
  11. package/templates/f7-app/src/shared/recorder/capacitorSink.ts +124 -0
  12. package/templates/f7-app/vite.config.ts +1 -0
  13. package/templates/m3e-app/.claude/rules/data-fetching.md +68 -0
  14. package/templates/m3e-app/.claude/rules/database.md +106 -0
  15. package/templates/m3e-app/.claude/rules/m3e-ui.md +48 -0
  16. package/templates/m3e-app/.claude/rules/modules.md +43 -0
  17. package/templates/m3e-app/.claude/rules/native.md +60 -0
  18. package/templates/m3e-app/.claude/skills/m3-expressive/SKILL.md +68 -0
  19. package/templates/m3e-app/.claude/skills/m3-expressive/color.md +44 -0
  20. package/templates/m3e-app/.claude/skills/m3-expressive/components.md +325 -0
  21. package/templates/m3e-app/.claude/skills/m3-expressive/layout.md +42 -0
  22. package/templates/m3e-app/.claude/skills/m3-expressive/motion.md +51 -0
  23. package/templates/m3e-app/.claude/skills/m3-expressive/shapes-type.md +48 -0
  24. package/templates/m3e-app/.claude/skills/m3-expressive/sources.md +53 -0
  25. package/templates/m3e-app/.claude/skills/module-architecture/SKILL.md +65 -0
  26. package/templates/m3e-app/.claude/skills/module-architecture/file-templates.md +178 -0
  27. package/templates/m3e-app/.claude/skills/reactive-data/SKILL.md +90 -0
  28. package/templates/m3e-app/.claude/skills/reactive-data/testing.md +55 -0
  29. package/templates/m3e-app/.env.example +32 -0
  30. package/templates/m3e-app/CLAUDE.md +93 -0
  31. package/templates/m3e-app/auto-imports.d.ts +851 -0
  32. package/templates/m3e-app/capacitor.config.ts +44 -0
  33. package/templates/m3e-app/components.d.ts +252 -0
  34. package/templates/m3e-app/index.html +16 -0
  35. package/templates/m3e-app/package.json +107 -0
  36. package/templates/m3e-app/src/App.vue +129 -0
  37. package/templates/m3e-app/src/app/pragmas.config.ts +35 -0
  38. package/templates/m3e-app/src/app/scroll.config.ts +20 -0
  39. package/templates/m3e-app/src/app/storage.config.ts +65 -0
  40. package/templates/m3e-app/src/app/tabs.ts +33 -0
  41. package/templates/m3e-app/src/app/theme.config.ts +51 -0
  42. package/templates/m3e-app/src/assets/css/app.css +18 -0
  43. package/templates/m3e-app/src/assets/css/base.css +53 -0
  44. package/templates/m3e-app/src/assets/css/layout/container-transform.css +113 -0
  45. package/templates/m3e-app/src/assets/css/layout/shell.css +69 -0
  46. package/templates/m3e-app/src/assets/css/layout/transitions.css +121 -0
  47. package/templates/m3e-app/src/assets/css/m3e.css +6 -0
  48. package/templates/m3e-app/src/assets/css/theme/framework7.css +18 -0
  49. package/templates/m3e-app/src/assets/css/theme/tailwind.css +365 -0
  50. package/templates/m3e-app/src/domains/benchmark/benchmark.dataset.ts +209 -0
  51. package/templates/m3e-app/src/domains/benchmark/benchmark.suite.ts +662 -0
  52. package/templates/m3e-app/src/domains/sales/sales.repository.ts +458 -0
  53. package/templates/m3e-app/src/env.d.ts +40 -0
  54. package/templates/m3e-app/src/locales/ar.json +1260 -0
  55. package/templates/m3e-app/src/locales/en.json +1260 -0
  56. package/templates/m3e-app/src/locales/fr.json +1260 -0
  57. package/templates/m3e-app/src/main.ts +41 -0
  58. package/templates/m3e-app/src/modules/demo/components/DemoBenchmark.vue +119 -0
  59. package/templates/m3e-app/src/modules/demo/components/DemoBusLog.vue +63 -0
  60. package/templates/m3e-app/src/modules/demo/components/DemoCreateOrderSheet.vue +203 -0
  61. package/templates/m3e-app/src/modules/demo/components/DemoMetricsSheet.vue +75 -0
  62. package/templates/m3e-app/src/modules/demo/components/DemoOrderList.vue +75 -0
  63. package/templates/m3e-app/src/modules/demo/components/DemoPipelineBenchmark.vue +65 -0
  64. package/templates/m3e-app/src/modules/demo/components/DemoStatCards.vue +71 -0
  65. package/templates/m3e-app/src/modules/demo/composables/useBenchmark.ts +139 -0
  66. package/templates/m3e-app/src/modules/demo/composables/useOrderStatus.ts +64 -0
  67. package/templates/m3e-app/src/modules/demo/composables/useReactiveDemo.ts +171 -0
  68. package/templates/m3e-app/src/modules/demo/router/routes/demo.routes.ts +22 -0
  69. package/templates/m3e-app/src/modules/demo/views/DemoView.vue +210 -0
  70. package/templates/m3e-app/src/modules/demo/views/OrderDetailView.vue +136 -0
  71. package/templates/m3e-app/src/modules/demo/views/OrderSearchView.vue +74 -0
  72. package/templates/m3e-app/src/modules/gallery/components/GalleryBlock.vue +16 -0
  73. package/templates/m3e-app/src/modules/gallery/components/GalleryCarouselTile.vue +71 -0
  74. package/templates/m3e-app/src/modules/gallery/components/GalleryCustomerForm.vue +76 -0
  75. package/templates/m3e-app/src/modules/gallery/components/GalleryProofOfDelivery.vue +69 -0
  76. package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaDay.vue +106 -0
  77. package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaMonth.vue +40 -0
  78. package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaVisitList.vue +45 -0
  79. package/templates/m3e-app/src/modules/gallery/components/chat/ChatAttachSheet.vue +106 -0
  80. package/templates/m3e-app/src/modules/gallery/components/chat/ChatContactPicker.vue +85 -0
  81. package/templates/m3e-app/src/modules/gallery/components/chat/ChatInviteComposer.vue +131 -0
  82. package/templates/m3e-app/src/modules/gallery/components/chat/ChatPollComposer.vue +148 -0
  83. package/templates/m3e-app/src/modules/gallery/components/chat/ChatRecentPhotos.vue +62 -0
  84. package/templates/m3e-app/src/modules/gallery/components/inputs/InputsAccount.vue +79 -0
  85. package/templates/m3e-app/src/modules/gallery/components/inputs/InputsTags.vue +53 -0
  86. package/templates/m3e-app/src/modules/gallery/components/inputs/InputsVerification.vue +73 -0
  87. package/templates/m3e-app/src/modules/gallery/components/inputs/PasswordStrength.vue +37 -0
  88. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryButtons.vue +128 -0
  89. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCarousels.vue +236 -0
  90. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCharts.vue +84 -0
  91. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryFabs.vue +70 -0
  92. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryInputs.vue +219 -0
  93. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryNavigation.vue +141 -0
  94. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryOverlays.vue +368 -0
  95. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryPickers.vue +175 -0
  96. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryProgress.vue +118 -0
  97. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryScale.vue +103 -0
  98. package/templates/m3e-app/src/modules/gallery/components/sections/GallerySelection.vue +219 -0
  99. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryShapes.vue +48 -0
  100. package/templates/m3e-app/src/modules/gallery/components/sections/GallerySurfaces.vue +213 -0
  101. package/templates/m3e-app/src/modules/gallery/components/sections/GalleryTables.vue +185 -0
  102. package/templates/m3e-app/src/modules/gallery/components/surfaces/SurfacesContainerTransform.vue +46 -0
  103. package/templates/m3e-app/src/modules/gallery/composables/chatTeam.ts +18 -0
  104. package/templates/m3e-app/src/modules/gallery/composables/composeKind.ts +2 -0
  105. package/templates/m3e-app/src/modules/gallery/composables/currentPosition.ts +35 -0
  106. package/templates/m3e-app/src/modules/gallery/composables/demoOrders.ts +29 -0
  107. package/templates/m3e-app/src/modules/gallery/composables/featuredStories.ts +73 -0
  108. package/templates/m3e-app/src/modules/gallery/composables/fieldFormats.ts +36 -0
  109. package/templates/m3e-app/src/modules/gallery/composables/openExternal.ts +11 -0
  110. package/templates/m3e-app/src/modules/gallery/composables/routePlan.ts +90 -0
  111. package/templates/m3e-app/src/modules/gallery/composables/useAgenda.ts +61 -0
  112. package/templates/m3e-app/src/modules/gallery/composables/useChatCustomers.ts +31 -0
  113. package/templates/m3e-app/src/modules/gallery/composables/useChatDemo.ts +299 -0
  114. package/templates/m3e-app/src/modules/gallery/composables/useGallerySections.ts +230 -0
  115. package/templates/m3e-app/src/modules/gallery/composables/useLocalAttachments.ts +71 -0
  116. package/templates/m3e-app/src/modules/gallery/composables/useLocationShare.ts +38 -0
  117. package/templates/m3e-app/src/modules/gallery/composables/usePhotoScenes.ts +82 -0
  118. package/templates/m3e-app/src/modules/gallery/composables/useTreeDemo.ts +67 -0
  119. package/templates/m3e-app/src/modules/gallery/composables/wilayas.ts +67 -0
  120. package/templates/m3e-app/src/modules/gallery/router/routes/gallery.routes.ts +52 -0
  121. package/templates/m3e-app/src/modules/gallery/views/GalleryAgendaView.vue +117 -0
  122. package/templates/m3e-app/src/modules/gallery/views/GalleryChatView.vue +292 -0
  123. package/templates/m3e-app/src/modules/gallery/views/GalleryContactsView.vue +77 -0
  124. package/templates/m3e-app/src/modules/gallery/views/GalleryFeaturedView.vue +60 -0
  125. package/templates/m3e-app/src/modules/gallery/views/GalleryLoginView.vue +135 -0
  126. package/templates/m3e-app/src/modules/gallery/views/GalleryOnboardingView.vue +116 -0
  127. package/templates/m3e-app/src/modules/gallery/views/GallerySectionView.vue +27 -0
  128. package/templates/m3e-app/src/modules/gallery/views/GalleryTabsView.vue +135 -0
  129. package/templates/m3e-app/src/modules/gallery/views/GalleryView.vue +50 -0
  130. package/templates/m3e-app/src/modules/home/components/HomeHero.vue +57 -0
  131. package/templates/m3e-app/src/modules/home/composables/useHomeFeatures.ts +128 -0
  132. package/templates/m3e-app/src/modules/home/composables/useOpenFeature.ts +22 -0
  133. package/templates/m3e-app/src/modules/home/router/routes/home.routes.ts +21 -0
  134. package/templates/m3e-app/src/modules/home/views/FeatureDetailView.vue +66 -0
  135. package/templates/m3e-app/src/modules/home/views/HomeView.vue +47 -0
  136. package/templates/m3e-app/src/modules/settings/components/RolePalette.vue +38 -0
  137. package/templates/m3e-app/src/modules/settings/components/SeedSwatches.vue +41 -0
  138. package/templates/m3e-app/src/modules/settings/components/SettingsChoice.vue +43 -0
  139. package/templates/m3e-app/src/modules/settings/components/StudioPreview.vue +52 -0
  140. package/templates/m3e-app/src/modules/settings/router/routes/settings.routes.ts +17 -0
  141. package/templates/m3e-app/src/modules/settings/types.ts +7 -0
  142. package/templates/m3e-app/src/modules/settings/views/ColorStudioView.vue +166 -0
  143. package/templates/m3e-app/src/modules/settings/views/SettingsView.vue +157 -0
  144. package/templates/m3e-app/src/plugins/bootstrapError.ts +62 -0
  145. package/templates/m3e-app/src/plugins/capacitor/index.ts +14 -0
  146. package/templates/m3e-app/src/plugins/capacitor/useAndroidBackButton.ts +36 -0
  147. package/templates/m3e-app/src/plugins/capacitor/useKeyboard.ts +48 -0
  148. package/templates/m3e-app/src/plugins/capacitor/useSplashScreen.ts +43 -0
  149. package/templates/m3e-app/src/plugins/capacitor/useStatusBar.ts +16 -0
  150. package/templates/m3e-app/src/plugins/framework7.plugin.ts +36 -0
  151. package/templates/m3e-app/src/plugins/i18n.plugin.ts +87 -0
  152. package/templates/m3e-app/src/plugins/m3e.plugin.ts +22 -0
  153. package/templates/m3e-app/src/plugins/seed.plugin.ts +7 -0
  154. package/templates/m3e-app/src/plugins/sqlite.plugin.ts +32 -0
  155. package/templates/m3e-app/src/router/global/global.routes.ts +12 -0
  156. package/templates/m3e-app/src/router/index.ts +20 -0
  157. package/templates/m3e-app/src/shared/components/error/404.vue +13 -0
  158. package/templates/m3e-app/src/shared/components/layout/EmptyState.vue +30 -0
  159. package/templates/m3e-app/src/shared/components/layout/SectionHeader.vue +10 -0
  160. package/templates/m3e-app/src/shared/components/page/AppPage.vue +104 -0
  161. package/templates/m3e-app/src/shared/composables/navigation/useActiveTab.ts +39 -0
  162. package/templates/m3e-app/src/shared/composables/navigation/useContainerTransform.ts +117 -0
  163. package/templates/m3e-app/src/shared/composables/navigation/useNavigationGuard.ts +48 -0
  164. package/templates/m3e-app/src/shared/composables/navigation/useNavigationVisibility.ts +64 -0
  165. package/templates/m3e-app/src/shared/composables/navigation/useViewRouter.ts +25 -0
  166. package/templates/m3e-app/src/shared/composables/navigation/useWindowClass.ts +22 -0
  167. package/templates/m3e-app/src/shared/composables/theme/useThemeSettings.ts +155 -0
  168. package/templates/m3e-app/src/shared/database/candidates/capacitorSqlite.ts +36 -0
  169. package/templates/m3e-app/src/shared/database/candidates/index.ts +4 -0
  170. package/templates/m3e-app/src/shared/database/candidates/opfsSahPool.ts +25 -0
  171. package/templates/m3e-app/src/shared/database/candidates/types.ts +56 -0
  172. package/templates/m3e-app/src/shared/database/candidates/waSqlite.ts +56 -0
  173. package/templates/m3e-app/src/shared/database/database.ts +219 -0
  174. package/templates/m3e-app/src/shared/database/index.ts +3 -0
  175. package/templates/m3e-app/src/shared/database/migrations.ts +223 -0
  176. package/templates/m3e-app/src/shared/database/opfs.worker.ts +5 -0
  177. package/templates/m3e-app/src/shared/database/queries.ts +26 -0
  178. package/templates/m3e-app/src/shared/database/schema.ts +153 -0
  179. package/templates/m3e-app/src/shared/database/storage.ts +64 -0
  180. package/templates/m3e-app/src/shared/database/wa.worker.ts +5 -0
  181. package/templates/m3e-app/src/shared/utils/lazyRoute.ts +41 -0
  182. package/templates/m3e-app/src/shared/utils/resolvers/resolvers.ts +42 -0
  183. package/templates/m3e-app/src/shared/utils/textDirection.ts +22 -0
  184. package/templates/m3e-app/src/shared/utils/theme/themeSettings.ts +59 -0
  185. package/templates/m3e-app/src/shared/utils/tone.ts +8 -0
  186. package/templates/m3e-app/tests/benchmark.suite.test.ts +104 -0
  187. package/templates/m3e-app/tests/containerTransform.test.ts +58 -0
  188. package/templates/m3e-app/tests/fieldFormats.test.ts +25 -0
  189. package/templates/m3e-app/tests/lazyRoute.test.ts +30 -0
  190. package/templates/m3e-app/tests/locales.test.ts +73 -0
  191. package/templates/m3e-app/tests/migrations.test.ts +74 -0
  192. package/templates/m3e-app/tests/navigationGuard.test.ts +82 -0
  193. package/templates/m3e-app/tests/openDatabase.test.ts +54 -0
  194. package/templates/m3e-app/tests/sales.repository.test.ts +329 -0
  195. package/templates/m3e-app/tests/storage.test.ts +117 -0
  196. package/templates/m3e-app/tests/textDirection.test.ts +11 -0
  197. package/templates/m3e-app/tooling/linkedPackages.ts +112 -0
  198. package/templates/m3e-app/tsconfig.json +21 -0
  199. package/templates/m3e-app/vite.config.ts +144 -0
@@ -0,0 +1,44 @@
1
+ import type { CapacitorConfig } from "@capacitor/cli";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ for (const file of [".env.local", ".env"]) {
6
+ const path = join(__dirname, file);
7
+ if (existsSync(path)) process.loadEnvFile(path);
8
+ }
9
+
10
+ /** A flavour built for distribution never points at a laptop, whatever `.env.local` says. */
11
+ const DISTRIBUTED = new Set(["staging", "prod"]);
12
+
13
+ const liveReload =
14
+ process.env.VITE_LIVE_RELOAD === "true" && !DISTRIBUTED.has(process.env.VITE_ENVIRONMENT ?? "");
15
+
16
+ /**
17
+ * Live reload: the installed debug app loads the dev server instead of its bundled files, so an
18
+ * edit shows on the device without a rebuild. With `adb reverse tcp:5173 tcp:5173` the device's
19
+ * localhost is this machine's, so the default host needs no IP and no shared network.
20
+ */
21
+ function liveReloadUrl(): string | undefined {
22
+ if (!liveReload) return undefined;
23
+ const scheme = process.env.VITE_LIVE_RELOAD_SCHEME ?? "http";
24
+ const host = process.env.VITE_LIVE_RELOAD_HOST ?? "localhost";
25
+ const port = process.env.VITE_LIVE_RELOAD_PORT ?? "5173";
26
+ return `${scheme}://${host}:${port}`;
27
+ }
28
+
29
+ const config: CapacitorConfig = {
30
+ appId: "com.example.m3e",
31
+ appName: "M3E",
32
+ webDir: "dist",
33
+ server: {
34
+ url: liveReloadUrl(),
35
+ cleartext: liveReload,
36
+ },
37
+ plugins: {
38
+ SplashScreen: { launchAutoHide: false },
39
+ Keyboard: { resizeOnFullScreen: true },
40
+ CapacitorSQLite: { androidIsEncryption: false },
41
+ },
42
+ };
43
+
44
+ export default config;
@@ -0,0 +1,252 @@
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
+ AgendaDay: typeof import('./src/modules/gallery/components/agenda/AgendaDay.vue')['default']
16
+ AgendaMonth: typeof import('./src/modules/gallery/components/agenda/AgendaMonth.vue')['default']
17
+ AgendaVisitList: typeof import('./src/modules/gallery/components/agenda/AgendaVisitList.vue')['default']
18
+ AppPage: typeof import('./src/shared/components/page/AppPage.vue')['default']
19
+ ChatAttachSheet: typeof import('./src/modules/gallery/components/chat/ChatAttachSheet.vue')['default']
20
+ ChatContactPicker: typeof import('./src/modules/gallery/components/chat/ChatContactPicker.vue')['default']
21
+ ChatInviteComposer: typeof import('./src/modules/gallery/components/chat/ChatInviteComposer.vue')['default']
22
+ ChatPollComposer: typeof import('./src/modules/gallery/components/chat/ChatPollComposer.vue')['default']
23
+ ChatRecentPhotos: typeof import('./src/modules/gallery/components/chat/ChatRecentPhotos.vue')['default']
24
+ ColorStudioView: typeof import('./src/modules/settings/views/ColorStudioView.vue')['default']
25
+ DemoBenchmark: typeof import('./src/modules/demo/components/DemoBenchmark.vue')['default']
26
+ DemoBusLog: typeof import('./src/modules/demo/components/DemoBusLog.vue')['default']
27
+ DemoCreateOrderSheet: typeof import('./src/modules/demo/components/DemoCreateOrderSheet.vue')['default']
28
+ DemoMetricsSheet: typeof import('./src/modules/demo/components/DemoMetricsSheet.vue')['default']
29
+ DemoOrderList: typeof import('./src/modules/demo/components/DemoOrderList.vue')['default']
30
+ DemoPipelineBenchmark: typeof import('./src/modules/demo/components/DemoPipelineBenchmark.vue')['default']
31
+ DemoStatCards: typeof import('./src/modules/demo/components/DemoStatCards.vue')['default']
32
+ DemoView: typeof import('./src/modules/demo/views/DemoView.vue')['default']
33
+ EmptyState: typeof import('./src/shared/components/layout/EmptyState.vue')['default']
34
+ F7App: typeof import('framework7-vue')['f7App']
35
+ F7Page: typeof import('framework7-vue')['f7Page']
36
+ F7View: typeof import('framework7-vue')['f7View']
37
+ F7Views: typeof import('framework7-vue')['f7Views']
38
+ FeatureDetailView: typeof import('./src/modules/home/views/FeatureDetailView.vue')['default']
39
+ GalleryAgendaView: typeof import('./src/modules/gallery/views/GalleryAgendaView.vue')['default']
40
+ GalleryBlock: typeof import('./src/modules/gallery/components/GalleryBlock.vue')['default']
41
+ GalleryButtons: typeof import('./src/modules/gallery/components/sections/GalleryButtons.vue')['default']
42
+ GalleryCarousels: typeof import('./src/modules/gallery/components/sections/GalleryCarousels.vue')['default']
43
+ GalleryCarouselTile: typeof import('./src/modules/gallery/components/GalleryCarouselTile.vue')['default']
44
+ GalleryCharts: typeof import('./src/modules/gallery/components/sections/GalleryCharts.vue')['default']
45
+ GalleryChatView: typeof import('./src/modules/gallery/views/GalleryChatView.vue')['default']
46
+ GalleryContactsView: typeof import('./src/modules/gallery/views/GalleryContactsView.vue')['default']
47
+ GalleryCustomerForm: typeof import('./src/modules/gallery/components/GalleryCustomerForm.vue')['default']
48
+ GalleryFabs: typeof import('./src/modules/gallery/components/sections/GalleryFabs.vue')['default']
49
+ GalleryFeaturedView: typeof import('./src/modules/gallery/views/GalleryFeaturedView.vue')['default']
50
+ GalleryInputs: typeof import('./src/modules/gallery/components/sections/GalleryInputs.vue')['default']
51
+ GalleryLoginView: typeof import('./src/modules/gallery/views/GalleryLoginView.vue')['default']
52
+ GalleryNavigation: typeof import('./src/modules/gallery/components/sections/GalleryNavigation.vue')['default']
53
+ GalleryOnboardingView: typeof import('./src/modules/gallery/views/GalleryOnboardingView.vue')['default']
54
+ GalleryOverlays: typeof import('./src/modules/gallery/components/sections/GalleryOverlays.vue')['default']
55
+ GalleryPickers: typeof import('./src/modules/gallery/components/sections/GalleryPickers.vue')['default']
56
+ GalleryProgress: typeof import('./src/modules/gallery/components/sections/GalleryProgress.vue')['default']
57
+ GalleryProofOfDelivery: typeof import('./src/modules/gallery/components/GalleryProofOfDelivery.vue')['default']
58
+ GalleryScale: typeof import('./src/modules/gallery/components/sections/GalleryScale.vue')['default']
59
+ GallerySectionView: typeof import('./src/modules/gallery/views/GallerySectionView.vue')['default']
60
+ GallerySelection: typeof import('./src/modules/gallery/components/sections/GallerySelection.vue')['default']
61
+ GalleryShapes: typeof import('./src/modules/gallery/components/sections/GalleryShapes.vue')['default']
62
+ GallerySurfaces: typeof import('./src/modules/gallery/components/sections/GallerySurfaces.vue')['default']
63
+ GalleryTables: typeof import('./src/modules/gallery/components/sections/GalleryTables.vue')['default']
64
+ GalleryTabsView: typeof import('./src/modules/gallery/views/GalleryTabsView.vue')['default']
65
+ GalleryView: typeof import('./src/modules/gallery/views/GalleryView.vue')['default']
66
+ HomeHero: typeof import('./src/modules/home/components/HomeHero.vue')['default']
67
+ HomeView: typeof import('./src/modules/home/views/HomeView.vue')['default']
68
+ IMsAddReactionOutlineRounded: typeof import('~icons/material-symbols/add-reaction-outline-rounded')['default']
69
+ IMsAddRounded: typeof import('~icons/material-symbols/add-rounded')['default']
70
+ IMsAlarmOutlineRounded: typeof import('~icons/material-symbols/alarm-outline-rounded')['default']
71
+ IMsAnimationRounded: typeof import('~icons/material-symbols/animation-rounded')['default']
72
+ IMsArchiveOutlineRounded: typeof import('~icons/material-symbols/archive-outline-rounded')['default']
73
+ IMsArrowBackRounded: typeof import('~icons/material-symbols/arrow-back-rounded')['default']
74
+ IMsAutoAwesomeOutlineRounded: typeof import('~icons/material-symbols/auto-awesome-outline-rounded')['default']
75
+ IMsBoltOutlineRounded: typeof import('~icons/material-symbols/bolt-outline-rounded')['default']
76
+ IMsBoltRounded: typeof import('~icons/material-symbols/bolt-rounded')['default']
77
+ IMsBookmarkOutlineRounded: typeof import('~icons/material-symbols/bookmark-outline-rounded')['default']
78
+ IMsBookmarkRounded: typeof import('~icons/material-symbols/bookmark-rounded')['default']
79
+ IMsCalendarMonthOutlineRounded: typeof import('~icons/material-symbols/calendar-month-outline-rounded')['default']
80
+ IMsCalendarTodayOutlineRounded: typeof import('~icons/material-symbols/calendar-today-outline-rounded')['default']
81
+ IMsCallOutlineRounded: typeof import('~icons/material-symbols/call-outline-rounded')['default']
82
+ IMsCategoryOutlineRounded: typeof import('~icons/material-symbols/category-outline-rounded')['default']
83
+ IMsCheckCircleRounded: typeof import('~icons/material-symbols/check-circle-rounded')['default']
84
+ IMsCheckRounded: typeof import('~icons/material-symbols/check-rounded')['default']
85
+ IMsChevronRightRounded: typeof import('~icons/material-symbols/chevron-right-rounded')['default']
86
+ IMsCloseRounded: typeof import('~icons/material-symbols/close-rounded')['default']
87
+ IMsContrastRounded: typeof import('~icons/material-symbols/contrast-rounded')['default']
88
+ IMsDatabaseOutlineRounded: typeof import('~icons/material-symbols/database-outline-rounded')['default']
89
+ IMsDeleteOutlineRounded: typeof import('~icons/material-symbols/delete-outline-rounded')['default']
90
+ IMsDraftOutlineRounded: typeof import('~icons/material-symbols/draft-outline-rounded')['default']
91
+ IMsEditOutlineRounded: typeof import('~icons/material-symbols/edit-outline-rounded')['default']
92
+ IMsEventUpcomingOutlineRounded: typeof import('~icons/material-symbols/event-upcoming-outline-rounded')['default']
93
+ IMsExpandMoreRounded: typeof import('~icons/material-symbols/expand-more-rounded')['default']
94
+ IMsFavoriteOutlineRounded: typeof import('~icons/material-symbols/favorite-outline-rounded')['default']
95
+ IMsFavoriteRounded: typeof import('~icons/material-symbols/favorite-rounded')['default']
96
+ IMsFolderOpenOutlineRounded: typeof import('~icons/material-symbols/folder-open-outline-rounded')['default']
97
+ IMsFolderOutlineRounded: typeof import('~icons/material-symbols/folder-outline-rounded')['default']
98
+ IMsFormatBoldRounded: typeof import('~icons/material-symbols/format-bold-rounded')['default']
99
+ IMsFormatItalicRounded: typeof import('~icons/material-symbols/format-italic-rounded')['default']
100
+ IMsFormatUnderlinedRounded: typeof import('~icons/material-symbols/format-underlined-rounded')['default']
101
+ IMsHelpOutlineRounded: typeof import('~icons/material-symbols/help-outline-rounded')['default']
102
+ IMsHistoryRounded: typeof import('~icons/material-symbols/history-rounded')['default']
103
+ IMsHomeOutlineRounded: typeof import('~icons/material-symbols/home-outline-rounded')['default']
104
+ IMsHomeRounded: typeof import('~icons/material-symbols/home-rounded')['default']
105
+ IMsInfoOutlineRounded: typeof import('~icons/material-symbols/info-outline-rounded')['default']
106
+ IMsInventory2OutlineRounded: typeof import('~icons/material-symbols/inventory2-outline-rounded')['default']
107
+ IMsLanguageRounded: typeof import('~icons/material-symbols/language-rounded')['default']
108
+ IMsLightModeOutlineRounded: typeof import('~icons/material-symbols/light-mode-outline-rounded')['default']
109
+ IMsLocalShippingOutlineRounded: typeof import('~icons/material-symbols/local-shipping-outline-rounded')['default']
110
+ IMsLocationOnOutlineRounded: typeof import('~icons/material-symbols/location-on-outline-rounded')['default']
111
+ IMsLockOutlineRounded: typeof import('~icons/material-symbols/lock-outline-rounded')['default']
112
+ IMsMailOutlineRounded: typeof import('~icons/material-symbols/mail-outline-rounded')['default']
113
+ IMsMenuRounded: typeof import('~icons/material-symbols/menu-rounded')['default']
114
+ IMsMicOutlineRounded: typeof import('~icons/material-symbols/mic-outline-rounded')['default']
115
+ IMsMonitoringRounded: typeof import('~icons/material-symbols/monitoring-rounded')['default']
116
+ IMsMoreVertRounded: typeof import('~icons/material-symbols/more-vert-rounded')['default']
117
+ IMsNearMeRounded: typeof import('~icons/material-symbols/near-me-rounded')['default']
118
+ IMsPaletteOutlineRounded: typeof import('~icons/material-symbols/palette-outline-rounded')['default']
119
+ IMsPersonOutlineRounded: typeof import('~icons/material-symbols/person-outline-rounded')['default']
120
+ IMsPhoneAndroidOutlineRounded: typeof import('~icons/material-symbols/phone-android-outline-rounded')['default']
121
+ IMsReceiptLongOutlineRounded: typeof import('~icons/material-symbols/receipt-long-outline-rounded')['default']
122
+ IMsRefreshRounded: typeof import('~icons/material-symbols/refresh-rounded')['default']
123
+ IMsRemoveRounded: typeof import('~icons/material-symbols/remove-rounded')['default']
124
+ IMsRequestQuoteOutlineRounded: typeof import('~icons/material-symbols/request-quote-outline-rounded')['default']
125
+ IMsRestartAltRounded: typeof import('~icons/material-symbols/restart-alt-rounded')['default']
126
+ IMsScheduleOutlineRounded: typeof import('~icons/material-symbols/schedule-outline-rounded')['default']
127
+ IMsSearchRounded: typeof import('~icons/material-symbols/search-rounded')['default']
128
+ IMsSendRounded: typeof import('~icons/material-symbols/send-rounded')['default']
129
+ IMsShareOutlineRounded: typeof import('~icons/material-symbols/share-outline-rounded')['default']
130
+ IMsSmsOutlineRounded: typeof import('~icons/material-symbols/sms-outline-rounded')['default']
131
+ IMsSortRounded: typeof import('~icons/material-symbols/sort-rounded')['default']
132
+ IMsSpeedRounded: typeof import('~icons/material-symbols/speed-rounded')['default']
133
+ IMsStarOutlineRounded: typeof import('~icons/material-symbols/star-outline-rounded')['default']
134
+ IMsStarRounded: typeof import('~icons/material-symbols/star-rounded')['default']
135
+ IMsStorefrontOutlineRounded: typeof import('~icons/material-symbols/storefront-outline-rounded')['default']
136
+ IMsSwipeRounded: typeof import('~icons/material-symbols/swipe-rounded')['default']
137
+ IMsSyncRounded: typeof import('~icons/material-symbols/sync-rounded')['default']
138
+ IMsTodayOutlineRounded: typeof import('~icons/material-symbols/today-outline-rounded')['default']
139
+ IMsTuneRounded: typeof import('~icons/material-symbols/tune-rounded')['default']
140
+ IMsVerifiedOutlineRounded: typeof import('~icons/material-symbols/verified-outline-rounded')['default']
141
+ IMsVisibilityOffOutlineRounded: typeof import('~icons/material-symbols/visibility-off-outline-rounded')['default']
142
+ IMsVisibilityOutlineRounded: typeof import('~icons/material-symbols/visibility-outline-rounded')['default']
143
+ IMsWandStarsRounded: typeof import('~icons/material-symbols/wand-stars-rounded')['default']
144
+ IMsWebRounded: typeof import('~icons/material-symbols/web-rounded')['default']
145
+ IMsWidgetsOutlineRounded: typeof import('~icons/material-symbols/widgets-outline-rounded')['default']
146
+ InputsAccount: typeof import('./src/modules/gallery/components/inputs/InputsAccount.vue')['default']
147
+ InputsTags: typeof import('./src/modules/gallery/components/inputs/InputsTags.vue')['default']
148
+ InputsVerification: typeof import('./src/modules/gallery/components/inputs/InputsVerification.vue')['default']
149
+ M3ActionSheetHost: typeof import('@cavulsqa/m3e-vue')['M3ActionSheetHost']
150
+ M3AttachSheet: typeof import('@cavulsqa/m3e-vue')['M3AttachSheet']
151
+ M3Badge: typeof import('@cavulsqa/m3e-vue')['M3Badge']
152
+ M3BarChart: typeof import('@cavulsqa/m3e-vue')['M3BarChart']
153
+ M3BottomSheet: typeof import('@cavulsqa/m3e-vue')['M3BottomSheet']
154
+ M3Breadcrumbs: typeof import('@cavulsqa/m3e-vue')['M3Breadcrumbs']
155
+ M3Button: typeof import('@cavulsqa/m3e-vue')['M3Button']
156
+ M3ButtonGroup: typeof import('@cavulsqa/m3e-vue')['M3ButtonGroup']
157
+ M3Calendar: typeof import('@cavulsqa/m3e-vue')['M3Calendar']
158
+ M3Card: typeof import('@cavulsqa/m3e-vue')['M3Card']
159
+ M3Carousel: typeof import('@cavulsqa/m3e-vue')['M3Carousel']
160
+ M3Checkbox: typeof import('@cavulsqa/m3e-vue')['M3Checkbox']
161
+ M3Chip: typeof import('@cavulsqa/m3e-vue')['M3Chip']
162
+ M3ChipField: typeof import('@cavulsqa/m3e-vue')['M3ChipField']
163
+ M3CircularProgress: typeof import('@cavulsqa/m3e-vue')['M3CircularProgress']
164
+ M3CodeField: typeof import('@cavulsqa/m3e-vue')['M3CodeField']
165
+ M3ColorPicker: typeof import('@cavulsqa/m3e-vue')['M3ColorPicker']
166
+ M3DataTable: typeof import('@cavulsqa/m3e-vue')['M3DataTable']
167
+ M3DatePicker: typeof import('@cavulsqa/m3e-vue')['M3DatePicker']
168
+ M3DateWheel: typeof import('@cavulsqa/m3e-vue')['M3DateWheel']
169
+ M3DayTimeline: typeof import('@cavulsqa/m3e-vue')['M3DayTimeline']
170
+ M3DialogHost: typeof import('@cavulsqa/m3e-vue')['M3DialogHost']
171
+ M3Divider: typeof import('@cavulsqa/m3e-vue')['M3Divider']
172
+ M3DockedToolbar: typeof import('@cavulsqa/m3e-vue')['M3DockedToolbar']
173
+ M3DonutChart: typeof import('@cavulsqa/m3e-vue')['M3DonutChart']
174
+ M3ExposedDropdown: typeof import('@cavulsqa/m3e-vue')['M3ExposedDropdown']
175
+ M3Fab: typeof import('@cavulsqa/m3e-vue')['M3Fab']
176
+ M3FabMenu: typeof import('@cavulsqa/m3e-vue')['M3FabMenu']
177
+ M3FabMenuItem: typeof import('@cavulsqa/m3e-vue')['M3FabMenuItem']
178
+ M3FabMorph: typeof import('@cavulsqa/m3e-vue')['M3FabMorph']
179
+ M3FloatingToolbar: typeof import('@cavulsqa/m3e-vue')['M3FloatingToolbar']
180
+ M3FullScreenDialog: typeof import('@cavulsqa/m3e-vue')['M3FullScreenDialog']
181
+ M3IconButton: typeof import('@cavulsqa/m3e-vue')['M3IconButton']
182
+ M3Image: typeof import('@cavulsqa/m3e-vue')['M3Image']
183
+ M3InfiniteScroll: typeof import('@cavulsqa/m3e-vue')['M3InfiniteScroll']
184
+ M3LinearProgress: typeof import('@cavulsqa/m3e-vue')['M3LinearProgress']
185
+ M3LineChart: typeof import('@cavulsqa/m3e-vue')['M3LineChart']
186
+ M3List: typeof import('@cavulsqa/m3e-vue')['M3List']
187
+ M3ListGroup: typeof import('@cavulsqa/m3e-vue')['M3ListGroup']
188
+ M3ListIndex: typeof import('@cavulsqa/m3e-vue')['M3ListIndex']
189
+ M3ListItem: typeof import('@cavulsqa/m3e-vue')['M3ListItem']
190
+ M3LoadingIndicator: typeof import('@cavulsqa/m3e-vue')['M3LoadingIndicator']
191
+ M3Menu: typeof import('@cavulsqa/m3e-vue')['M3Menu']
192
+ M3MenuGroup: typeof import('@cavulsqa/m3e-vue')['M3MenuGroup']
193
+ M3MenuItem: typeof import('@cavulsqa/m3e-vue')['M3MenuItem']
194
+ M3MessageBar: typeof import('@cavulsqa/m3e-vue')['M3MessageBar']
195
+ M3Messages: typeof import('@cavulsqa/m3e-vue')['M3Messages']
196
+ M3ModalNavigationRail: typeof import('@cavulsqa/m3e-vue')['M3ModalNavigationRail']
197
+ M3NavigationBar: typeof import('@cavulsqa/m3e-vue')['M3NavigationBar']
198
+ M3NavigationItem: typeof import('@cavulsqa/m3e-vue')['M3NavigationItem']
199
+ M3NavigationRail: typeof import('@cavulsqa/m3e-vue')['M3NavigationRail']
200
+ M3NotificationHost: typeof import('@cavulsqa/m3e-vue')['M3NotificationHost']
201
+ M3PageIndicator: typeof import('@cavulsqa/m3e-vue')['M3PageIndicator']
202
+ M3Pager: typeof import('@cavulsqa/m3e-vue')['M3Pager']
203
+ M3PagerPage: typeof import('@cavulsqa/m3e-vue')['M3PagerPage']
204
+ M3PhotoBrowser: typeof import('@cavulsqa/m3e-vue')['M3PhotoBrowser']
205
+ M3Popover: typeof import('@cavulsqa/m3e-vue')['M3Popover']
206
+ M3PullToRefresh: typeof import('@cavulsqa/m3e-vue')['M3PullToRefresh']
207
+ M3Radio: typeof import('@cavulsqa/m3e-vue')['M3Radio']
208
+ M3RangeSlider: typeof import('@cavulsqa/m3e-vue')['M3RangeSlider']
209
+ M3SearchBar: typeof import('@cavulsqa/m3e-vue')['M3SearchBar']
210
+ M3SearchView: typeof import('@cavulsqa/m3e-vue')['M3SearchView']
211
+ M3Shape: typeof import('@cavulsqa/m3e-vue')['M3Shape']
212
+ M3ShapeMorph: typeof import('@cavulsqa/m3e-vue')['M3ShapeMorph']
213
+ M3SideSheet: typeof import('@cavulsqa/m3e-vue')['M3SideSheet']
214
+ M3SignaturePad: typeof import('@cavulsqa/m3e-vue')['M3SignaturePad']
215
+ M3Skeleton: typeof import('@cavulsqa/m3e-vue')['M3Skeleton']
216
+ M3SkeletonBlock: typeof import('@cavulsqa/m3e-vue')['M3SkeletonBlock']
217
+ M3SkeletonText: typeof import('@cavulsqa/m3e-vue')['M3SkeletonText']
218
+ M3Slider: typeof import('@cavulsqa/m3e-vue')['M3Slider']
219
+ M3SmartSelect: typeof import('@cavulsqa/m3e-vue')['M3SmartSelect']
220
+ M3SnackbarHost: typeof import('@cavulsqa/m3e-vue')['M3SnackbarHost']
221
+ M3SplitButton: typeof import('@cavulsqa/m3e-vue')['M3SplitButton']
222
+ M3StandardBottomSheet: typeof import('@cavulsqa/m3e-vue')['M3StandardBottomSheet']
223
+ M3Stepper: typeof import('@cavulsqa/m3e-vue')['M3Stepper']
224
+ M3SwipeAction: typeof import('@cavulsqa/m3e-vue')['M3SwipeAction']
225
+ M3Switch: typeof import('@cavulsqa/m3e-vue')['M3Switch']
226
+ M3Tab: typeof import('@cavulsqa/m3e-vue')['M3Tab']
227
+ M3TabPanel: typeof import('@cavulsqa/m3e-vue')['M3TabPanel']
228
+ M3TabPanels: typeof import('@cavulsqa/m3e-vue')['M3TabPanels']
229
+ M3Tabs: typeof import('@cavulsqa/m3e-vue')['M3Tabs']
230
+ M3TextEditor: typeof import('@cavulsqa/m3e-vue')['M3TextEditor']
231
+ M3TextField: typeof import('@cavulsqa/m3e-vue')['M3TextField']
232
+ M3Timeline: typeof import('@cavulsqa/m3e-vue')['M3Timeline']
233
+ M3TimelineItem: typeof import('@cavulsqa/m3e-vue')['M3TimelineItem']
234
+ M3TimePicker: typeof import('@cavulsqa/m3e-vue')['M3TimePicker']
235
+ M3Tooltip: typeof import('@cavulsqa/m3e-vue')['M3Tooltip']
236
+ M3TopAppBar: typeof import('@cavulsqa/m3e-vue')['M3TopAppBar']
237
+ M3Tree: typeof import('@cavulsqa/m3e-vue')['M3Tree']
238
+ M3VirtualList: typeof import('@cavulsqa/m3e-vue')['M3VirtualList']
239
+ M3WeekStrip: typeof import('@cavulsqa/m3e-vue')['M3WeekStrip']
240
+ M3WheelPicker: typeof import('@cavulsqa/m3e-vue')['M3WheelPicker']
241
+ OrderDetailView: typeof import('./src/modules/demo/views/OrderDetailView.vue')['default']
242
+ OrderSearchView: typeof import('./src/modules/demo/views/OrderSearchView.vue')['default']
243
+ PasswordStrength: typeof import('./src/modules/gallery/components/inputs/PasswordStrength.vue')['default']
244
+ RolePalette: typeof import('./src/modules/settings/components/RolePalette.vue')['default']
245
+ SectionHeader: typeof import('./src/shared/components/layout/SectionHeader.vue')['default']
246
+ SeedSwatches: typeof import('./src/modules/settings/components/SeedSwatches.vue')['default']
247
+ SettingsChoice: typeof import('./src/modules/settings/components/SettingsChoice.vue')['default']
248
+ SettingsView: typeof import('./src/modules/settings/views/SettingsView.vue')['default']
249
+ StudioPreview: typeof import('./src/modules/settings/components/StudioPreview.vue')['default']
250
+ SurfacesContainerTransform: typeof import('./src/modules/gallery/components/surfaces/SurfacesContainerTransform.vue')['default']
251
+ }
252
+ }
@@ -0,0 +1,16 @@
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
+ <meta name="color-scheme" content="light dark" />
10
+ <title>App</title>
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ <script type="module" src="/src/main.ts"></script>
15
+ </body>
16
+ </html>
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@cavulsqa/template-m3e-app",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "description": "Vue 3 + Capacitor + SQLite starter in Material 3 Expressive: Framework7 as the navigation engine only, @cavulsqa/m3e-vue components, 2025-spec dynamic colour with a colour studio, light and dark.",
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": "^8.1.1",
16
+ "@capacitor/android": "^8.5.0",
17
+ "@capacitor/app": "^8.0.0",
18
+ "@capacitor/core": "^8.0.0",
19
+ "@capacitor/haptics": "^8.0.2",
20
+ "@capacitor/keyboard": "^8.0.0",
21
+ "@capacitor/preferences": "^8.0.0",
22
+ "@capacitor/splash-screen": "^8.0.0",
23
+ "@capacitor/status-bar": "^8.0.0",
24
+ "@cavulsqa/m3e": "^1.4.0",
25
+ "@cavulsqa/m3e-vue": "^1.4.0",
26
+ "@cavulsqa/mobile-db": "^1.4.0",
27
+ "@cavulsqa/reactive-db": "^1.4.0",
28
+ "@cavulsqa/reactive-vue": "^1.4.0",
29
+ "@fontsource-variable/google-sans-flex": "^5.3.1",
30
+ "@sqlite.org/sqlite-wasm": "3.53.0-build1",
31
+ "@tailwindcss/vite": "^4.3.3",
32
+ "@vueuse/core": "^14.4.0",
33
+ "framework7": "^9.0.2",
34
+ "framework7-vue": "^9.1.2",
35
+ "kysely": "^0.29.5",
36
+ "tailwindcss": "^4.3.3",
37
+ "vue": "^3.5.0",
38
+ "vue-i18n": "^11.2.2",
39
+ "wa-sqlite": "^1.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@capacitor/cli": "^8.0.0",
43
+ "@iconify-json/material-symbols": "1.2.93",
44
+ "@intlify/unplugin-vue-i18n": "^11.2.5",
45
+ "@types/node": "^24.12.2",
46
+ "@vitejs/plugin-vue": "^6.0.3",
47
+ "sql.js": "1.13.0",
48
+ "typescript": "^5.9.3",
49
+ "unplugin-auto-import": "^21.1.0",
50
+ "unplugin-icons": "^23.0.1",
51
+ "unplugin-vue-components": "^32.1.0",
52
+ "vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
53
+ "vite-plus": "0.3.0",
54
+ "vue-tsc": "^3.2.4"
55
+ },
56
+ "cavulsqa": {
57
+ "storageEngines": [
58
+ "sqlite-wasm-opfs-sahpool",
59
+ "wa-sqlite-access-handle-pool",
60
+ "wa-sqlite-opfs-async",
61
+ "wa-sqlite-idb-batch-atomic",
62
+ "capacitor-sqlite"
63
+ ],
64
+ "engineModules": {
65
+ "opfsSahPool": {
66
+ "file": "src/shared/database/candidates/opfsSahPool.ts",
67
+ "engines": [
68
+ "sqlite-wasm-opfs-sahpool"
69
+ ],
70
+ "exports": [
71
+ "opfsSahPool"
72
+ ],
73
+ "dependencies": [
74
+ "@sqlite.org/sqlite-wasm"
75
+ ]
76
+ },
77
+ "waSqlite": {
78
+ "file": "src/shared/database/candidates/waSqlite.ts",
79
+ "engines": [
80
+ "wa-sqlite-access-handle-pool",
81
+ "wa-sqlite-opfs-async",
82
+ "wa-sqlite-idb-batch-atomic"
83
+ ],
84
+ "exports": [
85
+ "waAccessHandlePool",
86
+ "waOriginPrivateFileSystem",
87
+ "waIdbBatchAtomic"
88
+ ],
89
+ "dependencies": [
90
+ "wa-sqlite"
91
+ ]
92
+ },
93
+ "capacitorSqlite": {
94
+ "file": "src/shared/database/candidates/capacitorSqlite.ts",
95
+ "engines": [
96
+ "capacitor-sqlite"
97
+ ],
98
+ "exports": [
99
+ "capacitorSqlite"
100
+ ],
101
+ "dependencies": [
102
+ "@capacitor-community/sqlite"
103
+ ]
104
+ }
105
+ }
106
+ }
107
+ }
@@ -0,0 +1,129 @@
1
+ <template>
2
+ <F7App v-bind="parameters">
3
+ <M3NavigationRail
4
+ v-if="rail"
5
+ class="app-shell__rail"
6
+ :model-value="active"
7
+ :expanded="railExpanded"
8
+ :label="t('shell.navigation')"
9
+ @update:model-value="selectTab"
10
+ @reselect="reselect"
11
+ >
12
+ <template #header>
13
+ <M3IconButton
14
+ :label="railExpanded ? t('shell.collapse') : t('shell.expand')"
15
+ @click="railExpanded = !railExpanded"
16
+ >
17
+ <i-ms-menu-rounded />
18
+ </M3IconButton>
19
+ </template>
20
+ <M3NavigationItem v-for="tab in tabs" :key="tab.id" :value="tab.id" :label="t(tab.labelKey)">
21
+ <template #icon="{ selected }">
22
+ <component :is="selected ? tab.iconSelected : tab.icon" />
23
+ </template>
24
+ </M3NavigationItem>
25
+ </M3NavigationRail>
26
+
27
+ <F7Views tabs class="app-shell__views">
28
+ <F7View
29
+ v-for="(tab, index) in tabs"
30
+ :id="`view-${tab.id}`"
31
+ :key="tab.id"
32
+ :main="index === 0"
33
+ :tab="true"
34
+ :tab-active="index === 0"
35
+ :url="`/${tab.id}/`"
36
+ />
37
+ </F7Views>
38
+
39
+ <M3NavigationBar
40
+ v-if="!rail"
41
+ class="app-shell__bar"
42
+ :class="{ 'app-shell__bar--hidden': !navVisible }"
43
+ :model-value="active"
44
+ :label="t('shell.navigation')"
45
+ :aria-hidden="!navVisible || undefined"
46
+ :inert="!navVisible"
47
+ @update:model-value="selectTab"
48
+ @reselect="reselect"
49
+ >
50
+ <M3NavigationItem v-for="tab in tabs" :key="tab.id" :value="tab.id" :label="t(tab.labelKey)">
51
+ <template #icon="{ selected }">
52
+ <component :is="selected ? tab.iconSelected : tab.icon" />
53
+ </template>
54
+ </M3NavigationItem>
55
+ </M3NavigationBar>
56
+
57
+ <M3SnackbarHost :close-label="t('shell.dismiss')" />
58
+ <M3NotificationHost
59
+ :close-label="t('shell.dismiss')"
60
+ :label="t('shell.notification')"
61
+ :more-label="notificationsMore"
62
+ :less-label="t('shell.notificationsLess')"
63
+ :clear-label="t('shell.notificationsClear')"
64
+ />
65
+ <M3DialogHost />
66
+ <M3ActionSheetHost />
67
+ </F7App>
68
+ </template>
69
+
70
+ <script setup lang="ts">
71
+ import { tabs } from "@/app/tabs";
72
+ import { initCapacitor } from "@/plugins/capacitor";
73
+ import { hideSplashWhenPageReady } from "@/plugins/capacitor/useSplashScreen";
74
+ import { framework7Parameters } from "@/plugins/framework7.plugin";
75
+
76
+ const { t } = useI18n();
77
+ const parameters = framework7Parameters();
78
+ const windowClass = useWindowClass();
79
+ const { active, show } = useActiveTab();
80
+ const { isVisible, isReserved, setScrollHidden } = useNavigationVisibility();
81
+ const railExpanded = useLocalStorage("app-rail-expanded", false);
82
+
83
+ function notificationsMore(count: number) {
84
+ return t("shell.notificationsMore", { count }, count);
85
+ }
86
+
87
+ const rail = computed(() => windowClass.value !== "compact");
88
+ const navVisible = computed(() => !rail.value && isVisible.value);
89
+ const navReserved = computed(() => !rail.value && isReserved.value);
90
+
91
+ /**
92
+ * How much of the bottom edge the bar occupies, for everything that floats above it: page padding,
93
+ * FABs, the floating toolbar, snackbars. One variable on the root, so nothing measures the bar.
94
+ * Page padding keeps the row while the bar is only scrolled away; what floats follows the bar.
95
+ */
96
+ watchEffect(() => {
97
+ const root = document.documentElement.style;
98
+ root.setProperty("--app-nav-offset", navReserved.value ? "64px" : "0px");
99
+ root.setProperty("--m3-snackbar-offset", navVisible.value ? "64px" : "0px");
100
+ root.setProperty("--m3-floating-toolbar-offset", navVisible.value ? "64px" : "0px");
101
+ });
102
+
103
+ function selectTab(id: string | undefined) {
104
+ if (id) show(id);
105
+ }
106
+
107
+ watch(active, () => setScrollHidden(false));
108
+
109
+ /** M3: tapping the current destination returns to its root, or scrolls its root to the top. */
110
+ function reselect(id: string) {
111
+ const view = f7.views.get(`#view-${id}`);
112
+ const router = view?.router;
113
+ if (router && router.history.length > 1) {
114
+ router.back(router.history[0], { force: true });
115
+ return;
116
+ }
117
+ document
118
+ .querySelector<HTMLElement>(`#view-${id} .page-current .page-content`)
119
+ ?.scrollTo({ top: 0, behavior: "smooth" });
120
+ }
121
+
122
+ onMounted(() => {
123
+ f7ready(async (instance) => {
124
+ useNavigationGuard();
125
+ await initCapacitor(instance);
126
+ hideSplashWhenPageReady(instance);
127
+ });
128
+ });
129
+ </script>
@@ -0,0 +1,35 @@
1
+ /**
2
+ * PRAGMAs applied to every engine identically, because SQLite's defaults are per-build and two
3
+ * engines left on their own are not comparable - an unpinned `synchronous` alone produced a 1.47x
4
+ * "ranking" between engines that were the same speed.
5
+ *
6
+ * `fast` is for measuring only: `synchronous = OFF` hands durability to the OS, so a battery pull can
7
+ * leave the database corrupt rather than merely stale. `safe` costs 19-57 ms on a single write and
8
+ * under 3 ms per row inside a transaction, so an app that batches gives up very little.
9
+ */
10
+ export type PragmaProfile = "fast" | "safe";
11
+
12
+ const PROFILES: Record<PragmaProfile, readonly string[]> = {
13
+ fast: [
14
+ // No journal file to create, write and delete per transaction.
15
+ "PRAGMA journal_mode = MEMORY",
16
+ // The big one for single writes, and the one that trades away crash durability.
17
+ "PRAGMA synchronous = OFF",
18
+ "PRAGMA temp_store = MEMORY",
19
+ // Negative means KiB rather than pages: 16 MB of page cache.
20
+ "PRAGMA cache_size = -16000",
21
+ ],
22
+ safe: [
23
+ "PRAGMA journal_mode = TRUNCATE",
24
+ "PRAGMA synchronous = FULL",
25
+ "PRAGMA temp_store = MEMORY",
26
+ "PRAGMA cache_size = -16000",
27
+ ],
28
+ };
29
+
30
+ export const pragmaProfile: PragmaProfile =
31
+ import.meta.env.VITE_PRAGMA_PROFILE === "fast" ? "fast" : "safe";
32
+
33
+ export function pragmasFor(profile: PragmaProfile): readonly string[] {
34
+ return PROFILES[profile];
35
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * How the bars behave while a page scrolls - one place for the whole app; a page can still pass its
3
+ * own `scrollBehavior` to `AppPage`.
4
+ *
5
+ * - `topAppBar`: `"enterAlways"` slides a small top app bar away with the content as it scrolls
6
+ * down and brings it back the moment it scrolls up (Compose's enter-always); `"pinned"` keeps it.
7
+ * The large and medium bars collapse into their small bar either way.
8
+ * - `navigationBar`: `"hideOnScroll"` slides the navigation bar off the bottom while scrolling down
9
+ * and back on the way up, at the top and at the end of the content (Material's hide-on-scroll);
10
+ * `"pinned"` keeps it.
11
+ */
12
+ export interface ScrollBehaviorConfig {
13
+ topAppBar: "pinned" | "enterAlways";
14
+ navigationBar: "pinned" | "hideOnScroll";
15
+ }
16
+
17
+ export const SCROLL_BEHAVIOR: ScrollBehaviorConfig = {
18
+ topAppBar: "enterAlways",
19
+ navigationBar: "hideOnScroll",
20
+ };