@mframework/ui 0.1.0-beta.2 → 0.1.0-beta.3
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/package.json +2 -3
- package/src/module.ts +0 -105
- package/src/runtime/assets/config/tailwind.conifg.js +0 -42
- package/src/runtime/components/Gallery.vue +0 -66
- package/src/runtime/components/MButton.vue +0 -17
- package/src/runtime/composables/useMToast.ts +0 -14
- package/src/runtime/design/tokens.ts +0 -22
- package/src/runtime/plugins/builder.ts +0 -326
- package/src/runtime/plugins/fontawesome.ts +0 -11
- package/src/runtime/plugins/formkit.ts +0 -9
- package/src/runtime/plugins/lightgallery.js +0 -21
- package/src/runtime/plugins/motion.ts +0 -6
- package/src/runtime/plugins/theme-switcher.ts +0 -32
- package/src/runtime/plugins/theme.ts +0 -57
- package/src/runtime/plugins/vuetify.ts +0 -36
- package/src/runtime/search/client.ts +0 -25
- package/src/runtime/search/components/MSearch.vue +0 -19
- package/src/runtime/search/plugin.ts +0 -9
- package/src/runtime/styles/index.scss +0 -101
- package/src/runtime/styles/tailwind.css +0 -9
- package/src/runtime/styles/vuetify.scss +0 -5
- package/src/types/runtime-config.d.ts +0 -12
- package/src/utils/color.js +0 -11
- package/src/utils/color.ts +0 -14
- package/src/utils/fonts.js +0 -18
- package/src/utils/fonts.ts +0 -24
- package/src/utils/formkit.js +0 -59
- package/src/utils/formkit.ts +0 -75
- package/src/utils/icons.js +0 -36
- package/src/utils/icons.ts +0 -62
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mframework/ui",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Opiniated UI module for the M Framework.",
|
|
6
6
|
"keywords": [
|
|
@@ -14,8 +14,7 @@
|
|
|
14
14
|
"main": "dist/module.js",
|
|
15
15
|
"module": "dist/module.mjs",
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
18
|
-
"src"
|
|
17
|
+
"dist"
|
|
19
18
|
],
|
|
20
19
|
"scripts": {
|
|
21
20
|
"build": "tsc -p tsconfig.json",
|
package/src/module.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
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
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
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>
|
|
@@ -1,17 +0,0 @@
|
|
|
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>
|
|
@@ -1,14 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineNuxtPlugin
|
|
3
|
-
} from 'nuxt/app'
|
|
4
|
-
import 'grapesjs/dist/css/grapes.min.css'
|
|
5
|
-
import grapesjs from 'grapesjs'
|
|
6
|
-
|
|
7
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
8
|
-
if (process.server) return
|
|
9
|
-
|
|
10
|
-
const mount = () => {
|
|
11
|
-
const el = document.querySelector('#gjs')
|
|
12
|
-
if (!el) return null
|
|
13
|
-
|
|
14
|
-
const editor = grapesjs.init({
|
|
15
|
-
container: `${el}`,
|
|
16
|
-
fromElement: true,
|
|
17
|
-
height: '100%',
|
|
18
|
-
width: 'auto',
|
|
19
|
-
storageManager: {
|
|
20
|
-
type: 'local',
|
|
21
|
-
autosave: true,
|
|
22
|
-
autoload: true,
|
|
23
|
-
stepsBeforeSave: 1,
|
|
24
|
-
options: {
|
|
25
|
-
local: {
|
|
26
|
-
key: 'gjsProject'
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
// Avoid any default panel
|
|
32
|
-
layerManager: {
|
|
33
|
-
appendTo: '.layers-container',
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
mediaCondition: 'min-width', // default is `max-width`
|
|
37
|
-
deviceManager: {
|
|
38
|
-
devices: [{
|
|
39
|
-
name: 'Desktop',
|
|
40
|
-
width: '', // default size
|
|
41
|
-
widthMedia: '1024px', // this value will be used in CSS @media
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: 'Mobile',
|
|
45
|
-
width: '320px', // this value will be used on canvas width
|
|
46
|
-
widthMedia: '480px', // this value will be used in CSS @media
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
blockManager: {
|
|
52
|
-
appendTo: '#blocks',
|
|
53
|
-
blocks: [{
|
|
54
|
-
id: 'section', // id is mandatory
|
|
55
|
-
label: '<b>Section</b>', // You can use HTML/SVG inside labels
|
|
56
|
-
category: 'Basic',
|
|
57
|
-
attributes: {
|
|
58
|
-
class: 'gjs-block-section'
|
|
59
|
-
},
|
|
60
|
-
content: {
|
|
61
|
-
tagName: 'div',
|
|
62
|
-
draggable: false,
|
|
63
|
-
attributes: {
|
|
64
|
-
'some-attribute': 'some-value'
|
|
65
|
-
},
|
|
66
|
-
components: [{
|
|
67
|
-
tagName: 'span',
|
|
68
|
-
content: '<b>Some static content</b>',
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
tagName: 'div',
|
|
72
|
-
// use `content` for static strings, `components` string will be parsed
|
|
73
|
-
// and transformed in Components
|
|
74
|
-
components: '<span>HTML at some point</span>',
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
id: 'text',
|
|
81
|
-
label: 'Text',
|
|
82
|
-
content: '<div data-gjs-type="text">Insert your text here</div>',
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
id: 'image',
|
|
86
|
-
label: 'Image',
|
|
87
|
-
// Select the component once it's dropped
|
|
88
|
-
select: true,
|
|
89
|
-
// You can pass components as a JSON instead of a simple HTML string,
|
|
90
|
-
// in this case we also use a defined component type `image`
|
|
91
|
-
content: {
|
|
92
|
-
type: 'image'
|
|
93
|
-
},
|
|
94
|
-
// This triggers `active` event on dropped components and the `image`
|
|
95
|
-
// reacts by opening the AssetManager
|
|
96
|
-
activate: true,
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
},
|
|
100
|
-
panels: {
|
|
101
|
-
defaults: [{
|
|
102
|
-
id: 'layers',
|
|
103
|
-
el: '.panel__right',
|
|
104
|
-
// Make the panel resizable
|
|
105
|
-
resizable: {
|
|
106
|
-
maxDim: 350,
|
|
107
|
-
minDim: 200,
|
|
108
|
-
tc: false, // Top handler
|
|
109
|
-
cl: true, // Left handler
|
|
110
|
-
cr: false, // Right handler
|
|
111
|
-
bc: false, // Bottom handler
|
|
112
|
-
// Being a flex child we need to change `flex-basis` property
|
|
113
|
-
// instead of the `width` (default)
|
|
114
|
-
keyWidth: 'flex-basis',
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
id: 'panel-switcher',
|
|
119
|
-
el: '.panel__switcher',
|
|
120
|
-
buttons: [{
|
|
121
|
-
id: 'show-layers',
|
|
122
|
-
active: true,
|
|
123
|
-
label: 'Layers',
|
|
124
|
-
command: 'show-layers',
|
|
125
|
-
// Once activated disable the possibility to turn it off
|
|
126
|
-
togglable: false,
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
id: 'show-style',
|
|
130
|
-
active: true,
|
|
131
|
-
label: 'Styles',
|
|
132
|
-
command: 'show-styles',
|
|
133
|
-
togglable: false,
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
id: 'show-traits',
|
|
137
|
-
active: true,
|
|
138
|
-
label: 'Traits',
|
|
139
|
-
command: 'show-traits',
|
|
140
|
-
togglable: false,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 'panel-devices',
|
|
146
|
-
el: '.panel__devices',
|
|
147
|
-
buttons: [{
|
|
148
|
-
id: 'device-desktop',
|
|
149
|
-
label: 'D',
|
|
150
|
-
command: 'set-device-desktop',
|
|
151
|
-
active: true,
|
|
152
|
-
togglable: false,
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
id: 'device-mobile',
|
|
156
|
-
label: 'M',
|
|
157
|
-
command: 'set-device-mobile',
|
|
158
|
-
togglable: false,
|
|
159
|
-
},
|
|
160
|
-
],
|
|
161
|
-
},
|
|
162
|
-
],
|
|
163
|
-
},
|
|
164
|
-
// The Selector Manager allows to assign classes and
|
|
165
|
-
// different states (eg. :hover) on components.
|
|
166
|
-
// Generally, it's used in conjunction with Style Manager
|
|
167
|
-
// but it's not mandatory
|
|
168
|
-
selectorManager: {
|
|
169
|
-
appendTo: '.styles-container',
|
|
170
|
-
},
|
|
171
|
-
styleManager: {
|
|
172
|
-
appendTo: '.styles-container',
|
|
173
|
-
sectors: [{
|
|
174
|
-
name: 'Dimension',
|
|
175
|
-
open: false,
|
|
176
|
-
// Use built-in properties
|
|
177
|
-
buildProps: ['width', 'min-height', 'padding'],
|
|
178
|
-
// Use `properties` to define/override single property
|
|
179
|
-
properties: [{
|
|
180
|
-
// Type of the input,
|
|
181
|
-
// options: integer | radio | select | color | slider | file | composite | stack
|
|
182
|
-
type: 'integer',
|
|
183
|
-
name: 'The width', // Label for the property
|
|
184
|
-
property: 'width', // CSS property (if buildProps contains it will be extended)
|
|
185
|
-
units: ['px', '%'], // Units, available only for 'integer' types
|
|
186
|
-
defaults: 'auto', // Default value
|
|
187
|
-
min: 0, // Min value, available only for 'integer' types
|
|
188
|
-
}, ],
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
name: 'Extra',
|
|
192
|
-
open: false,
|
|
193
|
-
buildProps: ['background-color', 'box-shadow', 'custom-prop'],
|
|
194
|
-
properties: [{
|
|
195
|
-
id: 'custom-prop',
|
|
196
|
-
name: 'Custom Label',
|
|
197
|
-
property: 'font-size',
|
|
198
|
-
type: 'select',
|
|
199
|
-
defaults: '32px',
|
|
200
|
-
// List of options, available only for 'select' and 'radio' types
|
|
201
|
-
options: [{
|
|
202
|
-
id: 'tiny',
|
|
203
|
-
value: '12px',
|
|
204
|
-
name: 'Tiny'
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
id: 'medium',
|
|
208
|
-
value: '18px',
|
|
209
|
-
name: 'Medium'
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
id: 'big',
|
|
213
|
-
value: '32px',
|
|
214
|
-
name: 'Big'
|
|
215
|
-
},
|
|
216
|
-
],
|
|
217
|
-
}, ],
|
|
218
|
-
},
|
|
219
|
-
],
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Define commands
|
|
224
|
-
editor.Commands.add('show-layers', {
|
|
225
|
-
getRowEl(editor: any) {
|
|
226
|
-
return editor.getContainer().closest('.editor-row');
|
|
227
|
-
},
|
|
228
|
-
getLayersEl(row: any) {
|
|
229
|
-
return row.querySelector('.layers-container');
|
|
230
|
-
},
|
|
231
|
-
|
|
232
|
-
run(editor: any, sender: any) {
|
|
233
|
-
const lmEl = this.getLayersEl(this.getRowEl(editor));
|
|
234
|
-
lmEl.style.display = '';
|
|
235
|
-
},
|
|
236
|
-
stop(editor: any, sender: any) {
|
|
237
|
-
const lmEl = this.getLayersEl(this.getRowEl(editor));
|
|
238
|
-
lmEl.style.display = 'none';
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
editor.Commands.add('show-styles', {
|
|
242
|
-
getRowEl(editor: any) {
|
|
243
|
-
return editor.getContainer().closest('.editor-row');
|
|
244
|
-
},
|
|
245
|
-
getStyleEl(row: any) {
|
|
246
|
-
return row.querySelector('.styles-container');
|
|
247
|
-
},
|
|
248
|
-
|
|
249
|
-
run(editor: any, sender: any) {
|
|
250
|
-
const smEl = this.getStyleEl(this.getRowEl(editor));
|
|
251
|
-
smEl.style.display = '';
|
|
252
|
-
},
|
|
253
|
-
stop(editor: any, sender: any) {
|
|
254
|
-
const smEl = this.getStyleEl(this.getRowEl(editor));
|
|
255
|
-
smEl.style.display = 'none';
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
editor.Commands.add('show-traits', {
|
|
260
|
-
getTraitsEl(editor: any) {
|
|
261
|
-
const row = editor.getContainer().closest('.editor-row');
|
|
262
|
-
return row.querySelector('.traits-container');
|
|
263
|
-
},
|
|
264
|
-
run(editor: any, sender: any) {
|
|
265
|
-
this.getTraitsEl(editor).style.display = '';
|
|
266
|
-
},
|
|
267
|
-
stop(editor: any, sender: any) {
|
|
268
|
-
this.getTraitsEl(editor).style.display = 'none';
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
editor.Panels.addPanel({
|
|
273
|
-
id: 'panel-top',
|
|
274
|
-
el: '.panel__top',
|
|
275
|
-
});
|
|
276
|
-
editor.Panels.addPanel({
|
|
277
|
-
id: 'basic-actions',
|
|
278
|
-
el: '.panel__basic-actions',
|
|
279
|
-
buttons: [{
|
|
280
|
-
id: 'visibility',
|
|
281
|
-
active: true, // active by default
|
|
282
|
-
className: 'btn-toggle-borders',
|
|
283
|
-
label: '<u>B</u>',
|
|
284
|
-
command: 'sw-visibility', // Built-in command
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
id: 'export',
|
|
288
|
-
className: 'btn-open-export',
|
|
289
|
-
label: 'Exp',
|
|
290
|
-
command: 'export-template',
|
|
291
|
-
context: 'export-template', // For grouping context of buttons from the same panel
|
|
292
|
-
},
|
|
293
|
-
{
|
|
294
|
-
id: 'show-json',
|
|
295
|
-
className: 'btn-show-json',
|
|
296
|
-
label: 'JSON',
|
|
297
|
-
context: 'show-json',
|
|
298
|
-
command(editor: any) {
|
|
299
|
-
editor.Modal.setTitle('Components JSON')
|
|
300
|
-
.setContent(
|
|
301
|
-
`<textarea style="width:100%; height: 250px;">
|
|
302
|
-
${JSON.stringify(editor.getComponents())}
|
|
303
|
-
</textarea>`,
|
|
304
|
-
)
|
|
305
|
-
.open();
|
|
306
|
-
},
|
|
307
|
-
},
|
|
308
|
-
],
|
|
309
|
-
});
|
|
310
|
-
editor.Commands.add('set-device-desktop', {
|
|
311
|
-
run: (editor) => editor.setDevice('Desktop'),
|
|
312
|
-
});
|
|
313
|
-
editor.Commands.add('set-device-mobile', {
|
|
314
|
-
run: (editor) => editor.setDevice('Mobile'),
|
|
315
|
-
});
|
|
316
|
-
editor.on('change:device', () => console.log('Current device: ', editor.getDevice()));
|
|
317
|
-
// Set initial device as Mobile
|
|
318
|
-
editor.setDevice('Mobile');
|
|
319
|
-
|
|
320
|
-
nuxtApp.provide('grapesStudio', editor)
|
|
321
|
-
return editor
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Auto‑mount when page loads
|
|
325
|
-
window.addEventListener('DOMContentLoaded', mount)
|
|
326
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
-
import { library } from '@fortawesome/fontawesome-svg-core'
|
|
3
|
-
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
|
4
|
-
import { fas } from '@fortawesome/free-solid-svg-icons'
|
|
5
|
-
import '@fortawesome/fontawesome-free/css/all.min.css'
|
|
6
|
-
|
|
7
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
8
|
-
library.add(fas)
|
|
9
|
-
|
|
10
|
-
nuxtApp.vueApp.component('Fa', FontAwesomeIcon)
|
|
11
|
-
})
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
-
import { plugin as formKitPlugin, defaultConfig } from '@formkit/vue'
|
|
3
|
-
import '@formkit/themes/genesis'
|
|
4
|
-
|
|
5
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
6
|
-
nuxtApp.vueApp.use(formKitPlugin, defaultConfig({
|
|
7
|
-
// You can inject your own inputs, locales, etc. here
|
|
8
|
-
}))
|
|
9
|
-
})
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
-
import lightGallery from 'lightgallery'
|
|
3
|
-
import lgZoom from 'lg-zoom'
|
|
4
|
-
import lgVideo from 'lg-video'
|
|
5
|
-
import lgThumbnail from 'lg-thumbnail'
|
|
6
|
-
import 'lightgallery/css/lightgallery.css'
|
|
7
|
-
import 'lightgallery/css/lg-zoom.css'
|
|
8
|
-
import 'lightgallery/css/lg-thumbnail.css'
|
|
9
|
-
import 'lightgallery/css/lg-video.css'
|
|
10
|
-
|
|
11
|
-
export default defineNuxtPlugin(() => {
|
|
12
|
-
// You can expose a composable or directive later if you want.
|
|
13
|
-
// For now, this ensures CSS + plugins are bundled.
|
|
14
|
-
// Example directive could be added here if needed.
|
|
15
|
-
document.querySelectorAll('.lightgallery').forEach((element) => {
|
|
16
|
-
lightGallery(element as HTMLElement, {
|
|
17
|
-
plugins: [lgZoom, lgVideo, lgThumbnail],
|
|
18
|
-
speed: 500,
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from 'nuxt/app'
|
|
2
|
-
import { useTheme } from 'vuetify'
|
|
3
|
-
|
|
4
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
5
|
-
if (process.server) return
|
|
6
|
-
|
|
7
|
-
const theme = useTheme()
|
|
8
|
-
|
|
9
|
-
const setTheme = (mode: 'light' | 'dark') => {
|
|
10
|
-
theme.global.name.value = mode
|
|
11
|
-
document.documentElement.classList.toggle('dark', mode === 'dark')
|
|
12
|
-
localStorage.setItem('mframework-theme', mode)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const toggleTheme = () => {
|
|
16
|
-
const current = theme.global.name.value === 'light' ? 'dark' : 'light'
|
|
17
|
-
setTheme(current)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Load saved theme
|
|
21
|
-
const saved = localStorage.getItem('mframework-theme')
|
|
22
|
-
if (saved === 'light' || saved === 'dark') {
|
|
23
|
-
setTheme(saved)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Expose composable
|
|
27
|
-
nuxtApp.provide('mTheme', {
|
|
28
|
-
setTheme,
|
|
29
|
-
toggleTheme,
|
|
30
|
-
current: () => theme.global.name.value
|
|
31
|
-
})
|
|
32
|
-
})
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineNuxtPlugin,
|
|
3
|
-
useRuntimeConfig
|
|
4
|
-
} from 'nuxt/app'
|
|
5
|
-
import {
|
|
6
|
-
useTheme
|
|
7
|
-
} from 'vuetify'
|
|
8
|
-
|
|
9
|
-
export default defineNuxtPlugin(() => {
|
|
10
|
-
if (process.server) return
|
|
11
|
-
|
|
12
|
-
const theme = useTheme()
|
|
13
|
-
const config = useRuntimeConfig()
|
|
14
|
-
|
|
15
|
-
const baseColors = {
|
|
16
|
-
primary: 'var(--m-primary)',
|
|
17
|
-
secondary: 'var(--m-secondary)',
|
|
18
|
-
accent: 'var(--m-accent)',
|
|
19
|
-
surface: 'var(--m-surface)',
|
|
20
|
-
background: 'var(--m-muted)',
|
|
21
|
-
border: 'var(--m-border)',
|
|
22
|
-
|
|
23
|
-
// Required Vuetify system colors
|
|
24
|
-
success: '#22c55e',
|
|
25
|
-
warning: '#f59e0b',
|
|
26
|
-
error: '#ef4444',
|
|
27
|
-
info: '#3b82f6',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// Vuetify internal required fields
|
|
31
|
-
'on-primary': '#ffffff',
|
|
32
|
-
'on-secondary': '#ffffff',
|
|
33
|
-
'on-surface': '#ffffff',
|
|
34
|
-
'on-background': '#ffffff',
|
|
35
|
-
'on-success': '#ffffff',
|
|
36
|
-
'on-warning': '#ffffff',
|
|
37
|
-
'on-error': '#ffffff',
|
|
38
|
-
'on-info': '#ffffff'
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const defaultTheme = config.public.mframeworkUi?.theme || 'light'
|
|
42
|
-
|
|
43
|
-
theme.global.name.value = defaultTheme
|
|
44
|
-
|
|
45
|
-
theme.themes.value = {
|
|
46
|
-
light: {
|
|
47
|
-
dark: false,
|
|
48
|
-
colors: baseColors,
|
|
49
|
-
variables: {}
|
|
50
|
-
},
|
|
51
|
-
dark: {
|
|
52
|
-
dark: true,
|
|
53
|
-
colors: baseColors,
|
|
54
|
-
variables: {}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
})
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app'
|
|
2
|
-
import { createVuetify } from 'vuetify'
|
|
3
|
-
import * as components from 'vuetify/components'
|
|
4
|
-
import * as directives from 'vuetify/directives'
|
|
5
|
-
import 'vuetify/styles'
|
|
6
|
-
|
|
7
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
8
|
-
const config = useRuntimeConfig()
|
|
9
|
-
const theme = config.public.mframeworkUi?.theme || 'light'
|
|
10
|
-
|
|
11
|
-
const vuetify = createVuetify({
|
|
12
|
-
components,
|
|
13
|
-
directives,
|
|
14
|
-
theme: {
|
|
15
|
-
defaultTheme: theme,
|
|
16
|
-
themes: {
|
|
17
|
-
light: {
|
|
18
|
-
dark: false,
|
|
19
|
-
colors: {
|
|
20
|
-
primary: '#3b82f6',
|
|
21
|
-
secondary: '#64748b'
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
dark: {
|
|
25
|
-
dark: true,
|
|
26
|
-
colors: {
|
|
27
|
-
primary: '#3b82f6',
|
|
28
|
-
secondary: '#64748b'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
nuxtApp.vueApp.use(vuetify)
|
|
36
|
-
})
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { SearchClient } from 'instantsearch.js'
|
|
2
|
-
|
|
3
|
-
export function getSearchClient(): SearchClient | null {
|
|
4
|
-
let mod: any
|
|
5
|
-
try {
|
|
6
|
-
mod = require('@searchkit/instantsearch-client')
|
|
7
|
-
} catch {
|
|
8
|
-
console.warn('[mframework-ui] Searchkit client missing')
|
|
9
|
-
return null
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const candidate =
|
|
13
|
-
mod?.default?.default ||
|
|
14
|
-
mod?.default?.createClient ||
|
|
15
|
-
mod?.default ||
|
|
16
|
-
mod?.createClient ||
|
|
17
|
-
mod
|
|
18
|
-
|
|
19
|
-
if (typeof candidate !== 'function') return null
|
|
20
|
-
|
|
21
|
-
const host = process.env.NUXT_PUBLIC_SEARCHKIT_HOST
|
|
22
|
-
if (!host) return null
|
|
23
|
-
|
|
24
|
-
return candidate({ host })
|
|
25
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
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 lang="ts">
|
|
17
|
-
const client = inject('mSearchClient')
|
|
18
|
-
const index = inject('mSearchIndex')
|
|
19
|
-
</script>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { getSearchClient } from './client'
|
|
2
|
-
|
|
3
|
-
export default (nuxtApp: any) => {
|
|
4
|
-
const client = getSearchClient()
|
|
5
|
-
const indexName = process.env.NUXT_PUBLIC_SEARCH_INDEX || 'default'
|
|
6
|
-
|
|
7
|
-
nuxtApp.provide('mSearchClient', client)
|
|
8
|
-
nuxtApp.provide('mSearchIndex', indexName)
|
|
9
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
@import './tailwind.css';
|
|
2
|
-
|
|
3
|
-
// Your design tokens, utilities, etc.
|
|
4
|
-
:root {
|
|
5
|
-
--m-primary: #3b82f6;
|
|
6
|
-
--m-secondary: #64748b;
|
|
7
|
-
--m-accent: #10b981;
|
|
8
|
-
--m-muted: #f3f4f6;
|
|
9
|
-
--m-surface: #ffffff;
|
|
10
|
-
--m-border: #e5e7eb;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.dark {
|
|
14
|
-
--m-primary: #60a5fa;
|
|
15
|
-
--m-secondary: #94a3b8;
|
|
16
|
-
--m-accent: #34d399;
|
|
17
|
-
--m-muted: #1f2937;
|
|
18
|
-
--m-surface: #111827;
|
|
19
|
-
--m-border: #374151;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// GrapesJS canvas and editor styling
|
|
23
|
-
/* Let's highlight canvas boundaries */
|
|
24
|
-
#gjs {
|
|
25
|
-
border: 3px solid #444;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* Theming */
|
|
29
|
-
|
|
30
|
-
/* Primary color for the background */
|
|
31
|
-
.gjs-one-bg {
|
|
32
|
-
background-color: #78366a;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* Secondary color for the text color */
|
|
36
|
-
.gjs-two-color {
|
|
37
|
-
color: rgba(255, 255, 255, 0.7);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* Tertiary color for the background */
|
|
41
|
-
.gjs-three-bg {
|
|
42
|
-
background-color: #ec5896;
|
|
43
|
-
color: white;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/* Quaternary color for the text color */
|
|
47
|
-
.gjs-four-color,
|
|
48
|
-
.gjs-four-color-h:hover {
|
|
49
|
-
color: #ec5896;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/* Reset some default styling */
|
|
53
|
-
.gjs-cv-canvas {
|
|
54
|
-
top: 0;
|
|
55
|
-
width: 100%;
|
|
56
|
-
height: 100%;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.gjs-block {
|
|
60
|
-
width: auto;
|
|
61
|
-
height: auto;
|
|
62
|
-
min-height: auto;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.panel__top {
|
|
66
|
-
padding: 0;
|
|
67
|
-
width: 100%;
|
|
68
|
-
display: flex;
|
|
69
|
-
position: initial;
|
|
70
|
-
justify-content: center;
|
|
71
|
-
justify-content: space-between;
|
|
72
|
-
}
|
|
73
|
-
.panel__basic-actions {
|
|
74
|
-
position: initial;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.editor-row {
|
|
78
|
-
display: flex;
|
|
79
|
-
justify-content: flex-start;
|
|
80
|
-
align-items: stretch;
|
|
81
|
-
flex-wrap: nowrap;
|
|
82
|
-
height: 300px;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.editor-canvas {
|
|
86
|
-
flex-grow: 1;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.panel__right {
|
|
90
|
-
flex-basis: 230px;
|
|
91
|
-
position: relative;
|
|
92
|
-
overflow-y: auto;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.panel__switcher {
|
|
96
|
-
position: initial;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.panel__devices {
|
|
100
|
-
position: initial;
|
|
101
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/* @mframework/ui/runtime/assets/css/tailwind.css */
|
|
2
|
-
|
|
3
|
-
/* Tailwind base (if using Tailwind 3 style) */
|
|
4
|
-
@import "tailwindcss/preflight";
|
|
5
|
-
|
|
6
|
-
/* Vuetify + Tailwind coexistence tips:
|
|
7
|
-
- Avoid global resets that fight Vuetify
|
|
8
|
-
- Prefer utility classes for layout, spacing, etc.
|
|
9
|
-
*/
|
package/src/utils/color.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
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 };
|
package/src/utils/color.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
function getContrastColor(hexColor: string) {
|
|
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
|
-
|
|
7
|
-
// Calculate relative luminance of the color
|
|
8
|
-
const luminance = (0.2126 * red + 0.7152 * green + 0.0722 * blue) / 255;
|
|
9
|
-
|
|
10
|
-
// Return black or white depending on the luminance value
|
|
11
|
-
return luminance > 0.5 ? '#000000' : '#ffffff';
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export { getContrastColor };
|
package/src/utils/fonts.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
};
|
package/src/utils/fonts.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
type FontFamilies = {
|
|
2
|
-
[font: string]: boolean | number[];
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
export const formatFonts = (families: FontFamilies, defaultWeights: number[] = [400]): string[] => {
|
|
6
|
-
const formatted: string[] = [];
|
|
7
|
-
|
|
8
|
-
for (const font in families) {
|
|
9
|
-
const formattedFont = font.replace(/ /g, '+'); // Replace spaces with '+'
|
|
10
|
-
const weights = families[font];
|
|
11
|
-
|
|
12
|
-
if (weights === true) {
|
|
13
|
-
for (const weight of defaultWeights) {
|
|
14
|
-
formatted.push(`${formattedFont}:${weight}`);
|
|
15
|
-
}
|
|
16
|
-
} else if (Array.isArray(weights)) {
|
|
17
|
-
for (const weight of weights) {
|
|
18
|
-
formatted.push(`${formattedFont}:${weight}`);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return formatted;
|
|
24
|
-
};
|
package/src/utils/formkit.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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
|
-
}
|
package/src/utils/formkit.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { unref } from 'vue';
|
|
2
|
-
|
|
3
|
-
export interface Condition {
|
|
4
|
-
field: string;
|
|
5
|
-
action: 'show' | 'hide';
|
|
6
|
-
condition: 'is_empty' | 'is_filled' | 'contains' | 'not_contains' | 'equals' | 'not_equal';
|
|
7
|
-
value: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function convertBoolean(value: string) {
|
|
11
|
-
if (value === 'true' || value === 'false') {
|
|
12
|
-
return value === 'true';
|
|
13
|
-
} else {
|
|
14
|
-
return value;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function mapCondition(condition: Condition['condition'], target: string) {
|
|
19
|
-
switch (condition) {
|
|
20
|
-
case 'is_empty':
|
|
21
|
-
return `!$get(${target}).value)`;
|
|
22
|
-
case 'is_filled':
|
|
23
|
-
return `$get(${target}).value)`;
|
|
24
|
-
default:
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function mapConditions(conditions: Condition[]) {
|
|
30
|
-
// 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:
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function transformSchema(schema: Array<object>) {
|
|
34
|
-
// Loop through the form schema from Directus
|
|
35
|
-
// This is required for FormKit to work
|
|
36
|
-
const items = unref(schema);
|
|
37
|
-
return items.map((item: any) => {
|
|
38
|
-
const { conditions, field, name, children, ...props } = item;
|
|
39
|
-
|
|
40
|
-
// console.log('conditions', conditions);
|
|
41
|
-
// console.log('mapCondition', mapCondition(conditions[0].condition, field));
|
|
42
|
-
|
|
43
|
-
const cmpSchema = {
|
|
44
|
-
$cmp: item.$el ? item.$el : 'FormKit',
|
|
45
|
-
|
|
46
|
-
children: children,
|
|
47
|
-
// if: conditions ? mapCondition(conditions[0].condition, field) : undefined,
|
|
48
|
-
|
|
49
|
-
props: {
|
|
50
|
-
id: name,
|
|
51
|
-
...props,
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Switch statement to handle item widths
|
|
56
|
-
switch (item.width) {
|
|
57
|
-
case '33':
|
|
58
|
-
cmpSchema.props.outerClass = 'md:col-span-2';
|
|
59
|
-
break;
|
|
60
|
-
case '50':
|
|
61
|
-
cmpSchema.props.outerClass = 'md:col-span-3';
|
|
62
|
-
break;
|
|
63
|
-
case '67':
|
|
64
|
-
cmpSchema.props.outerClass = 'md:col-span-4';
|
|
65
|
-
break;
|
|
66
|
-
case '100':
|
|
67
|
-
cmpSchema.props.outerClass = 'md:col-span-6';
|
|
68
|
-
break;
|
|
69
|
-
default:
|
|
70
|
-
cmpSchema.props.outerClass = 'md:col-span-6';
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return cmpSchema;
|
|
74
|
-
});
|
|
75
|
-
}
|
package/src/utils/icons.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
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/src/utils/icons.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
type FileType =
|
|
2
|
-
| 'folder'
|
|
3
|
-
| 'image/jpeg'
|
|
4
|
-
| 'image/png'
|
|
5
|
-
| 'image/gif'
|
|
6
|
-
| 'image/svg+xml'
|
|
7
|
-
| 'image/webp'
|
|
8
|
-
| 'video/mp4'
|
|
9
|
-
| 'video/quicktime'
|
|
10
|
-
| 'audio/mp3'
|
|
11
|
-
| 'audio/aac'
|
|
12
|
-
| 'audio/wav'
|
|
13
|
-
| 'audio/ogg'
|
|
14
|
-
| 'text/csv'
|
|
15
|
-
| 'text/plain'
|
|
16
|
-
| 'application/pdf'
|
|
17
|
-
| 'application/vnd.ms-excel'
|
|
18
|
-
| 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
19
|
-
| 'application/msword'
|
|
20
|
-
| 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
|
|
21
|
-
| 'application/vnd.ms-powerpoint'
|
|
22
|
-
| 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
|
|
23
|
-
|
|
24
|
-
export const fileIconMap: Record<FileType, string> = {
|
|
25
|
-
folder: 'material-symbols:folder',
|
|
26
|
-
// Images
|
|
27
|
-
'image/jpeg': 'material-symbols:image',
|
|
28
|
-
'image/png': 'material-symbols:image',
|
|
29
|
-
'image/gif': 'material-symbols:image',
|
|
30
|
-
'image/svg+xml': 'material-symbols:image',
|
|
31
|
-
'image/webp': 'material-symbols:image',
|
|
32
|
-
// Videos
|
|
33
|
-
'video/mp4': 'material-symbols:smart-display',
|
|
34
|
-
'video/quicktime': 'material-symbols:smart-display',
|
|
35
|
-
// Audio
|
|
36
|
-
'audio/mp3': 'material-symbols:audio-file',
|
|
37
|
-
'audio/aac': 'material-symbols:audio-file',
|
|
38
|
-
'audio/wav': 'material-symbols:audio-file',
|
|
39
|
-
'audio/ogg': 'material-symbols:audio-file',
|
|
40
|
-
// Text
|
|
41
|
-
'text/csv': 'material-symbols:csv',
|
|
42
|
-
'text/plain': 'material-symbols:text-snippet',
|
|
43
|
-
|
|
44
|
-
// Files
|
|
45
|
-
'application/pdf': 'material-symbols:picture-as-pdf-sharp',
|
|
46
|
-
'application/vnd.ms-excel': 'material-symbols:sheets',
|
|
47
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'material-symbols:sheets',
|
|
48
|
-
'application/msword': 'material-symbols:docs',
|
|
49
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'material-symbols:docs',
|
|
50
|
-
'application/vnd.ms-powerpoint': 'material-symbols:slides',
|
|
51
|
-
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'material-symbols:slides',
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export function getFileIcon(filetype: FileType | string | null | undefined) {
|
|
55
|
-
if (!filetype) return 'material-symbols:attachment';
|
|
56
|
-
|
|
57
|
-
if (typeof filetype === 'string' && !(filetype in fileIconMap)) {
|
|
58
|
-
return 'material-symbols:attachment';
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return fileIconMap[filetype as FileType];
|
|
62
|
-
}
|