@pluot/react 0.1.17 → 0.1.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"BrushOverlay.d.ts","sourceRoot":"","sources":["../src/BrushOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAkB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EAEL,KAAK,SAAS,EAAE,KAAK,aAAa,EACnC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAgBjF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,UAAU,EAAE,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC5C,gFAAgF;IAChF,QAAQ,EAAE,aAAa,CAAC;IACxB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,+FAA+F;IAC/F,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC1E,eAAe,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CACjD,CAAC;AA0BF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,2CAqLpD"}
1
+ {"version":3,"file":"BrushOverlay.d.ts","sourceRoot":"","sources":["../src/BrushOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAkB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC9D,OAAO,EAEL,KAAK,SAAS,EAAE,KAAK,aAAa,EACnC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAgBjF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,UAAU,EAAE,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC5C,gFAAgF;IAChF,QAAQ,EAAE,aAAa,CAAC;IACxB,kGAAkG;IAClG,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,+FAA+F;IAC/F,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC1E,eAAe,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CACjD,CAAC;AA0BF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,2CAyLpD"}
@@ -57,8 +57,12 @@ export function BrushOverlay(props) {
57
57
  // `useId` emits colons, which are legal in an id but awkward inside `url(#...)`.
58
58
  const clipPathId = `pluot-brush-clip-${useId().replace(/:/g, "")}`;
59
59
  // While drawing a lasso, the intermediate vertices are too dense to be useful
60
- // as handles, and they are not editable until the drag completes.
61
- const shouldShowVertexHandles = isClosed;
60
+ // as handles, and they are not editable until the drag completes. RangeX/RangeY
61
+ // brushes only resize along one axis via their edges, so their corners are not
62
+ // meaningful drag handles either.
63
+ const shouldShowVertexHandles = isClosed
64
+ && brushState?.shape !== "RangeX"
65
+ && brushState?.shape !== "RangeY";
62
66
  // Sides are draggable only once the shape is settled, and only for the
63
67
  // axis-aligned shapes; a lasso has no meaningful sides.
64
68
  const editableEdges = enableBrushEdit && isClosed && brushState
@@ -1 +1 @@
1
- {"version":3,"file":"Pluot.d.ts","sourceRoot":"","sources":["../src/Pluot.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACgB,UAAU,EACrC,MAAM,YAAY,CAAC;AA4CpB,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CA8lBtC"}
1
+ {"version":3,"file":"Pluot.d.ts","sourceRoot":"","sources":["../src/Pluot.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAC4C,UAAU,EAEjE,MAAM,YAAY,CAAC;AA2DpB,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,2CAipBtC"}
package/dist-tsc/Pluot.js CHANGED
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useLayoutEffect, useEffect, useEffectEvent, useRef, useState, useMemo, useReducer, useId } from "react";
3
3
  import lzs from "lz-string";
4
4
  import { throttle } from "lodash-es";
5
- import { initialize, getIsWasmReady, render_wasm, pick_wasm, normalizeStores, getStore, checkWebGpuFeatureDetection, onMouseMove2d, onWheel2d, onMouseMove3d, onWheel3d, } from '@pluot/core';
5
+ import { initialize, getIsWasmReady, render_wasm, pick_wasm, brush_wasm, normalizeStores, getStore, checkWebGpuFeatureDetection, onMouseMove2d, onWheel2d, onMouseMove3d, onWheel3d, } from '@pluot/core';
6
6
  import { Tooltip } from "./Tooltip.js";
7
7
  import { BrushOverlay } from "./BrushOverlay.js";
8
8
  import { useBrush } from "./use-brush.js";
@@ -40,6 +40,20 @@ function normalizePickingResult(data) {
40
40
  })),
41
41
  };
42
42
  }
43
+ // `brush_wasm` is typed `any` by wasm-bindgen, so `RawBrushingResult` is what
44
+ // documents its wire format (see types.ts).
45
+ function normalizeBrushingResult(data) {
46
+ return {
47
+ ...data,
48
+ layer_results: data.layer_results.map(({ layer_id, info, element_info }) => ({
49
+ layer_id,
50
+ // This is needed because serde-wasm-bindgen
51
+ // converts Rust HashMap to JS Map.
52
+ info: Object.fromEntries(info),
53
+ element_info: Object.fromEntries(element_info),
54
+ })),
55
+ };
56
+ }
43
57
  export function Pluot(props) {
44
58
  const { schemaVersion = null, width: widthProp, height: heightProp, plotId, plotType, store: storeProp, storeName: storeNameProp, stores: storesProp, registerStores = true, plotParams, viewMode = "2d", marginBottom = 100.0, marginLeft = 100.0, marginTop = 100.0, marginRight = 100.0, aspectRatioMode = "Contain", // "Ignore", "Contain", "Cover"
45
59
  aspectRatioAlignmentMode = "Start", // "Center", "Start", "End"
@@ -47,7 +61,9 @@ export function Pluot(props) {
47
61
  minTimeout = 32, maxTimeout = 5000, allowSimultaneousRenders = true, debugMargins = false, backgroundColor = undefined, cameraMatrix: controlledCameraMatrix = null, setCameraMatrix: setControlledCameraMatrix = null, enableClick = false, enableTooltip = false, onClick: onClickProp = null, onHover: onHoverProp = null, brushUnitsModeX = "Data", brushUnitsModeY = "Data", brushMarginTop, brushMarginRight, brushMarginBottom, brushMarginLeft, enableBrushCreate = false, enableBrushEdit = false, enableBrushClear = false, brushDelay = 1500, maybeBrushDelay = 250, persistBrush = false, brushMode = "Rect", brushColor = "#3b6ea5",
48
62
  // An omitted `brush` means uncontrolled; a controlled parent signals the
49
63
  // empty state with `NO_BRUSH`, never `undefined`.
50
- brush = null, onBrush, onBrushEnd, onBrushClear, } = props;
64
+ brush = null, onBrush, onBrushEnd, onBrushClear,
65
+ // Temporary workaround. See comments in LruStore.clearCache.
66
+ shouldClearCache = true, } = props;
51
67
  const onClick = typeof onClickProp === 'function' ? onClickProp : noop;
52
68
  const onHover = typeof onHoverProp === 'function' ? onHoverProp : identity;
53
69
  // If cameraMatrix is not provided, then we manage the camera matrix internally.
@@ -113,6 +129,49 @@ export function Pluot(props) {
113
129
  // (width x height) container, used to position the hover tooltip.
114
130
  const [hoverInfo, setHoverInfo] = useState(null);
115
131
  const progressBarId = useId();
132
+ // Runs the brush query against the wasm module for a given brush state,
133
+ // analogous to `pick` below (defined here, ahead of `pick`, since `useBrush`
134
+ // needs it immediately).
135
+ const runBrush = useEffectEvent(async (state) => {
136
+ if (!isWasmReady) {
137
+ return;
138
+ }
139
+ const renderParams = {
140
+ schema_version: schemaVersion,
141
+ width,
142
+ height,
143
+ format: format,
144
+ margin_bottom: marginBottom,
145
+ margin_left: marginLeft,
146
+ margin_top: marginTop,
147
+ margin_right: marginRight,
148
+ device_pixel_ratio: window.devicePixelRatio,
149
+ aspect_ratio_mode: aspectRatioMode,
150
+ aspect_ratio_alignment_mode: aspectRatioAlignmentMode,
151
+ view_mode: viewMode,
152
+ pickable: false,
153
+ camera_view: cameraMatrix,
154
+ plot_id: plotId,
155
+ plot_type: plotType,
156
+ stores,
157
+ plot_params: plotParams,
158
+ timeout: currentTimeout.current,
159
+ wait_for_store_gets: false,
160
+ cache_enabled: true,
161
+ svg_compression_enabled: true,
162
+ svg_include_document: false,
163
+ };
164
+ // Brush vertices are container-relative pixels with Y increasing downwards;
165
+ // the wasm side expects screen coordinates with Y increasing upwards (as
166
+ // with the `screenCoordX`/`screenCoordY` passed to `pick_wasm` below).
167
+ const brushParams = {
168
+ screen_vertices: state.vertices.map((vertex) => ({ x: vertex.x_pixels, y: height - vertex.y_pixels })),
169
+ brush_units_mode_x: brushUnitsModeX,
170
+ brush_units_mode_y: brushUnitsModeY,
171
+ brush_mode: state.shape,
172
+ };
173
+ return normalizeBrushingResult(await brush_wasm(renderParams, brushParams));
174
+ });
116
175
  const { brushState, overlayRef: brushOverlayRef, geometry: brushGeometry, pressProgress, isBrushHovered, isBrushingRef, shouldSuppressClickRef, onVertexMouseDown, onEdgeMouseDown, onClearClick, } = useBrush({
117
176
  containerRef,
118
177
  width, height,
@@ -122,7 +181,7 @@ export function Pluot(props) {
122
181
  brushMarginTop, brushMarginRight, brushMarginBottom, brushMarginLeft,
123
182
  enableBrushCreate, enableBrushEdit, enableBrushClear,
124
183
  brushDelay, maybeBrushDelay, persistBrush, brushMode,
125
- brush, onBrush, onBrushEnd, onBrushClear,
184
+ brush, onBrush, onBrushEnd, onBrushClear, runBrush,
126
185
  });
127
186
  useLayoutEffect(() => {
128
187
  initialize().then(() => setIsWasmReady(getIsWasmReady()));
@@ -371,7 +430,7 @@ export function Pluot(props) {
371
430
  // Clear the LRU cache for the store (via its store_name) corresponding to the rendered plot.
372
431
  Object.keys(stores ?? {}).forEach(storeName => {
373
432
  const storeUsed = getStore(storeName);
374
- if (storeUsed && typeof storeUsed.clearCache === 'function') {
433
+ if (storeUsed && typeof storeUsed.clearCache === 'function' && shouldClearCache) {
375
434
  storeUsed.clearCache();
376
435
  }
377
436
  });
@@ -1,5 +1,5 @@
1
1
  export * from '@pluot/core';
2
2
  export { Pluot } from "./Pluot.js";
3
3
  export { NO_BRUSH } from "./types.js";
4
- export type { PluotProps, ViewMode, GraphicsFormat, PlotType, LayerParams, PlotParams, RenderParams, ScreenCoord, DataCoord, LayerPickingResult, PickingResult, TooltipContent, BrushUnitsMode, BrushMode, RectLikeBrushMode, BrushVertex, BrushState, BrushResult, NoBrush, } from "./types.js";
4
+ export type { PluotProps, ViewMode, GraphicsFormat, PlotType, LayerParams, PlotParams, RenderParams, ScreenCoord, DataCoord, LayerPickingResult, PickingResult, TooltipContent, BrushUnitsMode, BrushMode, RectLikeBrushMode, BrushVertex, BrushState, BrushResult, LayerBrushingResult, BrushingResult, NoBrush, } from "./types.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACV,UAAU,EACV,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,WAAW,EACX,OAAO,GACR,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACV,UAAU,EACV,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,OAAO,GACR,MAAM,YAAY,CAAC"}
@@ -98,6 +98,33 @@ export type PickingResult = {
98
98
  export type RawLayerPickingResult = Omit<LayerPickingResult, "info"> & {
99
99
  info: Map<string, string>;
100
100
  };
101
+ /** Mirrors the Rust `LayerBrushingResult` struct. */
102
+ export type LayerBrushingResult = {
103
+ layer_id: string;
104
+ info: Record<string, string>;
105
+ element_info: Record<string, string[]>;
106
+ };
107
+ /**
108
+ * Mirrors the Rust `BrushingResult` struct, after normalization of the `info`
109
+ * and `element_info` maps (produced by serde-wasm-bindgen) to plain objects.
110
+ */
111
+ export type BrushingResult = {
112
+ layer_results: LayerBrushingResult[];
113
+ };
114
+ /**
115
+ * The un-normalized shape that `brush_wasm` actually resolves to. It is typed
116
+ * `any` on the wasm-bindgen side, so this type is what documents the wire
117
+ * format: `serde_wasm_bindgen` converts the Rust `HashMap`s behind `info` and
118
+ * `element_info` into JS `Map`s, which {@link BrushingResult} flattens to
119
+ * plain objects.
120
+ */
121
+ export type RawLayerBrushingResult = Omit<LayerBrushingResult, "info" | "element_info"> & {
122
+ info: Map<string, string>;
123
+ element_info: Map<string, string[]>;
124
+ };
125
+ export type RawBrushingResult = Omit<BrushingResult, "layer_results"> & {
126
+ layer_results: RawLayerBrushingResult[];
127
+ };
101
128
  export type RawPickingResult = Omit<PickingResult, "layer_results"> & {
102
129
  layer_results: RawLayerPickingResult[];
103
130
  };
@@ -248,8 +275,9 @@ export type PluotProps = {
248
275
  brushMode?: BrushMode;
249
276
  brushColor?: string;
250
277
  brush?: BrushState | NoBrush | null;
251
- onBrush?: (state: BrushState, snappedState: BrushState) => BrushResult;
252
- onBrushEnd?: (state: BrushState, snappedState: BrushState) => BrushResult;
278
+ onBrush?: (state: BrushState, brushingResult: BrushingResult | undefined) => BrushResult;
279
+ onBrushEnd?: (state: BrushState, brushingResult: BrushingResult | undefined) => BrushResult;
253
280
  onBrushClear?: (state: BrushState) => void;
281
+ shouldClearCache?: boolean;
254
282
  };
255
283
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { type RefObject } from "react";
2
2
  import type { AspectRatioMode, AspectRatioAlignmentMode, CameraMatrix } from "@pluot/core";
3
3
  import { type BrushEdge, type BrushGeometry } from "./brush.js";
4
- import type { BrushState, PluotProps } from "./types.js";
4
+ import type { BrushingResult, BrushState, PluotProps } from "./types.js";
5
5
  /** Radius (in pixels) of the hover target around the clear button. */
6
6
  export declare const CLEAR_BUTTON_RADIUS_PX = 9;
7
7
  /** What the overlay needs to draw the long-click progress indicator. */
@@ -22,6 +22,8 @@ export type UseBrushParams = Pick<PluotProps, "brushUnitsModeX" | "brushUnitsMod
22
22
  aspectRatioMode: AspectRatioMode;
23
23
  aspectRatioAlignmentMode: AspectRatioAlignmentMode;
24
24
  cameraMatrix: CameraMatrix;
25
+ /** Runs the brush query (via `brush_wasm`) for the given brush state. */
26
+ runBrush: (state: BrushState) => Promise<BrushingResult | undefined>;
25
27
  };
26
28
  export type UseBrushResult = {
27
29
  /** The brush to draw, already reprojected into the current geometry. */
@@ -1 +1 @@
1
- {"version":3,"file":"use-brush.d.ts","sourceRoot":"","sources":["../src/use-brush.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1G,OAAO,KAAK,EAAE,eAAe,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAWL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,UAAU,EAAe,UAAU,EAAE,MAAM,YAAY,CAAC;AAQtE,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,wEAAwE;AACxE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EACxC,iBAAiB,GAAG,iBAAiB,GACrC,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,GAAG,iBAAiB,GAC/E,mBAAmB,GAAG,iBAAiB,GAAG,kBAAkB,GAC5D,YAAY,GAAG,iBAAiB,GAAG,cAAc,GAAG,WAAW,GAC/D,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,cAAc,CACtD,GAAG;IACF,YAAY,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;IACjC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,wEAAwE;IACxE,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,aAAa,CAAC;IACxB,4FAA4F;IAC5F,UAAU,EAAE,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC5C,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,yFAAyF;IACzF,cAAc,EAAE,OAAO,CAAC;IACxB,gFAAgF;IAChF,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,mFAAmF;IACnF,sBAAsB,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC1E,eAAe,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CACjD,CAAC;AAWF;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAwZ/D"}
1
+ {"version":3,"file":"use-brush.d.ts","sourceRoot":"","sources":["../src/use-brush.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1G,OAAO,KAAK,EAAE,eAAe,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAWL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAe,UAAU,EAAE,MAAM,YAAY,CAAC;AAQtF,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,wEAAwE;AACxE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EACxC,iBAAiB,GAAG,iBAAiB,GACrC,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,GAAG,iBAAiB,GAC/E,mBAAmB,GAAG,iBAAiB,GAAG,kBAAkB,GAC5D,YAAY,GAAG,iBAAiB,GAAG,cAAc,GAAG,WAAW,GAC/D,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,cAAc,CACtD,GAAG;IACF,YAAY,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;IACjC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,YAAY,EAAE,YAAY,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,cAAc,GAAC,SAAS,CAAC,CAAC;CACpE,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,wEAAwE;IACxE,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,aAAa,CAAC;IACxB,4FAA4F;IAC5F,UAAU,EAAE,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAC5C,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,yFAAyF;IACzF,cAAc,EAAE,OAAO,CAAC;IACxB,gFAAgF;IAChF,aAAa,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAClC,mFAAmF;IACnF,sBAAsB,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,iBAAiB,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC1E,eAAe,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;CACjD,CAAC;AAWF;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CA0Z/D"}
@@ -18,7 +18,7 @@ export const CLEAR_BUTTON_RADIUS_PX = 9;
18
18
  * `onBrushEnd` and the parent is expected to feed them back through `brush`.
19
19
  */
20
20
  export function useBrush(params) {
21
- const { containerRef, width, height, marginTop, marginRight, marginBottom, marginLeft, aspectRatioMode, aspectRatioAlignmentMode, cameraMatrix, brushUnitsModeX = "Data", brushUnitsModeY = "Data", brushMarginTop, brushMarginRight, brushMarginBottom, brushMarginLeft, enableBrushCreate = false, enableBrushEdit = false, enableBrushClear = false, brushDelay = 1500, maybeBrushDelay = 250, persistBrush = false, brushMode = "Rect", brush: controlledBrush, onBrush, onBrushEnd, onBrushClear, } = params;
21
+ const { containerRef, width, height, marginTop, marginRight, marginBottom, marginLeft, aspectRatioMode, aspectRatioAlignmentMode, cameraMatrix, brushUnitsModeX = "Data", brushUnitsModeY = "Data", brushMarginTop, brushMarginRight, brushMarginBottom, brushMarginLeft, enableBrushCreate = false, enableBrushEdit = false, enableBrushClear = false, brushDelay = 1500, maybeBrushDelay = 250, persistBrush = false, brushMode = "Rect", brush: controlledBrush, onBrush, onBrushEnd, onBrushClear, runBrush, } = params;
22
22
  // `null` (or an omitted prop) means uncontrolled; a BrushState or `NO_BRUSH`
23
23
  // means controlled, with `NO_BRUSH` standing for "controlled, nothing brushed".
24
24
  const isControlledBrush = controlledBrush !== null && controlledBrush !== undefined;
@@ -75,9 +75,9 @@ export function useBrush(params) {
75
75
  return [event.clientX - rect.left, event.clientY - rect.top];
76
76
  }, [containerRef]);
77
77
  // Push a brush update out: internally when uncontrolled, and to the parent in
78
- // both cases. Until the Rust-side `Brushable` trait lands there is nothing to
79
- // snap to, so the snapped state is the state and the `BrushResult` is unused.
80
- const emitBrush = useEffectEvent((nextBrush, isEnd) => {
78
+ // both cases. `brush_wasm` is run first, so the parent's `onBrush`/`onBrushEnd`
79
+ // is always handed the resulting `BrushingResult` alongside the drawn state.
80
+ const emitBrush = useEffectEvent(async (nextBrush, isEnd) => {
81
81
  // The draft is always advanced, since the rest of the drag builds on it...
82
82
  draftRef.current = nextBrush;
83
83
  // ...but a brush that spans nothing is not a selection. Committing one would
@@ -89,8 +89,9 @@ export function useBrush(params) {
89
89
  if (!isControlledBrush) {
90
90
  setUncontrolledBrush(nextBrush);
91
91
  }
92
+ const brushingResult = await runBrush(nextBrush);
92
93
  if (isEnd) {
93
- onBrushEnd?.(nextBrush, nextBrush);
94
+ onBrushEnd?.(nextBrush, brushingResult);
94
95
  // `persistBrush` only applies when uncontrolled; when controlled, the brush
95
96
  // persists for exactly as long as the parent keeps passing it.
96
97
  if (!isControlledBrush && !persistBrush) {
@@ -99,7 +100,7 @@ export function useBrush(params) {
99
100
  }
100
101
  }
101
102
  else {
102
- onBrush?.(nextBrush, nextBrush);
103
+ onBrush?.(nextBrush, brushingResult);
103
104
  }
104
105
  });
105
106
  const clearBrush = useEffectEvent(() => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pluot/react",
3
3
  "private": false,
4
- "version": "0.1.17",
4
+ "version": "0.1.18",
5
5
  "description": "React component for visualization with Pluot",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Mark Keller",
@@ -36,7 +36,7 @@
36
36
  "mouse-wheel": "^1.0.2",
37
37
  "lz-string": "^1.5.0",
38
38
  "lodash-es": "^4.17.23",
39
- "@pluot/core": "0.1.17"
39
+ "@pluot/core": "0.1.18"
40
40
  },
41
41
  "devDependencies": {
42
42
  "vitest": "^3.2.4",
@@ -106,8 +106,12 @@ export function BrushOverlay(props: BrushOverlayProps) {
106
106
  const clipPathId = `pluot-brush-clip-${useId().replace(/:/g, "")}`;
107
107
 
108
108
  // While drawing a lasso, the intermediate vertices are too dense to be useful
109
- // as handles, and they are not editable until the drag completes.
110
- const shouldShowVertexHandles = isClosed;
109
+ // as handles, and they are not editable until the drag completes. RangeX/RangeY
110
+ // brushes only resize along one axis via their edges, so their corners are not
111
+ // meaningful drag handles either.
112
+ const shouldShowVertexHandles = isClosed
113
+ && brushState?.shape !== "RangeX"
114
+ && brushState?.shape !== "RangeY";
111
115
 
112
116
  // Sides are draggable only once the shape is settled, and only for the
113
117
  // axis-aligned shapes; a lasso has no meaningful sides.
package/src/Pluot.tsx CHANGED
@@ -3,7 +3,7 @@ import lzs from "lz-string";
3
3
  import { throttle } from "lodash-es";
4
4
  import {
5
5
  initialize, getIsWasmReady,
6
- render_wasm, pick_wasm,
6
+ render_wasm, pick_wasm, brush_wasm,
7
7
  normalizeStores, getStore,
8
8
  checkWebGpuFeatureDetection,
9
9
  onMouseMove2d, onWheel2d,
@@ -14,7 +14,8 @@ import { Tooltip } from "./Tooltip.js";
14
14
  import { BrushOverlay } from "./BrushOverlay.js";
15
15
  import { useBrush } from "./use-brush.js";
16
16
  import type {
17
- HoverInfo, PickingResult, PluotProps, RawPickingResult, RenderParams, TooltipContent,
17
+ BrushingResult, BrushState, HoverInfo, PickingResult, PluotProps, RawBrushingResult, RawPickingResult,
18
+ RenderParams, TooltipContent,
18
19
  } from "./types.js";
19
20
 
20
21
  // Needed due to "SyntaxError: Named export 'decompressFromUint8Array' not found.
@@ -58,6 +59,21 @@ function normalizePickingResult(data: RawPickingResult): PickingResult {
58
59
  };
59
60
  }
60
61
 
62
+ // `brush_wasm` is typed `any` by wasm-bindgen, so `RawBrushingResult` is what
63
+ // documents its wire format (see types.ts).
64
+ function normalizeBrushingResult(data: RawBrushingResult): BrushingResult {
65
+ return {
66
+ ...data,
67
+ layer_results: data.layer_results.map(({ layer_id, info, element_info }) => ({
68
+ layer_id,
69
+ // This is needed because serde-wasm-bindgen
70
+ // converts Rust HashMap to JS Map.
71
+ info: Object.fromEntries(info),
72
+ element_info: Object.fromEntries(element_info),
73
+ })),
74
+ };
75
+ }
76
+
61
77
 
62
78
  export function Pluot(props: PluotProps) {
63
79
  const {
@@ -110,6 +126,9 @@ export function Pluot(props: PluotProps) {
110
126
  onBrush,
111
127
  onBrushEnd,
112
128
  onBrushClear,
129
+
130
+ // Temporary workaround. See comments in LruStore.clearCache.
131
+ shouldClearCache = true,
113
132
  } = props;
114
133
 
115
134
  const onClick: (result: PickingResult) => void = typeof onClickProp === 'function' ? onClickProp : noop;
@@ -196,6 +215,54 @@ export function Pluot(props: PluotProps) {
196
215
 
197
216
  const progressBarId = useId();
198
217
 
218
+ // Runs the brush query against the wasm module for a given brush state,
219
+ // analogous to `pick` below (defined here, ahead of `pick`, since `useBrush`
220
+ // needs it immediately).
221
+ const runBrush = useEffectEvent(async (state: BrushState): Promise<BrushingResult|undefined> => {
222
+
223
+ if (!isWasmReady) {
224
+ return;
225
+ }
226
+
227
+ const renderParams: RenderParams = {
228
+ schema_version: schemaVersion,
229
+ width,
230
+ height,
231
+ format: format,
232
+ margin_bottom: marginBottom,
233
+ margin_left: marginLeft,
234
+ margin_top: marginTop,
235
+ margin_right: marginRight,
236
+ device_pixel_ratio: window.devicePixelRatio,
237
+ aspect_ratio_mode: aspectRatioMode,
238
+ aspect_ratio_alignment_mode: aspectRatioAlignmentMode,
239
+ view_mode: viewMode,
240
+ pickable: false,
241
+ camera_view: cameraMatrix,
242
+ plot_id: plotId,
243
+ plot_type: plotType,
244
+ stores,
245
+ plot_params: plotParams,
246
+ timeout: currentTimeout.current,
247
+ wait_for_store_gets: false,
248
+ cache_enabled: true,
249
+ svg_compression_enabled: true,
250
+ svg_include_document: false,
251
+ };
252
+
253
+ // Brush vertices are container-relative pixels with Y increasing downwards;
254
+ // the wasm side expects screen coordinates with Y increasing upwards (as
255
+ // with the `screenCoordX`/`screenCoordY` passed to `pick_wasm` below).
256
+ const brushParams = {
257
+ screen_vertices: state.vertices.map((vertex) => ({ x: vertex.x_pixels, y: height - vertex.y_pixels })),
258
+ brush_units_mode_x: brushUnitsModeX,
259
+ brush_units_mode_y: brushUnitsModeY,
260
+ brush_mode: state.shape,
261
+ };
262
+
263
+ return normalizeBrushingResult(await brush_wasm(renderParams, brushParams));
264
+ });
265
+
199
266
  const {
200
267
  brushState,
201
268
  overlayRef: brushOverlayRef,
@@ -216,7 +283,7 @@ export function Pluot(props: PluotProps) {
216
283
  brushMarginTop, brushMarginRight, brushMarginBottom, brushMarginLeft,
217
284
  enableBrushCreate, enableBrushEdit, enableBrushClear,
218
285
  brushDelay, maybeBrushDelay, persistBrush, brushMode,
219
- brush, onBrush, onBrushEnd, onBrushClear,
286
+ brush, onBrush, onBrushEnd, onBrushClear, runBrush,
220
287
  });
221
288
 
222
289
  useLayoutEffect(() => {
@@ -501,7 +568,7 @@ export function Pluot(props: PluotProps) {
501
568
  // Clear the LRU cache for the store (via its store_name) corresponding to the rendered plot.
502
569
  Object.keys(stores ?? {}).forEach(storeName => {
503
570
  const storeUsed = getStore(storeName);
504
- if (storeUsed && typeof storeUsed.clearCache === 'function') {
571
+ if (storeUsed && typeof storeUsed.clearCache === 'function' && shouldClearCache) {
505
572
  storeUsed.clearCache();
506
573
  }
507
574
  });
package/src/index.ts CHANGED
@@ -20,5 +20,7 @@ export type {
20
20
  BrushVertex,
21
21
  BrushState,
22
22
  BrushResult,
23
+ LayerBrushingResult,
24
+ BrushingResult,
23
25
  NoBrush,
24
26
  } from "./types.js";
package/src/types.ts CHANGED
@@ -115,6 +115,37 @@ export type RawLayerPickingResult = Omit<LayerPickingResult, "info"> & {
115
115
  info: Map<string, string>;
116
116
  };
117
117
 
118
+ /** Mirrors the Rust `LayerBrushingResult` struct. */
119
+ export type LayerBrushingResult = {
120
+ layer_id: string;
121
+ info: Record<string, string>;
122
+ element_info: Record<string, string[]>;
123
+ };
124
+
125
+ /**
126
+ * Mirrors the Rust `BrushingResult` struct, after normalization of the `info`
127
+ * and `element_info` maps (produced by serde-wasm-bindgen) to plain objects.
128
+ */
129
+ export type BrushingResult = {
130
+ layer_results: LayerBrushingResult[];
131
+ };
132
+
133
+ /**
134
+ * The un-normalized shape that `brush_wasm` actually resolves to. It is typed
135
+ * `any` on the wasm-bindgen side, so this type is what documents the wire
136
+ * format: `serde_wasm_bindgen` converts the Rust `HashMap`s behind `info` and
137
+ * `element_info` into JS `Map`s, which {@link BrushingResult} flattens to
138
+ * plain objects.
139
+ */
140
+ export type RawLayerBrushingResult = Omit<LayerBrushingResult, "info" | "element_info"> & {
141
+ info: Map<string, string>;
142
+ element_info: Map<string, string[]>;
143
+ };
144
+
145
+ export type RawBrushingResult = Omit<BrushingResult, "layer_results"> & {
146
+ layer_results: RawLayerBrushingResult[];
147
+ };
148
+
118
149
  export type RawPickingResult = Omit<PickingResult, "layer_results"> & {
119
150
  layer_results: RawLayerPickingResult[];
120
151
  };
@@ -366,13 +397,16 @@ export type PluotProps = {
366
397
 
367
398
  // Called on drag interactions, as the user is drawing the brush rect/polygon.
368
399
  // Also called if the brushed rect/polygon is edited (e.g., by dragging a vertex of a persisted brush, if enableBrushEdit is true).
369
- // Note: until the Rust `Brushable` trait exists, there is nothing to snap to, so
370
- // `snappedState` is the same object as `state` and the returned `BrushResult` is ignored.
371
- onBrush?: (state: BrushState, snappedState: BrushState) => BrushResult,
400
+ // `brushingResult` is the result of running the brush query (via `brush_wasm`)
401
+ // against the current `state`.
402
+ onBrush?: (state: BrushState, brushingResult: BrushingResult|undefined) => BrushResult,
372
403
  // Called at the conclusion of the drag interaction, with the final (i.e., complete) brush rect/polygon.
373
- onBrushEnd?: (state: BrushState, snappedState: BrushState) => BrushResult,
404
+ onBrushEnd?: (state: BrushState, brushingResult: BrushingResult|undefined) => BrushResult,
374
405
 
375
406
  // Called upon the user cancelling the brush, e.g., by clicking a clear button which appears when hovering the drawn rect/polygon.
376
407
  onBrushClear?: (state: BrushState) => void,
377
408
 
409
+
410
+ shouldClearCache?: boolean,
411
+
378
412
  };
package/src/use-brush.ts CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  type BrushGeometry,
17
17
  } from "./brush.js";
18
18
  import { NO_BRUSH } from "./types.js";
19
- import type { BrushState, BrushVertex, PluotProps } from "./types.js";
19
+ import type { BrushingResult, BrushState, BrushVertex, PluotProps } from "./types.js";
20
20
 
21
21
  /** Cursor movement (in pixels) that cancels a pending long-click, since the user is panning instead. */
22
22
  const LONG_CLICK_CANCEL_PX = 4;
@@ -52,6 +52,8 @@ export type UseBrushParams = Pick<PluotProps,
52
52
  aspectRatioMode: AspectRatioMode;
53
53
  aspectRatioAlignmentMode: AspectRatioAlignmentMode;
54
54
  cameraMatrix: CameraMatrix;
55
+ /** Runs the brush query (via `brush_wasm`) for the given brush state. */
56
+ runBrush: (state: BrushState) => Promise<BrushingResult|undefined>;
55
57
  };
56
58
 
57
59
  export type UseBrushResult = {
@@ -113,6 +115,7 @@ export function useBrush(params: UseBrushParams): UseBrushResult {
113
115
  onBrush,
114
116
  onBrushEnd,
115
117
  onBrushClear,
118
+ runBrush,
116
119
  } = params;
117
120
 
118
121
  // `null` (or an omitted prop) means uncontrolled; a BrushState or `NO_BRUSH`
@@ -181,9 +184,9 @@ export function useBrush(params: UseBrushParams): UseBrushResult {
181
184
  }, [containerRef]);
182
185
 
183
186
  // Push a brush update out: internally when uncontrolled, and to the parent in
184
- // both cases. Until the Rust-side `Brushable` trait lands there is nothing to
185
- // snap to, so the snapped state is the state and the `BrushResult` is unused.
186
- const emitBrush = useEffectEvent((nextBrush: BrushState, isEnd: boolean) => {
187
+ // both cases. `brush_wasm` is run first, so the parent's `onBrush`/`onBrushEnd`
188
+ // is always handed the resulting `BrushingResult` alongside the drawn state.
189
+ const emitBrush = useEffectEvent(async (nextBrush: BrushState, isEnd: boolean) => {
187
190
  // The draft is always advanced, since the rest of the drag builds on it...
188
191
  draftRef.current = nextBrush;
189
192
  // ...but a brush that spans nothing is not a selection. Committing one would
@@ -195,8 +198,9 @@ export function useBrush(params: UseBrushParams): UseBrushResult {
195
198
  if (!isControlledBrush) {
196
199
  setUncontrolledBrush(nextBrush);
197
200
  }
201
+ const brushingResult = await runBrush(nextBrush);
198
202
  if (isEnd) {
199
- onBrushEnd?.(nextBrush, nextBrush);
203
+ onBrushEnd?.(nextBrush, brushingResult);
200
204
  // `persistBrush` only applies when uncontrolled; when controlled, the brush
201
205
  // persists for exactly as long as the parent keeps passing it.
202
206
  if (!isControlledBrush && !persistBrush) {
@@ -204,7 +208,7 @@ export function useBrush(params: UseBrushParams): UseBrushResult {
204
208
  draftRef.current = null;
205
209
  }
206
210
  } else {
207
- onBrush?.(nextBrush, nextBrush);
211
+ onBrush?.(nextBrush, brushingResult);
208
212
  }
209
213
  });
210
214