Cleans up UI components, removes Shared as single file
This commit is contained in:
parent
88711523c7
commit
d66007b142
30 changed files with 784 additions and 711 deletions
|
@ -1,11 +1,11 @@
|
|||
import * as React from 'react'
|
||||
import styled from '~styles'
|
||||
import { Utils } from '@tldraw/core'
|
||||
import * as RadixContextMenu from '@radix-ui/react-context-menu'
|
||||
import styled from '~styles'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import type { Data } from '~types'
|
||||
import { Kbd } from '../kbd'
|
||||
import { Data, AlignType, DistributeType, StretchType } from '~types'
|
||||
import {
|
||||
Kbd,
|
||||
IconWrapper,
|
||||
breakpoints,
|
||||
RowButton,
|
||||
|
@ -17,7 +17,6 @@ import {
|
|||
ContextMenuRoot,
|
||||
MenuContent,
|
||||
} from '../shared'
|
||||
import { AlignType, DistributeType, StretchType } from '~types'
|
||||
import {
|
||||
ChevronRightIcon,
|
||||
AlignBottomIcon,
|
||||
|
|
14
packages/tldraw/src/components/icons/circle.tsx
Normal file
14
packages/tldraw/src/components/icons/circle.tsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
import * as React from 'react'
|
||||
|
||||
export default function CircleIcon(
|
||||
props: Pick<React.SVGProps<SVGSVGElement>, 'stroke' | 'fill'> & {
|
||||
size: number
|
||||
}
|
||||
) {
|
||||
const { size = 16, ...rest } = props
|
||||
return (
|
||||
<svg width={24} height={24} {...rest}>
|
||||
<circle cx={12} cy={12} r={size / 2} />
|
||||
</svg>
|
||||
)
|
||||
}
|
|
@ -2,3 +2,4 @@ export { default as Redo } from './redo'
|
|||
export { default as Trash } from './trash'
|
||||
export { default as Undo } from './undo'
|
||||
export { default as Check } from './check'
|
||||
export { default as CircleIcon } from './circle'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export * from './tooltip'
|
||||
export * from './kbd'
|
||||
export * from './shared/tooltip'
|
||||
export * from './shared/kbd'
|
||||
export * from './shared'
|
||||
export * from './icons'
|
||||
export * from './tldraw'
|
||||
|
|
|
@ -1,691 +0,0 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import * as React from 'react'
|
||||
import { Tooltip } from './tooltip'
|
||||
import {
|
||||
Root as CMRoot,
|
||||
TriggerItem as CMTriggerItem,
|
||||
Separator as CMSeparator,
|
||||
Item as CMItem,
|
||||
Arrow as CMArrow,
|
||||
Content as CMContent,
|
||||
ItemIndicator as CMItemIndicator,
|
||||
CheckboxItem as CMCheckboxItem,
|
||||
} from '@radix-ui/react-context-menu'
|
||||
import {
|
||||
Root as DMRoot,
|
||||
TriggerItem as DMTriggerItem,
|
||||
Separator as DMSeparator,
|
||||
Item as DMItem,
|
||||
Arrow as DMArrow,
|
||||
Content as DMContent,
|
||||
Trigger as DMTrigger,
|
||||
ItemIndicator as DMItemIndicator,
|
||||
CheckboxItem as DMCheckboxItem,
|
||||
} from '@radix-ui/react-dropdown-menu'
|
||||
import { Root as RGRoot } from '@radix-ui/react-radio-group'
|
||||
import { CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons'
|
||||
import styled from '~styles'
|
||||
|
||||
export const breakpoints: any = { '@initial': 'mobile', '@sm': 'small' }
|
||||
|
||||
export const IconButton = styled('button', {
|
||||
position: 'relative',
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
backgroundColor: '$panel',
|
||||
borderRadius: '4px',
|
||||
padding: '0',
|
||||
margin: '0',
|
||||
display: 'grid',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
pointerEvents: 'all',
|
||||
fontSize: '$0',
|
||||
color: '$text',
|
||||
cursor: 'pointer',
|
||||
|
||||
'& > *': {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
opacity: '0.5',
|
||||
},
|
||||
|
||||
'& > span': {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
variants: {
|
||||
bp: {
|
||||
mobile: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
small: {
|
||||
'&:hover:not(:disabled)': {
|
||||
backgroundColor: '$hover',
|
||||
},
|
||||
},
|
||||
},
|
||||
size: {
|
||||
small: {
|
||||
height: 32,
|
||||
width: 32,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '18px',
|
||||
width: '18px',
|
||||
},
|
||||
},
|
||||
large: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '20px',
|
||||
width: '20px',
|
||||
},
|
||||
},
|
||||
},
|
||||
isActive: {
|
||||
true: {
|
||||
color: '$selected',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const RowButton = styled('button', {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
background: 'none',
|
||||
height: '32px',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
color: '$text',
|
||||
outline: 'none',
|
||||
alignItems: 'center',
|
||||
fontFamily: '$ui',
|
||||
fontWeight: 400,
|
||||
fontSize: '$1',
|
||||
justifyContent: 'space-between',
|
||||
padding: '4px 8px 4px 12px',
|
||||
borderRadius: 4,
|
||||
userSelect: 'none',
|
||||
|
||||
'& label': {
|
||||
fontWeight: '$1',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
position: 'relative',
|
||||
stroke: '$overlay',
|
||||
strokeWidth: 1,
|
||||
zIndex: 1,
|
||||
},
|
||||
|
||||
'&[data-disabled]': {
|
||||
opacity: 0.3,
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
opacity: 0.3,
|
||||
},
|
||||
|
||||
variants: {
|
||||
bp: {
|
||||
mobile: {},
|
||||
small: {
|
||||
'& *[data-shy="true"]': {
|
||||
opacity: 0,
|
||||
},
|
||||
'&:hover:not(:disabled)': {
|
||||
backgroundColor: '$hover',
|
||||
'& *[data-shy="true"]': {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
size: {
|
||||
icon: {
|
||||
padding: '4px ',
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
variant: {
|
||||
noIcon: {
|
||||
padding: '4px 12px',
|
||||
},
|
||||
pageButton: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '24px auto',
|
||||
width: '100%',
|
||||
paddingLeft: '$1',
|
||||
gap: '$3',
|
||||
justifyContent: 'flex-start',
|
||||
[`& > *[data-state="checked"]`]: {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
'& > span': {
|
||||
gridRow: 1,
|
||||
gridColumn: 2,
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
warn: {
|
||||
true: {
|
||||
color: '$warn',
|
||||
},
|
||||
},
|
||||
isActive: {
|
||||
true: {
|
||||
backgroundColor: '$hover',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const Group = styled(RGRoot, {
|
||||
display: 'flex',
|
||||
})
|
||||
|
||||
export const ShortcutKey = styled('span', {
|
||||
fontSize: '$0',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '1px 1px 0px rgba(0,0,0,.5)',
|
||||
})
|
||||
|
||||
export const IconWrapper = styled('div', {
|
||||
height: '100%',
|
||||
borderRadius: '4px',
|
||||
marginRight: '1px',
|
||||
display: 'grid',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
pointerEvents: 'all',
|
||||
cursor: 'pointer',
|
||||
color: '$text',
|
||||
|
||||
'& svg': {
|
||||
height: 22,
|
||||
width: 22,
|
||||
strokeWidth: 1,
|
||||
},
|
||||
|
||||
'& > *': {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
|
||||
variants: {
|
||||
size: {
|
||||
small: {
|
||||
'& svg': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
'& svg': {
|
||||
height: '22px',
|
||||
width: '22px',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const ButtonsRow = styled('div', {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: 0,
|
||||
})
|
||||
|
||||
export const VerticalDivider = styled('hr', {
|
||||
width: '1px',
|
||||
margin: '-2px 3px',
|
||||
border: 'none',
|
||||
backgroundColor: '$brushFill',
|
||||
})
|
||||
|
||||
export const FloatingContainer = styled('div', {
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
borderRadius: '4px',
|
||||
boxShadow: '$4',
|
||||
display: 'flex',
|
||||
height: 'fit-content',
|
||||
padding: '$0',
|
||||
pointerEvents: 'all',
|
||||
position: 'relative',
|
||||
userSelect: 'none',
|
||||
zIndex: 200,
|
||||
|
||||
variants: {
|
||||
direction: {
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
},
|
||||
elevation: {
|
||||
0: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
2: {
|
||||
boxShadow: '$2',
|
||||
},
|
||||
3: {
|
||||
boxShadow: '$3',
|
||||
},
|
||||
4: {
|
||||
boxShadow: '$4',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Dialog */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const DialogContent = styled('div', {
|
||||
position: 'fixed',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
minWidth: 240,
|
||||
maxWidth: 'fit-content',
|
||||
maxHeight: '85vh',
|
||||
marginTop: '-5vh',
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
padding: '$0',
|
||||
boxShadow: '$4',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
|
||||
'&:focus': {
|
||||
outline: 'none',
|
||||
},
|
||||
})
|
||||
|
||||
export const DialogOverlay = styled('div', {
|
||||
backgroundColor: 'rgba(0, 0, 0, .15)',
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
})
|
||||
|
||||
export const DialogInputWrapper = styled('div', {
|
||||
padding: '$4 $2',
|
||||
})
|
||||
|
||||
export const DialogTitleRow = styled('div', {
|
||||
display: 'flex',
|
||||
padding: '0 0 0 $4',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
|
||||
h3: {
|
||||
fontSize: '$1',
|
||||
},
|
||||
})
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Menus */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const MenuContent = styled('div', {
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
userSelect: 'none',
|
||||
zIndex: 180,
|
||||
minWidth: 180,
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
padding: '$0',
|
||||
boxShadow: '$4',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
})
|
||||
|
||||
export const Divider = styled('div', {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
marginTop: '$2',
|
||||
marginRight: '-$2',
|
||||
marginBottom: '$2',
|
||||
marginLeft: '-$2',
|
||||
})
|
||||
|
||||
export function MenuButton({
|
||||
warn,
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: {
|
||||
warn?: boolean
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<RowButton bp={breakpoints} disabled={disabled} warn={warn} onSelect={onSelect}>
|
||||
{children}
|
||||
</RowButton>
|
||||
)
|
||||
}
|
||||
|
||||
export const MenuTextInput = styled('input', {
|
||||
backgroundColor: '$panel',
|
||||
border: 'none',
|
||||
padding: '$4 $3',
|
||||
width: '100%',
|
||||
outline: 'none',
|
||||
background: '$input',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
fontSize: '$1',
|
||||
})
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Dropdown Menu */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export function DropdownMenuRoot({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
children,
|
||||
}: {
|
||||
isOpen?: boolean
|
||||
onOpenChange?: (isOpen: boolean) => void
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<DMRoot dir="ltr" open={isOpen} onOpenChange={onOpenChange}>
|
||||
{children}
|
||||
</DMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export function DropdownMenuSubMenu({
|
||||
children,
|
||||
disabled = false,
|
||||
label,
|
||||
}: {
|
||||
label: string
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<DMRoot dir="ltr">
|
||||
<DMTriggerItem as={RowButton} bp={breakpoints} disabled={disabled}>
|
||||
<span>{label}</span>
|
||||
<IconWrapper size="small">
|
||||
<ChevronRightIcon />
|
||||
</IconWrapper>
|
||||
</DMTriggerItem>
|
||||
<DMContent as={MenuContent} sideOffset={2} alignOffset={-2}>
|
||||
{children}
|
||||
<DropdownMenuArrow offset={13} />
|
||||
</DMContent>
|
||||
</DMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export const DropdownMenuDivider = styled(DMSeparator, {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
marginTop: '$2',
|
||||
marginRight: '-$2',
|
||||
marginBottom: '$2',
|
||||
marginLeft: '-$2',
|
||||
})
|
||||
|
||||
export const DropdownMenuArrow = styled(DMArrow, {
|
||||
fill: '$panel',
|
||||
})
|
||||
|
||||
export function DropdownMenuButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: {
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<DMItem as={RowButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</DMItem>
|
||||
)
|
||||
}
|
||||
|
||||
interface DropdownMenuIconButtonProps {
|
||||
onSelect: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuIconButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: DropdownMenuIconButtonProps): JSX.Element {
|
||||
return (
|
||||
<DMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</DMItem>
|
||||
)
|
||||
}
|
||||
|
||||
interface DropdownMenuIconTriggerButtonProps {
|
||||
label: string
|
||||
kbd?: string
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
export function DropdownMenuIconTriggerButton({
|
||||
label,
|
||||
kbd,
|
||||
children,
|
||||
disabled = false,
|
||||
}: DropdownMenuIconTriggerButtonProps): JSX.Element {
|
||||
return (
|
||||
<DMTrigger as={IconButton} bp={breakpoints} disabled={disabled}>
|
||||
<Tooltip label={label} kbd={kbd}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
</DMTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
interface MenuCheckboxItemProps {
|
||||
checked: boolean
|
||||
disabled?: boolean
|
||||
onCheckedChange: (isChecked: boolean) => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuCheckboxItem({
|
||||
checked,
|
||||
disabled = false,
|
||||
onCheckedChange,
|
||||
children,
|
||||
}: MenuCheckboxItemProps): JSX.Element {
|
||||
return (
|
||||
<DMCheckboxItem
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
onCheckedChange={onCheckedChange}
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
<DMItemIndicator>
|
||||
<IconWrapper size="small">
|
||||
<CheckIcon />
|
||||
</IconWrapper>
|
||||
</DMItemIndicator>
|
||||
</DMCheckboxItem>
|
||||
)
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Context Menu */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export function ContextMenuRoot({
|
||||
onOpenChange,
|
||||
children,
|
||||
}: {
|
||||
onOpenChange?: (isOpen: boolean) => void
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<CMRoot dir="ltr" onOpenChange={onOpenChange}>
|
||||
{children}
|
||||
</CMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export function ContextMenuSubMenu({
|
||||
children,
|
||||
label,
|
||||
}: {
|
||||
label: string
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<CMRoot dir="ltr">
|
||||
<CMTriggerItem as={RowButton} bp={breakpoints}>
|
||||
<span>{label}</span>
|
||||
<IconWrapper size="small">
|
||||
<ChevronRightIcon />
|
||||
</IconWrapper>
|
||||
</CMTriggerItem>
|
||||
<CMContent as={MenuContent} sideOffset={2} alignOffset={-2}>
|
||||
{children}
|
||||
<ContextMenuArrow offset={13} />
|
||||
</CMContent>
|
||||
</CMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export const ContextMenuDivider = styled(CMSeparator, {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
margin: '$2 -$2',
|
||||
})
|
||||
|
||||
export const ContextMenuArrow = styled(CMArrow, {
|
||||
fill: '$panel',
|
||||
})
|
||||
|
||||
export function ContextMenuButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: {
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<RowButton as={CMItem} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</RowButton>
|
||||
)
|
||||
}
|
||||
|
||||
export function ContextMenuIconButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: {
|
||||
onSelect: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<CMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</CMItem>
|
||||
)
|
||||
}
|
||||
|
||||
export function ContextMenuCheckboxItem({
|
||||
checked,
|
||||
disabled = false,
|
||||
onCheckedChange,
|
||||
children,
|
||||
}: MenuCheckboxItemProps): JSX.Element {
|
||||
return (
|
||||
<CMCheckboxItem
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
onCheckedChange={onCheckedChange}
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
<CMItemIndicator>
|
||||
<IconWrapper size="small">
|
||||
<CheckIcon />
|
||||
</IconWrapper>
|
||||
</CMItemIndicator>
|
||||
</CMCheckboxItem>
|
||||
)
|
||||
}
|
||||
|
||||
export function CircleIcon(
|
||||
props: Pick<React.SVGProps<SVGSVGElement>, 'stroke' | 'fill'> & {
|
||||
size: number
|
||||
}
|
||||
) {
|
||||
const { size = 16, ...rest } = props
|
||||
return (
|
||||
<svg width={24} height={24} {...rest}>
|
||||
<circle cx={12} cy={12} r={size / 2} />
|
||||
</svg>
|
||||
)
|
||||
}
|
6
packages/tldraw/src/components/shared/breakpoints.tsx
Normal file
6
packages/tldraw/src/components/shared/breakpoints.tsx
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* -------------------------------------------------- */
|
||||
/* Breakpoints */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const breakpoints: any = { '@initial': 'mobile', '@sm': 'small' }
|
18
packages/tldraw/src/components/shared/buttons-row.tsx
Normal file
18
packages/tldraw/src/components/shared/buttons-row.tsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Buttons Row */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const ButtonsRow = styled('div', {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: 0,
|
||||
})
|
134
packages/tldraw/src/components/shared/context-menu.tsx
Normal file
134
packages/tldraw/src/components/shared/context-menu.tsx
Normal file
|
@ -0,0 +1,134 @@
|
|||
import * as React from 'react'
|
||||
import { CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons'
|
||||
import {
|
||||
Root as CMRoot,
|
||||
TriggerItem as CMTriggerItem,
|
||||
Separator as CMSeparator,
|
||||
Item as CMItem,
|
||||
Arrow as CMArrow,
|
||||
Content as CMContent,
|
||||
ItemIndicator as CMItemIndicator,
|
||||
CheckboxItem as CMCheckboxItem,
|
||||
} from '@radix-ui/react-context-menu'
|
||||
import { breakpoints } from './breakpoints'
|
||||
import { RowButton } from './row-button'
|
||||
import { IconButton } from './icon-button'
|
||||
import { IconWrapper } from './icon-wrapper'
|
||||
import { MenuContent } from './menu'
|
||||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Context Menu */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export interface ContextMenuRootProps {
|
||||
onOpenChange?: (isOpen: boolean) => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ContextMenuRoot({ onOpenChange, children }: ContextMenuRootProps): JSX.Element {
|
||||
return (
|
||||
<CMRoot dir="ltr" onOpenChange={onOpenChange}>
|
||||
{children}
|
||||
</CMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export interface ContextMenuSubMenuProps {
|
||||
label: string
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ContextMenuSubMenu({ children, label }: ContextMenuSubMenuProps): JSX.Element {
|
||||
return (
|
||||
<CMRoot dir="ltr">
|
||||
<CMTriggerItem as={RowButton} bp={breakpoints}>
|
||||
<span>{label}</span>
|
||||
<IconWrapper size="small">
|
||||
<ChevronRightIcon />
|
||||
</IconWrapper>
|
||||
</CMTriggerItem>
|
||||
<CMContent as={MenuContent} sideOffset={2} alignOffset={-2}>
|
||||
{children}
|
||||
<ContextMenuArrow offset={13} />
|
||||
</CMContent>
|
||||
</CMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export const ContextMenuDivider = styled(CMSeparator, {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
margin: '$2 -$2',
|
||||
})
|
||||
|
||||
export const ContextMenuArrow = styled(CMArrow, {
|
||||
fill: '$panel',
|
||||
})
|
||||
|
||||
export interface ContextMenuButtonProps {
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ContextMenuButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: ContextMenuButtonProps): JSX.Element {
|
||||
return (
|
||||
<RowButton as={CMItem} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</RowButton>
|
||||
)
|
||||
}
|
||||
|
||||
interface ContextMenuIconButtonProps {
|
||||
onSelect: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ContextMenuIconButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: ContextMenuIconButtonProps): JSX.Element {
|
||||
return (
|
||||
<CMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</CMItem>
|
||||
)
|
||||
}
|
||||
|
||||
interface ContextMenuCheckboxItemProps {
|
||||
checked: boolean
|
||||
disabled?: boolean
|
||||
onCheckedChange: (isChecked: boolean) => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function ContextMenuCheckboxItem({
|
||||
checked,
|
||||
disabled = false,
|
||||
onCheckedChange,
|
||||
children,
|
||||
}: ContextMenuCheckboxItemProps): JSX.Element {
|
||||
return (
|
||||
<CMCheckboxItem
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
onCheckedChange={onCheckedChange}
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
<CMItemIndicator>
|
||||
<IconWrapper size="small">
|
||||
<CheckIcon />
|
||||
</IconWrapper>
|
||||
</CMItemIndicator>
|
||||
</CMCheckboxItem>
|
||||
)
|
||||
}
|
51
packages/tldraw/src/components/shared/dialog.tsx
Normal file
51
packages/tldraw/src/components/shared/dialog.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Dialog */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const DialogContent = styled('div', {
|
||||
position: 'fixed',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
minWidth: 240,
|
||||
maxWidth: 'fit-content',
|
||||
maxHeight: '85vh',
|
||||
marginTop: '-5vh',
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
padding: '$0',
|
||||
boxShadow: '$4',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
|
||||
'&:focus': {
|
||||
outline: 'none',
|
||||
},
|
||||
})
|
||||
|
||||
export const DialogOverlay = styled('div', {
|
||||
backgroundColor: 'rgba(0, 0, 0, .15)',
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
})
|
||||
|
||||
export const DialogInputWrapper = styled('div', {
|
||||
padding: '$4 $2',
|
||||
})
|
||||
|
||||
export const DialogTitleRow = styled('div', {
|
||||
display: 'flex',
|
||||
padding: '0 0 0 $4',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
|
||||
h3: {
|
||||
fontSize: '$1',
|
||||
},
|
||||
})
|
173
packages/tldraw/src/components/shared/dropdown-menu.tsx
Normal file
173
packages/tldraw/src/components/shared/dropdown-menu.tsx
Normal file
|
@ -0,0 +1,173 @@
|
|||
import * as React from 'react'
|
||||
import { CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons'
|
||||
import {
|
||||
Root as DMRoot,
|
||||
TriggerItem as DMTriggerItem,
|
||||
Separator as DMSeparator,
|
||||
Item as DMItem,
|
||||
Arrow as DMArrow,
|
||||
Content as DMContent,
|
||||
Trigger as DMTrigger,
|
||||
ItemIndicator as DMItemIndicator,
|
||||
CheckboxItem as DMCheckboxItem,
|
||||
} from '@radix-ui/react-dropdown-menu'
|
||||
|
||||
import { Tooltip } from './tooltip'
|
||||
import { breakpoints } from './breakpoints'
|
||||
import { RowButton } from './row-button'
|
||||
import { IconButton } from './icon-button'
|
||||
import { IconWrapper } from './icon-wrapper'
|
||||
import { MenuContent } from './menu'
|
||||
|
||||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Dropdown Menu */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export interface DropdownMenuRootProps {
|
||||
isOpen?: boolean
|
||||
onOpenChange?: (isOpen: boolean) => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuRoot({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
children,
|
||||
}: DropdownMenuRootProps): JSX.Element {
|
||||
return (
|
||||
<DMRoot dir="ltr" open={isOpen} onOpenChange={onOpenChange}>
|
||||
{children}
|
||||
</DMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export interface DropdownMenuSubMenuProps {
|
||||
label: string
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuSubMenu({
|
||||
children,
|
||||
disabled = false,
|
||||
label,
|
||||
}: DropdownMenuSubMenuProps): JSX.Element {
|
||||
return (
|
||||
<DMRoot dir="ltr">
|
||||
<DMTriggerItem as={RowButton} bp={breakpoints} disabled={disabled}>
|
||||
<span>{label}</span>
|
||||
<IconWrapper size="small">
|
||||
<ChevronRightIcon />
|
||||
</IconWrapper>
|
||||
</DMTriggerItem>
|
||||
<DMContent as={MenuContent} sideOffset={2} alignOffset={-2}>
|
||||
{children}
|
||||
<DropdownMenuArrow offset={13} />
|
||||
</DMContent>
|
||||
</DMRoot>
|
||||
)
|
||||
}
|
||||
|
||||
export const DropdownMenuDivider = styled(DMSeparator, {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
marginTop: '$2',
|
||||
marginRight: '-$2',
|
||||
marginBottom: '$2',
|
||||
marginLeft: '-$2',
|
||||
})
|
||||
|
||||
export const DropdownMenuArrow = styled(DMArrow, {
|
||||
fill: '$panel',
|
||||
})
|
||||
|
||||
export interface DropdownMenuButtonProps {
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: DropdownMenuButtonProps): JSX.Element {
|
||||
return (
|
||||
<DMItem as={RowButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</DMItem>
|
||||
)
|
||||
}
|
||||
|
||||
interface DropdownMenuIconButtonProps {
|
||||
onSelect: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuIconButton({
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: DropdownMenuIconButtonProps): JSX.Element {
|
||||
return (
|
||||
<DMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
|
||||
{children}
|
||||
</DMItem>
|
||||
)
|
||||
}
|
||||
|
||||
interface DropdownMenuIconTriggerButtonProps {
|
||||
label: string
|
||||
kbd?: string
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuIconTriggerButton({
|
||||
label,
|
||||
kbd,
|
||||
children,
|
||||
disabled = false,
|
||||
}: DropdownMenuIconTriggerButtonProps): JSX.Element {
|
||||
return (
|
||||
<DMTrigger as={IconButton} bp={breakpoints} disabled={disabled}>
|
||||
<Tooltip label={label} kbd={kbd}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
</DMTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
interface MenuCheckboxItemProps {
|
||||
checked: boolean
|
||||
disabled?: boolean
|
||||
onCheckedChange: (isChecked: boolean) => void
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export function DropdownMenuCheckboxItem({
|
||||
checked,
|
||||
disabled = false,
|
||||
onCheckedChange,
|
||||
children,
|
||||
}: MenuCheckboxItemProps): JSX.Element {
|
||||
return (
|
||||
<DMCheckboxItem
|
||||
as={RowButton}
|
||||
bp={breakpoints}
|
||||
onCheckedChange={onCheckedChange}
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
>
|
||||
{children}
|
||||
<DMItemIndicator>
|
||||
<IconWrapper size="small">
|
||||
<CheckIcon />
|
||||
</IconWrapper>
|
||||
</DMItemIndicator>
|
||||
</DMCheckboxItem>
|
||||
)
|
||||
}
|
44
packages/tldraw/src/components/shared/floating-container.tsx
Normal file
44
packages/tldraw/src/components/shared/floating-container.tsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Floating Container */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const FloatingContainer = styled('div', {
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
borderRadius: '4px',
|
||||
boxShadow: '$4',
|
||||
display: 'flex',
|
||||
height: 'fit-content',
|
||||
padding: '$0',
|
||||
pointerEvents: 'all',
|
||||
position: 'relative',
|
||||
userSelect: 'none',
|
||||
zIndex: 200,
|
||||
|
||||
variants: {
|
||||
direction: {
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
column: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
},
|
||||
elevation: {
|
||||
0: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
2: {
|
||||
boxShadow: '$2',
|
||||
},
|
||||
3: {
|
||||
boxShadow: '$3',
|
||||
},
|
||||
4: {
|
||||
boxShadow: '$4',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
84
packages/tldraw/src/components/shared/icon-button.tsx
Normal file
84
packages/tldraw/src/components/shared/icon-button.tsx
Normal file
|
@ -0,0 +1,84 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Icon Button */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const IconButton = styled('button', {
|
||||
position: 'relative',
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
backgroundColor: '$panel',
|
||||
borderRadius: '4px',
|
||||
padding: '0',
|
||||
margin: '0',
|
||||
display: 'grid',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
pointerEvents: 'all',
|
||||
fontSize: '$0',
|
||||
color: '$text',
|
||||
cursor: 'pointer',
|
||||
|
||||
'& > *': {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
opacity: '0.5',
|
||||
},
|
||||
|
||||
'& > span': {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
variants: {
|
||||
bp: {
|
||||
mobile: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
small: {
|
||||
'&:hover:not(:disabled)': {
|
||||
backgroundColor: '$hover',
|
||||
},
|
||||
},
|
||||
},
|
||||
size: {
|
||||
small: {
|
||||
height: 32,
|
||||
width: 32,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '18px',
|
||||
width: '18px',
|
||||
},
|
||||
},
|
||||
large: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '20px',
|
||||
width: '20px',
|
||||
},
|
||||
},
|
||||
},
|
||||
isActive: {
|
||||
true: {
|
||||
color: '$selected',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
47
packages/tldraw/src/components/shared/icon-wrapper.tsx
Normal file
47
packages/tldraw/src/components/shared/icon-wrapper.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Icon Wrapper */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const IconWrapper = styled('div', {
|
||||
height: '100%',
|
||||
borderRadius: '4px',
|
||||
marginRight: '1px',
|
||||
display: 'grid',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
pointerEvents: 'all',
|
||||
cursor: 'pointer',
|
||||
color: '$text',
|
||||
|
||||
'& svg': {
|
||||
height: 22,
|
||||
width: 22,
|
||||
strokeWidth: 1,
|
||||
},
|
||||
|
||||
'& > *': {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
|
||||
variants: {
|
||||
size: {
|
||||
small: {
|
||||
'& svg': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
},
|
||||
medium: {
|
||||
'& svg': {
|
||||
height: '22px',
|
||||
width: '22px',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
13
packages/tldraw/src/components/shared/index.ts
Normal file
13
packages/tldraw/src/components/shared/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
export * from './breakpoints'
|
||||
export * from './buttons-row'
|
||||
export * from './context-menu'
|
||||
export * from './dialog'
|
||||
export * from './dropdown-menu'
|
||||
export * from './floating-container'
|
||||
export * from './icon-button'
|
||||
export * from './icon-wrapper'
|
||||
export * from './kbd'
|
||||
export * from './menu'
|
||||
export * from './radio-group'
|
||||
export * from './row-button'
|
||||
export * from './tooltip'
|
|
@ -2,6 +2,10 @@ import * as React from 'react'
|
|||
import styled from '~styles'
|
||||
import { Utils } from '@tldraw/core'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Keyboard Shortcut */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export function commandKey(): string {
|
||||
return Utils.isDarwin() ? '⌘' : 'Ctrl'
|
||||
}
|
61
packages/tldraw/src/components/shared/menu.tsx
Normal file
61
packages/tldraw/src/components/shared/menu.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { breakpoints } from './breakpoints'
|
||||
import styled from '~styles'
|
||||
import { RowButton } from './row-button'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Menu */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const MenuContent = styled('div', {
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
userSelect: 'none',
|
||||
zIndex: 180,
|
||||
minWidth: 180,
|
||||
pointerEvents: 'all',
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
padding: '$0',
|
||||
boxShadow: '$4',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
})
|
||||
|
||||
export const Divider = styled('div', {
|
||||
backgroundColor: '$hover',
|
||||
height: 1,
|
||||
marginTop: '$2',
|
||||
marginRight: '-$2',
|
||||
marginBottom: '$2',
|
||||
marginLeft: '-$2',
|
||||
})
|
||||
|
||||
export function MenuButton({
|
||||
warn,
|
||||
onSelect,
|
||||
children,
|
||||
disabled = false,
|
||||
}: {
|
||||
warn?: boolean
|
||||
onSelect?: () => void
|
||||
disabled?: boolean
|
||||
children: React.ReactNode
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<RowButton bp={breakpoints} disabled={disabled} warn={warn} onSelect={onSelect}>
|
||||
{children}
|
||||
</RowButton>
|
||||
)
|
||||
}
|
||||
|
||||
export const MenuTextInput = styled('input', {
|
||||
backgroundColor: '$panel',
|
||||
border: 'none',
|
||||
padding: '$4 $3',
|
||||
width: '100%',
|
||||
outline: 'none',
|
||||
background: '$input',
|
||||
borderRadius: '4px',
|
||||
font: '$ui',
|
||||
fontSize: '$1',
|
||||
})
|
10
packages/tldraw/src/components/shared/radio-group.tsx
Normal file
10
packages/tldraw/src/components/shared/radio-group.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import styled from '~styles'
|
||||
import { Root as RGRoot } from '@radix-ui/react-radio-group'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Radio Group */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const Group = styled(RGRoot, {
|
||||
display: 'flex',
|
||||
})
|
101
packages/tldraw/src/components/shared/row-button.tsx
Normal file
101
packages/tldraw/src/components/shared/row-button.tsx
Normal file
|
@ -0,0 +1,101 @@
|
|||
import styled from '~styles'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Row Button */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
export const RowButton = styled('button', {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
background: 'none',
|
||||
height: '32px',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
color: '$text',
|
||||
outline: 'none',
|
||||
alignItems: 'center',
|
||||
fontFamily: '$ui',
|
||||
fontWeight: 400,
|
||||
fontSize: '$1',
|
||||
justifyContent: 'space-between',
|
||||
padding: '4px 8px 4px 12px',
|
||||
borderRadius: 4,
|
||||
userSelect: 'none',
|
||||
|
||||
'& label': {
|
||||
fontWeight: '$1',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
},
|
||||
|
||||
'& svg': {
|
||||
position: 'relative',
|
||||
stroke: '$overlay',
|
||||
strokeWidth: 1,
|
||||
zIndex: 1,
|
||||
},
|
||||
|
||||
'&[data-disabled]': {
|
||||
opacity: 0.3,
|
||||
},
|
||||
|
||||
'&:disabled': {
|
||||
opacity: 0.3,
|
||||
},
|
||||
|
||||
variants: {
|
||||
bp: {
|
||||
mobile: {},
|
||||
small: {
|
||||
'& *[data-shy="true"]': {
|
||||
opacity: 0,
|
||||
},
|
||||
'&:hover:not(:disabled)': {
|
||||
backgroundColor: '$hover',
|
||||
'& *[data-shy="true"]': {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
size: {
|
||||
icon: {
|
||||
padding: '4px ',
|
||||
width: 'auto',
|
||||
},
|
||||
},
|
||||
variant: {
|
||||
noIcon: {
|
||||
padding: '4px 12px',
|
||||
},
|
||||
pageButton: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '24px auto',
|
||||
width: '100%',
|
||||
paddingLeft: '$1',
|
||||
gap: '$3',
|
||||
justifyContent: 'flex-start',
|
||||
[`& > *[data-state="checked"]`]: {
|
||||
gridRow: 1,
|
||||
gridColumn: 1,
|
||||
},
|
||||
'& > span': {
|
||||
gridRow: 1,
|
||||
gridColumn: 2,
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
warn: {
|
||||
true: {
|
||||
color: '$warn',
|
||||
},
|
||||
},
|
||||
isActive: {
|
||||
true: {
|
||||
backgroundColor: '$hover',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
|
@ -3,6 +3,10 @@ import * as React from 'react'
|
|||
import styled from '~styles'
|
||||
import { Kbd } from './kbd'
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Tooltip */
|
||||
/* -------------------------------------------------- */
|
||||
|
||||
interface TooltipProps {
|
||||
children: React.ReactNode
|
||||
label: string
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react'
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import { BoxIcon, StyleDropdownItem, StyleDropdownContent } from './shared'
|
||||
import { BoxIcon, StyleDropdownItem, StyleDropdownContent } from './styled'
|
||||
import { DropdownMenuIconTriggerButton } from '../shared'
|
||||
import { strokes } from '~shape'
|
||||
import { useTheme, useTLDrawContext } from '~hooks'
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
DashDashedIcon,
|
||||
StyleDropdownContent,
|
||||
StyleDropdownItem,
|
||||
} from './shared'
|
||||
} from './styled'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import { DashStyle, Data } from '~types'
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import * as React from 'react'
|
||||
import * as Checkbox from '@radix-ui/react-checkbox'
|
||||
import { breakpoints, IconButton, IconWrapper } from '../shared'
|
||||
import { BoxIcon, IsFilledFillIcon } from './shared'
|
||||
import { Tooltip } from '../tooltip'
|
||||
import { BoxIcon, IsFilledFillIcon } from './styled'
|
||||
import { breakpoints, Tooltip, IconButton, IconWrapper } from '../shared'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import type { Data } from '~types'
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import * as React from 'react'
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import { DropdownMenuIconTriggerButton, CircleIcon } from '../shared'
|
||||
import { StyleDropdownContent, StyleDropdownItem } from './shared'
|
||||
import { DropdownMenuIconTriggerButton } from '../shared/dropdown-menu'
|
||||
import { CircleIcon } from '../icons'
|
||||
import { StyleDropdownContent, StyleDropdownItem } from './styled'
|
||||
import { Data, SizeStyle } from '~types'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react'
|
||||
import { IconButton, ButtonsRow, breakpoints } from '../shared'
|
||||
import { Trash } from '../icons'
|
||||
import { Tooltip } from '../tooltip'
|
||||
import { Tooltip } from '../shared/tooltip'
|
||||
import {
|
||||
ArrowDownIcon,
|
||||
ArrowUpIcon,
|
||||
|
|
|
@ -9,8 +9,8 @@ import { QuickColorSelect } from './quick-color-select'
|
|||
import { QuickSizeSelect } from './quick-size-select'
|
||||
import { QuickDashSelect } from './quick-dash-select'
|
||||
import { QuickFillSelect } from './quick-fill-select'
|
||||
import { Tooltip } from '../tooltip'
|
||||
import { Kbd } from '../kbd'
|
||||
import { Tooltip } from '../shared/tooltip'
|
||||
import { Kbd } from '../shared/kbd'
|
||||
import {
|
||||
IconButton,
|
||||
ButtonsRow,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react'
|
||||
import { FloatingContainer } from '../shared'
|
||||
import { Tooltip } from '../tooltip'
|
||||
import { Tooltip } from '../shared/tooltip'
|
||||
import styled from '~styles'
|
||||
|
||||
export const ToolButton = styled('button', {
|
|
@ -14,7 +14,7 @@ import { Data, TLDrawShapeType } from '~types'
|
|||
import { useTLDrawContext } from '~hooks'
|
||||
import { StatusBar } from './status-bar'
|
||||
import { FloatingContainer } from '../shared'
|
||||
import { PrimaryButton, SecondaryButton } from './shared'
|
||||
import { PrimaryButton, SecondaryButton } from './styled'
|
||||
import { UndoRedo } from './undo-redo'
|
||||
import { Zoom } from './zoom'
|
||||
import { BackToContent } from './back-to-content'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './styled'
|
||||
import { Undo, Redo, Trash } from '../icons'
|
||||
|
||||
export const UndoRedo = React.memo((): JSX.Element => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react'
|
||||
import { ZoomInIcon, ZoomOutIcon } from '@radix-ui/react-icons'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './styled'
|
||||
import { useTLDrawContext } from '~hooks'
|
||||
import type { Data } from '~types'
|
||||
|
||||
|
|
Loading…
Reference in a new issue