@mframework/ui 0.1.0-beta.0 → 0.1.0-beta.2

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 (111) hide show
  1. package/dist/adapters/adapter-directus/src/types/ui.d.ts +21 -0
  2. package/dist/adapters/adapter-directus/src/types/ui.js +1 -0
  3. package/dist/module.d.mts +9 -0
  4. package/dist/module.d.ts +6 -0
  5. package/dist/module.js +68 -0
  6. package/dist/module.json +9 -0
  7. package/dist/module.mjs +38 -0
  8. package/dist/modules/ui/src/module.d.ts +8 -0
  9. package/dist/modules/ui/src/module.js +75 -0
  10. package/dist/modules/ui/src/runtime/composables/useMToast.d.ts +5 -0
  11. package/dist/modules/ui/src/runtime/composables/useMToast.js +11 -0
  12. package/dist/modules/ui/src/runtime/design/tokens.d.ts +22 -0
  13. package/dist/modules/ui/src/runtime/design/tokens.js +22 -0
  14. package/dist/modules/ui/src/runtime/plugins/builder.d.ts +3 -0
  15. package/dist/modules/ui/src/runtime/plugins/builder.js +311 -0
  16. package/dist/modules/ui/src/runtime/plugins/fontawesome.d.ts +3 -0
  17. package/dist/modules/ui/src/runtime/plugins/fontawesome.js +9 -0
  18. package/dist/modules/ui/src/runtime/plugins/formkit.d.ts +3 -0
  19. package/dist/modules/ui/src/runtime/plugins/formkit.js +8 -0
  20. package/dist/modules/ui/src/runtime/plugins/motion.d.ts +2 -0
  21. package/dist/modules/ui/src/runtime/plugins/motion.js +5 -0
  22. package/dist/modules/ui/src/runtime/plugins/theme-switcher.d.ts +2 -0
  23. package/dist/modules/ui/src/runtime/plugins/theme-switcher.js +27 -0
  24. package/dist/modules/ui/src/runtime/plugins/theme.d.ts +2 -0
  25. package/dist/modules/ui/src/runtime/plugins/theme.js +44 -0
  26. package/dist/modules/ui/src/runtime/plugins/vuetify.d.ts +3 -0
  27. package/dist/modules/ui/src/runtime/plugins/vuetify.js +33 -0
  28. package/dist/modules/ui/src/runtime/search/client.d.ts +2 -0
  29. package/dist/modules/ui/src/runtime/search/client.js +21 -0
  30. package/dist/modules/ui/src/runtime/search/plugin.d.ts +2 -0
  31. package/dist/modules/ui/src/runtime/search/plugin.js +7 -0
  32. package/dist/modules/ui/src/utils/color.d.ts +2 -0
  33. package/dist/modules/ui/src/utils/color.js +11 -0
  34. package/dist/modules/ui/src/utils/fonts.d.ts +5 -0
  35. package/dist/modules/ui/src/utils/fonts.js +18 -0
  36. package/dist/modules/ui/src/utils/formkit.d.ts +12 -0
  37. package/dist/modules/ui/src/utils/formkit.js +59 -0
  38. package/dist/modules/ui/src/utils/icons.d.ts +4 -0
  39. package/dist/modules/ui/src/utils/icons.js +36 -0
  40. package/dist/runtime/assets/config/tailwind.conifg.d.ts +0 -0
  41. package/dist/runtime/assets/config/tailwind.conifg.js +11 -0
  42. package/dist/runtime/components/MButton.d.vue.ts +0 -0
  43. package/dist/runtime/components/MButton.vue +15 -0
  44. package/dist/runtime/components/MButton.vue.d.ts +0 -0
  45. package/dist/runtime/composables/useMToast.d.ts +5 -0
  46. package/dist/runtime/composables/useMToast.js +11 -0
  47. package/dist/runtime/plugins/builder.d.ts +3 -0
  48. package/dist/runtime/plugins/builder.js +311 -0
  49. package/dist/runtime/plugins/fontawesome.d.ts +3 -0
  50. package/dist/runtime/plugins/fontawesome.js +9 -0
  51. package/dist/runtime/plugins/formkit.d.ts +3 -0
  52. package/dist/runtime/plugins/formkit.js +8 -0
  53. package/dist/runtime/plugins/icon-switcher.d.ts +1 -1
  54. package/dist/runtime/plugins/icon-switcher.js +15 -9
  55. package/dist/runtime/plugins/lightgallery.d.ts +6 -0
  56. package/dist/runtime/plugins/lightgallery.js +15 -0
  57. package/dist/runtime/plugins/motion.d.ts +2 -0
  58. package/dist/runtime/plugins/motion.js +5 -0
  59. package/dist/runtime/plugins/theme-switcher.d.ts +2 -0
  60. package/dist/runtime/plugins/theme-switcher.js +27 -0
  61. package/dist/runtime/plugins/theme.d.ts +1 -1
  62. package/dist/runtime/plugins/theme.js +31 -25
  63. package/dist/runtime/plugins/vuetify.d.ts +1 -86
  64. package/dist/runtime/plugins/vuetify.js +28 -55
  65. package/dist/runtime/search/components/MSearch.d.vue.ts +0 -0
  66. package/dist/runtime/search/components/MSearch.vue +19 -0
  67. package/dist/runtime/search/components/MSearch.vue.d.ts +0 -0
  68. package/dist/runtime/styles/index.css +5 -0
  69. package/dist/runtime/styles/tailwind.css +1 -0
  70. package/dist/runtime/styles/vuetify.css +3 -0
  71. package/dist/types.d.mts +9 -0
  72. package/dist/utils/color.d.ts +2 -0
  73. package/dist/utils/color.js +11 -0
  74. package/dist/utils/fonts.d.ts +5 -0
  75. package/dist/utils/fonts.js +18 -0
  76. package/dist/utils/formkit.d.ts +12 -0
  77. package/dist/utils/formkit.js +59 -0
  78. package/dist/utils/icons.d.ts +4 -0
  79. package/dist/utils/icons.js +36 -0
  80. package/package.json +12 -10
  81. package/src/module.ts +105 -0
  82. package/src/runtime/assets/config/tailwind.conifg.js +42 -0
  83. package/src/runtime/components/Gallery.vue +66 -0
  84. package/src/runtime/components/MButton.vue +17 -0
  85. package/src/runtime/composables/useMToast.ts +14 -0
  86. package/src/runtime/design/tokens.ts +22 -0
  87. package/src/runtime/plugins/builder.ts +326 -0
  88. package/src/runtime/plugins/fontawesome.ts +11 -0
  89. package/src/runtime/plugins/formkit.ts +9 -0
  90. package/src/runtime/plugins/lightgallery.js +21 -0
  91. package/src/runtime/plugins/motion.ts +6 -0
  92. package/src/runtime/plugins/theme-switcher.ts +32 -0
  93. package/src/runtime/plugins/theme.ts +57 -0
  94. package/src/runtime/plugins/vuetify.ts +36 -0
  95. package/src/runtime/search/client.ts +25 -0
  96. package/src/runtime/search/components/MSearch.vue +19 -0
  97. package/src/runtime/search/plugin.ts +9 -0
  98. package/src/runtime/styles/index.scss +101 -0
  99. package/src/runtime/styles/tailwind.css +9 -0
  100. package/src/runtime/styles/vuetify.scss +5 -0
  101. package/src/types/runtime-config.d.ts +12 -0
  102. package/src/utils/color.js +11 -0
  103. package/src/utils/color.ts +14 -0
  104. package/src/utils/fonts.js +18 -0
  105. package/src/utils/fonts.ts +24 -0
  106. package/src/utils/formkit.js +59 -0
  107. package/src/utils/formkit.ts +75 -0
  108. package/src/utils/icons.js +36 -0
  109. package/src/utils/icons.ts +62 -0
  110. package/dist/runtime/plugins/icons.d.ts +0 -4
  111. package/dist/runtime/plugins/icons.js +0 -13
@@ -1,60 +1,33 @@
1
- // plugins/vuetify.ts
2
- import '@mdi/font/css/materialdesignicons.css';
3
- import 'vuetify/styles';
1
+ import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app';
4
2
  import { createVuetify } from 'vuetify';
5
- import { aliases, fa } from 'vuetify/iconsets/fa-svg';
6
- import { library } from '@fortawesome/fontawesome-svg-core';
7
- import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
8
- import { fas } from '@fortawesome/free-solid-svg-icons';
9
3
  import * as components from 'vuetify/components';
10
- import * as labsComponents from 'vuetify/labs/components';
11
4
  import * as directives from 'vuetify/directives';
12
- import { mdi } from 'vuetify/iconsets/mdi';
13
- // Register fontawesome icons at module scope
14
- library.add(fas);
15
- // Create Vuetify instance at module scope so other runtime plugins can import it
16
- export const vuetify = createVuetify({
17
- ssr: true,
18
- directives,
19
- icons: {
20
- defaultSet: 'fa',
21
- aliases,
22
- sets: {
23
- fa,
24
- mdi,
25
- },
26
- },
27
- components: {
28
- ...components,
29
- ...labsComponents,
30
- },
31
- theme: {
32
- defaultTheme: 'light',
33
- themes: {
34
- light: {
35
- dark: false,
36
- variables: {}, // required to avoid Vuetify crash
37
- colors: {
38
- primary: '#6200EE',
39
- 'primary-darken-1': '#3700B3',
40
- secondary: '#03DAC6',
41
- 'secondary-darken-1': '#018786',
42
- error: '#B00020',
43
- info: '#2196F3',
44
- success: '#4CAF50',
45
- warning: '#FB8C00',
5
+ import 'vuetify/styles';
6
+ export default defineNuxtPlugin((nuxtApp) => {
7
+ const config = useRuntimeConfig();
8
+ const theme = config.public.mframeworkUi?.theme || 'light';
9
+ const vuetify = createVuetify({
10
+ components,
11
+ directives,
12
+ theme: {
13
+ defaultTheme: theme,
14
+ themes: {
15
+ light: {
16
+ dark: false,
17
+ colors: {
18
+ primary: '#3b82f6',
19
+ secondary: '#64748b'
20
+ }
46
21
  },
47
- },
48
- dark: {
49
- dark: true,
50
- variables: {},
51
- colors: {},
52
- },
53
- },
54
- },
55
- });
56
- export default (nuxtApp) => {
57
- // Register FontAwesome component on the actual Vue app instance
58
- nuxtApp.vueApp.component('font-awesome-icon', FontAwesomeIcon);
22
+ dark: {
23
+ dark: true,
24
+ colors: {
25
+ primary: '#3b82f6',
26
+ secondary: '#64748b'
27
+ }
28
+ }
29
+ }
30
+ }
31
+ });
59
32
  nuxtApp.vueApp.use(vuetify);
60
- };
33
+ });
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <ais-instant-search :search-client="client" :index-name="index">
3
+ <ais-search-box />
4
+ <ais-hits>
5
+ <template #item="{ item }">
6
+ <slot name="hit" :item="item">
7
+ <div class="p-2 border rounded">
8
+ <ais-highlight attribute="title" :hit="item" />
9
+ </div>
10
+ </slot>
11
+ </template>
12
+ </ais-hits>
13
+ </ais-instant-search>
14
+ </template>
15
+
16
+ <script setup>
17
+ const client = inject("mSearchClient");
18
+ const index = inject("mSearchIndex");
19
+ </script>
@@ -0,0 +1,5 @@
1
+ @import './tailwind.css';
2
+ :root {
3
+ --m-primary: #3b82f6;
4
+ --m-secondary: #64748b;
5
+ }
@@ -0,0 +1 @@
1
+ @tailwind base;@tailwind components;@tailwind utilities;
@@ -0,0 +1,3 @@
1
+ body {
2
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
3
+ }
@@ -0,0 +1,9 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.mjs'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.mjs'
8
+
9
+ export { type MFrameworkUiOptions } from './module.mjs'
@@ -0,0 +1,2 @@
1
+ declare function getContrastColor(hexColor: string): "#ffffff" | "#000000";
2
+ export { getContrastColor };
@@ -0,0 +1,11 @@
1
+ function getContrastColor(hexColor) {
2
+ // Convert hex color to RGB format
3
+ const red = parseInt(hexColor.slice(1, 3), 16);
4
+ const green = parseInt(hexColor.slice(3, 5), 16);
5
+ const blue = parseInt(hexColor.slice(5, 7), 16);
6
+ // Calculate relative luminance of the color
7
+ const luminance = (0.2126 * red + 0.7152 * green + 0.0722 * blue) / 255;
8
+ // Return black or white depending on the luminance value
9
+ return luminance > 0.5 ? '#000000' : '#ffffff';
10
+ }
11
+ export { getContrastColor };
@@ -0,0 +1,5 @@
1
+ type FontFamilies = {
2
+ [font: string]: boolean | number[];
3
+ };
4
+ export declare const formatFonts: (families: FontFamilies, defaultWeights?: number[]) => string[];
5
+ export {};
@@ -0,0 +1,18 @@
1
+ export const formatFonts = (families, defaultWeights = [400]) => {
2
+ const formatted = [];
3
+ for (const font in families) {
4
+ const formattedFont = font.replace(/ /g, '+'); // Replace spaces with '+'
5
+ const weights = families[font];
6
+ if (weights === true) {
7
+ for (const weight of defaultWeights) {
8
+ formatted.push(`${formattedFont}:${weight}`);
9
+ }
10
+ }
11
+ else if (Array.isArray(weights)) {
12
+ for (const weight of weights) {
13
+ formatted.push(`${formattedFont}:${weight}`);
14
+ }
15
+ }
16
+ }
17
+ return formatted;
18
+ };
@@ -0,0 +1,12 @@
1
+ export interface Condition {
2
+ field: string;
3
+ action: 'show' | 'hide';
4
+ condition: 'is_empty' | 'is_filled' | 'contains' | 'not_contains' | 'equals' | 'not_equal';
5
+ value: string;
6
+ }
7
+ export declare function mapConditions(conditions: Condition[]): void;
8
+ export declare function transformSchema(schema: Array<object>): {
9
+ $cmp: any;
10
+ children: any;
11
+ props: any;
12
+ }[];
@@ -0,0 +1,59 @@
1
+ import { unref } from 'vue';
2
+ function convertBoolean(value) {
3
+ if (value === 'true' || value === 'false') {
4
+ return value === 'true';
5
+ }
6
+ else {
7
+ return value;
8
+ }
9
+ }
10
+ function mapCondition(condition, target) {
11
+ switch (condition) {
12
+ case 'is_empty':
13
+ return `!$get(${target}).value)`;
14
+ case 'is_filled':
15
+ return `$get(${target}).value)`;
16
+ default:
17
+ return undefined;
18
+ }
19
+ }
20
+ export function mapConditions(conditions) {
21
+ // Both $el and $cmp schema nodes can leverage an if property that roughly equates to a v-if in Vue. If the expression assigned to the if property is truthy, the node is rendered, otherwise it is not:
22
+ }
23
+ export function transformSchema(schema) {
24
+ // Loop through the form schema from Directus
25
+ // This is required for FormKit to work
26
+ const items = unref(schema);
27
+ return items.map((item) => {
28
+ const { conditions, field, name, children, ...props } = item;
29
+ // console.log('conditions', conditions);
30
+ // console.log('mapCondition', mapCondition(conditions[0].condition, field));
31
+ const cmpSchema = {
32
+ $cmp: item.$el ? item.$el : 'FormKit',
33
+ children: children,
34
+ // if: conditions ? mapCondition(conditions[0].condition, field) : undefined,
35
+ props: {
36
+ id: name,
37
+ ...props,
38
+ },
39
+ };
40
+ // Switch statement to handle item widths
41
+ switch (item.width) {
42
+ case '33':
43
+ cmpSchema.props.outerClass = 'md:col-span-2';
44
+ break;
45
+ case '50':
46
+ cmpSchema.props.outerClass = 'md:col-span-3';
47
+ break;
48
+ case '67':
49
+ cmpSchema.props.outerClass = 'md:col-span-4';
50
+ break;
51
+ case '100':
52
+ cmpSchema.props.outerClass = 'md:col-span-6';
53
+ break;
54
+ default:
55
+ cmpSchema.props.outerClass = 'md:col-span-6';
56
+ }
57
+ return cmpSchema;
58
+ });
59
+ }
@@ -0,0 +1,4 @@
1
+ type FileType = 'folder' | 'image/jpeg' | 'image/png' | 'image/gif' | 'image/svg+xml' | 'image/webp' | 'video/mp4' | 'video/quicktime' | 'audio/mp3' | 'audio/aac' | 'audio/wav' | 'audio/ogg' | 'text/csv' | 'text/plain' | 'application/pdf' | 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/msword' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.ms-powerpoint' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
2
+ export declare const fileIconMap: Record<FileType, string>;
3
+ export declare function getFileIcon(filetype: FileType | string | null | undefined): string;
4
+ export {};
@@ -0,0 +1,36 @@
1
+ export const fileIconMap = {
2
+ folder: 'material-symbols:folder',
3
+ // Images
4
+ 'image/jpeg': 'material-symbols:image',
5
+ 'image/png': 'material-symbols:image',
6
+ 'image/gif': 'material-symbols:image',
7
+ 'image/svg+xml': 'material-symbols:image',
8
+ 'image/webp': 'material-symbols:image',
9
+ // Videos
10
+ 'video/mp4': 'material-symbols:smart-display',
11
+ 'video/quicktime': 'material-symbols:smart-display',
12
+ // Audio
13
+ 'audio/mp3': 'material-symbols:audio-file',
14
+ 'audio/aac': 'material-symbols:audio-file',
15
+ 'audio/wav': 'material-symbols:audio-file',
16
+ 'audio/ogg': 'material-symbols:audio-file',
17
+ // Text
18
+ 'text/csv': 'material-symbols:csv',
19
+ 'text/plain': 'material-symbols:text-snippet',
20
+ // Files
21
+ 'application/pdf': 'material-symbols:picture-as-pdf-sharp',
22
+ 'application/vnd.ms-excel': 'material-symbols:sheets',
23
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'material-symbols:sheets',
24
+ 'application/msword': 'material-symbols:docs',
25
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'material-symbols:docs',
26
+ 'application/vnd.ms-powerpoint': 'material-symbols:slides',
27
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'material-symbols:slides',
28
+ };
29
+ export function getFileIcon(filetype) {
30
+ if (!filetype)
31
+ return 'material-symbols:attachment';
32
+ if (typeof filetype === 'string' && !(filetype in fileIconMap)) {
33
+ return 'material-symbols:attachment';
34
+ }
35
+ return fileIconMap[filetype];
36
+ }
package/package.json CHANGED
@@ -1,14 +1,8 @@
1
1
  {
2
2
  "name": "@mframework/ui",
3
- "version": "0.1.0-beta.0",
3
+ "version": "0.1.0-beta.2",
4
4
  "type": "module",
5
5
  "description": "Opiniated UI module for the M Framework.",
6
- "main": "dist/module.cjs",
7
- "module": "dist/module.mjs",
8
- "types": "dist/module.d.ts",
9
- "files": [
10
- "dist"
11
- ],
12
6
  "keywords": [
13
7
  "vue",
14
8
  "nuxt",
@@ -17,8 +11,14 @@
17
11
  "mframework",
18
12
  "meeovi"
19
13
  ],
14
+ "main": "dist/module.js",
15
+ "module": "dist/module.mjs",
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
20
  "scripts": {
21
- "build": "nuxt-module-build",
21
+ "build": "tsc -p tsconfig.json",
22
22
  "dev": "nuxt-module-dev"
23
23
  },
24
24
  "peerDependencies": {
@@ -31,22 +31,24 @@
31
31
  "@fortawesome/fontawesome-svg-core": "^7.1.0",
32
32
  "@fortawesome/free-solid-svg-icons": "^7.1.0",
33
33
  "@fortawesome/vue-fontawesome": "^3.1.2",
34
- "@grapesjs/studio-sdk": "^1.0.57",
35
34
  "@mdi/font": "^7.4.47",
36
35
  "@nuxt/image": "^2.0.0",
37
36
  "@vueuse/motion": "^3.0.3",
37
+ "grapesjs": "^0.22.14",
38
38
  "izitoast": "^1.4.0",
39
39
  "lg-thumbnail": "^1.2.1",
40
40
  "lg-video": "^1.4.0",
41
41
  "lg-zoom": "^1.3.0",
42
42
  "lightgallery": "^2.9.0",
43
43
  "tailwindcss": "^4.1.18",
44
+ "vue-tsc": "^3.2.4",
44
45
  "vuetify": "^3.7.0",
45
46
  "vuetify-nuxt-module": "^0.18.8"
46
47
  },
47
48
  "devDependencies": {
49
+ "@nuxt/module-builder": "^1.0.2",
48
50
  "sass": "^1.94.2",
49
51
  "sass-embedded": "^1.93.3",
50
52
  "typescript": "^5.7.0"
51
53
  }
52
- }
54
+ }
package/src/module.ts ADDED
@@ -0,0 +1,105 @@
1
+ import {
2
+ defineNuxtModule,
3
+ addPlugin,
4
+ createResolver,
5
+ addComponentsDir,
6
+ addImportsDir
7
+ } from 'nuxt/kit'
8
+
9
+ export interface MFrameworkUiOptions {
10
+ theme ? : 'light' | 'dark'
11
+ builder ? : boolean | {
12
+ enabled ? : boolean
13
+ }
14
+ }
15
+
16
+ export default defineNuxtModule < MFrameworkUiOptions > ({
17
+ meta: {
18
+ name: '@mframework/ui',
19
+ configKey: 'mframeworkUi'
20
+ },
21
+
22
+ defaults: {
23
+ theme: 'light',
24
+ builder: true
25
+ },
26
+
27
+ setup(options, nuxt) {
28
+ const resolver = createResolver(import.meta.url)
29
+
30
+ //
31
+ // 1. Ensure Vuetify loads FIRST
32
+ //
33
+ addPlugin({
34
+ src: resolver.resolve('./runtime/plugins/vuetify'),
35
+ mode: 'all'
36
+ })
37
+
38
+ //
39
+ // 2. Global styles (Tailwind, Vuetify overrides, tokens)
40
+ //
41
+ nuxt.options.css = nuxt.options.css || []
42
+ nuxt.options.css.push(resolver.resolve('./runtime/styles/index.scss'))
43
+
44
+ //
45
+ // 3. Register core UI plugins
46
+ //
47
+ const plugins = [
48
+ 'formkit',
49
+ 'fontawesome',
50
+ 'lightgallery',
51
+ 'motion',
52
+ 'theme'
53
+ ]
54
+
55
+ plugins.forEach((name) => {
56
+ addPlugin({
57
+ src: resolver.resolve(`./runtime/plugins/${name}`),
58
+ mode: 'all'
59
+ })
60
+ })
61
+
62
+ //
63
+ // 4. Register GrapesJS builder (client‑only)
64
+ //
65
+ if (options.builder) {
66
+ addPlugin({
67
+ src: resolver.resolve('./runtime/plugins/builder'),
68
+ mode: 'client'
69
+ })
70
+ }
71
+
72
+ //
73
+ // 5. Auto‑import components & composables
74
+ //
75
+ addComponentsDir({
76
+ path: resolver.resolve('./runtime/components'),
77
+ prefix: 'M'
78
+ })
79
+
80
+ addImportsDir(resolver.resolve('./runtime/composables'))
81
+
82
+ //
83
+ // 6. Expose runtime config
84
+ //
85
+ // Normalize builder option
86
+ const normalizedBuilder =
87
+ typeof options.builder === 'boolean' ? {
88
+ enabled: options.builder
89
+ } :
90
+ options.builder || {
91
+ enabled: true
92
+ }
93
+
94
+ nuxt.options.runtimeConfig.public.mframeworkUi = {
95
+ theme: options.theme,
96
+ builder: normalizedBuilder
97
+ }
98
+
99
+ // Safe assignment without TS errors
100
+ ;(nuxt.options as any).tailwindcss = (nuxt.options as any).tailwindcss || {}
101
+ ;(nuxt.options as any).tailwindcss.configPath = resolver.resolve(
102
+ './runtime/assets/config/tailwind.config.js'
103
+ )
104
+ }
105
+ })
@@ -0,0 +1,42 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: [], // Nuxt will inject its own paths
4
+
5
+ theme: {
6
+ extend: {
7
+ colors: {
8
+ primary: 'var(--m-primary)',
9
+ secondary: 'var(--m-secondary)',
10
+ accent: 'var(--m-accent)',
11
+ muted: 'var(--m-muted)',
12
+ surface: 'var(--m-surface)',
13
+ border: 'var(--m-border)'
14
+ },
15
+
16
+ fontFamily: {
17
+ sans: ['Inter', 'system-ui', 'sans-serif'],
18
+ heading: ['Inter', 'system-ui', 'sans-serif']
19
+ },
20
+
21
+ borderRadius: {
22
+ sm: '4px',
23
+ DEFAULT: '8px',
24
+ lg: '12px',
25
+ xl: '16px'
26
+ },
27
+
28
+ spacing: {
29
+ '1/2': '50%',
30
+ 'full': '100%'
31
+ },
32
+
33
+ boxShadow: {
34
+ soft: '0 2px 8px rgba(0,0,0,0.06)',
35
+ medium: '0 4px 16px rgba(0,0,0,0.08)',
36
+ strong: '0 8px 24px rgba(0,0,0,0.12)'
37
+ }
38
+ }
39
+ },
40
+
41
+ plugins: []
42
+ }
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <lightgallery :settings="{ speed: 500, plugins: plugins }" :onInit="onInit" :onBeforeSlide="onBeforeSlide">
3
+ <a data-lg-size="1406-1390" class="gallery-item"
4
+ data-src="https://images.unsplash.com/photo-1581894158358-5ecd2c518883?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1406&q=80"
5
+ data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@entrycube' >Diego Guzmán </a></h4> <p> Location - <a href='https://unsplash.com/s/photos/fushimi-inari-taisha-shrine-senbontorii%2C-68%E7%95%AA%E5%9C%B0-fukakusa-yabunouchicho%2C-fushimi-ward%2C-kyoto%2C-japan'>Fushimi Ward, Kyoto, Japan</a></p>">
6
+ <img class="img-responsive"
7
+ src="https://images.unsplash.com/photo-1581894158358-5ecd2c518883?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=240&q=80" />
8
+ </a>
9
+ <a data-lg-size="1400-1400" class="gallery-item"
10
+ data-src="https://images.unsplash.com/photo-1544550285-f813152fb2fd?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80"
11
+ data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@asoshiation' >Shah </a></h4><p> Location - <a href='https://unsplash.com/s/photos/shinimamiya%2C-osaka%2C-japan'>Shinimamiya, Osaka, Japan</a></p>">
12
+ <img class="img-responsive"
13
+ src="https://images.unsplash.com/photo-1544550285-f813152fb2fd?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=240&q=80" />
14
+ </a>
15
+ <a data-lg-size="1400-1400" class="gallery-item"
16
+ data-src="https://images.unsplash.com/photo-1584592740039-cddf0671f3d4?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80"
17
+ data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@katherine_xx11' >Katherine Gu </a></h4><p> For all those years we were alone and helpless.</p>">
18
+ <img style="width: 200px" class="img-responsive"
19
+ src="https://images.unsplash.com/photo-1584592740039-cddf0671f3d4?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=240&q=80" />
20
+ </a>
21
+ <a class="gallery-item"
22
+ data-video='{"source": [{"src":"https://www.lightgalleryjs.com/videos/video1.mp4", "type":"video/mp4"}], "attributes": {"preload": false, "controls": true}}'
23
+ data-poster=""
24
+ data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@katherine_xx11' >Katherine Gu </a></h4><p> For all those years we were alone and helpless.</p>">
25
+ <img width="200" class="img-responsive"
26
+ src="https://www.lightgalleryjs.com/images/demo/html5-video-poster.jpg" />
27
+ </a>
28
+ </lightgallery>
29
+ </template>
30
+
31
+ <script>
32
+ import Lightgallery from 'lightgallery/vue';
33
+ import lgZoom from 'lightgallery/plugins/zoom';
34
+ import lgVideo from 'lightgallery/plugins/video';
35
+
36
+ export default {
37
+ name: 'App',
38
+ components: {
39
+ Lightgallery,
40
+ },
41
+ data: () => ({
42
+ plugins: [lgZoom, lgVideo],
43
+ }),
44
+ methods: {
45
+ onInit: () => {
46
+ console.log('lightGallery has been initialized');
47
+ },
48
+ onBeforeSlide: () => {
49
+ console.log('calling before slide');
50
+ },
51
+ },
52
+ };
53
+ </script>
54
+ <style lang="css">
55
+ @import url('https://cdn.jsdelivr.net/npm/lightgallery@2.0.0-beta.4/css/lightgallery.css');
56
+ @import url('https://cdn.jsdelivr.net/npm/lightgallery@2.0.0-beta.4/css/lg-zoom.css');
57
+ @import url('https://cdn.jsdelivr.net/npm/lightgallery@2.0.0-beta.4/css/lg-video.css');
58
+
59
+ body {
60
+ margin: 0;
61
+ }
62
+
63
+ .gallery-item {
64
+ margin: 5px;
65
+ }
66
+ </style>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <v-btn :color="color" class="m-btn" v-bind="$attrs">
3
+ <slot />
4
+ </v-btn>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ defineProps < {
9
+ color ? : string
10
+ } > ()
11
+ </script>
12
+
13
+ <style scoped>
14
+ .m-btn {
15
+ @apply px-4 py-2 rounded-md;
16
+ }
17
+ </style>
@@ -0,0 +1,14 @@
1
+ import iziToast from 'izitoast'
2
+ import 'izitoast/dist/css/iziToast.min.css'
3
+
4
+ export const useMToast = () => {
5
+ const success = (message: string, title = 'Success') => {
6
+ iziToast.success({ title, message })
7
+ }
8
+
9
+ const error = (message: string, title = 'Error') => {
10
+ iziToast.error({ title, message })
11
+ }
12
+
13
+ return { success, error }
14
+ }
@@ -0,0 +1,22 @@
1
+ export const tokens = {
2
+ colors: {
3
+ primary: '#4f46e5',
4
+ secondary: '#64748b',
5
+ success: '#22c55e',
6
+ warning: '#f59e0b',
7
+ error: '#ef4444',
8
+ surface: '#ffffff',
9
+ background: '#f8fafc'
10
+ },
11
+ radius: {
12
+ sm: '4px',
13
+ md: '8px',
14
+ lg: '12px'
15
+ },
16
+ spacing: {
17
+ xs: '4px',
18
+ sm: '8px',
19
+ md: '16px',
20
+ lg: '24px'
21
+ }
22
+ }