mango-cms 0.2.14 → 0.2.15
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/cli.js
CHANGED
|
@@ -271,6 +271,37 @@ program
|
|
|
271
271
|
}
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
+
// --- Mango UI Dev Command ---
|
|
275
|
+
program
|
|
276
|
+
.command('ui <action>')
|
|
277
|
+
.description('Run Mango UI commands (e.g., dev, build, preview)')
|
|
278
|
+
.action(async (action) => {
|
|
279
|
+
const allowed = ['dev', 'build', 'preview'];
|
|
280
|
+
if (!allowed.includes(action)) {
|
|
281
|
+
console.error(`Unknown UI action: ${action}`);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
const uiDir = path.join(__dirname, 'ui');
|
|
285
|
+
const viteConfig = path.join(uiDir, 'vite.config.js');
|
|
286
|
+
// Pass through the Mango config context via cwd and env
|
|
287
|
+
try {
|
|
288
|
+
execSync(
|
|
289
|
+
`npx vite ${action} --config "${viteConfig}"`,
|
|
290
|
+
{
|
|
291
|
+
cwd: uiDir,
|
|
292
|
+
stdio: 'inherit',
|
|
293
|
+
env: {
|
|
294
|
+
...process.env,
|
|
295
|
+
// Optionally add more env vars here if needed
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
console.error(`Error running Mango UI (${action}):`, error.message);
|
|
301
|
+
process.exit(1);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
274
305
|
// Helper function for starting Mango CMS
|
|
275
306
|
async function startMangoCMS() {
|
|
276
307
|
try {
|
|
@@ -1,113 +1,108 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<slot :close="close"/>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
<!-- max-w-md max-w-lg max-w-xl max-w-sm -->
|
|
2
|
+
<div
|
|
3
|
+
ref="modal"
|
|
4
|
+
@click.prevent.stop="close"
|
|
5
|
+
tabindex="-1"
|
|
6
|
+
class="fixed w-full h-screen bg-gray-800/50 dark:bg-black/60 backdrop-blur-sm md:backdrop-blur-md opacity-0 transition-all duration-500 flex items-start sm:items-center justify-center z-[100] inset-0 !m-0 overscroll-none cursor-default"
|
|
7
|
+
:class="{ '!opacity-100': fadeIn }"
|
|
8
|
+
aria-modal="true"
|
|
9
|
+
v-show="active"
|
|
10
|
+
role="dialog"
|
|
11
|
+
>
|
|
12
|
+
<button @click.prevent.stop="close" class="absolute top-2 right-3"><i class="fa fa-times md:text-4xl" /></button>
|
|
13
|
+
<div
|
|
14
|
+
ref="modalContent"
|
|
15
|
+
@click.stop
|
|
16
|
+
class="shadow-card rounded w-full p-4 md:p-8 m-2 dark:bg-gray-800 bg-white relative border dark:border-gray-700 space-y-4 md:space-y-8 max-h-[75vh]"
|
|
17
|
+
:class="[dialogClasses, maxWidth, allowOverflow ? 'overflow-visible' : 'overflow-y-scroll']"
|
|
18
|
+
>
|
|
19
|
+
<slot :close="close" />
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<!-- max-w-md max-w-lg max-w-xl max-w-sm -->
|
|
27
23
|
</template>
|
|
28
24
|
|
|
29
25
|
<script>
|
|
30
26
|
export default {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
27
|
+
props: {
|
|
28
|
+
dialogClasses: { type: String, default: '' },
|
|
29
|
+
maxWidth: { default: 'max-w-md' },
|
|
30
|
+
active: { default: true },
|
|
31
|
+
allowOverflow: { type: Boolean, default: false },
|
|
32
|
+
},
|
|
33
|
+
data() {
|
|
34
|
+
return {
|
|
35
|
+
fadeIn: false,
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
watch: {
|
|
39
|
+
active: {
|
|
40
|
+
handler() {
|
|
41
|
+
if (this.active) this.freeze()
|
|
42
|
+
else this.thaw()
|
|
43
|
+
},
|
|
44
|
+
immediate: true,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
beforeDestroy() {
|
|
48
|
+
this.thaw()
|
|
49
|
+
},
|
|
50
|
+
unmounted() {
|
|
51
|
+
this.thaw()
|
|
52
|
+
},
|
|
53
|
+
methods: {
|
|
54
|
+
freeze() {
|
|
55
|
+
this.$nextTick(() => {
|
|
56
|
+
this.$refs.modalContent.focus()
|
|
57
|
+
this.fadeIn = true
|
|
58
|
+
document.body.style.overflow = 'hidden'
|
|
59
|
+
document.getElementById('app').setAttribute('aria-hidden', 'true')
|
|
60
|
+
this.$refs?.modal?.setAttribute('aria-modal', 'true')
|
|
61
|
+
this.attachListeners()
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
thaw() {
|
|
65
|
+
document.body.style.overflow = ''
|
|
66
|
+
document.getElementById('app').setAttribute('aria-hidden', 'false')
|
|
67
|
+
this.$refs?.modal?.removeAttribute('aria-modal')
|
|
68
|
+
this.removeListeners()
|
|
69
|
+
},
|
|
70
|
+
close() {
|
|
71
|
+
this.fadeIn = false
|
|
72
|
+
this.thaw()
|
|
73
|
+
setTimeout(() => {
|
|
74
|
+
this.$emit('hide')
|
|
75
|
+
}, 500)
|
|
76
|
+
},
|
|
77
|
+
attachListeners() {
|
|
78
|
+
window.addEventListener('keydown', this.handleKeydown)
|
|
79
|
+
},
|
|
80
|
+
removeListeners() {
|
|
81
|
+
window.removeEventListener('keydown', this.handleKeydown)
|
|
82
|
+
},
|
|
83
|
+
handleKeydown(e) {
|
|
84
|
+
if (e.key === 'Tab') {
|
|
85
|
+
this.manageFocus(e)
|
|
86
|
+
} else if (e.key === 'Escape') {
|
|
87
|
+
this.close()
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
manageFocus(e) {
|
|
91
|
+
let focusable = Array.from(this.$refs.modal.querySelectorAll('button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])'))
|
|
92
|
+
focusable = focusable.filter((el) => window.getComputedStyle(el).display !== 'none')
|
|
93
|
+
console.log('focusable', focusable)
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
95
|
+
if (!focusable.includes(document.activeElement)) {
|
|
96
|
+
e.preventDefault()
|
|
97
|
+
focusable[0].focus()
|
|
98
|
+
} else if (e.shiftKey && document.activeElement === focusable[0]) {
|
|
99
|
+
e.preventDefault()
|
|
100
|
+
focusable[focusable.length - 1].focus()
|
|
101
|
+
} else if (document.activeElement === focusable[focusable.length - 1]) {
|
|
102
|
+
e.preventDefault()
|
|
103
|
+
focusable[0].focus()
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
112
107
|
}
|
|
113
108
|
</script>
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
<div class="text-lg">Looks like the local Mango server isn't up and running yet. Please start it by running:</div>
|
|
41
41
|
<div class="w-full">
|
|
42
42
|
<div class="flex items-center space-x-2 relative">
|
|
43
|
-
<code class="bg-gray-200 dark:bg-black p-3 border border-gray-700 rounded-lg flex-grow dark:selection:bg-sky-700">
|
|
44
|
-
<button @click="copyToClipboard('
|
|
43
|
+
<code class="bg-gray-200 dark:bg-black p-3 border border-gray-700 rounded-lg flex-grow dark:selection:bg-sky-700">yarn mango dev</code>
|
|
44
|
+
<button @click="copyToClipboard('yarn mango dev')" class="p-2 rounded-lg bg-gray-200 dark:bg-black border border-gray-700 hover:bg-gray-300 dark:hover:bg-gray-800 transition-colors relative group">
|
|
45
45
|
<svg v-if="!copied" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
46
46
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
|
|
47
47
|
</svg>
|
|
@@ -60,15 +60,14 @@ let oldQuery = JSON.stringify(props.query || {})
|
|
|
60
60
|
let inferedId = computed(() => props.id !== undefined ? props.id : props.query?.id || route?.params?.id || null )
|
|
61
61
|
let searchingAlgolia = computed(() => !!props.algoliaSearch || !!props.algoliaFilters )
|
|
62
62
|
|
|
63
|
-
let
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
})
|
|
63
|
+
let timer;
|
|
64
|
+
let debounceInit = (...args) => {
|
|
65
|
+
console.log('debouncing')
|
|
66
|
+
if (active.value === false || props.disabled) return
|
|
67
|
+
loading.value = true
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
timer = setTimeout(() => { init.apply(this, args); }, props.debounce);
|
|
70
|
+
};
|
|
72
71
|
|
|
73
72
|
watch(() => props.query, (n, o) => {
|
|
74
73
|
let newQuery = JSON.stringify(n)
|
|
@@ -77,8 +76,8 @@ watch(() => props.query, (n, o) => {
|
|
|
77
76
|
|
|
78
77
|
watch(inferedId, (n, o) => defer(null, null, 'id'))
|
|
79
78
|
watch(() => props.collection, (n, o) => defer(null, null, 'collection'))
|
|
80
|
-
watch(() => props.algoliaSearch, (n, o) => searchingAlgolia.value ? debounceInit
|
|
81
|
-
watch(() => props.algoliaFilters, (n, o) => searchingAlgolia.value ? debounceInit
|
|
79
|
+
watch(() => props.algoliaSearch, (n, o) => searchingAlgolia.value ? debounceInit() : init())
|
|
80
|
+
watch(() => props.algoliaFilters, (n, o) => searchingAlgolia.value ? debounceInit() : init())
|
|
82
81
|
watch(loading, (n, o) => emit('update:loading', loading.value))
|
|
83
82
|
watch(data, () => {
|
|
84
83
|
if (data?.value?.length && props.query?.limit && data?.value?.length < props.query?.limit) noneRemain.value = true
|
|
@@ -90,7 +89,7 @@ function defer(n,o,origin) {
|
|
|
90
89
|
console.log('n,o,origin', n,o,origin)
|
|
91
90
|
if (n == o && origin == 'query') return console.log(`they're the same...`)
|
|
92
91
|
if (origin == 'query') oldQuery = n
|
|
93
|
-
nextTick(() => debounceInit
|
|
92
|
+
nextTick(() => debounceInit())
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
async function loadMore() {
|
package/default/vite.config.js
CHANGED