@cavulsqa/create 2.9.2 → 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.
- package/README.md +12 -1
- package/bin/create.mjs +18 -25
- package/lib/templates.mjs +56 -0
- package/package.json +13 -5
- package/templates/f7-app/CLAUDE.md +3 -0
- package/templates/f7-app/auto-imports.d.ts +15 -0
- package/templates/f7-app/package.json +6 -3
- package/templates/f7-app/src/App.vue +1 -0
- package/templates/f7-app/src/env.d.ts +1 -0
- package/templates/f7-app/src/main.ts +3 -0
- package/templates/f7-app/src/modules/demo/router/routes/demo.routes.ts +4 -16
- package/templates/f7-app/src/modules/home/router/routes/home.routes.ts +3 -11
- package/templates/f7-app/src/modules/settings/router/routes/settings.routes.ts +2 -6
- package/templates/f7-app/src/plugins/bootstrapError.ts +2 -0
- package/templates/f7-app/src/plugins/recorder.plugin.ts +155 -0
- package/templates/f7-app/src/router/global/global.routes.ts +2 -6
- package/templates/f7-app/src/shared/composables/useNavigationGuard.ts +48 -0
- package/templates/f7-app/src/shared/recorder/capacitorSink.ts +124 -0
- package/templates/f7-app/src/shared/utils/lazyRoute.ts +25 -0
- package/templates/f7-app/tests/lazyRoute.test.ts +30 -0
- package/templates/f7-app/tests/navigationGuard.test.ts +82 -0
- package/templates/f7-app/vite.config.ts +1 -0
- package/templates/m3e-app/.claude/rules/data-fetching.md +68 -0
- package/templates/m3e-app/.claude/rules/database.md +106 -0
- package/templates/m3e-app/.claude/rules/m3e-ui.md +48 -0
- package/templates/m3e-app/.claude/rules/modules.md +43 -0
- package/templates/m3e-app/.claude/rules/native.md +60 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/SKILL.md +68 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/color.md +44 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/components.md +325 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/layout.md +42 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/motion.md +51 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/shapes-type.md +48 -0
- package/templates/m3e-app/.claude/skills/m3-expressive/sources.md +53 -0
- package/templates/m3e-app/.claude/skills/module-architecture/SKILL.md +65 -0
- package/templates/m3e-app/.claude/skills/module-architecture/file-templates.md +178 -0
- package/templates/m3e-app/.claude/skills/reactive-data/SKILL.md +90 -0
- package/templates/m3e-app/.claude/skills/reactive-data/testing.md +55 -0
- package/templates/m3e-app/.env.example +32 -0
- package/templates/m3e-app/CLAUDE.md +93 -0
- package/templates/m3e-app/auto-imports.d.ts +851 -0
- package/templates/m3e-app/capacitor.config.ts +44 -0
- package/templates/m3e-app/components.d.ts +252 -0
- package/templates/m3e-app/index.html +16 -0
- package/templates/m3e-app/package.json +107 -0
- package/templates/m3e-app/src/App.vue +129 -0
- package/templates/m3e-app/src/app/pragmas.config.ts +35 -0
- package/templates/m3e-app/src/app/scroll.config.ts +20 -0
- package/templates/m3e-app/src/app/storage.config.ts +65 -0
- package/templates/m3e-app/src/app/tabs.ts +33 -0
- package/templates/m3e-app/src/app/theme.config.ts +51 -0
- package/templates/m3e-app/src/assets/css/app.css +18 -0
- package/templates/m3e-app/src/assets/css/base.css +53 -0
- package/templates/m3e-app/src/assets/css/layout/container-transform.css +113 -0
- package/templates/m3e-app/src/assets/css/layout/shell.css +69 -0
- package/templates/m3e-app/src/assets/css/layout/transitions.css +121 -0
- package/templates/m3e-app/src/assets/css/m3e.css +6 -0
- package/templates/m3e-app/src/assets/css/theme/framework7.css +18 -0
- package/templates/m3e-app/src/assets/css/theme/tailwind.css +365 -0
- package/templates/m3e-app/src/domains/benchmark/benchmark.dataset.ts +209 -0
- package/templates/m3e-app/src/domains/benchmark/benchmark.suite.ts +662 -0
- package/templates/m3e-app/src/domains/sales/sales.repository.ts +458 -0
- package/templates/m3e-app/src/env.d.ts +40 -0
- package/templates/m3e-app/src/locales/ar.json +1260 -0
- package/templates/m3e-app/src/locales/en.json +1260 -0
- package/templates/m3e-app/src/locales/fr.json +1260 -0
- package/templates/m3e-app/src/main.ts +41 -0
- package/templates/m3e-app/src/modules/demo/components/DemoBenchmark.vue +119 -0
- package/templates/m3e-app/src/modules/demo/components/DemoBusLog.vue +63 -0
- package/templates/m3e-app/src/modules/demo/components/DemoCreateOrderSheet.vue +203 -0
- package/templates/m3e-app/src/modules/demo/components/DemoMetricsSheet.vue +75 -0
- package/templates/m3e-app/src/modules/demo/components/DemoOrderList.vue +75 -0
- package/templates/m3e-app/src/modules/demo/components/DemoPipelineBenchmark.vue +65 -0
- package/templates/m3e-app/src/modules/demo/components/DemoStatCards.vue +71 -0
- package/templates/m3e-app/src/modules/demo/composables/useBenchmark.ts +139 -0
- package/templates/m3e-app/src/modules/demo/composables/useOrderStatus.ts +64 -0
- package/templates/m3e-app/src/modules/demo/composables/useReactiveDemo.ts +171 -0
- package/templates/m3e-app/src/modules/demo/router/routes/demo.routes.ts +22 -0
- package/templates/m3e-app/src/modules/demo/views/DemoView.vue +210 -0
- package/templates/m3e-app/src/modules/demo/views/OrderDetailView.vue +136 -0
- package/templates/m3e-app/src/modules/demo/views/OrderSearchView.vue +74 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryBlock.vue +16 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryCarouselTile.vue +71 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryCustomerForm.vue +76 -0
- package/templates/m3e-app/src/modules/gallery/components/GalleryProofOfDelivery.vue +69 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaDay.vue +106 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaMonth.vue +40 -0
- package/templates/m3e-app/src/modules/gallery/components/agenda/AgendaVisitList.vue +45 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatAttachSheet.vue +106 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatContactPicker.vue +85 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatInviteComposer.vue +131 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatPollComposer.vue +148 -0
- package/templates/m3e-app/src/modules/gallery/components/chat/ChatRecentPhotos.vue +62 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsAccount.vue +79 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsTags.vue +53 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/InputsVerification.vue +73 -0
- package/templates/m3e-app/src/modules/gallery/components/inputs/PasswordStrength.vue +37 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryButtons.vue +128 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCarousels.vue +236 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryCharts.vue +84 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryFabs.vue +70 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryInputs.vue +219 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryNavigation.vue +141 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryOverlays.vue +368 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryPickers.vue +175 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryProgress.vue +118 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryScale.vue +103 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GallerySelection.vue +219 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryShapes.vue +48 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GallerySurfaces.vue +213 -0
- package/templates/m3e-app/src/modules/gallery/components/sections/GalleryTables.vue +185 -0
- package/templates/m3e-app/src/modules/gallery/components/surfaces/SurfacesContainerTransform.vue +46 -0
- package/templates/m3e-app/src/modules/gallery/composables/chatTeam.ts +18 -0
- package/templates/m3e-app/src/modules/gallery/composables/composeKind.ts +2 -0
- package/templates/m3e-app/src/modules/gallery/composables/currentPosition.ts +35 -0
- package/templates/m3e-app/src/modules/gallery/composables/demoOrders.ts +29 -0
- package/templates/m3e-app/src/modules/gallery/composables/featuredStories.ts +73 -0
- package/templates/m3e-app/src/modules/gallery/composables/fieldFormats.ts +36 -0
- package/templates/m3e-app/src/modules/gallery/composables/openExternal.ts +11 -0
- package/templates/m3e-app/src/modules/gallery/composables/routePlan.ts +90 -0
- package/templates/m3e-app/src/modules/gallery/composables/useAgenda.ts +61 -0
- package/templates/m3e-app/src/modules/gallery/composables/useChatCustomers.ts +31 -0
- package/templates/m3e-app/src/modules/gallery/composables/useChatDemo.ts +299 -0
- package/templates/m3e-app/src/modules/gallery/composables/useGallerySections.ts +230 -0
- package/templates/m3e-app/src/modules/gallery/composables/useLocalAttachments.ts +71 -0
- package/templates/m3e-app/src/modules/gallery/composables/useLocationShare.ts +38 -0
- package/templates/m3e-app/src/modules/gallery/composables/usePhotoScenes.ts +82 -0
- package/templates/m3e-app/src/modules/gallery/composables/useTreeDemo.ts +67 -0
- package/templates/m3e-app/src/modules/gallery/composables/wilayas.ts +67 -0
- package/templates/m3e-app/src/modules/gallery/router/routes/gallery.routes.ts +52 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryAgendaView.vue +117 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryChatView.vue +292 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryContactsView.vue +77 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryFeaturedView.vue +60 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryLoginView.vue +135 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryOnboardingView.vue +116 -0
- package/templates/m3e-app/src/modules/gallery/views/GallerySectionView.vue +27 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryTabsView.vue +135 -0
- package/templates/m3e-app/src/modules/gallery/views/GalleryView.vue +50 -0
- package/templates/m3e-app/src/modules/home/components/HomeHero.vue +57 -0
- package/templates/m3e-app/src/modules/home/composables/useHomeFeatures.ts +128 -0
- package/templates/m3e-app/src/modules/home/composables/useOpenFeature.ts +22 -0
- package/templates/m3e-app/src/modules/home/router/routes/home.routes.ts +21 -0
- package/templates/m3e-app/src/modules/home/views/FeatureDetailView.vue +66 -0
- package/templates/m3e-app/src/modules/home/views/HomeView.vue +47 -0
- package/templates/m3e-app/src/modules/settings/components/RolePalette.vue +38 -0
- package/templates/m3e-app/src/modules/settings/components/SeedSwatches.vue +41 -0
- package/templates/m3e-app/src/modules/settings/components/SettingsChoice.vue +43 -0
- package/templates/m3e-app/src/modules/settings/components/StudioPreview.vue +52 -0
- package/templates/m3e-app/src/modules/settings/router/routes/settings.routes.ts +17 -0
- package/templates/m3e-app/src/modules/settings/types.ts +7 -0
- package/templates/m3e-app/src/modules/settings/views/ColorStudioView.vue +166 -0
- package/templates/m3e-app/src/modules/settings/views/SettingsView.vue +157 -0
- package/templates/m3e-app/src/plugins/bootstrapError.ts +62 -0
- package/templates/m3e-app/src/plugins/capacitor/index.ts +14 -0
- package/templates/m3e-app/src/plugins/capacitor/useAndroidBackButton.ts +36 -0
- package/templates/m3e-app/src/plugins/capacitor/useKeyboard.ts +48 -0
- package/templates/m3e-app/src/plugins/capacitor/useSplashScreen.ts +43 -0
- package/templates/m3e-app/src/plugins/capacitor/useStatusBar.ts +16 -0
- package/templates/m3e-app/src/plugins/framework7.plugin.ts +36 -0
- package/templates/m3e-app/src/plugins/i18n.plugin.ts +87 -0
- package/templates/m3e-app/src/plugins/m3e.plugin.ts +22 -0
- package/templates/m3e-app/src/plugins/seed.plugin.ts +7 -0
- package/templates/m3e-app/src/plugins/sqlite.plugin.ts +32 -0
- package/templates/m3e-app/src/router/global/global.routes.ts +12 -0
- package/templates/m3e-app/src/router/index.ts +20 -0
- package/templates/m3e-app/src/shared/components/error/404.vue +13 -0
- package/templates/m3e-app/src/shared/components/layout/EmptyState.vue +30 -0
- package/templates/m3e-app/src/shared/components/layout/SectionHeader.vue +10 -0
- package/templates/m3e-app/src/shared/components/page/AppPage.vue +104 -0
- package/templates/m3e-app/src/shared/composables/navigation/useActiveTab.ts +39 -0
- package/templates/m3e-app/src/shared/composables/navigation/useContainerTransform.ts +117 -0
- package/templates/m3e-app/src/shared/composables/navigation/useNavigationGuard.ts +48 -0
- package/templates/m3e-app/src/shared/composables/navigation/useNavigationVisibility.ts +64 -0
- package/templates/m3e-app/src/shared/composables/navigation/useViewRouter.ts +25 -0
- package/templates/m3e-app/src/shared/composables/navigation/useWindowClass.ts +22 -0
- package/templates/m3e-app/src/shared/composables/theme/useThemeSettings.ts +155 -0
- package/templates/m3e-app/src/shared/database/candidates/capacitorSqlite.ts +36 -0
- package/templates/m3e-app/src/shared/database/candidates/index.ts +4 -0
- package/templates/m3e-app/src/shared/database/candidates/opfsSahPool.ts +25 -0
- package/templates/m3e-app/src/shared/database/candidates/types.ts +56 -0
- package/templates/m3e-app/src/shared/database/candidates/waSqlite.ts +56 -0
- package/templates/m3e-app/src/shared/database/database.ts +219 -0
- package/templates/m3e-app/src/shared/database/index.ts +3 -0
- package/templates/m3e-app/src/shared/database/migrations.ts +223 -0
- package/templates/m3e-app/src/shared/database/opfs.worker.ts +5 -0
- package/templates/m3e-app/src/shared/database/queries.ts +26 -0
- package/templates/m3e-app/src/shared/database/schema.ts +153 -0
- package/templates/m3e-app/src/shared/database/storage.ts +64 -0
- package/templates/m3e-app/src/shared/database/wa.worker.ts +5 -0
- package/templates/m3e-app/src/shared/utils/lazyRoute.ts +41 -0
- package/templates/m3e-app/src/shared/utils/resolvers/resolvers.ts +42 -0
- package/templates/m3e-app/src/shared/utils/textDirection.ts +22 -0
- package/templates/m3e-app/src/shared/utils/theme/themeSettings.ts +59 -0
- package/templates/m3e-app/src/shared/utils/tone.ts +8 -0
- package/templates/m3e-app/tests/benchmark.suite.test.ts +104 -0
- package/templates/m3e-app/tests/containerTransform.test.ts +58 -0
- package/templates/m3e-app/tests/fieldFormats.test.ts +25 -0
- package/templates/m3e-app/tests/lazyRoute.test.ts +30 -0
- package/templates/m3e-app/tests/locales.test.ts +73 -0
- package/templates/m3e-app/tests/migrations.test.ts +74 -0
- package/templates/m3e-app/tests/navigationGuard.test.ts +82 -0
- package/templates/m3e-app/tests/openDatabase.test.ts +54 -0
- package/templates/m3e-app/tests/sales.repository.test.ts +329 -0
- package/templates/m3e-app/tests/storage.test.ts +117 -0
- package/templates/m3e-app/tests/textDirection.test.ts +11 -0
- package/templates/m3e-app/tooling/linkedPackages.ts +112 -0
- package/templates/m3e-app/tsconfig.json +21 -0
- package/templates/m3e-app/vite.config.ts +144 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<GalleryBlock
|
|
3
|
+
:title="t('gallery.inputs.verification')"
|
|
4
|
+
:note="t('gallery.inputs.verificationNote', { code: DEMO_CODE })"
|
|
5
|
+
stack
|
|
6
|
+
>
|
|
7
|
+
<M3CodeField
|
|
8
|
+
ref="field"
|
|
9
|
+
v-model="code"
|
|
10
|
+
:label="t('gallery.inputs.codeLabel')"
|
|
11
|
+
:error="error"
|
|
12
|
+
:supporting="verified ? t('gallery.inputs.codeVerified') : t('gallery.inputs.codeSent')"
|
|
13
|
+
:success="verified"
|
|
14
|
+
@complete="check"
|
|
15
|
+
/>
|
|
16
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
17
|
+
<M3Button v-if="verified" variant="tonal" size="s" @click="reset">
|
|
18
|
+
{{ t("gallery.inputs.codeAgain") }}
|
|
19
|
+
</M3Button>
|
|
20
|
+
<M3Button v-else variant="text" size="s" :disabled="wait > 0" @click="resend">
|
|
21
|
+
<template #icon><i-ms-sms-outline-rounded /></template>
|
|
22
|
+
{{ wait > 0 ? t("gallery.inputs.resendIn", { s: wait }) : t("gallery.inputs.resend") }}
|
|
23
|
+
</M3Button>
|
|
24
|
+
</div>
|
|
25
|
+
</GalleryBlock>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup lang="ts">
|
|
29
|
+
import type { M3CodeField } from "@cavulsqa/m3e-vue";
|
|
30
|
+
import GalleryBlock from "@/modules/gallery/components/GalleryBlock.vue";
|
|
31
|
+
|
|
32
|
+
const DEMO_CODE = "246810";
|
|
33
|
+
const RESEND_AFTER = 30;
|
|
34
|
+
|
|
35
|
+
const { t } = useI18n();
|
|
36
|
+
const snackbar = useSnackbar();
|
|
37
|
+
const field = useTemplateRef<InstanceType<typeof M3CodeField>>("field");
|
|
38
|
+
const code = ref("");
|
|
39
|
+
const error = ref<string>();
|
|
40
|
+
const verified = ref(false);
|
|
41
|
+
const wait = ref(RESEND_AFTER);
|
|
42
|
+
|
|
43
|
+
const { pause, resume } = useIntervalFn(() => {
|
|
44
|
+
wait.value = Math.max(0, wait.value - 1);
|
|
45
|
+
if (wait.value === 0) pause();
|
|
46
|
+
}, 1000);
|
|
47
|
+
|
|
48
|
+
watch(code, (value) => {
|
|
49
|
+
if (value.length < DEMO_CODE.length) error.value = undefined;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
function check(value: string) {
|
|
53
|
+
if (value === DEMO_CODE) {
|
|
54
|
+
verified.value = true;
|
|
55
|
+
pause();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
error.value = t("gallery.inputs.codeWrong");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function resend() {
|
|
62
|
+
code.value = "";
|
|
63
|
+
wait.value = RESEND_AFTER;
|
|
64
|
+
resume();
|
|
65
|
+
void snackbar.show(t("gallery.inputs.codeResent"));
|
|
66
|
+
field.value?.focus();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function reset() {
|
|
70
|
+
verified.value = false;
|
|
71
|
+
resend();
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex items-center gap-3" :class="TONE[score]">
|
|
3
|
+
<div class="flex flex-1 gap-1" aria-hidden="true">
|
|
4
|
+
<span
|
|
5
|
+
v-for="step in 4"
|
|
6
|
+
:key="step"
|
|
7
|
+
class="password-strength__step h-1.5 flex-1 rounded-full"
|
|
8
|
+
:class="{ 'password-strength__step--on': step <= score }"
|
|
9
|
+
/>
|
|
10
|
+
</div>
|
|
11
|
+
<span class="type-label-medium min-w-14 text-end" role="status">{{ label }}</span>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
defineProps<{ score: 0 | 1 | 2 | 3 | 4; label: string }>();
|
|
17
|
+
|
|
18
|
+
const TONE = [
|
|
19
|
+
"text-on-surface-variant",
|
|
20
|
+
"text-error",
|
|
21
|
+
"text-tertiary",
|
|
22
|
+
"text-primary",
|
|
23
|
+
"text-primary",
|
|
24
|
+
] as const;
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
.password-strength__step {
|
|
29
|
+
background: var(--md-sys-color-surface-container-highest);
|
|
30
|
+
transition: background-color var(--md-sys-motion-spring-default-effects-duration)
|
|
31
|
+
var(--md-sys-motion-spring-default-effects);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.password-strength__step--on {
|
|
35
|
+
background: currentColor;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<GalleryBlock :title="t('gallery.buttons.variants')" :note="t('gallery.buttons.variantsNote')">
|
|
3
|
+
<M3Button v-for="variant in VARIANTS" :key="variant" :variant="variant">{{ variant }}</M3Button>
|
|
4
|
+
</GalleryBlock>
|
|
5
|
+
|
|
6
|
+
<GalleryBlock :title="t('gallery.buttons.sizes')" :note="t('gallery.buttons.sizesNote')" stack>
|
|
7
|
+
<div v-for="size in SIZES" :key="size" class="flex flex-wrap items-center gap-3">
|
|
8
|
+
<M3Button :size="size">
|
|
9
|
+
<template #icon><i-ms-add-rounded /></template>
|
|
10
|
+
{{ size.toUpperCase() }}
|
|
11
|
+
</M3Button>
|
|
12
|
+
<M3Button :size="size" shape="square" variant="tonal">{{ size.toUpperCase() }}</M3Button>
|
|
13
|
+
</div>
|
|
14
|
+
</GalleryBlock>
|
|
15
|
+
|
|
16
|
+
<GalleryBlock :title="t('gallery.buttons.toggle')" :note="t('gallery.buttons.toggleNote')">
|
|
17
|
+
<M3Button v-model:selected="saved" toggle size="m">
|
|
18
|
+
<template #icon="{ selected }">
|
|
19
|
+
<i-ms-bookmark-rounded v-if="selected" />
|
|
20
|
+
<i-ms-bookmark-outline-rounded v-else />
|
|
21
|
+
</template>
|
|
22
|
+
{{ t("gallery.buttons.save") }}
|
|
23
|
+
</M3Button>
|
|
24
|
+
<M3Button v-model:selected="starred" toggle variant="outlined" size="m" shape="square">
|
|
25
|
+
{{ t("gallery.buttons.star") }}
|
|
26
|
+
</M3Button>
|
|
27
|
+
</GalleryBlock>
|
|
28
|
+
|
|
29
|
+
<GalleryBlock :title="t('gallery.buttons.icon')" :note="t('gallery.buttons.iconNote')">
|
|
30
|
+
<M3IconButton
|
|
31
|
+
:label="t('gallery.buttons.favorite')"
|
|
32
|
+
variant="standard"
|
|
33
|
+
toggle
|
|
34
|
+
:selected="liked"
|
|
35
|
+
@update:selected="liked = $event"
|
|
36
|
+
>
|
|
37
|
+
<template #default="{ selected }">
|
|
38
|
+
<i-ms-favorite-rounded v-if="selected" />
|
|
39
|
+
<i-ms-favorite-outline-rounded v-else />
|
|
40
|
+
</template>
|
|
41
|
+
</M3IconButton>
|
|
42
|
+
<M3IconButton :label="t('gallery.buttons.share')" variant="filled" width="wide"
|
|
43
|
+
><i-ms-share-outline-rounded
|
|
44
|
+
/></M3IconButton>
|
|
45
|
+
<M3IconButton :label="t('gallery.buttons.edit')" variant="tonal" size="m" shape="square"
|
|
46
|
+
><i-ms-edit-outline-rounded
|
|
47
|
+
/></M3IconButton>
|
|
48
|
+
<M3IconButton :label="t('gallery.buttons.more')" variant="outlined" width="narrow"
|
|
49
|
+
><i-ms-more-vert-rounded
|
|
50
|
+
/></M3IconButton>
|
|
51
|
+
</GalleryBlock>
|
|
52
|
+
|
|
53
|
+
<GalleryBlock :title="t('gallery.buttons.group')" :note="t('gallery.buttons.groupNote')">
|
|
54
|
+
<M3ButtonGroup size="m" :label="t('gallery.buttons.group')">
|
|
55
|
+
<M3IconButton :label="t('gallery.buttons.bold')" variant="tonal"
|
|
56
|
+
><i-ms-format-bold-rounded
|
|
57
|
+
/></M3IconButton>
|
|
58
|
+
<M3IconButton :label="t('gallery.buttons.italic')" variant="tonal"
|
|
59
|
+
><i-ms-format-italic-rounded
|
|
60
|
+
/></M3IconButton>
|
|
61
|
+
<M3IconButton :label="t('gallery.buttons.underline')" variant="tonal"
|
|
62
|
+
><i-ms-format-underlined-rounded
|
|
63
|
+
/></M3IconButton>
|
|
64
|
+
</M3ButtonGroup>
|
|
65
|
+
</GalleryBlock>
|
|
66
|
+
|
|
67
|
+
<GalleryBlock :title="t('gallery.buttons.connected')" :note="t('gallery.buttons.connectedNote')">
|
|
68
|
+
<M3ButtonGroup variant="connected" size="s" :label="t('gallery.buttons.connected')">
|
|
69
|
+
<M3Button
|
|
70
|
+
v-for="period in PERIODS"
|
|
71
|
+
:key="period"
|
|
72
|
+
variant="tonal"
|
|
73
|
+
toggle
|
|
74
|
+
:selected="range === period"
|
|
75
|
+
@update:selected="range = period"
|
|
76
|
+
>
|
|
77
|
+
{{ t(`gallery.buttons.periods.${period}`) }}
|
|
78
|
+
</M3Button>
|
|
79
|
+
</M3ButtonGroup>
|
|
80
|
+
</GalleryBlock>
|
|
81
|
+
|
|
82
|
+
<GalleryBlock :title="t('gallery.buttons.split')" :note="t('gallery.buttons.splitNote')">
|
|
83
|
+
<M3SplitButton
|
|
84
|
+
v-model:open="splitOpen"
|
|
85
|
+
size="m"
|
|
86
|
+
:menu-label="t('gallery.buttons.moreOptions')"
|
|
87
|
+
@click="sent"
|
|
88
|
+
>
|
|
89
|
+
<template #icon><i-ms-share-outline-rounded /></template>
|
|
90
|
+
{{ t("gallery.buttons.send") }}
|
|
91
|
+
<template #menu>
|
|
92
|
+
<span ref="splitAnchor" class="absolute inset-0 pointer-events-none" />
|
|
93
|
+
</template>
|
|
94
|
+
</M3SplitButton>
|
|
95
|
+
<M3Menu
|
|
96
|
+
v-model:open="splitOpen"
|
|
97
|
+
:anchor="splitAnchor"
|
|
98
|
+
align="end"
|
|
99
|
+
:label="t('gallery.buttons.moreOptions')"
|
|
100
|
+
>
|
|
101
|
+
<M3MenuItem :label="t('gallery.buttons.schedule')" @select="sent" />
|
|
102
|
+
<M3MenuItem :label="t('gallery.buttons.saveDraft')" @select="sent" />
|
|
103
|
+
</M3Menu>
|
|
104
|
+
</GalleryBlock>
|
|
105
|
+
</template>
|
|
106
|
+
|
|
107
|
+
<script setup lang="ts">
|
|
108
|
+
import GalleryBlock from "@/modules/gallery/components/GalleryBlock.vue";
|
|
109
|
+
import type { ButtonSize } from "@cavulsqa/m3e-vue";
|
|
110
|
+
|
|
111
|
+
const { t } = useI18n();
|
|
112
|
+
const snackbar = useSnackbar();
|
|
113
|
+
|
|
114
|
+
const VARIANTS = ["filled", "tonal", "outlined", "elevated", "text"] as const;
|
|
115
|
+
const SIZES: readonly ButtonSize[] = ["xs", "s", "m", "l", "xl"];
|
|
116
|
+
const PERIODS = ["day", "week", "month"] as const;
|
|
117
|
+
|
|
118
|
+
const saved = ref(false);
|
|
119
|
+
const starred = ref(true);
|
|
120
|
+
const liked = ref(false);
|
|
121
|
+
const range = ref<(typeof PERIODS)[number]>("week");
|
|
122
|
+
const splitOpen = ref(false);
|
|
123
|
+
const splitAnchor = useTemplateRef<HTMLElement>("splitAnchor");
|
|
124
|
+
|
|
125
|
+
function sent() {
|
|
126
|
+
void snackbar.show(t("gallery.buttons.sent"));
|
|
127
|
+
}
|
|
128
|
+
</script>
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<GalleryBlock
|
|
3
|
+
:title="t('gallery.carousels.multiBrowse')"
|
|
4
|
+
:note="t('gallery.carousels.multiBrowseNote')"
|
|
5
|
+
stack
|
|
6
|
+
>
|
|
7
|
+
<M3Carousel
|
|
8
|
+
class="-mx-4 w-[calc(100%+2rem)]"
|
|
9
|
+
:items="PLACES"
|
|
10
|
+
:item-key="placeKey"
|
|
11
|
+
:label="t('gallery.carousels.multiBrowse')"
|
|
12
|
+
:slide-label="slideLabel"
|
|
13
|
+
>
|
|
14
|
+
<template #default="{ item, scrollTo }">
|
|
15
|
+
<GalleryCarouselTile
|
|
16
|
+
:title="t(`gallery.carousels.places.${item.id}`)"
|
|
17
|
+
:icon="item.icon"
|
|
18
|
+
:shape="item.shape"
|
|
19
|
+
:from="item.from"
|
|
20
|
+
:to="item.to"
|
|
21
|
+
@select="scrollTo"
|
|
22
|
+
/>
|
|
23
|
+
</template>
|
|
24
|
+
</M3Carousel>
|
|
25
|
+
</GalleryBlock>
|
|
26
|
+
|
|
27
|
+
<GalleryBlock :title="t('gallery.carousels.hero')" :note="t('gallery.carousels.heroNote')" stack>
|
|
28
|
+
<M3Carousel
|
|
29
|
+
v-model:item="featured"
|
|
30
|
+
class="-mx-4 w-[calc(100%+2rem)]"
|
|
31
|
+
variant="hero"
|
|
32
|
+
:items="PLACES.slice(0, 6)"
|
|
33
|
+
:item-key="placeKey"
|
|
34
|
+
:label="t('gallery.carousels.hero')"
|
|
35
|
+
:slide-label="slideLabel"
|
|
36
|
+
>
|
|
37
|
+
<template #default="{ item, scrollTo }">
|
|
38
|
+
<GalleryCarouselTile
|
|
39
|
+
:title="t(`gallery.carousels.places.${item.id}`)"
|
|
40
|
+
:icon="item.icon"
|
|
41
|
+
:shape="item.shape"
|
|
42
|
+
:from="item.from"
|
|
43
|
+
:to="item.to"
|
|
44
|
+
@select="scrollTo"
|
|
45
|
+
/>
|
|
46
|
+
</template>
|
|
47
|
+
</M3Carousel>
|
|
48
|
+
<span class="type-body-medium text-on-surface-variant">{{
|
|
49
|
+
t("gallery.carousels.featured", {
|
|
50
|
+
place: t(`gallery.carousels.places.${PLACES[featured]!.id}`),
|
|
51
|
+
})
|
|
52
|
+
}}</span>
|
|
53
|
+
</GalleryBlock>
|
|
54
|
+
|
|
55
|
+
<GalleryBlock
|
|
56
|
+
:title="t('gallery.carousels.uncontained')"
|
|
57
|
+
:note="t('gallery.carousels.uncontainedNote')"
|
|
58
|
+
stack
|
|
59
|
+
>
|
|
60
|
+
<M3Carousel
|
|
61
|
+
class="-mx-4 w-[calc(100%+2rem)]"
|
|
62
|
+
variant="uncontained"
|
|
63
|
+
:items="PLACES"
|
|
64
|
+
:item-key="placeKey"
|
|
65
|
+
:item-width="160"
|
|
66
|
+
:height="180"
|
|
67
|
+
:label="t('gallery.carousels.uncontained')"
|
|
68
|
+
:slide-label="slideLabel"
|
|
69
|
+
>
|
|
70
|
+
<template #default="{ item }">
|
|
71
|
+
<GalleryCarouselTile
|
|
72
|
+
:title="t(`gallery.carousels.places.${item.id}`)"
|
|
73
|
+
:icon="item.icon"
|
|
74
|
+
:shape="item.shape"
|
|
75
|
+
:from="item.from"
|
|
76
|
+
:to="item.to"
|
|
77
|
+
/>
|
|
78
|
+
</template>
|
|
79
|
+
</M3Carousel>
|
|
80
|
+
</GalleryBlock>
|
|
81
|
+
|
|
82
|
+
<GalleryBlock
|
|
83
|
+
:title="t('gallery.carousels.photos')"
|
|
84
|
+
:note="t('gallery.carousels.photosNote')"
|
|
85
|
+
stack
|
|
86
|
+
>
|
|
87
|
+
<div class="grid grid-cols-3 gap-1 overflow-hidden rounded-lg">
|
|
88
|
+
<button
|
|
89
|
+
v-for="(photo, position) in photos"
|
|
90
|
+
:key="position"
|
|
91
|
+
type="button"
|
|
92
|
+
class="aspect-square w-full overflow-hidden border-0 p-0"
|
|
93
|
+
:aria-label="photo.alt"
|
|
94
|
+
@click="openPhoto(position)"
|
|
95
|
+
>
|
|
96
|
+
<M3Image :src="photo.src" alt="" ratio="1 / 1" class="size-full" />
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
</GalleryBlock>
|
|
100
|
+
|
|
101
|
+
<GalleryBlock :title="t('gallery.carousels.lazy')" :note="t('gallery.carousels.lazyNote')" stack>
|
|
102
|
+
<div class="grid grid-cols-2 gap-3">
|
|
103
|
+
<M3Image
|
|
104
|
+
v-if="photos[0]"
|
|
105
|
+
:src="photos[0].src"
|
|
106
|
+
:alt="photos[0].alt"
|
|
107
|
+
:width="photos[0].width"
|
|
108
|
+
:height="photos[0].height"
|
|
109
|
+
placeholder="var(--md-sys-color-secondary-container)"
|
|
110
|
+
class="rounded-lg"
|
|
111
|
+
/>
|
|
112
|
+
<M3Image
|
|
113
|
+
src="/missing-photo.jpg"
|
|
114
|
+
:alt="t('gallery.carousels.missing')"
|
|
115
|
+
ratio="4 / 3"
|
|
116
|
+
class="rounded-lg"
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
</GalleryBlock>
|
|
120
|
+
|
|
121
|
+
<M3PhotoBrowser
|
|
122
|
+
v-model:open="browserOpen"
|
|
123
|
+
v-model:index="photoIndex"
|
|
124
|
+
:photos="photos"
|
|
125
|
+
:label="t('gallery.carousels.photos')"
|
|
126
|
+
:close-label="t('shell.dismiss')"
|
|
127
|
+
:counter-text="counterText"
|
|
128
|
+
/>
|
|
129
|
+
</template>
|
|
130
|
+
|
|
131
|
+
<script setup lang="ts">
|
|
132
|
+
import type { MaterialShapeName } from "@cavulsqa/m3e";
|
|
133
|
+
import { markRaw, type Component } from "vue";
|
|
134
|
+
import BeachIcon from "~icons/material-symbols/beach-access-outline-rounded";
|
|
135
|
+
import CafeIcon from "~icons/material-symbols/local-cafe-outline-rounded";
|
|
136
|
+
import CityIcon from "~icons/material-symbols/location-city-rounded";
|
|
137
|
+
import ForestIcon from "~icons/material-symbols/forest-outline-rounded";
|
|
138
|
+
import HikingIcon from "~icons/material-symbols/hiking-rounded";
|
|
139
|
+
import LandscapeIcon from "~icons/material-symbols/landscape-outline-rounded";
|
|
140
|
+
import ParkIcon from "~icons/material-symbols/park-outline-rounded";
|
|
141
|
+
import SailingIcon from "~icons/material-symbols/sailing-outline-rounded";
|
|
142
|
+
import GalleryBlock from "@/modules/gallery/components/GalleryBlock.vue";
|
|
143
|
+
import GalleryCarouselTile from "@/modules/gallery/components/GalleryCarouselTile.vue";
|
|
144
|
+
import { usePhotoScenes } from "@/modules/gallery/composables/usePhotoScenes";
|
|
145
|
+
|
|
146
|
+
interface Place {
|
|
147
|
+
id: string;
|
|
148
|
+
icon: Component;
|
|
149
|
+
shape: MaterialShapeName;
|
|
150
|
+
from: string;
|
|
151
|
+
to: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const { t } = useI18n();
|
|
155
|
+
const featured = ref(0);
|
|
156
|
+
const browserOpen = ref(false);
|
|
157
|
+
const photoIndex = ref(0);
|
|
158
|
+
const { photos } = usePhotoScenes((kind) => t(`gallery.carousels.scenes.${kind}`));
|
|
159
|
+
useDarkStatusBar(() => browserOpen.value);
|
|
160
|
+
|
|
161
|
+
function openPhoto(position: number) {
|
|
162
|
+
photoIndex.value = position;
|
|
163
|
+
browserOpen.value = true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function counterText(position: number, count: number) {
|
|
167
|
+
return t("gallery.carousels.counter", { position, count });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const PLACES: readonly Place[] = [
|
|
171
|
+
{
|
|
172
|
+
id: "mountains",
|
|
173
|
+
icon: markRaw(LandscapeIcon),
|
|
174
|
+
shape: "cookie9Sided",
|
|
175
|
+
from: "primary-container",
|
|
176
|
+
to: "tertiary-container",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "forest",
|
|
180
|
+
icon: markRaw(ForestIcon),
|
|
181
|
+
shape: "clover4Leaf",
|
|
182
|
+
from: "secondary-container",
|
|
183
|
+
to: "primary-container",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
id: "coast",
|
|
187
|
+
icon: markRaw(BeachIcon),
|
|
188
|
+
shape: "sunny",
|
|
189
|
+
from: "tertiary-container",
|
|
190
|
+
to: "secondary-container",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: "city",
|
|
194
|
+
icon: markRaw(CityIcon),
|
|
195
|
+
shape: "pentagon",
|
|
196
|
+
from: "primary-container",
|
|
197
|
+
to: "secondary-container",
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
id: "harbour",
|
|
201
|
+
icon: markRaw(SailingIcon),
|
|
202
|
+
shape: "flower",
|
|
203
|
+
from: "tertiary-container",
|
|
204
|
+
to: "primary-container",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: "trail",
|
|
208
|
+
icon: markRaw(HikingIcon),
|
|
209
|
+
shape: "softBurst",
|
|
210
|
+
from: "secondary-container",
|
|
211
|
+
to: "tertiary-container",
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: "park",
|
|
215
|
+
icon: markRaw(ParkIcon),
|
|
216
|
+
shape: "gem",
|
|
217
|
+
from: "primary-container",
|
|
218
|
+
to: "tertiary-container",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "cafe",
|
|
222
|
+
icon: markRaw(CafeIcon),
|
|
223
|
+
shape: "cookie4Sided",
|
|
224
|
+
from: "tertiary-container",
|
|
225
|
+
to: "secondary-container",
|
|
226
|
+
},
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
function placeKey(place: Place) {
|
|
230
|
+
return place.id;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function slideLabel(index: number, count: number) {
|
|
234
|
+
return t("gallery.carousels.slide", { n: index + 1, count });
|
|
235
|
+
}
|
|
236
|
+
</script>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<GalleryBlock :title="t('gallery.charts.line')" :note="t('gallery.charts.lineNote')" stack>
|
|
3
|
+
<M3LineChart
|
|
4
|
+
:labels="months"
|
|
5
|
+
:series="sales"
|
|
6
|
+
:label="t('gallery.charts.line')"
|
|
7
|
+
:format="compact"
|
|
8
|
+
area
|
|
9
|
+
/>
|
|
10
|
+
</GalleryBlock>
|
|
11
|
+
|
|
12
|
+
<GalleryBlock :title="t('gallery.charts.bar')" :note="t('gallery.charts.barNote')" stack>
|
|
13
|
+
<div>
|
|
14
|
+
<M3Chip
|
|
15
|
+
kind="filter"
|
|
16
|
+
:label="t('gallery.charts.stacked')"
|
|
17
|
+
:selected="stacked"
|
|
18
|
+
@update:selected="stacked = $event"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
<M3BarChart
|
|
22
|
+
:labels="REPS"
|
|
23
|
+
:series="reps"
|
|
24
|
+
:label="t('gallery.charts.bar')"
|
|
25
|
+
:format="compact"
|
|
26
|
+
:stacked="stacked"
|
|
27
|
+
/>
|
|
28
|
+
</GalleryBlock>
|
|
29
|
+
|
|
30
|
+
<GalleryBlock :title="t('gallery.charts.donut')" :note="t('gallery.charts.donutNote')" stack>
|
|
31
|
+
<M3DonutChart
|
|
32
|
+
:segments="channels"
|
|
33
|
+
:label="t('gallery.charts.donut')"
|
|
34
|
+
:total-label="t('gallery.charts.total')"
|
|
35
|
+
:format="compact"
|
|
36
|
+
/>
|
|
37
|
+
</GalleryBlock>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<script setup lang="ts">
|
|
41
|
+
import type { ChartSeries } from "@cavulsqa/m3e-vue";
|
|
42
|
+
import GalleryBlock from "@/modules/gallery/components/GalleryBlock.vue";
|
|
43
|
+
|
|
44
|
+
const REPS = ["Karim", "Samir", "Nabil", "Yacine", "Walid"];
|
|
45
|
+
|
|
46
|
+
const { t, locale } = useI18n();
|
|
47
|
+
const stacked = ref(false);
|
|
48
|
+
|
|
49
|
+
const months = computed(() =>
|
|
50
|
+
Array.from({ length: 12 }, (_, month) =>
|
|
51
|
+
new Date(2026, month, 1).toLocaleDateString(locale.value, { month: "short" }),
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const compact = (value: number) =>
|
|
56
|
+
new Intl.NumberFormat(locale.value, { notation: "compact", maximumFractionDigits: 1 }).format(
|
|
57
|
+
value,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const sales = computed<ChartSeries[]>(() => [
|
|
61
|
+
{
|
|
62
|
+
label: t("gallery.charts.thisYear"),
|
|
63
|
+
values: [420, 460, 510, 480, 560, 640, 700, 690, 760, 820, null, null].map((v) =>
|
|
64
|
+
v === null ? null : v * 1000,
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: t("gallery.charts.lastYear"),
|
|
69
|
+
values: [380, 400, 430, 470, 450, 520, 580, 610, 600, 650, 700, 780].map((v) => v * 1000),
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const reps = computed<ChartSeries[]>(() => [
|
|
74
|
+
{ label: t("gallery.charts.august"), values: [180, 140, 210, 95, 160].map((v) => v * 1000) },
|
|
75
|
+
{ label: t("gallery.charts.september"), values: [210, 120, 240, 130, 175].map((v) => v * 1000) },
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const channels = computed(() => [
|
|
79
|
+
{ label: t("gallery.charts.channels.shops"), value: 1_240_000 },
|
|
80
|
+
{ label: t("gallery.charts.channels.wholesale"), value: 860_000 },
|
|
81
|
+
{ label: t("gallery.charts.channels.online"), value: 310_000 },
|
|
82
|
+
{ label: t("gallery.charts.channels.export"), value: 120_000 },
|
|
83
|
+
]);
|
|
84
|
+
</script>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<GalleryBlock :title="t('gallery.fabs.sizes')" :note="t('gallery.fabs.sizesNote')">
|
|
3
|
+
<M3Fab v-for="size in SIZES" :key="size" :size="size" :label="t('gallery.fabs.compose')">
|
|
4
|
+
<i-ms-edit-outline-rounded />
|
|
5
|
+
</M3Fab>
|
|
6
|
+
</GalleryBlock>
|
|
7
|
+
|
|
8
|
+
<GalleryBlock :title="t('gallery.fabs.colors')" :note="t('gallery.fabs.colorsNote')">
|
|
9
|
+
<M3Fab v-for="color in COLORS" :key="color" :color="color" size="small" :label="color">
|
|
10
|
+
<i-ms-add-rounded />
|
|
11
|
+
</M3Fab>
|
|
12
|
+
</GalleryBlock>
|
|
13
|
+
|
|
14
|
+
<GalleryBlock :title="t('gallery.fabs.extended')" :note="t('gallery.fabs.extendedNote')">
|
|
15
|
+
<M3Fab
|
|
16
|
+
:extended="extended"
|
|
17
|
+
:label="t('gallery.fabs.compose')"
|
|
18
|
+
size="medium"
|
|
19
|
+
@click="extended = !extended"
|
|
20
|
+
>
|
|
21
|
+
<i-ms-edit-outline-rounded />
|
|
22
|
+
</M3Fab>
|
|
23
|
+
</GalleryBlock>
|
|
24
|
+
|
|
25
|
+
<GalleryBlock :title="t('gallery.fabs.menu')" :note="t('gallery.fabs.menuNote')">
|
|
26
|
+
<div class="flex w-full justify-end pt-64">
|
|
27
|
+
<M3FabMenu
|
|
28
|
+
v-model:open="menuOpen"
|
|
29
|
+
:label="t('gallery.fabs.create')"
|
|
30
|
+
:close-label="t('shell.dismiss')"
|
|
31
|
+
>
|
|
32
|
+
<template #icon><i-ms-add-rounded /></template>
|
|
33
|
+
<M3FabMenuItem :index="2" :label="t('gallery.fabs.order')" @click="done">
|
|
34
|
+
<i-ms-receipt-long-outline-rounded />
|
|
35
|
+
</M3FabMenuItem>
|
|
36
|
+
<M3FabMenuItem :index="1" :label="t('gallery.fabs.customer')" @click="done">
|
|
37
|
+
<i-ms-person-outline-rounded />
|
|
38
|
+
</M3FabMenuItem>
|
|
39
|
+
<M3FabMenuItem :index="0" :label="t('gallery.fabs.note')" @click="done">
|
|
40
|
+
<i-ms-draft-outline-rounded />
|
|
41
|
+
</M3FabMenuItem>
|
|
42
|
+
</M3FabMenu>
|
|
43
|
+
</div>
|
|
44
|
+
</GalleryBlock>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
import type { FabColor, FabSize } from "@cavulsqa/m3e-vue";
|
|
49
|
+
import GalleryBlock from "@/modules/gallery/components/GalleryBlock.vue";
|
|
50
|
+
|
|
51
|
+
const { t } = useI18n();
|
|
52
|
+
const snackbar = useSnackbar();
|
|
53
|
+
|
|
54
|
+
const SIZES: readonly FabSize[] = ["small", "default", "medium", "large"];
|
|
55
|
+
const COLORS: readonly FabColor[] = [
|
|
56
|
+
"primary-container",
|
|
57
|
+
"secondary-container",
|
|
58
|
+
"tertiary-container",
|
|
59
|
+
"primary",
|
|
60
|
+
"secondary",
|
|
61
|
+
"tertiary",
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const extended = ref(true);
|
|
65
|
+
const menuOpen = ref(false);
|
|
66
|
+
|
|
67
|
+
function done() {
|
|
68
|
+
void snackbar.show(t("gallery.fabs.picked"));
|
|
69
|
+
}
|
|
70
|
+
</script>
|