Skip to content

Pass data type through mark components #113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
146e305
docs: add cell example, figure out solution for passing thru types
gka Jun 6, 2025
bb808d1
improve typing of BarX
gka Jun 6, 2025
baf71cd
improve typing of BarY
gka Jun 6, 2025
1fbf3d8
ts: improve typing of Geo mark
gka Jun 8, 2025
d5b4e18
ts: improve dotx and doty
gka Jun 9, 2025
e6d013f
ts: improve frame
gka Jun 9, 2025
8498487
ts: improve line
gka Jun 9, 2025
89e47b2
ts: line marks
gka Jun 9, 2025
1a5789f
ts: bollinger marks
gka Jun 9, 2025
cabc2d8
ts: brush marks
gka Jun 9, 2025
8ff916c
ts: cell marks
gka Jun 9, 2025
2c0614b
ts: custom mark, screenshots
gka Jun 9, 2025
97b7462
fix
gka Jun 9, 2025
19658b4
fix brush mark
gka Jun 9, 2025
bfad61c
..
gka Jun 9, 2025
3f7bf76
ts: rect mark props
gka Jun 9, 2025
9077f34
fix axis marks
gka Jun 9, 2025
4f60da8
add rect examples
gka Jun 9, 2025
635db6d
increase title margin on axisY
gka Jun 9, 2025
6ee6ea7
ensure that interval ticks stay within domain
gka Jun 9, 2025
165b38b
..
gka Jun 9, 2025
8527c72
tests
gka Jun 10, 2025
8188532
ts: improve area prop type
gka Jun 10, 2025
b263fe6
..
gka Jun 10, 2025
8fcd536
add streamgraph example
gka Jun 10, 2025
5668cbc
docs
gka Jun 10, 2025
6135445
ts: improve arrow prop type
gka Jun 10, 2025
de86fae
remove unused css
gka Jun 11, 2025
114cbab
ts: improve link mark props
gka Jun 11, 2025
2e02df0
ts: improve pointer mark props
gka Jun 11, 2025
225ffff
docs: add link examples
gka Jun 11, 2025
76dc86b
chore: break types into separate files
gka Jun 11, 2025
7f90ed2
fix imports
gka Jun 11, 2025
cd7fc42
ts: improve rule mark props
gka Jun 11, 2025
a952693
fix aapl type
gka Jun 11, 2025
031fa05
docs: add rule examples
gka Jun 11, 2025
5a6edbb
ts: improve sphere mark props
gka Jun 11, 2025
edc97ea
ts: improve spike and vector mark props
gka Jun 11, 2025
17f45dd
ts: improve tick mark props
gka Jun 11, 2025
361043a
docs: add exmaples
gka Jun 11, 2025
df21c51
docs: add spike map example
gka Jun 11, 2025
c17157c
bump dependencies
gka Jun 11, 2025
bb39db8
add ssr
gka Jun 11, 2025
0a1fbb0
add screenshot
gka Jun 11, 2025
75edbb7
more examples
gka Jun 11, 2025
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
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelteplot",
"version": "0.3.3",
"version": "0.3.2",
"license": "ISC",
"author": {
"name": "Gregor Aisch",
Expand Down Expand Up @@ -68,10 +68,14 @@
"@types/d3-geo": "^3.1.0",
"@types/d3-interpolate": "^3.0.4",
"@types/d3-path": "^3.1.1",
"@types/d3-quadtree": "^3.0.6",
"@types/d3-random": "^3.0.3",
"@types/d3-scale": "^4.0.9",
"@types/d3-scale-chromatic": "^3.1.0",
"@types/d3-shape": "^3.1.7",
"@types/geojson": "^7946.0.16",
"@types/topojson": "^3.2.6",
"@types/topojson-client": "^3.1.5",
"@typescript-eslint/eslint-plugin": "^8.34.0",
"@typescript-eslint/parser": "^8.34.0",
"csstype": "^3.1.3",
Expand Down
67 changes: 63 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 50 additions & 1 deletion screenshot-examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const OUTPUT_DIR = path.join(__dirname, 'static', 'examples');
const SCREENSHOT_WIDTH = 600;
const DEVICE_PIXEL_RATIO = 2;

// Only take missing screenshots if ENV variable is set
const ONLY_MISSING = process.env.ONLY_MISSING == 1;

// Start the development server and return server instance and local URL
const startServer = () => {
console.log('Starting development server...');
Expand Down Expand Up @@ -70,6 +73,26 @@ const getSvelteFiles = async (dir) => {
return files.flat();
};

const getExistingScreenshots = async (dir) => {
const entries = await fs.readdir(dir, { withFileTypes: true });

const files = await Promise.all(
entries.map(async (entry) => {
const fullPath = path.join(dir, entry.name);

if (entry.isDirectory()) {
return getExistingScreenshots(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.png')) {
return [fullPath];
}

return [];
})
);

return files.flat();
};

// Convert file path to URL path
const filePathToUrlPath = (filePath) => {
const relativePath = path.relative(EXAMPLES_DIR, filePath);
Expand Down Expand Up @@ -161,9 +184,35 @@ const screenshotExamples = async () => {
});

// Get all example Svelte files
const svelteFiles = await getSvelteFiles(EXAMPLES_DIR);
let svelteFiles = await getSvelteFiles(EXAMPLES_DIR);
console.log(`Found ${svelteFiles.length} example files to screenshot`);

if (ONLY_MISSING) {
// Filter to only include files that don't have screenshots ()
const existingScreenshots = (await getExistingScreenshots(OUTPUT_DIR)).map((file) =>
path.relative(OUTPUT_DIR, file)
);

console.log(`Found ${existingScreenshots.length} existing screenshots`);

// Filter out files that already have screenshots
svelteFiles = svelteFiles.filter((filePath) => {
return (
!existingScreenshots.find((screenshot) =>
filePath.endsWith(screenshot.replace('.png', '.svelte'))
) ||
!existingScreenshots.find((screenshot) =>
filePath.endsWith(screenshot.replace('.dark.png', '.svelte'))
)
);
});

console.log(
`Filtered down to ${svelteFiles.length} files needing screenshots`,
svelteFiles
);
}

// Process each file
for (const filePath of svelteFiles) {
const urlPath = filePathToUrlPath(filePath);
Expand Down
52 changes: 25 additions & 27 deletions src/lib/Mark.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
<script lang="ts">
import { getContext, untrack, type Snippet } from 'svelte';
<script lang="ts" generics="Datum extends DataRecord">
interface MarkProps extends Partial<BaseMarkProps<Datum>> {
data?: Datum[];
automatic?: boolean;
type: MarkType;
channels?: ScaledChannelName[];
required?: ScaledChannelName[];
requiredScales?: Partial<Record<ScaleName, ScaleType[]>>;
children?: Snippet<
[
{
mark: Mark<GenericMarkOptions>;
usedScales: ReturnType<typeof getUsedScales>;
scaledData: ScaledDataRecord[];
}
]
>;
defaults?: Partial<Record<ScaledChannelName, RawValue>>;
}

import { getContext, untrack, type Snippet } from 'svelte';
import { CHANNEL_SCALE, INDEX } from '$lib/constants.js';
import type {
ScaledChannelName,
Expand All @@ -17,32 +35,12 @@
ResolvedDataRecord,
ScaledDataRecord,
ScaleType
} from './types.js';
} from './types/index.js';
import { isEqual } from 'es-toolkit';
import { getUsedScales, projectXY, projectX, projectY } from './helpers/scales.js';
import { testFilter, isValid } from '$lib/helpers/index.js';
import { resolveChannel, resolveProp } from './helpers/resolve.js';

type MarkProps = {
data?: DataRecord[];
automatic?: boolean;
type: MarkType;
channels?: ScaledChannelName[];
required?: ScaledChannelName[];
requiredScales?: Partial<Record<ScaleName, ScaleType[]>>;
children?: Snippet<
[
{
mark: Mark<GenericMarkOptions>;
usedScales: ReturnType<typeof getUsedScales>;
scaledData: ScaledDataRecord[];
}
]
>;
defaults?: Partial<Record<ScaledChannelName, RawValue>>;
} & Partial<Record<ChannelName, ChannelAccessor>> &
Partial<BaseMarkProps>;

let {
data = [],
children,
Expand Down Expand Up @@ -134,13 +132,13 @@
const { getTestFacet } = getContext<FacetContext>('svelteplot/facet');
const testFacet = $derived(getTestFacet());

const resolvedData: ResolvedDataRecord[] = $derived(
const resolvedData: ResolvedDataRecord<Datum>[] = $derived(
data
.map((d, i) => ({ ...d, [INDEX]: i }))
.flatMap((row) => {
const channels = options as Record<ChannelName, ChannelAccessor>;
const channels = options as Record<ChannelName, ChannelAccessor<Datum>>;
if (!testFacet(row, channels) || !testFilter(row, channels)) return [];
const out: ResolvedDataRecord = {
const out: ResolvedDataRecord<Datum> = {
datum: row
};
for (const [channel] of Object.entries(CHANNEL_SCALE) as [
Expand Down Expand Up @@ -208,7 +206,7 @@
*/
const scaledData = $derived(
resolvedData.flatMap((row) => {
const out: ScaledDataRecord = {
const out: ScaledDataRecord<Datum> = {
datum: row.datum,
valid: true
};
Expand Down
3 changes: 1 addition & 2 deletions src/lib/Plot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<script lang="ts">
import Plot from './core/Plot.svelte';

import type { PlotDefaults, PlotOptions } from './types.js';
import type { PlotDefaults, PlotOptions } from './types/index.js';

// implicit marks
import AxisX from './marks/AxisX.svelte';
Expand All @@ -28,7 +28,6 @@
import { autoScale, autoScaleColor } from './helpers/autoScales.js';
import { namedProjection } from './helpers/autoProjection.js';
import { isObject } from './helpers/index.js';
import { getContext } from 'svelte';

let {
header: userHeader,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/Facet.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { setContext, type Snippet } from 'svelte';
import { resolveChannel } from '../helpers/resolve.js';
import type { BaseMarkProps, DataRecord, RawValue } from '../types.js';
import type { BaseMarkProps, DataRecord, RawValue } from '../types/index.js';

let {
fx,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/FacetAxes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
-->
<script lang="ts">
import { getContext } from 'svelte';
import type { PlotContext } from '../types.js';
import type { PlotContext } from '../types/index.js';
import { scaleBand } from 'd3-scale';
import BaseAxisX from '../marks/helpers/BaseAxisX.svelte';
import BaseAxisY from '../marks/helpers/BaseAxisY.svelte';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/FacetGrid.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
-->
<script lang="ts">
import { getContext, type Snippet } from 'svelte';
import type { PlotContext, GenericMarkOptions, Mark } from '../types.js';
import type { PlotContext, GenericMarkOptions, Mark } from '../types/index.js';
import { scaleBand } from 'd3-scale';
import Facet from './Facet.svelte';
import { getEmptyFacets } from '../helpers/facets.js';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/Plot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
PlotDefaults,
PlotState,
RawValue
} from '../types.js';
} from '../types/index.js';
import FacetGrid from './FacetGrid.svelte';

import mergeDeep from '../helpers/mergeDeep.js';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/helpers/autoTicks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function autoTicks(
if (interval) {
const [lo, hi] = extent(domain);
const I = maybeInterval(interval, type);
return I.range(lo, I.offset(hi));
return I.range(lo, I.offset(hi)).filter((d) => d >= lo && d <= hi);
}
return typeof scaleFn.ticks === 'function' ? scaleFn.ticks(count) : [];
}
3 changes: 2 additions & 1 deletion src/lib/helpers/projection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { constant, isObject } from './index.js';
const identity = constant({ stream: (stream) => stream });

const defaultAspectRatio = 0.618;
type Clip = boolean | null | number | 'frame';

export type Clip = boolean | null | number | 'frame';

type ProjectionOptions = {
type: string;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/helpers/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ export function toChannelOption(
};
}

export function resolveChannel(
export function resolveChannel<T>(
channel: ChannelName,
datum: DataRow,
channels: Partial<Record<ChannelName, ChannelAccessor | ChannelAlias>>
datum: DataRow<T>,
channels: Partial<Record<ChannelName, ChannelAccessor<T> | ChannelAlias>>
): RawValue {
const scale = CHANNEL_SCALE[channel];
// the z channel has an automatic alias mechanism
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy