import React, { ReactElement, useCallback, useEffect, useRef, useState, } from 'react'; import { Box, IconButton, ListItemAction, Popover, Text, TextButton, Thumbnail, } from '@wix/design-system'; import { ChevronLeft, DataCollection, MoreSmall, } from '@wix/wix-ui-icons-common'; import { useWixPatternsContainer } from '@wix/bex-core/react'; import { ViewTypeState } from '../../state/ViewTypeState'; import { layoutOptions, layoutConfig, } from '../TableGridSwitchButton/layoutConfig'; type Translate = ReturnType['translate']; type Focusable = { focus: () => void }; export interface ToolbarOverflowPrimaryItem { text: string; icon: ReactElement; onClick: () => void; dataHook?: string; } export interface ToolbarOverflowSecondaryItem { text: string; prefixIcon: ReactElement; onClick: () => void; dataHook?: string; } export interface ToolbarOverflowLayoutSwitchConfig { viewTypeState: ViewTypeState; } type ActiveView = 'main' | 'layout'; export interface ToolbarOverflowMenuProps { primaryItems: ToolbarOverflowPrimaryItem[]; secondaryItems: ToolbarOverflowSecondaryItem[]; layoutSwitchConfig?: ToolbarOverflowLayoutSwitchConfig; } export function ToolbarOverflowMenu({ primaryItems, secondaryItems, layoutSwitchConfig, }: ToolbarOverflowMenuProps) { const [shown, setShown] = useState(false); const [activeView, setActiveView] = useState('main'); const triggerRef = useRef(null); const focusTargetRef = useRef<'first' | 'layoutSwitch' | null>(null); const { translate: t } = useWixPatternsContainer(); const shouldFocusTriggerOnCloseRef = useRef(false); const close = useCallback(() => { setShown(false); setActiveView('main'); }, []); const closeAndFocusTrigger = useCallback(() => { shouldFocusTriggerOnCloseRef.current = true; close(); }, [close]); useEffect(() => { if (!shown && shouldFocusTriggerOnCloseRef.current) { shouldFocusTriggerOnCloseRef.current = false; setTimeout(() => { triggerRef.current?.focus(); }); } }, [shown]); const hasItems = primaryItems.length > 0 || secondaryItems.length > 0 || !!layoutSwitchConfig; if (!hasItems) { return null; } return ( { setShown((prev) => { if (!prev) { focusTargetRef.current = 'first'; } return !prev; }); }} > {activeView === 'main' ? ( setActiveView('layout')} focusTarget={focusTargetRef} t={t} /> ) : ( { focusTargetRef.current = 'layoutSwitch'; setActiveView('main'); }} onSelect={closeAndFocusTrigger} t={t} /> )} ); } function MainView({ primaryItems, secondaryItems, layoutSwitchConfig, onItemClick, onLayoutSwitchClick, focusTarget, t, }: { primaryItems: ToolbarOverflowPrimaryItem[]; secondaryItems: ToolbarOverflowSecondaryItem[]; layoutSwitchConfig?: ToolbarOverflowLayoutSwitchConfig; onItemClick: () => void; onLayoutSwitchClick: () => void; focusTarget: React.MutableRefObject<'first' | 'layoutSwitch' | null>; t: Translate; }) { const firstItemRef = useRef(null); const layoutSwitchRef = useRef(null); useEffect(() => { const target = focusTarget.current; focusTarget.current = null; if (target === 'first') { firstItemRef.current?.focus(); } else if (target === 'layoutSwitch') { layoutSwitchRef.current?.focus(); } }); const isFirstItemPrimary = primaryItems.length > 0; return ( <> {primaryItems.length > 0 && ( {primaryItems.map((item, index) => ( { item.onClick(); onItemClick(); }} dataHook={item.dataHook} title={ {item.text} } width="100%" /> ))} )} {layoutSwitchConfig && ( { layoutSwitchRef.current = r; if (!firstItemRef.current) { firstItemRef.current = r; } } : layoutSwitchRef } size="medium" dataHook="overflow-layout-switch" prefixIcon={} title={t('cairo.table.layout.switchLayout')} onClick={() => { layoutSwitchConfig.viewTypeState.reportLayoutSwitch(); onLayoutSwitchClick(); }} /> )} {secondaryItems.map((item, index) => ( { item.onClick(); onItemClick(); }} prefixIcon={item.prefixIcon} dataHook={item.dataHook} /> ))} ); } function LayoutSwitchView({ config, onBack, onSelect, t, }: { config: ToolbarOverflowLayoutSwitchConfig; onBack: () => void; onSelect: () => void; t: Translate; }) { const { viewTypeState } = config; const activeOptionRef = useRef(null); useEffect(() => { activeOptionRef.current?.focus(); }, []); return ( <> } onClick={onBack} > {t('cairo.import.back')} {layoutOptions.map((option, index) => { const isActive = viewTypeState.viewType === option; return ( { viewTypeState.reportLayoutOptionClicked(option, index); if (!isActive) { viewTypeState.changeViewType(option); } onSelect(); }} /> ); })} ); }