@bicharts/chart-host 0.6.7 → 0.6.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/{chunk-RKOFRMS4.mjs → chunk-GJF6V6BZ.mjs} +31 -7
- package/dist/index.mjs +1 -1
- package/dist/react.mjs +15 -11
- package/dist/types/group.d.ts +13 -6
- package/package.json +1 -1
|
@@ -3848,9 +3848,27 @@ function toSourceRows(rowMap, payloadRowIdxs) {
|
|
|
3848
3848
|
if (!rowMap) return payloadRowIdxs.slice();
|
|
3849
3849
|
return payloadRowIdxs.map((i) => rowMap[i]).filter((i) => i !== void 0);
|
|
3850
3850
|
}
|
|
3851
|
-
function
|
|
3851
|
+
function toPayloadRows(rowMap, sourceRowIdxs) {
|
|
3852
|
+
const at3 = /* @__PURE__ */ new Map();
|
|
3853
|
+
rowMap.forEach((src, k3) => {
|
|
3854
|
+
if (!at3.has(src)) at3.set(src, k3);
|
|
3855
|
+
});
|
|
3856
|
+
return sourceRowIdxs.map((s) => at3.get(s)).filter((k3) => k3 !== void 0);
|
|
3857
|
+
}
|
|
3858
|
+
var sameRows = (a4, b4) => {
|
|
3859
|
+
if (a4.length !== b4.length) return false;
|
|
3860
|
+
const x2 = a4.slice().sort((p2, q3) => p2 - q3), y5 = b4.slice().sort((p2, q3) => p2 - q3);
|
|
3861
|
+
return x2.every((v4, i) => v4 === y5[i]);
|
|
3862
|
+
};
|
|
3863
|
+
function syncMemberSelection(host, selection, id, highlight, incoming, rowMap) {
|
|
3852
3864
|
const mine = selection.sourceId === id && selection.rows.length > 0;
|
|
3853
|
-
if (mine)
|
|
3865
|
+
if (mine) {
|
|
3866
|
+
if (rowMap) {
|
|
3867
|
+
const want = toPayloadRows(rowMap, selection.rows);
|
|
3868
|
+
if (!sameRows(want, host.selection.current ?? [])) host.selection.highlight(want);
|
|
3869
|
+
}
|
|
3870
|
+
return;
|
|
3871
|
+
}
|
|
3854
3872
|
if (highlight && incoming && incoming.length) {
|
|
3855
3873
|
host.selection.highlight(incoming.slice());
|
|
3856
3874
|
return;
|
|
@@ -3918,18 +3936,24 @@ function createChartGroup(columns, rows, opts = {}) {
|
|
|
3918
3936
|
attach(id, host, o = {}) {
|
|
3919
3937
|
const highlight = o.respondsWith === "highlight";
|
|
3920
3938
|
let rowMap = memberPayload(id, o).rowMap;
|
|
3939
|
+
const filterKey = (incoming) => highlight || !incoming ? "*" : incoming.join(",");
|
|
3940
|
+
let drawnUnder = filterKey(incomingFor(id, o.filteredBy));
|
|
3921
3941
|
const offHost = host.selection.onChange((payloadIdxs, source) => {
|
|
3922
3942
|
if (source === "host") return;
|
|
3923
3943
|
const sourceIdxs = toSourceRows(rowMap, payloadIdxs);
|
|
3924
3944
|
if (id) group.publish(id, sourceIdxs);
|
|
3925
3945
|
o.onSelect?.(sourceIdxs);
|
|
3926
3946
|
});
|
|
3927
|
-
const offGroup = group.onChange((sel) => {
|
|
3947
|
+
const offGroup = group.onChange((sel, change) => {
|
|
3928
3948
|
const incoming = incomingFor(id, o.filteredBy);
|
|
3929
|
-
const
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3949
|
+
const key = filterKey(incoming);
|
|
3950
|
+
if (change === "source" || key !== drawnUnder) {
|
|
3951
|
+
const next = payloadFor(highlight ? null : incoming);
|
|
3952
|
+
rowMap = next.rowMap;
|
|
3953
|
+
drawnUnder = key;
|
|
3954
|
+
host.setData(next.payload);
|
|
3955
|
+
}
|
|
3956
|
+
syncMemberSelection(host, sel, id, highlight, incoming, rowMap);
|
|
3933
3957
|
});
|
|
3934
3958
|
const member = {
|
|
3935
3959
|
get rowMap() {
|
package/dist/index.mjs
CHANGED
package/dist/react.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
loadGeo,
|
|
8
8
|
syncMemberSelection,
|
|
9
9
|
toSourceRows
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GJF6V6BZ.mjs";
|
|
11
11
|
import "./chunk-A2GMXZP7.mjs";
|
|
12
12
|
import "./chunk-GHODWOAL.mjs";
|
|
13
13
|
|
|
@@ -35,11 +35,7 @@ function BicChartGroup({ rows, columns, geo, point, children }) {
|
|
|
35
35
|
useEffect(() => group.onChange((s, change) => {
|
|
36
36
|
if (change !== "source") setSel(s);
|
|
37
37
|
}), [group]);
|
|
38
|
-
const value = useMemo(
|
|
39
|
-
() => ({ group, selection: sel }),
|
|
40
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
-
[group, sel, source]
|
|
42
|
-
);
|
|
38
|
+
const value = useMemo(() => ({ group, selection: sel, source }), [group, sel, source]);
|
|
43
39
|
return /* @__PURE__ */ jsx(Ctx.Provider, { value, children });
|
|
44
40
|
}
|
|
45
41
|
function BicChart(props) {
|
|
@@ -71,9 +67,11 @@ function BicChart(props) {
|
|
|
71
67
|
const built = useMemo(() => {
|
|
72
68
|
if (!group) return null;
|
|
73
69
|
return group.payloadFor(filterSel);
|
|
74
|
-
}, [ctx, filterSel && filterSel.join(",")]);
|
|
70
|
+
}, [group, ctx?.source, filterSel && filterSel.join(",")]);
|
|
75
71
|
const data = built ? built.payload : props.data;
|
|
76
72
|
rowMapRef.current = built ? built.rowMap : null;
|
|
73
|
+
const optKey = useMemo(() => JSON.stringify(options ?? {}), [options]);
|
|
74
|
+
const builtWithRef = useRef(null);
|
|
77
75
|
const onSelectRef = useRef(onSelect);
|
|
78
76
|
onSelectRef.current = onSelect;
|
|
79
77
|
const onLabelContrastRef = useRef(onLabelContrast);
|
|
@@ -124,23 +122,29 @@ function BicChart(props) {
|
|
|
124
122
|
onSelectRef.current?.(sourceIdxs);
|
|
125
123
|
});
|
|
126
124
|
host.render();
|
|
125
|
+
builtWithRef.current = { data, optKey };
|
|
127
126
|
return () => {
|
|
128
127
|
off();
|
|
129
128
|
host.destroy();
|
|
130
129
|
hostRef.current = null;
|
|
131
130
|
};
|
|
132
131
|
}, [code, renderFn, d3, geoKind, labelContrast]);
|
|
133
|
-
const optKey = useMemo(() => JSON.stringify(options ?? {}), [options]);
|
|
134
132
|
useEffect(() => {
|
|
135
|
-
if (hostRef.current
|
|
133
|
+
if (!hostRef.current || !options) return;
|
|
134
|
+
if (builtWithRef.current?.optKey === optKey) return;
|
|
135
|
+
builtWithRef.current = { ...builtWithRef.current, optKey };
|
|
136
|
+
hostRef.current.setOptions(options);
|
|
136
137
|
}, [optKey]);
|
|
137
138
|
useEffect(() => {
|
|
138
|
-
if (hostRef.current
|
|
139
|
+
if (!hostRef.current || !data) return;
|
|
140
|
+
if (builtWithRef.current?.data === data) return;
|
|
141
|
+
builtWithRef.current = { ...builtWithRef.current, data };
|
|
142
|
+
hostRef.current.setData(data);
|
|
139
143
|
}, [data]);
|
|
140
144
|
useEffect(() => {
|
|
141
145
|
const host = hostRef.current;
|
|
142
146
|
if (!host || !ctx) return;
|
|
143
|
-
syncMemberSelection(host, ctx.selection, id, highlightMode, incoming);
|
|
147
|
+
syncMemberSelection(host, ctx.selection, id, highlightMode, incoming, rowMapRef.current);
|
|
144
148
|
}, [ctx?.selection, id, ctx, highlightMode, incoming && incoming.join(",")]);
|
|
145
149
|
return /* @__PURE__ */ jsx("div", { ref, className, style });
|
|
146
150
|
}
|
package/dist/types/group.d.ts
CHANGED
|
@@ -74,13 +74,20 @@ export interface ChartGroup {
|
|
|
74
74
|
/** Payload row indices -> source row indices, dropping any the map does not cover. */
|
|
75
75
|
export declare function toSourceRows(rowMap: readonly number[] | null | undefined, payloadRowIdxs: readonly number[]): number[];
|
|
76
76
|
/**
|
|
77
|
-
* Make a member's painted selection agree with the group's. A member
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
77
|
+
* Make a member's painted selection agree with the group's. A highlight member with an incoming
|
|
78
|
+
* selection paints it. Any other member that still shows a selection clears it - a stale
|
|
79
|
+
* highlight left on the origin after the selection moved elsewhere, or after a clear.
|
|
80
|
+
*
|
|
81
|
+
* THE MEMBER THAT MADE THE SELECTION keeps it, repainted in the payload it draws NOW when
|
|
82
|
+
* `rowMap` (that payload's row map) is given. Its host holds the selection as PAYLOAD rows, and
|
|
83
|
+
* a member that was filtered when it was clicked stops filtering the moment it becomes the
|
|
84
|
+
* origin - its payload grows back to the whole table and renumbers, so the payload rows its
|
|
85
|
+
* host holds would name different records. The group's selection is in source rows, so it is
|
|
86
|
+
* translated through the new map and repainted when it differs.
|
|
87
|
+
*
|
|
88
|
+
* Every path notifies with source "host", so nothing done here is republished.
|
|
82
89
|
*/
|
|
83
|
-
export declare function syncMemberSelection(host: ChartHost, selection: ChartGroupSelection, id: string | undefined, highlight: boolean, incoming: readonly number[] | null): void;
|
|
90
|
+
export declare function syncMemberSelection(host: ChartHost, selection: ChartGroupSelection, id: string | undefined, highlight: boolean, incoming: readonly number[] | null, rowMap?: readonly number[] | null): void;
|
|
84
91
|
/**
|
|
85
92
|
* Create a cross-filter group over one source table: `rows` are objects keyed by column name,
|
|
86
93
|
* `columns` the column descriptors (`ingest()` returns both).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|