Skip to content

useCommonUtilities Composable ​

javascript
export function useCommonUtilities() {
  const mimeToExtension = {
    'image/jpeg': '.jpeg',
    'image/png': '.png',
    'image/gif': '.gif',
    'image/bmp': '.bmp',
    'image/webp': '.webp',
    'image/tiff': '.tiff',
    'image/svg+xml': '.svg',
    'image/x-icon': '.ico',
    'image/vnd.microsoft.icon': '.ico',
    'image/vnd.wap.wbmp': '.wbmp',
    'image/heic': '.heic',
    'image/heic-sequence': '.heics',
    'image/heif': '.heif',
    'image/heif-sequence': '.heifs',
  };

  function capitalizeFirstLetter(string) {
    let lowercasedString = string.toLowerCase();
    return lowercasedString.charAt(0).toUpperCase() + lowercasedString.slice(1);
  }

  async function copyToClipboard(textToCopy) {
    try {
      await navigator.clipboard.writeText(textToCopy);
    } catch (err) {
      console.error('Failed to copy text: ', err);
    }
  }

  async function uploadImageUsingSignedUrl(signedUrl, uploadObject) {
    return new Promise((resolve, reject) => {
      const request = new XMLHttpRequest();
      request.open('PUT', signedUrl, true);

      request.upload.onprogress = (e) => {
        // console.log('onprogress', e);
      };

      request.onload = function () {
        if (request.status >= 200 && request.status < 300) {
          // console.log('onload');
          resolve();
        } else {
          reject();
        }
      };

      request.send(uploadObject);
    });
  }

  async function convertObjectUrlsToFiles(urls) {
    const files = await Promise.all(
      urls.map(async (url, index) => {
        try {
          const response = await fetch(url);
          const blob = await response.blob();
          const mimeType = blob.type || 'image/png';
          const extension = mimeType.split('/')[1] || 'png';
          const fileName = `thumbnail_${index}.${extension}`;
          const file = new File([blob], fileName, { type: mimeType });
          return { file, mimeType };
        } catch (error) {
          console.error(`Failed to convert URL at index ${index}:`, error);
          return null;
        }
      })
    );
    return files.filter((f) => f !== null); // Filter out failed ones
  }

  function formatDateStringToAgo(dateString) {
    const now = new Date();
    const updatedDate = new Date(dateString);
    const diffMs = now - updatedDate; // Difference in milliseconds
    const diffSec = Math.floor(diffMs / 1000);
    const diffMin = Math.floor(diffSec / 60);
    const diffHr = Math.floor(diffMin / 60);
    const diffDay = Math.floor(diffHr / 24);

    if (diffDay >= 1) return `${diffDay} day${diffDay > 1 ? 's' : ''} ago`;
    if (diffHr >= 1) return `${diffHr} hr${diffHr > 1 ? 's' : ''}. ago`;
    if (diffMin >= 1) return `${diffMin} min${diffMin > 1 ? 's' : ''}. ago`;
    return `${diffSec} sec${diffSec > 1 ? 's' : ''}. ago`;
  }

  function formatDate(timestamp) {
    if (!timestamp) return '';
    const date = new Date(timestamp);

    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-based
    const day = String(date.getDate()).padStart(2, '0');

    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  }

  function formatDateShort(dateString) {
    const date = new Date(dateString);
    const options = { month: 'short', day: 'numeric', year: 'numeric' };
    return date.toLocaleDateString('en-US', options);
  }

  function getExtensionFromDataURI(dataURI) {
    const mimeType = getDataURIType(dataURI);

    return mimeToExtension[mimeType] || null;
  }

  function getDataURIType(dataURI) {
    const mimeType = dataURI.split(',')[0].split(':')[1].split(';')[0];
    return mimeType;
  }

  function cloneObject(object) {
    return JSON.parse(JSON.stringify(object));
  }

  function debounce(func, wait) {
    let timeout;
    return function (...args) {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => func.apply(context, args), wait);
    };
  }

  function getRandomId() {
    return window.crypto.randomUUID();
  }

  function prepareUniqueSvg(svgString) {
    const uniqueId = getRandomId();
    const imagePlaceholders = [];
    let placeholderIndex = 0;

    // Extract and replace <image> tags with placeholders
    const svgWithoutImages = svgString.replace(/<image[\s\S]*?\/>/gi, (match) => {
      const placeholder = `__IMAGE_PLACEHOLDER_${placeholderIndex}__`;
      imagePlaceholders[placeholderIndex] = match;
      placeholderIndex++;
      return placeholder;
    });

    // Process IDs and URL references in the SVG (excluding image tags)
    const processedSvg = svgWithoutImages
      .replace(/id="([^"]+)"/g, (match, id) => {
        return `id="${id}-${uniqueId}"`;
      })
      .replace(/url\(#([^"]+)\)/g, (match, id) => {
        return `url(#${id}-${uniqueId})`;
      });

    // Restore original <image> tags
    return processedSvg.replace(/__IMAGE_PLACEHOLDER_(\d+)__/g, (match, index) => {
      return imagePlaceholders[parseInt(index)];
    });
  }

  function dataURItoBlob(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for (var i = 0; i < binary.length; i++) {
      array.push(binary.charCodeAt(i));
    }

    return new Blob([new Uint8Array(array)], { type: getDataURIType(dataURI) });
  }

  function getXYPositionsOfElementByID(elementID) {
    const element = document.getElementById(elementID);
    if (!element) return null;
    const rect = element.getBoundingClientRect();
    const positions = { x: rect.left, y: rect.top, height: rect.height, width: rect.width };
    console.log('positions', positions);
    return positions;
  }

  function applyOrRemoveClassToBody(className, status) {
    if (status) {
      document.body.classList.add(className);
    } else {
      document.body.classList.remove(className);
    }
  }

  return {
    mimeToExtension,
    capitalizeFirstLetter,
    copyToClipboard,
    uploadImageUsingSignedUrl,
    convertObjectUrlsToFiles,
    formatDateStringToAgo,
    formatDate,
    formatDateShort,
    getExtensionFromDataURI,
    getDataURIType,
    cloneObject,
    debounce,
    getRandomId,
    prepareUniqueSvg,
    dataURItoBlob,
    getXYPositionsOfElementByID,
    applyOrRemoveClassToBody,
  };
}