@fusedashlabs/widgets 0.4.0 → 0.4.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/CHANGELOG.md +21 -0
- package/README.md +1 -1
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.d.ts +1 -0
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.d.ts.map +1 -1
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.js +18 -4
- package/dist/components/chart-renderer/element/ui9000-chart-renderer.js.map +1 -1
- package/dist/components/chart-renderer/lib/registry.d.ts.map +1 -1
- package/dist/components/chart-renderer/lib/registry.js +3 -1
- package/dist/components/chart-renderer/lib/registry.js.map +1 -1
- package/dist/components/kpi-widget/element/styles.d.ts.map +1 -1
- package/dist/components/kpi-widget/element/styles.js +268 -5
- package/dist/components/kpi-widget/element/styles.js.map +1 -1
- package/dist/components/kpi-widget/element/ui9000-kpi-widget.d.ts +10 -1
- package/dist/components/kpi-widget/element/ui9000-kpi-widget.d.ts.map +1 -1
- package/dist/components/kpi-widget/element/ui9000-kpi-widget.js +154 -27
- package/dist/components/kpi-widget/element/ui9000-kpi-widget.js.map +1 -1
- package/dist/components/kpi-widget/index.d.ts +1 -1
- package/dist/components/kpi-widget/index.d.ts.map +1 -1
- package/dist/components/kpi-widget/index.js +7 -4
- package/dist/components/kpi-widget/lib/extract.d.ts +5 -1
- package/dist/components/kpi-widget/lib/extract.d.ts.map +1 -1
- package/dist/components/kpi-widget/lib/extract.js +110 -34
- package/dist/components/kpi-widget/lib/extract.js.map +1 -1
- package/dist/components/kpi-widget/lib/format.d.ts +5 -0
- package/dist/components/kpi-widget/lib/format.d.ts.map +1 -1
- package/dist/components/kpi-widget/lib/format.js +10 -1
- package/dist/components/kpi-widget/lib/format.js.map +1 -1
- package/dist/components/kpi-widget/lib/grid.d.ts +5 -0
- package/dist/components/kpi-widget/lib/grid.d.ts.map +1 -1
- package/dist/components/kpi-widget/lib/grid.js +18 -0
- package/dist/components/kpi-widget/lib/grid.js.map +1 -1
- package/dist/components/kpi-widget/lib/index.d.ts +5 -5
- package/dist/components/kpi-widget/lib/index.d.ts.map +1 -1
- package/dist/components/kpi-widget/lib/normalize.d.ts +2 -0
- package/dist/components/kpi-widget/lib/normalize.d.ts.map +1 -1
- package/dist/components/kpi-widget/lib/normalize.js +73 -12
- package/dist/components/kpi-widget/lib/normalize.js.map +1 -1
- package/dist/components/kpi-widget/lib/types.d.ts +41 -0
- package/dist/components/kpi-widget/lib/types.d.ts.map +1 -1
- package/dist/components/kpi-widget/metadata.json.d.ts +1 -1
- package/dist/components/kpi-widget/metadata.json.js +1 -1
- package/dist/components/map-chart/element/ui9000-map-chart.d.ts +1 -0
- package/dist/components/map-chart/element/ui9000-map-chart.d.ts.map +1 -1
- package/dist/components/map-chart/element/ui9000-map-chart.js +12 -4
- package/dist/components/map-chart/element/ui9000-map-chart.js.map +1 -1
- package/dist/components/map-chart/lib/geojson.d.ts.map +1 -1
- package/dist/components/map-chart/lib/geojson.js +3 -1
- package/dist/components/map-chart/lib/geojson.js.map +1 -1
- package/dist/components/map-chart/metadata.json.d.ts +1 -1
- package/dist/components/map-chart/metadata.json.js +1 -1
- package/dist/components/map-chart/render/draw.d.ts.map +1 -1
- package/dist/components/map-chart/render/draw.js +2 -1
- package/dist/components/map-chart/render/draw.js.map +1 -1
- package/dist/components/partial-dependence-chart/element/styles.d.ts +2 -0
- package/dist/components/partial-dependence-chart/element/styles.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/element/styles.js +48 -0
- package/dist/components/partial-dependence-chart/element/styles.js.map +1 -0
- package/dist/components/partial-dependence-chart/element/ui9000-partial-dependence-chart.d.ts +30 -0
- package/dist/components/partial-dependence-chart/element/ui9000-partial-dependence-chart.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/element/ui9000-partial-dependence-chart.js +163 -0
- package/dist/components/partial-dependence-chart/element/ui9000-partial-dependence-chart.js.map +1 -0
- package/dist/components/partial-dependence-chart/index.d.ts +5 -0
- package/dist/components/partial-dependence-chart/index.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/index.js +18 -0
- package/dist/components/partial-dependence-chart/index.js.map +1 -0
- package/dist/components/partial-dependence-chart/lib/domain.d.ts +6 -0
- package/dist/components/partial-dependence-chart/lib/domain.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/lib/domain.js +16 -0
- package/dist/components/partial-dependence-chart/lib/domain.js.map +1 -0
- package/dist/components/partial-dependence-chart/lib/index.d.ts +5 -0
- package/dist/components/partial-dependence-chart/lib/index.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/lib/normalize.d.ts +4 -0
- package/dist/components/partial-dependence-chart/lib/normalize.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/lib/normalize.js +167 -0
- package/dist/components/partial-dependence-chart/lib/normalize.js.map +1 -0
- package/dist/components/partial-dependence-chart/lib/series.d.ts +15 -0
- package/dist/components/partial-dependence-chart/lib/series.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/lib/series.js +63 -0
- package/dist/components/partial-dependence-chart/lib/series.js.map +1 -0
- package/dist/components/partial-dependence-chart/lib/types.d.ts +50 -0
- package/dist/components/partial-dependence-chart/lib/types.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/metadata.json.d.ts +80 -0
- package/dist/components/partial-dependence-chart/metadata.json.js +42 -0
- package/dist/components/partial-dependence-chart/metadata.json.js.map +1 -0
- package/dist/components/partial-dependence-chart/render/draw.d.ts +34 -0
- package/dist/components/partial-dependence-chart/render/draw.d.ts.map +1 -0
- package/dist/components/partial-dependence-chart/render/draw.js +95 -0
- package/dist/components/partial-dependence-chart/render/draw.js.map +1 -0
- package/dist/components/partial-dependence-chart/render/index.d.ts +2 -0
- package/dist/components/partial-dependence-chart/render/index.d.ts.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -10
- package/dist/index.js.map +1 -1
- package/dist/lazy/index.d.ts +2 -1
- package/dist/lazy/index.d.ts.map +1 -1
- package/dist/lazy/index.js +8 -0
- package/dist/lazy/index.js.map +1 -1
- package/dist/lazy/partial-dependence-chart.d.ts +4 -0
- package/dist/lazy/partial-dependence-chart.d.ts.map +1 -0
- package/dist/lazy/partial-dependence-chart.js +5 -0
- package/dist/lazy/partial-dependence-chart.js.map +1 -0
- package/dist/utils/chart-helpers.d.ts +2 -0
- package/dist/utils/chart-helpers.d.ts.map +1 -1
- package/dist/utils/chart-helpers.js +15 -0
- package/dist/utils/chart-helpers.js.map +1 -1
- package/dist/utils/fusedash-visual.d.ts +12 -0
- package/dist/utils/fusedash-visual.d.ts.map +1 -1
- package/dist/utils/fusedash-visual.js +7 -0
- package/dist/utils/fusedash-visual.js.map +1 -1
- package/package.json +11 -2
- package/dist/node_modules/lit-html/directive.js +0 -28
- package/dist/node_modules/lit-html/directive.js.map +0 -1
- package/dist/node_modules/lit-html/directives/style-map.js +0 -37
- package/dist/node_modules/lit-html/directives/style-map.js.map +0 -1
- package/dist/node_modules/lit-html/lit-html.js +0 -231
- package/dist/node_modules/lit-html/lit-html.js.map +0 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { resolveFormattingColor } from "../../../utils/fuse-palette.js";
|
|
2
|
+
import { isFuseWidgetPayload, rowsOf, firstField, resolveGroupByKey, resolveUniqueValuesOrder } from "../../../utils/fuse-widget.js";
|
|
3
|
+
import { toNumber, computeAverageSeries } from "./series.js";
|
|
4
|
+
const EMPTY = {
|
|
5
|
+
iceSeries: [],
|
|
6
|
+
averageSeries: [],
|
|
7
|
+
xField: "",
|
|
8
|
+
yField: "",
|
|
9
|
+
color: resolveFormattingColor(void 0, "default", 1)
|
|
10
|
+
};
|
|
11
|
+
const AVERAGE_KEY = /average/i;
|
|
12
|
+
function buildModel(curves, order, fields) {
|
|
13
|
+
for (const [key, points] of curves) {
|
|
14
|
+
if (AVERAGE_KEY.test(key)) {
|
|
15
|
+
curves.delete(key);
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
points.sort((a, b) => a.x - b.x);
|
|
19
|
+
}
|
|
20
|
+
const iceSeries = order.filter((key) => curves.has(key)).map((key) => ({ key, points: curves.get(key) }));
|
|
21
|
+
if (!iceSeries.length) return { ...EMPTY, ...fields };
|
|
22
|
+
return {
|
|
23
|
+
iceSeries,
|
|
24
|
+
averageSeries: computeAverageSeries(iceSeries.map((s) => s.points)),
|
|
25
|
+
...fields
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function fromRows(rows) {
|
|
29
|
+
const curves = /* @__PURE__ */ new Map();
|
|
30
|
+
const order = [];
|
|
31
|
+
for (const row of rows) {
|
|
32
|
+
const x = toNumber(row.x);
|
|
33
|
+
const y = toNumber(row.y);
|
|
34
|
+
if (x == null || y == null) continue;
|
|
35
|
+
const key = row.group != null ? String(row.group) : "default";
|
|
36
|
+
let points = curves.get(key);
|
|
37
|
+
if (!points) {
|
|
38
|
+
points = [];
|
|
39
|
+
curves.set(key, points);
|
|
40
|
+
order.push(key);
|
|
41
|
+
}
|
|
42
|
+
points.push({ x, y });
|
|
43
|
+
}
|
|
44
|
+
return buildModel(curves, order, {
|
|
45
|
+
xField: "x",
|
|
46
|
+
yField: "y",
|
|
47
|
+
groupField: order.length > 1 || order[0] !== "default" ? "group" : void 0,
|
|
48
|
+
color: resolveFormattingColor(void 0, "default", 1)
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function fromIceSeries(series, fields) {
|
|
52
|
+
const curves = /* @__PURE__ */ new Map();
|
|
53
|
+
const order = [];
|
|
54
|
+
series.forEach((entry, index) => {
|
|
55
|
+
const key = String(entry.key ?? index);
|
|
56
|
+
const points = [];
|
|
57
|
+
for (const p of entry.points ?? []) {
|
|
58
|
+
const x = toNumber(p.x);
|
|
59
|
+
const y = toNumber(p.y);
|
|
60
|
+
if (x == null || y == null) continue;
|
|
61
|
+
points.push({ x, y });
|
|
62
|
+
}
|
|
63
|
+
if (!points.length) return;
|
|
64
|
+
curves.set(key, points);
|
|
65
|
+
order.push(key);
|
|
66
|
+
});
|
|
67
|
+
return buildModel(curves, order, {
|
|
68
|
+
xField: fields.xField ?? "x",
|
|
69
|
+
yField: fields.yField ?? "y",
|
|
70
|
+
groupField: fields.groupField,
|
|
71
|
+
color: fields.color ?? resolveFormattingColor(void 0, "default", 1),
|
|
72
|
+
axisDetails: fields.axisDetails
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function fromSeries(series) {
|
|
76
|
+
const curves = /* @__PURE__ */ new Map();
|
|
77
|
+
const order = [];
|
|
78
|
+
series.forEach((entry, index) => {
|
|
79
|
+
const key = String(entry.name ?? entry.id ?? index);
|
|
80
|
+
const points = [];
|
|
81
|
+
for (const p of entry.points ?? []) {
|
|
82
|
+
const x = toNumber(p.x);
|
|
83
|
+
const y = toNumber(p.y);
|
|
84
|
+
if (x == null || y == null) continue;
|
|
85
|
+
points.push({ x, y });
|
|
86
|
+
}
|
|
87
|
+
if (!points.length) return;
|
|
88
|
+
curves.set(key, points);
|
|
89
|
+
order.push(key);
|
|
90
|
+
});
|
|
91
|
+
return buildModel(curves, order, {
|
|
92
|
+
xField: "x",
|
|
93
|
+
yField: "y",
|
|
94
|
+
groupField: "series",
|
|
95
|
+
color: resolveFormattingColor(void 0, "default", 1)
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function fromFuseWidget(widget) {
|
|
99
|
+
const rows = rowsOf(widget);
|
|
100
|
+
const xField = firstField(widget.xAxe ?? void 0) ?? "x";
|
|
101
|
+
const yField = firstField(widget.yAxe ?? void 0) ?? "y";
|
|
102
|
+
const groupField = resolveGroupByKey(widget) ?? "series";
|
|
103
|
+
const curves = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const row of rows) {
|
|
105
|
+
const x = toNumber(row[xField]);
|
|
106
|
+
const y = toNumber(row[yField]);
|
|
107
|
+
if (x == null || y == null) continue;
|
|
108
|
+
const key = String(row[groupField] ?? "default");
|
|
109
|
+
let points = curves.get(key);
|
|
110
|
+
if (!points) {
|
|
111
|
+
points = [];
|
|
112
|
+
curves.set(key, points);
|
|
113
|
+
}
|
|
114
|
+
points.push({ x, y });
|
|
115
|
+
}
|
|
116
|
+
const order = resolveUniqueValuesOrder([...curves.keys()], widget.uniqueValues, groupField);
|
|
117
|
+
return buildModel(curves, order, {
|
|
118
|
+
xField,
|
|
119
|
+
yField,
|
|
120
|
+
groupField,
|
|
121
|
+
// The client paints every ICE curve and the average in one brand color, so
|
|
122
|
+
// the widget's formatting is read once instead of per group.
|
|
123
|
+
color: resolveFormattingColor(widget.formatting, "default", 1),
|
|
124
|
+
axisDetails: widget.axisDetails ?? void 0
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function normalizePartialDependenceData(input) {
|
|
128
|
+
if (!input) return EMPTY;
|
|
129
|
+
if (Array.isArray(input)) {
|
|
130
|
+
if (!input.length) return EMPTY;
|
|
131
|
+
const first = input[0];
|
|
132
|
+
if ("x" in first && "y" in first) {
|
|
133
|
+
return fromRows(input);
|
|
134
|
+
}
|
|
135
|
+
if ("label" in first && "value" in first) {
|
|
136
|
+
return fromRows(
|
|
137
|
+
input.map((d) => ({
|
|
138
|
+
x: d.label,
|
|
139
|
+
y: d.value
|
|
140
|
+
}))
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return EMPTY;
|
|
144
|
+
}
|
|
145
|
+
if (isFuseWidgetPayload(input)) return fromFuseWidget(input);
|
|
146
|
+
if (typeof input === "object") {
|
|
147
|
+
const candidate = input;
|
|
148
|
+
if (Array.isArray(candidate.iceSeries)) {
|
|
149
|
+
return fromIceSeries(candidate.iceSeries, {
|
|
150
|
+
xField: candidate.xField,
|
|
151
|
+
yField: candidate.yField,
|
|
152
|
+
groupField: candidate.groupField,
|
|
153
|
+
color: candidate.color,
|
|
154
|
+
axisDetails: candidate.axisDetails
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (Array.isArray(candidate.series)) return fromSeries(candidate.series);
|
|
158
|
+
if (Array.isArray(candidate.points)) {
|
|
159
|
+
return fromRows(candidate.points.map((p) => ({ x: p.x, y: p.y })));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return EMPTY;
|
|
163
|
+
}
|
|
164
|
+
export {
|
|
165
|
+
normalizePartialDependenceData
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sources":["../../../../src/components/partial-dependence-chart/lib/normalize.ts"],"sourcesContent":["import { resolveFormattingColor } from '../../../utils/fuse-palette.js';\nimport {\n firstField,\n isFuseWidgetPayload,\n resolveGroupByKey,\n resolveUniqueValuesOrder,\n rowsOf,\n type FuseWidgetLike,\n} from '../../../utils/fuse-widget.js';\nimport { computeAverageSeries, toNumber } from './series.js';\nimport type {\n IcePoint,\n IceSeries,\n PartialDependenceChartData,\n PartialDependenceModel,\n} from './types.js';\n\nconst EMPTY: PartialDependenceModel = {\n iceSeries: [],\n averageSeries: [],\n xField: '',\n yField: '',\n color: resolveFormattingColor(undefined, 'default', 1),\n};\n\n/** The chart always recomputes the average, so a supplied one is dropped. */\nconst AVERAGE_KEY = /average/i;\n\nfunction buildModel(\n curves: Map<string, IcePoint[]>,\n order: string[],\n fields: {\n xField: string;\n yField: string;\n groupField?: string;\n color: string;\n axisDetails?: PartialDependenceModel['axisDetails'];\n },\n): PartialDependenceModel {\n for (const [key, points] of curves) {\n if (AVERAGE_KEY.test(key)) {\n curves.delete(key);\n continue;\n }\n points.sort((a, b) => a.x - b.x);\n }\n\n const iceSeries: IceSeries[] = order\n .filter((key) => curves.has(key))\n .map((key) => ({ key, points: curves.get(key) as IcePoint[] }));\n\n if (!iceSeries.length) return { ...EMPTY, ...fields };\n\n return {\n iceSeries,\n averageSeries: computeAverageSeries(iceSeries.map((s) => s.points)),\n ...fields,\n };\n}\n\nfunction fromRows(\n rows: Array<{ x: unknown; y: unknown; group?: unknown }>,\n): PartialDependenceModel {\n const curves = new Map<string, IcePoint[]>();\n const order: string[] = [];\n for (const row of rows) {\n const x = toNumber(row.x);\n const y = toNumber(row.y);\n if (x == null || y == null) continue;\n const key = row.group != null ? String(row.group) : 'default';\n let points = curves.get(key);\n if (!points) {\n points = [];\n curves.set(key, points);\n order.push(key);\n }\n points.push({ x, y });\n }\n return buildModel(curves, order, {\n xField: 'x',\n yField: 'y',\n groupField: order.length > 1 || order[0] !== 'default' ? 'group' : undefined,\n color: resolveFormattingColor(undefined, 'default', 1),\n });\n}\n\nfunction fromIceSeries(\n series: Array<{ key?: unknown; points?: Array<{ x: unknown; y: unknown }> }>,\n fields: {\n xField?: string;\n yField?: string;\n groupField?: string;\n color?: string;\n axisDetails?: PartialDependenceModel['axisDetails'];\n },\n): PartialDependenceModel {\n const curves = new Map<string, IcePoint[]>();\n const order: string[] = [];\n series.forEach((entry, index) => {\n const key = String(entry.key ?? index);\n const points: IcePoint[] = [];\n for (const p of entry.points ?? []) {\n const x = toNumber(p.x);\n const y = toNumber(p.y);\n if (x == null || y == null) continue;\n points.push({ x, y });\n }\n if (!points.length) return;\n curves.set(key, points);\n order.push(key);\n });\n return buildModel(curves, order, {\n xField: fields.xField ?? 'x',\n yField: fields.yField ?? 'y',\n groupField: fields.groupField,\n color: fields.color ?? resolveFormattingColor(undefined, 'default', 1),\n axisDetails: fields.axisDetails,\n });\n}\n\nfunction fromSeries(\n series: Array<{ id?: string; name?: string; points?: Array<{ x: unknown; y: unknown }> }>,\n): PartialDependenceModel {\n const curves = new Map<string, IcePoint[]>();\n const order: string[] = [];\n series.forEach((entry, index) => {\n const key = String(entry.name ?? entry.id ?? index);\n const points: IcePoint[] = [];\n for (const p of entry.points ?? []) {\n const x = toNumber(p.x);\n const y = toNumber(p.y);\n if (x == null || y == null) continue;\n points.push({ x, y });\n }\n if (!points.length) return;\n curves.set(key, points);\n order.push(key);\n });\n return buildModel(curves, order, {\n xField: 'x',\n yField: 'y',\n groupField: 'series',\n color: resolveFormattingColor(undefined, 'default', 1),\n });\n}\n\nfunction fromFuseWidget(widget: FuseWidgetLike): PartialDependenceModel {\n const rows = rowsOf(widget);\n const xField = firstField(widget.xAxe ?? undefined) ?? 'x';\n const yField = firstField(widget.yAxe ?? undefined) ?? 'y';\n const groupField = resolveGroupByKey(widget) ?? 'series';\n\n const curves = new Map<string, IcePoint[]>();\n for (const row of rows) {\n const x = toNumber(row[xField]);\n const y = toNumber(row[yField]);\n if (x == null || y == null) continue;\n const key = String(row[groupField] ?? 'default');\n let points = curves.get(key);\n if (!points) {\n points = [];\n curves.set(key, points);\n }\n points.push({ x, y });\n }\n\n const order = resolveUniqueValuesOrder([...curves.keys()], widget.uniqueValues, groupField);\n\n return buildModel(curves, order, {\n xField,\n yField,\n groupField,\n // The client paints every ICE curve and the average in one brand color, so\n // the widget's formatting is read once instead of per group.\n color: resolveFormattingColor(widget.formatting, 'default', 1),\n axisDetails: widget.axisDetails ?? undefined,\n });\n}\n\n/** Normalize chat / FuseDash WidgetItem payloads into ICE curves plus the average. */\nexport function normalizePartialDependenceData(\n input: PartialDependenceChartData,\n): PartialDependenceModel {\n if (!input) return EMPTY;\n\n if (Array.isArray(input)) {\n if (!input.length) return EMPTY;\n const first = input[0] as Record<string, unknown>;\n if ('x' in first && 'y' in first) {\n return fromRows(input as Array<{ x: unknown; y: unknown; group?: unknown }>);\n }\n if ('label' in first && 'value' in first) {\n return fromRows(\n (input as Array<{ label: string | number; value: number }>).map((d) => ({\n x: d.label,\n y: d.value,\n })),\n );\n }\n return EMPTY;\n }\n\n if (isFuseWidgetPayload(input)) return fromFuseWidget(input);\n\n if (typeof input === 'object') {\n const candidate = input as Partial<PartialDependenceModel> & {\n points?: Array<{ x: unknown; y: unknown }>;\n series?: Array<{ id?: string; name?: string; points?: Array<{ x: unknown; y: unknown }> }>;\n };\n if (Array.isArray(candidate.iceSeries)) {\n return fromIceSeries(candidate.iceSeries, {\n xField: candidate.xField,\n yField: candidate.yField,\n groupField: candidate.groupField,\n color: candidate.color,\n axisDetails: candidate.axisDetails,\n });\n }\n if (Array.isArray(candidate.series)) return fromSeries(candidate.series);\n if (Array.isArray(candidate.points)) {\n return fromRows(candidate.points.map((p) => ({ x: p.x, y: p.y })));\n }\n }\n\n return EMPTY;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IcePoint } from './types.js';
|
|
2
|
+
export declare function toNumber(value: unknown): number | null;
|
|
3
|
+
/**
|
|
4
|
+
* Average the ICE curves on the union of their x values — client
|
|
5
|
+
* `computeAverageSeries`, with the linear `findIndex` scan replaced by a binary
|
|
6
|
+
* search so a dense mock stays O(x · groups · log n).
|
|
7
|
+
* Each group must already be sorted by x.
|
|
8
|
+
*/
|
|
9
|
+
export declare function computeAverageSeries(groups: Iterable<IcePoint[]>): IcePoint[];
|
|
10
|
+
/**
|
|
11
|
+
* Value of the average curve closest to `x` — backs the client's
|
|
12
|
+
* "tooltip shows nearest avg value" pointermove handler.
|
|
13
|
+
*/
|
|
14
|
+
export declare function nearestAveragePoint(averageSeries: IcePoint[], x: number): IcePoint | null;
|
|
15
|
+
//# sourceMappingURL=series.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../../../src/components/partial-dependence-chart/lib/series.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGtD;AAcD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,CA8B7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,QAAQ,EAAE,EACzB,CAAC,EAAE,MAAM,GACR,QAAQ,GAAG,IAAI,CAcjB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function toNumber(value) {
|
|
2
|
+
const n = Number(value);
|
|
3
|
+
return Number.isFinite(n) ? n : null;
|
|
4
|
+
}
|
|
5
|
+
function lowerBoundX(points, target) {
|
|
6
|
+
let lo = 0;
|
|
7
|
+
let hi = points.length;
|
|
8
|
+
while (lo < hi) {
|
|
9
|
+
const mid = lo + hi >> 1;
|
|
10
|
+
if (points[mid].x < target) lo = mid + 1;
|
|
11
|
+
else hi = mid;
|
|
12
|
+
}
|
|
13
|
+
return lo;
|
|
14
|
+
}
|
|
15
|
+
function computeAverageSeries(groups) {
|
|
16
|
+
const curves = [...groups].filter((points) => points.length > 0);
|
|
17
|
+
if (!curves.length) return [];
|
|
18
|
+
const xValues = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const points of curves) {
|
|
20
|
+
for (const p of points) xValues.add(p.x);
|
|
21
|
+
}
|
|
22
|
+
const xs = [...xValues].sort((a, b) => a - b);
|
|
23
|
+
return xs.map((x) => {
|
|
24
|
+
let sum = 0;
|
|
25
|
+
let count = 0;
|
|
26
|
+
for (const points of curves) {
|
|
27
|
+
const i = lowerBoundX(points, x);
|
|
28
|
+
if (i >= points.length) {
|
|
29
|
+
sum += points[points.length - 1].y;
|
|
30
|
+
} else if (i === 0) {
|
|
31
|
+
sum += points[0].y;
|
|
32
|
+
} else {
|
|
33
|
+
const p0 = points[i - 1];
|
|
34
|
+
const p1 = points[i];
|
|
35
|
+
const t = (x - p0.x) / Math.max(1e-12, p1.x - p0.x);
|
|
36
|
+
sum += p0.y + t * (p1.y - p0.y);
|
|
37
|
+
}
|
|
38
|
+
count += 1;
|
|
39
|
+
}
|
|
40
|
+
return { x, y: count ? sum / count : 0 };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function nearestAveragePoint(averageSeries, x) {
|
|
44
|
+
if (!averageSeries.length) return null;
|
|
45
|
+
const idx = lowerBoundX(averageSeries, x);
|
|
46
|
+
let best = null;
|
|
47
|
+
let bestDist = Infinity;
|
|
48
|
+
for (const candidate of [averageSeries[idx - 1], averageSeries[idx], averageSeries[idx + 1]]) {
|
|
49
|
+
if (!candidate) continue;
|
|
50
|
+
const dist = Math.abs(candidate.x - x);
|
|
51
|
+
if (dist < bestDist) {
|
|
52
|
+
best = candidate;
|
|
53
|
+
bestDist = dist;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return best;
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
computeAverageSeries,
|
|
60
|
+
nearestAveragePoint,
|
|
61
|
+
toNumber
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=series.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"series.js","sources":["../../../../src/components/partial-dependence-chart/lib/series.ts"],"sourcesContent":["import type { IcePoint } from './types.js';\n\nexport function toNumber(value: unknown): number | null {\n const n = Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\n/** First index whose `x >= target`, or `points.length` when every x is smaller. */\nfunction lowerBoundX(points: IcePoint[], target: number): number {\n let lo = 0;\n let hi = points.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (points[mid].x < target) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/**\n * Average the ICE curves on the union of their x values — client\n * `computeAverageSeries`, with the linear `findIndex` scan replaced by a binary\n * search so a dense mock stays O(x · groups · log n).\n * Each group must already be sorted by x.\n */\nexport function computeAverageSeries(groups: Iterable<IcePoint[]>): IcePoint[] {\n const curves = [...groups].filter((points) => points.length > 0);\n if (!curves.length) return [];\n\n const xValues = new Set<number>();\n for (const points of curves) {\n for (const p of points) xValues.add(p.x);\n }\n const xs = [...xValues].sort((a, b) => a - b);\n\n return xs.map((x) => {\n let sum = 0;\n let count = 0;\n for (const points of curves) {\n const i = lowerBoundX(points, x);\n if (i >= points.length) {\n // x sits past this curve — hold its last value\n sum += points[points.length - 1].y;\n } else if (i === 0) {\n sum += points[0].y;\n } else {\n const p0 = points[i - 1];\n const p1 = points[i];\n const t = (x - p0.x) / Math.max(1e-12, p1.x - p0.x);\n sum += p0.y + t * (p1.y - p0.y);\n }\n count += 1;\n }\n return { x, y: count ? sum / count : 0 };\n });\n}\n\n/**\n * Value of the average curve closest to `x` — backs the client's\n * \"tooltip shows nearest avg value\" pointermove handler.\n */\nexport function nearestAveragePoint(\n averageSeries: IcePoint[],\n x: number,\n): IcePoint | null {\n if (!averageSeries.length) return null;\n const idx = lowerBoundX(averageSeries, x);\n let best: IcePoint | null = null;\n let bestDist = Infinity;\n for (const candidate of [averageSeries[idx - 1], averageSeries[idx], averageSeries[idx + 1]]) {\n if (!candidate) continue;\n const dist = Math.abs(candidate.x - x);\n if (dist < bestDist) {\n best = candidate;\n bestDist = dist;\n }\n }\n return best;\n}\n"],"names":[],"mappings":"AAEO,SAAS,SAAS,OAA+B;AACtD,QAAM,IAAI,OAAO,KAAK;AACtB,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;AAGA,SAAS,YAAY,QAAoB,QAAwB;AAC/D,MAAI,KAAK;AACT,MAAI,KAAK,OAAO;AAChB,SAAO,KAAK,IAAI;AACd,UAAM,MAAO,KAAK,MAAO;AACzB,QAAI,OAAO,GAAG,EAAE,IAAI,aAAa,MAAM;AAAA,QAClC,MAAK;AAAA,EACZ;AACA,SAAO;AACT;AAQO,SAAS,qBAAqB,QAA0C;AAC7E,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,WAAW,OAAO,SAAS,CAAC;AAC/D,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAA;AAE3B,QAAM,8BAAc,IAAA;AACpB,aAAW,UAAU,QAAQ;AAC3B,eAAW,KAAK,OAAQ,SAAQ,IAAI,EAAE,CAAC;AAAA,EACzC;AACA,QAAM,KAAK,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAE5C,SAAO,GAAG,IAAI,CAAC,MAAM;AACnB,QAAI,MAAM;AACV,QAAI,QAAQ;AACZ,eAAW,UAAU,QAAQ;AAC3B,YAAM,IAAI,YAAY,QAAQ,CAAC;AAC/B,UAAI,KAAK,OAAO,QAAQ;AAEtB,eAAO,OAAO,OAAO,SAAS,CAAC,EAAE;AAAA,MACnC,WAAW,MAAM,GAAG;AAClB,eAAO,OAAO,CAAC,EAAE;AAAA,MACnB,OAAO;AACL,cAAM,KAAK,OAAO,IAAI,CAAC;AACvB,cAAM,KAAK,OAAO,CAAC;AACnB,cAAM,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,OAAO,GAAG,IAAI,GAAG,CAAC;AAClD,eAAO,GAAG,IAAI,KAAK,GAAG,IAAI,GAAG;AAAA,MAC/B;AACA,eAAS;AAAA,IACX;AACA,WAAO,EAAE,GAAG,GAAG,QAAQ,MAAM,QAAQ,EAAA;AAAA,EACvC,CAAC;AACH;AAMO,SAAS,oBACd,eACA,GACiB;AACjB,MAAI,CAAC,cAAc,OAAQ,QAAO;AAClC,QAAM,MAAM,YAAY,eAAe,CAAC;AACxC,MAAI,OAAwB;AAC5B,MAAI,WAAW;AACf,aAAW,aAAa,CAAC,cAAc,MAAM,CAAC,GAAG,cAAc,GAAG,GAAG,cAAc,MAAM,CAAC,CAAC,GAAG;AAC5F,QAAI,CAAC,UAAW;AAChB,UAAM,OAAO,KAAK,IAAI,UAAU,IAAI,CAAC;AACrC,QAAI,OAAO,UAAU;AACnB,aAAO;AACP,iBAAW;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { FuseWidgetLike } from '../../../utils/fuse-widget.js';
|
|
2
|
+
/** One point on an ICE (Individual Conditional Expectation) curve. */
|
|
3
|
+
export interface IcePoint {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}
|
|
7
|
+
export interface IceSeries {
|
|
8
|
+
/** groupBy value the curve was built from */
|
|
9
|
+
key: string;
|
|
10
|
+
points: IcePoint[];
|
|
11
|
+
}
|
|
12
|
+
export interface PartialDependenceModel {
|
|
13
|
+
/** One curve per groupBy value, each sorted by x. */
|
|
14
|
+
iceSeries: IceSeries[];
|
|
15
|
+
/** Average curve computed locally — never taken from the payload. */
|
|
16
|
+
averageSeries: IcePoint[];
|
|
17
|
+
xField: string;
|
|
18
|
+
yField: string;
|
|
19
|
+
groupField?: string;
|
|
20
|
+
/** Single brand color shared by the ICE band and the average line. */
|
|
21
|
+
color: string;
|
|
22
|
+
axisDetails?: Record<string, {
|
|
23
|
+
label?: string;
|
|
24
|
+
measure_unit_symbol?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/** Chat shapes accepted alongside the FuseDash widget payload. */
|
|
28
|
+
export type PartialDependenceChartData = Array<{
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
group?: string;
|
|
32
|
+
}> | Array<{
|
|
33
|
+
label: string | number;
|
|
34
|
+
value: number;
|
|
35
|
+
}> | {
|
|
36
|
+
points: Array<{
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
}>;
|
|
40
|
+
} | {
|
|
41
|
+
series: Array<{
|
|
42
|
+
id: string;
|
|
43
|
+
name?: string;
|
|
44
|
+
points: Array<{
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
}>;
|
|
48
|
+
}>;
|
|
49
|
+
} | FuseWidgetLike | PartialDependenceModel | null | undefined;
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/partial-dependence-chart/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,sEAAsE;AACtE,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,SAAS;IACxB,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,qEAAqE;IACrE,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChF;AAED,kEAAkE;AAClE,MAAM,MAAM,0BAA0B,GAClC,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/C,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAChD;IAAE,MAAM,EAAE,KAAK,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAC3C;IAAE,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,CAAC;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAAA;CAAE,GACzF,cAAc,GACd,sBAAsB,GACtB,IAAI,GACJ,SAAS,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
"id": "partial-dependence-chart",
|
|
3
|
+
"tag": "ui9000-partial-dependence-chart",
|
|
4
|
+
"title": "Partial Dependence (PDP) with ICE",
|
|
5
|
+
"description": "Chat-optimized partial dependence plot rewritten in D3. Faint ICE curves under a locally computed dashed average, no Redux.",
|
|
6
|
+
"chartTypeKeys": ["partialDependenceChart"],
|
|
7
|
+
"source": "client/libs/shared/components/src/Widgets/PartialDependenceChart/",
|
|
8
|
+
"stack": "d3",
|
|
9
|
+
"lazyImport": "@fusedashlabs/widgets/lazy/partial-dependence-chart",
|
|
10
|
+
"entry": "@fusedashlabs/widgets/partial-dependence-chart",
|
|
11
|
+
"usageConditions": {
|
|
12
|
+
"host": "mcp-chat",
|
|
13
|
+
"notFor": "fusedash-editor",
|
|
14
|
+
"mapsExcluded": true
|
|
15
|
+
},
|
|
16
|
+
"allowedActions": ["hover", "resize"],
|
|
17
|
+
"propsSchema": {
|
|
18
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"data": {
|
|
22
|
+
"oneOf": [
|
|
23
|
+
{
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"required": ["x", "y"],
|
|
28
|
+
"properties": {
|
|
29
|
+
"x": { "type": "number" },
|
|
30
|
+
"y": { "type": "number" },
|
|
31
|
+
"group": { "type": "string" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "object",
|
|
37
|
+
"required": ["series"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"series": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"id": { "type": "string" },
|
|
45
|
+
"name": { "type": "string" },
|
|
46
|
+
"points": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"items": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["x", "y"],
|
|
51
|
+
"properties": {
|
|
52
|
+
"x": { "type": "number" },
|
|
53
|
+
"y": { "type": "number" }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "object",
|
|
64
|
+
"description": "FuseDash WidgetItem-shaped payload"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"show-grid": { "type": "boolean" },
|
|
69
|
+
"show-legend": { "type": "boolean" },
|
|
70
|
+
"show-tooltip": { "type": "boolean" },
|
|
71
|
+
"scale": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"enum": ["compact", "default", "comfortable"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
;
|
|
79
|
+
|
|
80
|
+
export default _default;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const id = "partial-dependence-chart";
|
|
2
|
+
const tag = "ui9000-partial-dependence-chart";
|
|
3
|
+
const title = "Partial Dependence (PDP) with ICE";
|
|
4
|
+
const description = "Chat-optimized partial dependence plot rewritten in D3. Faint ICE curves under a locally computed dashed average, no Redux.";
|
|
5
|
+
const chartTypeKeys = ["partialDependenceChart"];
|
|
6
|
+
const source = "client/libs/shared/components/src/Widgets/PartialDependenceChart/";
|
|
7
|
+
const stack = "d3";
|
|
8
|
+
const lazyImport = "@fusedashlabs/widgets/lazy/partial-dependence-chart";
|
|
9
|
+
const entry = "@fusedashlabs/widgets/partial-dependence-chart";
|
|
10
|
+
const usageConditions = { "host": "mcp-chat", "notFor": "fusedash-editor", "mapsExcluded": true };
|
|
11
|
+
const allowedActions = ["hover", "resize"];
|
|
12
|
+
const propsSchema = { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "data": { "oneOf": [{ "type": "array", "items": { "type": "object", "required": ["x", "y"], "properties": { "x": { "type": "number" }, "y": { "type": "number" }, "group": { "type": "string" } } } }, { "type": "object", "required": ["series"], "properties": { "series": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "points": { "type": "array", "items": { "type": "object", "required": ["x", "y"], "properties": { "x": { "type": "number" }, "y": { "type": "number" } } } } } } } } }, { "type": "object", "description": "FuseDash WidgetItem-shaped payload" }] }, "show-grid": { "type": "boolean" }, "show-legend": { "type": "boolean" }, "show-tooltip": { "type": "boolean" }, "scale": { "type": "string", "enum": ["compact", "default", "comfortable"] } } };
|
|
13
|
+
const partialDependenceMeta = {
|
|
14
|
+
id,
|
|
15
|
+
tag,
|
|
16
|
+
title,
|
|
17
|
+
description,
|
|
18
|
+
chartTypeKeys,
|
|
19
|
+
source,
|
|
20
|
+
stack,
|
|
21
|
+
lazyImport,
|
|
22
|
+
entry,
|
|
23
|
+
usageConditions,
|
|
24
|
+
allowedActions,
|
|
25
|
+
propsSchema
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
allowedActions,
|
|
29
|
+
chartTypeKeys,
|
|
30
|
+
partialDependenceMeta as default,
|
|
31
|
+
description,
|
|
32
|
+
entry,
|
|
33
|
+
id,
|
|
34
|
+
lazyImport,
|
|
35
|
+
propsSchema,
|
|
36
|
+
source,
|
|
37
|
+
stack,
|
|
38
|
+
tag,
|
|
39
|
+
title,
|
|
40
|
+
usageConditions
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=metadata.json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { WidgetTheme } from '../../../types/index.js';
|
|
2
|
+
import { IcePoint, IceSeries } from '../lib/types.js';
|
|
3
|
+
export interface RenderPartialDependenceOptions {
|
|
4
|
+
iceSeries: IceSeries[];
|
|
5
|
+
averageSeries: IcePoint[];
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
/** Client PDP DEFAULT_MARGIN when omitted by the host */
|
|
9
|
+
margin?: {
|
|
10
|
+
top: number;
|
|
11
|
+
right: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
left: number;
|
|
14
|
+
};
|
|
15
|
+
theme: WidgetTheme;
|
|
16
|
+
themeMode?: 'light' | 'dark';
|
|
17
|
+
color: string;
|
|
18
|
+
showGrid?: boolean;
|
|
19
|
+
showTooltip?: boolean;
|
|
20
|
+
onHover?: (payload: {
|
|
21
|
+
x: number;
|
|
22
|
+
/** Average value nearest the cursor, or null when there is no average curve */
|
|
23
|
+
y: number | null;
|
|
24
|
+
event: PointerEvent;
|
|
25
|
+
}) => void;
|
|
26
|
+
onLeave?: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* FuseDash PartialDependenceChart — D3 rewrite.
|
|
30
|
+
* Coordinate system matches the client (Visx style): the margins live inside the
|
|
31
|
+
* scale ranges, so axis groups are placed in absolute SVG coordinates.
|
|
32
|
+
*/
|
|
33
|
+
export declare function renderPartialDependenceChart(container: HTMLElement, options: RenderPartialDependenceOptions): void;
|
|
34
|
+
//# sourceMappingURL=draw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draw.d.ts","sourceRoot":"","sources":["../../../../src/components/partial-dependence-chart/render/draw.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQ3D,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAClB,CAAC,EAAE,MAAM,CAAC;QACV,+EAA+E;QAC/E,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjB,KAAK,EAAE,YAAY,CAAC;KACrB,KAAK,IAAI,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAkBD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,8BAA8B,GACtC,IAAI,CA2KN"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { axisBottom, axisLeft } from "d3-axis";
|
|
2
|
+
import { scaleLinear } from "d3-scale";
|
|
3
|
+
import { select, pointer } from "d3-selection";
|
|
4
|
+
import { line, curveMonotoneX } from "d3-shape";
|
|
5
|
+
import { FD, calculateNumTicks, formatCompactNumber } from "../../../utils/fusedash-visual.js";
|
|
6
|
+
import { pdpLinearDomain } from "../lib/domain.js";
|
|
7
|
+
import { nearestAveragePoint } from "../lib/series.js";
|
|
8
|
+
function axisTickFormat(scale, count) {
|
|
9
|
+
const base = scale.tickFormat(count);
|
|
10
|
+
return (value) => {
|
|
11
|
+
const n = Number(value);
|
|
12
|
+
return Math.abs(n) >= 1e3 ? formatCompactNumber(n) : base(n);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function renderPartialDependenceChart(container, options) {
|
|
16
|
+
const {
|
|
17
|
+
iceSeries,
|
|
18
|
+
averageSeries,
|
|
19
|
+
width,
|
|
20
|
+
height,
|
|
21
|
+
margin = { ...FD.pdpMargin },
|
|
22
|
+
theme,
|
|
23
|
+
themeMode = "light",
|
|
24
|
+
color,
|
|
25
|
+
showGrid = true,
|
|
26
|
+
showTooltip = true,
|
|
27
|
+
onHover,
|
|
28
|
+
onLeave
|
|
29
|
+
} = options;
|
|
30
|
+
container.replaceChildren();
|
|
31
|
+
if (!iceSeries.length || width <= 0 || height <= 0) return;
|
|
32
|
+
const plotLeft = margin.left;
|
|
33
|
+
const plotRight = Math.max(margin.left + 1, width - margin.right);
|
|
34
|
+
const plotTop = margin.top;
|
|
35
|
+
const plotBottom = height - margin.bottom;
|
|
36
|
+
if (plotRight - plotLeft < 8 || plotBottom - plotTop < 8) return;
|
|
37
|
+
const xs = [];
|
|
38
|
+
const ys = [];
|
|
39
|
+
for (const series of iceSeries) {
|
|
40
|
+
for (const p of series.points) {
|
|
41
|
+
xs.push(p.x);
|
|
42
|
+
ys.push(p.y);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const p of averageSeries) {
|
|
46
|
+
xs.push(p.x);
|
|
47
|
+
ys.push(p.y);
|
|
48
|
+
}
|
|
49
|
+
const xScale = scaleLinear().domain(pdpLinearDomain(xs)).range([plotLeft, plotRight]);
|
|
50
|
+
const yScale = scaleLinear().domain(pdpLinearDomain(ys)).range([plotBottom, plotTop]);
|
|
51
|
+
const numXTicks = calculateNumTicks(plotRight - plotLeft);
|
|
52
|
+
const numYTicks = calculateNumTicks(plotBottom - plotTop);
|
|
53
|
+
const svg = select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("role", "img").attr("aria-label", "Partial dependence chart").style("display", "block").style("font-family", theme.fontFamily);
|
|
54
|
+
if (showGrid) {
|
|
55
|
+
svg.append("g").attr("class", "y-grid").selectAll("line").data(yScale.ticks(numYTicks)).join("line").attr("x1", plotLeft).attr("x2", plotRight).attr("y1", (d) => yScale(d)).attr("y2", (d) => yScale(d)).attr("stroke", FD.gridStroke).attr("stroke-dasharray", FD.gridDash).attr("shape-rendering", "crispEdges");
|
|
56
|
+
}
|
|
57
|
+
const xAxis = svg.append("g").attr("class", "x-axis").attr("transform", `translate(0,${plotBottom})`).call(axisBottom(xScale).ticks(numXTicks).tickFormat(axisTickFormat(xScale, numXTicks)));
|
|
58
|
+
xAxis.select(".domain").attr("stroke", FD.axisStroke);
|
|
59
|
+
xAxis.selectAll("line").attr("stroke", FD.axisStroke);
|
|
60
|
+
xAxis.selectAll("text").attr("fill", FD.axisLabelFill).attr("font-size", FD.axisLabelSize);
|
|
61
|
+
const yAxis = svg.append("g").attr("class", "y-axis").attr("transform", `translate(${plotLeft},0)`).call(axisLeft(yScale).ticks(numYTicks).tickFormat(axisTickFormat(yScale, numYTicks)));
|
|
62
|
+
yAxis.select(".domain").attr("stroke", FD.axisStroke);
|
|
63
|
+
yAxis.selectAll("line").attr("stroke", FD.axisStroke);
|
|
64
|
+
yAxis.selectAll("text").attr("fill", FD.axisLabelFill).attr("font-size", FD.axisLabelSize);
|
|
65
|
+
const lineGenerator = line().x((d) => xScale(d.x)).y((d) => yScale(d.y)).curve(curveMonotoneX);
|
|
66
|
+
svg.append("g").attr("class", "ice-lines").selectAll("path").data(iceSeries).join("path").attr("d", (d) => lineGenerator(d.points) ?? "").attr("fill", "none").attr("stroke", color).attr("opacity", FD.pdpIceOpacity).attr("stroke-width", FD.pdpIceStrokeWidth);
|
|
67
|
+
if (averageSeries.length) {
|
|
68
|
+
svg.append("path").attr("class", "avg-line").attr("d", lineGenerator(averageSeries) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", FD.pdpAverageStrokeWidth).attr("stroke-dasharray", FD.pdpAverageDash);
|
|
69
|
+
}
|
|
70
|
+
if (!showTooltip || !onHover) return;
|
|
71
|
+
const guide = svg.append("g").attr("class", "hover-guide").attr("opacity", 0).attr("pointer-events", "none");
|
|
72
|
+
const guideLine = guide.append("line").attr("y1", plotTop).attr("y2", plotBottom).attr("stroke", themeMode === "dark" ? FD.hoverGuideDark : FD.hoverGuideLight).attr("stroke-width", 1).attr("stroke-dasharray", FD.stepGuideDash);
|
|
73
|
+
const guideDot = guide.append("circle").attr("r", FD.stepHoverDotRadius).attr("fill", color).attr("stroke", themeMode === "dark" ? "#000" : "#fff").attr("stroke-width", 1);
|
|
74
|
+
svg.append("rect").attr("class", "hover-surface").attr("x", plotLeft).attr("y", plotTop).attr("width", plotRight - plotLeft).attr("height", plotBottom - plotTop).attr("fill", "transparent").on("pointermove", (event) => {
|
|
75
|
+
const svgNode = svg.node();
|
|
76
|
+
const [mx] = svgNode ? pointer(event, svgNode) : [plotLeft];
|
|
77
|
+
const x = xScale.invert(mx);
|
|
78
|
+
const nearest = nearestAveragePoint(averageSeries, x);
|
|
79
|
+
guideLine.attr("x1", mx).attr("x2", mx);
|
|
80
|
+
if (nearest) {
|
|
81
|
+
guideDot.attr("cx", xScale(nearest.x)).attr("cy", yScale(nearest.y)).attr("opacity", 1);
|
|
82
|
+
} else {
|
|
83
|
+
guideDot.attr("opacity", 0);
|
|
84
|
+
}
|
|
85
|
+
guide.attr("opacity", 1);
|
|
86
|
+
onHover({ x, y: nearest ? nearest.y : null, event });
|
|
87
|
+
}).on("pointerleave", () => {
|
|
88
|
+
guide.attr("opacity", 0);
|
|
89
|
+
onLeave == null ? void 0 : onLeave();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
renderPartialDependenceChart
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=draw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draw.js","sources":["../../../../src/components/partial-dependence-chart/render/draw.ts"],"sourcesContent":["import { axisBottom, axisLeft } from 'd3-axis';\nimport { scaleLinear, type NumberValue, type ScaleLinear } from 'd3-scale';\nimport { pointer, select } from 'd3-selection';\nimport { curveMonotoneX, line as d3Line } from 'd3-shape';\n\nimport type { WidgetTheme } from '../../../types/index.js';\nimport {\n calculateNumTicks,\n FD,\n formatCompactNumber,\n} from '../../../utils/fusedash-visual.js';\nimport { pdpLinearDomain } from '../lib/domain.js';\nimport { nearestAveragePoint } from '../lib/series.js';\nimport type { IcePoint, IceSeries } from '../lib/types.js';\n\nexport interface RenderPartialDependenceOptions {\n iceSeries: IceSeries[];\n averageSeries: IcePoint[];\n width: number;\n height: number;\n /** Client PDP DEFAULT_MARGIN when omitted by the host */\n margin?: { top: number; right: number; bottom: number; left: number };\n theme: WidgetTheme;\n themeMode?: 'light' | 'dark';\n color: string;\n showGrid?: boolean;\n showTooltip?: boolean;\n onHover?: (payload: {\n x: number;\n /** Average value nearest the cursor, or null when there is no average curve */\n y: number | null;\n event: PointerEvent;\n }) => void;\n onLeave?: () => void;\n}\n\n/**\n * PDP axes carry fractional feature values, so precision comes from d3's own\n * tick formatter (as in the client); only large magnitudes fall back to the\n * FuseDash compact K/M/B form.\n */\nfunction axisTickFormat(\n scale: ScaleLinear<number, number>,\n count: number,\n): (value: NumberValue) => string {\n const base = scale.tickFormat(count);\n return (value: NumberValue) => {\n const n = Number(value);\n return Math.abs(n) >= 1000 ? formatCompactNumber(n) : base(n);\n };\n}\n\n/**\n * FuseDash PartialDependenceChart — D3 rewrite.\n * Coordinate system matches the client (Visx style): the margins live inside the\n * scale ranges, so axis groups are placed in absolute SVG coordinates.\n */\nexport function renderPartialDependenceChart(\n container: HTMLElement,\n options: RenderPartialDependenceOptions,\n): void {\n const {\n iceSeries,\n averageSeries,\n width,\n height,\n margin = { ...FD.pdpMargin },\n theme,\n themeMode = 'light',\n color,\n showGrid = true,\n showTooltip = true,\n onHover,\n onLeave,\n } = options;\n\n container.replaceChildren();\n if (!iceSeries.length || width <= 0 || height <= 0) return;\n\n const plotLeft = margin.left;\n const plotRight = Math.max(margin.left + 1, width - margin.right);\n const plotTop = margin.top;\n const plotBottom = height - margin.bottom;\n if (plotRight - plotLeft < 8 || plotBottom - plotTop < 8) return;\n\n const xs: number[] = [];\n const ys: number[] = [];\n for (const series of iceSeries) {\n for (const p of series.points) {\n xs.push(p.x);\n ys.push(p.y);\n }\n }\n for (const p of averageSeries) {\n xs.push(p.x);\n ys.push(p.y);\n }\n\n const xScale = scaleLinear().domain(pdpLinearDomain(xs)).range([plotLeft, plotRight]);\n const yScale = scaleLinear().domain(pdpLinearDomain(ys)).range([plotBottom, plotTop]);\n\n const numXTicks = calculateNumTicks(plotRight - plotLeft);\n const numYTicks = calculateNumTicks(plotBottom - plotTop);\n\n const svg = select(container)\n .append('svg')\n .attr('width', width)\n .attr('height', height)\n .attr('viewBox', `0 0 ${width} ${height}`)\n .attr('role', 'img')\n .attr('aria-label', 'Partial dependence chart')\n .style('display', 'block')\n .style('font-family', theme.fontFamily);\n\n if (showGrid) {\n svg\n .append('g')\n .attr('class', 'y-grid')\n .selectAll('line')\n .data(yScale.ticks(numYTicks))\n .join('line')\n .attr('x1', plotLeft)\n .attr('x2', plotRight)\n .attr('y1', (d) => yScale(d))\n .attr('y2', (d) => yScale(d))\n .attr('stroke', FD.gridStroke)\n .attr('stroke-dasharray', FD.gridDash)\n .attr('shape-rendering', 'crispEdges');\n }\n\n const xAxis = svg\n .append('g')\n .attr('class', 'x-axis')\n .attr('transform', `translate(0,${plotBottom})`)\n .call(axisBottom(xScale).ticks(numXTicks).tickFormat(axisTickFormat(xScale, numXTicks)));\n xAxis.select('.domain').attr('stroke', FD.axisStroke);\n xAxis.selectAll('line').attr('stroke', FD.axisStroke);\n xAxis\n .selectAll('text')\n .attr('fill', FD.axisLabelFill)\n .attr('font-size', FD.axisLabelSize);\n\n const yAxis = svg\n .append('g')\n .attr('class', 'y-axis')\n .attr('transform', `translate(${plotLeft},0)`)\n .call(axisLeft(yScale).ticks(numYTicks).tickFormat(axisTickFormat(yScale, numYTicks)));\n yAxis.select('.domain').attr('stroke', FD.axisStroke);\n yAxis.selectAll('line').attr('stroke', FD.axisStroke);\n yAxis\n .selectAll('text')\n .attr('fill', FD.axisLabelFill)\n .attr('font-size', FD.axisLabelSize);\n\n const lineGenerator = d3Line<IcePoint>()\n .x((d) => xScale(d.x))\n .y((d) => yScale(d.y))\n .curve(curveMonotoneX);\n\n svg\n .append('g')\n .attr('class', 'ice-lines')\n .selectAll('path')\n .data(iceSeries)\n .join('path')\n .attr('d', (d) => lineGenerator(d.points) ?? '')\n .attr('fill', 'none')\n .attr('stroke', color)\n .attr('opacity', FD.pdpIceOpacity)\n .attr('stroke-width', FD.pdpIceStrokeWidth);\n\n if (averageSeries.length) {\n svg\n .append('path')\n .attr('class', 'avg-line')\n .attr('d', lineGenerator(averageSeries) ?? '')\n .attr('fill', 'none')\n .attr('stroke', color)\n .attr('stroke-width', FD.pdpAverageStrokeWidth)\n .attr('stroke-dasharray', FD.pdpAverageDash);\n }\n\n if (!showTooltip || !onHover) return;\n\n // Cursor chrome for the tooltip — the client reads the nearest average value\n // from an invisible overlay, which leaves nothing on screen to read it against.\n const guide = svg\n .append('g')\n .attr('class', 'hover-guide')\n .attr('opacity', 0)\n .attr('pointer-events', 'none');\n const guideLine = guide\n .append('line')\n .attr('y1', plotTop)\n .attr('y2', plotBottom)\n .attr('stroke', themeMode === 'dark' ? FD.hoverGuideDark : FD.hoverGuideLight)\n .attr('stroke-width', 1)\n .attr('stroke-dasharray', FD.stepGuideDash);\n const guideDot = guide\n .append('circle')\n .attr('r', FD.stepHoverDotRadius)\n .attr('fill', color)\n .attr('stroke', themeMode === 'dark' ? '#000' : '#fff')\n .attr('stroke-width', 1);\n\n svg\n .append('rect')\n .attr('class', 'hover-surface')\n .attr('x', plotLeft)\n .attr('y', plotTop)\n .attr('width', plotRight - plotLeft)\n .attr('height', plotBottom - plotTop)\n .attr('fill', 'transparent')\n .on('pointermove', (event: PointerEvent) => {\n const svgNode = svg.node();\n const [mx] = svgNode ? pointer(event, svgNode) : [plotLeft];\n const x = xScale.invert(mx);\n const nearest = nearestAveragePoint(averageSeries, x);\n guideLine.attr('x1', mx).attr('x2', mx);\n if (nearest) {\n guideDot.attr('cx', xScale(nearest.x)).attr('cy', yScale(nearest.y)).attr('opacity', 1);\n } else {\n guideDot.attr('opacity', 0);\n }\n guide.attr('opacity', 1);\n onHover({ x, y: nearest ? nearest.y : null, event });\n })\n .on('pointerleave', () => {\n guide.attr('opacity', 0);\n onLeave?.();\n });\n}\n"],"names":["d3Line"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/partial-dependence-chart/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,KAAK,8BAA8B,GACpC,MAAM,WAAW,CAAC"}
|