@fjader/svelte 0.2.2 → 0.2.3

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.
Files changed (118) hide show
  1. package/dist/components/axes/BandAxisTicks.svelte +63 -24
  2. package/dist/components/axes/BandAxisTicks.svelte.d.ts +5 -5
  3. package/dist/components/charts/ChartContainer.svelte +2 -1
  4. package/dist/components/guides/legend/ContinuousColorLegend.svelte +2 -1
  5. package/dist/components/guides/legend/OrdinalColorLegend.svelte +92 -34
  6. package/dist/components/marks/AreaMarkX.svelte +19 -6
  7. package/dist/components/marks/AreaMarkY.svelte +19 -6
  8. package/dist/components/marks/BarMarkX.svelte +3 -0
  9. package/dist/components/marks/BarMarkY.svelte +3 -0
  10. package/dist/components/marks/DotsMark.svelte +3 -0
  11. package/dist/components/marks/LineMark.svelte +3 -0
  12. package/dist/components/marks/ParallelCoordinatesMark.svelte +6 -0
  13. package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +3 -0
  14. package/dist/components/marks/RectMark.svelte +3 -0
  15. package/dist/components/marks/RectXMark.svelte +3 -0
  16. package/dist/components/marks/RectYMark.svelte +3 -0
  17. package/dist/components/marks/RuleMarkX.svelte +10 -2
  18. package/dist/components/marks/RuleMarkY.svelte +10 -2
  19. package/dist/components/marks/TextMark.svelte +68 -4
  20. package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +15 -1
  21. package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +116 -27
  22. package/dist/components/marks/lifecycle/domain-queries.js +13 -11
  23. package/dist/components/marks/lifecycle/transform-scale-key.d.ts +16 -0
  24. package/dist/components/marks/lifecycle/transform-scale-key.js +27 -0
  25. package/dist/components/marks/utils/area-outline.d.ts +24 -0
  26. package/dist/components/marks/utils/area-outline.js +10 -0
  27. package/dist/components/marks/utils/reactive-config.d.ts +1 -1
  28. package/dist/components/marks/utils/reactive-config.js +3 -0
  29. package/dist/components/rendering/Areas.svelte +30 -6
  30. package/dist/components/rendering/Areas.svelte.d.ts +2 -0
  31. package/dist/components/rendering/BaseGPURenderer.svelte.js +4 -1
  32. package/dist/components/rendering/Dots.svelte +24 -3
  33. package/dist/components/rendering/Dots.svelte.d.ts +2 -0
  34. package/dist/components/rendering/GridLine.svelte +2 -1
  35. package/dist/components/rendering/Lines.svelte +49 -7
  36. package/dist/components/rendering/Lines.svelte.d.ts +9 -0
  37. package/dist/components/rendering/ParallelLines.svelte +26 -7
  38. package/dist/components/rendering/ParallelLines.svelte.d.ts +2 -0
  39. package/dist/components/rendering/Rects.svelte +20 -5
  40. package/dist/components/rendering/Rects.svelte.d.ts +2 -0
  41. package/dist/components/rendering/RuleX.svelte +20 -5
  42. package/dist/components/rendering/RuleX.svelte.d.ts +2 -0
  43. package/dist/components/rendering/RuleY.svelte +20 -5
  44. package/dist/components/rendering/RuleY.svelte.d.ts +2 -0
  45. package/dist/components/rendering/activity-reads.d.ts +93 -0
  46. package/dist/components/rendering/activity-reads.js +135 -0
  47. package/dist/components/rendering/uniform-sizes.d.ts +26 -0
  48. package/dist/components/rendering/uniform-sizes.js +28 -0
  49. package/dist/config/ChartConfig.svelte.d.ts +2 -0
  50. package/dist/gpu/ColorScaleShaderLib.d.ts +13 -1
  51. package/dist/gpu/ColorScaleShaderLib.js +56 -5
  52. package/dist/gpu/GPUCoordinator.svelte.d.ts +8 -0
  53. package/dist/gpu/GPUCoordinator.svelte.js +68 -32
  54. package/dist/gpu/ResolveShader.d.ts +2 -2
  55. package/dist/gpu/ResolveShader.js +2 -2
  56. package/dist/gpu/ScaleTemplateSystem.d.ts +19 -0
  57. package/dist/gpu/ScaleTemplateSystem.js +86 -7
  58. package/dist/gpu/SizeScaleShaderLib.d.ts +4 -4
  59. package/dist/gpu/SizeScaleShaderLib.js +4 -4
  60. package/dist/gpu/identity-slot-packing.d.ts +157 -40
  61. package/dist/gpu/identity-slot-packing.js +262 -62
  62. package/dist/gpu/tracked-scales.d.ts +14 -0
  63. package/dist/gpu/tracked-scales.js +18 -0
  64. package/dist/index.js +1 -0
  65. package/dist/interactors/BandLabelToggle.svelte +5 -9
  66. package/dist/interactors/BandLabelToggle.svelte.d.ts +3 -3
  67. package/dist/interactors/DerivedInterval1D.svelte +26 -54
  68. package/dist/interactors/Interval1D.svelte +2 -1
  69. package/dist/interactors/Interval2D.svelte +2 -1
  70. package/dist/interactors/ParallelAxisSource.svelte +4 -4
  71. package/dist/interactors/ParallelAxisSource.svelte.d.ts +2 -1
  72. package/dist/interactors/ParallelBrushes.svelte +8 -9
  73. package/dist/interactors/ParallelBrushes.svelte.d.ts +3 -3
  74. package/dist/interactors/Toggle.svelte +17 -36
  75. package/dist/interactors/Toggle.svelte.d.ts +4 -3
  76. package/dist/interactors/Tooltip.svelte +2 -1
  77. package/dist/interactors/TooltipManager.svelte.js +8 -3
  78. package/dist/interactors/relay-clauses.d.ts +23 -0
  79. package/dist/interactors/relay-clauses.js +60 -0
  80. package/dist/query-engine/CrossfilterSelection.svelte.d.ts +88 -15
  81. package/dist/query-engine/CrossfilterSelection.svelte.js +94 -20
  82. package/dist/query-engine/FieldActivity.svelte.d.ts +79 -0
  83. package/dist/query-engine/FieldActivity.svelte.js +207 -0
  84. package/dist/query-engine/FilterGroup.svelte.d.ts +53 -29
  85. package/dist/query-engine/FilterGroup.svelte.js +181 -122
  86. package/dist/query-engine/FilterGroupRegistry.svelte.d.ts +42 -0
  87. package/dist/query-engine/FilterGroupRegistry.svelte.js +103 -1
  88. package/dist/query-engine/MarkHandle.svelte.d.ts +9 -1
  89. package/dist/query-engine/MarkHandle.svelte.js +12 -2
  90. package/dist/query-engine/QueryEngine.d.ts +52 -16
  91. package/dist/query-engine/QueryEngine.js +90 -28
  92. package/dist/query-engine/categorical-identity.d.ts +99 -27
  93. package/dist/query-engine/categorical-identity.js +210 -51
  94. package/dist/query-engine/index.d.ts +2 -1
  95. package/dist/query-engine/index.js +1 -0
  96. package/dist/query-engine/preagg/Preagg.d.ts +1 -1
  97. package/dist/query-engine/preagg/Preagg.js +11 -9
  98. package/dist/query-engine/preagg/plan.d.ts +9 -5
  99. package/dist/query-engine/preagg/plan.js +13 -11
  100. package/dist/query-engine/toggle-predicate.js +12 -1
  101. package/dist/scales/ActivityTable.d.ts +99 -0
  102. package/dist/scales/ActivityTable.js +211 -0
  103. package/dist/scales/BandScaleState.svelte.d.ts +28 -7
  104. package/dist/scales/BandScaleState.svelte.js +55 -20
  105. package/dist/scales/ChartScales.svelte.d.ts +2 -2
  106. package/dist/scales/ColorScaleState.svelte.d.ts +36 -8
  107. package/dist/scales/ColorScaleState.svelte.js +118 -24
  108. package/dist/scales/DomainResolver.d.ts +2 -0
  109. package/dist/scales/DomainResolver.js +15 -8
  110. package/dist/scales/ScaleRegistry.svelte.d.ts +9 -0
  111. package/dist/scales/ScaleRegistry.svelte.js +22 -1
  112. package/dist/scales/TimeScaleState.svelte.js +7 -1
  113. package/dist/spec/index.js +1 -0
  114. package/dist/spec/types.d.ts +2 -0
  115. package/dist/transforms/index.d.ts +27 -0
  116. package/dist/transforms/index.js +97 -3
  117. package/dist/types.d.ts +30 -0
  118. package/package.json +1 -1
@@ -18,12 +18,45 @@
18
18
  * on it. It is a pure function over plain arrays and maps, which is
19
19
  * what it should have been.
20
20
  *
21
- * Layout: index 0 is a permanent zero-length block, then one block per scale of
22
- * `[count, slot0, slot1, ...]`. The count header makes each block
23
- * self-describing, so the shader rejects an id past this scale's end instead of
24
- * reading into the next scale's slots — ids and the slot table can disagree
25
- * transiently while a dim appends. Budget is therefore
26
- * `capacity - 1 - (1 per scale)` slots.
21
+ * LAYOUT. Index 0 is a permanent empty block `[0, 0, 0]`. Then one SLOT
22
+ * block per scale, then one ACTIVITY block per live categorical field:
23
+ *
24
+ * scale block: [count, actRef, n, slot0 … slot(count-1)]
25
+ * field block: [group 0: act0 … act(n-1), group 1: act0 … act(n-1), …]
26
+ *
27
+ * Slots come first so that when the buffer runs out it is activity that is
28
+ * lost (a mark draws undimmed), never an axis. A field has a block while a
29
+ * scale draws it, selected on or not, and a field no chart draws any more
30
+ * frees its space. Tying the block to the selection instead saved that space
31
+ * on pages with nothing selected, but every select and clear then moved the
32
+ * block and rewrote every scale block pointing at it, slots included:
33
+ * measured at about 105000 floats uploaded per click for 20 scales on a
34
+ * 5000-category field, against 5000 when the block stays.
35
+ *
36
+ * KNOWN LIMIT: a field block that does not fit leaves a selection on that
37
+ * field doing nothing for the marks that dim by it. Routing (the mark's reads,
38
+ * see activity-reads.ts) still sends them to dim rather than filter, and their
39
+ * shader finds no activity. Routing does not ask the packer whether a field
40
+ * got a block, which would tie the query layer to the GPU layout; the packer
41
+ * warns instead, on load. It takes fields of tens of thousands of ids across
42
+ * several groups to reach. A buffer that grows on demand is the real fix.
43
+ *
44
+ * A scale block's header says how many ids its slots cover (`count`), where its
45
+ * field's activity block starts (`actRef`) and how many ids that block covers
46
+ * (`n`). The count is what makes a block self-describing, so the shader rejects
47
+ * an id past this scale's end instead of reading into the next scale's slots —
48
+ * ids and the slot table can disagree transiently while a dim appends.
49
+ *
50
+ * ACTIVITY says how selected each id is in each filter group (1 active, 0
51
+ * inactive; see FieldActivity). It belongs to the field, not to the scale:
52
+ * every scale on one field reads the same block, a mark choosing its group's
53
+ * half by its group index. So a click rewrites and resolves one half of one
54
+ * field block, however many scales draw that field. The header comes first so
55
+ * the shader finds `actRef` and `n` without reading `count`: the activity read
56
+ * is two dependent loads, as it was when the activity sat after the slots. No
57
+ * mark holds `actRef`; the packer writes it in the same pass that moves the
58
+ * field block, so it cannot go stale. A scale with no field to dim points at
59
+ * the empty block, where `n` is 0 and every id is active.
27
60
  *
28
61
  * TWO buffers share one set of offsets: `from` is where each id's current
29
62
  * transition started and `to` where it is going, and the resolve kernel writes
@@ -31,28 +64,43 @@
31
64
  * bindings rather than two runs in one buffer, so the halves line up at the
32
65
  * same base and one dispatch per block covers both.
33
66
  *
34
- * `t` is not in the buffers. It is PER SCALE — each band scale has its own
35
- * driver — and reaches the kernel as an immediate on that scale's dispatch, so
36
- * a frame where only `t` moved uploads nothing at all.
67
+ * `t` is not in the buffers. It is per scale (its data clock) and per field
68
+ * half (that group's selection clock), and reaches the kernel as an immediate
69
+ * on that range's dispatch, so a frame where only `t` moved uploads nothing.
37
70
  */
38
71
  /**
39
72
  * Floats GLOBALLY across every band and point scale on the page, headers
40
- * included.
73
+ * included, and every live field's activity.
41
74
  *
42
75
  * No longer a binding limit: the tables are storage buffers, bound only to the
43
- * resolve pass, and the render stages read one resolved storage buffer. The
44
- * number is left over from when they were 64 KB uniforms, and making the
45
- * allocation grow on demand (recreate the buffers, rebuild the bind groups) is
46
- * what would retire it.
76
+ * resolve pass, and the render stages read one resolved storage buffer. Making
77
+ * the allocation grow on demand (recreate the buffers, rebuild the bind groups)
78
+ * is what would retire it.
79
+ *
80
+ * Each scale takes `3 + count`; each live field `n × groups`. 65536 fits a
81
+ * 5000-category field selected on across 3 groups (15000) with its scales
82
+ * (about 5000 each) several times over. It costs 256 KB per buffer, 768 KB for
83
+ * the three; the resolve pass dispatches per block, sized by the block, so a
84
+ * larger buffer costs no GPU time.
47
85
  */
48
- export declare const IDENTITY_SLOT_CAPACITY = 16384;
86
+ export declare const IDENTITY_SLOT_CAPACITY = 65536;
49
87
  /**
50
- * Base of the permanent zero-length block. A scale that cannot be placed points
51
- * here, so every lookup finds count 0 and discards — which is what the capacity
52
- * warning claims happens. Pointing it at a stale base instead left the scale
53
- * rendering, from another scale's slots.
88
+ * Base of the permanent empty block `[0, 0, 0]`. A scale that cannot be placed
89
+ * points here, so every lookup finds count 0 and discards, and every activity
90
+ * read finds n 0 and is fully active. Pointing it at a stale base instead left
91
+ * the scale rendering, from another scale's slots.
54
92
  */
55
93
  export declare const IDENTITY_SLOT_EMPTY = 0;
94
+ /**
95
+ * The group index of a mark that reads no selection activity: identityActivity
96
+ * returns fully active for it before computing any offset, so it never indexes
97
+ * past a field block. A mark whose selectionResponse is 'filter' gets it: in
98
+ * the chart holding a selection's control it keeps its data (the chart skips
99
+ * its own selection), and this keeps it from dimming there too.
100
+ */
101
+ export declare const NO_GROUP = 4294967295;
102
+ /** Floats before a scale block's slots: count, actRef, n. */
103
+ export declare const IDENTITY_SLOT_HEADER = 3;
56
104
  /**
57
105
  * One scale's slot table as the packer reads it: identity id -> display slot,
58
106
  * as the two ends of a transition and where between them it is.
@@ -73,17 +121,51 @@ export interface SlotSource {
73
121
  /** Bumped whenever `from` or `to` move; the packer re-uploads on it alone. */
74
122
  readonly version: number;
75
123
  }
76
- /** A scale with a slot table, as the packer needs it. */
124
+ /**
125
+ * One group's activity on one field as the packer reads it: 1 active, 0
126
+ * inactive, as the two ends of a fade. ActivityTable has this shape.
127
+ *
128
+ * Its length is not trusted: the packer takes `n` from the field and pads with
129
+ * 1 or truncates, so a moment where the two disagree cannot shift the half onto
130
+ * the wrong ids.
131
+ */
132
+ export interface ActivitySource {
133
+ readonly from: Float32Array;
134
+ readonly to: Float32Array;
135
+ /** 0 -> from, 1 -> to. Its own clock, not the slots'. */
136
+ readonly t: number;
137
+ /** Bumped whenever `from` or `to` change. */
138
+ readonly version: number;
139
+ }
140
+ /**
141
+ * A scale with a slot table, as the packer needs it: its slots, and the identity
142
+ * key of its field, whose activity block its header points at. No field (or a
143
+ * field with no activity block) points it at the empty block.
144
+ */
77
145
  export interface IdentitySlotScale {
78
146
  id: string;
79
147
  slots: SlotSource;
148
+ field?: string | null;
80
149
  }
81
150
  /**
82
- * One block to resolve this frame: `length` floats from `base`, at `t`.
151
+ * A categorical field's selection activity, as the packer reads it: one fade
152
+ * per filter group, over `count` ids. FieldActivity has this shape.
153
+ */
154
+ export interface ActivityField {
155
+ readonly key: string;
156
+ /** Ids covered: the block's `n`. */
157
+ readonly count: number;
158
+ /** Group `index`'s fade, or null when that group never selected here (all 1). */
159
+ fadeOf(index: number): ActivitySource | null;
160
+ }
161
+ /**
162
+ * One range to resolve this frame: `length` floats from `base`, at `t`. A
163
+ * scale's slots and each group's half of a field block are separate ranges,
164
+ * since each has its own `t`.
83
165
  *
84
- * The count header is inside the range rather than skipped: it holds the same
85
- * value in both halves, so mixing it returns it, and the render stages read
86
- * their bound from the resolved copy. Pooled in the state and overwritten by
166
+ * The header is inside the slot range rather than skipped: it holds the same
167
+ * values in both buffers, so the kernel returns them exactly, and the render
168
+ * stages read it from the resolved copy. Pooled in the state and overwritten by
87
169
  * the next pack.
88
170
  */
89
171
  export interface ResolveBlock {
@@ -116,30 +198,65 @@ export interface IdentitySlotState {
116
198
  offsets: Map<string, number>;
117
199
  /** Last packed slotVersion per scale, so a static chart re-uploads nothing. */
118
200
  versions: Map<string, number>;
201
+ /** Last packed count per scale. */
202
+ counts: Map<string, number>;
203
+ /** Last packed actRef and n per scale: a field block that moved rewrites the header. */
204
+ refs: Map<string, number>;
205
+ ns: Map<string, number>;
206
+ /**
207
+ * The `t` each scale's slots were last resolved at, so a still frame
208
+ * dispatches nothing. A typed array per scale, created once, rather than a
209
+ * `Map<string, number>`: a fractional `t` stored as a Map value is boxed,
210
+ * which allocated on every frame of every transition.
211
+ */
212
+ resolvedT: Map<string, Float64Array>;
213
+ /** Per field: its block's base, `n` and the group count it was packed for. */
214
+ fieldBases: Map<string, number>;
215
+ fieldNs: Map<string, number>;
216
+ fieldGroups: Map<string, number>;
217
+ /** Per field, per group: the fade version last written and the `t` last resolved. */
218
+ fieldVersions: Map<string, Float64Array>;
219
+ fieldT: Map<string, Float64Array>;
220
+ /** The pass a scale last drew each field in: a field no scale draws gets no block. */
221
+ fieldSeen: Map<string, number>;
222
+ /** Fields whose block did not fit, warned about once until they fit again. */
223
+ warnedFields: Set<string>;
119
224
  /**
120
- * The `t` each scale's block was last resolved at, so a still frame
121
- * dispatches nothing and an animating one dispatches only the scales that
122
- * are moving.
225
+ * The pass each scale was last seen in, for the eviction sweep.
226
+ *
227
+ * A pass counter rather than a Set cleared every pack: clearing a Set
228
+ * allocates a new table in V8, which made every frame allocate ~370 bytes
229
+ * (measured, 20 scales) even when nothing moved. Re-setting an existing key
230
+ * to a small integer allocates nothing.
123
231
  */
124
- resolvedT: Map<string, number>;
125
- /** Scratch for the eviction sweep; cleared, not reallocated, per pack. */
126
- seen: Set<string>;
232
+ seenPass: Map<string, number>;
233
+ /** The current pass, a small integer that wraps. */
234
+ pass: number;
127
235
  /** Returned by every pack and overwritten by the next — read it immediately. */
128
236
  result: PackResult;
129
237
  }
130
238
  /** A state with the permanent empty block in place. */
131
239
  export declare function createIdentitySlotState(capacity?: number): IdentitySlotState;
132
240
  /**
133
- * Assign every scale a base, write the blocks that moved, and list what to
134
- * upload and what to resolve.
241
+ * Assign every field and scale a base, write the ranges that moved, and list
242
+ * what to upload and what to resolve.
243
+ *
244
+ * | Range | Rewritten when | Resolved when |
245
+ * |---|---|---|
246
+ * | A field's group half | its base, `n` or the group count moved, or that group's fade version | rewritten, or that fade's `t` moved |
247
+ * | A scale's header + slots | its base, slot version, or its field block's base or `n` moved | rewritten, or slot `t` moved |
248
+ *
249
+ * A range that is rewritten must be resolved even when its `t` did not move:
250
+ * the render stages read the resolved buffer, not these. A parked scale is
251
+ * neither rewritten nor resolved: it has no block, and the empty block it
252
+ * points at is never written.
135
253
  *
136
- * A block is REWRITTEN when its base or its version moved, and RESOLVED when it
137
- * was rewritten or its `t` moved. A parked scale is neither: it has no block,
138
- * and the empty block it points at is never written.
254
+ * Offsets are recomputed on every call because a block appearing or
255
+ * disappearing shifts every block after it. That is a running sum over a
256
+ * handful of blocks, and the alternative — a free list — would have to survive
257
+ * a block changing size, which happens whenever a dim appends. A field block
258
+ * that moves rewrites the headers pointing at it in the same pass.
139
259
  *
140
- * Offsets are recomputed on every call because a scale appearing or
141
- * disappearing shifts every scale after it. That is a running sum over a
142
- * handful of scales, and the alternative — a free list — would have to survive
143
- * a scale changing size, which happens whenever a dim appends.
260
+ * `fields` and `groups` default to none, which packs the slots alone.
144
261
  */
145
- export declare function packIdentitySlots(scales: readonly IdentitySlotScale[], state: IdentitySlotState): PackResult;
262
+ export declare function packIdentitySlots(scales: readonly IdentitySlotScale[], state: IdentitySlotState, fields?: readonly ActivityField[], groups?: number): PackResult;