- .cc-shape-header and .cc-shape-toolbar button were missing pointer-events:all, causing toolbar buttons to be unclickable inside tldraw canvas - Replace color:'white' on lock indicator with var(--cc-text-inverse)
98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import React from 'react'
|
|
import { BaseBoxShapeUtil, HTMLContainer, toDomPrecision } from '@tldraw/tldraw'
|
|
import { CCBaseShape } from './cc-types'
|
|
import { logger } from '../../../debugConfig'
|
|
|
|
export interface ToolbarItem {
|
|
id: string
|
|
icon: string | React.ReactNode
|
|
label: string
|
|
onClick: (e: React.MouseEvent, shape: CCBaseShape) => void
|
|
isActive?: boolean
|
|
}
|
|
|
|
export abstract class CCBaseShapeUtil<T extends CCBaseShape> extends BaseBoxShapeUtil<T> {
|
|
abstract renderContent: (shape: T) => React.ReactElement
|
|
|
|
indicator(shape: T) {
|
|
return (
|
|
<rect
|
|
width={shape.props.w}
|
|
height={shape.props.h}
|
|
fill="none"
|
|
rx={CC_BASE_STYLE_CONSTANTS.CONTAINER.borderRadius}
|
|
stroke={CC_BASE_STYLE_CONSTANTS.COLORS.border}
|
|
strokeWidth={CC_BASE_STYLE_CONSTANTS.CONTAINER.borderWidth}
|
|
/>
|
|
)
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
getToolbarItems(shape: T): ToolbarItem[] {
|
|
return []
|
|
}
|
|
|
|
onAfterCreate(shape: T) {
|
|
logger.info('cc-base-shape-util', 'onAfterCreate', shape)
|
|
return shape
|
|
}
|
|
|
|
component(shape: T) {
|
|
const {
|
|
props: { w, h, isLocked, headerColor },
|
|
} = shape
|
|
const toolbarItems = this.getToolbarItems(shape)
|
|
|
|
return (
|
|
<HTMLContainer
|
|
id={shape.id}
|
|
className="cc-shape-container"
|
|
style={{
|
|
width: toDomPrecision(w),
|
|
height: toDomPrecision(h),
|
|
'--shape-header-color': headerColor,
|
|
} as React.CSSProperties}
|
|
>
|
|
{/* Header */}
|
|
<div
|
|
className="cc-shape-header"
|
|
style={{ cursor: isLocked ? 'not-allowed' : 'move' }}
|
|
>
|
|
<span className="shape-title">{shape.props.title}</span>
|
|
<div className="cc-shape-toolbar">
|
|
{toolbarItems.map((item) => (
|
|
<button
|
|
key={item.id}
|
|
title={item.label}
|
|
style={{ opacity: item.isActive ? 1 : 0.7 }}
|
|
onClick={(e) => {
|
|
logger.info('cc-base-shape-util', 'toolbar item clicked', item.id)
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
item.onClick(e, shape)
|
|
}}
|
|
onPointerDown={(e) => {
|
|
logger.info('cc-base-shape-util', 'toolbar item pointer down', item.id)
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
}}
|
|
>
|
|
<div style={{ pointerEvents: 'none' }}>
|
|
{item.icon}
|
|
</div>
|
|
</button>
|
|
))}
|
|
{isLocked && <span style={{ color: 'var(--cc-text-inverse)' }}>🔒</span>}
|
|
</div>
|
|
</div>
|
|
{/* Content */}
|
|
<div
|
|
className="cc-shape-content"
|
|
style={{ backgroundColor: shape.props.backgroundColor }}
|
|
>
|
|
{this.renderContent(shape)}
|
|
</div>
|
|
</HTMLContainer>
|
|
)
|
|
}
|
|
}
|