FormLockField.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <script setup>
  2. import { useIdGenerator } from '@/composables/helpers'
  3. import { UseColorMode } from '@vueuse/components'
  4. defineOptions({
  5. inheritAttrs: false
  6. })
  7. const { inputId } = useIdGenerator(props.inputType, props.fieldName)
  8. const props = defineProps({
  9. modelValue: String,
  10. modelModifiers: { default: () => ({}) },
  11. isEditMode: {
  12. type: Boolean,
  13. default: false
  14. },
  15. label: {
  16. type: String,
  17. default: ''
  18. },
  19. fieldName: {
  20. type: String,
  21. default: '',
  22. required: true
  23. },
  24. fieldError: [String],
  25. inputType: {
  26. type: String,
  27. default: 'text'
  28. },
  29. placeholder: {
  30. type: String,
  31. default: ''
  32. },
  33. help: {
  34. type: String,
  35. default: ''
  36. },
  37. hasOffset: {
  38. type: Boolean,
  39. default: false
  40. },
  41. isDisabled: {
  42. type: Boolean,
  43. default: false
  44. },
  45. isExpanded: {
  46. type: Boolean,
  47. default: true
  48. },
  49. maxLength: {
  50. type: Number,
  51. default: null
  52. }
  53. })
  54. const fieldIsLocked = ref(props.isDisabled || props.isEditMode)
  55. const hasBeenTrimmed = ref(false)
  56. const componentKey = ref(0);
  57. const emit = defineEmits(['input:modelValue'])
  58. /**
  59. * Removes spaces from the input string
  60. */
  61. function emitValue(e) {
  62. let value = e.target.value
  63. if (props.modelModifiers.trimAll) {
  64. value = value.replace(/\s+/g, '')
  65. }
  66. emit('update:modelValue', value)
  67. }
  68. function alertOnSpace(e) {
  69. let value = e.target.value
  70. hasBeenTrimmed.value = value.includes(' ')
  71. emit('update:modelValue', value)
  72. }
  73. function forceRefresh(e) {
  74. hasBeenTrimmed.value = e.target.value.includes(' ')
  75. componentKey.value += 1
  76. }
  77. </script>
  78. <template>
  79. <label :for="inputId" class="label" v-html="$t(label)" />
  80. <div class="field has-addons mb-0" :class="{ 'pt-3' : hasOffset }">
  81. <div class="control" :class="{ 'is-expanded': isExpanded }">
  82. <input
  83. :key="componentKey"
  84. :disabled="fieldIsLocked"
  85. :id="inputId"
  86. :type="inputType"
  87. class="input"
  88. :value="modelValue"
  89. :placeholder="placeholder"
  90. v-bind="$attrs"
  91. v-on:input="alertOnSpace"
  92. v-on:change="emitValue"
  93. v-on:blur="forceRefresh"
  94. :maxlength="maxLength"
  95. />
  96. </div>
  97. <UseColorMode v-slot="{ mode }" v-if="isEditMode">
  98. <div class="control" v-if="fieldIsLocked">
  99. <button type="button" class="button field-lock" :class="{'is-dark' : mode == 'dark'}" @click.stop="fieldIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
  100. <span class="icon">
  101. <FontAwesomeIcon :icon="['fas', 'lock']" />
  102. </span>
  103. </button>
  104. </div>
  105. <div class="control" v-else>
  106. <button type="button" class="button field-unlock" :class="{'is-dark' : mode == 'dark'}" @click.stop="fieldIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
  107. <span class="icon has-text-danger">
  108. <FontAwesomeIcon :icon="['fas', 'lock-open']" />
  109. </span>
  110. </button>
  111. </div>
  112. </UseColorMode>
  113. </div>
  114. <FieldError v-if="hasBeenTrimmed" :error="$t('twofaccounts.forms.spaces_are_ignored')" :field="'spaces'" :alertType="'is-warning'" />
  115. <FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
  116. <p class="help" v-html="$t(help)" v-if="help"></p>
  117. </template>