Index: src/UploadZone.vue
===================================================================
--- src/UploadZone.vue	(revision 4b96189c351c92e8383b4411f7a4a73de521da76)
+++ src/UploadZone.vue	(revision 64249d67d46154f425d75b148c215f53466b90e0)
@@ -1,5 +1,5 @@
 <script setup lang="ts">
 
-import { ref, defineProps, withDefaults, defineEmits, getCurrentInstance, defineExpose } from 'vue'
+import { ref, computed, defineProps, withDefaults, defineEmits, getCurrentInstance, defineExpose, watch, nextTick } from 'vue'
 
 import $ from 'jQuery'
@@ -28,4 +28,8 @@
   (e: 'upload:progress', vec: any[]): void
   (e: 'upload:done', vec: any[]): void
+  (e: 'update:canReset', flag: boolean): void
+  (e: 'update:canPick', flag: boolean): void
+  (e: 'update:canStart', flag: boolean): void
+  (e: 'update:canAbort', flag: boolean): void
 }>()
 
@@ -131,4 +135,7 @@
 
 const reset_cb = (): void => {
+  if(mode.value == Mode.m_idle)
+    return
+
   mode.value = Mode.m_idle
   files = []
@@ -136,5 +143,5 @@
 
 const pick_cb = (): void => {
-  if(mode.value != Mode.m_idle && Mode.value != Mode.m_wait)
+  if(mode.value != Mode.m_idle && mode.value != Mode.m_wait)
     return
 
@@ -168,5 +175,5 @@
   })
 
-  queue.value = queue.value.filter(queue.value, (file) => {
+  queue.value = queue.value.filter((file) => {
     return file !== cur
   })
@@ -184,5 +191,5 @@
 
       xhr.upload.addEventListener('progress', (evt): void => {
-        queue.value.forEach(current.value, (item) => {
+        current.value.forEach((item) => {
           if(item.file === cur) {
             item.current = evt.loaded
@@ -196,5 +203,5 @@
   })
     .then((res: any) => {
-      current.value = queue.value.filter(current.value, (item) => {
+      current.value = current.value.filter((item) => {
         return item.file !== cur
       })
@@ -223,10 +230,9 @@
         files = [] // XXX can drop w/o reset
 
-        if(errors.value.length) {
+        if(errors.value.length)
           if(props.keepGoing || props.keepGoing === '')
             mode.value = Mode.m_with_errors
           else
             mode.value = Mode.m_error
-        }
         else
           if(props.autoReset || props.autoReset === '')
@@ -243,5 +249,5 @@
     .catch((err: any) => {
       if(props.keepGoing || props.keepGoing === '') {
-        current.value = current.value.filter(current.value, (item) => {
+        current.value = current.value.filter((item) => {
           return item.file !== cur
         })
@@ -269,9 +275,59 @@
 }
 
+const can_pick = computed({
+  get: () => {
+    return mode.value == Mode.m_idle || mode.value == Mode.m_wait
+  },
+  set: () => {
+  }
+})
+
+const can_start = computed({
+  get: () => {
+    return mode.value == Mode.m_wait
+  },
+  set: () => {
+  }
+})
+
+const can_abort = computed({
+  get: () => {
+    return mode.value == Mode.m_uploading
+  },
+  set: () => {
+  }
+})
+
+const can_reset = computed({
+  get: () => {
+    return mode.value != Mode.m_idle
+  },
+  set: () => {
+  }
+})
+
+const update_can = (state: Mode): void => {
+  emit('update:canPick', can_pick.value)
+  emit('update:canStart', can_start.value)
+  emit('update:canAbort', can_abort.value)
+  emit('update:canReset', can_reset.value)
+}
+
+watch(() => { return mode.value }, (t: Mode, f: Mode) => { update_can(t) } )
+
+nextTick(() => {
+  update_can(mode.value)
+})
+
 defineExpose({
   reset: reset_cb,
   start: start_cb,
   pick: pick_cb,
-  abort: abort_cb
+  abort: abort_cb,
+
+  can_pick,
+  can_start,
+  can_abort,
+  can_reset
 })
 
