@fjader/svelte 0.2.4 → 0.2.5
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/README.md +1 -1
- package/dist/animation/EntranceGate.d.ts +52 -0
- package/dist/animation/EntranceGate.js +93 -0
- package/dist/animation/TransitionClock.d.ts +61 -30
- package/dist/animation/TransitionClock.js +67 -29
- package/dist/animation/transition-log.d.ts +41 -0
- package/dist/animation/transition-log.js +57 -0
- package/dist/components/axes/AxisBottom.svelte +4 -2
- package/dist/components/axes/AxisCenter.svelte +4 -2
- package/dist/components/axes/AxisLeft.svelte +4 -2
- package/dist/components/axes/BandAxisTicks.svelte +3 -2
- package/dist/components/charts/ChartCell.svelte +32 -5
- package/dist/components/charts/ChartCell.svelte.d.ts +9 -0
- package/dist/components/charts/ChartContainer.svelte +45 -3
- package/dist/components/charts/ChartContainer.svelte.d.ts +7 -1
- package/dist/components/charts/ChartHover.svelte.d.ts +14 -0
- package/dist/components/charts/ChartHover.svelte.js +22 -0
- package/dist/components/charts/ChartVisibility.svelte.d.ts +43 -0
- package/dist/components/charts/ChartVisibility.svelte.js +67 -0
- package/dist/components/guides/Grid.svelte +12 -1
- package/dist/components/marks/AreaMarkX.svelte +16 -4
- package/dist/components/marks/AreaMarkY.svelte +16 -4
- package/dist/components/marks/BarMarkX.svelte +7 -3
- package/dist/components/marks/BarMarkY.svelte +7 -3
- package/dist/components/marks/DotsMark.svelte +6 -3
- package/dist/components/marks/LineMark.svelte +11 -8
- package/dist/components/marks/ParallelCoordinatesMark.svelte +7 -2
- package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +2 -0
- package/dist/components/marks/RectMark.svelte +6 -3
- package/dist/components/marks/RectXMark.svelte +7 -3
- package/dist/components/marks/RectYMark.svelte +7 -3
- package/dist/components/marks/RuleMarkX.svelte +30 -26
- package/dist/components/marks/RuleMarkY.svelte +30 -26
- package/dist/components/marks/TextMark.svelte +44 -5
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +16 -0
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +398 -54
- package/dist/components/marks/lifecycle/domain-queries.d.ts +11 -2
- package/dist/components/marks/lifecycle/domain-queries.js +33 -6
- package/dist/components/marks/lifecycle/domain-registration.d.ts +6 -1
- package/dist/components/marks/lifecycle/domain-registration.js +15 -14
- package/dist/components/marks/lifecycle/other-rows.svelte.d.ts +9 -1
- package/dist/components/marks/lifecycle/other-rows.svelte.js +2 -2
- package/dist/components/marks/lifecycle/query-builder.d.ts +27 -2
- package/dist/components/marks/lifecycle/query-builder.js +23 -20
- package/dist/components/marks/utils/MarkColor.svelte.d.ts +3 -1
- package/dist/components/marks/utils/MarkColor.svelte.js +33 -3
- package/dist/components/marks/utils/MarkSeries.svelte.d.ts +14 -1
- package/dist/components/marks/utils/MarkSeries.svelte.js +25 -1
- package/dist/components/marks/utils/MarkSize.svelte.js +4 -0
- package/dist/components/marks/utils/reactive-config.d.ts +1 -1
- package/dist/components/marks/utils/reactive-config.js +3 -0
- package/dist/components/rendering/Areas.svelte +57 -19
- package/dist/components/rendering/Areas.svelte.d.ts +12 -0
- package/dist/components/rendering/BaseGPURenderer.svelte.d.ts +1 -1
- package/dist/components/rendering/Dots.svelte +23 -3
- package/dist/components/rendering/Dots.svelte.d.ts +6 -0
- package/dist/components/rendering/GridLine.svelte +13 -1
- package/dist/components/rendering/GridLine.svelte.d.ts +5 -0
- package/dist/components/rendering/Lines.svelte +48 -13
- package/dist/components/rendering/Lines.svelte.d.ts +12 -0
- package/dist/components/rendering/ParallelLines.svelte +5 -5
- package/dist/components/rendering/Rects.svelte +51 -11
- package/dist/components/rendering/Rects.svelte.d.ts +16 -2
- package/dist/components/rendering/RuleX.svelte +1 -1
- package/dist/components/rendering/RuleY.svelte +1 -1
- package/dist/components/rendering/WebGPUCanvas.svelte +4 -2
- package/dist/components/rendering/activity-reads.d.ts +41 -24
- package/dist/components/rendering/activity-reads.js +54 -31
- package/dist/components/rendering/uniform-sizes.d.ts +1 -1
- package/dist/components/rendering/uniform-sizes.js +1 -1
- package/dist/config/ChartConfig.svelte.d.ts +7 -0
- package/dist/config/ChartConfig.svelte.js +17 -0
- package/dist/gpu/GPUCoordinator.svelte.d.ts +31 -1
- package/dist/gpu/GPUCoordinator.svelte.js +164 -7
- package/dist/gpu/MorphedChannels.d.ts +11 -2
- package/dist/gpu/MorphedChannels.js +33 -11
- package/dist/gpu/ScaleTemplateSystem.d.ts +20 -2
- package/dist/gpu/ScaleTemplateSystem.js +58 -2
- package/dist/index.d.ts +17 -4
- package/dist/index.js +19 -4
- package/dist/interactors/TooltipManager.svelte.js +14 -5
- package/dist/query-engine/CrossfilterSelection.svelte.d.ts +4 -2
- package/dist/query-engine/CrossfilterSelection.svelte.js +2 -0
- package/dist/query-engine/FieldActivity.svelte.d.ts +2 -3
- package/dist/query-engine/FieldActivity.svelte.js +1 -2
- package/dist/query-engine/MarkHandle.svelte.d.ts +28 -1
- package/dist/query-engine/MarkHandle.svelte.js +33 -1
- package/dist/query-engine/QueryEngine.d.ts +225 -5
- package/dist/query-engine/QueryEngine.js +671 -41
- package/dist/query-engine/categorical-identity.d.ts +34 -8
- package/dist/query-engine/categorical-identity.js +138 -73
- package/dist/query-engine/debug/query-log.d.ts +39 -0
- package/dist/query-engine/debug/query-log.js +90 -0
- package/dist/query-engine/duckdb.d.ts +55 -8
- package/dist/query-engine/duckdb.js +82 -30
- package/dist/query-engine/index.d.ts +7 -4
- package/dist/query-engine/index.js +3 -3
- package/dist/query-engine/preagg/BuildQueue.d.ts +33 -13
- package/dist/query-engine/preagg/BuildQueue.js +51 -15
- package/dist/query-engine/preagg/Preagg.d.ts +46 -3
- package/dist/query-engine/preagg/Preagg.js +159 -31
- package/dist/query-engine/preagg/plan.d.ts +28 -1
- package/dist/query-engine/preagg/plan.js +128 -8
- package/dist/query-engine/sliced-lane.d.ts +108 -0
- package/dist/query-engine/sliced-lane.js +299 -0
- package/dist/query-engine/source-routing.d.ts +106 -0
- package/dist/query-engine/source-routing.js +189 -0
- package/dist/scales/BandScaleState.svelte.d.ts +9 -1
- package/dist/scales/BandScaleState.svelte.js +16 -5
- package/dist/scales/ChartScales.svelte.d.ts +3 -0
- package/dist/scales/ChartScales.svelte.js +26 -8
- package/dist/scales/ColorScaleState.svelte.d.ts +18 -2
- package/dist/scales/ColorScaleState.svelte.js +138 -26
- package/dist/scales/LinearScaleState.svelte.d.ts +7 -10
- package/dist/scales/LinearScaleState.svelte.js +21 -39
- package/dist/scales/ScaleGeneration.svelte.d.ts +48 -0
- package/dist/scales/ScaleGeneration.svelte.js +42 -0
- package/dist/scales/ScaleRegistry.svelte.js +3 -1
- package/dist/scales/SlotTransition.d.ts +15 -1
- package/dist/scales/SlotTransition.js +33 -4
- package/dist/scales/TimeScaleState.svelte.d.ts +7 -3
- package/dist/scales/TimeScaleState.svelte.js +7 -7
- package/dist/scales/color-utils.d.ts +0 -3
- package/dist/scales/color-utils.js +0 -3
- package/dist/scales/entered.d.ts +8 -0
- package/dist/scales/entered.js +10 -0
- package/dist/spec/LazyQueryEngine.js +2 -19
- package/dist/spec/MarkRegistry.d.ts +3 -1
- package/dist/spec/MarkRegistry.js +13 -1
- package/dist/spec/PlotFromSpec.svelte +1 -0
- package/dist/spec/export.js +11 -2
- package/dist/spec/types.d.ts +41 -13
- package/dist/sql/bin.d.ts +25 -0
- package/dist/sql/bin.js +108 -5
- package/dist/transforms/TransformCompiler.d.ts +10 -0
- package/dist/transforms/TransformCompiler.js +26 -0
- package/dist/transforms/index.js +144 -24
- package/dist/types.d.ts +136 -2
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { noteTransition, transitionsObserved } from '../animation/transition-log';
|
|
1
2
|
import { TransitionClock } from '../animation';
|
|
2
3
|
export class SlotTransition {
|
|
3
4
|
#target = new Float32Array(0);
|
|
@@ -197,7 +198,14 @@ export class SlotTransition {
|
|
|
197
198
|
* one). The space is unchanged, existing ids keep their paths, and the copy
|
|
198
199
|
* on resize is exactly right.
|
|
199
200
|
*/
|
|
200
|
-
layout(space, order, idCount
|
|
201
|
+
layout(space, order, idCount,
|
|
202
|
+
/**
|
|
203
|
+
* Land at once rather than travel: every id takes its new slot, leavers
|
|
204
|
+
* go and entrants appear. For a catch-up result, a change nobody just
|
|
205
|
+
* made. It settles the clock, which the marks on this axis share: their
|
|
206
|
+
* values land with it, which is what the caller wants for its chart.
|
|
207
|
+
*/
|
|
208
|
+
instant = false) {
|
|
201
209
|
if (space !== this.#space) {
|
|
202
210
|
this.#space = space;
|
|
203
211
|
this.#discard();
|
|
@@ -211,8 +219,21 @@ export class SlotTransition {
|
|
|
211
219
|
if (id >= 0 && id < target.length)
|
|
212
220
|
target[id] = slot;
|
|
213
221
|
}
|
|
214
|
-
this.#
|
|
222
|
+
this.#layouts++;
|
|
223
|
+
this.#landedLayout = instant ? this.#layouts : 0;
|
|
224
|
+
this.#retarget(shown, instant);
|
|
215
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* The latest layout's number if it landed at once (an instant layout), 0
|
|
228
|
+
* otherwise. What follows from a layout, like a band grid's line opacity,
|
|
229
|
+
* lands with it, once: a number, so a consumer lands only its first write
|
|
230
|
+
* after that layout.
|
|
231
|
+
*/
|
|
232
|
+
get landedLayout() {
|
|
233
|
+
return this.#landedLayout;
|
|
234
|
+
}
|
|
235
|
+
#layouts = 0;
|
|
236
|
+
#landedLayout = 0;
|
|
216
237
|
/**
|
|
217
238
|
* Start a transition without changing what is displayed.
|
|
218
239
|
*
|
|
@@ -310,7 +331,7 @@ export class SlotTransition {
|
|
|
310
331
|
* Fold, then point every id at its new slot, and wake the loop if anything
|
|
311
332
|
* has somewhere to go. `shown` is how many slots are displayed.
|
|
312
333
|
*/
|
|
313
|
-
#retarget(shown) {
|
|
334
|
+
#retarget(shown, instant = false) {
|
|
314
335
|
const target = this.#target;
|
|
315
336
|
const from = this.#from;
|
|
316
337
|
const to = this.#to;
|
|
@@ -383,9 +404,17 @@ export class SlotTransition {
|
|
|
383
404
|
this.#hasLaidOut = true;
|
|
384
405
|
// With no loop to drive it, the clock settles inside the restart, through
|
|
385
406
|
// #onClockRest — the same landing the loop would reach.
|
|
386
|
-
if (moving) {
|
|
407
|
+
if (moving && transitionsObserved()) {
|
|
408
|
+
noteTransition('slots', instant || settled, () => this.clock._affectedChartsArray, 'band slots');
|
|
409
|
+
}
|
|
410
|
+
if (moving && !instant) {
|
|
387
411
|
this.clock.restart();
|
|
388
412
|
}
|
|
413
|
+
else if (moving) {
|
|
414
|
+
// Landed at once: the end the loop would reach, leavers retired now
|
|
415
|
+
// (finish calls #onClockRest).
|
|
416
|
+
this.clock.finish();
|
|
417
|
+
}
|
|
389
418
|
else {
|
|
390
419
|
this.#settle();
|
|
391
420
|
}
|
|
@@ -25,13 +25,17 @@ export declare class TimeScaleState extends LinearScaleState {
|
|
|
25
25
|
* Register a mark's datetime extent.
|
|
26
26
|
* Computes t0, converts all extents to offsets, updates parent.
|
|
27
27
|
*/
|
|
28
|
-
addDatetimeExtent(datetimeRange: [Date | number | bigint | string, Date | number | bigint | string], markId: string
|
|
28
|
+
addDatetimeExtent(datetimeRange: [Date | number | bigint | string, Date | number | bigint | string], markId: string, options?: {
|
|
29
|
+
instant?: boolean;
|
|
30
|
+
}): void;
|
|
29
31
|
/**
|
|
30
32
|
* Register a mark's extent using offset values (seconds from t0).
|
|
31
33
|
* Useful when data is already in offset form (e.g., from binned queries).
|
|
32
34
|
* Converts offsets back to datetimes and delegates to addDatetimeExtent.
|
|
33
35
|
*/
|
|
34
|
-
addOffsetExtent(offsetRange: [number, number], markId: string
|
|
36
|
+
addOffsetExtent(offsetRange: [number, number], markId: string, options?: {
|
|
37
|
+
instant?: boolean;
|
|
38
|
+
}): void;
|
|
35
39
|
/**
|
|
36
40
|
* Remove a mark's datetime extent.
|
|
37
41
|
*/
|
|
@@ -40,7 +44,7 @@ export declare class TimeScaleState extends LinearScaleState {
|
|
|
40
44
|
* Override: apply time-aware nice instead of linear nice.
|
|
41
45
|
* Called by super.addMark via polymorphism.
|
|
42
46
|
*/
|
|
43
|
-
updateExtentFromExtents(nice?: boolean): void;
|
|
47
|
+
updateExtentFromExtents(nice?: boolean, instant?: boolean): void;
|
|
44
48
|
/** The actual database column name (may differ from scale registry key). */
|
|
45
49
|
get sourceField(): string;
|
|
46
50
|
/** The derived column name for this time scale's offsets. */
|
|
@@ -62,7 +62,7 @@ export class TimeScaleState extends LinearScaleState {
|
|
|
62
62
|
* Register a mark's datetime extent.
|
|
63
63
|
* Computes t0, converts all extents to offsets, updates parent.
|
|
64
64
|
*/
|
|
65
|
-
addDatetimeExtent(datetimeRange, markId) {
|
|
65
|
+
addDatetimeExtent(datetimeRange, markId, options = {}) {
|
|
66
66
|
const minDate = toDate(datetimeRange[0]);
|
|
67
67
|
const maxDate = toDate(datetimeRange[1]);
|
|
68
68
|
this.#datetimeExtents.set(markId, [minDate, maxDate]);
|
|
@@ -77,21 +77,21 @@ export class TimeScaleState extends LinearScaleState {
|
|
|
77
77
|
}
|
|
78
78
|
this.#suppressUpdate = false;
|
|
79
79
|
// Single update with time-aware nice
|
|
80
|
-
this.updateExtentFromExtents();
|
|
80
|
+
this.updateExtentFromExtents(true, options.instant);
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
83
|
* Register a mark's extent using offset values (seconds from t0).
|
|
84
84
|
* Useful when data is already in offset form (e.g., from binned queries).
|
|
85
85
|
* Converts offsets back to datetimes and delegates to addDatetimeExtent.
|
|
86
86
|
*/
|
|
87
|
-
addOffsetExtent(offsetRange, markId) {
|
|
87
|
+
addOffsetExtent(offsetRange, markId, options = {}) {
|
|
88
88
|
if (!this.#t0) {
|
|
89
89
|
console.warn(`[TimeScaleState] Cannot add offset extent: t0 not set yet`);
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
92
|
const minDate = this.offsetToDate(offsetRange[0]);
|
|
93
93
|
const maxDate = this.offsetToDate(offsetRange[1]);
|
|
94
|
-
this.addDatetimeExtent([minDate, maxDate], markId);
|
|
94
|
+
this.addDatetimeExtent([minDate, maxDate], markId, options);
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Remove a mark's datetime extent.
|
|
@@ -110,12 +110,12 @@ export class TimeScaleState extends LinearScaleState {
|
|
|
110
110
|
* Override: apply time-aware nice instead of linear nice.
|
|
111
111
|
* Called by super.addMark via polymorphism.
|
|
112
112
|
*/
|
|
113
|
-
updateExtentFromExtents(nice = true) {
|
|
113
|
+
updateExtentFromExtents(nice = true, instant = false) {
|
|
114
114
|
if (this.#suppressUpdate)
|
|
115
115
|
return;
|
|
116
116
|
// If no datetime extents, fall through to linear behavior
|
|
117
117
|
if (this.#datetimeExtents.size === 0) {
|
|
118
|
-
super.updateExtentFromExtents(nice);
|
|
118
|
+
super.updateExtentFromExtents(nice, instant);
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
// Compute global datetime range
|
|
@@ -141,7 +141,7 @@ export class TimeScaleState extends LinearScaleState {
|
|
|
141
141
|
this._setExtent(minOffset, maxOffset);
|
|
142
142
|
}
|
|
143
143
|
this.resetDomainLimits();
|
|
144
|
-
this.resetZoom();
|
|
144
|
+
this.resetZoom(instant);
|
|
145
145
|
}
|
|
146
146
|
// ===========================================================================
|
|
147
147
|
// VIEWMANAGER INTEGRATION
|
|
@@ -26,9 +26,6 @@ export declare function getInterpolator(scheme: string): Interpolator | null;
|
|
|
26
26
|
* Get the color array for an ordinal scheme.
|
|
27
27
|
*/
|
|
28
28
|
export declare function getOrdinalColors(scheme: string): readonly string[] | null;
|
|
29
|
-
/**
|
|
30
|
-
* Determine if a scheme is ordinal (discrete) or continuous.
|
|
31
|
-
*/
|
|
32
29
|
/**
|
|
33
30
|
* All available scheme names, grouped by type.
|
|
34
31
|
*/
|
|
@@ -327,9 +327,6 @@ export function getOrdinalColors(scheme) {
|
|
|
327
327
|
const key = scheme.toLowerCase();
|
|
328
328
|
return ORDINAL_SCHEMES[key] || null;
|
|
329
329
|
}
|
|
330
|
-
/**
|
|
331
|
-
* Determine if a scheme is ordinal (discrete) or continuous.
|
|
332
|
-
*/
|
|
333
330
|
/**
|
|
334
331
|
* All available scheme names, grouped by type.
|
|
335
332
|
*/
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a scale's domain is ready to show: a continuous scale only once a
|
|
3
|
+
* chart drawing it has its marks' first data in (LinearScaleState.entered).
|
|
4
|
+
* Before that its domain is a placeholder, and an axis or grid drawn from it
|
|
5
|
+
* shows [0, 100] for a moment. Scales without the notion (band, point) are
|
|
6
|
+
* always shown.
|
|
7
|
+
*/
|
|
8
|
+
export declare function hasEntered(scale: unknown): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a scale's domain is ready to show: a continuous scale only once a
|
|
3
|
+
* chart drawing it has its marks' first data in (LinearScaleState.entered).
|
|
4
|
+
* Before that its domain is a placeholder, and an axis or grid drawn from it
|
|
5
|
+
* shows [0, 100] for a moment. Scales without the notion (band, point) are
|
|
6
|
+
* always shown.
|
|
7
|
+
*/
|
|
8
|
+
export function hasEntered(scale) {
|
|
9
|
+
return scale?.entered !== false;
|
|
10
|
+
}
|
|
@@ -8,10 +8,7 @@
|
|
|
8
8
|
* DuckDB runs in the browser via @duckdb/duckdb-wasm, loaded from jsDelivr.
|
|
9
9
|
*/
|
|
10
10
|
import { QueryEngine } from '../query-engine/QueryEngine';
|
|
11
|
-
|
|
12
|
-
// Configuration (must be set before first getOrCreateQueryEngine call)
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
/** Inline WASM bytes + worker code (for environments where separate assets can't be served). */
|
|
11
|
+
import { initDuckDB } from '../query-engine/duckdb';
|
|
15
12
|
// ---------------------------------------------------------------------------
|
|
16
13
|
// Singleton QueryEngine
|
|
17
14
|
// ---------------------------------------------------------------------------
|
|
@@ -35,24 +32,10 @@ export async function getOrCreateQueryEngine(userEngine) {
|
|
|
35
32
|
return _enginePromise;
|
|
36
33
|
}
|
|
37
34
|
async function initEngine() {
|
|
38
|
-
_engine = new QueryEngine(await
|
|
35
|
+
_engine = new QueryEngine(await initDuckDB());
|
|
39
36
|
return _engine;
|
|
40
37
|
}
|
|
41
38
|
// ---------------------------------------------------------------------------
|
|
42
|
-
// WASM init (standard CDN bundles)
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
async function initFromWasm() {
|
|
45
|
-
const duckdb = await import('@duckdb/duckdb-wasm');
|
|
46
|
-
const bundles = duckdb.getJsDelivrBundles();
|
|
47
|
-
const bundle = await duckdb.selectBundle(bundles);
|
|
48
|
-
const workerUrl = URL.createObjectURL(new Blob([`importScripts("${bundle.mainWorker}");`], { type: 'text/javascript' }));
|
|
49
|
-
const worker = new Worker(workerUrl);
|
|
50
|
-
const db = new duckdb.AsyncDuckDB(new duckdb.VoidLogger(), worker);
|
|
51
|
-
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
|
|
52
|
-
URL.revokeObjectURL(workerUrl);
|
|
53
|
-
return (await db.connect());
|
|
54
|
-
}
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
39
|
// Data loading (shared across all render calls)
|
|
57
40
|
// ---------------------------------------------------------------------------
|
|
58
41
|
const _loadedTables = new Set();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* and resolves mark spec objects into component props.
|
|
4
4
|
*/
|
|
5
5
|
import type { Component } from 'svelte';
|
|
6
|
-
import type { MarkSpec } from './types';
|
|
6
|
+
import type { MarkSpec, ColorFieldSpec } from './types';
|
|
7
7
|
export declare const MARK_REGISTRY: Record<string, Component<any>>;
|
|
8
8
|
/** Channel prop names that hold FieldSpec values and need resolution. */
|
|
9
9
|
export declare const FIELD_CHANNELS: Set<string>;
|
|
@@ -11,6 +11,8 @@ export declare const FIELD_CHANNELS: Set<string>;
|
|
|
11
11
|
export declare const STROKE_AS_FIELD_MARKS: Set<string>;
|
|
12
12
|
/** Internal mark type → spec mark type. Used by both resolveMarkEntry and exportSpec. */
|
|
13
13
|
export declare const SPEC_MARK_TYPES: Record<string, string>;
|
|
14
|
+
/** A colour channel with explicit `domain`/`range`, which is not a FieldSpec. */
|
|
15
|
+
export declare function isColorFieldSpec(value: unknown): value is ColorFieldSpec;
|
|
14
16
|
/**
|
|
15
17
|
* Convert a MarkSpec into { component, props } for svelte:component rendering.
|
|
16
18
|
* Resolves FieldSpecs, transforms, and selection references.
|
|
@@ -44,6 +44,13 @@ export const SPEC_MARK_TYPES = {
|
|
|
44
44
|
rectx: 'rectX',
|
|
45
45
|
text: 'text'
|
|
46
46
|
};
|
|
47
|
+
/** A colour channel with explicit `domain`/`range`, which is not a FieldSpec. */
|
|
48
|
+
export function isColorFieldSpec(value) {
|
|
49
|
+
return (typeof value === 'object' &&
|
|
50
|
+
value !== null &&
|
|
51
|
+
typeof value.field === 'string' &&
|
|
52
|
+
('domain' in value || 'range' in value));
|
|
53
|
+
}
|
|
47
54
|
/**
|
|
48
55
|
* Convert a MarkSpec into { component, props } for svelte:component rendering.
|
|
49
56
|
* Resolves FieldSpecs, transforms, and selection references.
|
|
@@ -62,11 +69,16 @@ export function resolveMarkEntry(markSpec) {
|
|
|
62
69
|
// Numbers are constants (e.g. r=3), not field references — skip resolution
|
|
63
70
|
if (typeof props[key] === 'number')
|
|
64
71
|
continue;
|
|
72
|
+
// Explicit colours pass through as the colour prop's object form
|
|
73
|
+
if (isColorFieldSpec(props[key]))
|
|
74
|
+
continue;
|
|
65
75
|
props[key] = resolveFieldSpec(props[key]);
|
|
66
76
|
}
|
|
67
77
|
}
|
|
68
78
|
// stroke is data-driven (FieldSpec) on lines, but a CSS constant on areas
|
|
69
|
-
if (STROKE_AS_FIELD_MARKS.has(markSpec.mark) &&
|
|
79
|
+
if (STROKE_AS_FIELD_MARKS.has(markSpec.mark) &&
|
|
80
|
+
props.stroke != null &&
|
|
81
|
+
!isColorFieldSpec(props.stroke)) {
|
|
70
82
|
props.stroke = resolveFieldSpec(props.stroke);
|
|
71
83
|
}
|
|
72
84
|
// Resolve transforms
|
package/dist/spec/export.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* back to spec format using the same types as the spec renderer.
|
|
6
6
|
*/
|
|
7
7
|
import { fieldRefToSpec } from './ExpressionParser';
|
|
8
|
-
import { SPEC_MARK_TYPES, FIELD_CHANNELS, STROKE_AS_FIELD_MARKS } from './MarkRegistry';
|
|
8
|
+
import { SPEC_MARK_TYPES, FIELD_CHANNELS, STROKE_AS_FIELD_MARKS, isColorFieldSpec } from './MarkRegistry';
|
|
9
9
|
/** Props handled specially (not passthrough) or internal-only (skip entirely). */
|
|
10
10
|
const SKIP_PROPS = new Set([
|
|
11
11
|
// Internal — not part of the spec
|
|
@@ -67,13 +67,22 @@ function entryToMarkSpec(entry) {
|
|
|
67
67
|
const val = entry[ch];
|
|
68
68
|
if (val == null)
|
|
69
69
|
continue;
|
|
70
|
+
// Explicit colours: the colour prop's object form is already spec-shaped
|
|
71
|
+
if (isColorFieldSpec(val)) {
|
|
72
|
+
spec[ch] = { ...val };
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
70
75
|
const converted = fieldRefToSpec(val);
|
|
71
76
|
if (converted != null)
|
|
72
77
|
spec[ch] = converted;
|
|
73
78
|
}
|
|
74
79
|
// stroke: data-driven on lines, CSS constant on areas
|
|
75
80
|
if (entry.stroke != null) {
|
|
76
|
-
|
|
81
|
+
const stroke = entry.stroke;
|
|
82
|
+
if (STROKE_AS_FIELD_MARKS.has(entry.markType) && isColorFieldSpec(stroke)) {
|
|
83
|
+
spec.stroke = { ...stroke };
|
|
84
|
+
}
|
|
85
|
+
else if (STROKE_AS_FIELD_MARKS.has(entry.markType)) {
|
|
77
86
|
const converted = fieldRefToSpec(entry.stroke);
|
|
78
87
|
if (converted != null)
|
|
79
88
|
spec.stroke = converted;
|
package/dist/spec/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Fjader Spec Schema — TypeScript interfaces defining the JSON contract
|
|
3
3
|
* between spec producers (Python wrapper, JS API) and the spec renderer.
|
|
4
4
|
*/
|
|
5
|
-
import type { ColorScheme, CurveType, ScaleType, SortConfig } from '../types';
|
|
5
|
+
import type { ColorDomainValue, ColorScheme, CurveType, EntranceMode, ScaleType, SortConfig } from '../types';
|
|
6
6
|
import type { QueryEngine } from '../query-engine/QueryEngine';
|
|
7
7
|
/** A layout item: either a single plot or a nested layout. */
|
|
8
8
|
export type LayoutItem = PlotSpec | {
|
|
@@ -64,6 +64,8 @@ export interface PlotSpec {
|
|
|
64
64
|
xDisableZoom?: boolean;
|
|
65
65
|
yDisableZoom?: boolean;
|
|
66
66
|
legend?: LegendSpec | boolean;
|
|
67
|
+
/** How the marks enter when data first draws; see ChartContainer. Default 'auto'. */
|
|
68
|
+
entrance?: EntranceMode;
|
|
67
69
|
}
|
|
68
70
|
export type InteractorSpec = IntervalXSpec | IntervalYSpec | Interval2DSpec | ToggleSpec | DerivedIntervalSpec;
|
|
69
71
|
export interface IntervalXSpec {
|
|
@@ -97,6 +99,17 @@ export interface DerivedIntervalSpec {
|
|
|
97
99
|
}
|
|
98
100
|
/** A column name, aggregate shorthand ("count()"), or structured object. */
|
|
99
101
|
export type FieldSpec = string | AggregateFieldSpec | BinFieldSpec | WindowFieldSpec | RawSqlFieldSpec;
|
|
102
|
+
/**
|
|
103
|
+
* A colour channel with explicit ordinal colours, as on the Svelte colour prop:
|
|
104
|
+
* `{ "field": "won", "domain": [0, 1], "range": ["#d62728", "#2ca02c"] }`.
|
|
105
|
+
*/
|
|
106
|
+
export interface ColorFieldSpec {
|
|
107
|
+
field: string;
|
|
108
|
+
domain?: ColorDomainValue[];
|
|
109
|
+
range?: string[];
|
|
110
|
+
}
|
|
111
|
+
/** What a colour channel (fill, a line's stroke) accepts. */
|
|
112
|
+
export type ColorChannelSpec = FieldSpec | ColorFieldSpec;
|
|
100
113
|
export interface AggregateFieldSpec {
|
|
101
114
|
aggregate: 'count' | 'sum' | 'avg' | 'min' | 'max' | 'median';
|
|
102
115
|
field?: string;
|
|
@@ -134,9 +147,11 @@ interface BaseMarkSpec {
|
|
|
134
147
|
table: string;
|
|
135
148
|
selection?: string;
|
|
136
149
|
/** How the mark responds to selections in its group; see BaseMarkProps. Default 'auto'. */
|
|
137
|
-
selectionResponse?: 'auto' | 'filter';
|
|
150
|
+
selectionResponse?: 'auto' | 'filter' | 'ignore';
|
|
138
151
|
/** What the mark does with NULL in its categorical channels; see BaseMarkProps. Default 'keep'. */
|
|
139
152
|
nulls?: 'keep' | 'drop';
|
|
153
|
+
/** Whether the chart's entrance waits for this mark's first data; see BaseMarkProps. Default true. */
|
|
154
|
+
holdsEntrance?: boolean;
|
|
140
155
|
scheme?: ColorScheme;
|
|
141
156
|
limit?: number;
|
|
142
157
|
transforms?: TransformSpec[];
|
|
@@ -145,7 +160,10 @@ interface BaseMarkSpec {
|
|
|
145
160
|
x?: string[];
|
|
146
161
|
y?: string[];
|
|
147
162
|
} | null;
|
|
148
|
-
tooltip
|
|
163
|
+
/** Hover tooltips, or options; see BaseMarkProps.tooltip. */
|
|
164
|
+
tooltip?: boolean | {
|
|
165
|
+
sortTable?: boolean;
|
|
166
|
+
};
|
|
149
167
|
tooltipProximity?: 'x' | 'y' | 'xy';
|
|
150
168
|
tip?: (string | '*' | AggregateFieldSpec | LabeledTipFieldSpec)[] | false;
|
|
151
169
|
fitDomain?: 'x' | 'y' | boolean;
|
|
@@ -158,7 +176,7 @@ export interface DotMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
|
158
176
|
mark: 'dot';
|
|
159
177
|
x: FieldSpec;
|
|
160
178
|
y: FieldSpec;
|
|
161
|
-
fill?:
|
|
179
|
+
fill?: ColorChannelSpec | null;
|
|
162
180
|
opacity?: number;
|
|
163
181
|
r?: number | FieldSpec;
|
|
164
182
|
radiusRange?: [number, number];
|
|
@@ -169,7 +187,7 @@ export interface BarXMarkSpec extends BaseMarkSpec {
|
|
|
169
187
|
x1?: FieldSpec;
|
|
170
188
|
x2?: FieldSpec;
|
|
171
189
|
y: FieldSpec;
|
|
172
|
-
fill?:
|
|
190
|
+
fill?: ColorChannelSpec | null;
|
|
173
191
|
opacity?: number;
|
|
174
192
|
padding?: number;
|
|
175
193
|
paddingInner?: number;
|
|
@@ -177,6 +195,11 @@ export interface BarXMarkSpec extends BaseMarkSpec {
|
|
|
177
195
|
inset?: number;
|
|
178
196
|
dx?: number;
|
|
179
197
|
dy?: number;
|
|
198
|
+
/**
|
|
199
|
+
* `false`: follow the band axis the other marks on it decide, adding no
|
|
200
|
+
* categories to it; see BaseMarkProps. Default `true`.
|
|
201
|
+
*/
|
|
202
|
+
contributeDomain?: boolean;
|
|
180
203
|
}
|
|
181
204
|
export interface BarYMarkSpec extends BaseMarkSpec {
|
|
182
205
|
mark: 'barY';
|
|
@@ -184,7 +207,7 @@ export interface BarYMarkSpec extends BaseMarkSpec {
|
|
|
184
207
|
y: FieldSpec;
|
|
185
208
|
y1?: FieldSpec;
|
|
186
209
|
y2?: FieldSpec;
|
|
187
|
-
fill?:
|
|
210
|
+
fill?: ColorChannelSpec | null;
|
|
188
211
|
opacity?: number;
|
|
189
212
|
padding?: number;
|
|
190
213
|
paddingInner?: number;
|
|
@@ -192,12 +215,17 @@ export interface BarYMarkSpec extends BaseMarkSpec {
|
|
|
192
215
|
inset?: number;
|
|
193
216
|
dx?: number;
|
|
194
217
|
dy?: number;
|
|
218
|
+
/**
|
|
219
|
+
* `false`: follow the band axis the other marks on it decide, adding no
|
|
220
|
+
* categories to it; see BaseMarkProps. Default `true`.
|
|
221
|
+
*/
|
|
222
|
+
contributeDomain?: boolean;
|
|
195
223
|
}
|
|
196
224
|
export interface LineMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
197
225
|
mark: 'line';
|
|
198
226
|
x: FieldSpec;
|
|
199
227
|
y: FieldSpec;
|
|
200
|
-
stroke?:
|
|
228
|
+
stroke?: ColorChannelSpec | null;
|
|
201
229
|
z?: FieldSpec | null;
|
|
202
230
|
strokeWidth?: number;
|
|
203
231
|
dotRadius?: number;
|
|
@@ -222,7 +250,7 @@ export interface AreaYMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
|
222
250
|
y: FieldSpec;
|
|
223
251
|
y1?: FieldSpec;
|
|
224
252
|
y2?: FieldSpec;
|
|
225
|
-
fill?:
|
|
253
|
+
fill?: ColorChannelSpec | null;
|
|
226
254
|
z?: FieldSpec | null;
|
|
227
255
|
fillOpacity?: number;
|
|
228
256
|
stroke?: string | null;
|
|
@@ -237,7 +265,7 @@ export interface AreaXMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
|
237
265
|
x: FieldSpec;
|
|
238
266
|
x1?: FieldSpec;
|
|
239
267
|
x2?: FieldSpec;
|
|
240
|
-
fill?:
|
|
268
|
+
fill?: ColorChannelSpec | null;
|
|
241
269
|
z?: FieldSpec | null;
|
|
242
270
|
fillOpacity?: number;
|
|
243
271
|
stroke?: string | null;
|
|
@@ -254,7 +282,7 @@ export interface RectMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
|
254
282
|
y?: FieldSpec | null;
|
|
255
283
|
y1?: FieldSpec | null;
|
|
256
284
|
y2?: FieldSpec | null;
|
|
257
|
-
fill?:
|
|
285
|
+
fill?: ColorChannelSpec | null;
|
|
258
286
|
opacity?: number;
|
|
259
287
|
padding?: number;
|
|
260
288
|
paddingInner?: number;
|
|
@@ -271,7 +299,7 @@ export interface RectXMarkSpec extends BaseMarkSpec {
|
|
|
271
299
|
y?: FieldSpec | null;
|
|
272
300
|
y1?: FieldSpec | null;
|
|
273
301
|
y2?: FieldSpec | null;
|
|
274
|
-
fill?:
|
|
302
|
+
fill?: ColorChannelSpec | null;
|
|
275
303
|
opacity?: number;
|
|
276
304
|
inset?: number;
|
|
277
305
|
dx?: number;
|
|
@@ -287,7 +315,7 @@ export interface RectYMarkSpec extends BaseMarkSpec {
|
|
|
287
315
|
y: FieldSpec;
|
|
288
316
|
y1?: FieldSpec;
|
|
289
317
|
y2?: FieldSpec;
|
|
290
|
-
fill?:
|
|
318
|
+
fill?: ColorChannelSpec | null;
|
|
291
319
|
opacity?: number;
|
|
292
320
|
inset?: number;
|
|
293
321
|
dx?: number;
|
|
@@ -300,7 +328,7 @@ export interface TextMarkSpec extends BaseMarkSpec, ContinuousScaleTypeSpec {
|
|
|
300
328
|
x: FieldSpec;
|
|
301
329
|
y: FieldSpec;
|
|
302
330
|
text: FieldSpec;
|
|
303
|
-
fill?:
|
|
331
|
+
fill?: ColorChannelSpec | null;
|
|
304
332
|
fontSize?: number;
|
|
305
333
|
fontWeight?: string;
|
|
306
334
|
fontFamily?: string | null;
|
package/dist/sql/bin.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExprNode, BinHistogramOptions, BinDateOptions } from '@uwdata/mosaic-sql';
|
|
2
|
+
import type { BinPadding } from '../types';
|
|
2
3
|
type BinOptions = BinHistogramOptions & BinDateOptions;
|
|
3
4
|
interface FieldStats {
|
|
4
5
|
column: string;
|
|
@@ -9,14 +10,38 @@ interface FieldInfo {
|
|
|
9
10
|
max?: number;
|
|
10
11
|
type?: string;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The edge of numeric bin `index` (SQL), `min + alpha * (index + offset)`, in
|
|
15
|
+
* DOUBLE arithmetic. The one formula both `bin()` and `dense()`'s padding
|
|
16
|
+
* write, so a bin's edge is the same bits whichever produced it: a padded row
|
|
17
|
+
* then merges with a real one, and a mark's rows are the same bits whether
|
|
18
|
+
* they came from the base table or a preagg table.
|
|
19
|
+
*/
|
|
20
|
+
export declare function numericBinEdgeSQL(min: number, alpha: number, offset: number, index: string): string;
|
|
12
21
|
export declare function bin(field: string | ExprNode, options?: BinOptions): AutoBinNode;
|
|
13
22
|
export declare class AutoBinNode {
|
|
23
|
+
#private;
|
|
14
24
|
field: string | ExprNode;
|
|
15
25
|
options: BinOptions;
|
|
16
26
|
isAutoBinNode: true;
|
|
17
27
|
constructor(field: string | ExprNode, options?: BinOptions);
|
|
18
28
|
get stats(): FieldStats;
|
|
19
29
|
resolve(fieldInfo: Record<string, FieldInfo>, scaleType: string, timeOffset?: number | null, currentDomain?: [number, number] | null, binStepMultiplier?: number): ExprNode;
|
|
30
|
+
/**
|
|
31
|
+
* The bins `resolve` produces with the same arguments: every bin a value of
|
|
32
|
+
* the field can fall in. What `dense()` pads a histogram from, so a bin
|
|
33
|
+
* emptied by a filter stays as a zero row and the bars can morph.
|
|
34
|
+
*
|
|
35
|
+
* Numeric bins as numbers, edge k at `min + alpha * (k + offset)`. Time
|
|
36
|
+
* buckets as the interval `time_bucket` steps by, and the field's extent;
|
|
37
|
+
* those need `t0`, the time scale's origin in epoch seconds, because a time
|
|
38
|
+
* channel is drawn as seconds from it, and are null without it (before the
|
|
39
|
+
* scale has one, the channel is not rewritten either).
|
|
40
|
+
*
|
|
41
|
+
* Null for a field with a single value, which binHistogram floors instead
|
|
42
|
+
* of binning.
|
|
43
|
+
*/
|
|
44
|
+
padding(fieldInfo: Record<string, FieldInfo>, scaleType: string, currentDomain?: [number, number] | null, binStepMultiplier?: number, t0?: number | null): BinPadding | null;
|
|
20
45
|
withOffset(offset: number): AutoBinNode;
|
|
21
46
|
}
|
|
22
47
|
export declare function isBinExpression(expr: unknown): expr is AutoBinNode;
|