New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

coachmarks

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

coachmarks - npm Package Compare versions

Comparing version 1.2.1 to 1.3.0

dist/coachmarks.esm.js

2

cypress.json
{
"projectId": "agt1up",
"videoRecording": false
"video": true
}

@@ -5,7 +5,9 @@

cy.visit('http://localhost:10002'); // change URL to match your dev URL
cy.wait(1000);
cy.get('#single-btn').click();
cy.get('.coachmark-text').should('exist');
cy.get('.coachmark-action-btn').should('be.visible');
cy.get('.text-container .text').should('exist');
cy.get('.action-btn').should('be.visible');
// cy.get('.coachmark-svg').should('be.visible');
cy.get('.coachmark-glow').should('be.visible');
cy.get('.glow').should('be.visible');
cy.get('.leader-line').should('exist'); // for some reason cypress things it's not visible

@@ -15,8 +17,8 @@ });

it('closes on closebutton click', () => {
cy.get('.coachmark-action-btn').click();
cy.get('.action-btn').click();
cy.get('.coachmark-text').should('not.be.visible');
cy.get('.coachmark-action-btn').should('not.be.visible');
cy.get('.text').should('not.be.visible');
cy.get('.action-btn').should('not.be.visible');
// cy.get('.coachmark-svg').should('not.be.visible');
cy.get('.coachmark-glow').should('not.be.visible');
cy.get('.glow').should('not.be.visible');
cy.get('.leader-line').should('not.exist');

@@ -29,8 +31,8 @@ });

cy.get('.coachmark-text').should('exist');
cy.get('.coachmark-action-btn').should('be.visible');
cy.get('.text').should('exist');
cy.get('.action-btn').should('be.visible');
// cy.get('.coachmark-svg').should('be.visible');
cy.get('.coachmark-glow').should('be.visible');
cy.get('.glow').should('be.visible');
cy.get('.leader-line').should('exist'); // for some reason cypress things it's not visible
});
});
{
"name": "coachmarks",
"version": "1.2.1",
"version": "1.3.0",
"description": "On-board new users to your app and introduce new features with SVG sketches (coachmarks)",
"source": "src/index.js",
"main": "dist/coachmarks.js",
"browser": "dist/coachmarks.js",
"main": "dist/coachmarks.umd.js",
"browser": "dist/coachmarks.umd.js",
"module": "dist/coachmarks.esm.js",
"scripts": {

@@ -21,3 +22,5 @@ "build": "rollup -c",

"version": "npm run toc",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
},

@@ -38,10 +41,10 @@ "author": "Brian Hann",

"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.7.0",
"cypress": "^2.1.0",
"cypress": "^3.0.1",
"doctoc": "^1.3.0",
"eslint": "^4.5.0",
"eslint-config-xo-space": "^0.16.0",
"less": "^3.0.4",
"node-sass": "^4.7.2",

@@ -58,11 +61,12 @@ "npm-run-all": "^4.1.2",

"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-postcss": "^0.5.5",
"rollup-plugin-sass": "^0.5.3",
"rollup-plugin-scss": "^0.4.0",
"rollup-plugin-serve": "^0.4.2",
"rollup-plugin-string": "^2.0.2",
"rollup-plugin-svelte": "^4.1.0",
"rollup-plugin-uglify": "^2.0.1",
"svelte": "^2.7.0",
"tiny-lr": "^1.0.5",
"uglify-es": "^3.2.2",
"uglify-js": "^3.1.3",
"vuepress": "^0.10.0",
"wait-on": "^2.0.2",

@@ -151,3 +155,6 @@ "xo": "^0.18.2"

]
},
"engines": {
"yarn": "YARN NO LONGER USED - use npm instead."
}
}

@@ -33,3 +33,7 @@ <!-- START doctoc generated TOC please keep comment here to allow auto update -->

import coachmarks from 'coachmarks';
```
then
```javascript
coachmarks.add('start-button', {

@@ -49,2 +53,3 @@ target: '#start-button',

// Example: show a coachmark on page load
document.addEventListener('DOMContentLoaded', () => {

@@ -61,11 +66,12 @@ coachmarks.show('start-button');

- [ ] Remove extraneous packages that are no longer needed now that we're doing leader-line for arrows
- [ ] Clean up readme
- [x] Remove extraneous packages that are no longer needed now that we're doing leader-line for arrows
- [x] Change to hand-drawn font
- [ ] Set up "flow" of coachmarks, so one gets displayed after the other
- [ ] Make close button a "next" arrow if there's a flow
- [ ] Make sure JS is transpiling with Rollup. Can probably remove a lot of babel dependencies.
- [x] Set up "flow" of coachmarks, so one gets displayed after the other
- [x] Make close button a "next" arrow if there's a flow
- [x] Make sure JS is transpiling with Rollup. Can probably remove a lot of babel dependencies.
- Looks like it isn't, because tests fail on cypress headless with what appears to be a JS-related error (lambda function?). Lambdas aren't being
transpiled
- [ ] Make close button more readable. Probably an SVG where the text/icon is transparent and the background is a white circle?
- [ ] Fix positioning of arrow line
- [x] Make close button more readable. Probably an SVG where the text/icon is transparent and the background is a white circle?
- [x] Fix positioning of arrow line
Principles:

@@ -72,0 +78,0 @@ * Line should start and end at the points closest from the center of one rectangle to the nearest edge of the other rectangle, BUT favoring edge

@@ -8,2 +8,3 @@ import { merge } from 'lodash';

import resolve from 'rollup-plugin-node-resolve';
import less from 'less';
import serve from 'rollup-plugin-serve';

@@ -13,3 +14,4 @@ import string from 'rollup-plugin-string';

import sass from 'rollup-plugin-sass';
import rollupAnalyzer from 'rollup-analyzer-plugin';
import svelte from 'rollup-plugin-svelte';
// import rollupAnalyzer from 'rollup-analyzer-plugin';
import { minify } from 'uglify-es';

@@ -21,3 +23,3 @@ import pkg from './package.json';

output: {
file: pkg.browser,
file: pkg.main,
format: 'umd',

@@ -29,29 +31,21 @@ },

resolve({ browser: true }),
commonjs({
// namedExports: {
// 'node_modules/leader-line/leader-line.min.js': ['LeaderLine'],
// },
}),
commonjs(),
legacy({
'node_modules/leader-line/leader-line.min.js': 'LeaderLine',
}),
// postcss({
// plugins: [
// // cssnext(),
// // yourPostcssPlugin()
// ],
// // sourceMap: false, // default value
// // extract: false, // default value
// extensions: ['.css', '.sss'], // default value
// // parser: sugarss
// }),
// scss({
// output: false,
// }),
sass({
insert: true,
}),
// postcss(),
svelte({
preprocess: {
style: ({ content, attributes }) => {
if (attributes.lang !== 'less') return;
return less.render(content)
.then(output => ({ code: output.css, map: output.map }));
},
},
}),
string({
include: 'src/**/*.{svg,html}',
include: 'src/**/*.svg',
}),

@@ -62,3 +56,3 @@ babel({

filesize(),
rollupAnalyzer({ limit: 5 }),
// rollupAnalyzer({ limit: 5 }),
],

@@ -76,9 +70,10 @@ };

process.env.DEV ? livereload({
watch: ['dist'], // src
watch: ['dist'],
}) : undefined,
],
}),
// Minified version
merge({}, config, {
output: {
file: 'dist/coachmarks.min.js',
file: 'dist/coachmarks.umd.min.js',
format: 'umd',

@@ -90,2 +85,15 @@ },

}),
// Module
merge({}, config, {
// NOTE: this externalizes leader-line, which won't work because it exports a global variable that has to be loaded with a special loader
// external: Object.keys(pkg.dependencies).concat(['path-svg/svg-path']),
external: [
'lodash',
'raf',
],
output: {
file: pkg.module,
format: 'es',
},
}),
];
'use strict';
import distance from 'euclidean-distance';
import polar from 'array-polar';
import LeaderLine from 'leader-line';
import raf from 'raf';
import SvgPath from 'path-svg/svg-path';
import cache from './cache';
import { default as Flow } from './flow';
import ActionButton from './components/ActionButton.svelte';
import Text from './components/Text.svelte';
import Overlay from './components/Overlay.svelte';

@@ -14,4 +14,4 @@ const COLOR = '#fff';

// Spacing between line and node
const lineOffset = 20;
const elmNames = ['text', 'textContainer', 'coachTop', 'coachLeft', 'coachRight', 'coachBottom', 'glow', 'actionButton', 'svg', 'path'];
const lineOffset = 20; // TODO: remove? it's unused
const elmNames = ['text', 'textContainer', 'overlay', 'actionButton'];

@@ -23,5 +23,9 @@ export function clear() {

const node = cache(name);
if (node instanceof Node) {
if (!node) return;
if (node instanceof Node) { // regular node
node.remove();
cache.remove(name);
} else if (node.destroy) { // svelte.js node
node.destroy();
cache.remove(name);
}

@@ -66,7 +70,9 @@ });

const coached = coach(mark);
const text = addText(mark.text);
raf(() => {
const coached = coach(mark);
const text = addText(mark.text);
// arrow(coached, text);
leaderLine(text, coached);
// arrow(coached, text);
leaderLine(text.getTextElement(), coached);
});
}

@@ -88,55 +94,16 @@

// if (elm.className.indexOf('draggable-source') === -1) elm.className += ' draggable-source';
const body = document.querySelector('body');
const overlay = cache.default('overlay', () => new Overlay({ target: body }));
overlay.show(elm);
// elm.style.position = 'absolute';
// elm.style['z-index'] = 102;
// const actionBtn = createActionButton(mark);
// document.body.appendChild(actionBtn);
const borderRadius = window.getComputedStyle(elm).getPropertyValue('border-radius');
// borderRadius = parseInt(borderRadius, 10);
const actionBtn = cache.default('actionButton', () => new ActionButton({
target: body,
}));
actionBtn.set({ coachmark: mark });
actionBtn.on('clear', () => clear());
actionBtn.on('next', event => draw(event.next));
const rect = elm.getBoundingClientRect();
const top = rect.top;
const left = rect.left;
const width = rect.width;
const height = rect.height;
const right = left + width;
const bottom = top + height;
const coachTop = cache.default('coachTop', () => document.createElement('div'));
coachTop.className = 'coachmark-top';
const coachLeft = cache.default('coachLeft', () => document.createElement('div'));
coachLeft.className = 'coachmark-left';
const coachRight = cache.default('coachRight', () => document.createElement('div'));
coachRight.className = 'coachmark-right';
const coachBottom = cache.default('coachBottom', () => document.createElement('div'));
coachBottom.className = 'coachmark-bottom';
coachTop.style.height = top + 'px';
coachLeft.style.top = top + 'px';
coachRight.style.top = coachLeft.style.top;
coachLeft.style.height = height + 'px';
coachRight.style.height = coachLeft.style.height;
coachLeft.style.width = left + 'px';
coachRight.style.left = right + 'px';
coachBottom.style.top = bottom + 'px';
const glow = cache.default('glow', () => document.createElement('div'));
glow.className = 'coachmark-glow';
glow.style.top = (top) + 'px';
glow.style.left = (left) + 'px';
glow.style.width = (width) + 'px';
glow.style.height = (height) + 'px';
glow.style['border-radius'] = borderRadius;
glow.style['box-shadow'] = '0 0 ' + 20 + 'px ' + 10 + 'px #fff'; // TODO: this style should probably be dynamic
const actionBtn = createActionButton(mark);
[coachTop, coachLeft, coachRight, coachBottom, glow, actionBtn].forEach(c => {
if (!c.parentNode) {
document.body.appendChild(c);
}
});
// TODO: Make this a setting, to close on click anywhere

@@ -166,31 +133,11 @@ // setTimeout(() => {

const text = cache.default('text', () => document.createElement('div'));
const text = cache.default('text', () => new Text({
target: document.querySelector('body'),
data: {
target: elm,
},
}));
text.set({ text: textStr });
text.position();
const [box1, box2] = splitScreen();
// See if the element is in box1 or box2;
let elmMiddle = middleOf(elm);
elmMiddle = { x: Math.floor(elmMiddle[0]), y: Math.floor(elmMiddle[1]) };
let box;
if (rectContains(elmMiddle, box1)) {
box = box2;
} else {
box = box1;
}
const textContainer = cache.default('textContainer', () => document.createElement('div'));
textContainer.className = 'coachmark-text-container';
textContainer.style.top = box.top + 'px';
textContainer.style.left = box.left + 'px';
textContainer.style.width = box.width + 'px';
textContainer.style.height = box.height + 'px';
textContainer.appendChild(text);
document.body.appendChild(textContainer);
text.className = 'coachmark-text draggable-source';
// const ref = (text.innerText || text.textContent);
text.textContent = textStr;
return text;

@@ -203,8 +150,5 @@ }

let line = cache.get('leaderLine');
if (line) {
line.remove();
}
if (line) line.remove();
line = new LeaderLine(
// from, to,
LeaderLine.areaAnchor(from, { color: 'transparency' }),

@@ -215,5 +159,3 @@ LeaderLine.areaAnchor(to, { color: 'transparency' }),

startPlugColor: COLOR,
// endPlug: 'arrow2',
endPlugSize: 0.5,
// markerEnd: 'url(#coachmark-arrow)',
},

@@ -235,268 +177,4 @@ );

// Draw arrow from one node to another
function arrow(from, to) {
const fromRect = elementRect(from);
const toRect = elementRect(to);
// let fromPos = nearestEdgePoint(fromRect, toRect, { useCorners: false });
// let toPos = nearestEdgePoint(toRect, fromRect, { useCorners: false });
// fromPos = nearestEdgePoint(fromPos, toRect);
// toPos = nearestEdgePoint(toPos, fromRect);
const fromPos = arrowPoints(fromRect, toRect);
const toPos = arrowPoints(toRect, fromRect);
// NOTE: for curved line
const mid = midPoint(fromPos[0], fromPos[1], toPos[0], toPos[1]);
// let c1x = mid[0];
// let c1y = toPos[1];
// const c2x = fromPos[0];
// const c2y = mid[1];
// Find point, 50% of segment length away from midPoint
const dist = lineDist(fromPos[0], fromPos[1], toPos[0], toPos[1]);
// const vMid = viewportMid();
const coords = polar([fromPos[0], fromPos[1], toPos[0], toPos[1]], [fromPos[0], fromPos[1]]);
// const midCoords = polar([fromPos[0], fromPos[1], mid[0], mid[1]], [fromPos[0], fromPos[1]]);
const angle = coords[3];
let deg = angle * 180 / Math.PI;
deg = deg < 0 ? deg + 360 : deg;
const degPerp = deg - 90;
const degPerpRad = degPerp * Math.PI / 180;
const newCoords = polar.cartesian([0, Math.PI, dist * 0.2, degPerpRad]);
const midCtrl = [mid[0] + newCoords[2], mid[1] + newCoords[3]];
// const sl = slope(fromPos[0], fromPos[1], toPos[0], toPos[1]);
// const recip = -1 / sl;
// console.log('SLOPE', sl, recip);
// const pathStr = SvgPath().M(fromPos[0], fromPos[1]).C(c2x, c2y, c1x, c1y, toPos[0], toPos[1]).str();
// NOTE: quadratic curve using these args looks better. Also arrowhead orients right
// const pathStr = SvgPath().M(fromPos[0], fromPos[1]).Q(c1x, c1y, toPos[0], toPos[1]).str();
// NOTE: This is a nice smooth quadratic bezier curve
const pathStr = SvgPath().M(fromPos[0], fromPos[1]).Q(midCtrl[0], midCtrl[1], toPos[0], toPos[1]).str();
// const pathStr = SvgPath().M(fromPos[0], fromPos[1]).L(toPos[0], toPos[1]).str();
// Bezier S-Curve
// const dx = toPos[0] - fromPos[0];
// const dy = toPos[1] - fromPos[1];
// pathStr = SvgPath().M(fromPos[0], fromPos[1]).C(fromPos[0] + (dx * 0.33), fromPos[1], fromPos[0] + (dx * 0.67), toPos[1], toPos[0], toPos[1]).str();
// End Bezier S-Curve
const svg = cache.default('svg', () => createSVG());
const path = cache.default('path', () => document.createElementNS('http://www.w3.org/2000/svg', 'path'));
path.setAttribute('d', pathStr);
path.setAttribute('class', 'coachmark-line');
path.setAttribute('stroke-width', '5');
path.setAttribute('fill', 'none');
path.setAttribute('filter', 'url(#coachmark-chalk)');
path.setAttribute('marker-end', 'url(#arrow)');
// path.setAttribute('stroke-dasharray', '50, 15');
path.setAttribute('stroke-linecap', 'round');
if (!path.parentNode) {
svg.appendChild(path);
}
if (!svg.parentNode) {
document.body.insertBefore(svg, document.body.firstChild);
}
}
function createSVG() {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('height', '100%');
svg.setAttribute('width', '100%');
svg.setAttribute('class', 'coachmark-svg');
return svg;
}
function createActionButton(mark) {
let icon = 'X';
let action = clear;
let flow = cache('flow');
if (mark.flow) flow = cache.set('flow', mark.flow);
if (flow) {
const next = flow.getNext(mark.name);
if (next) {
icon = nextButtonHTML();
action = () => {
draw(next);
};
} else cache.remove('flow');
}
const close = cache.default('actionButton', () => document.createElement('div'));
close.setAttribute('class', 'coachmark-action-btn');
close.innerHTML = icon;
close.addEventListener('click', () => {
action();
});
return close;
}
function nextButtonHTML() {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); // ok
svg.setAttribute('class', 'coachmark-next-button');
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
g.setAttribute('transform', 'scale(0.065), translate(100, 140)');
const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
use.setAttribute('xlink:href', '#right-arrow');
g.appendChild(use);
svg.appendChild(g);
return svg.outerHTML;
}
/* Calculations Methods */
// function dist(pt1, pt2) {
// return Math.sqrt(
// Math.pow(pt2[0] - pt1[0], 2)
// *
// Math.pow(pt2[1] - pt1[1], 2)
// );
// }
function arrowPoints(from, to, opts = {}) {
// From is a rect, calc line from middle of rectangle
// const fromPt = middleOf(from);
// const toPt = middleOf(to);
const nearestFrom = nearestEdgePoint(from, to);
const nearestTo = nearestEdgePoint(to, from);
const dx = nearestTo[0] - nearestFrom[0];
const dy = nearestTo[1] - nearestFrom[1];
opts.favor = (dx > dy) ? 'x' : 'y';
return nearestEdgePoint(nearestFrom, to, opts);
}
function nearestEdgePoint(from, toRect, { useCorners, favor } = {}) {
/*
rect: {
top, left, width, height
}
*/
// From is a rect, calc line from middle of rectangle
if (Object.prototype.hasOwnProperty.call(from, 'top')) {
from = middleOf(from);
}
// NOTE: overall I think snapping to middle only actually looks a bit better, assuming that we calculated the edges properly
// Get list of point around toRect;
const points = {
leftTop: [toRect.left, toRect.top],
middleTop: [toRect.left + (toRect.width / 2), toRect.top],
rightTop: [toRect.left + toRect.width, toRect.top],
rightMiddle: [toRect.left + toRect.width, toRect.top + (toRect.height / 2)],
rightBottom: [toRect.left + toRect.width, toRect.top + toRect.height],
middleBottom: [toRect.left + (toRect.width / 2), toRect.top + toRect.height],
leftBottom: [toRect.left, toRect.top + toRect.height],
leftMiddle: [toRect.left, toRect.top + (toRect.height / 2)],
};
if (useCorners === false) {
Object.keys(points).forEach(key => {
if (key.toLowerCase().indexOf('middle') === -1) delete points[key];
});
}
if (favor && favor === 'x') {
// Remove top/bottom edges
Object.keys(points).forEach(key => {
if (/left|right/i.test(key)) delete points[key];
});
} else if (favor && favor === 'y') {
// Remove left/right edges
Object.keys(points).forEach(key => {
if (/top|bottom/i.test(key)) delete points[key];
});
}
let nearest = { point: [0, 0], dist: Infinity };
let nearestName = '';
Object.keys(points).forEach(key => {
const point = points[key];
const dist = distance(from, point);
if (dist < nearest.dist) {
nearest = { point, dist };
nearestName = key;
}
});
nearestName = nearestName.toLowerCase();
const point = nearest.point;
if (nearestName.indexOf('top') !== -1) point[1] -= lineOffset;
if (nearestName.indexOf('bottom') !== -1) point[1] += lineOffset;
if (nearestName.indexOf('left') !== -1) point[0] -= lineOffset;
if (nearestName.indexOf('right') !== -1) point[0] += lineOffset;
return point;
}
function middleOf(node) {
let rect = node;
if (node instanceof Node) {
rect = elementRect(node);
}
return [rect.left + (rect.width / 2), rect.top + (rect.height / 2)];
}
function rectContains({ x, y }, { left, top, width, height }) {
return left <= x && x <= left + width &&
top <= y && y <= top + height;
}
function splitScreen() {
const w = document.body.offsetWidth;
const h = document.body.offsetHeight;
let box1;
let box2;
// Split vertically
if (w > h) {
const boxWidth = Math.floor(w / 2);
box1 = {
top: 0,
left: 0,
height: h,
width: boxWidth,
};
box2 = {
top: 0,
left: boxWidth,
height: h,
width: w - boxWidth,
};
} else {
const boxHeight = Math.floor(h / 2);
box1 = {
top: 0,
left: 0,
height: boxHeight,
width: w,
};
box2 = {
top: boxHeight,
left: 0,
height: h - boxHeight,
width: w,
};
}
return [box1, box2];
}
/* NOTE: not in use currently

@@ -554,29 +232,2 @@ function middleOfEdge(node, edge) {

function midPoint(x1, y1, x2, y2) {
return [(x1 + x2) / 2, (y1 + y2) / 2];
}
function lineDist(x1, y1, x2, y2) {
return Math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2));
}
// function slope(x1, y1, x2, y2) {
// return (y2 - y1) / (x2 - x1);
// }
function viewportMid() {
return [
Math.max(document.documentElement.clientWidth, window.innerWidth || 0) / 2,
Math.max(document.documentElement.clientHeight, window.innerHeight || 0) / 2,
];
}
// function dirToViewportMid(pos) {
// const mid = viewportMid();
// return [
// pos[0] > mid[0] ? -1 : 1,
// pos[1] > mid[1] ? -1 : 1,
// ];
// }
/* NOTE: not in use currently

@@ -583,0 +234,0 @@ function intersectionEdge(point, rect) {

@@ -0,1 +1,2 @@

import raf from 'raf';
import cache from './cache';

@@ -6,3 +7,12 @@ import { clear, draw, redrawAll, flow } from './draw';

import injectSVG from './inject-svg';
import Overlay from './components/Overlay.svelte';
// document.addEventListener('DOMContentLoaded', () => {
// const overlay = new Overlay({
// target: document.querySelector('body'),
// });
//
// overlay.show(document.querySelector('button'));
// });
// Run on module load

@@ -13,5 +23,5 @@ init();

export default {
export default class Coachmark {
// Add a coachmark
add(name, config = {}) {
static add(name, config = {}) {
if (!(typeof name === 'string')) {

@@ -28,14 +38,31 @@ config = name;

cache(`mark.${name}`, config);
},
}
add() {
return Coachmark.add.apply(null, arguments);
}
// Show a coachmark given a name
show(name) {
static show(name) {
clear();
draw(name);
},
cache: () => cache.cache,
draw,
redrawAll,
flow,
};
}
static cache() {
return cache.cache;
}
static draw() {
return draw.apply(null, arguments);
}
static redrawAll() {
return redrawAll.apply(null, arguments);
}
static flow() {
return flow.apply(null, arguments);
}
}
function init() {

@@ -52,3 +79,3 @@ document.addEventListener('DOMContentLoaded', () => {

window.addEventListener('resize', () => {
requestAnimationFrame(() => {
raf(() => {
redrawAll();

@@ -55,0 +82,0 @@ });

@@ -14,5 +14,5 @@ import css from './css/main.scss';

link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'https://fonts.googleapis.com/css?family=Indie+Flower');
link.setAttribute('href', 'https://fonts.googleapis.com/css?family=Short+Stack');
document.head.appendChild(link);
return link;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc