({
name,
content,
isEnabled,
hasRing,
ringStyles,
onSelect,
actionBar,
}: NoteBlockViewProps)
| 192 | * body (rich text + embeds). Carries no store, socket, or permission coupling. |
| 193 | */ |
| 194 | export function NoteBlockView({ |
| 195 | name, |
| 196 | content, |
| 197 | isEnabled, |
| 198 | hasRing, |
| 199 | ringStyles, |
| 200 | onSelect, |
| 201 | actionBar, |
| 202 | }: NoteBlockViewProps) { |
| 203 | const isEmpty = content.trim().length === 0 |
| 204 | |
| 205 | return ( |
| 206 | <div className='group relative'> |
| 207 | <div |
| 208 | role='button' |
| 209 | tabIndex={0} |
| 210 | className={cn( |
| 211 | 'note-drag-handle relative z-[20] w-[250px] cursor-grab select-none rounded-lg border border-[var(--border)] bg-[var(--surface-2)] [&:active]:cursor-grabbing' |
| 212 | )} |
| 213 | onClick={onSelect} |
| 214 | onKeyDown={(event) => handleKeyboardActivation(event, onSelect)} |
| 215 | > |
| 216 | {actionBar} |
| 217 | |
| 218 | <div className='flex items-center justify-between border-[var(--divider)] border-b p-2'> |
| 219 | <div className='flex min-w-0 flex-1 items-center'> |
| 220 | <span |
| 221 | className={cn( |
| 222 | 'truncate font-medium text-md', |
| 223 | !isEnabled && 'text-[var(--text-muted)]' |
| 224 | )} |
| 225 | title={name} |
| 226 | > |
| 227 | {name} |
| 228 | </span> |
| 229 | </div> |
| 230 | </div> |
| 231 | |
| 232 | <div className='relative overflow-hidden p-2'> |
| 233 | <div className='relative max-w-full break-all'> |
| 234 | {isEmpty ? ( |
| 235 | <p className='text-[var(--text-placeholder)] text-sm'>Add note…</p> |
| 236 | ) : ( |
| 237 | <NoteMarkdown content={content} /> |
| 238 | )} |
| 239 | </div> |
| 240 | </div> |
| 241 | {hasRing && ( |
| 242 | <div className={cn('pointer-events-none absolute inset-0 z-40 rounded-lg', ringStyles)} /> |
| 243 | )} |
| 244 | </div> |
| 245 | </div> |
| 246 | ) |
| 247 | } |
nothing calls this directly
no test coverage detected