import { GeoShapeGeoStyle, preventDefault, track, useEditor, useValue } from '@bigbluebutton/editor' import classNames from 'classnames' import React, { memo } from 'react' import { useBreakpoint } from '../../hooks/useBreakpoint' import { useReadonly } from '../../hooks/useReadonly' import { TLUiToolbarItem, useToolbarSchema } from '../../hooks/useToolbarSchema' import { TLUiToolItem } from '../../hooks/useTools' import { useTranslation } from '../../hooks/useTranslation/useTranslation' import { ActionsMenu } from '../ActionsMenu' import { MobileStylePanel } from '../MobileStylePanel' import { Button } from '../primitives/Button' import * as M from '../primitives/DropdownMenu' import { kbdStr } from '../primitives/shared' import { ToggleToolLockedButton } from './ToggleToolLockedButton' /** @public */ export const Toolbar = memo(function Toolbar() { const editor = useEditor() const msg = useTranslation() const breakpoint = useBreakpoint() const rMostRecentlyActiveDropdownItem = React.useRef(undefined) const isReadonly = useReadonly() const toolbarItems = useToolbarSchema() const laserTool = toolbarItems.find((item) => item.toolItem.id === 'laser') const activeToolId = useValue('current tool id', () => editor.getCurrentToolId(), [editor]) const geoState = useValue( 'geo', () => editor.getSharedStyles().getAsKnownValue(GeoShapeGeoStyle), [editor] ) const showEditingTools = !isReadonly const getTitle = (item: TLUiToolItem) => item.label ? `${msg(item.label)} ${item.kbd ? kbdStr(item.kbd) : ''}` : '' const activeTLUiToolbarItem = toolbarItems.find((item) => { return isActiveTLUiToolItem(item.toolItem, activeToolId, geoState) }) const { itemsInPanel, itemsInDropdown, dropdownFirstItem } = React.useMemo(() => { const itemsInPanel: TLUiToolbarItem[] = [] const itemsInDropdown: TLUiToolbarItem[] = [] let dropdownFirstItem: TLUiToolbarItem | undefined const overflowIndex = Math.min(9, 6 + breakpoint) for (let i = 4; i < toolbarItems.length; i++) { const item = toolbarItems[i] if (i < overflowIndex) { // Items below the overflow index will always be in the panel itemsInPanel.push(item) } else { // Items above will be in the dropdown menu unless the item // is active (or was the most recently selected active item) if (item === activeTLUiToolbarItem) { // If the dropdown item is active, make it the dropdownFirstItem dropdownFirstItem = item } // Otherwise, add it to the items in dropdown menu itemsInDropdown.push(item) } } if (dropdownFirstItem) { // noop } else { // If we don't have a currently active dropdown item, use the most // recently active dropdown item as the current dropdown first item. // If haven't ever had a most recently active dropdown item, then // make the first item in the dropdown menu the most recently // active dropdown item. if (!rMostRecentlyActiveDropdownItem.current) { rMostRecentlyActiveDropdownItem.current = itemsInDropdown[0] } dropdownFirstItem = rMostRecentlyActiveDropdownItem.current // If the most recently active dropdown item is no longer in the // dropdown (because the breakpoint has changed) then make the // first item in the dropdown menu the most recently active // dropdown item. if (!itemsInDropdown.includes(dropdownFirstItem)) { dropdownFirstItem = itemsInDropdown[0] } } // We want this ref set to remember which item from the current // set of dropdown items was most recently active rMostRecentlyActiveDropdownItem.current = dropdownFirstItem if (itemsInDropdown.length <= 2) { itemsInPanel.push(...itemsInDropdown) itemsInDropdown.length = 0 } return { itemsInPanel, itemsInDropdown, dropdownFirstItem } }, [toolbarItems, activeTLUiToolbarItem, breakpoint]) return (
{!isReadonly && (
{/* {breakpoint < 6 && !(activeToolId === 'hand' || activeToolId === 'zoom') && (
)} */}
)}
{/* Select / Hand */} {toolbarItems.slice(0, 2).map(({ toolItem }) => { return ( ) })} {isReadonly && laserTool && ( )} {showEditingTools && ( <> {/* Draw / Eraser */} {toolbarItems.slice(2, 4).map(({ toolItem }) => ( ))} {/* Everything Else */} {itemsInPanel.map(({ toolItem }) => ( ))} {/* Overflowing Shapes */} {itemsInDropdown.length ? ( <> {/* Last selected (or first) item from the overflow */} {/* The dropdown to select everything else */}
{breakpoint < 5 && !isReadonly && (
)}
) }) const OverflowToolsContent = track(function OverflowToolsContent({ toolbarItems, }: { toolbarItems: TLUiToolbarItem[] }) { const msg = useTranslation() return (
{toolbarItems.map(({ toolItem: { id, meta, kbd, label, onSelect, icon } }) => { return ( onSelect('toolbar')} title={label ? `${msg(label)} ${kbd ? kbdStr(kbd) : ''}` : ''} icon={icon} /> ) })}
) }) function ToolbarButton({ item, title, isSelected, }: { item: TLUiToolItem title: string isSelected: boolean }) { return (