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-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-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',
|
||||
'button__subtle bg-transparent hover:bg-white/10 text-white border-transparent':
|
||||
props.variant === 'subtle',
|
||||
|
|
@ -38,10 +39,6 @@ const classString = computed(() => {
|
|||
.filter((key) => classes[key])
|
||||
.join(' ')
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log(classString)
|
||||
})
|
||||
</script>
|
||||
|
||||
<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