@figtreejs/core 0.0.1-alpha.1 → 0.0.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -8874
- package/dist/index.d.ts +18 -7
- package/dist/index.mjs +4215 -6421
- package/package.json +7 -4
- package/src/bauble-makers/set-up-baubles.ts +1 -1
- package/src/components/baubles/clades/highlight.tsx +1 -1
- package/src/components/decorations/axis/polar-axis.tsx +1 -1
- package/src/components/decorations/axis/rectangular-axis.tsx +1 -1
- package/src/components/figtree/figtree.tsx +1 -1
- package/src/components/hoc/with-node.tsx +1 -1
- package/src/evo/tree/normalized-tree/immutable-tree-helpers.ts +2 -2
- package/src/evo/tree/normalized-tree/immutable-tree.test.ts +1 -1
- package/src/evo/tree/normalized-tree/immutable-tree.ts +2 -2
- package/src/evo/tree/parsers/newick-character-parser.ts +1 -1
- package/src/evo/tree/parsers/parsing.test.ts +1 -1
- package/src/evo/tree/parsers/stream-reader/nexus-importer.ts +1 -1
- package/src/evo/tree/parsers/stream-reader/nexus-tokenizer.ts +1 -1
- package/src/evo/tree/taxa/helper-functions.ts +2 -2
- package/src/evo/tree/taxa/taxon.ts +1 -1
- package/src/index.ts +1 -1
- package/src/layouts/functional/radial-layout.ts +1 -1
- package/src/layouts/functional/rectangular-layout.ts +1 -1
- package/src/path.helpers.ts +76 -59
- package/src/tests/clades/cartoon.test.tsx +1 -1
- package/src/tests/clades/highlight.test.tsx +1 -1
- package/src/tests/layouts/rectangularlayout.test.ts +1 -1
- package/src/tests/shapes/label.test.tsx +1 -1
- package/src/utils/dateUtils.ts +41 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/maybe.ts +67 -0
- package/CHANGELOG.md +0 -17
- package/eslint.config.js +0 -9
- package/src/utils.ts +0 -57
- package/tsconfig.json +0 -12
- package/vite.config.ts +0 -34
- package/vitetest.config.ts +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@figtreejs/core",
|
|
3
|
-
"version": "0.0.1-
|
|
3
|
+
"version": "0.0.1-beta.0",
|
|
4
4
|
"description": "A react component library for phylogenetic visualization and app building",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"main": "./dist/index.cjs",
|
|
20
20
|
"module": "./dist/index.mjs",
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"./dist/*",
|
|
24
|
+
"./src/*"
|
|
25
|
+
],
|
|
22
26
|
"scripts": {
|
|
23
27
|
"build": "vite build",
|
|
24
28
|
"check-types": "tsc --noEmit",
|
|
@@ -37,7 +41,6 @@
|
|
|
37
41
|
]
|
|
38
42
|
},
|
|
39
43
|
"dependencies": {
|
|
40
|
-
"@figtreejs/maybe": "0.0.1-alpha.1",
|
|
41
44
|
"@react-spring/web": "^9.7.5",
|
|
42
45
|
"abs-svg-path": "^0.1.1",
|
|
43
46
|
"d3-array": "^3.2.4",
|
|
@@ -51,8 +54,8 @@
|
|
|
51
54
|
"uuid": "^13.0.0"
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
54
|
-
"@figtreejs/eslint-config": "
|
|
55
|
-
"@figtreejs/typescript-config": "
|
|
57
|
+
"@figtreejs/eslint-config": "*",
|
|
58
|
+
"@figtreejs/typescript-config": "*",
|
|
56
59
|
"@microsoft/api-extractor": "^7.55.1",
|
|
57
60
|
"@testing-library/react": "^16.3.0",
|
|
58
61
|
"@types/abs-svg-path": "^0.1.3",
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
} from "./makers";
|
|
23
23
|
import { mapAttrsToProps, mapInteractionsToProps } from "./utils";
|
|
24
24
|
import type { Clade } from "../components/hoc/with-clades";
|
|
25
|
-
import { notNull } from "../utils";
|
|
25
|
+
import { notNull } from "../utils/maybe";
|
|
26
26
|
|
|
27
27
|
export type InternalBaubleOptions =
|
|
28
28
|
| InternalNodeOptions
|
|
@@ -5,7 +5,7 @@ import { withClades } from "../../hoc/with-clades";
|
|
|
5
5
|
|
|
6
6
|
import { BasePath, BaseRectangle } from "../shapes";
|
|
7
7
|
import type { PolarVertex, simplePolarVertex } from "../../../layouts/types";
|
|
8
|
-
import { notNull } from "../../../utils";
|
|
8
|
+
import { notNull } from "../../../utils/maybe";
|
|
9
9
|
import { ScaleContext } from "../../../context/scale-context";
|
|
10
10
|
import { layoutContext } from "../../../context/layout-context";
|
|
11
11
|
import { animatedContext } from "../../../context/aminated-context";
|
|
@@ -7,7 +7,7 @@ import { defaultAxisProps } from "./axis-types";
|
|
|
7
7
|
|
|
8
8
|
import { normalizeAngle } from "../../../store/polar-scale";
|
|
9
9
|
import type { dimensionType } from "../../figtree/figtree-types";
|
|
10
|
-
import { unNullify } from "../../../utils";
|
|
10
|
+
import { unNullify } from "../../../utils/maybe";
|
|
11
11
|
import { DimensionContext } from "../../../context/dimension-context";
|
|
12
12
|
import { ScaleContext } from "../../../context/scale-context";
|
|
13
13
|
import PolarAxisBars from "./polar-axis-bars";
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
} from "./axis-types";
|
|
10
10
|
import { defaultAxisProps } from "./axis-types";
|
|
11
11
|
import { makeAxisScale } from "./polar-axis";
|
|
12
|
-
import { unNullify } from "../../../utils";
|
|
12
|
+
import { unNullify } from "../../../utils/maybe";
|
|
13
13
|
import { DimensionContext } from "../../../context/dimension-context";
|
|
14
14
|
import { ScaleContext } from "../../../context/scale-context";
|
|
15
15
|
import RectangleAxisBars from "./rectangular-axis-bars";
|
|
@@ -4,7 +4,7 @@ import { defaultInternalLayoutOptions, rectangularLayout } from "../../layouts";
|
|
|
4
4
|
import { ImmutableTree } from "../../evo/tree";
|
|
5
5
|
import { getScale } from "../../store/store";
|
|
6
6
|
import { extent } from "d3-array";
|
|
7
|
-
import { unNullify } from "../../utils";
|
|
7
|
+
import { unNullify } from "../../utils/maybe";
|
|
8
8
|
import { Bauble } from "../baubles/bauble";
|
|
9
9
|
|
|
10
10
|
import { ScaleContext } from "../../context/scale-context";
|
|
@@ -8,7 +8,7 @@ import { layoutClass } from "../../layouts";
|
|
|
8
8
|
import { defaultNodeLabelData } from "../../store/store";
|
|
9
9
|
import type { PolarVertex } from "../../layouts/types";
|
|
10
10
|
import { textSafeDegrees } from "../../store/polar-scale";
|
|
11
|
-
import { unNullify } from "../../utils";
|
|
11
|
+
import { unNullify } from "../../utils/maybe";
|
|
12
12
|
|
|
13
13
|
//The goal here is now to take a shape components that accepts Attrs: number | string , x/y
|
|
14
14
|
// and return a component that takes a node / layout/ scale and attrs:number|string | function
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* those can't be called by immer proxies.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type { Maybe, Undefinable } from "
|
|
10
|
-
import {
|
|
9
|
+
import type { Maybe, Undefinable } from "../../../utils";
|
|
10
|
+
import { Nothing, Some, MaybeType } from "../../../utils";
|
|
11
11
|
import type { Annotation, NodeRef } from "../tree-types";
|
|
12
12
|
import type { ImmutableTree, nodeIndex, Node } from "./immutable-tree";
|
|
13
13
|
import type { Taxon } from "../taxa";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//TODO test immutable tree include tests that check nodes to roots update as well.
|
|
2
2
|
|
|
3
|
-
import { notNull, u } from "../../../utils";
|
|
3
|
+
import { notNull, u } from "../../../utils/maybe";
|
|
4
4
|
import { ImmutableTree } from "./immutable-tree";
|
|
5
5
|
import { describe, it, expect } from "vitest";
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
type Undefinable,
|
|
29
29
|
UnwrapErr,
|
|
30
30
|
type Maybe,
|
|
31
|
-
} from "
|
|
31
|
+
} from "../../../utils";
|
|
32
32
|
import {
|
|
33
33
|
maybeGetAnnotation,
|
|
34
34
|
maybeGetNode,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
maybeGetTaxon,
|
|
38
38
|
maybeGetTaxonFromNode,
|
|
39
39
|
} from "./immutable-tree-helpers";
|
|
40
|
-
import { notNull, unNullify } from "../../../utils";
|
|
40
|
+
import { notNull, unNullify } from "../../../utils/maybe";
|
|
41
41
|
import { v4 as uuidv4 } from "uuid";
|
|
42
42
|
|
|
43
43
|
export type nodeIndex = string | number | Taxon;
|
|
@@ -3,7 +3,7 @@ import { TaxonSet } from "../taxa/taxon";
|
|
|
3
3
|
import type { NodeRef } from "../tree-types";
|
|
4
4
|
import { ImmutableTree } from "../normalized-tree/immutable-tree";
|
|
5
5
|
import { parseAnnotation } from "./annotation-parser";
|
|
6
|
-
import { notNull, unNullify } from "../../../utils";
|
|
6
|
+
import { notNull, unNullify } from "../../../utils/maybe";
|
|
7
7
|
|
|
8
8
|
export class NewickCharacterParser {
|
|
9
9
|
done: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Maybe, Undefinable } from "
|
|
2
|
-
import { Nothing, Some, MaybeType } from "
|
|
1
|
+
import type { Maybe, Undefinable } from "../../../utils";
|
|
2
|
+
import { Nothing, Some, MaybeType } from "../../../utils";
|
|
3
3
|
import type { Taxon, TaxonSetData } from "./taxon";
|
|
4
4
|
|
|
5
5
|
export function maybeGetNameFromIndex(
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type { ImmutableTree, NodeRef } from "../../evo";
|
|
4
4
|
import { preOrderIterator, tipIterator } from "../../evo";
|
|
5
5
|
import type { NodeLabelType } from "../types";
|
|
6
|
-
import { notNull } from "../../utils";
|
|
6
|
+
import { notNull } from "../../utils/maybe";
|
|
7
7
|
import type { FunctionalVertex } from "../types";
|
|
8
8
|
import { layoutClass } from "../types";
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ import type { ImmutableTree, NodeRef } from "../../evo";
|
|
|
3
3
|
import { postOrderIterator } from "../../evo";
|
|
4
4
|
import type { NodeLabelType, FunctionalVertex } from "../types";
|
|
5
5
|
import { layoutClass } from "../types";
|
|
6
|
-
import { unNullify } from "../../utils";
|
|
6
|
+
import { unNullify } from "../../utils/maybe";
|
|
7
7
|
|
|
8
8
|
export function baseLayout(lc: layoutClass) {
|
|
9
9
|
function layout(tree: ImmutableTree): (node: NodeRef) => FunctionalVertex {
|
package/src/path.helpers.ts
CHANGED
|
@@ -6,76 +6,93 @@
|
|
|
6
6
|
|
|
7
7
|
// curve splitting by https://pomax.github.io/bezierinfo/#introduction
|
|
8
8
|
|
|
9
|
-
import abs from
|
|
10
|
-
import normalize from
|
|
11
|
-
import parse from
|
|
12
|
-
import type { NormalizedCommand } from
|
|
13
|
-
import { unNullify } from
|
|
9
|
+
import abs from "abs-svg-path";
|
|
10
|
+
import normalize from "normalize-svg-path";
|
|
11
|
+
import parse from "parse-svg-path";
|
|
12
|
+
import type { NormalizedCommand } from "./@custom-types/svg-path-types";
|
|
13
|
+
import { unNullify } from "./utils/maybe";
|
|
14
14
|
|
|
15
|
-
class point{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
class point {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
constructor(x: number, y: number) {
|
|
19
|
+
this.x = x;
|
|
20
|
+
this.y = y;
|
|
21
|
+
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const NUMBER_OF_POINTS=6; // this should be more than needed by layouts
|
|
24
|
+
const NUMBER_OF_POINTS = 6; // this should be more than needed by layouts
|
|
25
25
|
type curveArray = [string, number, number, number, number, number, number];
|
|
26
|
-
export function normalizePath(path:string):string{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
export function normalizePath(path: string): string {
|
|
27
|
+
//TODO this might remove the fill on cartoons.
|
|
28
|
+
const parsedPath = parse(path); //as AnyCommand[]
|
|
29
|
+
const absPath = abs(parsedPath);
|
|
30
|
+
const normalizedPath = normalize(absPath); // normalized path is [M, x,y ] [C, x1,y1, x2,y2, x,y]....
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
let newPath = `${normalizedPath[0][0]} ${normalizedPath[0][1]} ${normalizedPath[0][2]} `;
|
|
33
|
+
const curves = normalizedPath
|
|
34
|
+
.filter((d: NormalizedCommand) => d[0] === "C")
|
|
35
|
+
.map((curve: curveArray) => {
|
|
36
|
+
return [
|
|
37
|
+
new point(curve[1], curve[2]),
|
|
38
|
+
new point(curve[3], curve[4]),
|
|
39
|
+
new point(curve[5], curve[6]),
|
|
40
|
+
];
|
|
41
|
+
});
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
if (curves.length > NUMBER_OF_POINTS) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Path must have no more than ${NUMBER_OF_POINTS} nodes (excluding start point) detected ${curves.length} nodes update layout or path.helpers`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
if (curves.length == 0) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
"Path must have at least 1 node (excluding start point) update layout or path.helpers",
|
|
51
|
+
);
|
|
52
|
+
}
|
|
40
53
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
while (curves.length < NUMBER_OF_POINTS) {
|
|
55
|
+
const toSplit = unNullify(curves.pop(), `Internal error in normalization`);
|
|
56
|
+
const { left, right } = splitCubicB(toSplit, 0.5);
|
|
57
|
+
curves.push(left);
|
|
58
|
+
curves.push(right.reverse());
|
|
59
|
+
}
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
for (let i = 0; i < curves.length; i++) {
|
|
62
|
+
const curve = curves[i];
|
|
63
|
+
newPath += `C${curve[0].x},${curve[0].y} ${curve[1].x},${curve[1].y} ${curve[2].x},${curve[2].y} `;
|
|
64
|
+
}
|
|
65
|
+
return newPath;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
|
-
function splitCubicB(
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
function splitCubicB(
|
|
69
|
+
curve: point[],
|
|
70
|
+
t: number,
|
|
71
|
+
): { left: point[]; right: point[] } {
|
|
72
|
+
const left: point[] = [];
|
|
73
|
+
const right: point[] = [];
|
|
58
74
|
|
|
59
|
-
function getCurve(points:point[],t:number){
|
|
60
|
-
if(points.length==1){
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}else{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
if(i==newPoints.length-1){
|
|
70
|
-
right.push(points[i+1])
|
|
71
|
-
}
|
|
72
|
-
newPoints[i]=new point((1-t)*points[i].x+t*points[i+1].x,(1-t)*points[i].y+t*points[i+1].y)
|
|
75
|
+
function getCurve(points: point[], t: number) {
|
|
76
|
+
if (points.length == 1) {
|
|
77
|
+
left.push(points[0]);
|
|
78
|
+
right.push(points[0]);
|
|
79
|
+
} else {
|
|
80
|
+
const newPoints: point[] = Array(points.length - 1) as point[];
|
|
81
|
+
for (let i = 0; i < newPoints.length; i++) {
|
|
82
|
+
if (i == 0) {
|
|
83
|
+
left.push(points[0]);
|
|
73
84
|
}
|
|
74
|
-
|
|
85
|
+
if (i == newPoints.length - 1) {
|
|
86
|
+
right.push(points[i + 1]);
|
|
87
|
+
}
|
|
88
|
+
newPoints[i] = new point(
|
|
89
|
+
(1 - t) * points[i].x + t * points[i + 1].x,
|
|
90
|
+
(1 - t) * points[i].y + t * points[i + 1].y,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
getCurve(newPoints, t);
|
|
75
94
|
}
|
|
95
|
+
}
|
|
96
|
+
getCurve(curve, t);
|
|
97
|
+
return { left, right };
|
|
76
98
|
}
|
|
77
|
-
getCurve(curve,t);
|
|
78
|
-
return {left,right}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
@@ -2,7 +2,7 @@ import { render } from "@testing-library/react";
|
|
|
2
2
|
import { ImmutableTree } from "../../evo";
|
|
3
3
|
import { FigTree } from "../../components";
|
|
4
4
|
import { polarLayout, rectangularLayout } from "../../layouts";
|
|
5
|
-
import { u } from "../../utils";
|
|
5
|
+
import { u } from "../../utils/maybe";
|
|
6
6
|
import { Branches, CartoonClades } from "../../bauble-makers/makers";
|
|
7
7
|
|
|
8
8
|
const tree = ImmutableTree.fromNewick("((A:1,B:1):2,C:1);");
|
|
@@ -3,7 +3,7 @@ import { ImmutableTree } from "../../evo";
|
|
|
3
3
|
import { FigTree } from "../../components";
|
|
4
4
|
import { polarLayout, rectangularLayout } from "../../layouts";
|
|
5
5
|
|
|
6
|
-
import { u } from "../../utils";
|
|
6
|
+
import { u } from "../../utils/maybe";
|
|
7
7
|
import { Branches, HighlightClades } from "../../bauble-makers/makers";
|
|
8
8
|
|
|
9
9
|
const tree = ImmutableTree.fromNewick("((A:1,B:1):2,C:1);");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { ImmutableTree } from "../../evo";
|
|
3
3
|
import { rectangularLayout } from "../../layouts";
|
|
4
|
-
import { u } from "../../utils";
|
|
4
|
+
import { u } from "../../utils/maybe";
|
|
5
5
|
|
|
6
6
|
describe("Test rectangular layout", () => {
|
|
7
7
|
it("check x and y on root", function () {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
2
|
import { render, screen } from "@testing-library/react";
|
|
3
3
|
import { BaseLabel } from "../../components/baubles/shapes/label";
|
|
4
|
-
import { unNullify } from "../../utils";
|
|
4
|
+
import { unNullify } from "../../utils/maybe";
|
|
5
5
|
|
|
6
6
|
describe("BaseLabel", () => {
|
|
7
7
|
test("renders an SVG text element that uses transform to position", () => {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { timeParse, timeFormat } from "d3-time-format";
|
|
2
|
+
import { unNullify } from "./maybe";
|
|
3
|
+
|
|
4
|
+
//https://stackoverflow.com/questions/29400171/how-do-i-convert-a-decimal-year-value-into-a-date-in-javascript
|
|
5
|
+
/**
|
|
6
|
+
* Helper function to determine if the provided year is a leap year
|
|
7
|
+
* @param year
|
|
8
|
+
* @return {boolean}
|
|
9
|
+
*/
|
|
10
|
+
export function leapYear(year: number): boolean {
|
|
11
|
+
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A function which converts a decimal float into a date object
|
|
16
|
+
* @param decimalDate
|
|
17
|
+
* @return {Date}
|
|
18
|
+
*/
|
|
19
|
+
export function decimalToDate(decimal: number): Date {
|
|
20
|
+
const year = Math.trunc(decimal);
|
|
21
|
+
const totalNumberOfDays = leapYear(year) ? 366 : 365;
|
|
22
|
+
const day = Math.round((decimal - year) * totalNumberOfDays);
|
|
23
|
+
const date = timeParse("%Y-%j")(`${year}-${day}`);
|
|
24
|
+
// notNull(date,`Could not convert ${decimal} to date tried (year:${year} - day: ${day})`)
|
|
25
|
+
return unNullify(
|
|
26
|
+
date,
|
|
27
|
+
`Could not convert ${decimal} to date tried (year:${year} - day: ${day})`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A function that converts a date into a decimal.
|
|
33
|
+
* @param date
|
|
34
|
+
* @return {number}
|
|
35
|
+
*/
|
|
36
|
+
export function dateToDecimal(date: Date) {
|
|
37
|
+
const year = parseInt(timeFormat("%Y")(date));
|
|
38
|
+
const day = parseInt(timeFormat("%j")(date));
|
|
39
|
+
const totalNumberOfDays = leapYear(year) ? 366 : 365;
|
|
40
|
+
return year + day / totalNumberOfDays;
|
|
41
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// types to avoid always checking for null values
|
|
2
|
+
|
|
3
|
+
//https://engineering.dollarshaveclub.com/typescript-maybe-type-and-module-627506ecc5c8#950b
|
|
4
|
+
export enum MaybeType {
|
|
5
|
+
Some = "some",
|
|
6
|
+
Nothing = "nothing",
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type Some<T> = {
|
|
10
|
+
type: typeof MaybeType.Some;
|
|
11
|
+
value: T;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Nothing = {
|
|
15
|
+
type: typeof MaybeType.Nothing;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type Maybe<T> = Some<T> | Nothing;
|
|
19
|
+
|
|
20
|
+
export const Nothing = (): Nothing => ({
|
|
21
|
+
type: MaybeType.Nothing,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const Some = <T>(value: T): Some<T> => ({
|
|
25
|
+
type: MaybeType.Some,
|
|
26
|
+
value,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const UnwrapErr = <T>(v: Maybe<T>, message: string): T => {
|
|
30
|
+
switch (v.type) {
|
|
31
|
+
case MaybeType.Some:
|
|
32
|
+
return v.value;
|
|
33
|
+
case MaybeType.Nothing:
|
|
34
|
+
throw new Error(message);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const UnwrapOr = <T>(v: Maybe<T>, d: T): T => {
|
|
39
|
+
switch (v.type) {
|
|
40
|
+
case MaybeType.Some:
|
|
41
|
+
return v.value;
|
|
42
|
+
case MaybeType.Nothing:
|
|
43
|
+
return d;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// A helper type so we can appease the linters and check some accesses for undefined without having to check them all.
|
|
47
|
+
export type Undefinable<T> = T | undefined;
|
|
48
|
+
|
|
49
|
+
export function panic(message: string): never {
|
|
50
|
+
throw new Error(message);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function u<T>(x: T | undefined): NonNullable<T> {
|
|
54
|
+
if (x === undefined) {
|
|
55
|
+
throw new Error("internal bug! unhandled undefined");
|
|
56
|
+
}
|
|
57
|
+
return x as NonNullable<T>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function notNull<T>(x: T, message: string): asserts x is NonNullable<T> {
|
|
61
|
+
if (x === undefined) throw new Error(message);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function unNullify<T>(x: T, message: string): NonNullable<T> {
|
|
65
|
+
if (x === null) throw new Error(message);
|
|
66
|
+
return x as NonNullable<T>;
|
|
67
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# @figtreejs/core
|
|
2
|
-
|
|
3
|
-
## 0.0.1-alpha.1
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- includes dist files for publication
|
|
8
|
-
- Updated dependencies
|
|
9
|
-
- @figtreejs/maybe@0.0.1-alpha.1
|
|
10
|
-
|
|
11
|
-
## 0.0.1-alpha.0
|
|
12
|
-
|
|
13
|
-
### Patch Changes
|
|
14
|
-
|
|
15
|
-
- This version marks the initial version of several packages, and the start of a new developement system
|
|
16
|
-
- Updated dependencies
|
|
17
|
-
- @figtreejs/maybe@0.0.1-alpha.0
|
package/eslint.config.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "eslint/config";
|
|
2
|
-
import defaultConfig from "@figtreejs/eslint-config";
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
"extends": [defaultConfig],
|
|
6
|
-
"rules":{
|
|
7
|
-
"@typescript-eslint/restrict-template-expressions": ["error", { allowNumber: true }]
|
|
8
|
-
}
|
|
9
|
-
})
|
package/src/utils.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {timeParse, timeFormat} from "d3-time-format";
|
|
2
|
-
|
|
3
|
-
//https://stackoverflow.com/questions/29400171/how-do-i-convert-a-decimal-year-value-into-a-date-in-javascript
|
|
4
|
-
/**
|
|
5
|
-
* Helper function to determine if the provided year is a leap year
|
|
6
|
-
* @param year
|
|
7
|
-
* @return {boolean}
|
|
8
|
-
*/
|
|
9
|
-
export function leapYear(year:number):boolean {
|
|
10
|
-
return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A function which converts a decimal float into a date object
|
|
15
|
-
* @param decimalDate
|
|
16
|
-
* @return {Date}
|
|
17
|
-
*/
|
|
18
|
-
export function decimalToDate(decimal:number):Date{
|
|
19
|
-
const year = Math.trunc(decimal);
|
|
20
|
-
const totalNumberOfDays = leapYear(year)? 366:365;
|
|
21
|
-
const day = Math.round(((decimal-year)*totalNumberOfDays));
|
|
22
|
-
const date = timeParse("%Y-%j")(`${year}-${day}`)
|
|
23
|
-
// notNull(date,`Could not convert ${decimal} to date tried (year:${year} - day: ${day})`)
|
|
24
|
-
return unNullify(date,`Could not convert ${decimal} to date tried (year:${year} - day: ${day})`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A function that converts a date into a decimal.
|
|
29
|
-
* @param date
|
|
30
|
-
* @return {number}
|
|
31
|
-
*/
|
|
32
|
-
export function dateToDecimal(date:Date){
|
|
33
|
-
const year = parseInt(timeFormat("%Y")(date));
|
|
34
|
-
const day = parseInt(timeFormat("%j")(date));
|
|
35
|
-
const totalNumberOfDays = leapYear(year)? 366:365;
|
|
36
|
-
return year+day/totalNumberOfDays
|
|
37
|
-
}
|
|
38
|
-
export function panic(message: string): never { throw new Error(message); }
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export function u<T>(x: T | undefined): NonNullable<T> {
|
|
42
|
-
if (x === undefined) {
|
|
43
|
-
throw new Error('internal bug! unhandled undefined');
|
|
44
|
-
}
|
|
45
|
-
return x as NonNullable<T>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export function notNull<T>(x: T,message:string): asserts x is NonNullable<T> {
|
|
50
|
-
if (x === undefined) throw new Error(message);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function unNullify<T>(x: T,message:string): NonNullable<T> {
|
|
54
|
-
if (x === null) throw new Error(message);
|
|
55
|
-
return x as NonNullable<T>
|
|
56
|
-
}
|
|
57
|
-
|
package/tsconfig.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@figtreejs/typescript-config/vite.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"noEmit": true,
|
|
6
|
-
"noUncheckedIndexedAccess": false,
|
|
7
|
-
"jsx": "react-jsx",
|
|
8
|
-
"types": ["vitest/globals"], // gives types for describe/test/expect
|
|
9
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"] // DOM types for `document`
|
|
10
|
-
},
|
|
11
|
-
"include": ["src/**/*.ts", "src/**/*.tsx", "*.js", "*.ts"] // /src files and config files
|
|
12
|
-
}
|