import { IconButton } from '@mui/material' import { CheckBoxOutlined } from '@mui/icons-material' import { useCallback, useEffect } from 'react' import type { LockSelectionProps, LockSelectionState } from './types' import { actionButtonStyles } from '../shared/styles' import { Tooltip } from '../../../components' import { widgetStoreActions } from '../../stores/widget-store' import { useWidgetSelector } from '../../stores/use-widget-selector' import type { EchartWidgetData } from '../../echart/types' export const LOCK_SELECTION_TOOL_ID = 'lock-selection' /** * Widget action button to lock the current selection. * * When locked, the widget data is filtered to only show the selected items. * The button is only visible when there are selected items. * Registers a transformation tool in the widget pipeline when mounted. * * @example * ```tsx * * ``` */ export function LockSelection({ id, selectedItems, order = 30, labels, Icon, IconButtonProps, }: LockSelectionProps) { const { storeIsLocked } = useWidgetSelector(id, (w) => ({ storeIsLocked: (w as LockSelectionState | undefined)?.isLocked, })) const isLocked = storeIsLocked ?? false // Register tool once — fn reads lockedItems from the store at execution time useEffect(() => { widgetStoreActions.registerTool(id, { id: LOCK_SELECTION_TOOL_ID, order, enabled: false, fn: (data) => { const widget = widgetStoreActions.getWidget(id) const items = widget?.lockedItems ?? [] if (items.length === 0) return data return filterDataByLockedItems(data as EchartWidgetData, items) }, }) return () => widgetStoreActions.unregisterTool(id, LOCK_SELECTION_TOOL_ID) }, [id, order]) // Sync enabled from store — lightweight, no re-registration. // When selectedItems is empty (e.g., remount with no active selection), // disable the tool and clear stale lock state. useEffect(() => { if (isLocked && selectedItems.length === 0) { widgetStoreActions.setWidget(id, { isLocked: false, lockedItems: [] }) return } widgetStoreActions.setToolEnabled(id, LOCK_SELECTION_TOOL_ID, isLocked) }, [id, isLocked, selectedItems.length]) const handleToggle = useCallback(() => { if (isLocked) { // Unlock: clear locked items and disable tool widgetStoreActions.setWidget(id, { isLocked: false, lockedItems: [], }) } else { // Lock: save selected items and enable tool widgetStoreActions.setWidget(id, { isLocked: true, lockedItems: selectedItems, }) } }, [id, isLocked, selectedItems]) // Don't render if no selections if (selectedItems.length === 0) { return null } const tooltipLabel = isLocked ? (labels?.unlock ?? 'Unlock selection') : (labels?.lock ?? 'Lock selection') const ariaLabel = labels?.ariaLabel ?? tooltipLabel return ( {Icon ?? } ) } /** * Filters widget data to only include items with names matching the locked items. */ function filterDataByLockedItems( data: EchartWidgetData, lockedItems: string[], ): EchartWidgetData { return data.map((series) => series.filter((item) => { const name = item.name return typeof name === 'string' && lockedItems.includes(name) }), ) }