Files
app/src/utils/tldraw/cc-base/CCBaseShapeUtil.tsx
T
CC Worker 061cd22748 fix(shape-css): add pointer-events:all to header/toolbar; fix hardcoded white on lock icon
- .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)
2026-05-31 22:10:08 +00:00

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>
)
}
}