tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SmartGap.js (4368B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 import {
      6  svg,
      7  polygon,
      8 } from "devtools/client/shared/vendor/react-dom-factories";
      9 import PropTypes from "devtools/client/shared/vendor/react-prop-types";
     10 
     11 function shorten(coordinates) {
     12  // In cases where the token is wider than the preview, the smartGap
     13  // gets distorted. This shortens the coordinate array so that the smartGap
     14  // is only touching 2 corners of the token (instead of all 4 corners)
     15  coordinates.splice(0, 2);
     16  coordinates.splice(4, 2);
     17  return coordinates;
     18 }
     19 
     20 function getSmartGapCoordinates(
     21  preview,
     22  token,
     23  offset,
     24  orientation,
     25  gapHeight,
     26  coords
     27 ) {
     28  if (orientation === "up") {
     29    const coordinates = [
     30      token.left - coords.left + offset,
     31      token.top + token.height - (coords.top + preview.height) + gapHeight,
     32      0,
     33      0,
     34      preview.width + offset,
     35      0,
     36      token.left + token.width - coords.left + offset,
     37      token.top + token.height - (coords.top + preview.height) + gapHeight,
     38      token.left + token.width - coords.left + offset,
     39      token.top - (coords.top + preview.height) + gapHeight,
     40      token.left - coords.left + offset,
     41      token.top - (coords.top + preview.height) + gapHeight,
     42    ];
     43    return preview.width > token.width ? coordinates : shorten(coordinates);
     44  }
     45  if (orientation === "down") {
     46    const coordinates = [
     47      token.left + token.width - (coords.left + preview.top) + offset,
     48      0,
     49      preview.width + offset,
     50      coords.top - token.top + gapHeight,
     51      0,
     52      coords.top - token.top + gapHeight,
     53      token.left - (coords.left + preview.top) + offset,
     54      0,
     55      token.left - (coords.left + preview.top) + offset,
     56      token.height,
     57      token.left + token.width - (coords.left + preview.top) + offset,
     58      token.height,
     59    ];
     60    return preview.width > token.width ? coordinates : shorten(coordinates);
     61  }
     62  return [
     63    0,
     64    token.top - coords.top,
     65    gapHeight + token.width,
     66    0,
     67    gapHeight + token.width,
     68    preview.height - gapHeight,
     69    0,
     70    token.top + token.height - coords.top,
     71    token.width,
     72    token.top + token.height - coords.top,
     73    token.width,
     74    token.top - coords.top,
     75  ];
     76 }
     77 
     78 function getSmartGapDimensions(
     79  previewRect,
     80  tokenRect,
     81  offset,
     82  orientation,
     83  gapHeight,
     84  coords
     85 ) {
     86  if (orientation === "up") {
     87    return {
     88      height:
     89        tokenRect.top +
     90        tokenRect.height -
     91        coords.top -
     92        previewRect.height +
     93        gapHeight,
     94      width: Math.max(previewRect.width, tokenRect.width) + offset,
     95    };
     96  }
     97  if (orientation === "down") {
     98    return {
     99      height: coords.top - tokenRect.top + gapHeight,
    100      width: Math.max(previewRect.width, tokenRect.width) + offset,
    101    };
    102  }
    103  return {
    104    height: previewRect.height - gapHeight,
    105    width: coords.left - tokenRect.left + gapHeight,
    106  };
    107 }
    108 
    109 export default function SmartGap({
    110  token,
    111  preview,
    112  gapHeight,
    113  coords,
    114  offset,
    115 }) {
    116  const tokenRect = token.getBoundingClientRect();
    117  const previewRect = preview.getBoundingClientRect();
    118  const { orientation } = coords;
    119  let optionalMarginLeft, optionalMarginTop;
    120 
    121  if (orientation === "down") {
    122    optionalMarginTop = -tokenRect.height;
    123  } else if (orientation === "right") {
    124    optionalMarginLeft = -tokenRect.width;
    125  }
    126 
    127  const { height, width } = getSmartGapDimensions(
    128    previewRect,
    129    tokenRect,
    130    -offset,
    131    orientation,
    132    gapHeight,
    133    coords
    134  );
    135  const coordinates = getSmartGapCoordinates(
    136    previewRect,
    137    tokenRect,
    138    -offset,
    139    orientation,
    140    gapHeight,
    141    coords
    142  );
    143  return svg(
    144    {
    145      version: "1.1",
    146      xmlns: "http://www.w3.org/2000/svg",
    147      style: {
    148        height,
    149        width,
    150        position: "absolute",
    151        marginLeft: optionalMarginLeft,
    152        marginTop: optionalMarginTop,
    153      },
    154    },
    155    polygon({
    156      points: coordinates,
    157      fill: "transparent",
    158    })
    159  );
    160 }
    161 
    162 SmartGap.propTypes = {
    163  coords: PropTypes.object.isRequired,
    164  gapHeight: PropTypes.number.isRequired,
    165  offset: PropTypes.number.isRequired,
    166  preview: PropTypes.object.isRequired,
    167  token: PropTypes.object.isRequired,
    168  type: PropTypes.oneOf(["popover", "tooltip"]).isRequired,
    169 };