├── .gitignore
├── README.md
├── build.sbt
├── project
├── build.properties
└── build.sbt
└── src
└── main
└── scala
└── paths
├── high
├── Bar.scala
├── Graph.scala
├── Pie.scala
├── Radar.scala
├── Sankey.scala
├── SmoothLine.scala
├── Stack.scala
├── Stock.scala
├── Tree.scala
├── Voronoi.scala
└── Waterfall.scala
├── low
└── Path.scala
├── mid
├── Bezier.scala
├── Connector.scala
├── CurvedRectangle.scala
├── Polygon.scala
├── Rectangle.scala
├── Sector.scala
├── SemiRegularPolygon.scala
└── Shape.scala
├── misc
└── Linear.scala
└── paths.scala
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .cache
3 | .classpath
4 | .project
5 | .settings/
6 | .idea/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Paths.scala.js
2 | ==============
3 |
4 | [Paths.js](https://github.com/andreaferretti/paths-js) is a library to generate [SVG paths](http://www.w3.org/TR/SVG/paths.html), allowing you to create your own charts using a functional and testable API. Paths.scala.js is the binding of Paths.js for [Scala.js](http://www.scala-js.org/).
5 |
6 | Documentation
7 | -------------
8 |
9 | The usage of Paths.scala.js is mostly similar to its parent library. You can
10 |
11 | - browse the [documentation of Paths.js](https://github.com/andreaferretti/paths-js/wiki)
12 | - explore the [Scaladocs API](http://andreaferretti.github.io/paths-scala-js)
13 | - see an [example application](https://github.com/andreaferretti/paths-scala-js-demo) ([live demo](http://andreaferretti.github.io/paths-scala-js-demo/))
14 |
15 | The demo application is still incomplete, and fails to show many of Paths.scala.js features. The [Paths.js demo](http://andreaferretti.github.io/paths-js-demo/) better showcases what can be done.
16 |
17 | Usage
18 | -----
19 |
20 | Paths.scala.js is published for Scala 2.11 and Scala 2.12 with Scala.js 0.6. In a Scala.js project, you can depend on Paths.scala.js with
21 |
22 | libraryDependencies += "eu.unicredit" %%% "paths-scala-js" % "0.4.5"
23 |
24 | Compatibility
25 | -------------
26 |
27 | Paths.scala.js is meant to have an API that is exactly equivalent to its parent library. The only exception is in the `Graph` and `Sankey` charts, where instead of accepting a parameter `data` with `nodes` and `links` fields, the Scala.js API directly requires `nodes` and `links` parameters. This removes one level of nesting and eliminates the need for structural typing in this particular case.
28 |
29 | Please, file any other incompatibility between Paths.js and Paths.scala.js as an issue.
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | // Turn this project into a Scala.js project by importing these settings
2 | enablePlugins(ScalaJSPlugin)
3 |
4 | organization := "eu.unicredit"
5 |
6 | name := "paths-scala-js"
7 |
8 | version := "0.4.5"
9 |
10 | scalaVersion := "2.12.4"
11 |
12 | crossScalaVersions := Seq("2.11.7", "2.12.4")
13 |
14 | scalaJSUseMainModuleInitializer in Compile := true
15 |
16 | scalaJSUseMainModuleInitializer in Test := false
17 |
18 | testFrameworks += new TestFramework("utest.runner.Framework")
19 |
20 | jsDependencies += "org.webjars.bower" % "paths-js" % "0.4.5" / "paths.js"
21 |
22 | skip in packageJSDependencies := false
23 |
24 | scalacOptions ++= Seq(
25 | "-feature",
26 | "-deprecation",
27 | "-language:reflectiveCalls"
28 | )
29 |
30 | publishMavenStyle := true
31 |
32 | pomIncludeRepository := { x => false }
33 |
34 | publishTo := sonatypePublishTo.value
35 |
36 | credentials += Credentials(Path.userHome / ".ivy2" / "sonatype.credentials")
37 |
38 | pomExtra := {
39 | https://github.com/andreaferretti/paths-scala-js
40 |
41 |
42 | Apache 2
43 | http://www.apache.org/licenses/LICENSE-2.0.txt
44 |
45 |
46 |
47 | scm:git:github.com/andreaferretti/paths-scala-js
48 | scm:git:git@github.com:andreaferretti/paths-scala-js
49 | github.com/andreaferretti/paths-scala-js
50 |
51 |
52 |
53 | andreaferretti
54 | Andrea Ferretti
55 | https://github.com/andreaferretti/
56 |
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.17
2 |
--------------------------------------------------------------------------------
/project/build.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.22")
2 |
3 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3")
4 |
5 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Bar.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Rectangle
9 | import misc.Linear
10 |
11 | @js.native
12 | trait BarOpts[A] extends js.Object {
13 | val data: js.Array[js.Array[A]] = js.native
14 | val accessor: js.Function1[A, Double] = js.native
15 | val width: Int = js.native
16 | val height: Int = js.native
17 | val gutter: Int = js.native
18 | val offset: js.Array[Double] = js.native
19 | }
20 |
21 | object BarOpts {
22 | def apply[A](data: js.Array[js.Array[A]], accessor: js.Function1[A, Double],
23 | width: Int, height: Int, gutter: Int, offset: js.Array[Double]): BarOpts[A] =
24 | js.Dynamic.literal(
25 | data = data,
26 | accessor = accessor,
27 | width = width,
28 | height = height,
29 | gutter = gutter,
30 | offset = offset
31 | ).asInstanceOf[BarOpts[A]]
32 | }
33 |
34 | @js.native
35 | @JSName("Paths.Bar")
36 | object BarNative extends js.Object {
37 | def apply[A](options: BarOpts[A]): Bar[A] = js.native
38 | }
39 |
40 | @js.native
41 | trait BarCurve[A] extends js.Object {
42 | val line: Rectangle = js.native
43 | val item: A = js.native
44 | val index: Int = js.native
45 | val group: Int = js.native
46 | }
47 |
48 | @js.native
49 | trait Bar[A] extends js.Object {
50 | val curves: js.Array[BarCurve[A]] = js.native
51 | val scale: Linear = js.native
52 | }
53 |
54 | object Bar {
55 | def apply[A](data: Seq[Seq[A]], accessor: A => Double, width: Int, height: Int, gutter: Int, offset: (Double, Double) = (0, 0)) = {
56 | val d = data.toJSArray.map(_.toJSArray)
57 | BarNative(BarOpts(d, accessor, width, height, gutter, tuple2point(offset)))
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Graph.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Polygon
9 |
10 |
11 | @js.native
12 | trait GraphData[V, E] extends js.Object {
13 | val nodes: js.Array[V] = js.native
14 | val links: js.Array[E] = js.native
15 | }
16 |
17 | @js.native
18 | trait GraphEdge extends js.Object {
19 | val start: String = js.native
20 | val end: String = js.native
21 | val weight: Double = js.native
22 | }
23 |
24 | @js.native
25 | trait GraphOpts[V, E] extends js.Object {
26 | val data: GraphData[V, E] = js.native
27 | val nodeaccessor: js.Function1[V, String] = js.native
28 | val linkaccessor: js.Function1[E, GraphEdge] = js.native
29 | val width: Int = js.native
30 | val height: Int = js.native
31 | val attraction: js.UndefOr[Double] = js.native
32 | val repulsion: js.UndefOr[Double] = js.native
33 | val threshold: js.UndefOr[Double] = js.native
34 | }
35 |
36 | object GraphOpts {
37 | def apply[V, E](data: GraphData[V, E], nodeaccessor: js.Function1[V, String],
38 | linkaccessor: js.Function1[E, GraphEdge], width: Int, height: Int,
39 | attraction: Double = 1, repulsion: Double = 1, threshold: Double = 0.5): GraphOpts[V, E] =
40 | js.Dynamic.literal(
41 | data = data,
42 | nodeaccessor = nodeaccessor,
43 | linkaccessor = linkaccessor,
44 | width = width,
45 | height = height,
46 | attraction = attraction,
47 | repulsion = repulsion,
48 | threshold = threshold
49 | ).asInstanceOf[GraphOpts[V, E]]
50 | }
51 |
52 | @js.native
53 | @JSName("Paths.Graph")
54 | object GraphNative extends js.Object {
55 | def apply[V, E](options: GraphOpts[V, E]): Graph[V, E] = js.native
56 | }
57 |
58 | @js.native
59 | trait GraphCurve[E] extends js.Object {
60 | val link: Polygon = js.native
61 | val item: E = js.native
62 | val index: Int = js.native
63 | }
64 |
65 | @js.native
66 | trait GraphNode[V] extends js.Object {
67 | val point: Point = js.native
68 | val item: V = js.native
69 | }
70 |
71 | @js.native
72 | trait Graph[V, E] extends js.Object {
73 | var curves: js.Array[GraphCurve[E]] = js.native
74 | var nodes: js.Array[GraphNode[V]] = js.native
75 | def tick(): Graph[V, E] = js.native
76 | def constrain(id: String, coordinates: Point): Unit = js.native
77 | def unconstrain(id: String): Unit = js.native
78 | }
79 |
80 | object Graph {
81 | type GraphScalaEdge = { def start: String; def end: String; def weight: Double }
82 |
83 | def apply[V, E](nodes: Seq[V], links: Seq[E], nodeaccessor: V => String, linkaccessor: E => GraphScalaEdge,
84 | width: Int, height: Int, attraction: Double = 1, repulsion: Double = 1, threshold: Double = 0.5) = {
85 |
86 | def dynamic(e: GraphScalaEdge): GraphEdge = js.Dynamic.literal(
87 | start = e.start,
88 | end = e.end,
89 | weight = e.weight
90 | ).asInstanceOf[GraphEdge]
91 |
92 | val data = js.Dynamic.literal(
93 | nodes = nodes.toJSArray,
94 | links = links.toJSArray
95 | ).asInstanceOf[GraphData[V, E]]
96 |
97 | GraphNative(GraphOpts(data, nodeaccessor, linkaccessor.andThen(dynamic),
98 | width, height, attraction, repulsion, threshold))
99 | }
100 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Pie.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Sector
9 |
10 |
11 | @js.native
12 | trait PieOpts[A] extends js.Object {
13 | val data: js.Array[A] = js.native
14 | val accessor: js.Function1[A, Double] = js.native
15 | val center: Point = js.native
16 | val r: Double = js.native
17 | val R: Double = js.native
18 | }
19 |
20 | object PieOpts {
21 | def apply[A](data: js.Array[A], accessor: js.Function1[A, Double],
22 | center: Point, r: Double, R: Double): PieOpts[A] =
23 | js.Dynamic.literal(
24 | data = data,
25 | accessor = accessor,
26 | center = center,
27 | r = r,
28 | R = R
29 | ).asInstanceOf[PieOpts[A]]
30 | }
31 |
32 | @js.native
33 | @JSName("Paths.Pie")
34 | object PieNative extends js.Object {
35 | def apply[A](options: PieOpts[A]): Pie[A] = js.native
36 | }
37 |
38 | @js.native
39 | trait PieCurve[A] extends js.Object {
40 | val sector: Sector = js.native
41 | val item: A = js.native
42 | val index: Int = js.native
43 | }
44 |
45 | @js.native
46 | trait Pie[A] extends js.Object {
47 | val curves: js.Array[PieCurve[A]] = js.native
48 | }
49 |
50 | object Pie {
51 | def apply[A](data: Seq[A], accessor: A => Double, center: (Double, Double), r: Double, R: Double) = {
52 | val (x, y) = center
53 | PieNative(PieOpts(data.toJSArray, accessor, js.Array(x, y), r, R))
54 | }
55 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Radar.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.{ Shape, SemiRegularPolygon }
9 |
10 |
11 | @js.native
12 | trait RadarOpts[A] extends js.Object {
13 | val data: js.Array[A] = js.native
14 | val accessor: Map[String, js.Function1[A, Double]] = js.native
15 | val max: js.UndefOr[Double] = js.native
16 | val center: Point = js.native
17 | val r: Double = js.native
18 | val rings: Int = js.native
19 | }
20 |
21 | object RadarOpts {
22 | def apply[A](data: js.Array[A], accessor: js.Dictionary[js.Function1[A, Double]],
23 | max: js.UndefOr[Double], center: Point, r: Double, rings: Int = 3): RadarOpts[A] =
24 | js.Dynamic.literal(
25 | data = data,
26 | accessor = accessor,
27 | max = max,
28 | center = center,
29 | r = r,
30 | rings = rings
31 | ).asInstanceOf[RadarOpts[A]]
32 | }
33 |
34 | @js.native
35 | @JSName("Paths.Radar")
36 | object RadarNative extends js.Object {
37 | def apply[A](options: RadarOpts[A]): Radar[A] = js.native
38 | }
39 |
40 | @js.native
41 | trait RadarCurve[A] extends js.Object {
42 | val polygon: SemiRegularPolygon = js.native
43 | val item: A = js.native
44 | val index: Int = js.native
45 | }
46 |
47 | @js.native
48 | trait Radar[A] extends js.Object {
49 | val curves: js.Array[RadarCurve[A]] = js.native
50 | val rings: js.Array[Shape] = js.native
51 | }
52 |
53 | object Radar {
54 | def apply[A](data: Seq[A], accessor: Map[String, A => Double], max: Option[Double] = None,
55 | center: (Double, Double), r: Double, rings: Int = 3) = {
56 | // val d = data.toJSArray.asInstanceOf[js.Array[Any]]
57 | // val acc = accessor mapValues { f => (x: Any) => f(x.asInstanceOf[A]) }
58 | val acc: Map[String, js.Function1[A, Double]] = accessor mapValues { x => x }
59 | val (x, y) = center
60 | RadarNative(RadarOpts(data.toJSArray, acc.toJSDictionary, max.orUndefined, js.Array(x, y), r, rings))
61 | }
62 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Sankey.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.{ CurvedRectangle, Rectangle }
9 |
10 |
11 | @js.native
12 | trait SankeyData[V, E] extends js.Object {
13 | val nodes: js.Array[js.Array[V]] = js.native
14 | val links: js.Array[E] = js.native
15 | }
16 |
17 | @js.native
18 | trait SankeyEdge extends js.Object {
19 | val start: String = js.native
20 | val end: String = js.native
21 | val weight: Double = js.native
22 | }
23 |
24 | @js.native
25 | trait SankeyOpts[V, E] extends js.Object {
26 | val data: SankeyData[V, E] = js.native
27 | val nodeaccessor: js.Function1[V, String] = js.native
28 | val linkaccessor: js.Function1[E, SankeyEdge] = js.native
29 | val width: Int = js.native
30 | val height: Int = js.native
31 | val gutter: js.UndefOr[Int] = js.native
32 | val rect_width: js.UndefOr[Int] = js.native
33 | }
34 |
35 | object SankeyOpts {
36 | def apply[V, E](data: SankeyData[V, E], nodeaccessor: js.Function1[V, String],
37 | linkaccessor: js.Function1[E, SankeyEdge], width: Int, height: Int,
38 | gutter: Int = 10, rect_width: Int = 10): SankeyOpts[V, E] =
39 | js.Dynamic.literal(
40 | data = data,
41 | nodeaccessor = nodeaccessor,
42 | linkaccessor = linkaccessor,
43 | width = width,
44 | height = height,
45 | gutter = gutter,
46 | rect_width = rect_width
47 | ).asInstanceOf[SankeyOpts[V, E]]
48 | }
49 |
50 | @js.native
51 | @JSName("Paths.Sankey")
52 | object SankeyNative extends js.Object {
53 | def apply[V, E](options: SankeyOpts[V, E]): Sankey[V, E] = js.native
54 | }
55 |
56 | @js.native
57 | trait SankeyCurve[E] extends js.Object {
58 | val curve: CurvedRectangle = js.native
59 | val item: E = js.native
60 | val index: Int = js.native
61 | }
62 |
63 | @js.native
64 | trait SankeyNode[V] extends js.Object {
65 | val curve: Rectangle = js.native
66 | val item: V = js.native
67 | val index: Int = js.native
68 | val group: Int = js.native
69 | }
70 |
71 | @js.native
72 | trait Sankey[V, E] extends js.Object {
73 | var curvedRectangles: js.Array[SankeyCurve[E]] = js.native
74 | var rectangles: js.Array[SankeyNode[V]] = js.native
75 | }
76 |
77 | object Sankey {
78 | type SankeyScalaEdge = { def start: String; def end: String; def weight: Double }
79 |
80 | def apply[V, E](nodes: Seq[Seq[V]], links: Seq[E], nodeaccessor: V => String, linkaccessor: E => SankeyScalaEdge,
81 | width: Int, height: Int, gutter: Int = 10, rectWidth: Int = 10) = {
82 |
83 | def dynamic(e: SankeyScalaEdge): SankeyEdge = js.Dynamic.literal(
84 | start = e.start,
85 | end = e.end,
86 | weight = e.weight
87 | ).asInstanceOf[SankeyEdge]
88 |
89 | val data = js.Dynamic.literal(
90 | nodes = nodes.toJSArray.map(_.toJSArray),
91 | links = links.toJSArray
92 | ).asInstanceOf[SankeyData[V, E]]
93 |
94 | SankeyNative(SankeyOpts(data, nodeaccessor, linkaccessor.andThen(dynamic),
95 | width, height, gutter, rectWidth))
96 | }
97 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/SmoothLine.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Shape
9 | import misc.Linear
10 |
11 |
12 | @js.native
13 | trait SmoothLineOpts[A] extends js.Object {
14 | val data: js.Array[js.Array[A]] = js.native
15 | val xaccessor: js.Function1[A, Double] = js.native
16 | val yaccessor: js.Function1[A, Double] = js.native
17 | val width: Int = js.native
18 | val height: Int = js.native
19 | val closed: Boolean = js.native
20 | val sort: Boolean = js.native
21 | }
22 |
23 | object SmoothLineOpts {
24 | def apply[A](data: js.Array[js.Array[A]], xaccessor: js.Function1[A, Double],
25 | yaccessor: js.Function1[A, Double], width: Int, height: Int,
26 | closed: Boolean = false, sort: Boolean = true): SmoothLineOpts[A] =
27 | js.Dynamic.literal(
28 | data = data,
29 | xaccessor = xaccessor,
30 | yaccessor = yaccessor,
31 | width = width,
32 | height = height,
33 | closed = closed,
34 | sort = sort
35 | ).asInstanceOf[SmoothLineOpts[A]]
36 | }
37 |
38 | @js.native
39 | @JSName("Paths.SmoothLine")
40 | object SmoothLineNative extends js.Object {
41 | def apply[A](options: SmoothLineOpts[A]): SmoothLine[A] = js.native
42 | }
43 |
44 | @js.native
45 | trait SmoothLineCurve[A] extends js.Object {
46 | val line: Shape = js.native
47 | val area: Shape = js.native
48 | val item: js.Array[A] = js.native
49 | val index: Int = js.native
50 | }
51 |
52 | @js.native
53 | trait SmoothLine[A] extends js.Object {
54 | val curves: js.Array[SmoothLineCurve[A]] = js.native
55 | val xscale: Linear = js.native
56 | val yscale: Linear = js.native
57 | }
58 |
59 | object SmoothLine {
60 | def apply[A](data: Seq[Seq[A]], xaccessor: A => Double, yaccessor: A => Double,
61 | width: Int, height: Int, closed: Boolean = false, sort: Boolean = true) = {
62 | val d = data.toJSArray.map(_.toJSArray)
63 | SmoothLineNative(SmoothLineOpts(d, xaccessor, yaccessor, width, height, closed, sort))
64 | }
65 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Stack.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Rectangle
9 |
10 |
11 | @js.native
12 | trait StackOpts[A] extends js.Object {
13 | val data: js.Array[js.Array[A]] = js.native
14 | val accessor: js.Function1[A, Double] = js.native
15 | val width: Int = js.native
16 | val height: Int = js.native
17 | val gutter: Int = js.native
18 | }
19 |
20 | object StackOpts {
21 | def apply[A](data: js.Array[js.Array[A]], accessor: js.Function1[A, Double],
22 | width: Int, height: Int, gutter: Int): StackOpts[A] =
23 | js.Dynamic.literal(
24 | data = data,
25 | accessor = accessor,
26 | width = width,
27 | height = height,
28 | gutter = gutter
29 | ).asInstanceOf[StackOpts[A]]
30 | }
31 |
32 | @js.native
33 | @JSName("Paths.Stack")
34 | object StackNative extends js.Object {
35 | def apply[A](options: StackOpts[A]): Stack[A] = js.native
36 | }
37 |
38 | @js.native
39 | trait StackCurve[A] extends js.Object {
40 | val line: Rectangle = js.native
41 | val item: A = js.native
42 | val index: Int = js.native
43 | val group: Int = js.native
44 | }
45 |
46 | @js.native
47 | trait Stack[A] extends js.Object {
48 | val curves: js.Array[StackCurve[A]] = js.native
49 | }
50 |
51 | object Stack {
52 | def apply[A](data: Seq[Seq[A]], accessor: A => Double, width: Int, height: Int, gutter: Int) = {
53 | val d = data.toJSArray.map(_.toJSArray)
54 | StackNative(StackOpts(d, accessor, width, height, gutter))
55 | }
56 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Stock.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Polygon
9 | import misc.Linear
10 |
11 |
12 | @js.native
13 | trait StockOpts[A] extends js.Object {
14 | val data: js.Array[js.Array[A]] = js.native
15 | val xaccessor: js.Function1[A, Double] = js.native
16 | val yaccessor: js.Function1[A, Double] = js.native
17 | val width: Int = js.native
18 | val height: Int = js.native
19 | val closed: Boolean = js.native
20 | val sort: Boolean = js.native
21 | }
22 |
23 | object StockOpts {
24 | def apply[A](data: js.Array[js.Array[A]], xaccessor: js.Function1[A, Double],
25 | yaccessor: js.Function1[A, Double], width: Int, height: Int,
26 | closed: Boolean = false, sort: Boolean = true): StockOpts[A] =
27 | js.Dynamic.literal(
28 | data = data,
29 | xaccessor = xaccessor,
30 | yaccessor = yaccessor,
31 | width = width,
32 | height = height,
33 | closed = closed,
34 | sort = sort
35 | ).asInstanceOf[StockOpts[A]]
36 | }
37 |
38 | @js.native
39 | @JSName("Paths.Stock")
40 | object StockNative extends js.Object {
41 | def apply[A](options: StockOpts[A]): Stock[A] = js.native
42 | }
43 |
44 | @js.native
45 | trait StockCurve[A] extends js.Object {
46 | val line: Polygon = js.native
47 | val area: Polygon = js.native
48 | val item: js.Array[A] = js.native
49 | val index: Int = js.native
50 | }
51 |
52 | @js.native
53 | trait Stock[A] extends js.Object {
54 | val curves: js.Array[StockCurve[A]] = js.native
55 | val xscale: Linear = js.native
56 | val yscale: Linear = js.native
57 | }
58 |
59 | object Stock {
60 | def apply[A](data: Seq[Seq[A]], xaccessor: A => Double, yaccessor: A => Double,
61 | width: Int, height: Int, closed: Boolean = false, sort: Boolean = true) = {
62 | val d = data.toJSArray.map(_.toJSArray)
63 | StockNative(StockOpts(d, xaccessor, yaccessor, width, height, closed, sort))
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Tree.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Connector
9 |
10 |
11 | @js.native
12 | trait TreeOpts[A] extends js.Object {
13 | val data: A = js.native
14 | val children: js.Function1[A, js.Array[A]] = js.native
15 | val width: Int = js.native
16 | val height: Int = js.native
17 | }
18 |
19 | object TreeOpts {
20 | def apply[A](data: A, children: js.Function1[A, js.Array[A]],
21 | width: Int, height: Int): TreeOpts[A] =
22 | js.Dynamic.literal(
23 | data = data.asInstanceOf[js.Any],
24 | children = children,
25 | width = width,
26 | height = height
27 | ).asInstanceOf[TreeOpts[A]]
28 | }
29 |
30 | @js.native
31 | @JSName("Paths.Tree")
32 | object TreeNative extends js.Object {
33 | def apply[A](options: TreeOpts[A]): Tree[A] = js.native
34 | }
35 |
36 | @js.native
37 | trait TreeCurve[A] extends js.Object {
38 | val connector: Connector = js.native
39 | val item: A = js.native
40 | val index: Int = js.native
41 | }
42 |
43 | @js.native
44 | trait TreeNode[A] extends js.Object {
45 | val point: Point = js.native
46 | val item: A = js.native
47 | }
48 |
49 | @js.native
50 | trait Tree[A] extends js.Object {
51 | val curves: js.Array[TreeCurve[A]] = js.native
52 | val nodes: js.Array[TreeNode[A]] = js.native
53 | }
54 |
55 | object Tree {
56 | def apply[A](data: A, children: A => Seq[A], width: Int, height: Int) = {
57 | val c = children.andThen(_.toJSArray)
58 | TreeNative(TreeOpts(data, c, width, height))
59 | }
60 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Voronoi.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Sector
9 |
10 |
11 | @js.native
12 | trait VoronoiOpts[A] extends js.Object {
13 | val data: js.Array[A] = js.native
14 | val accessor: js.Function1[A, Point] = js.native
15 | val xrange: Point = js.native
16 | val yrange: Point = js.native
17 | val width: Int = js.native
18 | val height: Int = js.native
19 | }
20 |
21 | object VoronoiOpts {
22 | def apply[A](data: js.Array[A], accessor: js.Function1[A, Point],
23 | xrange: Point, yrange: Point, width: Int, height: Int): VoronoiOpts[A] =
24 | js.Dynamic.literal(
25 | data = data,
26 | accessor = accessor,
27 | xrange = xrange,
28 | yrange = yrange,
29 | width = width,
30 | height = height
31 | ).asInstanceOf[VoronoiOpts[A]]
32 | }
33 |
34 | @js.native
35 | @JSName("Paths.Voronoi")
36 | object VoronoiNative extends js.Object {
37 | def apply[A](options: VoronoiOpts[A]): Voronoi[A] = js.native
38 | }
39 |
40 | @js.native
41 | trait VoronoiCurve[A] extends js.Object {
42 | val line: Sector = js.native
43 | val item: A = js.native
44 | val index: Int = js.native
45 | }
46 |
47 | @js.native
48 | trait VoronoiPoint[A] extends js.Object {
49 | val point: Point = js.native
50 | val item: A = js.native
51 | }
52 |
53 | @js.native
54 | trait Voronoi[A] extends js.Object {
55 | val curves: js.Array[VoronoiCurve[A]] = js.native
56 | val nodes: js.Array[VoronoiPoint[A]] = js.native
57 | }
58 |
59 | object Voronoi {
60 | def apply[A](data: Seq[A], accessor: A => (Double, Double),
61 | xrange: (Double, Double), yrange: (Double, Double), width: Int, height: Int) = {
62 |
63 | val acc: js.Function1[A, Point] = accessor andThen tuple2point
64 |
65 | VoronoiNative(VoronoiOpts(data.toJSArray, acc, tuple2point(xrange), tuple2point(yrange), width, height))
66 | }
67 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/high/Waterfall.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package high
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | import mid.Rectangle
9 |
10 |
11 | @js.native
12 | trait WaterfallItem extends js.Object {
13 | val value: js.UndefOr[Double] = js.native
14 | val absolute: js.UndefOr[Boolean] = js.native
15 | }
16 |
17 | trait WaterfallScalaItem {
18 | def value: Option[Double]
19 | def absolute: Boolean
20 | }
21 |
22 | @js.native
23 | trait WaterfallOpts[A] extends js.Object {
24 | val data: js.Array[A] = js.native
25 | val accessor: js.Function1[A, WaterfallItem] = js.native
26 | val max: js.UndefOr[Double] = js.native
27 | val min: js.UndefOr[Double] = js.native
28 | val width: Int = js.native
29 | val height: Int = js.native
30 | val gutter: js.UndefOr[Int] = js.native
31 | }
32 |
33 | object WaterfallOpts {
34 | def apply[A](data: js.Array[A], accessor: js.Function1[A, WaterfallItem],
35 | max: js.UndefOr[Double], min: js.UndefOr[Double], width: Int, height: Int,
36 | gutter: js.UndefOr[Int]): WaterfallOpts[A] =
37 | js.Dynamic.literal(
38 | data = data,
39 | accessor = accessor,
40 | max = max,
41 | min = min,
42 | width = width,
43 | height = height,
44 | gutter = gutter
45 | ).asInstanceOf[WaterfallOpts[A]]
46 | }
47 |
48 | @js.native
49 | @JSName("Paths.Waterfall")
50 | object WaterfallNative extends js.Object {
51 | def apply[A](options: WaterfallOpts[A]): Waterfall[A] = js.native
52 | }
53 |
54 | @js.native
55 | trait WaterfallCurve[A] extends js.Object {
56 | val line: Rectangle = js.native
57 | val value: Double = js.native
58 | val item: A = js.native
59 | val index: Int = js.native
60 | }
61 |
62 | @js.native
63 | trait Waterfall[A] extends js.Object {
64 | val curves: js.Array[WaterfallCurve[A]] = js.native
65 | }
66 |
67 | object Waterfall {
68 | type WaterfallScalaItem = { def value: Option[Double]; def absolute: Boolean }
69 |
70 | def apply[A](data: Seq[A], accessor: A => WaterfallScalaItem, max: Option[Double] = None,
71 | min: Option[Double] = None, width: Int, height: Int, gutter: Option[Int] = None) = {
72 |
73 | def dynamic(s: WaterfallScalaItem): WaterfallItem = js.Dynamic.literal(
74 | value = s.value.orUndefined,
75 | absolute = s.absolute
76 | ).asInstanceOf[WaterfallItem]
77 |
78 | WaterfallNative(WaterfallOpts(data.toJSArray, accessor.andThen(dynamic), max.orUndefined, min.orUndefined,
79 | width, height, gutter.orUndefined))
80 | }
81 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/low/Path.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package low
3 |
4 | import scala.scalajs.js
5 | import scala.scalajs.js.annotation.JSName
6 |
7 | @js.native
8 | trait Path extends js.Object {
9 | def print(): String = js.native
10 | def points(): js.Array[Point] = js.native
11 | def connect(path: Path): Path = js.native
12 |
13 | def moveto(x: Number, y: Number): Path = js.native
14 | def lineto(x: Number, y: Number): Path = js.native
15 | def hlineto(x: Number): Path = js.native
16 | def vlineto(y: Number): Path = js.native
17 | def curveto(x1: Number, y1: Number, x2: Number, y2: Number, x: Number, y: Number): Path = js.native
18 | def smoothcurveto(x2: Number, y2: Number, x: Number, y: Number): Path = js.native
19 | def qcurveto(x1: Number, y1: Number, x: Number, y: Number): Path = js.native
20 | def smoothqcurveto(x: Number, y: Number): Path = js.native
21 | def arc(rx: Number, ry: Number, xrot: Number, largeArcFlag: Number, sweepFlag: Number, x: Number, y: Number): Path = js.native
22 | def closepath(): Path = js.native
23 | }
24 |
25 | @js.native
26 | @JSName("Paths.Path")
27 | object Path extends js.Object {
28 | def apply(): Path = js.native
29 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Bezier.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 | @js.native
9 | trait BezierOpts extends js.Object {
10 | val points: js.Array[Point] = js.native
11 | val tension: Double = js.native
12 | }
13 |
14 | object BezierOpts {
15 | def apply(points: js.Array[Point], tension: Double = 0.3): BezierOpts =
16 | js.Dynamic.literal(
17 | points = points,
18 | tension = tension
19 | ).asInstanceOf[BezierOpts]
20 | }
21 |
22 | @js.native
23 | @JSName("Paths.Bezier")
24 | object BezierNative extends js.Object {
25 | def apply(options: BezierOpts): Bezier = js.native
26 | }
27 |
28 | @js.native
29 | trait Bezier extends Shape
30 |
31 | object Bezier {
32 | def apply(points: Seq[(Double, Double)], tension: Double = 0.3): Bezier = {
33 | val jsPoints = for ((x, y) <- points.toJSArray) yield js.Array(x, y)
34 | BezierNative(BezierOpts(jsPoints, tension))
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Connector.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait ConnectorOpts extends js.Object {
11 | val start: Point = js.native
12 | val end: Point = js.native
13 | }
14 |
15 | object ConnectorOpts {
16 | def apply(start: Point, end: Point): ConnectorOpts =
17 | js.Dynamic.literal(
18 | start = start,
19 | end = end
20 | ).asInstanceOf[ConnectorOpts]
21 | }
22 |
23 | @js.native
24 | @JSName("Paths.Connector")
25 | object ConnectorNative extends js.Object {
26 | def apply(options: ConnectorOpts): Connector = js.native
27 | }
28 |
29 | @js.native
30 | trait Connector extends Shape
31 |
32 | object Connector {
33 | def apply(start: (Double, Double), end: (Double, Double)): Connector = {
34 | val (a, b) = start
35 | val (c, d) = end
36 | ConnectorNative(ConnectorOpts(js.Array(a, b), js.Array(c, d)))
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/CurvedRectangle.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait CurvedRectangleOpts extends js.Object {
11 | val topleft: Point = js.native
12 | val topright: Point = js.native
13 | val bottomleft: Point = js.native
14 | val bottomright: Point = js.native
15 | }
16 |
17 | object CurvedRectangleOpts {
18 | def apply(topleft: Point, topright: Point, bottomleft: Point, bottomright: Point): CurvedRectangleOpts =
19 | js.Dynamic.literal(
20 | topleft = topleft,
21 | topright = topright,
22 | bottomleft = bottomleft,
23 | bottomright = bottomright
24 | ).asInstanceOf[CurvedRectangleOpts]
25 | }
26 |
27 | @js.native
28 | @JSName("Paths.CurvedRectangle")
29 | object CurvedRectangleNative extends js.Object {
30 | def apply(options: CurvedRectangleOpts): CurvedRectangle = js.native
31 | }
32 |
33 | @js.native
34 | trait CurvedRectangle extends Shape
35 |
36 | object CurvedRectangle {
37 | def apply(topleft: (Double, Double), topright: (Double, Double),
38 | bottomleft: (Double, Double), bottomright: (Double, Double)): CurvedRectangle = {
39 | CurvedRectangleNative(CurvedRectangleOpts(tuple2point(topleft), tuple2point(topright),
40 | tuple2point(bottomleft), tuple2point(bottomright)))
41 | }
42 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Polygon.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait PolygonOpts extends js.Object {
11 | val points: js.Array[Point] = js.native
12 | val closed: Boolean = js.native
13 | }
14 |
15 | object PolygonOpts {
16 | def apply(points: js.Array[Point], closed: Boolean = false): PolygonOpts =
17 | js.Dynamic.literal(
18 | points = points,
19 | closed = closed
20 | ).asInstanceOf[PolygonOpts]
21 | }
22 |
23 | @js.native
24 | @JSName("Paths.Polygon")
25 | object PolygonNative extends js.Object {
26 | def apply(options: PolygonOpts): Polygon = js.native
27 | }
28 |
29 | @js.native
30 | trait Polygon extends Shape
31 |
32 | object Polygon {
33 | def apply(points: Seq[(Double, Double)], closed: Boolean = false): Polygon = {
34 | val jsPoints = for ((x, y) <- points.toJSArray) yield js.Array(x, y)
35 | PolygonNative(PolygonOpts(jsPoints, closed))
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Rectangle.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait RectangleOpts extends js.Object {
11 | val top: Double = js.native
12 | val bottom: Double = js.native
13 | val left: Double = js.native
14 | val right: Double = js.native
15 | }
16 |
17 | object RectangleOpts {
18 | def apply(top: Double, bottom: Double, left: Double, right: Double): RectangleOpts =
19 | js.Dynamic.literal(
20 | top = top,
21 | bottom = bottom,
22 | left = left,
23 | right = right
24 | ).asInstanceOf[RectangleOpts]
25 | }
26 |
27 | @js.native
28 | @JSName("Paths.Rectangle")
29 | object RectangleNative extends js.Object {
30 | def apply(options: RectangleOpts): Rectangle = js.native
31 | }
32 |
33 | @js.native
34 | trait Rectangle extends Shape
35 |
36 | object Rectangle {
37 | def apply(top: Double, bottom: Double, left: Double, right: Double): Rectangle = {
38 | RectangleNative(RectangleOpts(top, bottom, left, right))
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Sector.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait SectorOpts extends js.Object {
11 | val center: Point = js.native
12 | val r: Double = js.native
13 | val R: Double = js.native
14 | val start: Double = js.native
15 | val end: Double = js.native
16 | }
17 |
18 | object SectorOpts {
19 | def apply(center: Point, r: Double, R: Double, start: Double, end: Double): SectorOpts =
20 | js.Dynamic.literal(
21 | center = center,
22 | r = r,
23 | R = R,
24 | start = start,
25 | end = end
26 | ).asInstanceOf[SectorOpts]
27 | }
28 |
29 | @js.native
30 | @JSName("Paths.Sector")
31 | object SectorNative extends js.Object {
32 | def apply(options: SectorOpts): Sector = js.native
33 | }
34 |
35 | @js.native
36 | trait Sector extends Shape
37 |
38 | object Sector {
39 | def apply(center: (Double, Double), r: Double, R: Double, start: Double, end: Double): Sector = {
40 | val (x, y) = center
41 | SectorNative(SectorOpts(js.Array(x, y), r, R, start, end))
42 | }
43 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/SemiRegularPolygon.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 | import js.JSConverters._
7 |
8 |
9 | @js.native
10 | trait SemiRegularPolygonOpts extends js.Object {
11 | val center: Point = js.native
12 | val radii: js.Array[Double] = js.native
13 | }
14 |
15 | object SemiRegularPolygonOpts {
16 | def apply(center: Point, radii: js.Array[Double]): SemiRegularPolygonOpts =
17 | js.Dynamic.literal(
18 | center = center,
19 | radii = radii
20 | ).asInstanceOf[SemiRegularPolygonOpts]
21 | }
22 |
23 | @js.native
24 | @JSName("Paths.SemiRegularPolygon")
25 | object SemiRegularPolygonNative extends js.Object {
26 | def apply(options: SemiRegularPolygonOpts): SemiRegularPolygon = js.native
27 | }
28 |
29 | @js.native
30 | trait SemiRegularPolygon extends Shape
31 |
32 | object SemiRegularPolygon {
33 | def apply(center: (Double, Double), radii: Seq[Double]): SemiRegularPolygon = {
34 | val (x, y) = center
35 | SemiRegularPolygonNative(SemiRegularPolygonOpts(js.Array(x, y), radii.toJSArray))
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/mid/Shape.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package mid
3 |
4 | import scala.scalajs.js
5 |
6 | import low.Path
7 |
8 |
9 | @js.native
10 | trait Shape extends js.Object {
11 | val path: Path = js.native
12 | val centroid: Point = js.native
13 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/misc/Linear.scala:
--------------------------------------------------------------------------------
1 | package paths
2 | package misc
3 |
4 | import scala.scalajs.js
5 | import js.annotation.JSName
6 |
7 | @js.native
8 | @JSName("Paths.Linear")
9 | object LinearNative extends js.Object {
10 | def apply(source: js.Array[Double], target: js.Array[Double]): Linear = js.native
11 | }
12 |
13 | @js.native
14 | trait Linear extends js.Object {
15 | def apply(x: Double): Double = js.native
16 | def inverse(): Linear = js.native
17 | }
18 |
19 | object Linear {
20 | def apply(source: (Double, Double), target: (Double, Double)): Linear = {
21 | val (a, b) = source
22 | val (c, d) = target
23 | LinearNative(js.Array(a, b), js.Array(c, d))
24 | }
25 | }
--------------------------------------------------------------------------------
/src/main/scala/paths/paths.scala:
--------------------------------------------------------------------------------
1 | import scala.scalajs.js
2 | import js.JSConverters._
3 |
4 | package object paths {
5 | type Point = js.Array[Double]
6 | private[paths] def tuple2point(x: (Double, Double)) = js.Array(x._1, x._2)
7 | }
--------------------------------------------------------------------------------