Skip to content

Commit

Permalink
feat: add Snappable
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed Jun 17, 2022
1 parent 766561c commit c7bbd98
Show file tree
Hide file tree
Showing 13 changed files with 6,887 additions and 2 deletions.
45 changes: 45 additions & 0 deletions packages/snappable/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"import"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended"
],
"rules": {
"import/no-webpack-loader-syntax": "off",
"no-unused-vars": "off",
"no-console": "error",
"no-shadow": "error",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-unused-vars": ["error"],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/ban-types": "off",
"indent": ["error", 2],
"@typescript-eslint/indent": "off",
"@typescript-eslint/adjacent-overload-signatures": "off",
"max-len": ["error", { "code": 120, "comments": 400, "ignoreTemplateLiterals": true }],
"@typescript-eslint/naming-convention": [
"error",
{ "selector": "default", "modifiers": ["protected"], "format": ["camelCase"], "leadingUnderscore": "require" },
{ "selector": "default", "modifiers": ["private"], "format": ["camelCase"], "leadingUnderscore": "require" }
],
"no-empty-interface": "off",
"comma-dangle": [
"error",
"always-multiline"
],
"semi": [
"error",
"always"
]
}
}
18 changes: 18 additions & 0 deletions packages/snappable/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
"roots": [
"<rootDir>",
],
"transform": {
"^.+\\.tsx?$": "ts-jest",
},
"testMatch": ["<rootDir>/test/**/*.spec.ts"],
// "testRegex": "spec\\.ts$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node",
],
};
6,509 changes: 6,509 additions & 0 deletions packages/snappable/package-lock.json

Large diffs are not rendered by default.

24 changes: 22 additions & 2 deletions packages/snappable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
"description": "snappable",
"private": true,
"scripts": {
"build": ""
"start": "rollup -c -w",
"build": "rm -rf ./dist ./declaration && rollup -c && npm run declaration",
"declaration": "rm -rf declaration && tsc -p tsconfig.declaration.json",
"lint": "eslint ./src/ --ext .ts",
"test": "jest --watchAll",
"coverage": "npm run test:node && jest --coverage && print-coveralls --sort=desc"
},
"keywords": [
"moveable",
Expand Down Expand Up @@ -42,5 +47,20 @@
"bugs": {
"url": "https://github.com/daybrush/moveable/issues"
},
"homepage": "https://daybrush.com/moveable"
"homepage": "https://daybrush.com/moveable",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.9.1",
"eslint": "^7.32.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.22.0",
"print-coveralls": "^1.2.2",
"typescript": "^4.6.4",
"@types/jest": "^24.0.13",
"jest": "^24.8.0",
"ts-jest": "^24.0.2"
},
"dependencies": {
"@daybrush/utils": "^1.6.0"
}
}
29 changes: 29 additions & 0 deletions packages/snappable/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import builder from "@daybrush/builder";

const defaultOptions = {
tsconfig: "tsconfig.build.json",
};

export default builder([{
...defaultOptions,
input: "src/index.ts",
output: "./dist/snappable.esm.js",
format: "es",
exports: "named",
},
{
...defaultOptions,
input: "src/index.umd.ts",
output: "./dist/snappable.esm.js",
format: "es",
exports: "default",
name: "Snappable",
},
{
...defaultOptions,
input: "src/index.umd.ts",
output: "./dist/snappable.cjs.js",
format: "cjs",
exports: "default",
},
]);
38 changes: 38 additions & 0 deletions packages/snappable/src/BoundLine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { SnappableLine } from "./types";
import { solveConstantsOffset, solveLineConstants } from "./utils";


export class BoundLine {
private _constants!: [number, number, number];
constructor(public type: "up" | "down", public line: SnappableLine) {}
public get a() {
return this[0];
}
public get b() {
return this[1];
}
public get c() {
return this[2];
}
public get slope() {
return -this.a / this.b;
}
public get 0() {
return this.constants[0];
}
public get 1() {
return this.constants[1];
}
public get 2() {
return this.constants[2];
}
public get constants() {
if (!this._constants) {
this._constants = solveLineConstants(this.line);
}
return this._constants;
}
public getOffset(pos: number[]) {
return solveConstantsOffset(this.constants, pos);
}
}
32 changes: 32 additions & 0 deletions packages/snappable/src/Snappable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { BoundLine } from "./BoundLine";
import { SnappableBoundLine, SnappableLine } from "./types";
import { groupBy, solveConstantsOffset, solveLineConstants } from "./utils";

export class Snappable {
private _snaps: SnappableLine[] = [];
private _bounds: BoundLine[] = [];
private _innerBounds: SnappableLine[] = [];
constructor() {

}
public move(lines: SnappableLine[], dist: number[]) {

}
private _checkBounds(lines: SnappableLine[]) {
const bounds = this._bounds;


groupBy(bounds, boundLine => boundLine.slope).forEach(boundLines => {
boundLines.forEach(boundLine => {
const type = boundLine.type;
const isIncrease = type === "up"

lines.forEach(line => {
[line.point1, line.point2].forEach(point => {
const offset = boundLine.getOffset(point);
});
});
});
});
}
}
16 changes: 16 additions & 0 deletions packages/snappable/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface SnappableOptions {

}

export interface SnappableLine {
point1: number[];
point2: number[];
}

export interface SnappableBoundLine extends SnappableLine {
/**
* "up" if above or to the left of the line's slope,
* "down" if below or to the right of the line
*/
type: "up" | "down";
}
99 changes: 99 additions & 0 deletions packages/snappable/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { throttle } from "@daybrush/utils";
import { TINY_NUM } from "@daybrush/utils";
import { SnappableLine } from "./types";


export function groupBy<T>(arr: T[], func: (el: T, index: number, arr: T[]) => any) {
const groups: T[][] = [];
const groupKeys: any[] = [];

arr.forEach((el, index) => {
const groupKey = func(el, index, arr);
const keyIndex = groupKeys.indexOf(groupKey);
const group = groups[keyIndex] || [];

if (keyIndex === -1) {
groupKeys.push(groupKey);
groups.push(group);
}
group.push(el);
});
return groups;
}

export function solveLineConstants(line: SnappableLine): [number, number, number] {
const { point1, point2 } = line;
let dx = point2[0] - point1[0];
let dy = point2[1] - point1[1];

if (Math.abs(dx) < TINY_NUM) {
dx = 0;
}
if (Math.abs(dy) < TINY_NUM) {
dy = 0;
}

// b > 0
// ax + by + c = 0
let a = 0;
let b = 0;
let c = 0;

if (!dx) {
// -x + 1 = 0
a = -1;
c = point1[0];
} else if (!dy) {
// y - 1 = 0
b = 1;
c = -point1[1];
} else {
// y = -a(x - x1) + y1
// ax + y + a * x1 - y1 = 0
a = -dy / dx;
b = 1;
c = a * point1[0] - point1[1];
}

return [a, b, c].map(v => throttle(v, TINY_NUM)) as [number, number, number];
}
export function solveLineDistance(
line: SnappableLine,
pos: number[],
) {
return solveConstantsDistance(
solveLineConstants(line),
pos,
);
}

export function solveConstantsDistance(
[a, b, c]: [number, number, number],
pos: number[],
) {
return (a * pos[0] + b * pos[1] + c) / (a * a + b * b);
}
export function solveConstantsOffset(
[a, b, c]: [number, number, number],
[x, y]: number[],
) {
let offsetX = 0;
let offsetY = 0;

// ax + by + c

if (!a) {
// y = -c / b (by + c = 0)
offsetY = y + c / b;
} else if (!b) {
// x = -c / a (ax + c = 0)
offsetX = x + c / a;
} else {
// y = -a/bx - c / b
offsetY = y + a / b * x + c / b;
// x = -b/ay - c / a
offsetX = x + b / a * y + c / a;
}

return [offsetX, offsetY];
}
6 changes: 6 additions & 0 deletions packages/snappable/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"jsx": "react"
},
}
15 changes: 15 additions & 0 deletions packages/snappable/tsconfig.declaration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"allowJs": false,
"noEmit": false,
"isolatedModules": false,
"removeComments": false,
"declaration": true,
"emitDeclarationOnly": true,
"declarationDir": "declaration"
},
"include": [
"./src/**/*"
]
}
33 changes: 33 additions & 0 deletions packages/snappable/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"compilerOptions": {
"outDir": "./outjs/",
"esModuleInterop": false,
"sourceMap": true,
"module": "esnext",
"target": "es5",
"experimentalDecorators": true,
"skipLibCheck": true,
"moduleResolution": "node",
"jsx": "preserve",
"lib": [
"es2019",
"es2015",
"dom"
],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"strictNullChecks": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"baseUrl": ".",
},
"include": [
"./src/**/*.ts",
"./src/**/*.tsx",
"./test/**/*.ts",
"./test/**/*.tsx"
]
}

0 comments on commit c7bbd98

Please sign in to comment.