Improves performance issue caused by @radix-ui/use-direction

This commit is contained in:
Steve Ruiz 2021-06-27 20:19:57 +01:00
parent 1e8cba347d
commit 9f16f886ea
11 changed files with 60 additions and 51 deletions

View file

@ -96,7 +96,7 @@ export default function ContextMenu({
const hasThreeOrMore = selectedShapeIds.length > 2 const hasThreeOrMore = selectedShapeIds.length > 2
return ( return (
<_ContextMenu.Root> <_ContextMenu.Root dir="ltr">
<_ContextMenu.Trigger>{children}</_ContextMenu.Trigger> <_ContextMenu.Trigger>{children}</_ContextMenu.Trigger>
<StyledContent ref={rContent} isMobile={isMobile()}> <StyledContent ref={rContent} isMobile={isMobile()}>
{selectedShapeIds.length ? ( {selectedShapeIds.length ? (
@ -342,7 +342,7 @@ function SubMenu({
children: React.ReactNode children: React.ReactNode
}) { }) {
return ( return (
<_ContextMenu.Root> <_ContextMenu.Root dir="ltr">
<_ContextMenu.TriggerItem <_ContextMenu.TriggerItem
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}
@ -367,7 +367,7 @@ function AlignDistributeSubMenu({
hasThreeOrMore: boolean hasThreeOrMore: boolean
}) { }) {
return ( return (
<_ContextMenu.Root> <_ContextMenu.Root dir="ltr">
<_ContextMenu.TriggerItem <_ContextMenu.TriggerItem
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}
@ -451,7 +451,7 @@ function MoveToPageMenu() {
if (sorted.length === 0) return null if (sorted.length === 0) return null
return ( return (
<_ContextMenu.Root> <_ContextMenu.Root dir="ltr">
<_ContextMenu.TriggerItem <_ContextMenu.TriggerItem
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}

View file

@ -3,8 +3,8 @@ import { useSelector } from 'state'
import styled from 'styles' import styled from 'styles'
import { getShapeUtils } from 'state/shape-utils' import { getShapeUtils } from 'state/shape-utils'
import { getPage, getSelectedIds, isMobile } from 'utils' import { getPage, getSelectedIds, isMobile } from 'utils'
import { Shape as _Shape } from 'types'
import useShapeEvents from 'hooks/useShapeEvents' import useShapeEvents from 'hooks/useShapeEvents'
import { Shape as _Shape } from 'types'
import vec from 'utils/vec' import vec from 'utils/vec'
import { getShapeStyle } from 'state/shape-styles' import { getShapeStyle } from 'state/shape-styles'
@ -83,7 +83,7 @@ function Shape({ id, isSelecting, parentPoint }: ShapeProps): JSX.Element {
as="use" as="use"
href={'#' + id} href={'#' + id}
strokeWidth={+style.strokeWidth + 5} strokeWidth={+style.strokeWidth + 5}
variant={getShapeUtils(shape).canStyleFill ? 'filled' : 'hollow'} variant={shapeUtils.canStyleFill ? 'filled' : 'hollow'}
/> />
)} )}
</> </>
@ -93,13 +93,7 @@ function Shape({ id, isSelecting, parentPoint }: ShapeProps): JSX.Element {
(isForeignObject ? ( (isForeignObject ? (
shapeUtils.render(shape, { isEditing, ref: rFocusable }) shapeUtils.render(shape, { isEditing, ref: rFocusable })
) : ( ) : (
<RealShape <RealShape id={id} isParent={isParent} shape={shape} />
isParent={isParent}
id={id}
shape={shape}
style={style}
isEditing={isEditing}
/>
))} ))}
{isParent && {isParent &&
@ -117,10 +111,8 @@ function Shape({ id, isSelecting, parentPoint }: ShapeProps): JSX.Element {
interface RealShapeProps { interface RealShapeProps {
id: string id: string
style: Partial<React.SVGProps<SVGUseElement>>
isParent: boolean
shape: _Shape shape: _Shape
isEditing: boolean isParent: boolean
} }
const RealShape = memo(function RealShape({ id, isParent }: RealShapeProps) { const RealShape = memo(function RealShape({ id, isParent }: RealShapeProps) {

View file

@ -130,6 +130,7 @@ export default function CodePanel(): JSX.Element {
return ( return (
<Panel.Root <Panel.Root
dir="ltr"
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}
data-bp-desktop data-bp-desktop
ref={rContainer} ref={rContainer}

View file

@ -18,6 +18,7 @@ export default function ControlPanel(): JSX.Element {
return ( return (
<Panel.Root <Panel.Root
dir="ltr"
data-bp-desktop data-bp-desktop
ref={rContainer} ref={rContainer}
isOpen={isOpen} isOpen={isOpen}

View file

@ -29,6 +29,7 @@ export default function PagePanel(): JSX.Element {
return ( return (
<DropdownMenu.Root <DropdownMenu.Root
dir="ltr"
open={isOpen} open={isOpen}
onOpenChange={(isOpen) => { onOpenChange={(isOpen) => {
if (rIsOpen.current !== isOpen) { if (rIsOpen.current !== isOpen) {
@ -36,7 +37,7 @@ export default function PagePanel(): JSX.Element {
} }
}} }}
> >
<PanelRoot> <PanelRoot dir="ltr">
<DropdownMenu.Trigger <DropdownMenu.Trigger
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}
@ -55,7 +56,7 @@ export default function PagePanel(): JSX.Element {
}} }}
> >
{sorted.map(({ id, name }) => ( {sorted.map(({ id, name }) => (
<ContextMenu.Root key={id}> <ContextMenu.Root dir="ltr" key={id}>
<ContextMenu.Trigger> <ContextMenu.Trigger>
<StyledRadioItem <StyledRadioItem
key={id} key={id}

View file

@ -12,7 +12,7 @@ interface Props {
export default function ColorPicker({ color, onChange }: Props): JSX.Element { export default function ColorPicker({ color, onChange }: Props): JSX.Element {
return ( return (
<DropdownMenu.Root> <DropdownMenu.Root dir="ltr">
<DropdownMenu.Trigger <DropdownMenu.Trigger
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}

View file

@ -15,6 +15,7 @@ export default function IsFilledPicker({
}: Props): JSX.Element { }: Props): JSX.Element {
return ( return (
<Checkbox.Root <Checkbox.Root
dir="ltr"
as={RowButton} as={RowButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}
checked={isFilled} checked={isFilled}

View file

@ -10,7 +10,7 @@ export default function QuickColorSelect(): JSX.Element {
const color = useSelector((s) => s.values.selectedStyle.color) const color = useSelector((s) => s.values.selectedStyle.color)
return ( return (
<DropdownMenu.Root> <DropdownMenu.Root dir="ltr">
<DropdownMenu.Trigger <DropdownMenu.Trigger
as={IconButton} as={IconButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}

View file

@ -21,7 +21,7 @@ export default function QuickdashSelect(): JSX.Element {
const dash = useSelector((s) => s.values.selectedStyle.dash) const dash = useSelector((s) => s.values.selectedStyle.dash)
return ( return (
<DropdownMenu.Root> <DropdownMenu.Root dir="ltr">
<DropdownMenu.Trigger <DropdownMenu.Trigger
as={IconButton} as={IconButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}

View file

@ -16,7 +16,7 @@ export default function QuickSizeSelect(): JSX.Element {
const size = useSelector((s) => s.values.selectedStyle.size) const size = useSelector((s) => s.values.selectedStyle.size)
return ( return (
<DropdownMenu.Root> <DropdownMenu.Root dir="ltr">
<DropdownMenu.Trigger <DropdownMenu.Trigger
as={IconButton} as={IconButton}
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={{ '@initial': 'mobile', '@sm': 'small' }}

View file

@ -36,12 +36,28 @@ import QuickSizeSelect from './quick-size-select'
import QuickdashSelect from './quick-dash-select' import QuickdashSelect from './quick-dash-select'
import Tooltip from 'components/tooltip' import Tooltip from 'components/tooltip'
const breakpoints = { '@initial': 'mobile', '@sm': 'small' } as any
const handleStylePanelOpen = () => state.send('TOGGLED_STYLE_PANEL_OPEN')
const handleColorChange = (color) => state.send('CHANGED_STYLE', { color })
const handleRotateCcw = () => () => state.send('ROTATED_CCW')
const handleIsFilledChange = (dash) => state.send('CHANGED_STYLE', { dash })
const handleDuplicate = () => state.send('DUPLICATED')
const handleHide = () => state.send('TOGGLED_SHAPE_HIDE')
const handleLock = () => state.send('TOGGLED_SHAPE_LOCK')
const handleAspectLock = () => state.send('TOGGLED_SHAPE_ASPECT_LOCK')
const handleMoveToBack = () => state.send('MOVED', { type: MoveType.ToBack })
const handleMoveBackward = () =>
state.send('MOVED', { type: MoveType.Backward })
const handleMoveForward = () => state.send('MOVED', { type: MoveType.Forward })
const handleMoveToFront = () => state.send('MOVED', { type: MoveType.ToFront })
const handleDelete = () => state.send('DELETED')
export default function StylePanel(): JSX.Element { export default function StylePanel(): JSX.Element {
const rContainer = useRef<HTMLDivElement>(null) const rContainer = useRef<HTMLDivElement>(null)
const isOpen = useSelector((s) => s.data.settings.isStyleOpen) const isOpen = useSelector((s) => s.data.settings.isStyleOpen)
return ( return (
<StylePanelRoot ref={rContainer} isOpen={isOpen}> <StylePanelRoot dir="ltr" ref={rContainer} isOpen={isOpen}>
{isOpen ? ( {isOpen ? (
<SelectedShapeStyles /> <SelectedShapeStyles />
) : ( ) : (
@ -50,10 +66,10 @@ export default function StylePanel(): JSX.Element {
<QuickSizeSelect /> <QuickSizeSelect />
<QuickdashSelect /> <QuickdashSelect />
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
title="Style" title="Style"
size="small" size="small"
onClick={() => state.send('TOGGLED_STYLE_PANEL_OPEN')} onClick={handleStylePanelOpen}
> >
<Tooltip label="More"> <Tooltip label="More">
<ChevronDown /> <ChevronDown />
@ -99,21 +115,18 @@ function SelectedShapeStyles(): JSX.Element {
<Panel.Header side="right"> <Panel.Header side="right">
<h3>Style</h3> <h3>Style</h3>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
size="small" size="small"
onClick={() => state.send('TOGGLED_STYLE_PANEL_OPEN')} onClick={handleStylePanelOpen}
> >
<X /> <X />
</IconButton> </IconButton>
</Panel.Header> </Panel.Header>
<Content> <Content>
<ColorPicker <ColorPicker color={commonStyle.color} onChange={handleColorChange} />
color={commonStyle.color}
onChange={(color) => state.send('CHANGED_STYLE', { color })}
/>
<IsFilledPicker <IsFilledPicker
isFilled={commonStyle.isFilled} isFilled={commonStyle.isFilled}
onChange={(isFilled) => state.send('CHANGED_STYLE', { isFilled })} onChange={handleIsFilledChange}
/> />
<Row> <Row>
<label htmlFor="size">Size</label> <label htmlFor="size">Size</label>
@ -125,10 +138,10 @@ function SelectedShapeStyles(): JSX.Element {
</Row> </Row>
<ButtonsRow> <ButtonsRow>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('DUPLICATED')} onClick={handleDuplicate}
> >
<Tooltip label="Duplicate"> <Tooltip label="Duplicate">
<CopyIcon /> <CopyIcon />
@ -138,7 +151,7 @@ function SelectedShapeStyles(): JSX.Element {
<IconButton <IconButton
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('ROTATED_CCW')} onClick={handleRotateCcw}
> >
<Tooltip label="Rotate"> <Tooltip label="Rotate">
<RotateCounterClockwiseIcon /> <RotateCounterClockwiseIcon />
@ -146,10 +159,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('TOGGLED_SHAPE_HIDE')} onClick={handleHide}
> >
<Tooltip label="Toogle Hidden"> <Tooltip label="Toogle Hidden">
{isAllHidden ? <EyeClosedIcon /> : <EyeOpenIcon />} {isAllHidden ? <EyeClosedIcon /> : <EyeOpenIcon />}
@ -157,10 +170,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('TOGGLED_SHAPE_LOCK')} onClick={handleLock}
> >
<Tooltip label="Toogle Locked"> <Tooltip label="Toogle Locked">
{isAllLocked ? <LockClosedIcon /> : <LockOpen1Icon />} {isAllLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
@ -168,10 +181,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('TOGGLED_SHAPE_ASPECT_LOCK')} onClick={handleAspectLock}
> >
<Tooltip label="Toogle Aspect Ratio Lock"> <Tooltip label="Toogle Aspect Ratio Lock">
{isAllAspectLocked ? <AspectRatioIcon /> : <BoxIcon />} {isAllAspectLocked ? <AspectRatioIcon /> : <BoxIcon />}
@ -180,10 +193,10 @@ function SelectedShapeStyles(): JSX.Element {
</ButtonsRow> </ButtonsRow>
<ButtonsRow> <ButtonsRow>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('MOVED', { type: MoveType.ToBack })} onClick={handleMoveToBack}
> >
<Tooltip label="Move to Back"> <Tooltip label="Move to Back">
<PinBottomIcon /> <PinBottomIcon />
@ -191,10 +204,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('MOVED', { type: MoveType.Backward })} onClick={handleMoveBackward}
> >
<Tooltip label="Move Backward"> <Tooltip label="Move Backward">
<ArrowDownIcon /> <ArrowDownIcon />
@ -202,10 +215,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('MOVED', { type: MoveType.Forward })} onClick={handleMoveForward}
> >
<Tooltip label="Move Forward"> <Tooltip label="Move Forward">
<ArrowUpIcon /> <ArrowUpIcon />
@ -213,10 +226,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('MOVED', { type: MoveType.ToFront })} onClick={handleMoveToFront}
> >
<Tooltip label="More to Front"> <Tooltip label="More to Front">
<PinTopIcon /> <PinTopIcon />
@ -224,10 +237,10 @@ function SelectedShapeStyles(): JSX.Element {
</IconButton> </IconButton>
<IconButton <IconButton
bp={{ '@initial': 'mobile', '@sm': 'small' }} bp={breakpoints}
disabled={!hasSelection} disabled={!hasSelection}
size="small" size="small"
onClick={() => state.send('DELETED')} onClick={handleDelete}
> >
<Tooltip label="Delete"> <Tooltip label="Delete">
<Trash2 size="15" /> <Trash2 size="15" />