Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@heduapp/playground

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@heduapp/playground - npm Package Compare versions

Comparing version 0.9.2 to 0.9.3

dist/typings/src/classes/createPlaygroundStyles.d.ts

0

dist/typings/src/classes/Acceptor.d.ts

@@ -0,0 +0,0 @@ import * as TC from 'touchcontroller';

@@ -0,0 +0,0 @@ import * as TC from 'touchcontroller';

@@ -0,0 +0,0 @@ import * as TC from 'touchcontroller';

33

dist/typings/src/classes/Playground.d.ts

@@ -1,20 +0,19 @@

import * as TC from 'touchcontroller';
import { Rect } from './Rect';
interface IPlaygroundState {
itemsIds: string[];
activeItems: Rect[];
}
export declare class Playground {
svgElement: SVGSVGElement;
anchorElement: HTMLElement;
debugCanvasElement: HTMLCanvasElement | null;
private getScroll;
rects: Rect[];
debugCanvasElementCtx: CanvasRenderingContext2D | null;
offset: TC.Vector2;
initialScroll: TC.Vector2;
constructor(svgElement: SVGSVGElement, anchorElement: HTMLElement, //public touchcontroller: TC.touchcontroller,
debugCanvasElement: HTMLCanvasElement | null, getScroll: () => TC.Vector2);
private _parseSvg;
addSvgGroup(groupElement: SVGGElement, immediateDrag?: Event | null): void;
addRect(rect: Rect, immediateDrag?: Event | null): void;
touchController: TC.TouchController;
private _initializeTouches;
private _renderLoopTick;
private playgroundElement;
private debugMode;
private preserveOriginalSvg;
constructor(playgroundElement: HTMLElement, debugMode?: boolean, preserveOriginalSvg?: boolean);
private subscribers;
subscribe(callback: Function): void;
private subscribersCall;
readonly state: IPlaygroundState;
private itemsIds;
private playgroundActive;
private init;
}
export {};
import * as TC from 'touchcontroller';
import { Playground } from './Playground';
import { PlaygroundActive } from './PlaygroundActive';
import { Donor } from './Donor';

@@ -9,7 +9,7 @@ import { Acceptor } from './Acceptor';

svgElement: SVGGElement;
playground: Playground;
playgroundActive: PlaygroundActive;
private _anchorPairs;
hovered: boolean;
playgroundData: IPlaygroundData;
constructor(color: string, svgElement: SVGGElement, center: TC.Vector2, size: TC.Vector2, rotation: number, playground: Playground);
constructor(color: string, svgElement: SVGGElement, center: TC.Vector2, size: TC.Vector2, rotation: number, playgroundActive: PlaygroundActive);
visualFeedback(): void;

@@ -16,0 +16,0 @@ acceptors: Acceptor[];

import { Playground } from './classes/Playground';
import { initializePlayground } from './initializePlayground';
export { initializePlayground, Playground };
export default Playground;

@@ -1,1 +0,7 @@

export declare function initializePlayground(playgroundElement: HTMLElement, debugMode?: boolean, preserveOriginalSvg?: boolean): Promise<() => void>;
export declare class Playground {
private playgroundElement;
private debugMode;
private preserveOriginalSvg;
constructor(playgroundElement: HTMLElement, debugMode?: boolean, preserveOriginalSvg?: boolean);
private init;
}

@@ -0,0 +0,0 @@ export interface IPlaygroundData {

export declare function getBoundingRectWithoutRotation(element: Element): ClientRect | DOMRect;
import * as TC from 'touchcontroller';
export declare function getScroll(element: Element): TC.Vector2;
import { IPlaygroundData } from './../interfaces/IPlaygroundData';
export declare function parsePlaygroundData(gElement: SVGGElement): IPlaygroundData;
export declare function waitImmediate(): Promise<void>;
{
"name": "@heduapp/playground",
"version": "0.9.2",
"author": "Pavol Hejný",
"version": "0.9.3",
"author": "H-Edu s.r.o.",
"description": "Interactive SVG images for H-Edu Books.",
"main": "./dist/index.js",
"typings": "./dist/typings/src/index.d.ts",
"private": false,
"scripts": {

@@ -15,2 +14,3 @@ "start": "npm run develop",

"develop": "onchange \"src/**/*.{ts,tsx}\" --initial --kill --delay 500 -- webpack --config webpack.config.js --mode development",
"deploy": "git push --tags",
"expose": "node server.js",

@@ -46,4 +46,6 @@ "prettier": "prettier --config .prettierrc --write \"src/**/*.{ts,tsx,js,css}\" \"test/**/*.{ts,tsx,js,css}\" webpack.config.js",

"dependencies": {
"touchcontroller": "^0.13.2"
"@types/uuid": "^3.4.4",
"touchcontroller": "^0.13.2",
"uuid": "^3.3.2"
}
}

@@ -32,3 +32,2 @@ import * as TC from 'touchcontroller';

if (this.donors.indexOf(donor) === -1) {
//console.log(donor);

@@ -35,0 +34,0 @@ //console.log(`snapDonor`);

@@ -12,4 +12,6 @@ import * as TC from 'touchcontroller';

get position() {
return this.relativePosition.rotate(this.rect.rotation).add(this.rect.shadowBoundingBox.topLeft);
return this.relativePosition
.rotate(this.rect.rotation)
.add(this.rect.shadowBoundingBox.topLeft);
}
}

@@ -0,191 +1,197 @@

import { Rect } from './Rect';
import { IPlaygroundData } from '../interfaces/IPlaygroundData';
import { PlaygroundActive } from './PlaygroundActive';
import * as TC from 'touchcontroller';
import { Rect } from './Rect';
import { v4 as uuidV4 } from 'uuid';
import { getBoundingRectWithoutRotation } from '../tools/getBoundingRectWithoutRotation';
import { getScroll } from '../tools/getScroll';
import { parsePlaygroundData } from '../tools/parsePlaygroundData';
import { waitImmediate } from '../tools/wait';
import { createPlaygroundStyles } from '../tools/createPlaygroundStyles';
//import { translateToVector, vectorToTranslate } from './svgTools';
interface IPlaygroundState {
itemsIds: string[];
activeItems: Rect[];
}
export class Playground {
public rects: Rect[];
public debugCanvasElementCtx: CanvasRenderingContext2D | null = null;
public offset: TC.Vector2;
public initialScroll: TC.Vector2;
constructor(
public svgElement: SVGSVGElement,
public anchorElement: HTMLElement, //public touchcontroller: TC.touchcontroller,
public debugCanvasElement: HTMLCanvasElement | null = null,
private getScroll: () => TC.Vector2,
private playgroundElement: HTMLElement,
private debugMode = false,
private preserveOriginalSvg = false,
) {
this.rects = [];
if (!playgroundElement) {
throw new Error(
`Can not initialize playground because playground element is null.`,
);
}
this.init();
}
if (debugCanvasElement) {
this.debugCanvasElementCtx = debugCanvasElement.getContext('2d');
this._renderLoopTick();
private subscribers: Function[] = [];
subscribe(callback: Function) {
this.subscribers.push(callback);
}
private subscribersCall() {
for (const subscriber of this.subscribers) {
subscriber();
}
}
this.initialScroll = this.getScroll();
this._initializeTouches();
this._parseSvg(svgElement);
get state(): IPlaygroundState {
return {
itemsIds: this.itemsIds,
activeItems: this.playgroundActive
? this.playgroundActive.rects
: [],
};
}
private _parseSvg(svgElement: SVGElement) {
//console.log('parsing svg',svgElement);
//todo initialized
private itemsIds: string[] = [];
private playgroundActive: null | PlaygroundActive = null;
private async init() {
await waitImmediate();
const boundingBoxAll = svgElement.getBoundingClientRect(); //todo to rect
this.offset = new TC.Vector2(boundingBoxAll.left, boundingBoxAll.top);
const playgroundId = `playground-${uuidV4()}`;
this.playgroundElement.classList.add(playgroundId);
for (const groupElement of Array.prototype.slice.call(
svgElement.querySelectorAll('g'),
)) {
this.addSvgGroup(svgElement as SVGGElement, null);
let playgroundSvg = (document.createElement(
'svg',
) as any) as SVGSVGElement; //todo better
const playgroungDiv = document.createElement('div');
playgroungDiv.classList.add('interactive-layer');
playgroungDiv.appendChild(playgroundSvg);
playgroungDiv.innerHTML = playgroungDiv.innerHTML; //This hack shows regenerated svg. Otherwise SVG is not visible.
let debugLayerCanvas: HTMLCanvasElement | null = null;
if (this.debugMode) {
const debugLayerDiv = document.createElement('div');
debugLayerDiv.classList.add('interactive-layer');
debugLayerCanvas = document.createElement('canvas');
debugLayerCanvas.width = this.playgroundElement.getBoundingClientRect().width;
debugLayerCanvas.height = this.playgroundElement.getBoundingClientRect().height;
debugLayerDiv.appendChild(debugLayerCanvas);
this.playgroundElement.insertBefore(
debugLayerDiv,
this.playgroundElement.children[0],
);
}
}
addSvgGroup(groupElement: SVGGElement, immediateDrag: Event | null = null) {
const transformOriginal = TC.svgTransformationDecode(
groupElement.getAttribute('transform') || undefined,
this.playgroundElement.insertBefore(
playgroungDiv,
this.playgroundElement.children[0],
);
const transformZeroRotation = transformOriginal.clone();
transformZeroRotation.rotate = 0;
playgroundSvg = playgroungDiv.querySelector('svg')!;
groupElement.setAttribute(
'transform',
TC.svgTransformationEncode(transformZeroRotation),
);
const boundingBoxZeroRotate = groupElement.getBoundingClientRect(); //todo to rect
groupElement.setAttribute(
'transform',
TC.svgTransformationEncode(transformOriginal),
);
const boundingBoxWithRotate = groupElement.getBoundingClientRect(); //todo to rect
const styleElement = createPlaygroundStyles(playgroundId);
//console.log(this.anchorElement.scrollTop);
const scrollDelta = this.getScroll().subtract(this.initialScroll);
this.playgroundElement.appendChild(styleElement);
this.addRect(
new Rect(
'transparent', //'rgba(1,0,0,0.5)',
groupElement,
new TC.Vector2(
(boundingBoxWithRotate.right + boundingBoxWithRotate.left) /
2,
(boundingBoxWithRotate.bottom + boundingBoxWithRotate.top) /
2,
)
.addInPlace(scrollDelta)
.subtractInPlace(this.offset),
new TC.Vector2(
boundingBoxZeroRotate.right - boundingBoxZeroRotate.left,
boundingBoxZeroRotate.bottom - boundingBoxZeroRotate.top,
),
transformOriginal.rotate,
this,
),
immediateDrag,
const playgroundActive = new PlaygroundActive(
playgroundSvg,
this.playgroundElement,
debugLayerCanvas,
() => getScroll(this.playgroundElement),
);
}
addRect(rect: Rect, immediateDrag: Event | null = null) {
//console.log(rect);
this.rects.push(rect);
this.touchController.addElement(
(rect.svgElement as any) as HTMLElement,
immediateDrag,
);
}
for (const svgElement of Array.from(
this.playgroundElement.querySelectorAll('svg'),
)) {
const moveBy = TC.Vector2.Zero();
public touchController: TC.TouchController;
if (svgElement.hasAttribute('viewBox')) {
const [minX, minY, width, height] = svgElement
.getAttribute('viewBox')!
.split(' ')
.map((s) => parseFloat(s));
moveBy.addInPlace(new TC.Vector2(minX, minY));
}
private _initializeTouches() {
//console.log(this.rects);
//console.log(this.rects.map((rect)=>rect.svgElement)[0]);
for (const gElement of Array.from(
svgElement.querySelectorAll('g'), //todo there should be :scope > g but IE 11 don`t support it
)) {
let id: null | string = null;
this.touchController = new TC.TouchController(
[], //this.rects.map((rect) => rect.svgElement) as any,
document.body,
true,
);
if (gElement.hasAttribute('data-playground-id')) {
id = gElement.getAttribute('data-playground-id');
this.itemsIds.push(id!);
} else {
//do not worry
// console.warn(`Element in playground do not have attribute "data-playground-id".`,gElement);
}
const multiTouchController = new TC.MultiTouchController(
this.touchController,
(frame) =>
this.rects.find(
(rect) =>
(rect.svgElement as any) === (frame.element as any),
),
);
let amount = parsePlaygroundData(gElement).amount;
//console.log(multiTouchController);
multiTouchController.hoveredElementsChanges.subscribe(
([elementNew, elementOld]) => {
//console.log([elementNew,elementOld]);
if (elementNew || false) {
elementNew.hovered = true;
}
if (elementOld || false) {
elementOld.hovered = false;
}
},
);
gElement.addEventListener('pointerdown', (event) => {
//console.log(`Click on virgin element - making clone.`);
multiTouchController.multiTouches.subscribe(function(multitouch) {
//console.log('multitouch', multitouch);
const playgroundElementBoundingRect = this.playgroundElement.getBoundingClientRect();
const topLeftAnchor = new TC.Vector2(
playgroundElementBoundingRect.left -
this.playgroundElement.scrollLeft,
playgroundElementBoundingRect.top -
this.playgroundElement.scrollTop,
);
const svgElementBoundingRect = svgElement.getBoundingClientRect();
const topLeft = new TC.Vector2(
svgElementBoundingRect.left,
svgElementBoundingRect.top,
)
.subtractInPlace(topLeftAnchor)
.subtractInPlace(moveBy);
if (typeof multitouch.element === 'undefined') return;
const rect = multitouch.element;
const sizeRatio = rect.size.y / rect.size.x;
const gElementBoundingRect = getBoundingRectWithoutRotation(
gElement,
);
const gElementNew = gElement.cloneNode(true) as SVGGElement;
rect.startTransformations();
let transform = TC.svgTransformationDecode(
gElement.getAttribute('transform') || undefined, //todo take new or old? Which is better???
);
multitouch
.transformations(
/*new TC.Transformation(
rect.center,
rect.rotation,
rect.size.x
)*/
rect,
)
.subscribe(
function(transformation) {
//console.log(transformation);
/*multitouch.element.center = transformation.translate;
multitouch.element.rotation = transformation.rotate;
multitouch.element.size.x = transformation.scale;
multitouch.element.size.y = transformation.scale * sizeRatio;*/
//multitouch.element.position = multitouch.element.position.add(transformation.translate);
},
function() {},
function() {
if (!multitouch.element) {
return;
}
transform = transform.add(
TC.Transformation.translate(topLeft),
); //todo use inPlace
transform.rotateCenter = new TC.Vector2(
gElementBoundingRect.width / 2,
gElementBoundingRect.height / 2,
);
if (multitouch.empty) {
//alert(`You have selected ${multitouch.element.color} rectangle.`);
rect.tap();
}
gElementNew.setAttribute(
'transform',
TC.svgTransformationEncode(transform),
);
playgroundSvg.appendChild(gElementNew);
rect.endTransformations();
},
);
});
}
playgroundActive.addSvgGroup(gElementNew, event);
private _renderLoopTick() {
if (this.debugCanvasElementCtx) {
this.debugCanvasElementCtx.clearRect(
0,
0,
this.debugCanvasElementCtx.canvas.width,
this.debugCanvasElementCtx.canvas.height,
);
for (const rect of this.rects.slice().reverse()) {
rect.render(this.debugCanvasElementCtx);
if (this.preserveOriginalSvg) {
return;
}
if (amount < 0) {
return;
}
if (amount > 1) {
amount -= 1;
return;
}
//console.log(`Removing virgin element.`);
svgElement.removeChild(gElement);
});
}
for (const rect of this.rects) {
rect.renderAnchors(this.debugCanvasElementCtx);
}
requestAnimationFrame(() => this._renderLoopTick());
}
playgroundActive.subscribe(() => {
this.subscribersCall();
});
this.playgroundActive = playgroundActive;
}
}

@@ -6,3 +6,3 @@ import {

import * as TC from 'touchcontroller';
import { Playground } from './Playground';
import { PlaygroundActive } from './PlaygroundActive';
import { Donor } from './Donor';

@@ -12,2 +12,3 @@ import { Acceptor } from './Acceptor';

import { parsePlaygroundData } from '../tools/parsePlaygroundData';
import window from '@heduapp/fake-window';

@@ -25,3 +26,3 @@ export class Rect extends TC.BoundingBox {

rotation: number,
public playground: Playground,
public playgroundActive: PlaygroundActive,
) {

@@ -38,3 +39,3 @@ super(center, size, rotation);

this.svgElement.style.opacity = '0.5';
setTimeout(() => {
window.setTimeout(() => {
this.svgElement.style.opacity = '1';

@@ -53,3 +54,3 @@ }, 500);

//console.log(this);
for (const rect of this.playground.rects) {
for (const rect of this.playgroundActive.rects) {
if (rect !== this) {

@@ -363,3 +364,8 @@ this.acceptors.push(

//todo optimize
this.renderAnchor(ctx, anchor.position, 'ACCEPTOR',`${anchor.donors.length}/${anchor.accepts}`);
this.renderAnchor(
ctx,
anchor.position,
'ACCEPTOR',
`${anchor.donors.length}/${anchor.accepts}`,
);
}

@@ -421,4 +427,4 @@ }

private rawAnchorsWithoutRotationToAnchors() {
this.anchors = this.rawAnchorsWithoutRotation;
this.anchors = this.rawAnchorsWithoutRotation;
/*

@@ -425,0 +431,0 @@ todo purge

import { Playground } from './classes/Playground';
import { initializePlayground } from './initializePlayground';
export { initializePlayground, Playground };
export default Playground;

@@ -1,7 +0,9 @@

export function waitImmediate():Promise<void>{
return new Promise((resolve,reject)=>{
setImmediate(()=>{
import window from '@heduapp/fake-window';
export function waitImmediate(): Promise<void> {
return new Promise((resolve, reject) => {
window.setImmediate(() => {
resolve();
});
})
}
});
}

@@ -15,3 +15,3 @@ const path = require('path');

//externals: [nodeExternals()],
target: 'web',
target: 'node',
module: {

@@ -18,0 +18,0 @@ rules: [

Sorry, the diff of this file is too big to display

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