EditPressKey.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <div>
  3. <ui-textarea
  4. :model-value="data.description"
  5. class="w-full"
  6. :placeholder="t('common.description')"
  7. @change="updateData({ description: $event })"
  8. />
  9. <edit-autocomplete class="mt-2">
  10. <ui-input
  11. :model-value="data.selector"
  12. class="w-full"
  13. autocomplete="off"
  14. label="Target element (Optional)"
  15. placeholder="CSS Selector or XPath"
  16. @change="updateData({ selector: $event })"
  17. />
  18. </edit-autocomplete>
  19. <div class="flex items-end">
  20. <ui-autocomplete
  21. :items="keysList"
  22. :model-value="dataKeys"
  23. hide-empty
  24. block
  25. class="mt-2"
  26. >
  27. <ui-input
  28. :label="t('workflow.blocks.press-key.key')"
  29. :model-value="dataKeys"
  30. :disabled="isRecordingKey"
  31. placeholder="(Enter, Esc, a, b, ...)"
  32. autocomplete="off"
  33. class="w-full"
  34. @change="updateKeys"
  35. />
  36. </ui-autocomplete>
  37. <ui-button
  38. v-tooltip="
  39. isRecordingKey
  40. ? t('common.cancel')
  41. : t('workflow.blocks.press-key.detect')
  42. "
  43. icon
  44. class="ml-2"
  45. @click="toggleRecordKeys"
  46. >
  47. <v-remixicon :name="isRecordingKey ? 'riCloseLine' : 'riFocus3Line'" />
  48. </ui-button>
  49. </div>
  50. </div>
  51. </template>
  52. <script setup>
  53. import { ref, onBeforeUnmount } from 'vue';
  54. import { useI18n } from 'vue-i18n';
  55. import { toCamelCase } from '@/utils/helper';
  56. import { keyDefinitions } from '@/utils/USKeyboardLayout';
  57. import EditAutocomplete from './EditAutocomplete.vue';
  58. const props = defineProps({
  59. data: {
  60. type: Object,
  61. default: () => ({}),
  62. },
  63. });
  64. const emit = defineEmits(['update:data']);
  65. const includedKeys = ['Enter', 'Control', 'Meta', 'Shift', 'Alt', 'Space'];
  66. const filteredDefinitions = Object.keys(keyDefinitions).filter(
  67. (key) => key.trim().length <= 1 || key.startsWith('Arrow')
  68. );
  69. const keysList = filteredDefinitions.concat(includedKeys);
  70. const modifierKeys = ['Control', 'Alt', 'Shift', 'Meta'];
  71. const { t } = useI18n();
  72. const isRecordingKey = ref(false);
  73. const dataKeys = ref(`${props.data.keys}`);
  74. function updateData(value) {
  75. emit('update:data', { ...props.data, ...value });
  76. }
  77. function updateKeys(value) {
  78. dataKeys.value = value;
  79. updateData({ keys: value });
  80. }
  81. function onKeydown(event) {
  82. if (event.repeat || modifierKeys.includes(event.key)) return;
  83. event.preventDefault();
  84. event.stopPropagation();
  85. const { shiftKey, metaKey, altKey, ctrlKey, key } = event;
  86. let pressedKey = key.length > 1 || shiftKey ? toCamelCase(key, true) : key;
  87. if (pressedKey === ' ') pressedKey = 'Space';
  88. else if (pressedKey === '+') pressedKey = 'NumpadAdd';
  89. const keys = [pressedKey];
  90. if (shiftKey) keys.unshift('Shift');
  91. if (metaKey) keys.unshift('Meta');
  92. if (altKey) keys.unshift('Alt');
  93. if (ctrlKey) keys.unshift('Control');
  94. updateKeys(keys.join('+'));
  95. }
  96. function onKeyup() {
  97. isRecordingKey.value = false;
  98. /* eslint-disable-next-line */
  99. detachKeyEvents();
  100. }
  101. function attachKeyEvents() {
  102. window.addEventListener('keyup', onKeyup);
  103. window.addEventListener('keydown', onKeydown);
  104. }
  105. function detachKeyEvents() {
  106. window.removeEventListener('keyup', onKeyup);
  107. window.removeEventListener('keydown', onKeydown);
  108. }
  109. function toggleRecordKeys() {
  110. isRecordingKey.value = !isRecordingKey.value;
  111. if (isRecordingKey.value) {
  112. attachKeyEvents();
  113. } else {
  114. detachKeyEvents();
  115. }
  116. }
  117. onBeforeUnmount(() => {
  118. detachKeyEvents();
  119. });
  120. </script>