mirror of
https://github.com/Macrame-App/Macrame
synced 2025-12-29 07:19:26 +00:00
Base components added and updated.
This commit is contained in:
parent
b6f7694a0e
commit
f4a4bc5c4a
4 changed files with 293 additions and 4 deletions
|
|
@ -25,6 +25,7 @@ const classString = computed(() => {
|
||||||
'bg-sky-500/80 hover:bg-sky-400 text-white border-sky-400': props.variant === 'primary',
|
'bg-sky-500/80 hover:bg-sky-400 text-white border-sky-400': props.variant === 'primary',
|
||||||
'bg-white/80 hover:bg-white text-slate-900 border-white': props.variant === 'secondary',
|
'bg-white/80 hover:bg-white text-slate-900 border-white': props.variant === 'secondary',
|
||||||
'bg-red-700/80 hover:bg-red-700 text-white border-red-800': props.variant === 'danger',
|
'bg-red-700/80 hover:bg-red-700 text-white border-red-800': props.variant === 'danger',
|
||||||
|
'bg-slate-700/80 hover:bg-slate-700 text-white border-slate-600': props.variant === 'dark',
|
||||||
'bg-lime-500/80 hover:bg-lime-500 text-white border-lime-600': props.variant === 'success',
|
'bg-lime-500/80 hover:bg-lime-500 text-white border-lime-600': props.variant === 'success',
|
||||||
'button__subtle bg-transparent hover:bg-white/10 text-white border-transparent':
|
'button__subtle bg-transparent hover:bg-white/10 text-white border-transparent':
|
||||||
props.variant === 'subtle',
|
props.variant === 'subtle',
|
||||||
|
|
@ -38,10 +39,6 @@ const classString = computed(() => {
|
||||||
.filter((key) => classes[key])
|
.filter((key) => classes[key])
|
||||||
.join(' ')
|
.join(' ')
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
console.log(classString)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
||||||
76
fe/src/components/base/ContextMenu.vue
Normal file
76
fe/src/components/base/ContextMenu.vue
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
<template>
|
||||||
|
<div class="context-menu">
|
||||||
|
<div class="context-menu__trigger" @click="menuOpen = !menuOpen">
|
||||||
|
<slot name="trigger" />
|
||||||
|
</div>
|
||||||
|
<div :class="`context-menu__content ${menuOpen ? 'open' : ''}`">
|
||||||
|
<slot name="content" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
open: Boolean,
|
||||||
|
})
|
||||||
|
|
||||||
|
const menuOpen = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
menuOpen.value = props.open
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@reference "@/assets/main.css";
|
||||||
|
|
||||||
|
.context-menu {
|
||||||
|
@apply relative;
|
||||||
|
|
||||||
|
.context-menu__content {
|
||||||
|
@apply absolute
|
||||||
|
top-full
|
||||||
|
-translate-y-full
|
||||||
|
opacity-0
|
||||||
|
pointer-events-none
|
||||||
|
mt-2
|
||||||
|
min-w-full
|
||||||
|
grid
|
||||||
|
border
|
||||||
|
border-white/50
|
||||||
|
bg-slate-100/60
|
||||||
|
backdrop-blur-3xl
|
||||||
|
text-slate-800
|
||||||
|
rounded-md
|
||||||
|
z-50
|
||||||
|
transition-all;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
@apply translate-y-0
|
||||||
|
opacity-100
|
||||||
|
pointer-events-auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
@apply text-slate-800
|
||||||
|
divide-y
|
||||||
|
divide-slate-300;
|
||||||
|
|
||||||
|
li {
|
||||||
|
@apply flex
|
||||||
|
gap-2
|
||||||
|
items-center
|
||||||
|
p-2
|
||||||
|
hover:bg-black/10
|
||||||
|
cursor-pointer;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
@apply size-5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
107
fe/src/components/base/DialogComp.vue
Normal file
107
fe/src/components/base/DialogComp.vue
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
<template>
|
||||||
|
<div class="dialog-container">
|
||||||
|
<div class="trigger" @click="toggleDialog(true)">
|
||||||
|
<slot name="trigger" />
|
||||||
|
</div>
|
||||||
|
<dialog ref="dialog">
|
||||||
|
<ButtonComp
|
||||||
|
class="dialog__close p-0"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
tabindex="-1"
|
||||||
|
@click="toggleDialog(false)"
|
||||||
|
>
|
||||||
|
<IconX />
|
||||||
|
</ButtonComp>
|
||||||
|
<slot name="content" />
|
||||||
|
</dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ButtonComp from './ButtonComp.vue'
|
||||||
|
import { IconX } from '@tabler/icons-vue'
|
||||||
|
import { onMounted, onUpdated, ref } from 'vue'
|
||||||
|
|
||||||
|
const dialog = ref(null)
|
||||||
|
const openDialog = ref()
|
||||||
|
|
||||||
|
const emit = defineEmits(['onOpen', 'onClose', 'onToggle'])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
open: Boolean,
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.open === true) toggleDialog(props.open)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
if (props.open === true) toggleDialog(props.open)
|
||||||
|
})
|
||||||
|
|
||||||
|
const toggleDialog = (openToggle) => {
|
||||||
|
if (openToggle) {
|
||||||
|
dialog.value.showModal()
|
||||||
|
emit('onOpen')
|
||||||
|
} else {
|
||||||
|
dialog.value.close()
|
||||||
|
emit('onClose')
|
||||||
|
}
|
||||||
|
|
||||||
|
openDialog.value = openToggle
|
||||||
|
emit('onToggle')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
openDialog.value = props.open
|
||||||
|
|
||||||
|
if (dialog.value.innerHTML.includes('form')) {
|
||||||
|
dialog.value.querySelector('form').addEventListener('submit', () => {
|
||||||
|
toggleDialog()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@reference "@/assets/main.css";
|
||||||
|
|
||||||
|
.dialog-container {
|
||||||
|
@apply relative;
|
||||||
|
|
||||||
|
dialog {
|
||||||
|
@apply fixed
|
||||||
|
top-1/2 left-1/2
|
||||||
|
-translate-x-1/2 -translate-y-1/2
|
||||||
|
p-4
|
||||||
|
bg-slate-800
|
||||||
|
border
|
||||||
|
border-slate-600
|
||||||
|
rounded-lg
|
||||||
|
shadow-md
|
||||||
|
shadow-black
|
||||||
|
z-50
|
||||||
|
pointer-events-none;
|
||||||
|
|
||||||
|
&[open] {
|
||||||
|
@apply pointer-events-auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::backdrop {
|
||||||
|
@apply bg-black/50 backdrop-blur-xs transition;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog__close {
|
||||||
|
@apply absolute
|
||||||
|
top-2 right-2
|
||||||
|
p-0
|
||||||
|
text-white;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
@apply size-5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
109
fe/src/components/macros/MacroInput.vue
Normal file
109
fe/src/components/macros/MacroInput.vue
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
<template>
|
||||||
|
<div class="macro-input">
|
||||||
|
<div class="macro-input__output" ref="macroOutput"></div>
|
||||||
|
<input class="macro-input__input" type="text" ref="macroInput" @keydown.prevent="keyDown" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
|
const macroOutput = ref(null)
|
||||||
|
const macroInput = ref(null)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
macroInput.value.focus()
|
||||||
|
})
|
||||||
|
|
||||||
|
const keyDown = (e) => {
|
||||||
|
console.log(e)
|
||||||
|
|
||||||
|
const modKeys = {
|
||||||
|
Control: 'Ctrl',
|
||||||
|
Shift: 'Shift',
|
||||||
|
Alt: 'Alt',
|
||||||
|
Meta: 'Win',
|
||||||
|
}
|
||||||
|
|
||||||
|
const specialKeys = {
|
||||||
|
PageUp: 'PgUp',
|
||||||
|
PageDown: 'PgDn',
|
||||||
|
ScrollLock: 'Scr Lk',
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = e.key
|
||||||
|
|
||||||
|
if (e.shiftKey) {
|
||||||
|
key = e.key.toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
const newKeyEl = document.createElement('kbd')
|
||||||
|
|
||||||
|
if (e.code === 'Space') {
|
||||||
|
newKeyEl.innerHTML = 'Space'
|
||||||
|
} else if (e.location === 1 && Object.keys(modKeys).includes(key)) {
|
||||||
|
newKeyEl.innerHTML = '<sup>left</sup> ' + (modKeys[key] || key)
|
||||||
|
} else if (e.location === 2 && Object.keys(modKeys).includes(key)) {
|
||||||
|
newKeyEl.innerHTML = '<sup>right</sup> ' + (modKeys[key] || key)
|
||||||
|
} else if (e.location === 3) {
|
||||||
|
newKeyEl.innerHTML = '<sup>num</sup> ' + (modKeys[key] || key)
|
||||||
|
} else if (Object.keys(specialKeys).includes(key)) {
|
||||||
|
newKeyEl.innerHTML = specialKeys[key] || key
|
||||||
|
} else {
|
||||||
|
newKeyEl.innerHTML = key
|
||||||
|
}
|
||||||
|
|
||||||
|
macroOutput.value.appendChild(newKeyEl)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@reference "@/assets/main.css";
|
||||||
|
|
||||||
|
.macro-input {
|
||||||
|
@apply relative
|
||||||
|
w-full
|
||||||
|
h-96
|
||||||
|
my-4
|
||||||
|
rounded-lg
|
||||||
|
bg-slate-900/50
|
||||||
|
border
|
||||||
|
border-white/10
|
||||||
|
overflow-auto;
|
||||||
|
|
||||||
|
.macro-input__input,
|
||||||
|
.macro-input__output {
|
||||||
|
@apply absolute
|
||||||
|
inset-0
|
||||||
|
size-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.macro-input__output {
|
||||||
|
@apply flex
|
||||||
|
flex-wrap
|
||||||
|
items-start
|
||||||
|
gap-2
|
||||||
|
p-4
|
||||||
|
h-fit;
|
||||||
|
}
|
||||||
|
|
||||||
|
kbd {
|
||||||
|
@apply flex
|
||||||
|
items-center
|
||||||
|
gap-2
|
||||||
|
px-4 py-1
|
||||||
|
h-9
|
||||||
|
bg-white/10
|
||||||
|
font-sans
|
||||||
|
font-bold
|
||||||
|
text-lg
|
||||||
|
uppercase
|
||||||
|
rounded-md
|
||||||
|
border;
|
||||||
|
|
||||||
|
sup {
|
||||||
|
@apply text-xs font-light -ml-1.5 mt-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue