CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vueuse--integrations

Vue.js composition API wrappers for popular utility libraries enabling seamless integration of third-party tools

Pending
Overview
Eval results
Files

visual-effects.mddocs/

Visual Effects and Progress

Drawing, progress indication, and QR code generation for enhanced user experience and visual feedback.

Capabilities

useDrauu

Interactive drawing and sketching using drauu library with canvas integration.

/**
 * Interactive drawing and sketching with canvas integration
 * @param target - Target element (canvas or container) for drawing
 * @param options - Drawing configuration options
 * @returns Drawing control interface and event handlers
 */
function useDrauu(
  target: MaybeComputedElementRef,
  options?: UseDrauuOptions
): UseDrauuReturn;

interface UseDrauuReturn {
  /** The drauu instance for direct access */
  drauuInstance: Ref<Drauu | undefined>;
  /** Load SVG drawing data */
  load: (svg: string) => void;
  /** Export current drawing as SVG string */
  dump: () => string | undefined;
  /** Clear all drawings */
  clear: () => void;
  /** Cancel current drawing operation */
  cancel: () => void;
  /** Undo last drawing action */
  undo: () => boolean | undefined;
  /** Redo previously undone action */
  redo: () => boolean | undefined;
  /** Whether undo is available */
  canUndo: ShallowRef<boolean>;
  /** Whether redo is available */
  canRedo: ShallowRef<boolean>;
  /** Current brush configuration */
  brush: Ref<Brush>;
  /** Drawing state change events */
  onChanged: EventHookOn;
  /** Drawing commit events */
  onCommitted: EventHookOn;
  /** Drawing start events */
  onStart: EventHookOn;
  /** Drawing end events */
  onEnd: EventHookOn;
  /** Drawing cancel events */
  onCanceled: EventHookOn;
}

type UseDrauuOptions = Omit<Options, 'el'>;

// drauu library types
interface Options {
  brush?: Brush;
  acceptsInputTypes?: InputType[];
  coordinate?: CoordinateType;
  coordinateScale?: number | false;
  coordinateTransform?: boolean | CoordinateTransform;
}

interface Brush {
  mode?: DrawingMode;
  color?: string;
  size?: number;
  cornerRadius?: number;
  dasharray?: string | undefined;
  arrowEnd?: boolean;
  arrowStart?: boolean;
}

type DrawingMode = 'draw' | 'line' | 'rectangle' | 'ellipse' | 'stylus';
type InputType = 'mouse' | 'touch' | 'pen';
type CoordinateType = 'relative' | 'absolute';

Usage Examples:

import { useDrauu } from "@vueuse/integrations/useDrauu";
import { ref, onMounted } from 'vue';

// Basic drawing setup
const canvasRef = ref<HTMLCanvasElement>();
const {
  drauuInstance,
  brush,
  clear,
  undo,
  redo,
  canUndo,
  canRedo,
  dump,
  load,
  onChanged
} = useDrauu(canvasRef, {
  brush: {
    mode: 'draw',
    color: '#000000',
    size: 3
  }
});

// Change brush settings
const changeBrushColor = (color: string) => {
  brush.value.color = color;
};

const changeBrushSize = (size: number) => {
  brush.value.size = size;
};

const changeBrushMode = (mode: DrawingMode) => {
  brush.value.mode = mode;
};

// Drawing tools
const clearCanvas = () => clear();
const undoLastAction = () => undo();
const redoAction = () => redo();

// Save and load drawings
const saveDrawing = () => {
  const svgData = dump();
  if (svgData) {
    localStorage.setItem('saved-drawing', svgData);
  }
};

const loadDrawing = () => {
  const svgData = localStorage.getItem('saved-drawing');
  if (svgData) {
    load(svgData);
  }
};

// Listen to drawing changes
onChanged(() => {
  console.log('Drawing changed');
  // Auto-save or validation logic
});

// Advanced brush configuration
const setupAdvancedBrush = () => {
  brush.value = {
    mode: 'line',
    color: '#ff0000',
    size: 5,
    dasharray: '5,5', // Dashed line
    arrowEnd: true,   // Arrow at end
    cornerRadius: 2   // Rounded corners
  };
};

// Multiple drawing modes
const drawingModes = [
  { name: 'Pen', mode: 'draw' },
  { name: 'Line', mode: 'line' },
  { name: 'Rectangle', mode: 'rectangle' },
  { name: 'Ellipse', mode: 'ellipse' },
  { name: 'Stylus', mode: 'stylus' }
];

useNProgress

Progress bar indication using NProgress library with reactive state management.

/**
 * Progress bar indication with reactive state management
 * @param currentProgress - Current progress value (0-1 or null)
 * @param options - NProgress configuration options
 * @returns Progress control interface
 */
function useNProgress(
  currentProgress?: MaybeRefOrGetter<number | null | undefined>,
  options?: UseNProgressOptions
): {
  /** Whether progress bar is currently showing */
  isLoading: WritableComputedRef<boolean>;
  /** Current progress value */
  progress: Ref<number | null | undefined>;
  /** Start progress indication */
  start: () => NProgress;
  /** Complete progress and hide bar */
  done: (force?: boolean) => NProgress;
  /** Remove progress bar from DOM */
  remove: () => void;
};

type UseNProgressOptions = Partial<NProgressOptions>;

// NProgress configuration options
interface NProgressOptions {
  /** Minimum progress value */
  minimum?: number;
  /** Animation template */
  template?: string;
  /** Easing function */
  easing?: string;
  /** Animation speed */
  speed?: number;
  /** Trickle animation */
  trickle?: boolean;
  /** Trickle speed */
  trickleSpeed?: number;
  /** Show spinner */
  showSpinner?: boolean;
  /** Barber pole moving animation */
  barberPole?: boolean;
  /** Parent element selector */
  parent?: string;
}

Usage Examples:

import { useNProgress } from "@vueuse/integrations/useNProgress";
import { ref } from 'vue';

// Basic progress indication
const { isLoading, start, done } = useNProgress();

// Show progress during async operations
const fetchData = async () => {
  start();
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } finally {
    done();
  }
};

// Controlled progress
const uploadProgress = ref(0);
const { progress, isLoading } = useNProgress(uploadProgress, {
  minimum: 0.1,
  speed: 200,
  showSpinner: false
});

const simulateUpload = () => {
  uploadProgress.value = 0;
  const interval = setInterval(() => {
    uploadProgress.value += 0.1;
    if (uploadProgress.value >= 1) {
      clearInterval(interval);
      uploadProgress.value = null; // Hide progress bar
    }
  }, 100);
};

// Router integration
import { useRoute } from 'vue-router';

const route = useRoute();
const { start, done } = useNProgress();

// Show progress on route changes
watch(() => route.path, () => {
  start();
  nextTick(() => done());
});

// Custom configuration
const { start, done } = useNProgress(undefined, {
  minimum: 0.2,
  easing: 'ease',
  speed: 500,
  trickle: true,
  trickleSpeed: 200,
  showSpinner: true,
  barberPole: true,
  template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
});

// Global loading state
const globalLoading = ref(false);
const { isLoading: nprogress } = useNProgress();

// Sync with global state
watch(globalLoading, (loading) => {
  nprogress.value = loading;
});

useQRCode

QR code generation using qrcode library with reactive updates.

/**
 * QR code generation with reactive updates
 * @param text - Text content to encode in QR code
 * @param options - QR code generation options
 * @returns Reactive data URL for QR code image
 */
function useQRCode(
  text: MaybeRefOrGetter<string>,
  options?: QRCode.QRCodeToDataURLOptions
): ShallowRef<string>;

// QR code generation options
namespace QRCode {
  interface QRCodeToDataURLOptions {
    /** Error correction level */
    errorCorrectionLevel?: 'low' | 'medium' | 'quartile' | 'high';
    /** QR code type (auto-detected if not specified) */
    type?: 'image/png' | 'image/jpeg' | 'image/webp';
    /** Rendered image quality (0.0 to 1.0) */
    quality?: number;
    /** Margin around QR code in modules */
    margin?: number;
    /** Scale factor for image size */
    scale?: number;
    /** Image width in pixels (overrides scale) */
    width?: number;
    /** Color options */
    color?: {
      /** Dark color (foreground) */
      dark?: string;
      /** Light color (background) */
      light?: string;
    };
  }
}

Usage Examples:

import { useQRCode } from "@vueuse/integrations/useQRCode";
import { ref, computed } from 'vue';

// Basic QR code generation
const text = ref('https://example.com');
const qrCode = useQRCode(text);

// QR code will be a data URL string like:
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK..."

// Dynamic QR code
const userInput = ref('');
const qrCodeUrl = useQRCode(userInput, {
  width: 200,
  margin: 2,
  color: {
    dark: '#000000',
    light: '#FFFFFF'
  }
});

// Contact information QR code
const contactInfo = computed(() => {
  return [
    'BEGIN:VCARD',
    'VERSION:3.0',
    'FN:John Doe',
    'TEL:+1234567890',
    'EMAIL:john@example.com',
    'URL:https://johndoe.com',
    'END:VCARD'
  ].join('\n');
});

const contactQR = useQRCode(contactInfo, {
  errorCorrectionLevel: 'medium',
  width: 300
});

// WiFi QR code
const wifiConfig = computed(() => {
  const ssid = 'MyWiFi';
  const password = 'MyPassword';
  const security = 'WPA';
  return `WIFI:T:${security};S:${ssid};P:${password};;`;
});

const wifiQR = useQRCode(wifiConfig);

// Custom styling options
const styledQR = useQRCode('Custom styled QR code', {
  width: 250,
  margin: 3,
  color: {
    dark: '#1a365d',    // Dark blue
    light: '#f7fafc'    // Light gray
  },
  errorCorrectionLevel: 'high'
});

// Multiple QR codes with different options
const qrCodes = [
  {
    name: 'Website',
    text: ref('https://example.com'),
    options: { width: 150, color: { dark: '#2563eb' } }
  },
  {
    name: 'Email',
    text: ref('mailto:contact@example.com'),
    options: { width: 150, color: { dark: '#dc2626' } }
  },
  {
    name: 'Phone',
    text: ref('tel:+1234567890'),
    options: { width: 150, color: { dark: '#059669' } }
  }
].map(item => ({
  ...item,
  qrCode: useQRCode(item.text, item.options)
}));

// Download QR code
const downloadQRCode = (dataUrl: string, filename: string) => {
  const link = document.createElement('a');
  link.download = filename;
  link.href = dataUrl;
  link.click();
};

Template Usage Examples:

<template>
  <div class="qr-code-examples">
    <!-- Basic QR code display -->
    <div>
      <h3>Website QR Code</h3>
      <img :src="qrCode" alt="QR Code" />
    </div>

    <!-- Dynamic QR code generator -->
    <div>
      <h3>Generate QR Code</h3>
      <input v-model="userInput" placeholder="Enter text or URL" />
      <div v-if="userInput">
        <img :src="qrCodeUrl" alt="Generated QR Code" />
        <button @click="downloadQRCode(qrCodeUrl, 'qrcode.png')">
          Download QR Code
        </button>
      </div>
    </div>

    <!-- Multiple QR codes -->
    <div class="qr-grid">
      <div v-for="item in qrCodes" :key="item.name" class="qr-item">
        <h4>{{ item.name }}</h4>
        <img :src="item.qrCode" :alt="`${item.name} QR Code`" />
      </div>
    </div>
  </div>
</template>

<style>
.qr-code-examples {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.qr-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

.qr-item {
  text-align: center;
  padding: 16px;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
}

.qr-item img {
  max-width: 100%;
  height: auto;
}
</style>

Install with Tessl CLI

npx tessl i tessl/npm-vueuse--integrations

docs

form-validation.md

http-client.md

index.md

search-data.md

storage-state.md

ui-interactions.md

visual-effects.md

tile.json