All files / src/components/shared ColorInput.vue

0% Statements 0/55
0% Branches 0/1
0% Functions 0/1
0% Lines 0/55

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                                                                                                                                                                                                                                       
<template>
  <div class="color-input">
    <label v-if="label" class="color-label">{{ label }}</label>
    <div class="color-controls">
      <input
        :value="modelValue"
        type="color"
        class="color-picker"
        @input="$emit('update:modelValue', $event.target.value)"
      />
      <input
        :value="modelValue"
        type="text"
        class="color-text"
        placeholder="#3B82F6"
        maxlength="7"
        @input="handleTextInput"
      />
    </div>
    <p v-if="helpText" class="color-help">{{ helpText }}</p>
  </div>
</template>
 
<script>
export default {
  name: 'ColorInput',
  props: {
    modelValue: {
      type: String,
      default: '#3B82F6',
    },
    label: {
      type: String,
      default: '',
    },
    helpText: {
      type: String,
      default: '',
    },
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const handleTextInput = event => {
      let value = event.target.value;
      // Ensure it starts with #
      if (value && !value.startsWith('#')) {
        value = '#' + value;
      }
      // Only emit if it's a valid hex color or partial
      if (/^#[0-9A-Fa-f]{0,6}$/.test(value)) {
        emit('update:modelValue', value);
      }
    };
 
    return {
      handleTextInput,
    };
  },
};
</script>
 
<style scoped>
.color-input {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
 
.color-label {
  font-weight: 600;
  color: #374151;
  font-size: 14px;
}
 
.color-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}
 
.color-picker {
  width: 40px;
  height: 40px;
  border-radius: 6px;
  cursor: pointer;
  border: 2px solid #e5e7eb;
  padding: 2px;
}
 
.color-picker:hover {
  border-color: #9ca3af;
}
 
.color-text {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  font-family: monospace;
  font-size: 14px;
  text-transform: uppercase;
}
 
.color-text:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
 
.color-help {
  font-size: 12px;
  color: #6b7280;
  margin: 0;
}
</style>