@ggterm/core 0.2.5 → 0.2.9

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/dist/cli.js CHANGED
@@ -30,426 +30,74 @@ var __export = (target, all) => {
30
30
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
31
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
32
32
 
33
- // src/pipeline/scales.ts
34
- var exports_scales = {};
35
- __export(exports_scales, {
36
- niceDomain: () => niceDomain,
37
- inferDiscreteDomain: () => inferDiscreteDomain,
38
- inferContinuousDomain: () => inferContinuousDomain,
39
- getTransformFunctions: () => getTransformFunctions,
40
- expandDomain: () => expandDomain,
41
- createResolvedSizeScale: () => createResolvedSizeScale,
42
- createResolvedDiscreteScale: () => createResolvedDiscreteScale,
43
- createResolvedDiscreteColorScale: () => createResolvedDiscreteColorScale,
44
- createResolvedContinuousScale: () => createResolvedContinuousScale,
45
- createResolvedContinuousColorScale: () => createResolvedContinuousColorScale,
46
- buildScaleContext: () => buildScaleContext,
47
- DEFAULT_POINT_COLOR: () => DEFAULT_POINT_COLOR
48
- });
49
- function inferContinuousDomain(data, field) {
50
- let min = Infinity;
51
- let max = -Infinity;
52
- for (const row of data) {
53
- const value = row[field];
54
- if (typeof value === "number" && !isNaN(value)) {
55
- if (value < min)
56
- min = value;
57
- if (value > max)
58
- max = value;
59
- }
60
- }
61
- if (min === Infinity)
62
- min = 0;
63
- if (max === -Infinity)
64
- max = 1;
65
- if (min === max) {
66
- min = min - 1;
67
- max = max + 1;
68
- }
69
- return [min, max];
70
- }
71
- function inferDiscreteDomain(data, field, options = {}) {
72
- const { limits, order = "alphabetical", reverse = false, exclude, drop = true } = options;
73
- const seen = new Map;
74
- let index = 0;
75
- for (const row of data) {
76
- const value = row[field];
77
- if (value !== null && value !== undefined) {
78
- const key = String(value);
79
- if (!seen.has(key)) {
80
- seen.set(key, { firstIndex: index, count: 1 });
81
- } else {
82
- seen.get(key).count++;
83
- }
84
- }
85
- index++;
86
- }
87
- let result;
88
- if (limits) {
89
- if (drop) {
90
- result = limits.filter((v) => seen.has(v));
91
- } else {
92
- result = [...limits];
93
- }
94
- } else {
95
- const values = Array.from(seen.keys());
96
- switch (order) {
97
- case "data":
98
- result = values.sort((a, b) => seen.get(a).firstIndex - seen.get(b).firstIndex);
99
- break;
100
- case "frequency":
101
- result = values.sort((a, b) => seen.get(b).count - seen.get(a).count);
102
- break;
103
- case "reverse":
104
- result = values.sort().reverse();
105
- break;
106
- case "alphabetical":
107
- default:
108
- result = values.sort();
109
- break;
110
- }
111
- }
112
- if (exclude && exclude.length > 0) {
113
- const excludeSet = new Set(exclude);
114
- result = result.filter((v) => !excludeSet.has(v));
115
- }
116
- if (reverse) {
117
- result = result.reverse();
118
- }
119
- return result;
120
- }
121
- function expandDomain(domain, expand = 0.05) {
122
- const range = domain[1] - domain[0];
123
- const padding = range * expand;
124
- return [domain[0] - padding, domain[1] + padding];
125
- }
126
- function niceStep(range, targetTicks = 5) {
127
- const rawStep = range / Math.max(1, targetTicks - 1);
128
- const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
129
- const normalized = rawStep / magnitude;
130
- let nice;
131
- if (normalized <= 1.5)
132
- nice = 1;
133
- else if (normalized <= 3)
134
- nice = 2;
135
- else if (normalized <= 7)
136
- nice = 5;
137
- else
138
- nice = 10;
139
- return nice * magnitude;
140
- }
141
- function niceDomain(domain, targetTicks = 5) {
142
- const [min, max] = domain;
143
- const range = max - min;
144
- if (range === 0) {
145
- if (min === 0)
146
- return [-1, 1];
147
- const magnitude = Math.pow(10, Math.floor(Math.log10(Math.abs(min))));
148
- return [min - magnitude, min + magnitude];
149
- }
150
- const step = niceStep(range, targetTicks);
151
- const niceMin = Math.floor(min / step) * step;
152
- const niceMax = Math.ceil(max / step) * step;
153
- return [niceMin, niceMax];
154
- }
155
- function getTransformFunctions(trans = "identity") {
156
- switch (trans) {
157
- case "log10":
158
- return {
159
- type: "log10",
160
- transform: (v) => v > 0 ? Math.log10(v) : -Infinity,
161
- invert: (v) => Math.pow(10, v)
162
- };
163
- case "sqrt":
164
- return {
165
- type: "sqrt",
166
- transform: (v) => v >= 0 ? Math.sqrt(v) : 0,
167
- invert: (v) => v * v
168
- };
169
- case "reverse":
170
- return {
171
- type: "reverse",
172
- transform: (v) => -v,
173
- invert: (v) => -v
174
- };
175
- default:
176
- return {
177
- type: "identity",
178
- transform: (v) => v,
179
- invert: (v) => v
180
- };
181
- }
182
- }
183
- function createResolvedContinuousScale(aesthetic, domain, range, trans = "identity") {
184
- const [domainMin, domainMax] = domain;
185
- const [rangeMin, rangeMax] = range;
186
- const rangeSpan = rangeMax - rangeMin;
187
- const { transform, invert } = getTransformFunctions(trans);
33
+ // src/themes/default.ts
34
+ function defaultTheme() {
188
35
  return {
189
- aesthetic,
190
- type: "continuous",
191
- domain,
192
- range,
193
- trans,
194
- transform,
195
- invert,
196
- normalize(value) {
197
- const num = Number(value);
198
- if (isNaN(num))
199
- return 0;
200
- const transformed = transform(num);
201
- const transformedMin = transform(domainMin);
202
- const transformedMax = transform(domainMax);
203
- if (transformedMax === transformedMin)
204
- return 0.5;
205
- return (transformed - transformedMin) / (transformedMax - transformedMin);
36
+ panel: {
37
+ background: "",
38
+ border: "single",
39
+ grid: { major: "·", minor: null }
206
40
  },
207
- toCanvas(normalized) {
208
- return rangeMin + normalized * rangeSpan;
41
+ axis: {
42
+ text: { color: "" },
43
+ ticks: { char: "┼", length: 1 },
44
+ title: { color: "", bold: false }
209
45
  },
210
- map(value) {
211
- return this.toCanvas(this.normalize(value));
46
+ legend: {
47
+ position: "right",
48
+ title: { bold: true }
49
+ },
50
+ title: {
51
+ align: "center",
52
+ bold: true
53
+ },
54
+ facet: {
55
+ strip: {
56
+ text: "#c8c8c8",
57
+ background: ""
58
+ }
212
59
  }
213
60
  };
214
61
  }
215
- function createResolvedDiscreteScale(aesthetic, domain, range) {
216
- const [rangeMin, rangeMax] = range;
217
- const rangeSpan = rangeMax - rangeMin;
62
+ function themeMinimal() {
218
63
  return {
219
- aesthetic,
220
- type: "discrete",
221
- domain,
222
- range,
223
- normalize(value) {
224
- const str = String(value);
225
- const index = domain.indexOf(str);
226
- if (index < 0)
227
- return 0;
228
- return domain.length > 1 ? index / (domain.length - 1) : 0.5;
64
+ panel: {
65
+ background: "",
66
+ border: "none",
67
+ grid: { major: null, minor: null }
229
68
  },
230
- toCanvas(normalized) {
231
- return rangeMin + normalized * rangeSpan;
69
+ axis: {
70
+ text: { color: "" },
71
+ ticks: { char: "│", length: 1 },
72
+ title: { color: "", bold: false }
232
73
  },
233
- map(value) {
234
- return this.toCanvas(this.normalize(value));
74
+ legend: {
75
+ position: "right",
76
+ title: { bold: false }
77
+ },
78
+ title: {
79
+ align: "left",
80
+ bold: false
81
+ },
82
+ facet: {
83
+ strip: {
84
+ text: "#999999",
85
+ background: ""
86
+ }
235
87
  }
236
88
  };
237
89
  }
238
- function interpolateColor(color1, color2, t) {
239
- return {
240
- r: Math.round(color1.r + (color2.r - color1.r) * t),
241
- g: Math.round(color1.g + (color2.g - color1.g) * t),
242
- b: Math.round(color1.b + (color2.b - color1.b) * t),
243
- a: color1.a + (color2.a - color1.a) * t
244
- };
245
- }
246
- function createResolvedDiscreteColorScale(domain, palette = CATEGORY_COLORS) {
247
- return {
248
- aesthetic: "color",
249
- type: "discrete",
250
- domain,
251
- map(value) {
252
- const str = String(value);
253
- const index = domain.indexOf(str);
254
- if (index < 0)
255
- return palette[0];
256
- return palette[index % palette.length];
257
- }
258
- };
259
- }
260
- function createResolvedContinuousColorScale(domain, lowColor = { r: 68, g: 1, b: 84, a: 1 }, highColor = { r: 253, g: 231, b: 37, a: 1 }) {
261
- const [min, max] = domain;
262
- const span = max - min;
263
- return {
264
- aesthetic: "color",
265
- type: "continuous",
266
- domain,
267
- map(value) {
268
- const num = Number(value);
269
- if (isNaN(num))
270
- return lowColor;
271
- const t = Math.max(0, Math.min(1, (num - min) / span));
272
- return interpolateColor(lowColor, highColor, t);
273
- }
274
- };
275
- }
276
- function isCategoricalField(data, field) {
277
- for (const row of data) {
278
- const value = row[field];
279
- if (value !== null && value !== undefined) {
280
- if (typeof value === "string" && isNaN(Number(value))) {
281
- return true;
282
- }
283
- }
284
- }
285
- return false;
286
- }
287
- function createResolvedSizeScale(domain) {
288
- const [min, max] = domain;
289
- const span = max - min;
290
- return {
291
- aesthetic: "size",
292
- type: "continuous",
293
- domain,
294
- map(value) {
295
- const num = Number(value);
296
- if (isNaN(num))
297
- return 1;
298
- const t = Math.max(0, Math.min(1, (num - min) / span));
299
- return Math.floor(t * 3.99);
300
- }
301
- };
302
- }
303
- function computeDomain(data, field, trans = "identity") {
304
- const rawDomain = inferContinuousDomain(data, field);
305
- if (trans === "log10") {
306
- const [min, max] = rawDomain;
307
- const safeMin = min > 0 ? min : 0.001;
308
- const safeMax = max > 0 ? max : 1;
309
- const minPow = Math.floor(Math.log10(safeMin));
310
- const maxPow = Math.ceil(Math.log10(safeMax));
311
- return [Math.pow(10, minPow), Math.pow(10, maxPow)];
312
- }
313
- return niceDomain(rawDomain);
314
- }
315
- function buildScaleContext(data, aes, plotArea, userScales = [], coordLimits) {
316
- const userXScale = userScales.find((s) => s.aesthetic === "x");
317
- const userYScale = userScales.find((s) => s.aesthetic === "y");
318
- const userColorScale = userScales.find((s) => s.aesthetic === "color" || s.aesthetic === "fill");
319
- const xIsCategorical = isCategoricalField(data, aes.x);
320
- let x;
321
- if (xIsCategorical) {
322
- const xOrderOptions = {};
323
- if (userXScale) {
324
- if (userXScale.domain && Array.isArray(userXScale.domain)) {
325
- xOrderOptions.limits = userXScale.domain;
326
- }
327
- const orderOpts = userXScale.orderOptions;
328
- if (orderOpts) {
329
- if (orderOpts.order)
330
- xOrderOptions.order = orderOpts.order;
331
- if (orderOpts.reverse)
332
- xOrderOptions.reverse = orderOpts.reverse;
333
- if (orderOpts.exclude)
334
- xOrderOptions.exclude = orderOpts.exclude;
335
- if (orderOpts.drop !== undefined)
336
- xOrderOptions.drop = orderOpts.drop;
337
- }
338
- }
339
- const xDomain = inferDiscreteDomain(data, aes.x, xOrderOptions);
340
- x = createResolvedDiscreteScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1]);
341
- if (userXScale?.labels) {
342
- x.labels = userXScale.labels;
343
- }
344
- } else {
345
- const xTrans = userXScale?.trans ?? "identity";
346
- const xDomain = coordLimits?.xlim ?? userXScale?.domain ?? computeDomain(data, aes.x, xTrans);
347
- x = createResolvedContinuousScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1], xTrans);
348
- if (userXScale?.breaks) {
349
- x.breaks = userXScale.breaks;
350
- }
351
- if (userXScale?.labels) {
352
- x.labels = userXScale.labels;
353
- }
354
- }
355
- const yTrans = userYScale?.trans ?? "identity";
356
- const yDomain = coordLimits?.ylim ?? userYScale?.domain ?? computeDomain(data, aes.y, yTrans);
357
- const y = createResolvedContinuousScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y], yTrans);
358
- if (userYScale?.breaks) {
359
- y.breaks = userYScale.breaks;
360
- }
361
- if (userYScale?.labels) {
362
- y.labels = userYScale.labels;
363
- }
364
- const context = { x, y };
365
- if (aes.y2) {
366
- const userY2Scale = userScales.find((s) => s.aesthetic === "y2");
367
- const y2Trans = userY2Scale?.trans ?? "identity";
368
- const y2Domain = userY2Scale?.domain ?? computeDomain(data, aes.y2, y2Trans);
369
- const y2 = createResolvedContinuousScale("y2", y2Domain, [plotArea.y + plotArea.height - 1, plotArea.y], y2Trans);
370
- if (userY2Scale?.breaks) {
371
- y2.breaks = userY2Scale.breaks;
372
- }
373
- if (userY2Scale?.labels) {
374
- y2.labels = userY2Scale.labels;
375
- }
376
- context.y2 = y2;
377
- }
378
- const colorAesField = aes.color || aes.fill;
379
- if (colorAesField) {
380
- const colorOrderOptions = {};
381
- if (userColorScale) {
382
- if (userColorScale.domain && Array.isArray(userColorScale.domain)) {
383
- colorOrderOptions.limits = userColorScale.domain;
384
- }
385
- const orderOpts = userColorScale.orderOptions;
386
- if (orderOpts) {
387
- if (orderOpts.order)
388
- colorOrderOptions.order = orderOpts.order;
389
- if (orderOpts.reverse)
390
- colorOrderOptions.reverse = orderOpts.reverse;
391
- if (orderOpts.exclude)
392
- colorOrderOptions.exclude = orderOpts.exclude;
393
- if (orderOpts.drop !== undefined)
394
- colorOrderOptions.drop = orderOpts.drop;
395
- }
396
- }
397
- const colorDomain = inferDiscreteDomain(data, colorAesField, colorOrderOptions);
398
- if (userColorScale && userColorScale.map) {
399
- context.color = {
400
- aesthetic: userColorScale.aesthetic || "color",
401
- type: userColorScale.type === "continuous" ? "continuous" : "discrete",
402
- domain: userColorScale.type === "continuous" ? userColorScale.domain ?? inferContinuousDomain(data, colorAesField) : colorDomain,
403
- map: (value) => {
404
- const result = userColorScale.map(value);
405
- if (typeof result === "object" && "r" in result) {
406
- return result;
407
- }
408
- return { r: 128, g: 128, b: 128, a: 1 };
409
- }
410
- };
411
- } else {
412
- context.color = createResolvedDiscreteColorScale(colorDomain);
413
- }
414
- }
415
- if (aes.size) {
416
- const sizeDomain = inferContinuousDomain(data, aes.size);
417
- context.size = createResolvedSizeScale(sizeDomain);
418
- }
419
- return context;
420
- }
421
- var CATEGORY_COLORS, DEFAULT_POINT_COLOR;
422
- var init_scales = __esm(() => {
423
- CATEGORY_COLORS = [
424
- { r: 31, g: 119, b: 180, a: 1 },
425
- { r: 255, g: 127, b: 14, a: 1 },
426
- { r: 44, g: 160, b: 44, a: 1 },
427
- { r: 214, g: 39, b: 40, a: 1 },
428
- { r: 148, g: 103, b: 189, a: 1 },
429
- { r: 140, g: 86, b: 75, a: 1 },
430
- { r: 227, g: 119, b: 194, a: 1 },
431
- { r: 127, g: 127, b: 127, a: 1 },
432
- { r: 188, g: 189, b: 34, a: 1 },
433
- { r: 23, g: 190, b: 207, a: 1 }
434
- ];
435
- DEFAULT_POINT_COLOR = { r: 79, g: 169, b: 238, a: 1 };
436
- });
437
-
438
- // src/repl/repl.ts
439
- import * as readline from "readline";
440
-
441
- // src/themes/default.ts
442
- function defaultTheme() {
90
+ function themeDark() {
443
91
  return {
444
92
  panel: {
445
- background: "",
446
- border: "single",
93
+ background: "#1e1e1e",
94
+ border: "rounded",
447
95
  grid: { major: "·", minor: null }
448
96
  },
449
97
  axis: {
450
- text: { color: "" },
98
+ text: { color: "#ccc" },
451
99
  ticks: { char: "┼", length: 1 },
452
- title: { color: "", bold: false }
100
+ title: { color: "#fff", bold: true }
453
101
  },
454
102
  legend: {
455
103
  position: "right",
@@ -461,51 +109,23 @@ function defaultTheme() {
461
109
  },
462
110
  facet: {
463
111
  strip: {
464
- text: "#c8c8c8",
465
- background: ""
112
+ text: "#ffffff",
113
+ background: "#333333"
466
114
  }
467
115
  }
468
116
  };
469
117
  }
470
- function themeMinimal() {
118
+ function themeClassic() {
471
119
  return {
472
120
  panel: {
473
121
  background: "",
474
- border: "none",
122
+ border: "single",
475
123
  grid: { major: null, minor: null }
476
124
  },
477
125
  axis: {
478
126
  text: { color: "" },
479
- ticks: { char: "", length: 1 },
480
- title: { color: "", bold: false }
481
- },
482
- legend: {
483
- position: "right",
484
- title: { bold: false }
485
- },
486
- title: {
487
- align: "left",
488
- bold: false
489
- },
490
- facet: {
491
- strip: {
492
- text: "#999999",
493
- background: ""
494
- }
495
- }
496
- };
497
- }
498
- function themeDark() {
499
- return {
500
- panel: {
501
- background: "#1e1e1e",
502
- border: "rounded",
503
- grid: { major: "·", minor: null }
504
- },
505
- axis: {
506
- text: { color: "#ccc" },
507
- ticks: { char: "┼", length: 1 },
508
- title: { color: "#fff", bold: true }
127
+ ticks: { char: "", length: 1 },
128
+ title: { color: "", bold: true }
509
129
  },
510
130
  legend: {
511
131
  position: "right",
@@ -517,304 +137,705 @@ function themeDark() {
517
137
  },
518
138
  facet: {
519
139
  strip: {
520
- text: "#ffffff",
521
- background: "#333333"
140
+ text: "#c8c8c8",
141
+ background: ""
522
142
  }
523
143
  }
524
144
  };
525
145
  }
526
- function themeClassic() {
146
+ function themeVoid() {
527
147
  return {
528
148
  panel: {
529
149
  background: "",
530
- border: "single",
150
+ border: "none",
531
151
  grid: { major: null, minor: null }
532
152
  },
533
153
  axis: {
534
154
  text: { color: "" },
535
- ticks: { char: "", length: 1 },
536
- title: { color: "", bold: true }
155
+ ticks: { char: "", length: 0 },
156
+ title: { color: "", bold: false }
537
157
  },
538
158
  legend: {
539
- position: "right",
540
- title: { bold: true }
159
+ position: "none",
160
+ title: { bold: false }
541
161
  },
542
162
  title: {
543
- align: "center",
544
- bold: true
163
+ align: "left",
164
+ bold: false
545
165
  },
546
166
  facet: {
547
167
  strip: {
548
- text: "#c8c8c8",
168
+ text: "#888888",
549
169
  background: ""
550
170
  }
551
171
  }
552
- };
172
+ };
173
+ }
174
+
175
+ // src/coords/cartesian.ts
176
+ function coordCartesian(options = {}) {
177
+ return {
178
+ type: "cartesian",
179
+ xlim: options.xlim,
180
+ ylim: options.ylim,
181
+ clip: options.clip ?? true,
182
+ transform(x, y) {
183
+ return { x, y };
184
+ }
185
+ };
186
+ }
187
+ function coordFlip() {
188
+ return {
189
+ type: "flip",
190
+ transform(x, y) {
191
+ return { x: y, y: x };
192
+ }
193
+ };
194
+ }
195
+ function coordPolar(options = {}) {
196
+ const theta = options.theta ?? "x";
197
+ return {
198
+ type: "polar",
199
+ transform(x, y) {
200
+ const angle = theta === "x" ? x : y;
201
+ const radius = theta === "x" ? y : x;
202
+ return {
203
+ x: radius * Math.cos(angle),
204
+ y: radius * Math.sin(angle)
205
+ };
206
+ }
207
+ };
208
+ }
209
+ function coordFixed(options = {}) {
210
+ const ratio = options.ratio ?? 1;
211
+ return {
212
+ type: "fixed",
213
+ xlim: options.xlim,
214
+ ylim: options.ylim,
215
+ clip: options.clip ?? true,
216
+ ratio,
217
+ transform(x, y) {
218
+ return { x, y };
219
+ }
220
+ };
221
+ }
222
+ function coordEqual(options = {}) {
223
+ return coordFixed({ ...options, ratio: 1 });
224
+ }
225
+ function getTransform(type) {
226
+ switch (type) {
227
+ case "log10":
228
+ return (v) => v > 0 ? Math.log10(v) : -Infinity;
229
+ case "sqrt":
230
+ return (v) => v >= 0 ? Math.sqrt(v) : 0;
231
+ case "reverse":
232
+ return (v) => -v;
233
+ default:
234
+ return (v) => v;
235
+ }
236
+ }
237
+ function coordTrans(options = {}) {
238
+ const xTrans = getTransform(options.x ?? "identity");
239
+ const yTrans = getTransform(options.y ?? "identity");
240
+ return {
241
+ type: "trans",
242
+ xlim: options.xlim,
243
+ ylim: options.ylim,
244
+ clip: options.clip ?? true,
245
+ xTransType: options.x ?? "identity",
246
+ yTransType: options.y ?? "identity",
247
+ transform(x, y) {
248
+ return {
249
+ x: xTrans(x),
250
+ y: yTrans(y)
251
+ };
252
+ }
253
+ };
254
+ }
255
+ function coordFlipWithLimits(options = {}) {
256
+ return {
257
+ type: "flip",
258
+ xlim: options.xlim,
259
+ ylim: options.ylim,
260
+ clip: options.clip ?? true,
261
+ transform(x, y) {
262
+ return { x: y, y: x };
263
+ }
264
+ };
265
+ }
266
+
267
+ // src/canvas/canvas.ts
268
+ function createEmptyCell() {
269
+ return {
270
+ char: " ",
271
+ fg: { ...DEFAULT_FG },
272
+ bg: { ...DEFAULT_BG }
273
+ };
274
+ }
275
+
276
+ class TerminalCanvas {
277
+ width;
278
+ height;
279
+ cells;
280
+ constructor(width, height) {
281
+ this.width = width;
282
+ this.height = height;
283
+ this.cells = [];
284
+ this.clear();
285
+ }
286
+ setCell(x, y, cell) {
287
+ if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || x >= this.width || y < 0 || y >= this.height) {
288
+ return;
289
+ }
290
+ const ix = Math.floor(x);
291
+ const iy = Math.floor(y);
292
+ const existing = this.cells[iy][ix];
293
+ this.cells[iy][ix] = {
294
+ char: cell.char ?? existing.char,
295
+ fg: cell.fg ?? existing.fg,
296
+ bg: cell.bg ?? existing.bg,
297
+ bold: cell.bold ?? existing.bold,
298
+ italic: cell.italic ?? existing.italic,
299
+ underline: cell.underline ?? existing.underline
300
+ };
301
+ }
302
+ getCell(x, y) {
303
+ if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || x >= this.width || y < 0 || y >= this.height) {
304
+ return createEmptyCell();
305
+ }
306
+ return this.cells[Math.floor(y)][Math.floor(x)];
307
+ }
308
+ clear() {
309
+ this.cells = [];
310
+ for (let y = 0;y < this.height; y++) {
311
+ const row = [];
312
+ for (let x = 0;x < this.width; x++) {
313
+ row.push(createEmptyCell());
314
+ }
315
+ this.cells.push(row);
316
+ }
317
+ }
318
+ drawChar(x, y, char, fg) {
319
+ this.setCell(x, y, { char, fg });
320
+ }
321
+ drawString(x, y, str, fg) {
322
+ for (let i = 0;i < str.length; i++) {
323
+ this.drawChar(x + i, y, str[i], fg);
324
+ }
325
+ }
326
+ drawHLine(x, y, length, char = "─", fg) {
327
+ for (let i = 0;i < length; i++) {
328
+ this.drawChar(x + i, y, char, fg);
329
+ }
330
+ }
331
+ drawVLine(x, y, length, char = "│", fg) {
332
+ for (let i = 0;i < length; i++) {
333
+ this.drawChar(x, y + i, char, fg);
334
+ }
335
+ }
336
+ drawPoint(x, y, fg, shape = "●") {
337
+ this.drawChar(x, y, shape, fg);
338
+ }
339
+ fillRect(x, y, width, height, char = " ", fg, bg) {
340
+ for (let dy = 0;dy < height; dy++) {
341
+ for (let dx = 0;dx < width; dx++) {
342
+ this.setCell(x + dx, y + dy, { char, fg, bg });
343
+ }
344
+ }
345
+ }
346
+ drawBox(x, y, width, height, style = "single", fg) {
347
+ const chars = style === "double" ? { tl: "╔", tr: "╗", bl: "╚", br: "╝", h: "═", v: "║" } : style === "rounded" ? { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│" } : { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" };
348
+ this.drawChar(x, y, chars.tl, fg);
349
+ this.drawChar(x + width - 1, y, chars.tr, fg);
350
+ this.drawChar(x, y + height - 1, chars.bl, fg);
351
+ this.drawChar(x + width - 1, y + height - 1, chars.br, fg);
352
+ this.drawHLine(x + 1, y, width - 2, chars.h, fg);
353
+ this.drawHLine(x + 1, y + height - 1, width - 2, chars.h, fg);
354
+ this.drawVLine(x, y + 1, height - 2, chars.v, fg);
355
+ this.drawVLine(x + width - 1, y + 1, height - 2, chars.v, fg);
356
+ }
357
+ toString() {
358
+ return this.cells.map((row) => row.map((cell) => cell.char).join("")).join(`
359
+ `);
360
+ }
361
+ toAnsiString() {
362
+ const lines = [];
363
+ for (const row of this.cells) {
364
+ let line = "";
365
+ let currentFg = null;
366
+ let currentBg = null;
367
+ for (const cell of row) {
368
+ const fgChanged = !currentFg || currentFg.r !== cell.fg.r || currentFg.g !== cell.fg.g || currentFg.b !== cell.fg.b;
369
+ const bgChanged = cell.bg.a > 0 && (!currentBg || currentBg.r !== cell.bg.r || currentBg.g !== cell.bg.g || currentBg.b !== cell.bg.b);
370
+ if (fgChanged) {
371
+ line += `\x1B[38;2;${cell.fg.r};${cell.fg.g};${cell.fg.b}m`;
372
+ currentFg = cell.fg;
373
+ }
374
+ if (bgChanged) {
375
+ line += `\x1B[48;2;${cell.bg.r};${cell.bg.g};${cell.bg.b}m`;
376
+ currentBg = cell.bg;
377
+ }
378
+ if (cell.bold)
379
+ line += "\x1B[1m";
380
+ if (cell.italic)
381
+ line += "\x1B[3m";
382
+ if (cell.underline)
383
+ line += "\x1B[4m";
384
+ line += cell.char;
385
+ if (cell.bold || cell.italic || cell.underline) {
386
+ line += "\x1B[22;23;24m";
387
+ if (currentFg) {
388
+ line += `\x1B[38;2;${currentFg.r};${currentFg.g};${currentFg.b}m`;
389
+ }
390
+ }
391
+ }
392
+ line += "\x1B[0m";
393
+ lines.push(line);
394
+ }
395
+ return lines.join(`
396
+ `);
397
+ }
398
+ }
399
+ function createCanvas(width, height) {
400
+ return new TerminalCanvas(width, height);
401
+ }
402
+ var DEFAULT_FG, DEFAULT_BG;
403
+ var init_canvas = __esm(() => {
404
+ DEFAULT_FG = { r: 255, g: 255, b: 255, a: 1 };
405
+ DEFAULT_BG = { r: 0, g: 0, b: 0, a: 0 };
406
+ });
407
+
408
+ // src/pipeline/scales.ts
409
+ var exports_scales = {};
410
+ __export(exports_scales, {
411
+ niceDomain: () => niceDomain,
412
+ inferDiscreteDomain: () => inferDiscreteDomain,
413
+ inferContinuousDomain: () => inferContinuousDomain,
414
+ getTransformFunctions: () => getTransformFunctions,
415
+ expandDomain: () => expandDomain,
416
+ createResolvedSizeScale: () => createResolvedSizeScale,
417
+ createResolvedDiscreteScale: () => createResolvedDiscreteScale,
418
+ createResolvedDiscreteColorScale: () => createResolvedDiscreteColorScale,
419
+ createResolvedContinuousScale: () => createResolvedContinuousScale,
420
+ createResolvedContinuousColorScale: () => createResolvedContinuousColorScale,
421
+ buildScaleContext: () => buildScaleContext,
422
+ DEFAULT_POINT_COLOR: () => DEFAULT_POINT_COLOR
423
+ });
424
+ function inferContinuousDomain(data, field) {
425
+ let min = Infinity;
426
+ let max = -Infinity;
427
+ for (const row of data) {
428
+ const value = row[field];
429
+ if (typeof value === "number" && !isNaN(value)) {
430
+ if (value < min)
431
+ min = value;
432
+ if (value > max)
433
+ max = value;
434
+ }
435
+ }
436
+ if (min === Infinity)
437
+ min = 0;
438
+ if (max === -Infinity)
439
+ max = 1;
440
+ if (min === max) {
441
+ min = min - 1;
442
+ max = max + 1;
443
+ }
444
+ return [min, max];
553
445
  }
554
- function themeVoid() {
555
- return {
556
- panel: {
557
- background: "",
558
- border: "none",
559
- grid: { major: null, minor: null }
560
- },
561
- axis: {
562
- text: { color: "" },
563
- ticks: { char: "", length: 0 },
564
- title: { color: "", bold: false }
565
- },
566
- legend: {
567
- position: "none",
568
- title: { bold: false }
569
- },
570
- title: {
571
- align: "left",
572
- bold: false
573
- },
574
- facet: {
575
- strip: {
576
- text: "#888888",
577
- background: ""
446
+ function inferDiscreteDomain(data, field, options = {}) {
447
+ const { limits, order = "alphabetical", reverse = false, exclude, drop = true } = options;
448
+ const seen = new Map;
449
+ let index = 0;
450
+ for (const row of data) {
451
+ const value = row[field];
452
+ if (value !== null && value !== undefined) {
453
+ const key = String(value);
454
+ if (!seen.has(key)) {
455
+ seen.set(key, { firstIndex: index, count: 1 });
456
+ } else {
457
+ seen.get(key).count++;
578
458
  }
579
459
  }
580
- };
581
- }
582
-
583
- // src/coords/cartesian.ts
584
- function coordCartesian(options = {}) {
585
- return {
586
- type: "cartesian",
587
- xlim: options.xlim,
588
- ylim: options.ylim,
589
- clip: options.clip ?? true,
590
- transform(x, y) {
591
- return { x, y };
460
+ index++;
461
+ }
462
+ let result;
463
+ if (limits) {
464
+ if (drop) {
465
+ result = limits.filter((v) => seen.has(v));
466
+ } else {
467
+ result = [...limits];
592
468
  }
593
- };
594
- }
595
- function coordFlip() {
596
- return {
597
- type: "flip",
598
- transform(x, y) {
599
- return { x: y, y: x };
469
+ } else {
470
+ const values = Array.from(seen.keys());
471
+ switch (order) {
472
+ case "data":
473
+ result = values.sort((a, b) => seen.get(a).firstIndex - seen.get(b).firstIndex);
474
+ break;
475
+ case "frequency":
476
+ result = values.sort((a, b) => seen.get(b).count - seen.get(a).count);
477
+ break;
478
+ case "reverse":
479
+ result = values.sort().reverse();
480
+ break;
481
+ case "alphabetical":
482
+ default:
483
+ result = values.sort();
484
+ break;
600
485
  }
601
- };
486
+ }
487
+ if (exclude && exclude.length > 0) {
488
+ const excludeSet = new Set(exclude);
489
+ result = result.filter((v) => !excludeSet.has(v));
490
+ }
491
+ if (reverse) {
492
+ result = result.reverse();
493
+ }
494
+ return result;
602
495
  }
603
- function coordPolar(options = {}) {
604
- const theta = options.theta ?? "x";
605
- return {
606
- type: "polar",
607
- transform(x, y) {
608
- const angle = theta === "x" ? x : y;
609
- const radius = theta === "x" ? y : x;
610
- return {
611
- x: radius * Math.cos(angle),
612
- y: radius * Math.sin(angle)
613
- };
614
- }
615
- };
496
+ function expandDomain(domain, expand = 0.05) {
497
+ const range = domain[1] - domain[0];
498
+ const padding = range * expand;
499
+ return [domain[0] - padding, domain[1] + padding];
616
500
  }
617
- function coordFixed(options = {}) {
618
- const ratio = options.ratio ?? 1;
619
- return {
620
- type: "fixed",
621
- xlim: options.xlim,
622
- ylim: options.ylim,
623
- clip: options.clip ?? true,
624
- ratio,
625
- transform(x, y) {
626
- return { x, y };
627
- }
628
- };
501
+ function niceStep(range, targetTicks = 5) {
502
+ const rawStep = range / Math.max(1, targetTicks - 1);
503
+ const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
504
+ const normalized = rawStep / magnitude;
505
+ let nice;
506
+ if (normalized <= 1.5)
507
+ nice = 1;
508
+ else if (normalized <= 3)
509
+ nice = 2;
510
+ else if (normalized <= 7)
511
+ nice = 5;
512
+ else
513
+ nice = 10;
514
+ return nice * magnitude;
629
515
  }
630
- function coordEqual(options = {}) {
631
- return coordFixed({ ...options, ratio: 1 });
516
+ function niceDomain(domain, targetTicks = 5) {
517
+ const [min, max] = domain;
518
+ const range = max - min;
519
+ if (range === 0) {
520
+ if (min === 0)
521
+ return [-1, 1];
522
+ const magnitude = Math.pow(10, Math.floor(Math.log10(Math.abs(min))));
523
+ return [min - magnitude, min + magnitude];
524
+ }
525
+ const step = niceStep(range, targetTicks);
526
+ const niceMin = Math.floor(min / step) * step;
527
+ const niceMax = Math.ceil(max / step) * step;
528
+ return [niceMin, niceMax];
632
529
  }
633
- function getTransform(type) {
634
- switch (type) {
530
+ function getTransformFunctions(trans = "identity") {
531
+ switch (trans) {
635
532
  case "log10":
636
- return (v) => v > 0 ? Math.log10(v) : -Infinity;
533
+ return {
534
+ type: "log10",
535
+ transform: (v) => v > 0 ? Math.log10(v) : -Infinity,
536
+ invert: (v) => Math.pow(10, v)
537
+ };
637
538
  case "sqrt":
638
- return (v) => v >= 0 ? Math.sqrt(v) : 0;
539
+ return {
540
+ type: "sqrt",
541
+ transform: (v) => v >= 0 ? Math.sqrt(v) : 0,
542
+ invert: (v) => v * v
543
+ };
639
544
  case "reverse":
640
- return (v) => -v;
545
+ return {
546
+ type: "reverse",
547
+ transform: (v) => -v,
548
+ invert: (v) => -v
549
+ };
641
550
  default:
642
- return (v) => v;
551
+ return {
552
+ type: "identity",
553
+ transform: (v) => v,
554
+ invert: (v) => v
555
+ };
643
556
  }
644
557
  }
645
- function coordTrans(options = {}) {
646
- const xTrans = getTransform(options.x ?? "identity");
647
- const yTrans = getTransform(options.y ?? "identity");
558
+ function createResolvedContinuousScale(aesthetic, domain, range, trans = "identity") {
559
+ const [domainMin, domainMax] = domain;
560
+ const [rangeMin, rangeMax] = range;
561
+ const rangeSpan = rangeMax - rangeMin;
562
+ const { transform, invert } = getTransformFunctions(trans);
648
563
  return {
649
- type: "trans",
650
- xlim: options.xlim,
651
- ylim: options.ylim,
652
- clip: options.clip ?? true,
653
- xTransType: options.x ?? "identity",
654
- yTransType: options.y ?? "identity",
655
- transform(x, y) {
656
- return {
657
- x: xTrans(x),
658
- y: yTrans(y)
659
- };
564
+ aesthetic,
565
+ type: "continuous",
566
+ domain,
567
+ range,
568
+ trans,
569
+ transform,
570
+ invert,
571
+ normalize(value) {
572
+ const num = Number(value);
573
+ if (isNaN(num))
574
+ return 0;
575
+ const transformed = transform(num);
576
+ const transformedMin = transform(domainMin);
577
+ const transformedMax = transform(domainMax);
578
+ if (transformedMax === transformedMin)
579
+ return 0.5;
580
+ return (transformed - transformedMin) / (transformedMax - transformedMin);
581
+ },
582
+ toCanvas(normalized) {
583
+ return rangeMin + normalized * rangeSpan;
584
+ },
585
+ map(value) {
586
+ return this.toCanvas(this.normalize(value));
587
+ }
588
+ };
589
+ }
590
+ function createResolvedDiscreteScale(aesthetic, domain, range) {
591
+ const [rangeMin, rangeMax] = range;
592
+ const rangeSpan = rangeMax - rangeMin;
593
+ return {
594
+ aesthetic,
595
+ type: "discrete",
596
+ domain,
597
+ range,
598
+ normalize(value) {
599
+ const str = String(value);
600
+ const index = domain.indexOf(str);
601
+ if (index < 0)
602
+ return 0;
603
+ return domain.length > 1 ? index / (domain.length - 1) : 0.5;
604
+ },
605
+ toCanvas(normalized) {
606
+ return rangeMin + normalized * rangeSpan;
607
+ },
608
+ map(value) {
609
+ return this.toCanvas(this.normalize(value));
660
610
  }
661
611
  };
662
612
  }
663
- function coordFlipWithLimits(options = {}) {
613
+ function interpolateColor(color1, color2, t) {
664
614
  return {
665
- type: "flip",
666
- xlim: options.xlim,
667
- ylim: options.ylim,
668
- clip: options.clip ?? true,
669
- transform(x, y) {
670
- return { x: y, y: x };
615
+ r: Math.round(color1.r + (color2.r - color1.r) * t),
616
+ g: Math.round(color1.g + (color2.g - color1.g) * t),
617
+ b: Math.round(color1.b + (color2.b - color1.b) * t),
618
+ a: color1.a + (color2.a - color1.a) * t
619
+ };
620
+ }
621
+ function createResolvedDiscreteColorScale(domain, palette = CATEGORY_COLORS) {
622
+ return {
623
+ aesthetic: "color",
624
+ type: "discrete",
625
+ domain,
626
+ map(value) {
627
+ const str = String(value);
628
+ const index = domain.indexOf(str);
629
+ if (index < 0)
630
+ return palette[0];
631
+ return palette[index % palette.length];
671
632
  }
672
633
  };
673
634
  }
674
-
675
- // src/canvas/canvas.ts
676
- var DEFAULT_FG = { r: 255, g: 255, b: 255, a: 1 };
677
- var DEFAULT_BG = { r: 0, g: 0, b: 0, a: 0 };
678
- function createEmptyCell() {
635
+ function createResolvedContinuousColorScale(domain, lowColor = { r: 68, g: 1, b: 84, a: 1 }, highColor = { r: 253, g: 231, b: 37, a: 1 }) {
636
+ const [min, max] = domain;
637
+ const span = max - min;
679
638
  return {
680
- char: " ",
681
- fg: { ...DEFAULT_FG },
682
- bg: { ...DEFAULT_BG }
639
+ aesthetic: "color",
640
+ type: "continuous",
641
+ domain,
642
+ map(value) {
643
+ const num = Number(value);
644
+ if (isNaN(num))
645
+ return lowColor;
646
+ const t = Math.max(0, Math.min(1, (num - min) / span));
647
+ return interpolateColor(lowColor, highColor, t);
648
+ }
683
649
  };
684
650
  }
685
-
686
- class TerminalCanvas {
687
- width;
688
- height;
689
- cells;
690
- constructor(width, height) {
691
- this.width = width;
692
- this.height = height;
693
- this.cells = [];
694
- this.clear();
695
- }
696
- setCell(x, y, cell) {
697
- if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
698
- return;
651
+ function isCategoricalField(data, field) {
652
+ for (const row of data) {
653
+ const value = row[field];
654
+ if (value !== null && value !== undefined) {
655
+ if (typeof value === "string") {
656
+ return true;
657
+ }
699
658
  }
700
- const ix = Math.floor(x);
701
- const iy = Math.floor(y);
702
- const existing = this.cells[iy][ix];
703
- this.cells[iy][ix] = {
704
- char: cell.char ?? existing.char,
705
- fg: cell.fg ?? existing.fg,
706
- bg: cell.bg ?? existing.bg,
707
- bold: cell.bold ?? existing.bold,
708
- italic: cell.italic ?? existing.italic,
709
- underline: cell.underline ?? existing.underline
710
- };
711
659
  }
712
- getCell(x, y) {
713
- if (x < 0 || x >= this.width || y < 0 || y >= this.height) {
714
- return createEmptyCell();
660
+ return false;
661
+ }
662
+ function createResolvedSizeScale(domain) {
663
+ const [min, max] = domain;
664
+ const span = max - min;
665
+ return {
666
+ aesthetic: "size",
667
+ type: "continuous",
668
+ domain,
669
+ map(value) {
670
+ const num = Number(value);
671
+ if (isNaN(num))
672
+ return 1;
673
+ const t = Math.max(0, Math.min(1, (num - min) / span));
674
+ return Math.floor(t * 3.99);
715
675
  }
716
- return this.cells[Math.floor(y)][Math.floor(x)];
676
+ };
677
+ }
678
+ function computeDomain(data, field, trans = "identity") {
679
+ const rawDomain = inferContinuousDomain(data, field);
680
+ if (trans === "log10") {
681
+ const [min, max] = rawDomain;
682
+ const safeMin = min > 0 ? min : 0.001;
683
+ const safeMax = max > 0 ? max : 1;
684
+ const minPow = Math.floor(Math.log10(safeMin));
685
+ const maxPow = Math.ceil(Math.log10(safeMax));
686
+ return [Math.pow(10, minPow), Math.pow(10, maxPow)];
717
687
  }
718
- clear() {
719
- this.cells = [];
720
- for (let y = 0;y < this.height; y++) {
721
- const row = [];
722
- for (let x = 0;x < this.width; x++) {
723
- row.push(createEmptyCell());
688
+ return niceDomain(rawDomain);
689
+ }
690
+ function buildScaleContext(data, aes, plotArea, userScales = [], coordLimits) {
691
+ const userXScale = userScales.find((s) => s.aesthetic === "x");
692
+ const userYScale = userScales.find((s) => s.aesthetic === "y");
693
+ const userColorScale = userScales.find((s) => s.aesthetic === "color" || s.aesthetic === "fill");
694
+ const xIsCategorical = isCategoricalField(data, aes.x);
695
+ let x;
696
+ if (xIsCategorical) {
697
+ const xOrderOptions = {};
698
+ if (userXScale) {
699
+ if (userXScale.domain && Array.isArray(userXScale.domain)) {
700
+ xOrderOptions.limits = userXScale.domain;
701
+ }
702
+ const orderOpts = userXScale.orderOptions;
703
+ if (orderOpts) {
704
+ if (orderOpts.order)
705
+ xOrderOptions.order = orderOpts.order;
706
+ if (orderOpts.reverse)
707
+ xOrderOptions.reverse = orderOpts.reverse;
708
+ if (orderOpts.exclude)
709
+ xOrderOptions.exclude = orderOpts.exclude;
710
+ if (orderOpts.drop !== undefined)
711
+ xOrderOptions.drop = orderOpts.drop;
724
712
  }
725
- this.cells.push(row);
726
713
  }
727
- }
728
- drawChar(x, y, char, fg) {
729
- this.setCell(x, y, { char, fg });
730
- }
731
- drawString(x, y, str, fg) {
732
- for (let i = 0;i < str.length; i++) {
733
- this.drawChar(x + i, y, str[i], fg);
714
+ const xDomain = inferDiscreteDomain(data, aes.x, xOrderOptions);
715
+ x = createResolvedDiscreteScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1]);
716
+ if (userXScale?.labels) {
717
+ x.labels = userXScale.labels;
734
718
  }
735
- }
736
- drawHLine(x, y, length, char = "", fg) {
737
- for (let i = 0;i < length; i++) {
738
- this.drawChar(x + i, y, char, fg);
719
+ } else {
720
+ const xTrans = userXScale?.trans ?? "identity";
721
+ const xDomain = coordLimits?.xlim ?? userXScale?.domain ?? computeDomain(data, aes.x, xTrans);
722
+ x = createResolvedContinuousScale("x", xDomain, [plotArea.x, plotArea.x + plotArea.width - 1], xTrans);
723
+ if (userXScale?.breaks) {
724
+ x.breaks = userXScale.breaks;
739
725
  }
740
- }
741
- drawVLine(x, y, length, char = "│", fg) {
742
- for (let i = 0;i < length; i++) {
743
- this.drawChar(x, y + i, char, fg);
726
+ if (userXScale?.labels) {
727
+ x.labels = userXScale.labels;
744
728
  }
745
729
  }
746
- drawPoint(x, y, fg, shape = "●") {
747
- this.drawChar(x, y, shape, fg);
748
- }
749
- fillRect(x, y, width, height, char = " ", fg, bg) {
750
- for (let dy = 0;dy < height; dy++) {
751
- for (let dx = 0;dx < width; dx++) {
752
- this.setCell(x + dx, y + dy, { char, fg, bg });
730
+ const yIsCategorical = isCategoricalField(data, aes.y);
731
+ let y;
732
+ if (yIsCategorical) {
733
+ const yOrderOptions = {};
734
+ if (userYScale) {
735
+ if (userYScale.domain && Array.isArray(userYScale.domain)) {
736
+ yOrderOptions.limits = userYScale.domain;
737
+ }
738
+ const orderOpts = userYScale.orderOptions;
739
+ if (orderOpts) {
740
+ if (orderOpts.order)
741
+ yOrderOptions.order = orderOpts.order;
742
+ if (orderOpts.reverse)
743
+ yOrderOptions.reverse = orderOpts.reverse;
744
+ if (orderOpts.exclude)
745
+ yOrderOptions.exclude = orderOpts.exclude;
746
+ if (orderOpts.drop !== undefined)
747
+ yOrderOptions.drop = orderOpts.drop;
753
748
  }
754
749
  }
750
+ const yDomain = inferDiscreteDomain(data, aes.y, yOrderOptions);
751
+ y = createResolvedDiscreteScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y]);
752
+ if (userYScale?.labels) {
753
+ y.labels = userYScale.labels;
754
+ }
755
+ } else {
756
+ const yTrans = userYScale?.trans ?? "identity";
757
+ const yDomain = coordLimits?.ylim ?? userYScale?.domain ?? computeDomain(data, aes.y, yTrans);
758
+ y = createResolvedContinuousScale("y", yDomain, [plotArea.y + plotArea.height - 1, plotArea.y], yTrans);
759
+ if (userYScale?.breaks) {
760
+ y.breaks = userYScale.breaks;
761
+ }
762
+ if (userYScale?.labels) {
763
+ y.labels = userYScale.labels;
764
+ }
755
765
  }
756
- drawBox(x, y, width, height, style = "single", fg) {
757
- const chars = style === "double" ? { tl: "╔", tr: "╗", bl: "╚", br: "╝", h: "═", v: "║" } : style === "rounded" ? { tl: "╭", tr: "╮", bl: "╰", br: "╯", h: "─", v: "│" } : { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" };
758
- this.drawChar(x, y, chars.tl, fg);
759
- this.drawChar(x + width - 1, y, chars.tr, fg);
760
- this.drawChar(x, y + height - 1, chars.bl, fg);
761
- this.drawChar(x + width - 1, y + height - 1, chars.br, fg);
762
- this.drawHLine(x + 1, y, width - 2, chars.h, fg);
763
- this.drawHLine(x + 1, y + height - 1, width - 2, chars.h, fg);
764
- this.drawVLine(x, y + 1, height - 2, chars.v, fg);
765
- this.drawVLine(x + width - 1, y + 1, height - 2, chars.v, fg);
766
- }
767
- toString() {
768
- return this.cells.map((row) => row.map((cell) => cell.char).join("")).join(`
769
- `);
766
+ const context = { x, y };
767
+ if (aes.y2) {
768
+ const userY2Scale = userScales.find((s) => s.aesthetic === "y2");
769
+ const y2Trans = userY2Scale?.trans ?? "identity";
770
+ const y2Domain = userY2Scale?.domain ?? computeDomain(data, aes.y2, y2Trans);
771
+ const y2 = createResolvedContinuousScale("y2", y2Domain, [plotArea.y + plotArea.height - 1, plotArea.y], y2Trans);
772
+ if (userY2Scale?.breaks) {
773
+ y2.breaks = userY2Scale.breaks;
774
+ }
775
+ if (userY2Scale?.labels) {
776
+ y2.labels = userY2Scale.labels;
777
+ }
778
+ context.y2 = y2;
770
779
  }
771
- toAnsiString() {
772
- const lines = [];
773
- for (const row of this.cells) {
774
- let line = "";
775
- let currentFg = null;
776
- let currentBg = null;
777
- for (const cell of row) {
778
- const fgChanged = !currentFg || currentFg.r !== cell.fg.r || currentFg.g !== cell.fg.g || currentFg.b !== cell.fg.b;
779
- const bgChanged = cell.bg.a > 0 && (!currentBg || currentBg.r !== cell.bg.r || currentBg.g !== cell.bg.g || currentBg.b !== cell.bg.b);
780
- if (fgChanged) {
781
- line += `\x1B[38;2;${cell.fg.r};${cell.fg.g};${cell.fg.b}m`;
782
- currentFg = cell.fg;
783
- }
784
- if (bgChanged) {
785
- line += `\x1B[48;2;${cell.bg.r};${cell.bg.g};${cell.bg.b}m`;
786
- currentBg = cell.bg;
787
- }
788
- if (cell.bold)
789
- line += "\x1B[1m";
790
- if (cell.italic)
791
- line += "\x1B[3m";
792
- if (cell.underline)
793
- line += "\x1B[4m";
794
- line += cell.char;
795
- if (cell.bold || cell.italic || cell.underline) {
796
- line += "\x1B[22;23;24m";
797
- if (currentFg) {
798
- line += `\x1B[38;2;${currentFg.r};${currentFg.g};${currentFg.b}m`;
780
+ const colorAesField = aes.color || aes.fill;
781
+ if (colorAesField) {
782
+ const colorOrderOptions = {};
783
+ if (userColorScale) {
784
+ if (userColorScale.domain && Array.isArray(userColorScale.domain)) {
785
+ colorOrderOptions.limits = userColorScale.domain;
786
+ }
787
+ const orderOpts = userColorScale.orderOptions;
788
+ if (orderOpts) {
789
+ if (orderOpts.order)
790
+ colorOrderOptions.order = orderOpts.order;
791
+ if (orderOpts.reverse)
792
+ colorOrderOptions.reverse = orderOpts.reverse;
793
+ if (orderOpts.exclude)
794
+ colorOrderOptions.exclude = orderOpts.exclude;
795
+ if (orderOpts.drop !== undefined)
796
+ colorOrderOptions.drop = orderOpts.drop;
797
+ }
798
+ }
799
+ const colorDomain = inferDiscreteDomain(data, colorAesField, colorOrderOptions);
800
+ if (userColorScale && userColorScale.map) {
801
+ context.color = {
802
+ aesthetic: userColorScale.aesthetic || "color",
803
+ type: userColorScale.type === "continuous" ? "continuous" : "discrete",
804
+ domain: userColorScale.type === "continuous" ? userColorScale.domain ?? inferContinuousDomain(data, colorAesField) : colorDomain,
805
+ map: (value) => {
806
+ const result = userColorScale.map(value);
807
+ if (typeof result === "object" && "r" in result) {
808
+ return result;
799
809
  }
810
+ return { r: 128, g: 128, b: 128, a: 1 };
800
811
  }
801
- }
802
- line += "\x1B[0m";
803
- lines.push(line);
812
+ };
813
+ } else {
814
+ context.color = createResolvedDiscreteColorScale(colorDomain);
804
815
  }
805
- return lines.join(`
806
- `);
807
816
  }
817
+ if (aes.size) {
818
+ const sizeDomain = inferContinuousDomain(data, aes.size);
819
+ context.size = createResolvedSizeScale(sizeDomain);
820
+ }
821
+ return context;
808
822
  }
809
- function createCanvas(width, height) {
810
- return new TerminalCanvas(width, height);
811
- }
812
-
813
- // src/pipeline/pipeline.ts
814
- init_scales();
815
-
816
- // src/pipeline/render-geoms.ts
817
- init_scales();
823
+ var CATEGORY_COLORS, DEFAULT_POINT_COLOR;
824
+ var init_scales = __esm(() => {
825
+ CATEGORY_COLORS = [
826
+ { r: 31, g: 119, b: 180, a: 1 },
827
+ { r: 255, g: 127, b: 14, a: 1 },
828
+ { r: 44, g: 160, b: 44, a: 1 },
829
+ { r: 214, g: 39, b: 40, a: 1 },
830
+ { r: 148, g: 103, b: 189, a: 1 },
831
+ { r: 140, g: 86, b: 75, a: 1 },
832
+ { r: 227, g: 119, b: 194, a: 1 },
833
+ { r: 127, g: 127, b: 127, a: 1 },
834
+ { r: 188, g: 189, b: 34, a: 1 },
835
+ { r: 23, g: 190, b: 207, a: 1 }
836
+ ];
837
+ DEFAULT_POINT_COLOR = { r: 79, g: 169, b: 238, a: 1 };
838
+ });
818
839
 
819
840
  // src/positions/index.ts
820
841
  function position_identity() {
@@ -1016,22 +1037,6 @@ function getPositionType(position) {
1016
1037
  }
1017
1038
 
1018
1039
  // src/pipeline/render-geoms.ts
1019
- var POINT_SHAPES = {
1020
- circle: "●",
1021
- filled_circle: "●",
1022
- open_circle: "○",
1023
- square: "■",
1024
- open_square: "□",
1025
- diamond: "◆",
1026
- open_diamond: "◇",
1027
- triangle: "▲",
1028
- open_triangle: "△",
1029
- cross: "✕",
1030
- plus: "+",
1031
- star: "★",
1032
- dot: "•"
1033
- };
1034
- var SIZE_CHARS = ["·", "•", "●", "⬤"];
1035
1040
  function getPointShape(shape) {
1036
1041
  if (!shape)
1037
1042
  return POINT_SHAPES.circle;
@@ -1044,6 +1049,44 @@ function getPointColor(row, aes, colorScale) {
1044
1049
  }
1045
1050
  return DEFAULT_POINT_COLOR;
1046
1051
  }
1052
+ function parseColorToRgba(color, fallback = { r: 128, g: 128, b: 128, a: 1 }) {
1053
+ if (!color)
1054
+ return fallback;
1055
+ if (typeof color === "object" && color !== null && "r" in color) {
1056
+ return color;
1057
+ }
1058
+ if (typeof color === "string") {
1059
+ if (color.startsWith("#")) {
1060
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
1061
+ if (result) {
1062
+ return {
1063
+ r: parseInt(result[1], 16),
1064
+ g: parseInt(result[2], 16),
1065
+ b: parseInt(result[3], 16),
1066
+ a: 1
1067
+ };
1068
+ }
1069
+ }
1070
+ const namedColors = {
1071
+ red: { r: 255, g: 0, b: 0, a: 1 },
1072
+ blue: { r: 0, g: 0, b: 255, a: 1 },
1073
+ green: { r: 0, g: 128, b: 0, a: 1 },
1074
+ black: { r: 0, g: 0, b: 0, a: 1 },
1075
+ white: { r: 255, g: 255, b: 255, a: 1 },
1076
+ gray: { r: 128, g: 128, b: 128, a: 1 },
1077
+ grey: { r: 128, g: 128, b: 128, a: 1 },
1078
+ yellow: { r: 255, g: 255, b: 0, a: 1 },
1079
+ orange: { r: 255, g: 165, b: 0, a: 1 },
1080
+ purple: { r: 128, g: 0, b: 128, a: 1 },
1081
+ cyan: { r: 0, g: 255, b: 255, a: 1 },
1082
+ magenta: { r: 255, g: 0, b: 255, a: 1 }
1083
+ };
1084
+ const named = namedColors[color.toLowerCase()];
1085
+ if (named)
1086
+ return named;
1087
+ }
1088
+ return fallback;
1089
+ }
1047
1090
  function renderGeomPoint(data, geom, aes, scales, canvas) {
1048
1091
  const defaultShape = getPointShape(geom.params.shape);
1049
1092
  const positionType = getPositionType(geom.position);
@@ -1442,7 +1485,7 @@ function renderGeomHLine(_data, geom, _aes, scales, canvas) {
1442
1485
  if (yintercept === undefined)
1443
1486
  return;
1444
1487
  const cy = Math.round(scales.y.map(yintercept));
1445
- const color = geom.params.color ?? { r: 128, g: 128, b: 128, a: 1 };
1488
+ const color = parseColorToRgba(geom.params.color);
1446
1489
  const startX = Math.round(scales.x.range[0]);
1447
1490
  const endX = Math.round(scales.x.range[1]);
1448
1491
  canvas.drawHLine(startX, cy, endX - startX + 1, "─", color);
@@ -1452,7 +1495,7 @@ function renderGeomVLine(_data, geom, _aes, scales, canvas) {
1452
1495
  if (xintercept === undefined)
1453
1496
  return;
1454
1497
  const cx = Math.round(scales.x.map(xintercept));
1455
- const color = geom.params.color ?? { r: 128, g: 128, b: 128, a: 1 };
1498
+ const color = parseColorToRgba(geom.params.color);
1456
1499
  const startY = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
1457
1500
  const endY = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
1458
1501
  canvas.drawVLine(cx, startY, endY - startY + 1, "│", color);
@@ -1769,20 +1812,52 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
1769
1812
  const plotRight = Math.round(scales.x.range[1]);
1770
1813
  const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
1771
1814
  const plotBottom = Math.round(Math.max(scales.y.range[0], scales.y.range[1]));
1772
- let tileWidth = geom.params.width;
1773
- let tileHeight = geom.params.height;
1774
- if (!tileWidth || !tileHeight) {
1775
- const xVals = [...new Set(data.map((r) => Number(r[aes.x]) || 0))].sort((a, b) => a - b);
1776
- const yVals = [...new Set(data.map((r) => Number(r[aes.y]) || 0))].sort((a, b) => a - b);
1777
- if (xVals.length > 1) {
1778
- tileWidth = tileWidth ?? xVals[1] - xVals[0];
1815
+ let halfW;
1816
+ let halfH;
1817
+ const xIsDiscrete = scales.x.type === "discrete";
1818
+ const yIsDiscrete = scales.y.type === "discrete";
1819
+ if (xIsDiscrete) {
1820
+ const xDomain = scales.x.domain;
1821
+ const canvasWidth = Math.abs(scales.x.range[1] - scales.x.range[0]);
1822
+ halfW = Math.max(1, Math.floor(canvasWidth / (xDomain.length * 2)));
1823
+ } else {
1824
+ let tileWidth = data[0]?.width ?? geom.params.width;
1825
+ if (!tileWidth) {
1826
+ const xVals = [...new Set(data.map((r) => Number(r[aes.x])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
1827
+ if (xVals.length > 1) {
1828
+ tileWidth = xVals[1] - xVals[0];
1829
+ }
1830
+ }
1831
+ tileWidth = tileWidth ?? 1;
1832
+ const sampleX = data.find((r) => r[aes.x] !== null && r[aes.x] !== undefined)?.[aes.x];
1833
+ if (sampleX !== undefined) {
1834
+ const cx = scales.x.map(sampleX);
1835
+ halfW = Math.max(1, Math.floor(Math.abs(scales.x.map(Number(sampleX) + tileWidth / 2) - cx)));
1836
+ } else {
1837
+ halfW = 1;
1838
+ }
1839
+ }
1840
+ if (yIsDiscrete) {
1841
+ const yDomain = scales.y.domain;
1842
+ const canvasHeight = Math.abs(scales.y.range[1] - scales.y.range[0]);
1843
+ halfH = Math.max(1, Math.floor(canvasHeight / (yDomain.length * 2)));
1844
+ } else {
1845
+ let tileHeight = data[0]?.height ?? geom.params.height;
1846
+ if (!tileHeight) {
1847
+ const yVals = [...new Set(data.map((r) => Number(r[aes.y])).filter((v) => !isNaN(v)))].sort((a, b) => a - b);
1848
+ if (yVals.length > 1) {
1849
+ tileHeight = yVals[1] - yVals[0];
1850
+ }
1779
1851
  }
1780
- if (yVals.length > 1) {
1781
- tileHeight = tileHeight ?? yVals[1] - yVals[0];
1852
+ tileHeight = tileHeight ?? 1;
1853
+ const sampleY = data.find((r) => r[aes.y] !== null && r[aes.y] !== undefined)?.[aes.y];
1854
+ if (sampleY !== undefined) {
1855
+ const cy = scales.y.map(sampleY);
1856
+ halfH = Math.max(1, Math.floor(Math.abs(scales.y.map(Number(sampleY) + tileHeight / 2) - cy)));
1857
+ } else {
1858
+ halfH = 1;
1782
1859
  }
1783
1860
  }
1784
- tileWidth = tileWidth ?? 1;
1785
- tileHeight = tileHeight ?? 1;
1786
1861
  for (const row of data) {
1787
1862
  const xVal = row[aes.x];
1788
1863
  const yVal = row[aes.y];
@@ -1792,8 +1867,6 @@ function renderGeomTile(data, geom, aes, scales, canvas) {
1792
1867
  }
1793
1868
  const cx = Math.round(scales.x.map(xVal));
1794
1869
  const cy = Math.round(scales.y.map(yVal));
1795
- const halfW = Math.max(1, Math.floor(Math.abs(scales.x.map(Number(xVal) + tileWidth / 2) - cx)));
1796
- const halfH = Math.max(1, Math.floor(Math.abs(scales.y.map(Number(yVal) + tileHeight / 2) - cy)));
1797
1870
  let color;
1798
1871
  if (scales.color && typeof fillVal === "number") {
1799
1872
  color = scales.color.map(fillVal);
@@ -1981,7 +2054,7 @@ function renderGeomAbline(_data, geom, _aes, scales, canvas) {
1981
2054
  const intercept = geom.params.intercept ?? 0;
1982
2055
  const linetype = geom.params.linetype ?? "solid";
1983
2056
  const lineChar = linetype === "dotted" ? "·" : linetype === "dashed" ? "╌" : "─";
1984
- const color = geom.params.color ?? { r: 128, g: 128, b: 128, a: 1 };
2057
+ const color = parseColorToRgba(geom.params.color);
1985
2058
  const plotLeft = Math.round(scales.x.range[0]);
1986
2059
  const plotRight = Math.round(scales.x.range[1]);
1987
2060
  const plotTop = Math.round(Math.min(scales.y.range[0], scales.y.range[1]));
@@ -2173,6 +2246,7 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
2173
2246
  break;
2174
2247
  case "tile":
2175
2248
  case "raster":
2249
+ case "bin2d":
2176
2250
  renderGeomTile(data, geom, aes, scales, canvas);
2177
2251
  break;
2178
2252
  case "contour":
@@ -2202,6 +2276,26 @@ function renderGeom(data, geom, aes, scales, canvas, coordType) {
2202
2276
  break;
2203
2277
  }
2204
2278
  }
2279
+ var POINT_SHAPES, SIZE_CHARS;
2280
+ var init_render_geoms = __esm(() => {
2281
+ init_scales();
2282
+ POINT_SHAPES = {
2283
+ circle: "●",
2284
+ filled_circle: "●",
2285
+ open_circle: "○",
2286
+ square: "■",
2287
+ open_square: "□",
2288
+ diamond: "◆",
2289
+ open_diamond: "◇",
2290
+ triangle: "▲",
2291
+ open_triangle: "△",
2292
+ cross: "✕",
2293
+ plus: "+",
2294
+ star: "★",
2295
+ dot: "•"
2296
+ };
2297
+ SIZE_CHARS = ["·", "•", "●", "⬤"];
2298
+ });
2205
2299
 
2206
2300
  // src/pipeline/render-axes.ts
2207
2301
  function calculateTicks(domain, targetTicks = 5, transform, invert) {
@@ -2509,7 +2603,6 @@ function renderTitle(canvas, title, width, theme) {
2509
2603
  }
2510
2604
  canvas.drawString(x, 0, title, titleColor);
2511
2605
  }
2512
- var SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
2513
2606
  function renderMultiLegend(canvas, entries, x, y, theme, width) {
2514
2607
  if (theme.legend.position === "none" || entries.length === 0)
2515
2608
  return;
@@ -2637,6 +2730,10 @@ function formatContinuousLegendValue(value) {
2637
2730
  }
2638
2731
  return value.toFixed(1);
2639
2732
  }
2733
+ var SIZE_SYMBOLS;
2734
+ var init_render_axes = __esm(() => {
2735
+ SIZE_SYMBOLS = ["·", "•", "●", "⬤"];
2736
+ });
2640
2737
 
2641
2738
  // src/stats/bin.ts
2642
2739
  function computeBins(data, field, params = {}) {
@@ -2748,6 +2845,248 @@ function stat_bin(params = {}) {
2748
2845
  };
2749
2846
  }
2750
2847
 
2848
+ // src/performance/binning.ts
2849
+ function computeDomain2(data, field) {
2850
+ let min = Infinity;
2851
+ let max = -Infinity;
2852
+ for (const d of data) {
2853
+ const v = d[field];
2854
+ if (typeof v === "number" && !isNaN(v)) {
2855
+ if (v < min)
2856
+ min = v;
2857
+ if (v > max)
2858
+ max = v;
2859
+ }
2860
+ }
2861
+ if (min === Infinity)
2862
+ return [0, 1];
2863
+ if (min === max)
2864
+ return [min - 0.5, max + 0.5];
2865
+ return [min, max];
2866
+ }
2867
+ function aggregateValues(values, method) {
2868
+ if (values.length === 0)
2869
+ return 0;
2870
+ switch (method) {
2871
+ case "count":
2872
+ return values.length;
2873
+ case "sum":
2874
+ return values.reduce((a, b) => a + b, 0);
2875
+ case "mean":
2876
+ return values.reduce((a, b) => a + b, 0) / values.length;
2877
+ case "median":
2878
+ const sorted = [...values].sort((a, b) => a - b);
2879
+ const mid = Math.floor(sorted.length / 2);
2880
+ return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
2881
+ case "min":
2882
+ return Math.min(...values);
2883
+ case "max":
2884
+ return Math.max(...values);
2885
+ default:
2886
+ return values.length;
2887
+ }
2888
+ }
2889
+ function rectbin(data, options) {
2890
+ const {
2891
+ xField,
2892
+ yField,
2893
+ xBins = 20,
2894
+ yBins = 20,
2895
+ aggregate = "count",
2896
+ valueField
2897
+ } = options;
2898
+ if (data.length === 0)
2899
+ return [];
2900
+ const xDomain = options.xDomain ?? computeDomain2(data, xField);
2901
+ const yDomain = options.yDomain ?? computeDomain2(data, yField);
2902
+ const xRange = xDomain[1] - xDomain[0];
2903
+ const yRange = yDomain[1] - yDomain[0];
2904
+ const binWidth = xRange / xBins;
2905
+ const binHeight = yRange / yBins;
2906
+ const bins = new Map;
2907
+ for (const point of data) {
2908
+ const x = point[xField];
2909
+ const y = point[yField];
2910
+ if (typeof x !== "number" || typeof y !== "number")
2911
+ continue;
2912
+ const bx = Math.min(xBins - 1, Math.max(0, Math.floor((x - xDomain[0]) / binWidth)));
2913
+ const by = Math.min(yBins - 1, Math.max(0, Math.floor((y - yDomain[0]) / binHeight)));
2914
+ const key = `${bx},${by}`;
2915
+ if (!bins.has(key)) {
2916
+ bins.set(key, { points: [], values: [] });
2917
+ }
2918
+ const bin = bins.get(key);
2919
+ bin.points.push(point);
2920
+ if (valueField && typeof point[valueField] === "number") {
2921
+ bin.values.push(point[valueField]);
2922
+ }
2923
+ }
2924
+ const result = [];
2925
+ for (const [key, bin] of bins) {
2926
+ const [bx, by] = key.split(",").map(Number);
2927
+ const centerX = xDomain[0] + (bx + 0.5) * binWidth;
2928
+ const centerY = yDomain[0] + (by + 0.5) * binHeight;
2929
+ result.push({
2930
+ x: centerX,
2931
+ y: centerY,
2932
+ count: bin.points.length,
2933
+ value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
2934
+ width: binWidth,
2935
+ height: binHeight,
2936
+ points: bin.points
2937
+ });
2938
+ }
2939
+ return result;
2940
+ }
2941
+ function hexbin(data, options) {
2942
+ const { xField, yField, aggregate = "count", valueField, radius = 10 } = options;
2943
+ if (data.length === 0)
2944
+ return [];
2945
+ const xDomain = options.xDomain ?? computeDomain2(data, xField);
2946
+ const yDomain = options.yDomain ?? computeDomain2(data, yField);
2947
+ const hexWidth = radius * 2;
2948
+ const hexHeight = radius * Math.sqrt(3);
2949
+ const bins = new Map;
2950
+ for (const point of data) {
2951
+ const x = point[xField];
2952
+ const y = point[yField];
2953
+ if (typeof x !== "number" || typeof y !== "number")
2954
+ continue;
2955
+ const col = Math.round((x - xDomain[0]) / (hexWidth * 0.75));
2956
+ const row = Math.round((y - yDomain[0]) / hexHeight - col % 2 * 0.5);
2957
+ const key = `${col},${row}`;
2958
+ if (!bins.has(key)) {
2959
+ bins.set(key, { points: [], values: [], col, row });
2960
+ }
2961
+ const bin = bins.get(key);
2962
+ bin.points.push(point);
2963
+ if (valueField && typeof point[valueField] === "number") {
2964
+ bin.values.push(point[valueField]);
2965
+ }
2966
+ }
2967
+ function hexVertices(cx, cy, r) {
2968
+ const vertices = [];
2969
+ for (let i = 0;i < 6; i++) {
2970
+ const angle = Math.PI / 3 * i + Math.PI / 6;
2971
+ vertices.push({
2972
+ x: cx + r * Math.cos(angle),
2973
+ y: cy + r * Math.sin(angle)
2974
+ });
2975
+ }
2976
+ return vertices;
2977
+ }
2978
+ const result = [];
2979
+ for (const [, bin] of bins) {
2980
+ const centerX = xDomain[0] + bin.col * hexWidth * 0.75;
2981
+ const centerY = yDomain[0] + (bin.row + bin.col % 2 * 0.5) * hexHeight;
2982
+ result.push({
2983
+ x: centerX,
2984
+ y: centerY,
2985
+ count: bin.points.length,
2986
+ value: aggregateValues(bin.values.length > 0 ? bin.values : [bin.points.length], aggregate),
2987
+ width: hexWidth,
2988
+ height: hexHeight,
2989
+ points: bin.points,
2990
+ vertices: hexVertices(centerX, centerY, radius),
2991
+ col: bin.col,
2992
+ row: bin.row
2993
+ });
2994
+ }
2995
+ return result;
2996
+ }
2997
+
2998
+ class Binner {
2999
+ options;
3000
+ type;
3001
+ hexRadius;
3002
+ constructor(options) {
3003
+ this.options = options;
3004
+ this.type = options.type ?? "rect";
3005
+ this.hexRadius = options.hexRadius ?? 10;
3006
+ }
3007
+ bin(data) {
3008
+ if (this.type === "hex") {
3009
+ return hexbin(data, { ...this.options, radius: this.hexRadius });
3010
+ }
3011
+ return rectbin(data, this.options);
3012
+ }
3013
+ toPlotData(data) {
3014
+ const bins = this.bin(data);
3015
+ const maxCount = Math.max(...bins.map((b) => b.count));
3016
+ const minSize = 1;
3017
+ const maxSize = 5;
3018
+ return bins.map((bin) => ({
3019
+ x: bin.x,
3020
+ y: bin.y,
3021
+ count: bin.count,
3022
+ value: bin.value,
3023
+ size: minSize + bin.count / maxCount * (maxSize - minSize)
3024
+ }));
3025
+ }
3026
+ getDensityColors(bins, colorScale) {
3027
+ const maxCount = Math.max(...bins.map((b) => b.count));
3028
+ const colors = new Map;
3029
+ for (const bin of bins) {
3030
+ const t = bin.count / maxCount;
3031
+ colors.set(bin, colorScale(t));
3032
+ }
3033
+ return colors;
3034
+ }
3035
+ }
3036
+ function createBinner(options) {
3037
+ return new Binner(options);
3038
+ }
3039
+
3040
+ // src/stats/bin2d.ts
3041
+ function computeBins2d(data, xField, yField, params = {}) {
3042
+ const {
3043
+ bins = 30,
3044
+ binsx,
3045
+ binsy,
3046
+ drop = true
3047
+ } = params;
3048
+ const xBins = binsx ?? bins;
3049
+ const yBins = binsy ?? bins;
3050
+ const binned = rectbin(data, {
3051
+ xField,
3052
+ yField,
3053
+ xBins,
3054
+ yBins,
3055
+ aggregate: "count"
3056
+ });
3057
+ const total = data.length;
3058
+ const results = binned.map((bin) => ({
3059
+ x: bin.x,
3060
+ y: bin.y,
3061
+ count: bin.count,
3062
+ density: total > 0 ? bin.count / total : 0,
3063
+ width: bin.width,
3064
+ height: bin.height
3065
+ }));
3066
+ if (drop) {
3067
+ return results.filter((r) => r.count > 0);
3068
+ }
3069
+ return results;
3070
+ }
3071
+ function stat_bin2d(params = {}) {
3072
+ return {
3073
+ type: "bin2d",
3074
+ compute(data, aes) {
3075
+ const bins = computeBins2d(data, aes.x, aes.y, params);
3076
+ return bins.map((bin) => ({
3077
+ x: bin.x,
3078
+ y: bin.y,
3079
+ count: bin.count,
3080
+ density: bin.density,
3081
+ fill: bin.count,
3082
+ width: bin.width,
3083
+ height: bin.height
3084
+ }));
3085
+ }
3086
+ };
3087
+ }
3088
+ var init_bin2d = () => {};
3089
+
2751
3090
  // src/stats/boxplot.ts
2752
3091
  function quantile(sorted, p) {
2753
3092
  if (sorted.length === 0)
@@ -3163,17 +3502,6 @@ function stat_smooth(params = {}) {
3163
3502
  }
3164
3503
 
3165
3504
  // src/stats/summary.ts
3166
- var summaryFunctions = {
3167
- mean: (values) => values.reduce((a, b) => a + b, 0) / values.length,
3168
- median: (values) => {
3169
- const sorted = [...values].sort((a, b) => a - b);
3170
- const mid = Math.floor(sorted.length / 2);
3171
- return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
3172
- },
3173
- min: (values) => Math.min(...values),
3174
- max: (values) => Math.max(...values),
3175
- sum: (values) => values.reduce((a, b) => a + b, 0)
3176
- };
3177
3505
  function sd(values) {
3178
3506
  const n = values.length;
3179
3507
  if (n < 2)
@@ -3305,6 +3633,20 @@ function stat_summary(params = {}) {
3305
3633
  }
3306
3634
  };
3307
3635
  }
3636
+ var summaryFunctions;
3637
+ var init_summary = __esm(() => {
3638
+ summaryFunctions = {
3639
+ mean: (values) => values.reduce((a, b) => a + b, 0) / values.length,
3640
+ median: (values) => {
3641
+ const sorted = [...values].sort((a, b) => a - b);
3642
+ const mid = Math.floor(sorted.length / 2);
3643
+ return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
3644
+ },
3645
+ min: (values) => Math.min(...values),
3646
+ max: (values) => Math.max(...values),
3647
+ sum: (values) => values.reduce((a, b) => a + b, 0)
3648
+ };
3649
+ });
3308
3650
 
3309
3651
  // src/stats/qq.ts
3310
3652
  function qnorm(p, mean = 0, sd2 = 1) {
@@ -3487,15 +3829,125 @@ function stat_qq_line(params = {}) {
3487
3829
  };
3488
3830
  }
3489
3831
 
3832
+ // src/stats/density2d.ts
3833
+ function gaussian2d(dx, dy, hx, hy) {
3834
+ const ux = dx / hx;
3835
+ const uy = dy / hy;
3836
+ return Math.exp(-0.5 * (ux * ux + uy * uy)) / (2 * Math.PI * hx * hy);
3837
+ }
3838
+ function scottBandwidth2d(values) {
3839
+ const n = values.length;
3840
+ if (n < 2)
3841
+ return 1;
3842
+ const mean = values.reduce((a, b) => a + b, 0) / n;
3843
+ const variance = values.reduce((sum, v) => sum + (v - mean) ** 2, 0) / (n - 1);
3844
+ const std = Math.sqrt(variance);
3845
+ return std * Math.pow(n, -1 / 6);
3846
+ }
3847
+ function computeDensity2d(data, xField, yField, params = {}) {
3848
+ const points = [];
3849
+ const xValues = [];
3850
+ const yValues = [];
3851
+ for (const row of data) {
3852
+ const xVal = row[xField];
3853
+ const yVal = row[yField];
3854
+ if (xVal === null || xVal === undefined || yVal === null || yVal === undefined)
3855
+ continue;
3856
+ const x = Number(xVal);
3857
+ const y = Number(yVal);
3858
+ if (isNaN(x) || isNaN(y))
3859
+ continue;
3860
+ points.push({ x, y });
3861
+ xValues.push(x);
3862
+ yValues.push(y);
3863
+ }
3864
+ if (points.length < 3) {
3865
+ return [];
3866
+ }
3867
+ const n = params.n ?? 50;
3868
+ const nx = params.nx ?? n;
3869
+ const ny = params.ny ?? n;
3870
+ const adjust = params.adjust ?? 1;
3871
+ let hx, hy;
3872
+ if (Array.isArray(params.h)) {
3873
+ hx = params.h[0] * adjust;
3874
+ hy = params.h[1] * adjust;
3875
+ } else if (params.h !== undefined) {
3876
+ hx = params.h * adjust;
3877
+ hy = params.h * adjust;
3878
+ } else {
3879
+ hx = scottBandwidth2d(xValues) * adjust;
3880
+ hy = scottBandwidth2d(yValues) * adjust;
3881
+ }
3882
+ if (hx <= 0)
3883
+ hx = 1;
3884
+ if (hy <= 0)
3885
+ hy = 1;
3886
+ const xMin = Math.min(...xValues);
3887
+ const xMax = Math.max(...xValues);
3888
+ const yMin = Math.min(...yValues);
3889
+ const yMax = Math.max(...yValues);
3890
+ const xPad = 3 * hx;
3891
+ const yPad = 3 * hy;
3892
+ const gridXMin = xMin - xPad;
3893
+ const gridXMax = xMax + xPad;
3894
+ const gridYMin = yMin - yPad;
3895
+ const gridYMax = yMax + yPad;
3896
+ const xStep = (gridXMax - gridXMin) / (nx - 1);
3897
+ const yStep = (gridYMax - gridYMin) / (ny - 1);
3898
+ const results = [];
3899
+ const nPoints = points.length;
3900
+ for (let i = 0;i < nx; i++) {
3901
+ const gx = gridXMin + i * xStep;
3902
+ for (let j = 0;j < ny; j++) {
3903
+ const gy = gridYMin + j * yStep;
3904
+ let density = 0;
3905
+ for (const pt of points) {
3906
+ density += gaussian2d(gx - pt.x, gy - pt.y, hx, hy);
3907
+ }
3908
+ density /= nPoints;
3909
+ results.push({
3910
+ x: gx,
3911
+ y: gy,
3912
+ z: density,
3913
+ density,
3914
+ level: density
3915
+ });
3916
+ }
3917
+ }
3918
+ return results;
3919
+ }
3920
+ function stat_density_2d(params = {}) {
3921
+ return {
3922
+ type: "density_2d",
3923
+ compute(data, aes) {
3924
+ if (aes.color) {
3925
+ const groups = new Map;
3926
+ for (const row of data) {
3927
+ const group = String(row[aes.color] ?? "default");
3928
+ if (!groups.has(group)) {
3929
+ groups.set(group, []);
3930
+ }
3931
+ groups.get(group).push(row);
3932
+ }
3933
+ const result = [];
3934
+ for (const [group, groupData] of groups) {
3935
+ const density = computeDensity2d(groupData, aes.x, aes.y, params);
3936
+ for (const d of density) {
3937
+ result.push({
3938
+ ...d,
3939
+ [aes.color]: group
3940
+ });
3941
+ }
3942
+ }
3943
+ return result;
3944
+ }
3945
+ return computeDensity2d(data, aes.x, aes.y, params);
3946
+ }
3947
+ };
3948
+ }
3949
+
3490
3950
  // src/facets/index.ts
3491
- var label_value = (value) => value;
3492
- var label_both = (value, variable) => variable ? `${variable}: ${value}` : value;
3493
- var label_parsed = (value) => value.replace(/_/g, " ");
3494
- var label_wrap = (width) => (value) => {
3495
- if (value.length <= width)
3496
- return value;
3497
- return value.substring(0, width - 1) + "…";
3498
- };
3499
3951
  function as_labeller(labels) {
3500
3952
  return (value) => labels[value] ?? value;
3501
3953
  }
@@ -3688,6 +4140,11 @@ function calculateGridStripLayout(totalWidth, totalHeight, nrow, ncol, hasTitle,
3688
4140
  rowStripWidth: rowStripWidth - 1
3689
4141
  };
3690
4142
  }
4143
+ var label_value = (value) => value, label_both = (value, variable) => variable ? `${variable}: ${value}` : value, label_parsed = (value) => value.replace(/_/g, " "), label_wrap = (width) => (value) => {
4144
+ if (value.length <= width)
4145
+ return value;
4146
+ return value.substring(0, width - 1) + "…";
4147
+ };
3691
4148
 
3692
4149
  // src/pipeline/pipeline.ts
3693
4150
  function calculateLayout(spec, options) {
@@ -3800,6 +4257,23 @@ function applyStatTransform(data, geom, aes) {
3800
4257
  dparams: geom.params.dparams
3801
4258
  });
3802
4259
  return qqLineStat.compute(data, aes);
4260
+ } else if (geom.stat === "bin2d") {
4261
+ const bin2dStat = stat_bin2d({
4262
+ bins: geom.params.bins,
4263
+ binsx: geom.params.binsx,
4264
+ binsy: geom.params.binsy,
4265
+ drop: geom.params.drop
4266
+ });
4267
+ return bin2dStat.compute(data, aes);
4268
+ } else if (geom.stat === "density_2d") {
4269
+ const density2dStat = stat_density_2d({
4270
+ h: geom.params.bandwidth,
4271
+ n: geom.params.n,
4272
+ nx: geom.params.nx,
4273
+ ny: geom.params.ny,
4274
+ adjust: geom.params.adjust
4275
+ });
4276
+ return density2dStat.compute(data, aes);
3803
4277
  }
3804
4278
  return data;
3805
4279
  }
@@ -3864,6 +4338,14 @@ function renderToCanvas(spec, options) {
3864
4338
  scaleAes = { ...spec.aes, x: "x", y: "y" };
3865
4339
  }
3866
4340
  break;
4341
+ } else if (geom.stat === "bin2d") {
4342
+ scaleData = applyStatTransform(spec.data, geom, spec.aes);
4343
+ scaleAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
4344
+ break;
4345
+ } else if (geom.stat === "density_2d") {
4346
+ scaleData = applyStatTransform(spec.data, geom, spec.aes);
4347
+ scaleAes = { ...spec.aes, x: "x", y: "y" };
4348
+ break;
3867
4349
  }
3868
4350
  }
3869
4351
  scaleData = applyCoordTransform(scaleData, scaleAes, spec.coord);
@@ -3898,6 +4380,10 @@ function renderToCanvas(spec, options) {
3898
4380
  geomAes = { ...spec.aes, x: "x", y: "y" };
3899
4381
  } else if (geom.stat === "qq_line") {
3900
4382
  geomAes = { ...spec.aes, x: "x", y: "y", xend: "xend", yend: "yend" };
4383
+ } else if (geom.stat === "bin2d") {
4384
+ geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
4385
+ } else if (geom.stat === "density_2d") {
4386
+ geomAes = { ...spec.aes, x: "x", y: "y" };
3901
4387
  }
3902
4388
  geomData = applyCoordTransform(geomData, geomAes, spec.coord);
3903
4389
  }
@@ -4148,8 +4634,14 @@ function renderPanel(canvas, panel, layout, spec, facet, sharedScales, nrow = 1,
4148
4634
  renderPanelAxes(canvas, scales, plotArea, panel.row, panel.col, nrow, ncol, spec.theme);
4149
4635
  for (const geom of spec.geoms) {
4150
4636
  let geomData = applyStatTransform(panel.data, geom, spec.aes);
4151
- geomData = applyCoordTransform(geomData, spec.aes, spec.coord);
4152
- renderGeom(geomData, geom, spec.aes, scales, canvas, spec.coord.type);
4637
+ let geomAes = spec.aes;
4638
+ if (geom.stat === "bin" || geom.stat === "boxplot" || geom.stat === "count" || geom.stat === "qq") {
4639
+ geomAes = { ...spec.aes, x: "x", y: "y" };
4640
+ } else if (geom.stat === "bin2d") {
4641
+ geomAes = { ...spec.aes, x: "x", y: "y", fill: "fill" };
4642
+ }
4643
+ geomData = applyCoordTransform(geomData, geomAes, spec.coord);
4644
+ renderGeom(geomData, geom, geomAes, scales, canvas, spec.coord.type);
4153
4645
  }
4154
4646
  }
4155
4647
  function renderPanelAxes(canvas, scales, plotArea, row, col, nrow, _ncol, _theme) {
@@ -4197,9 +4689,22 @@ function renderToString(spec, options) {
4197
4689
  }
4198
4690
  return canvas.toAnsiString();
4199
4691
  }
4692
+ var init_pipeline = __esm(() => {
4693
+ init_canvas();
4694
+ init_scales();
4695
+ init_render_geoms();
4696
+ init_render_axes();
4697
+ init_bin2d();
4698
+ init_summary();
4699
+ });
4200
4700
 
4201
4701
  // src/pipeline/index.ts
4202
- init_scales();
4702
+ var init_pipeline2 = __esm(() => {
4703
+ init_pipeline();
4704
+ init_scales();
4705
+ init_render_geoms();
4706
+ init_render_axes();
4707
+ });
4203
4708
 
4204
4709
  // src/grammar.ts
4205
4710
  class GGPlot {
@@ -4290,6 +4795,9 @@ class GGPlot {
4290
4795
  function gg(data = []) {
4291
4796
  return new GGPlot(data);
4292
4797
  }
4798
+ var init_grammar = __esm(() => {
4799
+ init_pipeline2();
4800
+ });
4293
4801
 
4294
4802
  // src/geoms/point.ts
4295
4803
  function geom_point(options = {}) {
@@ -4305,6 +4813,7 @@ function geom_point(options = {}) {
4305
4813
  }
4306
4814
  };
4307
4815
  }
4816
+
4308
4817
  // src/geoms/line.ts
4309
4818
  function geom_line(options = {}) {
4310
4819
  return {
@@ -4343,6 +4852,7 @@ function geom_vline(options) {
4343
4852
  }
4344
4853
  };
4345
4854
  }
4855
+
4346
4856
  // src/geoms/path.ts
4347
4857
  function geom_path(options = {}) {
4348
4858
  return {
@@ -4359,6 +4869,7 @@ function geom_path(options = {}) {
4359
4869
  }
4360
4870
  };
4361
4871
  }
4872
+
4362
4873
  // src/geoms/bar.ts
4363
4874
  function geom_bar(options = {}) {
4364
4875
  return {
@@ -4376,6 +4887,7 @@ function geom_bar(options = {}) {
4376
4887
  function geom_col(options = {}) {
4377
4888
  return geom_bar({ ...options, stat: "identity" });
4378
4889
  }
4890
+
4379
4891
  // src/geoms/text.ts
4380
4892
  function geom_text(options = {}) {
4381
4893
  return {
@@ -4408,6 +4920,7 @@ function geom_label(options = {}) {
4408
4920
  }
4409
4921
  };
4410
4922
  }
4923
+
4411
4924
  // src/geoms/area.ts
4412
4925
  function geom_area(options = {}) {
4413
4926
  return {
@@ -4433,6 +4946,7 @@ function geom_ribbon(options = {}) {
4433
4946
  }
4434
4947
  };
4435
4948
  }
4949
+
4436
4950
  // src/geoms/histogram.ts
4437
4951
  function geom_histogram(options = {}) {
4438
4952
  return {
@@ -4464,6 +4978,7 @@ function geom_freqpoly(options = {}) {
4464
4978
  }
4465
4979
  };
4466
4980
  }
4981
+
4467
4982
  // src/geoms/boxplot.ts
4468
4983
  function geom_boxplot(options = {}) {
4469
4984
  return {
@@ -4480,6 +4995,7 @@ function geom_boxplot(options = {}) {
4480
4995
  }
4481
4996
  };
4482
4997
  }
4998
+
4483
4999
  // src/geoms/segment.ts
4484
5000
  function geom_segment(options = {}) {
4485
5001
  return {
@@ -4512,6 +5028,7 @@ function geom_curve(options = {}) {
4512
5028
  }
4513
5029
  };
4514
5030
  }
5031
+
4515
5032
  // src/geoms/smooth.ts
4516
5033
  function geom_smooth(options = {}) {
4517
5034
  return {
@@ -4531,6 +5048,7 @@ function geom_smooth(options = {}) {
4531
5048
  }
4532
5049
  };
4533
5050
  }
5051
+
4534
5052
  // src/geoms/step.ts
4535
5053
  function geom_step(options = {}) {
4536
5054
  return {
@@ -4546,6 +5064,7 @@ function geom_step(options = {}) {
4546
5064
  }
4547
5065
  };
4548
5066
  }
5067
+
4549
5068
  // src/geoms/rug.ts
4550
5069
  function geom_rug(options = {}) {
4551
5070
  return {
@@ -4561,6 +5080,7 @@ function geom_rug(options = {}) {
4561
5080
  }
4562
5081
  };
4563
5082
  }
5083
+
4564
5084
  // src/geoms/violin.ts
4565
5085
  function geom_violin(options = {}) {
4566
5086
  return {
@@ -4578,6 +5098,7 @@ function geom_violin(options = {}) {
4578
5098
  }
4579
5099
  };
4580
5100
  }
5101
+
4581
5102
  // src/geoms/tile.ts
4582
5103
  function geom_tile(options = {}) {
4583
5104
  return {
@@ -4596,6 +5117,22 @@ function geom_tile(options = {}) {
4596
5117
  function geom_raster(options = {}) {
4597
5118
  return geom_tile(options);
4598
5119
  }
5120
+
5121
+ // src/geoms/bin2d.ts
5122
+ function geom_bin2d(options = {}) {
5123
+ return {
5124
+ type: "bin2d",
5125
+ stat: "bin2d",
5126
+ params: {
5127
+ bins: options.bins ?? 30,
5128
+ binsx: options.binsx,
5129
+ binsy: options.binsy,
5130
+ alpha: options.alpha ?? 1,
5131
+ drop: options.drop ?? true
5132
+ }
5133
+ };
5134
+ }
5135
+
4599
5136
  // src/geoms/contour.ts
4600
5137
  function geom_contour(options = {}) {
4601
5138
  return {
@@ -4638,6 +5175,7 @@ function geom_density_2d(options = {}) {
4638
5175
  }
4639
5176
  };
4640
5177
  }
5178
+
4641
5179
  // src/geoms/errorbar.ts
4642
5180
  function geom_errorbar(options = {}) {
4643
5181
  return {
@@ -4704,6 +5242,7 @@ function geom_pointrange(options = {}) {
4704
5242
  }
4705
5243
  };
4706
5244
  }
5245
+
4707
5246
  // src/geoms/rect.ts
4708
5247
  function geom_rect(options = {}) {
4709
5248
  return {
@@ -4732,6 +5271,7 @@ function geom_abline(options = {}) {
4732
5271
  }
4733
5272
  };
4734
5273
  }
5274
+
4735
5275
  // src/geoms/qq.ts
4736
5276
  function geom_qq(options = {}) {
4737
5277
  return {
@@ -4760,6 +5300,10 @@ function geom_qq_line(options = {}) {
4760
5300
  }
4761
5301
  };
4762
5302
  }
5303
+
5304
+ // src/geoms/index.ts
5305
+ var init_geoms = () => {};
5306
+
4763
5307
  // src/scales/continuous.ts
4764
5308
  function createContinuousScale(aesthetic, options = {}) {
4765
5309
  const trans = options.trans ?? "identity";
@@ -4838,6 +5382,7 @@ function scale_y2_sqrt(options = {}) {
4838
5382
  function scale_y2_reverse(options = {}) {
4839
5383
  return createContinuousScale("y2", { ...options, trans: "reverse" });
4840
5384
  }
5385
+
4841
5386
  // src/scales/discrete.ts
4842
5387
  function createDiscreteScale(aesthetic, options = {}) {
4843
5388
  const valueToPosition = new Map;
@@ -4887,123 +5432,8 @@ function scale_x_discrete(options = {}) {
4887
5432
  function scale_y_discrete(options = {}) {
4888
5433
  return createDiscreteScale("y", options);
4889
5434
  }
5435
+
4890
5436
  // src/scales/color.ts
4891
- var PALETTES = {
4892
- viridis: ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"],
4893
- plasma: ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"],
4894
- inferno: ["#000004", "#420a68", "#932667", "#dd513a", "#fca50a", "#fcffa4"],
4895
- magma: ["#000004", "#3b0f70", "#8c2981", "#de4968", "#fe9f6d", "#fcfdbf"],
4896
- cividis: ["#002051", "#1d3f6e", "#52596a", "#7b7b78", "#a89f68", "#d9c84a", "#fdea45"],
4897
- turbo: ["#30123b", "#4662d7", "#35aaf8", "#1ae4b6", "#72fe5e", "#c8ef34", "#faba39", "#f66b19", "#ca2a04"],
4898
- Blues: ["#f7fbff", "#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c", "#08306b"],
4899
- Greens: ["#f7fcf5", "#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c", "#00441b"],
4900
- Greys: ["#ffffff", "#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525", "#000000"],
4901
- Oranges: ["#fff5eb", "#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603", "#7f2704"],
4902
- Purples: ["#fcfbfd", "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"],
4903
- Reds: ["#fff5f0", "#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15", "#67000d"],
4904
- BuGn: ["#f7fcfd", "#e5f5f9", "#ccece6", "#99d8c9", "#66c2a4", "#41ae76", "#238b45", "#006d2c", "#00441b"],
4905
- BuPu: ["#f7fcfd", "#e0ecf4", "#bfd3e6", "#9ebcda", "#8c96c6", "#8c6bb1", "#88419d", "#810f7c", "#4d004b"],
4906
- GnBu: ["#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081"],
4907
- OrRd: ["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"],
4908
- PuBu: ["#fff7fb", "#ece7f2", "#d0d1e6", "#a6bddb", "#74a9cf", "#3690c0", "#0570b0", "#045a8d", "#023858"],
4909
- PuBuGn: ["#fff7fb", "#ece2f0", "#d0d1e6", "#a6bddb", "#67a9cf", "#3690c0", "#02818a", "#016c59", "#014636"],
4910
- PuRd: ["#f7f4f9", "#e7e1ef", "#d4b9da", "#c994c7", "#df65b0", "#e7298a", "#ce1256", "#980043", "#67001f"],
4911
- RdPu: ["#fff7f3", "#fde0dd", "#fcc5c0", "#fa9fb5", "#f768a1", "#dd3497", "#ae017e", "#7a0177", "#49006a"],
4912
- YlGn: ["#ffffe5", "#f7fcb9", "#d9f0a3", "#addd8e", "#78c679", "#41ab5d", "#238b45", "#006837", "#004529"],
4913
- YlGnBu: ["#ffffd9", "#edf8b1", "#c7e9b4", "#7fcdbb", "#41b6c4", "#1d91c0", "#225ea8", "#253494", "#081d58"],
4914
- YlOrBr: ["#ffffe5", "#fff7bc", "#fee391", "#fec44f", "#fe9929", "#ec7014", "#cc4c02", "#993404", "#662506"],
4915
- YlOrRd: ["#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026"],
4916
- BrBG: ["#543005", "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", "#003c30"],
4917
- PiYG: ["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"],
4918
- PRGn: ["#40004b", "#762a83", "#9970ab", "#c2a5cf", "#e7d4e8", "#f7f7f7", "#d9f0d3", "#a6dba0", "#5aae61", "#1b7837", "#00441b"],
4919
- PuOr: ["#7f3b08", "#b35806", "#e08214", "#fdb863", "#fee0b6", "#f7f7f7", "#d8daeb", "#b2abd2", "#8073ac", "#542788", "#2d004b"],
4920
- RdBu: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", "#053061"],
4921
- RdGy: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#ffffff", "#e0e0e0", "#bababa", "#878787", "#4d4d4d", "#1a1a1a"],
4922
- RdYlBu: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"],
4923
- RdYlGn: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#d9ef8b", "#a6d96a", "#66bd63", "#1a9850", "#006837"],
4924
- Spectral: ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"],
4925
- category10: [
4926
- "#1f77b4",
4927
- "#ff7f0e",
4928
- "#2ca02c",
4929
- "#d62728",
4930
- "#9467bd",
4931
- "#8c564b",
4932
- "#e377c2",
4933
- "#7f7f7f",
4934
- "#bcbd22",
4935
- "#17becf"
4936
- ],
4937
- category20: [
4938
- "#1f77b4",
4939
- "#aec7e8",
4940
- "#ff7f0e",
4941
- "#ffbb78",
4942
- "#2ca02c",
4943
- "#98df8a",
4944
- "#d62728",
4945
- "#ff9896",
4946
- "#9467bd",
4947
- "#c5b0d5",
4948
- "#8c564b",
4949
- "#c49c94",
4950
- "#e377c2",
4951
- "#f7b6d2",
4952
- "#7f7f7f",
4953
- "#c7c7c7",
4954
- "#bcbd22",
4955
- "#dbdb8d",
4956
- "#17becf",
4957
- "#9edae5"
4958
- ],
4959
- Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"],
4960
- Dark2: ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"],
4961
- Paired: ["#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928"],
4962
- Pastel1: ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"],
4963
- Pastel2: ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"],
4964
- Set1: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"],
4965
- Set2: ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"],
4966
- Set3: ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"],
4967
- Tab10: [
4968
- "#4e79a7",
4969
- "#f28e2c",
4970
- "#e15759",
4971
- "#76b7b2",
4972
- "#59a14f",
4973
- "#edc949",
4974
- "#af7aa1",
4975
- "#ff9da7",
4976
- "#9c755f",
4977
- "#bab0ab"
4978
- ],
4979
- Tab20: [
4980
- "#4e79a7",
4981
- "#a0cbe8",
4982
- "#f28e2c",
4983
- "#ffbe7d",
4984
- "#59a14f",
4985
- "#8cd17d",
4986
- "#b6992d",
4987
- "#f1ce63",
4988
- "#499894",
4989
- "#86bcb6",
4990
- "#e15759",
4991
- "#ff9d9a",
4992
- "#79706e",
4993
- "#bab0ac",
4994
- "#d37295",
4995
- "#fabfd2",
4996
- "#b07aa1",
4997
- "#d4a6c8",
4998
- "#9d7660",
4999
- "#d7b5a6"
5000
- ],
5001
- thermal: ["#042333", "#2c3e50", "#0b5345", "#1e8449", "#f39c12", "#e74c3c", "#fadbd8"],
5002
- haline: ["#2c3e50", "#1a5276", "#2980b9", "#5dade2", "#aed6f1", "#d5f5e3"],
5003
- terrain: ["#333399", "#0099ff", "#00cc00", "#ffff00", "#ff9900", "#cc6600", "#996633", "#ffffff"],
5004
- rainbow: ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", "#00ffff", "#0080ff", "#0000ff", "#8000ff"],
5005
- cubehelix: ["#000000", "#1a1530", "#30304d", "#4d5366", "#6d826e", "#8ab17d", "#add38a", "#dae8a2", "#ffffff"]
5006
- };
5007
5437
  function hexToRgba(hex) {
5008
5438
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
5009
5439
  if (!result)
@@ -5224,6 +5654,126 @@ function getAvailablePalettes() {
5224
5654
  function getPaletteColors(name) {
5225
5655
  return PALETTES[name];
5226
5656
  }
5657
+ var PALETTES;
5658
+ var init_color = __esm(() => {
5659
+ PALETTES = {
5660
+ viridis: ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"],
5661
+ plasma: ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"],
5662
+ inferno: ["#000004", "#420a68", "#932667", "#dd513a", "#fca50a", "#fcffa4"],
5663
+ magma: ["#000004", "#3b0f70", "#8c2981", "#de4968", "#fe9f6d", "#fcfdbf"],
5664
+ cividis: ["#002051", "#1d3f6e", "#52596a", "#7b7b78", "#a89f68", "#d9c84a", "#fdea45"],
5665
+ turbo: ["#30123b", "#4662d7", "#35aaf8", "#1ae4b6", "#72fe5e", "#c8ef34", "#faba39", "#f66b19", "#ca2a04"],
5666
+ Blues: ["#f7fbff", "#deebf7", "#c6dbef", "#9ecae1", "#6baed6", "#4292c6", "#2171b5", "#08519c", "#08306b"],
5667
+ Greens: ["#f7fcf5", "#e5f5e0", "#c7e9c0", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#006d2c", "#00441b"],
5668
+ Greys: ["#ffffff", "#f0f0f0", "#d9d9d9", "#bdbdbd", "#969696", "#737373", "#525252", "#252525", "#000000"],
5669
+ Oranges: ["#fff5eb", "#fee6ce", "#fdd0a2", "#fdae6b", "#fd8d3c", "#f16913", "#d94801", "#a63603", "#7f2704"],
5670
+ Purples: ["#fcfbfd", "#efedf5", "#dadaeb", "#bcbddc", "#9e9ac8", "#807dba", "#6a51a3", "#54278f", "#3f007d"],
5671
+ Reds: ["#fff5f0", "#fee0d2", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#a50f15", "#67000d"],
5672
+ BuGn: ["#f7fcfd", "#e5f5f9", "#ccece6", "#99d8c9", "#66c2a4", "#41ae76", "#238b45", "#006d2c", "#00441b"],
5673
+ BuPu: ["#f7fcfd", "#e0ecf4", "#bfd3e6", "#9ebcda", "#8c96c6", "#8c6bb1", "#88419d", "#810f7c", "#4d004b"],
5674
+ GnBu: ["#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081"],
5675
+ OrRd: ["#fff7ec", "#fee8c8", "#fdd49e", "#fdbb84", "#fc8d59", "#ef6548", "#d7301f", "#b30000", "#7f0000"],
5676
+ PuBu: ["#fff7fb", "#ece7f2", "#d0d1e6", "#a6bddb", "#74a9cf", "#3690c0", "#0570b0", "#045a8d", "#023858"],
5677
+ PuBuGn: ["#fff7fb", "#ece2f0", "#d0d1e6", "#a6bddb", "#67a9cf", "#3690c0", "#02818a", "#016c59", "#014636"],
5678
+ PuRd: ["#f7f4f9", "#e7e1ef", "#d4b9da", "#c994c7", "#df65b0", "#e7298a", "#ce1256", "#980043", "#67001f"],
5679
+ RdPu: ["#fff7f3", "#fde0dd", "#fcc5c0", "#fa9fb5", "#f768a1", "#dd3497", "#ae017e", "#7a0177", "#49006a"],
5680
+ YlGn: ["#ffffe5", "#f7fcb9", "#d9f0a3", "#addd8e", "#78c679", "#41ab5d", "#238b45", "#006837", "#004529"],
5681
+ YlGnBu: ["#ffffd9", "#edf8b1", "#c7e9b4", "#7fcdbb", "#41b6c4", "#1d91c0", "#225ea8", "#253494", "#081d58"],
5682
+ YlOrBr: ["#ffffe5", "#fff7bc", "#fee391", "#fec44f", "#fe9929", "#ec7014", "#cc4c02", "#993404", "#662506"],
5683
+ YlOrRd: ["#ffffcc", "#ffeda0", "#fed976", "#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026"],
5684
+ BrBG: ["#543005", "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", "#003c30"],
5685
+ PiYG: ["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"],
5686
+ PRGn: ["#40004b", "#762a83", "#9970ab", "#c2a5cf", "#e7d4e8", "#f7f7f7", "#d9f0d3", "#a6dba0", "#5aae61", "#1b7837", "#00441b"],
5687
+ PuOr: ["#7f3b08", "#b35806", "#e08214", "#fdb863", "#fee0b6", "#f7f7f7", "#d8daeb", "#b2abd2", "#8073ac", "#542788", "#2d004b"],
5688
+ RdBu: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", "#053061"],
5689
+ RdGy: ["#67001f", "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#ffffff", "#e0e0e0", "#bababa", "#878787", "#4d4d4d", "#1a1a1a"],
5690
+ RdYlBu: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", "#313695"],
5691
+ RdYlGn: ["#a50026", "#d73027", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#d9ef8b", "#a6d96a", "#66bd63", "#1a9850", "#006837"],
5692
+ Spectral: ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b", "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"],
5693
+ category10: [
5694
+ "#1f77b4",
5695
+ "#ff7f0e",
5696
+ "#2ca02c",
5697
+ "#d62728",
5698
+ "#9467bd",
5699
+ "#8c564b",
5700
+ "#e377c2",
5701
+ "#7f7f7f",
5702
+ "#bcbd22",
5703
+ "#17becf"
5704
+ ],
5705
+ category20: [
5706
+ "#1f77b4",
5707
+ "#aec7e8",
5708
+ "#ff7f0e",
5709
+ "#ffbb78",
5710
+ "#2ca02c",
5711
+ "#98df8a",
5712
+ "#d62728",
5713
+ "#ff9896",
5714
+ "#9467bd",
5715
+ "#c5b0d5",
5716
+ "#8c564b",
5717
+ "#c49c94",
5718
+ "#e377c2",
5719
+ "#f7b6d2",
5720
+ "#7f7f7f",
5721
+ "#c7c7c7",
5722
+ "#bcbd22",
5723
+ "#dbdb8d",
5724
+ "#17becf",
5725
+ "#9edae5"
5726
+ ],
5727
+ Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"],
5728
+ Dark2: ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"],
5729
+ Paired: ["#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31a1c", "#fdbf6f", "#ff7f00", "#cab2d6", "#6a3d9a", "#ffff99", "#b15928"],
5730
+ Pastel1: ["#fbb4ae", "#b3cde3", "#ccebc5", "#decbe4", "#fed9a6", "#ffffcc", "#e5d8bd", "#fddaec", "#f2f2f2"],
5731
+ Pastel2: ["#b3e2cd", "#fdcdac", "#cbd5e8", "#f4cae4", "#e6f5c9", "#fff2ae", "#f1e2cc", "#cccccc"],
5732
+ Set1: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"],
5733
+ Set2: ["#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", "#ffd92f", "#e5c494", "#b3b3b3"],
5734
+ Set3: ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"],
5735
+ Tab10: [
5736
+ "#4e79a7",
5737
+ "#f28e2c",
5738
+ "#e15759",
5739
+ "#76b7b2",
5740
+ "#59a14f",
5741
+ "#edc949",
5742
+ "#af7aa1",
5743
+ "#ff9da7",
5744
+ "#9c755f",
5745
+ "#bab0ab"
5746
+ ],
5747
+ Tab20: [
5748
+ "#4e79a7",
5749
+ "#a0cbe8",
5750
+ "#f28e2c",
5751
+ "#ffbe7d",
5752
+ "#59a14f",
5753
+ "#8cd17d",
5754
+ "#b6992d",
5755
+ "#f1ce63",
5756
+ "#499894",
5757
+ "#86bcb6",
5758
+ "#e15759",
5759
+ "#ff9d9a",
5760
+ "#79706e",
5761
+ "#bab0ac",
5762
+ "#d37295",
5763
+ "#fabfd2",
5764
+ "#b07aa1",
5765
+ "#d4a6c8",
5766
+ "#9d7660",
5767
+ "#d7b5a6"
5768
+ ],
5769
+ thermal: ["#042333", "#2c3e50", "#0b5345", "#1e8449", "#f39c12", "#e74c3c", "#fadbd8"],
5770
+ haline: ["#2c3e50", "#1a5276", "#2980b9", "#5dade2", "#aed6f1", "#d5f5e3"],
5771
+ terrain: ["#333399", "#0099ff", "#00cc00", "#ffff00", "#ff9900", "#cc6600", "#996633", "#ffffff"],
5772
+ rainbow: ["#ff0000", "#ff8000", "#ffff00", "#80ff00", "#00ff00", "#00ff80", "#00ffff", "#0080ff", "#0000ff", "#8000ff"],
5773
+ cubehelix: ["#000000", "#1a1530", "#30304d", "#4d5366", "#6d826e", "#8ab17d", "#add38a", "#dae8a2", "#ffffff"]
5774
+ };
5775
+ });
5776
+
5227
5777
  // src/scales/size.ts
5228
5778
  function scale_size_continuous(options = {}) {
5229
5779
  const range = options.range ?? [1, 6];
@@ -5292,45 +5842,8 @@ function scale_size_binned(options = {}) {
5292
5842
  }
5293
5843
  };
5294
5844
  }
5845
+
5295
5846
  // src/scales/shape.ts
5296
- var DEFAULT_SHAPES = [
5297
- "circle",
5298
- "square",
5299
- "triangle",
5300
- "diamond",
5301
- "cross",
5302
- "plus",
5303
- "star",
5304
- "open_circle",
5305
- "open_square",
5306
- "open_triangle",
5307
- "open_diamond",
5308
- "dot"
5309
- ];
5310
- var SHAPE_CHARS = {
5311
- circle: "●",
5312
- filled_circle: "●",
5313
- open_circle: "○",
5314
- square: "■",
5315
- filled_square: "■",
5316
- open_square: "□",
5317
- triangle: "▲",
5318
- filled_triangle: "▲",
5319
- open_triangle: "△",
5320
- triangle_down: "▼",
5321
- diamond: "◆",
5322
- filled_diamond: "◆",
5323
- open_diamond: "◇",
5324
- cross: "✕",
5325
- plus: "+",
5326
- star: "★",
5327
- open_star: "☆",
5328
- dot: "•",
5329
- bullet: "•",
5330
- asterisk: "*",
5331
- hash: "#",
5332
- at: "@"
5333
- };
5334
5847
  function scale_shape_discrete(options = {}) {
5335
5848
  const shapes = options.values ?? DEFAULT_SHAPES;
5336
5849
  return {
@@ -5389,6 +5902,48 @@ function scale_shape_ordinal(options = {}) {
5389
5902
  }
5390
5903
  };
5391
5904
  }
5905
+ var DEFAULT_SHAPES, SHAPE_CHARS;
5906
+ var init_shape = __esm(() => {
5907
+ DEFAULT_SHAPES = [
5908
+ "circle",
5909
+ "square",
5910
+ "triangle",
5911
+ "diamond",
5912
+ "cross",
5913
+ "plus",
5914
+ "star",
5915
+ "open_circle",
5916
+ "open_square",
5917
+ "open_triangle",
5918
+ "open_diamond",
5919
+ "dot"
5920
+ ];
5921
+ SHAPE_CHARS = {
5922
+ circle: "●",
5923
+ filled_circle: "●",
5924
+ open_circle: "○",
5925
+ square: "■",
5926
+ filled_square: "■",
5927
+ open_square: "□",
5928
+ triangle: "▲",
5929
+ filled_triangle: "▲",
5930
+ open_triangle: "△",
5931
+ triangle_down: "▼",
5932
+ diamond: "◆",
5933
+ filled_diamond: "◆",
5934
+ open_diamond: "◇",
5935
+ cross: "✕",
5936
+ plus: "+",
5937
+ star: "★",
5938
+ open_star: "☆",
5939
+ dot: "•",
5940
+ bullet: "•",
5941
+ asterisk: "*",
5942
+ hash: "#",
5943
+ at: "@"
5944
+ };
5945
+ });
5946
+
5392
5947
  // src/scales/alpha.ts
5393
5948
  function scale_alpha_continuous(options = {}) {
5394
5949
  const range = options.range ?? [0.1, 1];
@@ -5485,17 +6040,8 @@ function scale_alpha_binned(options = {}) {
5485
6040
  }
5486
6041
  };
5487
6042
  }
6043
+
5488
6044
  // src/scales/datetime.ts
5489
- var TIME_INTERVALS = [
5490
- { name: "millisecond", ms: 1 },
5491
- { name: "second", ms: 1000 },
5492
- { name: "minute", ms: 60 * 1000 },
5493
- { name: "hour", ms: 60 * 60 * 1000 },
5494
- { name: "day", ms: 24 * 60 * 60 * 1000 },
5495
- { name: "week", ms: 7 * 24 * 60 * 60 * 1000 },
5496
- { name: "month", ms: 30 * 24 * 60 * 60 * 1000 },
5497
- { name: "year", ms: 365 * 24 * 60 * 60 * 1000 }
5498
- ];
5499
6045
  function parseDateTime(value) {
5500
6046
  if (value === null || value === undefined)
5501
6047
  return null;
@@ -5677,7 +6223,30 @@ function scale_y_duration(options = {}) {
5677
6223
  scale.aesthetic = "y";
5678
6224
  return scale;
5679
6225
  }
6226
+ var TIME_INTERVALS;
6227
+ var init_datetime = __esm(() => {
6228
+ TIME_INTERVALS = [
6229
+ { name: "millisecond", ms: 1 },
6230
+ { name: "second", ms: 1000 },
6231
+ { name: "minute", ms: 60 * 1000 },
6232
+ { name: "hour", ms: 60 * 60 * 1000 },
6233
+ { name: "day", ms: 24 * 60 * 60 * 1000 },
6234
+ { name: "week", ms: 7 * 24 * 60 * 60 * 1000 },
6235
+ { name: "month", ms: 30 * 24 * 60 * 60 * 1000 },
6236
+ { name: "year", ms: 365 * 24 * 60 * 60 * 1000 }
6237
+ ];
6238
+ });
6239
+
6240
+ // src/scales/index.ts
6241
+ var init_scales2 = __esm(() => {
6242
+ init_color();
6243
+ init_shape();
6244
+ init_datetime();
6245
+ });
6246
+
5680
6247
  // src/repl/repl.ts
6248
+ import * as readline from "readline";
6249
+
5681
6250
  class GGTermREPL {
5682
6251
  rl = null;
5683
6252
  state;
@@ -6312,7 +6881,19 @@ function startREPL(options) {
6312
6881
  repl.start();
6313
6882
  return repl;
6314
6883
  }
6884
+ var init_repl = __esm(() => {
6885
+ init_grammar();
6886
+ init_geoms();
6887
+ init_scales2();
6888
+ });
6889
+
6890
+ // src/repl/index.ts
6891
+ var init_repl2 = __esm(() => {
6892
+ init_repl();
6893
+ });
6894
+
6315
6895
  // src/cli.ts
6896
+ init_repl2();
6316
6897
  import * as fs from "fs";
6317
6898
  import * as path from "path";
6318
6899
  var VERSION = "0.0.1";