Starts on menu, page panel
This commit is contained in:
parent
72f680ce65
commit
9c45e0a5a5
46 changed files with 811 additions and 35 deletions
|
@ -5,7 +5,7 @@ import { Binding } from './binding'
|
|||
jest.spyOn(console, 'error').mockImplementation(() => void null)
|
||||
|
||||
describe('binding', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(<Binding point={[0, 0]} type={'anchor'} />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { renderWithSvg } from '+test'
|
|||
import { Bounds } from './bounds'
|
||||
|
||||
describe('bounds', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(
|
||||
<Bounds
|
||||
zoom={1}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { renderWithSvg } from '+test'
|
|||
import { Brush } from './brush'
|
||||
|
||||
describe('brush', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(<Brush />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mockDocument, renderWithContext } from '+test'
|
|||
import { Canvas } from './canvas'
|
||||
|
||||
describe('page', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(
|
||||
<Canvas
|
||||
page={mockDocument.page}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { renderWithSvg } from '+test'
|
|||
import { Defs } from './defs'
|
||||
|
||||
describe('defs', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(<Defs zoom={1} />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { renderWithContext } from '+test'
|
|||
import { ErrorFallback } from './error-fallback'
|
||||
|
||||
describe('error fallback', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<ErrorFallback error={new Error()} resetErrorBoundary={() => void null} />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mockUtils, renderWithContext } from '+test'
|
|||
import { Handles } from './handles'
|
||||
|
||||
describe('handles', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<Handles zoom={1} shape={mockUtils.box.create({})} />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mockDocument, renderWithContext } from '+test'
|
|||
import { Page } from './page'
|
||||
|
||||
describe('page', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(
|
||||
<Page
|
||||
page={mockDocument.page}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { render } from '@testing-library/react'
|
|||
import { Renderer } from './renderer'
|
||||
|
||||
describe('context menu', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
render(
|
||||
<Renderer
|
||||
shapeUtils={mockUtils}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mockUtils, renderWithSvg } from '+test'
|
|||
import { ShapeIndicator } from './shape-indicator'
|
||||
|
||||
describe('shape indicator', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(<ShapeIndicator shape={mockUtils.box.create({})} variant={'selected'} />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { mockUtils, renderWithSvg } from '+test'
|
|||
import { Shape } from './shape'
|
||||
|
||||
describe('handles', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithSvg(
|
||||
<Shape
|
||||
shape={mockUtils.box.create({})}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
"react-dom": "^17.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-alert-dialog": "^0.0.20",
|
||||
"@radix-ui/react-checkbox": "^0.0.16",
|
||||
"@radix-ui/react-context-menu": "^0.0.23",
|
||||
"@radix-ui/react-dropdown-menu": "^0.0.22",
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ContextMenu } from './context-menu'
|
|||
import { renderWithContext } from '~test'
|
||||
|
||||
describe('context menu', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(
|
||||
<ContextMenu>
|
||||
<div>Hello</div>
|
||||
|
|
0
packages/tldraw/src/components/menu/index.ts
Normal file
0
packages/tldraw/src/components/menu/index.ts
Normal file
9
packages/tldraw/src/components/menu/menu.test.tsx
Normal file
9
packages/tldraw/src/components/menu/menu.test.tsx
Normal file
|
@ -0,0 +1,9 @@
|
|||
import * as React from 'react'
|
||||
import { Menu } from './menu'
|
||||
import { mockDocument, renderWithContext } from '~test'
|
||||
|
||||
describe('menu menu', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<Menu />)
|
||||
})
|
||||
})
|
126
packages/tldraw/src/components/menu/menu.tsx
Normal file
126
packages/tldraw/src/components/menu/menu.tsx
Normal file
|
@ -0,0 +1,126 @@
|
|||
import * as React from 'react'
|
||||
import { ExitIcon, HamburgerMenuIcon } from '@radix-ui/react-icons'
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import {
|
||||
FloatingContainer,
|
||||
DropdownMenuRoot,
|
||||
MenuContent,
|
||||
IconButton,
|
||||
breakpoints,
|
||||
DropdownMenuButton,
|
||||
DropdownMenuSubMenu,
|
||||
DropdownMenuDivider,
|
||||
DropdownMenuCheckboxItem,
|
||||
IconWrapper,
|
||||
Kbd,
|
||||
} from '~components/shared'
|
||||
import { useTLDrawContext, useTheme } from '~hooks'
|
||||
import type { Data } from '~types'
|
||||
|
||||
export const Menu = React.memo(() => {
|
||||
const { tlstate } = useTLDrawContext()
|
||||
|
||||
const handleNew = React.useCallback(() => {
|
||||
tlstate.newProject()
|
||||
}, [tlstate])
|
||||
|
||||
const handleSave = React.useCallback(() => {
|
||||
tlstate.saveProject()
|
||||
}, [tlstate])
|
||||
|
||||
const handleLoad = React.useCallback(() => {
|
||||
tlstate.loadProject()
|
||||
}, [tlstate])
|
||||
|
||||
const toggleDebugMode = React.useCallback(() => {
|
||||
tlstate.toggleDebugMode()
|
||||
}, [tlstate])
|
||||
|
||||
const handleSignOut = React.useCallback(() => {
|
||||
tlstate.signOut()
|
||||
}, [tlstate])
|
||||
|
||||
return (
|
||||
<FloatingContainer>
|
||||
<DropdownMenuRoot>
|
||||
<DropdownMenu.Trigger as={IconButton} bp={breakpoints}>
|
||||
<HamburgerMenuIcon />
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content as={MenuContent} sideOffset={8} align="end">
|
||||
<DropdownMenuButton onSelect={handleNew} disabled={true}>
|
||||
<span>New Project</span>
|
||||
<Kbd variant="menu">#N</Kbd>
|
||||
</DropdownMenuButton>
|
||||
<DropdownMenuDivider />
|
||||
<DropdownMenuButton onSelect={handleLoad}>
|
||||
<span>Open...</span>
|
||||
<Kbd variant="menu">#L</Kbd>
|
||||
</DropdownMenuButton>
|
||||
<RecentFiles />
|
||||
<DropdownMenuDivider />
|
||||
<DropdownMenuButton onSelect={handleSave}>
|
||||
<span>Save</span>
|
||||
<Kbd variant="menu">#S</Kbd>
|
||||
</DropdownMenuButton>
|
||||
<DropdownMenuButton onSelect={handleSave}>
|
||||
<span>Save As...</span>
|
||||
<Kbd variant="menu">⇧#S</Kbd>
|
||||
</DropdownMenuButton>
|
||||
<DropdownMenuDivider />
|
||||
<Preferences />
|
||||
<DropdownMenuDivider />
|
||||
<DropdownMenuButton onSelect={handleSignOut}>
|
||||
<span>Sign Out</span>
|
||||
<IconWrapper size="small">
|
||||
<ExitIcon />
|
||||
</IconWrapper>
|
||||
</DropdownMenuButton>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenuRoot>
|
||||
</FloatingContainer>
|
||||
)
|
||||
})
|
||||
|
||||
function RecentFiles() {
|
||||
return (
|
||||
<DropdownMenuSubMenu label="Open Recent..." disabled={true}>
|
||||
<DropdownMenuButton>
|
||||
<span>Project A</span>
|
||||
</DropdownMenuButton>
|
||||
<DropdownMenuButton>
|
||||
<span>Project B</span>
|
||||
</DropdownMenuButton>
|
||||
<DropdownMenuButton>
|
||||
<span>Project C</span>
|
||||
</DropdownMenuButton>
|
||||
</DropdownMenuSubMenu>
|
||||
)
|
||||
}
|
||||
|
||||
const isDebugModeSelector = (s: Data) => s.settings.isDebugMode
|
||||
|
||||
function Preferences() {
|
||||
const { tlstate, useSelector } = useTLDrawContext()
|
||||
const { theme, setTheme } = useTheme()
|
||||
|
||||
const isDebugMode = useSelector(isDebugModeSelector)
|
||||
const isDarkMode = theme === 'dark'
|
||||
|
||||
const toggleDebugMode = React.useCallback(() => {
|
||||
tlstate.toggleDebugMode()
|
||||
}, [tlstate])
|
||||
|
||||
return (
|
||||
<DropdownMenuSubMenu label="Preferences">
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={isDarkMode}
|
||||
onCheckedChange={() => setTheme(isDarkMode ? 'light' : 'dark')}
|
||||
>
|
||||
<span>Dark Mode</span>
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem checked={isDebugMode} onCheckedChange={toggleDebugMode}>
|
||||
<span>Debug Mode</span>
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuSubMenu>
|
||||
)
|
||||
}
|
20
packages/tldraw/src/components/menu/preferences.tsx
Normal file
20
packages/tldraw/src/components/menu/preferences.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
export function Preferences() {
|
||||
const { theme, setTheme } = useTheme()
|
||||
|
||||
const isDebugMode = useSelector((s) => s.data.settings.isDebugMode)
|
||||
const isDarkMode = theme === 'dark'
|
||||
|
||||
return (
|
||||
<DropdownMenuSubMenu label="Preferences">
|
||||
<DropdownMenuCheckboxItem
|
||||
checked={isDarkMode}
|
||||
onCheckedChange={() => setTheme(isDarkMode ? 'light' : 'dark')}
|
||||
>
|
||||
<span>Dark Mode</span>
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem checked={isDebugMode} onCheckedChange={toggleDebugMode}>
|
||||
<span>Debug Mode</span>
|
||||
</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuSubMenu>
|
||||
)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './page-options-dialog'
|
|
@ -0,0 +1,9 @@
|
|||
import * as React from 'react'
|
||||
import { PageOptionsDialog } from './page-options-dialog'
|
||||
import { mockDocument, renderWithContext } from '~test'
|
||||
|
||||
describe('page options dialog', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<PageOptionsDialog page={mockDocument.pages.page} />)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,122 @@
|
|||
import * as React from 'react'
|
||||
import * as Dialog from '@radix-ui/react-alert-dialog'
|
||||
import { MixerVerticalIcon } from '@radix-ui/react-icons'
|
||||
import {
|
||||
breakpoints,
|
||||
IconButton,
|
||||
DialogOverlay,
|
||||
DialogContent,
|
||||
RowButton,
|
||||
MenuTextInput,
|
||||
DialogInputWrapper,
|
||||
Divider,
|
||||
} from '~components/shared'
|
||||
import type { Data, TLDrawPage } from '~types'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
|
||||
const canDeleteSelector = (s: Data) => {
|
||||
// TODO: Include all pages
|
||||
return [s.page].length <= 1
|
||||
}
|
||||
|
||||
export function PageOptionsDialog({ page }: { page: TLDrawPage }): JSX.Element {
|
||||
const { tlstate, useSelector } = useTLDrawContext()
|
||||
|
||||
const [isOpen, setIsOpen] = React.useState(false)
|
||||
|
||||
const canDelete = useSelector(canDeleteSelector)
|
||||
|
||||
const rInput = React.useRef<HTMLInputElement>(null)
|
||||
|
||||
const [name, setName] = React.useState(page.name || 'Page')
|
||||
|
||||
const handleNameChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(e.currentTarget.value)
|
||||
}, [])
|
||||
|
||||
const handleDuplicate = React.useCallback(() => {
|
||||
tlstate.duplicatePage(page.id)
|
||||
}, [tlstate])
|
||||
|
||||
const handleDelete = React.useCallback(() => {
|
||||
tlstate.deletePage(page.id)
|
||||
}, [tlstate])
|
||||
|
||||
const handleOpenChange = React.useCallback(
|
||||
(isOpen: boolean) => {
|
||||
setIsOpen(isOpen)
|
||||
|
||||
if (isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
if (name.length === 0) {
|
||||
tlstate.renamePage(page.id, 'Page')
|
||||
}
|
||||
},
|
||||
[tlstate, name]
|
||||
)
|
||||
|
||||
const handleSave = React.useCallback(() => {
|
||||
tlstate.renamePage(page.id, name)
|
||||
}, [tlstate, name])
|
||||
|
||||
function stopPropagation(e: React.KeyboardEvent<HTMLDivElement>) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
function handleKeydown(e: React.KeyboardEvent<HTMLDivElement>) {
|
||||
if (e.key === 'Enter') {
|
||||
handleSave()
|
||||
setIsOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isOpen) {
|
||||
setTimeout(() => {
|
||||
rInput.current?.focus()
|
||||
rInput.current?.select()
|
||||
}, 0)
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
return (
|
||||
<Dialog.Root open={isOpen} onOpenChange={handleOpenChange}>
|
||||
<Dialog.Trigger as={IconButton} bp={breakpoints} size="small" data-shy="true">
|
||||
<MixerVerticalIcon />
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Overlay as={DialogOverlay} />
|
||||
<Dialog.Content as={DialogContent} onKeyDown={stopPropagation} onKeyUp={stopPropagation}>
|
||||
<DialogInputWrapper>
|
||||
<MenuTextInput
|
||||
ref={rInput}
|
||||
value={name}
|
||||
onChange={handleNameChange}
|
||||
onKeyDown={handleKeydown}
|
||||
/>
|
||||
</DialogInputWrapper>
|
||||
<Divider />
|
||||
<Dialog.Action as={RowButton} bp={breakpoints} onClick={handleDuplicate}>
|
||||
Duplicate
|
||||
</Dialog.Action>
|
||||
<Dialog.Action
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
disabled={!canDelete}
|
||||
onClick={handleDelete}
|
||||
warn={true}
|
||||
>
|
||||
Delete
|
||||
</Dialog.Action>
|
||||
<Divider />
|
||||
<Dialog.Action as={RowButton} bp={breakpoints} onClick={handleSave}>
|
||||
Save
|
||||
</Dialog.Action>
|
||||
<Dialog.Cancel as={RowButton} bp={breakpoints}>
|
||||
Cancel
|
||||
</Dialog.Cancel>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
)
|
||||
}
|
1
packages/tldraw/src/components/page-panel/index.ts
Normal file
1
packages/tldraw/src/components/page-panel/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './page-panel'
|
|
@ -0,0 +1,9 @@
|
|||
import * as React from 'react'
|
||||
import { PagePanel } from './page-panel'
|
||||
import { renderWithContext } from '~test'
|
||||
|
||||
describe('page panel', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<PagePanel />)
|
||||
})
|
||||
})
|
110
packages/tldraw/src/components/page-panel/page-panel.tsx
Normal file
110
packages/tldraw/src/components/page-panel/page-panel.tsx
Normal file
|
@ -0,0 +1,110 @@
|
|||
import * as React from 'react'
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import { PlusIcon, CheckIcon } from '@radix-ui/react-icons'
|
||||
import {
|
||||
breakpoints,
|
||||
DropdownMenuButton,
|
||||
DropdownMenuDivider,
|
||||
RowButton,
|
||||
MenuContent,
|
||||
FloatingContainer,
|
||||
IconWrapper,
|
||||
} from '~components/shared'
|
||||
import { PageOptionsDialog } from '~components/page-options-dialog'
|
||||
import styled from '~styles'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import type { Data } from '~types'
|
||||
|
||||
const currentPageSelector = (s: Data) => s.page
|
||||
|
||||
export function PagePanel(): JSX.Element {
|
||||
const rIsOpen = React.useRef(false)
|
||||
const [isOpen, setIsOpen] = React.useState(false)
|
||||
|
||||
const { tlstate, useSelector } = useTLDrawContext()
|
||||
|
||||
React.useEffect(() => {
|
||||
if (rIsOpen.current !== isOpen) {
|
||||
rIsOpen.current = isOpen
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
const handleCreatePage = React.useCallback(() => {
|
||||
tlstate.createPage()
|
||||
}, [tlstate])
|
||||
|
||||
const handleChangePage = React.useCallback(
|
||||
(id: string) => {
|
||||
setIsOpen(false)
|
||||
tlstate.changePage(id)
|
||||
},
|
||||
[tlstate]
|
||||
)
|
||||
|
||||
const currentPage = useSelector(currentPageSelector)
|
||||
|
||||
const sorted = Object.values([currentPage]).sort(
|
||||
(a, b) => (a.childIndex || 0) - (b.childIndex || 0)
|
||||
)
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root
|
||||
dir="ltr"
|
||||
open={isOpen}
|
||||
onOpenChange={(isOpen) => {
|
||||
if (rIsOpen.current !== isOpen) {
|
||||
setIsOpen(isOpen)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FloatingContainer>
|
||||
<RowButton as={DropdownMenu.Trigger} bp={breakpoints} variant="noIcon">
|
||||
<span>{currentPage.name || 'Page'}</span>
|
||||
</RowButton>
|
||||
</FloatingContainer>
|
||||
<MenuContent as={DropdownMenu.Content} sideOffset={8} align="start">
|
||||
<DropdownMenu.RadioGroup value={currentPage.id} onValueChange={handleChangePage}>
|
||||
{sorted.map((page) => (
|
||||
<ButtonWithOptions key={page.id}>
|
||||
<DropdownMenu.RadioItem
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
value={page.id}
|
||||
variant="pageButton"
|
||||
>
|
||||
<span>{page.name}</span>
|
||||
<DropdownMenu.ItemIndicator>
|
||||
<IconWrapper size="small">
|
||||
<CheckIcon />
|
||||
</IconWrapper>
|
||||
</DropdownMenu.ItemIndicator>
|
||||
</DropdownMenu.RadioItem>
|
||||
<PageOptionsDialog page={page} />
|
||||
</ButtonWithOptions>
|
||||
))}
|
||||
</DropdownMenu.RadioGroup>
|
||||
<DropdownMenuDivider />
|
||||
<DropdownMenuButton onSelect={handleCreatePage}>
|
||||
<span>Create Page</span>
|
||||
<IconWrapper size="small">
|
||||
<PlusIcon />
|
||||
</IconWrapper>
|
||||
</DropdownMenuButton>
|
||||
</MenuContent>
|
||||
</DropdownMenu.Root>
|
||||
)
|
||||
}
|
||||
|
||||
const ButtonWithOptions = styled('div', {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr auto',
|
||||
gridAutoFlow: 'column',
|
||||
|
||||
'& > *[data-shy="true"]': {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
'&:hover > *[data-shy="true"]': {
|
||||
opacity: 1,
|
||||
},
|
||||
})
|
|
@ -3,7 +3,7 @@ import { renderWithContext } from '~test'
|
|||
import { StylePanel } from './style-panel'
|
||||
|
||||
describe('style panel', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<StylePanel />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { render } from '@testing-library/react'
|
|||
import { TLDraw } from './tldraw'
|
||||
|
||||
describe('tldraw', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
render(<TLDraw />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -124,6 +124,7 @@ export function TLDraw({ document, currentPageId, onMount, onChange: _onChange }
|
|||
onTextKeyUp={tlstate.onTextKeyUp}
|
||||
/>
|
||||
</ContextMenu>
|
||||
<MenuButtons />
|
||||
<Spacer />
|
||||
<StylePanel />
|
||||
<ToolsPanel />
|
||||
|
@ -137,10 +138,10 @@ const Spacer = styled('div', {
|
|||
flexGrow: 2,
|
||||
})
|
||||
|
||||
// const MenuButtons = styled('div', {
|
||||
// display: 'flex',
|
||||
// gap: 8,
|
||||
// })
|
||||
const MenuButtons = styled('div', {
|
||||
display: 'flex',
|
||||
gap: 8,
|
||||
})
|
||||
|
||||
const Layout = styled('main', {
|
||||
position: 'fixed',
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ToolsPanel } from './tools-panel'
|
|||
import { renderWithContext } from '~test'
|
||||
|
||||
describe('tools panel', () => {
|
||||
test('mounts component', () => {
|
||||
test('mounts component without crashing', () => {
|
||||
renderWithContext(<ToolsPanel />)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,5 +4,6 @@ export function useTheme() {
|
|||
return {
|
||||
theme: 'light' as Theme,
|
||||
toggle: () => null,
|
||||
setTheme: (theme: Theme) => void theme,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { TLDrawState } from '~state'
|
||||
import { mockDocument } from '~test'
|
||||
|
||||
describe('Change page command', () => {
|
||||
const tlstate = new TLDrawState()
|
||||
|
||||
it('does, undoes and redoes command', () => {
|
||||
tlstate.loadDocument(mockDocument)
|
||||
|
||||
const initialId = tlstate.page.id
|
||||
|
||||
tlstate.createPage()
|
||||
|
||||
const nextId = tlstate.page.id
|
||||
|
||||
tlstate.changePage(initialId)
|
||||
|
||||
expect(tlstate.page.id).toBe(initialId)
|
||||
|
||||
tlstate.undo()
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
|
||||
tlstate.redo()
|
||||
|
||||
expect(tlstate.page.id).toBe(initialId)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
import type { TLDrawShape, Data, Command } from '~types'
|
||||
import { TLDR } from '~state/tldr'
|
||||
|
||||
export function changePage(data: Data): Command {
|
||||
return {
|
||||
id: 'create_page',
|
||||
before: {},
|
||||
after: {},
|
||||
}
|
||||
}
|
1
packages/tldraw/src/state/command/change-page/index.ts
Normal file
1
packages/tldraw/src/state/command/change-page/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './change-page.command'
|
|
@ -0,0 +1,26 @@
|
|||
import { TLDrawState } from '~state'
|
||||
import { mockDocument } from '~test'
|
||||
|
||||
describe('Create page command', () => {
|
||||
const tlstate = new TLDrawState()
|
||||
|
||||
it('does, undoes and redoes command', () => {
|
||||
tlstate.loadDocument(mockDocument)
|
||||
|
||||
const initialId = tlstate.page.id
|
||||
|
||||
tlstate.createPage()
|
||||
|
||||
const nextId = tlstate.page.id
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
|
||||
tlstate.undo()
|
||||
|
||||
expect(tlstate.page.id).toBe(initialId)
|
||||
|
||||
tlstate.redo()
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
import type { TLDrawShape, Data, Command } from '~types'
|
||||
import { TLDR } from '~state/tldr'
|
||||
|
||||
export function createPage(data: Data): Command {
|
||||
return {
|
||||
id: 'create_page',
|
||||
before: {},
|
||||
after: {},
|
||||
}
|
||||
}
|
1
packages/tldraw/src/state/command/create-page/index.ts
Normal file
1
packages/tldraw/src/state/command/create-page/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './create-page.command'
|
|
@ -0,0 +1,28 @@
|
|||
import { TLDrawState } from '~state'
|
||||
import { mockDocument } from '~test'
|
||||
|
||||
describe('Delete page', () => {
|
||||
const tlstate = new TLDrawState()
|
||||
|
||||
it('does, undoes and redoes command', () => {
|
||||
tlstate.loadDocument(mockDocument)
|
||||
|
||||
const initialId = tlstate.page.id
|
||||
|
||||
tlstate.createPage()
|
||||
|
||||
const nextId = tlstate.page.id
|
||||
|
||||
tlstate.deletePage()
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
|
||||
tlstate.undo()
|
||||
|
||||
expect(tlstate.page.id).toBe(initialId)
|
||||
|
||||
tlstate.redo()
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
import type { TLDrawShape, Data, Command } from '~types'
|
||||
import { TLDR } from '~state/tldr'
|
||||
|
||||
export function deletePage(data: Data, id: string): Command {
|
||||
return {
|
||||
id: 'delete_page',
|
||||
before: {},
|
||||
after: {},
|
||||
}
|
||||
}
|
1
packages/tldraw/src/state/command/delete-page/index.ts
Normal file
1
packages/tldraw/src/state/command/delete-page/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './delete-page.command'
|
|
@ -0,0 +1,24 @@
|
|||
import { TLDrawState } from '~state'
|
||||
import { mockDocument } from '~test'
|
||||
|
||||
describe('Duplicate page', () => {
|
||||
const tlstate = new TLDrawState()
|
||||
|
||||
it('does, undoes and redoes command', () => {
|
||||
tlstate.loadDocument(mockDocument)
|
||||
|
||||
const initialId = tlstate.page.id
|
||||
|
||||
tlstate.duplicatePage()
|
||||
|
||||
const nextId = tlstate.page.id
|
||||
|
||||
tlstate.undo()
|
||||
|
||||
expect(tlstate.page.id).toBe(initialId)
|
||||
|
||||
tlstate.redo()
|
||||
|
||||
expect(tlstate.page.id).toBe(nextId)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
import type { TLDrawShape, Data, Command } from '~types'
|
||||
import { TLDR } from '~state/tldr'
|
||||
|
||||
export function duplicatePage(data: Data, id: string): Command {
|
||||
return {
|
||||
id: 'duplicate_page',
|
||||
before: {},
|
||||
after: {},
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './duplicate-page.command'
|
1
packages/tldraw/src/state/command/rename-page/index.ts
Normal file
1
packages/tldraw/src/state/command/rename-page/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './rename-page.command'
|
|
@ -0,0 +1,25 @@
|
|||
import { TLDrawState } from '~state'
|
||||
import { mockDocument } from '~test'
|
||||
|
||||
describe('Edit page', () => {
|
||||
const tlstate = new TLDrawState()
|
||||
|
||||
it('does, undoes and redoes command', () => {
|
||||
tlstate.loadDocument(mockDocument)
|
||||
|
||||
const initialId = tlstate.page.id
|
||||
const initialName = tlstate.page.name
|
||||
|
||||
tlstate.renamePage(initialId, 'My Special Page')
|
||||
|
||||
expect(tlstate.page.name).toBe('My Special Page')
|
||||
|
||||
tlstate.undo()
|
||||
|
||||
expect(tlstate.page.name).toBe(initialName)
|
||||
|
||||
tlstate.redo()
|
||||
|
||||
expect(tlstate.page.name).toBe('My Special Page')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
import type { TLDrawShape, Data, Command } from '~types'
|
||||
import { TLDR } from '~state/tldr'
|
||||
|
||||
export function editPage(data: Data, id: string): Command {
|
||||
return {
|
||||
id: 'edit_page',
|
||||
before: {},
|
||||
after: {},
|
||||
}
|
||||
}
|
|
@ -519,7 +519,22 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
/* ---------------------- Document --------------------- */
|
||||
/* -------------------------------------------------- */
|
||||
/* Document */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
private setCurrentPageId(pageId: string) {
|
||||
if (pageId === this.currentPageId) return this
|
||||
|
||||
this.currentPageId = pageId
|
||||
|
||||
this.setState({
|
||||
page: this.pages[pageId],
|
||||
pageState: this.pageStates[pageId],
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
loadDocument = (document: TLDrawDocument, onChange?: TLDrawState['_onChange']) => {
|
||||
this._onChange = onChange
|
||||
this.currentDocumentId = document.id
|
||||
|
@ -543,19 +558,26 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
setCurrentPageId(pageId: string) {
|
||||
if (pageId === this.currentPageId) return this
|
||||
|
||||
this.currentPageId = pageId
|
||||
|
||||
this.setState({
|
||||
page: this.pages[pageId],
|
||||
pageState: this.pageStates[pageId],
|
||||
})
|
||||
return this
|
||||
newProject = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* -------------------- Sessions -------------------- */
|
||||
saveProject = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
loadProject = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
signOut = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Sessions */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
startSession<T extends Session>(session: T, ...args: ParametersExceptFirst<T['start']>) {
|
||||
this.session = session
|
||||
this.setState((data) => session.start(data, ...args), session.status)
|
||||
|
@ -658,7 +680,10 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
/* -------------------- Commands -------------------- */
|
||||
/* -------------------------------------------------- */
|
||||
/* History */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
do(command: Command) {
|
||||
const { history } = this
|
||||
|
||||
|
@ -739,7 +764,10 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
/* -------------------- Selection ------------------- */
|
||||
/* -------------------------------------------------- */
|
||||
/* Selection */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
setSelectedIds(ids: string[], push = false) {
|
||||
this.setState((data) => {
|
||||
return {
|
||||
|
@ -936,6 +964,10 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
toggleDebugMode = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
rotate = (delta = Math.PI * -0.5, ids?: string[]) => {
|
||||
const data = this.store.getState()
|
||||
const idsToMutate = ids ? ids : data.pageState.selectedIds
|
||||
|
@ -1006,6 +1038,52 @@ export class TLDrawState implements TLCallbacks {
|
|||
return this
|
||||
}
|
||||
|
||||
createPage() {
|
||||
const newId = Utils.uniqueId()
|
||||
this.pages[newId] = { id: newId, shapes: {}, bindings: {} }
|
||||
this.changePage(newId)
|
||||
return this
|
||||
}
|
||||
|
||||
changePage(id: string) {
|
||||
this.setCurrentPageId(id)
|
||||
return this
|
||||
}
|
||||
|
||||
renamePage(id: string, name: string) {
|
||||
this.pages[id] = { ...this.pages[id], name }
|
||||
return this
|
||||
}
|
||||
|
||||
duplicatePage(id: string = this.currentPageId) {
|
||||
const newId = Utils.uniqueId()
|
||||
this.pages[newId] = { ...this.pages[id], id: newId }
|
||||
this.changePage(newId)
|
||||
return this
|
||||
}
|
||||
|
||||
deletePage(id: string = this.currentPageId) {
|
||||
const pages = Object.values(this.pages).sort(
|
||||
(a, b) => (a.childIndex || 0) - (b.childIndex || 0)
|
||||
)
|
||||
|
||||
const currentIndex = pages.findIndex((page) => page.id === this.currentPageId)
|
||||
|
||||
if (Object.values(this.pages).length <= 1) return
|
||||
|
||||
delete this.pages[id]
|
||||
|
||||
if (id === this.currentPageId) {
|
||||
if (currentIndex === pages.length - 1) {
|
||||
this.changePage(pages[pages.length - 2].id)
|
||||
} else {
|
||||
this.changePage(pages[currentIndex + 1].id)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
copy = (ids?: string[]) => {
|
||||
const data = this.store.getState()
|
||||
const idsToCopy = ids ? ids : data.pageState.selectedIds
|
||||
|
|
|
@ -8,9 +8,11 @@ import type { StoreApi } from 'zustand'
|
|||
export type TLStore = StoreApi<Data>
|
||||
export type TLChange = Data
|
||||
|
||||
export type TLDrawPage = TLPage<TLDrawShape, TLDrawBinding>
|
||||
|
||||
export interface TLDrawDocument {
|
||||
id: string
|
||||
pages: Record<string, TLPage<TLDrawShape, TLDrawBinding>>
|
||||
pages: Record<string, TLDrawPage>
|
||||
pageStates: Record<string, TLPageState>
|
||||
}
|
||||
|
||||
|
|
100
yarn.lock
100
yarn.lock
|
@ -1634,6 +1634,20 @@
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-alert-dialog@^0.0.20":
|
||||
version "0.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-0.0.20.tgz#1adb997c899fd9cb6f0d13bc66b50d2166414339"
|
||||
integrity sha512-Vaz16wc4rDVHC7BH2At3TM+HEU56jN6fAWoeXatZyv1BAaehSabusbghC4V8Cfc0llP4ijvOY7Eznkt0+jP/fQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/primitive" "0.0.5"
|
||||
"@radix-ui/react-compose-refs" "0.0.5"
|
||||
"@radix-ui/react-context" "0.0.5"
|
||||
"@radix-ui/react-dialog" "0.0.20"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
"@radix-ui/react-primitive" "0.0.15"
|
||||
"@radix-ui/react-slot" "0.0.12"
|
||||
|
||||
"@radix-ui/react-arrow@0.0.14":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-0.0.14.tgz#70b2c66efbf3cde0c9dd0895417e39f6cdf31805"
|
||||
|
@ -1696,6 +1710,28 @@
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
|
||||
"@radix-ui/react-dialog@0.0.20":
|
||||
version "0.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-0.0.20.tgz#b26607bea68fc20067d06fab996bac7f1acf68c1"
|
||||
integrity sha512-fXgWxWyvmNiimxrFGdvUNve0tyQEFyPwrNgkSi6Xiha9cX8sqWdiYWq500zhzUQQFJVS7No73ylx8kgrI7SoLw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/primitive" "0.0.5"
|
||||
"@radix-ui/react-compose-refs" "0.0.5"
|
||||
"@radix-ui/react-context" "0.0.5"
|
||||
"@radix-ui/react-dismissable-layer" "0.0.15"
|
||||
"@radix-ui/react-focus-guards" "0.0.7"
|
||||
"@radix-ui/react-focus-scope" "0.0.15"
|
||||
"@radix-ui/react-id" "0.0.6"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
"@radix-ui/react-portal" "0.0.15"
|
||||
"@radix-ui/react-presence" "0.0.15"
|
||||
"@radix-ui/react-primitive" "0.0.15"
|
||||
"@radix-ui/react-slot" "0.0.12"
|
||||
"@radix-ui/react-use-controllable-state" "0.0.6"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "^2.4.0"
|
||||
|
||||
"@radix-ui/react-dismissable-layer@0.0.14":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.0.14.tgz#9d8a3415a2830688070c6596dec18b43c33df7b2"
|
||||
|
@ -1709,6 +1745,19 @@
|
|||
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||
"@radix-ui/react-use-escape-keydown" "0.0.6"
|
||||
|
||||
"@radix-ui/react-dismissable-layer@0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-0.0.15.tgz#02c0e68684d60933c82b5af6793c87a5f9ee0750"
|
||||
integrity sha512-2zABi8rh/t6liFfRLBw6h+B7MNNFxVQrgYfWRMs1elNX41z3G2vLoBlWdqGzAlYrtqEr/6CL4pQfhwVtd7rNGw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/primitive" "0.0.5"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
"@radix-ui/react-primitive" "0.0.15"
|
||||
"@radix-ui/react-use-body-pointer-events" "0.0.7"
|
||||
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||
"@radix-ui/react-use-escape-keydown" "0.0.6"
|
||||
|
||||
"@radix-ui/react-dropdown-menu@^0.0.22":
|
||||
version "0.0.22"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-0.0.22.tgz#914dbbb12d31b4379df697f1262150b3f50916ae"
|
||||
|
@ -1742,6 +1791,17 @@
|
|||
"@radix-ui/react-primitive" "0.0.14"
|
||||
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||
|
||||
"@radix-ui/react-focus-scope@0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-0.0.15.tgz#60917075e53ee72d2a473fba88eb31e7aaf7d841"
|
||||
integrity sha512-zNgEe1lyLPfxa003VD8lCXaadGqCYhboA3X1WDNGes74lzJgLOPJgzLI0F/ksSokkx/yDDdReyOWui3/LCTqTw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "0.0.5"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
"@radix-ui/react-primitive" "0.0.15"
|
||||
"@radix-ui/react-use-callback-ref" "0.0.5"
|
||||
|
||||
"@radix-ui/react-icons@^1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-icons/-/react-icons-1.0.3.tgz#4ef61f1234f44991f7a19e108f77ca37032b4be2"
|
||||
|
@ -1796,6 +1856,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.12.tgz#bf4ae516669b68e059549538104d97322f7c876b"
|
||||
integrity sha512-/GYNMicBnGzjD1d2fCAuzql1VeFrp8mqM3xfzT1kxhnV85TKdURO45jBfMgqo17XNXoNhWIAProUsCO4qFAAIg==
|
||||
|
||||
"@radix-ui/react-polymorphic@0.0.13":
|
||||
version "0.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-polymorphic/-/react-polymorphic-0.0.13.tgz#d010d48281626191c9513f11db5d82b37662418a"
|
||||
integrity sha512-0sGqBp+v9/yrsMhPfAejxcem2MwAFgaSAxF3Sieaklm6ZVYM/hTZxxWI5NVOLGV+482GwW0wIqwpVUzREjmh+w==
|
||||
|
||||
"@radix-ui/react-popper@0.0.17":
|
||||
version "0.0.17"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-0.0.17.tgz#a73486e19a628cb3fecaf3fb6eecf6e2cab9d0be"
|
||||
|
@ -1822,6 +1887,16 @@
|
|||
"@radix-ui/react-primitive" "0.0.14"
|
||||
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||
|
||||
"@radix-ui/react-portal@0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-0.0.15.tgz#833bccb192aafb9420bd037d5827e88caf429dc4"
|
||||
integrity sha512-qMESsdqph1gbRGzy9oSzUoeZYXnR2egXVcEZDqmesfn8w/o1rC1wadKkyBf7qo/YyjUX4mvXknAA+ftp1aQp+w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
"@radix-ui/react-primitive" "0.0.15"
|
||||
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||
|
||||
"@radix-ui/react-presence@0.0.14":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.0.14.tgz#6a86058bbbf46234dd8840dacd620b3ac5797025"
|
||||
|
@ -1830,6 +1905,15 @@
|
|||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "0.0.5"
|
||||
|
||||
"@radix-ui/react-presence@0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-0.0.15.tgz#4ff12feb436f1499148feb11c3a63a5d8fab568a"
|
||||
integrity sha512-+5+ePKUdTkqN1ze7nYmcoeHSsmKCcREwt0NhvNgDocPaqEUoZSkK9Mq6eMiMXSj02NkXH9P+bK32VCClYFnMBQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "0.0.5"
|
||||
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||
|
||||
"@radix-ui/react-primitive@0.0.14":
|
||||
version "0.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.0.14.tgz#752a967cb05d4c5643634fe20274e7dc905d1cce"
|
||||
|
@ -1838,6 +1922,14 @@
|
|||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-polymorphic" "0.0.12"
|
||||
|
||||
"@radix-ui/react-primitive@0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-0.0.15.tgz#c0cf609ee565a32969d20943e2697b42a04fbdf3"
|
||||
integrity sha512-Y7JLnen/G3AT0cQXXkBo3A1OuWaKGerkd2gKs0Fuqxv+kTxEmYoqSp/soo0Mm3Ccw61LKLQAjPiE37GK9/Zqwg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-polymorphic" "0.0.13"
|
||||
|
||||
"@radix-ui/react-radio-group@^0.0.18":
|
||||
version "0.0.18"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-radio-group/-/react-radio-group-0.0.18.tgz#d6f9ce132102deb23ee782e08f7b3e185ea317f0"
|
||||
|
@ -1912,6 +2004,14 @@
|
|||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||
|
||||
"@radix-ui/react-use-body-pointer-events@0.0.7":
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.0.7.tgz#e4249690ca0db85c969400e867476206feda4d1e"
|
||||
integrity sha512-mXAGyb8mhVjRqtpKPeZePuvee40bgsWpt378oQrIcLU1uZNbNX9eyrIPnnL9OMLAvxqloAOClVj0PZ1bMQmfDw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-use-layout-effect" "0.0.5"
|
||||
|
||||
"@radix-ui/react-use-callback-ref@0.0.5":
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-0.0.5.tgz#fa8db050229cda573dfeeae213d74ef06f6130db"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue