()
| 2614 | }; |
| 2615 | |
| 2616 | const updateZoom = (): void => { |
| 2617 | const cfg = getZoomOptionsConfig(currentOptions); |
| 2618 | |
| 2619 | if (!cfg) { |
| 2620 | insideZoom?.dispose(); |
| 2621 | insideZoom = null; |
| 2622 | unsubscribeZoom?.(); |
| 2623 | unsubscribeZoom = null; |
| 2624 | zoomState = null; |
| 2625 | lastOptionsZoomRange = null; |
| 2626 | return; |
| 2627 | } |
| 2628 | |
| 2629 | if (!zoomState) { |
| 2630 | const constraints = computeEffectiveZoomSpanConstraints(); |
| 2631 | zoomState = createZoomState(cfg.start, cfg.end, constraints); |
| 2632 | lastOptionsZoomRange = { start: cfg.start, end: cfg.end }; |
| 2633 | unsubscribeZoom = zoomState.onChange((range) => { |
| 2634 | // Coalesce slicing (and visible-bounds recompute) to at most once per rendered frame. |
| 2635 | sliceRenderSeriesDue = true; |
| 2636 | // Immediate render for UI feedback (axes/crosshair/slider). |
| 2637 | requestRender(); |
| 2638 | // Debounce resampling; the unified flush will do the work. |
| 2639 | scheduleZoomResample(); |
| 2640 | // Ensure listeners get a stable readonly object. |
| 2641 | emitZoomRange({ start: range.start, end: range.end }); |
| 2642 | }); |
| 2643 | } else { |
| 2644 | const constraints = computeEffectiveZoomSpanConstraints(); |
| 2645 | const withConstraints = zoomState as unknown as { |
| 2646 | setSpanConstraints?: (minSpan: number, maxSpan: number) => void; |
| 2647 | }; |
| 2648 | withConstraints.setSpanConstraints?.(constraints.minSpan, constraints.maxSpan); |
| 2649 | |
| 2650 | if ( |
| 2651 | lastOptionsZoomRange == null || |
| 2652 | lastOptionsZoomRange.start !== cfg.start || |
| 2653 | lastOptionsZoomRange.end !== cfg.end |
| 2654 | ) { |
| 2655 | // Only apply option-provided start/end when: |
| 2656 | // - zoom is first created, or |
| 2657 | // - start/end actually changed in options |
| 2658 | zoomState.setRange(cfg.start, cfg.end); |
| 2659 | lastOptionsZoomRange = { start: cfg.start, end: cfg.end }; |
| 2660 | } |
| 2661 | } |
| 2662 | |
| 2663 | // Only enable inside zoom handler when `{ type: 'inside' }` exists. |
| 2664 | // Requires event manager (HTMLCanvasElement only). |
| 2665 | if (cfg.hasInside && eventManager) { |
| 2666 | if (!insideZoom) { |
| 2667 | insideZoom = createInsideZoom(eventManager, zoomState); |
| 2668 | insideZoom.enable(); |
| 2669 | } |
| 2670 | } else { |
| 2671 | insideZoom?.dispose(); |
| 2672 | insideZoom = null; |
| 2673 | } |
no test coverage detected