isFile() — Basic

Validates that a file has been selected.

import { isFile } from '@andresclua/validate'

const config = { required: true }

// On Change
fileInput.addEventListener('change', () => {
    const result = isFile({ element: fileInput.files[0], config })
    if (result.isValid) {
        fileInput.classList.remove('c--form-file-a--error')
        fileInput.classList.add('c--form-file-a--valid')
        errorEl.textContent = ''
    } else {
        fileInput.classList.add('c--form-file-a--error')
        fileInput.classList.remove('c--form-file-a--valid')
        errorEl.textContent = result.errorMessage
    }
})

// On Submit
validateBtn.addEventListener('click', () => {
    const result = isFile({ element: fileInput.files[0], config })
    if (result.isValid) {
        fileInput.classList.remove('c--form-file-a--error')
        fileInput.classList.add('c--form-file-a--valid')
        errorEl.textContent = ''
    } else {
        fileInput.classList.add('c--form-file-a--error')
        fileInput.classList.remove('c--form-file-a--valid')
        errorEl.textContent = result.errorMessage
    }
})
<div class="c--form-group-a">
  <label class="c--label-a" for="file">Select a file</label>
  <input type="file" id="file" class="c--form-file-a">
  <span class="c--form-error-a"></span>
</div>
/* Orientative — feel free to adapt to your own conventions */

.c--form-group-a {
    margin-bottom: 1.5em;
}

.c--label-a {
    display: block;
    font-size: 1em;
    margin-bottom: 0.5em;
}

.c--form-file-a {
    display: block;
    width: 100%;
    font-size: 1em;
    cursor: pointer;
}
.c--form-file-a--error { outline: 2px solid red; border-radius: 4px; }
.c--form-file-a--valid { outline: 2px solid green; border-radius: 4px; }

.c--form-error-a {
    color: red;
    font-size: 0.875em;
    display: none;
}
.c--form-error-a:not(:empty) { display: block; }
required  boolean  Whether a file is required. Default: false
Playground

On Change

On Submit