Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/layerchart/src/routes/_NavMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
'Candlestick',
'Compound',
'Duration',
'DualAxis',
'Histogram',
'Line',
'Oscilloscope',
Expand Down
229 changes: 224 additions & 5 deletions packages/layerchart/src/routes/docs/examples/Compound/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script lang="ts">
import { Area, BarChart, Spline, Tooltip } from 'layerchart';
import { Area, Axis, BarChart, Chart, Highlight, Spline, Svg, Tooltip } from 'layerchart';
import { scaleLinear, scaleTime } from 'd3-scale';
import { extent } from 'd3-array';

import Preview from '$lib/docs/Preview.svelte';
import { createDateSeries } from '$lib/utils/genData.js';
Expand All @@ -17,9 +19,9 @@

<h1>Examples</h1>

<h2>Common scale</h2>
<h2>Common scale with extra marks</h2>

<Preview {data}>
<Preview data={dateSeries}>
<div class="h-[300px] p-4 border rounded-sm">
<BarChart
data={dateSeries}
Expand Down Expand Up @@ -48,9 +50,9 @@
</div>
</Preview>

<h2>Stacked Charts</h2>
<h2>Separate scales with stacked charts and overridden marks</h2>

<Preview {data}>
<Preview data={data.appleTicker}>
<div class="h-[300px] grid grid-stack p-4 border rounded-sm">
<!-- First chart (bar), with different domain scale for volume -->
<BarChart
Expand Down Expand Up @@ -101,3 +103,220 @@
</BarChart>
</div>
</Preview>

<h2>Dual axis with single chart using remapped scale</h2>

<Preview data={data.newPassengerCars}>
<div class="h-[300px] p-4 border rounded-sm">
<!-- Remap efficiency to its equivalent value in sales - https://observablehq.com/@observablehq/plot-dual-axis -->
<Chart
data={data.newPassengerCars}
x="year"
y="sales"
yDomain={[0, null]}
yNice
y1="efficiency"
y1Scale={scaleLinear()}
y1Range={({ yScale }) => yScale.domain()}
padding={{ top: 24, bottom: 24, left: 24, right: 24 }}
tooltip={{ mode: 'bisect-x' }}
>
{#snippet children({ context })}
<Svg>
<Axis
placement="left"
rule
format="metric"
label="↑ sales (M)"
labelPlacement="start"
labelProps={{ class: 'fill-primary' }}
/>
<Axis
placement="right"
scale={scaleLinear(context.y1Scale?.domain() ?? [], [context.height, 0])}
ticks={context.y1Scale?.ticks?.()}
rule
label="efficiency (mpg) ↑"
labelPlacement="start"
labelProps={{ class: 'fill-secondary' }}
/>
<Axis placement="bottom" format="none" rule />
<Spline class="stroke-2 stroke-primary" />
<Spline y={(d) => context.y1Scale?.(d.efficiency)} class="stroke-2 stroke-secondary" />
<Highlight lines points />
<Highlight
points={{ class: 'fill-secondary' }}
y={(d) => context.y1Scale?.(d.efficiency)}
/>
</Svg>

<Tooltip.Root {context}>
{#snippet children({ data })}
<Tooltip.Header>{data.year}</Tooltip.Header>
<Tooltip.List>
<Tooltip.Item label="sales" value={data.sales} format="currencyRound" />
<Tooltip.Item label="efficiency" value={data.efficiency} />
</Tooltip.List>
{/snippet}
</Tooltip.Root>
{/snippet}
</Chart>
</div>
</Preview>

<h2>Dual axis with stacked charts</h2>

<Preview data={data.newPassengerCars}>
<div class="h-[300px] grid grid-stack p-4 border rounded-sm">
<!-- Sales chart-->
<Chart
data={data.newPassengerCars}
x="year"
y="sales"
yDomain={[0, null]}
yNice
padding={{ top: 24, bottom: 24, left: 24, right: 24 }}
>
<Svg>
<Axis
placement="left"
rule
format="metric"
label="↑ sales (M)"
labelPlacement="start"
labelProps={{ class: 'fill-primary' }}
/>
<Axis placement="bottom" format="none" rule />
<Spline class="stroke-2 stroke-primary" />
<Highlight lines points />
</Svg>
</Chart>

<!-- Efficiency chart, provides tooltip for both values -->
<Chart
data={data.newPassengerCars}
x="year"
y="efficiency"
padding={{ top: 24, bottom: 24, left: 24, right: 24 }}
tooltip={{ mode: 'bisect-x' }}
>
<Svg>
<Axis
placement="right"
rule
label="efficiency (mpg) ↑"
labelPlacement="start"
labelProps={{ class: 'fill-secondary' }}
/>
<Spline class="stroke-2 stroke-secondary" />
<!-- Difficult to add points for both charts without using a remaped scale for one value -->
<Highlight lines />
</Svg>

<Tooltip.Root>
{#snippet children({ data })}
<Tooltip.Header>{data.year}</Tooltip.Header>
<Tooltip.List>
<Tooltip.Item label="sales" value={data.sales} format="currencyRound" />
<Tooltip.Item label="efficiency" value={data.efficiency} />
</Tooltip.List>
{/snippet}
</Tooltip.Root>
</Chart>
</div>
</Preview>

<h2>Separate scales with stacked charts with inverted range (top down)</h2>

<Preview data={data.hydro}>
<div class="h-[300px] grid grid-stack p-4 border rounded-sm">
<!-- First chart with inverted yRange (top down) -->
<BarChart
data={data.hydro}
x="date"
y="rain"
axis={{ placement: 'right', tickMarks: false }}
yDomain={[0, 500]}
yRange={({ height }) => [0, height]}
padding={{ left: 32, right: 32, bottom: 20 }}
props={{
bars: {
// TODO: Determine why non-rounded Rect within Bar is not working for inverted range
// rounded: 'none',
class: 'stroke-none fill-blue-500',
},
}}
/>

<BarChart
data={data.hydro}
x="date"
yDomain={[0, 1000]}
padding={{ left: 32, right: 32, bottom: 20 }}
series={[
{
key: 'infiltration',
// TODO: Not sure what to be done with negative values
// value: (d) => Math.abs(d.infiltration),
value: (d) => (d.infiltration > 0 ? d.infiltration : 0),
color: 'hsl(25, 95%, 53%)',
props: {
rounded: 'none',
},
},
{
key: 'dirtyh2o',
color: 'hsl(0, 84%, 60%)',
props: {
rounded: 'none',
},
},
{
key: 'rain_induced',
color: 'hsl(142, 71%, 45%)',
props: {
rounded: 'none',
},
},
]}
seriesLayout="stack"
>
{#snippet axis({ context })}
<Axis placement="left" />
<!-- Provide better axis than band scale currently does with time data-->
<Axis
placement="bottom"
scale={scaleTime(
// @ts-expect-error
extent(data.hydro, (d) => d.date),
[0, context.width]
)}
tickMultiline
rule
/>
{/snippet}

{#snippet tooltip({ context })}
<Tooltip.Root {context}>
{#snippet children({ data })}
<Tooltip.Header value={data.date} format="day" />
<Tooltip.List>
<Tooltip.Item label="rain" color="hsl(200 100% 50%)" value={data.rain} />
<Tooltip.Item
label="infiltration"
color="hsl(25, 95%, 53%)"
value={data.infiltration}
/>
<Tooltip.Item label="dirtyh2o" color="hsl(0, 84%, 60%)" value={data.dirtyh2o} />
<Tooltip.Item
label="rain_induced"
color="hsl(142, 71%, 45%)"
value={data.rain_induced}
/>
</Tooltip.List>
{/snippet}
</Tooltip.Root>
{/snippet}
</BarChart>
</div>
</Preview>
11 changes: 11 additions & 0 deletions packages/layerchart/src/routes/docs/examples/Compound/+page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { autoType, csvParse } from 'd3-dsv';
import { parse } from '@layerstack/utils';

import type { AppleTickerData } from '$static/data/examples/date/apple-ticker.js';
import type { NewPassengerCars } from '$static/data/examples/new-passenger-cars.js';
import type { HydroData } from '$static/data/examples/date/hydro.js';

import pageSource from './+page.svelte?raw';

Expand All @@ -8,6 +12,13 @@ export async function load({ fetch }) {
appleTicker: (await fetch('/data/examples/date/apple-ticker.json').then(async (r) =>
parse(await r.text())
)) as AppleTickerData,
newPassengerCars: await fetch('/data/examples/new-passenger-cars.csv').then(async (r) =>
// @ts-expect-error
csvParse<NewPassengerCars>(await r.text(), autoType)
),
hydro: (await fetch('/data/examples/date/hydro.json').then(async (r) =>
parse(await r.text())
)) as HydroData,
meta: {
pageSource,
related: [
Expand Down
Loading