All files / packages/sds-components/src/sds/image image.js

0% Statements 0/35
0% Branches 0/18
0% Functions 0/8
0% Lines 0/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144                                                                                                                                                                                                                                                                                               
import { LightningElement, api } from 'lwc';
import 'sds/privateThemeProvider';
 
export default class Image extends LightningElement {
  static shadowSupportMode = 'native';
 
  _declarativeRatios = ['square', 'landscape', 'portrait', 'wide', 'ultrawide'];
  _ratio;
  _src;
  _srcset;
 
  /**
   * The alternative text used to describe the image.
   *
   * @type {string}
   */
  @api alt = '';
 
  /**
   * The object-fit CSS property.
   *
   * @type {string}
   */
  @api fit;
 
  /**
   * The aspect ratio of the image.
   * ---
   * Checks if the value is a valid declarative aspect ratio or a valid custom
   * aspect ratio. If the value is not valid, it will log a warning.
   *
   * @type {string}
   */
  @api
  get ratio() {
    return this._ratio;
  }
  set ratio(value) {
    this._ratio = this._declarativeRatios.includes(value)
      ? null
      : this.isValidCustomAspectRatio(value)
        ? `aspect-ratio: ${value};`
        : console.warn(`${value} is not a valid aspect-ratio value.`);
  }
 
  /**
   * The URL of the image.
   *
   * @type {string}
   */
  @api
  get src() {
    return this._src;
  }
  set src(value) {
    this.isValidImageUrl(value) ? (this._src = value) : console.warn(`${value} is not a valid image url.`);
  }
 
  /**
   * String which identifies one or more image candidate strings, separated using commas (,) each specifying
   * image resources to use under given circumstances.
   *
   * @type {string}
   */
  @api
  get srcset() {
    return this._srcset;
  }
  set srcset(value) {
    this.isValidImageUrl(value)
      ? (this._srcset = value)
      : console.warn(`${value} is not a valid image url or srcset value.`);
  }
 
  /**
   * Specifies the layout width of the image for each of a list of media conditions.
   *
   * @type {string}
   */
  @api sizes;
 
  /**
   * Determines if the URL passed into src and srcset is valid.
   *
   * @param {string} url
   * @returns {boolean}
   */
  isValidImageUrl(url) {
    if (typeof url !== 'string') {
      return false;
    }
 
    const srcRegex = /\.(jpeg|jpg|gif|png|svg|bmp)$/i;
    const srcsetRegex = /^(\S+)(\s+(\d+w|[\d.]+x))?$/i;
    const srcsetItems = url.split(',');
 
    for (const item of srcsetItems) {
      const trimmedItem = item.trim();
      const match = trimmedItem.match(srcsetRegex);
 
      if (!match) {
        return false;
      }
 
      const imageUrl = match[1];
      if (!srcRegex.test(imageUrl)) {
        return false;
      }
    }
    return true;
  }
 
  /**
   * Check if the custom value is a valid aspect ratio.
   *
   * @param {string} value
   * @returns {boolean}
   */
  isValidCustomAspectRatio(value) {
    // Check if the value is a string
    if (typeof value !== 'string') {
      return false;
    }
 
    // Use a regular expression to match the aspect ratio pattern
    const regex = /^\s*(\d+)\s*\/\s*(\d+)\s*$/;
    const match = value.match(regex);
    if (!match) {
      return false;
    }
 
    // Extract width and height from the match object
    const width = parseInt(match[1], 10);
    const height = parseInt(match[2], 10);
 
    // Ensure both width and height are positive integers
    if (width <= 0 || height <= 0) {
      return false;
    }
 
    return true;
  }
}