slider-captcha-action.vue 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. <script setup lang="ts">
  2. import type { CSSProperties } from 'vue';
  3. import { computed, ref, useTemplateRef } from 'vue';
  4. import { Check, ChevronsRight } from '@vben/icons';
  5. import { Slot } from '@vben-core/shadcn-ui';
  6. const props = defineProps<{
  7. actionStyle: CSSProperties;
  8. isPassing: boolean;
  9. toLeft: boolean;
  10. }>();
  11. const actionRef = useTemplateRef<HTMLDivElement>('actionRef');
  12. const left = ref('0');
  13. const style = computed(() => {
  14. const { actionStyle } = props;
  15. return {
  16. ...actionStyle,
  17. left: left.value,
  18. };
  19. });
  20. const isDragging = computed(() => {
  21. const currentLeft = Number.parseInt(left.value as string);
  22. return currentLeft > 10 && !props.isPassing;
  23. });
  24. defineExpose({
  25. getEl: () => {
  26. return actionRef.value;
  27. },
  28. getStyle: () => {
  29. return actionRef?.value?.style;
  30. },
  31. setLeft: (val: string) => {
  32. left.value = val;
  33. },
  34. });
  35. </script>
  36. <template>
  37. <div
  38. ref="actionRef"
  39. :class="{
  40. 'transition-width !left-0 duration-300': toLeft,
  41. 'rounded-md': isDragging,
  42. }"
  43. :style="style"
  44. class="bg-background dark:bg-accent absolute left-0 top-0 flex h-full cursor-move items-center justify-center px-3.5 shadow-md"
  45. name="captcha-action"
  46. >
  47. <Slot :is-passing="isPassing" class="text-foreground/60 size-4">
  48. <slot name="icon">
  49. <ChevronsRight v-if="!isPassing" />
  50. <Check v-else />
  51. </slot>
  52. </Slot>
  53. </div>
  54. </template>