@svgrid/grid 3.0.1 → 3.0.2
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/GridFooter.svelte +14 -5
- package/dist/GridFooter.svelte.d.ts +8 -0
- package/dist/GridMenus.svelte +18 -10
- package/dist/GridMenus.svelte.d.ts +2 -1
- package/dist/SvGrid.controller.svelte.d.ts +17 -0
- package/dist/SvGrid.controller.svelte.js +128 -14
- package/dist/SvGrid.css +79 -10
- package/dist/SvGrid.svelte +191 -186
- package/dist/SvGrid.types.d.ts +42 -1
- package/dist/SvGridChart.svelte +571 -41
- package/dist/SvGridChart.svelte.d.ts +63 -1
- package/dist/SvGridChartPanel.svelte +169 -21
- package/dist/SvGridChartView.svelte +9 -0
- package/dist/SvGridChartView.svelte.d.ts +7 -0
- package/dist/SvGroupCell.svelte +28 -3
- package/dist/SvGroupCell.svelte.d.ts +8 -0
- package/dist/SvRowGroupPanel.svelte +20 -4
- package/dist/SvRowGroupPanel.svelte.d.ts +8 -0
- package/dist/ai.d.ts +11 -2
- package/dist/ai.js +51 -7
- package/dist/cdn/GridMenus-DyFA-QxA.js +602 -0
- package/dist/cdn/{GridMenus-DFB6iwF8.js → GridMenus-M2XP9t0_.js} +152 -150
- package/dist/cdn/SvGridChart-DAb9RbRs.js +1480 -0
- package/dist/cdn/SvGridChart-Yl-IXZFO.js +1481 -0
- package/dist/cdn/SvGridChartPanel-DayQpDsR.js +834 -0
- package/dist/cdn/SvGridChartPanel-aqf8n-vJ.js +810 -0
- package/dist/cdn/{SvGridChartView-BhUEJ5ki.js → SvGridChartView-CxfakxR0.js} +5 -3
- package/dist/cdn/{SvGridChartView-00LPUHL1.js → SvGridChartView-Dm_YEx9L.js} +5 -3
- package/dist/cdn/cell-formatting-C2Hf5gqd.js +86 -0
- package/dist/cdn/chart-CKJRCPOk.js +1652 -0
- package/dist/cdn/{export-format-Cv1Dll6k.js → export-format-CUDLy2yn.js} +84 -168
- package/dist/cdn/{src-C8QjSaq-.js → src-BJ2opd0j.js} +3608 -3414
- package/dist/cdn/{src-D0hO2eYN.js → src-DNbz94Ct.js} +8617 -8423
- package/dist/cdn/svgrid.js +16 -15
- package/dist/cdn/svgrid.svelte-external.js +16 -15
- package/dist/cell-formatting.d.ts +7 -0
- package/dist/cell-formatting.js +7 -1
- package/dist/chart-export.d.ts +23 -2
- package/dist/chart-export.js +80 -6
- package/dist/chart.d.ts +410 -18
- package/dist/chart.js +824 -24
- package/dist/grid-icons.d.ts +49 -0
- package/dist/grid-icons.js +86 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/package.json +11 -11
- package/src/GridFooter.svelte +14 -5
- package/src/GridMenus.svelte +18 -10
- package/src/SvGrid.controller.svelte.ts +146 -13
- package/src/SvGrid.css +79 -10
- package/src/SvGrid.svelte +191 -186
- package/src/SvGrid.types.ts +42 -1
- package/src/SvGridChart.svelte +571 -41
- package/src/SvGridChart.test.ts +243 -1
- package/src/SvGridChartPanel.svelte +169 -21
- package/src/SvGridChartView.svelte +9 -0
- package/src/SvGroupCell.svelte +28 -3
- package/src/SvRowGroupPanel.svelte +20 -4
- package/src/ai.test.ts +60 -1
- package/src/ai.ts +59 -6
- package/src/cell-formatting.ts +7 -1
- package/src/chart-export.test.ts +112 -0
- package/src/chart-export.ts +76 -8
- package/src/chart.test.ts +830 -1
- package/src/chart.ts +1053 -32
- package/src/grid-icons.test.ts +46 -0
- package/src/grid-icons.ts +184 -0
- package/src/icon-overrides.grid.test.ts +188 -0
- package/src/icon-seam.test.ts +100 -0
- package/src/index.ts +19 -0
- package/src/svgrid.charting.test.ts +120 -0
- package/dist/cdn/GridMenus-CYzOvmNQ.js +0 -600
- package/dist/cdn/SvGridChart-BEJmNNx9.js +0 -1203
- package/dist/cdn/SvGridChart-BwVos976.js +0 -1202
- package/dist/cdn/SvGridChartPanel-BOknOkrP.js +0 -561
- package/dist/cdn/SvGridChartPanel-D2PjII4O.js +0 -585
- package/dist/cdn/chart-i4XcXyHJ.js +0 -1214
package/dist/ai.js
CHANGED
|
@@ -511,7 +511,7 @@ export async function aiChart(api, query, opts = {}) {
|
|
|
511
511
|
`into a strict-JSON chart plan the grid can render.\n\n` +
|
|
512
512
|
`Columns:\n${schemaToPromptBlock(schema)}\n\n` +
|
|
513
513
|
`Output JSON schema:\n` +
|
|
514
|
-
`{ "type": "bar"|"line"|"area"|"pie", ` +
|
|
514
|
+
`{ "type": "bar"|"line"|"area"|"pie"|"treemap"|"funnel"|"waterfall"|"radar"|"heatmap"|"boxplot"|"gauge"|"calendar"|"sankey", ` +
|
|
515
515
|
`"dimension": "<a categorical column to group by>", ` +
|
|
516
516
|
`"series": "<a second categorical column to split into series, or null>", ` +
|
|
517
517
|
`"measure": "<a numeric column to aggregate>", ` +
|
|
@@ -523,6 +523,16 @@ export async function aiChart(api, query, opts = {}) {
|
|
|
523
523
|
`"rationale": "<one-sentence explanation>" }\n\n` +
|
|
524
524
|
`Rules: pick "dimension" and "series" from text/date columns and "measure" ` +
|
|
525
525
|
`from a numeric column; use only column names from the list above; ` +
|
|
526
|
+
`default to "bar" unless the request clearly wants another type. ` +
|
|
527
|
+
`Type hints: share/proportion/breakdown -> pie; nested/hierarchy/"what makes ` +
|
|
528
|
+
`up" -> treemap; drop-off/conversion/stages/pipeline -> funnel; ` +
|
|
529
|
+
`running total/contribution/bridge -> waterfall; comparing several measures ` +
|
|
530
|
+
`per item -> radar; a grid of two dimensions -> heatmap (needs "series"); ` +
|
|
531
|
+
`spread/distribution/variance/outliers/percentiles -> boxplot; a single ` +
|
|
532
|
+
`number vs a target -> gauge (leave "dimension" null); a year of daily ` +
|
|
533
|
+
`activity -> calendar (dimension must be a date column); flow between two ` +
|
|
534
|
+
`things -> sankey (needs "series": dimension is the source, series the ` +
|
|
535
|
+
`target). ` +
|
|
526
536
|
`"stacked"/"stack" -> stacked:true; "log"/"logarithmic" -> logScale:true; ` +
|
|
527
537
|
`"over time"/"by date"/a date dimension -> timeAxis:true; ` +
|
|
528
538
|
`money/revenue/price/$ -> valueFormat:"currency"; rate/%/share -> valueFormat:"percent"; ` +
|
|
@@ -537,7 +547,11 @@ export async function aiChart(api, query, opts = {}) {
|
|
|
537
547
|
});
|
|
538
548
|
const valid = new Set(schema.map((c) => c.field));
|
|
539
549
|
const numericFields = new Set(schema.filter((c) => c.type === 'number').map((c) => c.field));
|
|
540
|
-
const CHART_TYPES = [
|
|
550
|
+
const CHART_TYPES = [
|
|
551
|
+
'bar', 'line', 'area', 'pie',
|
|
552
|
+
'treemap', 'funnel', 'waterfall', 'radar',
|
|
553
|
+
'heatmap', 'boxplot', 'gauge', 'calendar', 'sankey',
|
|
554
|
+
];
|
|
541
555
|
plan.type = CHART_TYPES.includes(plan.type) ? plan.type : 'bar';
|
|
542
556
|
plan.dimension = plan.dimension && valid.has(plan.dimension) ? plan.dimension : null;
|
|
543
557
|
plan.series = plan.series && valid.has(plan.series) && plan.series !== plan.dimension ? plan.series : null;
|
|
@@ -545,6 +559,21 @@ export async function aiChart(api, query, opts = {}) {
|
|
|
545
559
|
plan.measure && numericFields.has(plan.measure)
|
|
546
560
|
? plan.measure
|
|
547
561
|
: (schema.find((c) => c.type === 'number')?.field ?? null);
|
|
562
|
+
// Shape check. Some types need more than a dimension and a measure, and a
|
|
563
|
+
// plan that does not satisfy one renders an empty frame - the model asked for
|
|
564
|
+
// a chart the data cannot make. Fall back to a bar, which any dimension and
|
|
565
|
+
// measure can draw, rather than showing nothing and blaming the request.
|
|
566
|
+
const dateFields = new Set(schema.filter((c) => c.type === 'date').map((c) => c.field));
|
|
567
|
+
const needsSplit = plan.type === 'heatmap' || plan.type === 'sankey';
|
|
568
|
+
if (needsSplit && !plan.series)
|
|
569
|
+
plan.type = 'bar';
|
|
570
|
+
if (plan.type === 'calendar' && !(plan.dimension && dateFields.has(plan.dimension)))
|
|
571
|
+
plan.type = 'bar';
|
|
572
|
+
// A gauge is one number: it has no category axis, so a dimension is noise.
|
|
573
|
+
if (plan.type === 'gauge')
|
|
574
|
+
plan.dimension = null;
|
|
575
|
+
if (plan.type !== 'gauge' && !plan.dimension)
|
|
576
|
+
plan.type = 'bar';
|
|
548
577
|
plan.reduce = ['sum', 'avg', 'count'].includes(plan.reduce) ? plan.reduce : 'sum';
|
|
549
578
|
plan.stacked = plan.stacked === true;
|
|
550
579
|
plan.logScale = plan.logScale === true;
|
|
@@ -640,10 +669,22 @@ function buildMockChart(prompt) {
|
|
|
640
669
|
const typed = extractFieldTypes(prompt);
|
|
641
670
|
const textFields = typed.filter((f) => f.type === 'string' || f.type === 'date').map((f) => f.name);
|
|
642
671
|
const numberFields = typed.filter((f) => f.type === 'number').map((f) => f.name);
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
672
|
+
// Mirrors the type hints in the real prompt, so the bundled offline provider
|
|
673
|
+
// can reach the same charts a model can. Ordered most-specific first: "share
|
|
674
|
+
// of the pipeline" is a funnel request, not a pie one.
|
|
675
|
+
const type = /\bfunnel\b|drop.?off|conversion|\bstages?\b|pipeline/.test(q) ? 'funnel'
|
|
676
|
+
: /\bwaterfall\b|running total|contribution|\bbridge\b/.test(q) ? 'waterfall'
|
|
677
|
+
: /\btree ?map\b|nested|hierarch/.test(q) ? 'treemap'
|
|
678
|
+
: /\bradar\b|spider|multi.?measure/.test(q) ? 'radar'
|
|
679
|
+
: /\bheat ?map\b/.test(q) ? 'heatmap'
|
|
680
|
+
: /\bbox ?plot\b|spread|distribution|variance|outlier|percentile|quartile/.test(q) ? 'boxplot'
|
|
681
|
+
: /\bgauge\b|\bdial\b|vs target|against target/.test(q) ? 'gauge'
|
|
682
|
+
: /\bcalendar\b|daily activity|year of/.test(q) ? 'calendar'
|
|
683
|
+
: /\bsankey\b|\bflow\b/.test(q) ? 'sankey'
|
|
684
|
+
: /\bline\b|\btrend\b|over time/.test(q) ? 'line'
|
|
685
|
+
: /\barea\b/.test(q) ? 'area'
|
|
686
|
+
: /\bpie\b|share|proportion|breakdown/.test(q) ? 'pie'
|
|
687
|
+
: 'bar';
|
|
647
688
|
const byMatch = q.match(/\bby\s+([a-z0-9_ ]+?)(?:\s+(?:split|stacked|grouped|by|as|,|$))/);
|
|
648
689
|
const pickText = (hint) => {
|
|
649
690
|
if (hint) {
|
|
@@ -654,7 +695,10 @@ function buildMockChart(prompt) {
|
|
|
654
695
|
return null;
|
|
655
696
|
};
|
|
656
697
|
const dimension = pickText(byMatch?.[1]) ?? textFields[0] ?? null;
|
|
657
|
-
|
|
698
|
+
// Heatmap and sankey are two-dimension charts: without a split the shape
|
|
699
|
+
// check downgrades them to a bar, so the mock would answer "heatmap" with a
|
|
700
|
+
// bar chart and look broken rather than offline.
|
|
701
|
+
const series = /\b(split|stack(?:ed)?|by product|by category|per)\b/.test(q) || type === 'heatmap' || type === 'sankey'
|
|
658
702
|
? (textFields.find((t) => t !== dimension) ?? null)
|
|
659
703
|
: null;
|
|
660
704
|
const measure = numberFields.find((n) => q.includes(n.toLowerCase())) ?? numberFields[0] ?? null;
|