Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | <script setup lang="ts"> import { ref } from 'vue' import { Settings, Play, FileText } from 'lucide-vue-next' import { ElTooltip } from 'element-plus' interface Props { showTestButton?: boolean testButtonTooltip?: string testButtonDisabled?: boolean } withDefaults(defineProps<Props>(), { showTestButton: true, testButtonTooltip: 'Test Node', testButtonDisabled: false }) const emit = defineEmits<{ 'open-config': [] 'view-io': [] 'test': [] }>() const showActions = ref(false) defineExpose({ show: () => { showActions.value = true }, hide: () => { showActions.value = false } }) </script> <template> <Transition name="actions"> <div v-if="showActions" class="node-actions"> <ElTooltip content="Configure Node" placement="top"> <button class="action-btn" @click.stop="emit('open-config')"> <Settings :size="14" /> </button> </ElTooltip> <ElTooltip v-if="showTestButton" :content="testButtonTooltip" placement="top"> <button class="action-btn test-btn" @click.stop="emit('test')" :disabled="testButtonDisabled" > <Play :size="14" /> </button> </ElTooltip> <ElTooltip content="View Input/Output" placement="top"> <button class="action-btn io-btn" @click.stop="emit('view-io')"> <FileText :size="14" /> </button> </ElTooltip> <slot name="extra" /> </div> </Transition> </template> <style lang="scss" scoped> .node-actions { position: absolute; top: calc(-1 * var(--rf-spacing-5xl)); left: 50%; transform: translateX(-50%); display: flex; gap: var(--rf-spacing-xs); padding: var(--rf-spacing-3xs); background: var(--rf-color-bg-container); border-radius: var(--rf-radius-base); box-shadow: var(--rf-shadow-md); z-index: var(--rf-z-index-dropdown); .action-btn { width: var(--rf-size-icon-md); height: var(--rf-size-icon-md); padding: 0; border: none; background: var(--rf-color-bg-secondary); color: var(--rf-color-text-secondary); cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: var(--rf-radius-small); transition: all var(--rf-transition-fast); &:hover { background: var(--rf-color-primary-bg-lighter); color: var(--rf-color-primary); transform: scale(1.1); } &.io-btn:hover { background: var(--rf-color-info-bg-lighter); color: var(--rf-color-info); } &.test-btn:hover:not(:disabled) { background: var(--rf-color-success-bg-lighter); color: var(--rf-color-success); } &:disabled { opacity: 0.5; cursor: not-allowed; } } } .actions-enter-active, .actions-leave-active { transition: all var(--rf-transition-fast); } .actions-enter-from, .actions-leave-to { opacity: 0; transform: translateX(-50%) translateY(5px); } </style> |