diff --git a/bsconfig.json b/bsconfig.json
index 359646a4..81ef6fe0 100644
--- a/bsconfig.json
+++ b/bsconfig.json
@@ -3,10 +3,16 @@
   "reason": {
     "react-jsx": 3
   },
-  "sources": {
-    "dir": "src",
-    "subdirs": true
-  },
+  "sources": [{
+      "dir": "src",
+      "subdirs": true
+    },
+    {
+      "dir": "showcase",
+      "type": "dev",
+      "subdirs": true
+    }
+  ],
   "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
   "package-specs": [{
     "module": "commonjs",
diff --git a/package.json b/package.json
index 90305344..59806ab0 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
     "clean": "bsb -clean-world",
     "parcel": "parcel ./src/index.html --public-url / --no-autoinstall -- watch",
     "parcel-build": "parcel build ./src/index.html --no-source-maps --no-autoinstall",
+    "showcase": "PORT=12345 parcel showcase/index.html",
     "server": "moduleserve ./ --port 8000",
     "predeploy": "parcel build ./src/index.html --no-source-maps --no-autoinstall",
     "deploy": "gh-pages -d dist",
@@ -31,6 +32,7 @@
     "bs-css": "^11.0.0",
     "bs-moment": "0.4.4",
     "bs-reform": "9.7.1",
+    "d3": "^5.15.0",
     "lenses-ppx": "4.0.0",
     "less": "^3.10.3",
     "lodash": "^4.17.15",
diff --git a/showcase/Entries.re b/showcase/Entries.re
new file mode 100644
index 00000000..ae4cef64
--- /dev/null
+++ b/showcase/Entries.re
@@ -0,0 +1 @@
+let entries = EntryTypes.[Continuous.entry];
\ No newline at end of file
diff --git a/showcase/EntryTypes.re b/showcase/EntryTypes.re
new file mode 100644
index 00000000..49a61a33
--- /dev/null
+++ b/showcase/EntryTypes.re
@@ -0,0 +1,30 @@
+type compEntry = {
+  mutable id: string,
+  title: string,
+  render: unit => React.element,
+  container: containerType,
+}
+and folderEntry = {
+  mutable id: string,
+  title: string,
+  children: list(navEntry),
+}
+and navEntry =
+  | CompEntry(compEntry)
+  | FolderEntry(folderEntry)
+and containerType =
+  | FullWidth
+  | Sidebar;
+
+let entry = (~title, ~render): navEntry => {
+  CompEntry({id: "", title, render, container: FullWidth});
+};
+
+// Maybe different api, this avoids breaking changes
+let sidebar = (~title, ~render): navEntry => {
+  CompEntry({id: "", title, render, container: Sidebar});
+};
+
+let folder = (~title, ~children): navEntry => {
+  FolderEntry({id: "", title, children});
+};
diff --git a/showcase/Lib.re b/showcase/Lib.re
new file mode 100644
index 00000000..60c27f79
--- /dev/null
+++ b/showcase/Lib.re
@@ -0,0 +1,200 @@
+open EntryTypes;
+
+module HS = Belt.HashMap.String;
+
+let entriesByPath: HS.t(navEntry) = HS.make(~hintSize=100);
+
+/* Creates unique id's per scope based on title */
+let buildIds = entries => {
+  let genId = (title, path) => {
+    let noSpaces = Js.String.replaceByRe([%bs.re "/\\s+/g"], "-", title);
+    if (!HS.has(entriesByPath, path ++ "/" ++ noSpaces)) {
+      noSpaces;
+    } else {
+      let rec loop = num => {
+        let testId = noSpaces ++ "-" ++ string_of_int(num);
+        if (!HS.has(entriesByPath, path ++ "/" ++ testId)) {
+          testId;
+        } else {
+          loop(num + 1);
+        };
+      };
+      loop(2);
+    };
+  };
+  let rec processFolder = (f: folderEntry, curPath) => {
+    f.id = curPath ++ "/" ++ genId(f.title, curPath);
+    HS.set(entriesByPath, f.id, FolderEntry(f));
+    f.children
+    |> E.L.iter(e =>
+         switch (e) {
+         | CompEntry(c) => processEntry(c, f.id)
+         | FolderEntry(f) => processFolder(f, f.id)
+         }
+       );
+  }
+  and processEntry = (c: compEntry, curPath) => {
+    c.id = curPath ++ "/" ++ genId(c.title, curPath);
+    HS.set(entriesByPath, c.id, CompEntry(c));
+  };
+  entries
+  |> E.L.iter(e =>
+       switch (e) {
+       | CompEntry(c) => processEntry(c, "")
+       | FolderEntry(f) => processFolder(f, "")
+       }
+     );
+};
+
+let entries = Entries.entries;
+buildIds(entries);
+
+module Styles = {
+  open Css;
+  let pageContainer = style([display(`flex), height(`vh(100.))]);
+  let leftNav =
+    style([
+      padding(`em(2.)),
+      flexBasis(`px(200)),
+      flexShrink(0.),
+      backgroundColor(`hex("eaeff3")),
+      boxShadows([
+        Shadow.box(
+          ~x=px(-1),
+          ~blur=px(1),
+          ~inset=true,
+          rgba(0, 0, 0, 0.1),
+        ),
+      ]),
+    ]);
+
+  let folderNav =
+    style([
+      selector(
+        ">h4",
+        [
+          cursor(`pointer),
+          margin2(~v=`em(0.3), ~h=`zero),
+          hover([color(`hex("7089ad"))]),
+        ],
+      ),
+    ]);
+  let folderChildren = style([paddingLeft(`px(7))]);
+  let compNav =
+    style([
+      cursor(`pointer),
+      paddingBottom(`px(3)),
+      hover([color(`hex("7089ad"))]),
+    ]);
+  let compContainer = style([padding(`em(2.)), flexGrow(1.)]);
+  // Approximate sidebar container for entry
+  let sidebarContainer = style([maxWidth(`px(430))]);
+  let folderChildContainer = style([marginBottom(`em(2.))]);
+};
+
+let baseUrl = "/showcase/index.html";
+
+module Index = {
+  type state = {route: ReasonReactRouter.url};
+
+  type action =
+    | ItemClick(string)
+    | ChangeRoute(ReasonReactRouter.url);
+
+  let changeId = (id: string) => {
+    ReasonReactRouter.push(baseUrl ++ "#" ++ id);
+    ();
+  };
+
+  let buildNav = setRoute => {
+    let rec buildFolder = (f: folderEntry) => {
+      
+        
 changeId(f.id)}> f.title->React.string  
+        
+          {(
+             f.children
+             |> E.L.fmap(e =>
+                  switch (e) {
+                  | FolderEntry(folder) => buildFolder(folder)
+                  | CompEntry(entry) => buildEntry(entry)
+                  }
+                )
+             |> E.L.toArray
+           )
+           ->React.array}
+        
+      
 ;
+    }
+    and buildEntry = (e: compEntry) => {
+       changeId(e.id)}>
+        e.title->React.string
+      
;
+    };
+    (
+      entries
+      |> E.L.fmap(e =>
+           switch (e) {
+           | FolderEntry(folder) => buildFolder(folder)
+           | CompEntry(entry) => buildEntry(entry)
+           }
+         )
+      |> E.L.toArray
+    )
+    ->React.array;
+  };
+
+  let renderEntry = e => {
+    switch (e.container) {
+    | FullWidth => e.render()
+    | Sidebar =>  {e.render()} 
+    };
+  };
+
+  [@react.component]
+  let make = () => {
+    let (route, setRoute) =
+      React.useState(() => {
+        let url: ReasonReactRouter.url = {path: [], hash: "", search: ""};
+        url;
+      });
+
+    React.useState(() => {
+      ReasonReactRouter.watchUrl(url => setRoute(_ => url));
+      ();
+    })
+    |> ignore;
+
+    
+      
 {buildNav(setRoute)} 
+      
+        {if (route.hash == "") {
+           React.null;
+         } else {
+           switch (HS.get(entriesByPath, route.hash)) {
+           | Some(navEntry) =>
+             switch (navEntry) {
+             | CompEntry(c) => renderEntry(c)
+             | FolderEntry(f) =>
+               /* Rendering immediate children */
+               (
+                 f.children
+                 |> E.L.fmap(child =>
+                      switch (child) {
+                      | CompEntry(c) =>
+                        
+                          {renderEntry(c)}
+                        
+                      | _ => React.null
+                      }
+                    )
+                 |> E.L.toArray
+               )
+               ->React.array
+             }
+           | None => 
 "Component not found"->React.string 
+           };
+         }}
+      
+    
 ;
+  };
+};
\ No newline at end of file
diff --git a/showcase/ShowcaseIndex.re b/showcase/ShowcaseIndex.re
new file mode 100644
index 00000000..e3912686
--- /dev/null
+++ b/showcase/ShowcaseIndex.re
@@ -0,0 +1,2 @@
+ReactDOMRe.renderToElementWithId(   
, "main");
+ReasonReactRouter.push("");
\ No newline at end of file
diff --git a/showcase/entries/Continuous.re b/showcase/entries/Continuous.re
new file mode 100644
index 00000000..5475fd92
--- /dev/null
+++ b/showcase/entries/Continuous.re
@@ -0,0 +1,19 @@
+open ForetoldComponents.Base;
+
+let data: DistributionTypes.xyShape = {
+  xs: [|0.2, 20., 80., 212., 330.|],
+  ys: [|0.0, 0.3, 0.5, 0.2, 0.1|],
+};
+
+let alerts = () =>
+  
+    
   
+    
+       Shape.XYShape.integral}
+        color={`hex("333")}
+      />
+     
+  
 ;
+
+let entry = EntryTypes.(entry(~title="Pdf", ~render=alerts));
\ No newline at end of file
diff --git a/showcase/index.html b/showcase/index.html
new file mode 100644
index 00000000..7879deec
--- /dev/null
+++ b/showcase/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+     
+     
+     
+     
+    
+    
+    Showcase 
+
+
+
+    
+    
+
+
+
\ No newline at end of file
diff --git a/src/components/charts/CdfChart__Base.re b/src/components/charts/CdfChart__Base.re
new file mode 100644
index 00000000..6abb50bc
--- /dev/null
+++ b/src/components/charts/CdfChart__Base.re
@@ -0,0 +1,43 @@
+[@bs.module "./cdfChartReact.js"]
+external cdfChart: ReasonReact.reactClass = "default";
+
+type primaryDistribution = {
+  .
+  "xs": array(float),
+  "ys": array(float),
+};
+
+[@react.component]
+let make =
+    (
+      ~height=?,
+      ~verticalLine=?,
+      ~showVerticalLine=?,
+      ~marginBottom=?,
+      ~marginTop=?,
+      ~showDistributionLines=?,
+      ~maxX=?,
+      ~minX=?,
+      ~onHover=(f: float) => (),
+      ~primaryDistribution=?,
+      ~children=[||],
+    ) =>
+  ReasonReact.wrapJsForReason(
+    ~reactClass=cdfChart,
+    ~props=
+      makeProps(
+        ~height?,
+        ~verticalLine?,
+        ~marginBottom?,
+        ~marginTop?,
+        ~onHover,
+        ~showVerticalLine?,
+        ~showDistributionLines?,
+        ~maxX?,
+        ~minX?,
+        ~primaryDistribution?,
+        (),
+      ),
+    children,
+  )
+  |> ReasonReact.element;
\ No newline at end of file
diff --git a/src/components/charts/CdfChart__Plain.re b/src/components/charts/CdfChart__Plain.re
new file mode 100644
index 00000000..72067a3e
--- /dev/null
+++ b/src/components/charts/CdfChart__Plain.re
@@ -0,0 +1,41 @@
+module Styles = {
+  open Css;
+  let textOverlay = style([position(`absolute)]);
+  let mainText = style([fontSize(`em(1.1))]);
+  let secondaryText = style([fontSize(`em(0.9))]);
+
+  let graph = chartColor =>
+    style([
+      position(`relative),
+      selector(".axis", [fontSize(`px(9))]),
+      selector(".domain", [display(`none)]),
+      selector(".tick line", [display(`none)]),
+      selector(".tick text", [color(`hex("bfcad4"))]),
+      selector(".chart .area-path", [SVG.fill(chartColor)]),
+    ]);
+};
+
+[@react.component]
+let make =
+    (
+      ~data,
+      ~minX=?,
+      ~maxX=?,
+      ~height=200,
+      ~color=`hex("111"),
+      ~onHover: float => unit,
+    ) => {
+  
+     Shape.XYShape.toJs}
+    />
+   
;
+};
\ No newline at end of file
diff --git a/src/components/charts/ChartSimple.re b/src/components/charts/ChartSimple.re
new file mode 100644
index 00000000..37f8697c
--- /dev/null
+++ b/src/components/charts/ChartSimple.re
@@ -0,0 +1,24 @@
+module Styles = {
+  open Css;
+  let graph = chartColor =>
+    style([
+      selector(".axis", [fontSize(`px(9))]),
+      selector(".domain", [display(`none)]),
+      selector(".tick line", [display(`none)]),
+      selector(".tick text", [color(`hex("bfcad4"))]),
+      selector(".chart .area-path", [SVG.fill(chartColor)]),
+    ]);
+};
+
+[@react.component]
+let make = (~minX=None, ~maxX=None, ~height=50, ~color=`hex("7e9db7")) =>
+  
+     
+  
;
\ No newline at end of file
diff --git a/src/components/charts/ChartWithNumber.re b/src/components/charts/ChartWithNumber.re
new file mode 100644
index 00000000..b8ac5bfb
--- /dev/null
+++ b/src/components/charts/ChartWithNumber.re
@@ -0,0 +1,23 @@
+[@react.component]
+let make = (~data, ~color=?) => {
+  let (x, setX) = React.useState(() => 0.);
+  let chart =
+    React.useMemo1(
+      () =>  setX(_ => r)} />,
+      [|data|],
+    );
+  
+    chart
+    
 {x |> E.Float.toString |> ReasonReact.string} 
+    
+      {Shape.Continuous.findY(x, data)
+       |> E.Float.toString
+       |> ReasonReact.string}
+    
+    
+      {Shape.Continuous.findY(x, Shape.XYShape.integral(data))
+       |> E.Float.toString
+       |> ReasonReact.string}
+    
+  
 ;
+};
\ No newline at end of file
diff --git a/src/components/charts/cdfChartReact.js b/src/components/charts/cdfChartReact.js
new file mode 100644
index 00000000..f72e5db7
--- /dev/null
+++ b/src/components/charts/cdfChartReact.js
@@ -0,0 +1,66 @@
+import React, { useEffect } from 'react';
+import { useSize } from 'react-use';
+
+import chart from './cdfChartd3';
+
+/**
+ * @param min
+ * @param max
+ * @returns {number}
+ */
+function getRandomInt(min, max) {
+  min = Math.ceil(min);
+  max = Math.floor(max);
+  return Math.floor(Math.random() * (max - min + 1)) + min;
+}
+
+/**
+ * Example input:
+ * {
+ * xs: [50,100,300,400,500,600],
+ * ys: [0.1, 0.4, 0.6, 0.7,0.8, 0.9]}
+ * }
+ */
+function CdfChart(props) {
+  const id = "chart-" + getRandomInt(0, 100000);
+  const [sized, { width }] = useSize(() => {
+    return React.createElement("div", {
+      key: "resizable-div",
+    });
+  }, {
+    width: props.width,
+  });
+
+  useEffect(() => {
+    chart()
+      .svgWidth(width)
+      .svgHeight(props.height)
+      .maxX(props.maxX)
+      .minX(props.minX)
+      .onHover(props.onHover)
+      .marginBottom(props.marginBottom || 15)
+      .marginLeft(5)
+      .marginRight(5)
+      .marginTop(5)
+      .showDistributionLines(props.showDistributionLines)
+      .verticalLine(props.verticalLine)
+      .showVerticalLine(props.showVerticalLine)
+      .container("#" + id)
+      .data({ primary: props.primaryDistribution }).render();
+  });
+
+  const style = !!props.width ? { width: props.width + "px" } : {};
+  const key = id;
+
+  return React.createElement("div", {
+    style: {
+      paddingLeft: "10px",
+      paddingRight: "10px",
+    },
+  }, [
+    sized,
+    React.createElement("div", { id, style, key }),
+  ]);
+}
+
+export default CdfChart;
diff --git a/src/components/charts/cdfChartd3.js b/src/components/charts/cdfChartd3.js
new file mode 100644
index 00000000..a57b8cb1
--- /dev/null
+++ b/src/components/charts/cdfChartd3.js
@@ -0,0 +1,302 @@
+import * as d3 from 'd3';
+
+function chart() {
+  // Id for event handlings.
+  var attrs = {
+    id: 'ID' + Math.floor(Math.random() * 1000000),
+    svgWidth: 400,
+    svgHeight: 400,
+
+    marginTop: 5,
+    marginBottom: 5,
+    marginRight: 5,
+    marginLeft: 5,
+
+    container: 'body',
+    minX: false,
+    maxX: false,
+    scale: 'linear',
+    showDistributionLines: true,
+    areaColors: ['#E1E5EC', '#E1E5EC'],
+    logBase: 10,
+    verticalLine: 110,
+    showVerticalLine: true,
+    data: null,
+    onHover: (e) => {},
+  };
+
+  var main = function main() {
+    // Drawing containers.
+    var container = d3.select(attrs.container);
+
+    if (container.node() === null) {
+      return;
+    }
+
+    var containerRect = container.node().getBoundingClientRect();
+    if (containerRect.width > 0) {
+      attrs.svgWidth = containerRect.width;
+    }
+
+    // Calculated properties.
+    // id for event handlings.
+    var calc = {};
+    calc.id = 'ID' + Math.floor(Math.random() * 1000000);
+    calc.chartLeftMargin = attrs.marginLeft;
+    calc.chartTopMargin = attrs.marginTop;
+    calc.chartWidth = attrs.svgWidth - attrs.marginRight - attrs.marginLeft;
+    calc.chartHeight = attrs.svgHeight - attrs.marginBottom - attrs.marginTop;
+
+    var areaColor = d3.scaleOrdinal().range(attrs.areaColors);
+
+    var dataPoints = [getDatapoints('primary')];
+
+    // Scales.
+    var xScale;
+
+    var xMin = d3.min(attrs.data.primary.xs);
+    var xMax = d3.max(attrs.data.primary.xs);
+
+    if (attrs.scale === 'linear') {
+      xScale = d3.scaleLinear()
+        .domain([
+          attrs.minX || xMin,
+          attrs.maxX || xMax
+        ])
+        .range([0, calc.chartWidth]);
+    } else {
+      xScale = d3.scaleLog()
+        .base(attrs.logBase)
+        .domain([
+          attrs.minX,
+          attrs.maxX,
+        ])
+        .range([0, calc.chartWidth]);
+    }
+
+    var yMin = d3.min(attrs.data.primary.ys);
+    var yMax = d3.max(attrs.data.primary.ys);
+
+    var yScale = d3.scaleLinear()
+      .domain([
+        yMin,
+        yMax,
+      ])
+      .range([calc.chartHeight, 0]);
+
+    // Axis generator.
+    var xAxis = d3.axisBottom(xScale)
+      .ticks(3)
+      .tickFormat(d => {
+        if (Math.abs(d) < 1) {
+          return d3.format(".2")(d);
+        } else if (xMin > 1000 && xMax < 3000) {
+          // Condition which identifies years; 2019, 2020, 2021.
+          return d3.format(".0")(d);
+        } else {
+          var prefix = d3.formatPrefix(".0", d);
+          var output = prefix(d);
+          return output.replace("G", "B");
+        }
+      });
+
+    // Line generator.
+    var line = d3.line()
+      .x(function (d, i) {
+        return xScale(d.x);
+      })
+      .y(function (d, i) {
+        return yScale(d.y);
+      });
+
+    var area = d3.area()
+      .x(function (d, i) {
+        return xScale(d.x);
+      })
+      .y1(function (d, i) {
+        return yScale(d.y);
+      })
+      .y0(calc.chartHeight);
+
+    // Add svg.
+    var svg = container
+      .patternify({ tag: 'svg', selector: 'svg-chart-container' })
+      .attr('width', "100%")
+      .attr('height', attrs.svgHeight)
+      .attr('pointer-events', 'none');
+
+    // Add container g element.
+    var chart = svg
+      .patternify({ tag: 'g', selector: 'chart' })
+      .attr(
+        'transform',
+        'translate(' + calc.chartLeftMargin + ',' + calc.chartTopMargin + ')',
+      );
+
+    // Add axis.
+    chart.patternify({ tag: 'g', selector: 'axis' })
+      .attr('transform', 'translate(' + 0 + ',' + calc.chartHeight + ')')
+      .call(xAxis);
+
+    // Draw area.
+    chart
+      .patternify({
+        tag: 'path',
+        selector: 'area-path',
+        data: dataPoints
+      })
+      .attr('d', area)
+      .attr('fill', (d, i) => areaColor(i))
+      .attr('opacity', (d, i) => i === 0 ? 0.7 : 1);
+
+    // Draw line.
+    if (attrs.showDistributionLines) {
+      chart
+        .patternify({
+          tag: 'path',
+          selector: 'line-path',
+          data: dataPoints
+        })
+        .attr('d', line)
+        .attr('id', (d, i) => 'line-' + (i + 1))
+        .attr('opacity', (d, i) => {
+          return i === 0 ? 0.7 : 1
+        })
+        .attr('fill', 'none');
+    }
+
+    if (attrs.showVerticalLine) {
+      chart.patternify({ tag: 'line', selector: 'v-line' })
+        .attr('x1', xScale(attrs.verticalLine))
+        .attr('x2', xScale(attrs.verticalLine))
+        .attr('y1', 0)
+        .attr('y2', calc.chartHeight)
+        .attr('stroke-width', 1.5)
+        .attr('stroke-dasharray', '6 6')
+        .attr('stroke', 'steelblue');
+    }
+
+    var hoverLine = chart.patternify({ tag: 'line', selector: 'hover-line' })
+      .attr('x1', 0)
+      .attr('x2', 0)
+      .attr('y1', 0)
+      .attr('y2', calc.chartHeight)
+      .attr('opacity', 0)
+      .attr('stroke-width', 1.5)
+      .attr('stroke-dasharray', '6 6')
+      .attr('stroke', '#22313F');
+
+    // Add drawing rectangle.
+    chart.patternify({ tag: 'rect', selector: 'mouse-rect' })
+      .attr('width', calc.chartWidth)
+      .attr('height', calc.chartHeight)
+      .attr('fill', 'transparent')
+      .attr('pointer-events', 'all')
+      .on('mouseover', mouseover)
+      .on('mousemove', mouseover)
+      .on('mouseout', mouseout);
+
+    function mouseover() {
+      var mouse = d3.mouse(this);
+
+      hoverLine.attr('opacity', 1)
+        .attr('x1', mouse[0])
+        .attr('x2', mouse[0]);
+
+      var range = [
+        xScale(dataPoints[dataPoints.length - 1][0].x),
+        xScale(
+          dataPoints
+            [dataPoints.length - 1]
+            [dataPoints[dataPoints.length - 1].length - 1].x,
+        ),
+      ];
+
+      var xValue = xScale.invert(mouse[0]).toFixed(2);
+
+      if (mouse[0] > range[0] && mouse[0] < range[1]) {
+        attrs.onHover(xValue);
+      } else {
+        attrs.onHover(0.0);
+      }
+    }
+
+    function mouseout() {
+      hoverLine.attr('opacity', 0)
+    }
+
+    /**
+     * @param key
+     * @returns {[]}
+     */
+    function getDatapoints(key) {
+      var dt = [];
+      var data = attrs.data[key];
+      var len = data.xs.length;
+
+      for (let i = 0; i < len; i++) {
+        dt.push({
+          x: data.xs[i],
+          y: data.ys[i]
+        })
+      }
+
+      return dt;
+    }
+  };
+
+  d3.selection.prototype.patternify = function patternify(params) {
+    var container = this;
+    var selector = params.selector;
+    var elementTag = params.tag;
+    var data = params.data || [selector];
+
+    // Pattern in action.
+    var selection = container.selectAll('.' + selector).data(data, (d, i) => {
+      if (typeof d === 'object') {
+        if (d.id) {
+          return d.id;
+        }
+      }
+      return i;
+    });
+
+    selection.exit().remove();
+    selection = selection.enter().append(elementTag).merge(selection);
+    selection.attr('class', selector);
+    return selection;
+  };
+
+  // @todo: Do not do like that.
+  // Dynamic keys functions.
+  // Attach variables to main function.
+  Object.keys(attrs).forEach((key) => {
+    main[key] = function (_) {
+      if (!arguments.length) {
+        return attrs[key];
+      }
+      attrs[key] = _;
+      return main;
+    };
+  });
+
+  //Set attrs as property.
+  main.attrs = attrs;
+
+  //Exposed update functions.
+  main.data = function data(value) {
+    if (!arguments.length) return attrs.data;
+    attrs.data = value;
+    return main;
+  };
+
+  // Run visual.
+  main.render = function render() {
+    main();
+    return main;
+  };
+
+  return main;
+}
+
+export default chart;
diff --git a/src/core/MixedCdf.re b/src/core/MixedCdf.re
index 8ffb7b31..2006df48 100644
--- a/src/core/MixedCdf.re
+++ b/src/core/MixedCdf.re
@@ -8,8 +8,7 @@ type yPdfPoint = {
 let getY = (t: t, x: float): yPdfPoint => {
   continuous: Shape.Continuous.findY(x, t.continuous),
   discrete: Shape.Discrete.findY(x, t.discrete),
-} /* }*/;
+} /*   discrete: Shape.Discrete.findY(x, t.discrete)*/;
 
 // let getIntegralY = (t: t, x: float): float => {
-//   continuous: Shape.Continuous.findY(x, t.continuous),
-//   discrete: Shape.Discrete.findY(x, t.discrete),
\ No newline at end of file
+//   continuous: Shape.Continuous.findY(x, t.continuous),
\ No newline at end of file
diff --git a/src/core/Shape.re b/src/core/Shape.re
index 507e05a7..7d0ebe06 100644
--- a/src/core/Shape.re
+++ b/src/core/Shape.re
@@ -3,7 +3,7 @@ open DistributionTypes;
 let _lastElement = (a: array('a)) =>
   switch (Belt.Array.size(a)) {
   | 0 => None
-  | n => Belt.Array.get(a, n)
+  | n => Belt.Array.get(a, n - 1)
   };
 
 module XYShape = {
@@ -28,7 +28,8 @@ module XYShape = {
       Belt.Array.zip(p.xs, p.ys)
       ->Belt.Array.reduce([||], (items, (x, y)) =>
           switch (_lastElement(items)) {
-          | Some((_, yLast)) => [|(x, fn(y, yLast))|]
+          | Some((_, yLast)) =>
+            Belt.Array.concat(items, [|(x, fn(y, yLast))|])
           | None => [|(x, y)|]
           }
         )
diff --git a/src/utility/CdfLibrary.js b/src/utility/CdfLibrary.js
index 528e2dda..ab9134de 100644
--- a/src/utility/CdfLibrary.js
+++ b/src/utility/CdfLibrary.js
@@ -1,5 +1,6 @@
 const {
     Cdf,
+    Pdf,
     ContinuousDistribution,
     ContinuousDistributionCombination,
     scoringFunctions,
diff --git a/src/utility/CdfLibrary.re b/src/utility/CdfLibrary.re
index fdc08392..2354331c 100644
--- a/src/utility/CdfLibrary.re
+++ b/src/utility/CdfLibrary.re
@@ -38,7 +38,7 @@ module JS = {
 
 module Distribution = {
   let toPdf = dist => dist |> JS.doAsDist(JS.cdfToPdf);
-  let toCdf = dist => dist |> JS.doAsDist(JS.cdfToPdf);
+  let toCdf = dist => dist |> JS.doAsDist(JS.pdfToCdf);
   let findX = (y, dist) => dist |> JS.distToJs |> JS.findX(y);
   let findY = (x, dist) => dist |> JS.distToJs |> JS.findY(x);
   let integral = dist => dist |> JS.distToJs |> JS.integral;
diff --git a/yarn.lock b/yarn.lock
index fa7acb48..2e276981 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2967,6 +2967,43 @@ d3@5.9.2:
     d3-voronoi "1"
     d3-zoom "1"
 
+d3@^5.15.0:
+  version "5.15.0"
+  resolved "https://registry.yarnpkg.com/d3/-/d3-5.15.0.tgz#ffd44958e6a3cb8a59a84429c45429b8bca5677a"
+  integrity sha512-C+E80SL2nLLtmykZ6klwYj5rPqB5nlfN5LdWEAVdWPppqTD8taoJi2PxLZjPeYT8FFRR2yucXq+kBlOnnvZeLg==
+  dependencies:
+    d3-array "1"
+    d3-axis "1"
+    d3-brush "1"
+    d3-chord "1"
+    d3-collection "1"
+    d3-color "1"
+    d3-contour "1"
+    d3-dispatch "1"
+    d3-drag "1"
+    d3-dsv "1"
+    d3-ease "1"
+    d3-fetch "1"
+    d3-force "1"
+    d3-format "1"
+    d3-geo "1"
+    d3-hierarchy "1"
+    d3-interpolate "1"
+    d3-path "1"
+    d3-polygon "1"
+    d3-quadtree "1"
+    d3-random "1"
+    d3-scale "2"
+    d3-scale-chromatic "1"
+    d3-selection "1"
+    d3-shape "1"
+    d3-time "1"
+    d3-time-format "2"
+    d3-timer "1"
+    d3-transition "1"
+    d3-voronoi "1"
+    d3-zoom "1"
+
 dashdash@^1.12.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"