92 lines
3 KiB
TypeScript
92 lines
3 KiB
TypeScript
import { Box, Icon, IconSrc, color } from 'folds';
|
|
import React, { ReactNode, useRef } from 'react';
|
|
import classNames from 'classnames';
|
|
import * as layoutCss from '../layout/layout.css';
|
|
import { ChannelEventContent } from '../layout/Channel';
|
|
import { useStreamLayoutDebug } from '../layout/streamDebug';
|
|
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
|
|
|
export type EventContentProps = {
|
|
time: ReactNode;
|
|
iconSrc: IconSrc;
|
|
content: ReactNode;
|
|
railStart?: boolean;
|
|
railEnd?: boolean;
|
|
// M3: pick rendering. `'stream'` = 3-track rail/dot grid (DM/Bots).
|
|
// `'channel'` = no-rail flex row (channels timeline). Time slot is
|
|
// dropped for channels — syslines render compact without timestamp.
|
|
layout?: 'stream' | 'channel';
|
|
};
|
|
export function EventContent({
|
|
time,
|
|
iconSrc,
|
|
content,
|
|
railStart,
|
|
railEnd,
|
|
layout = 'stream',
|
|
}: EventContentProps) {
|
|
const compact = useScreenSizeContext() === ScreenSize.Mobile;
|
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
const timeRef = useRef<HTMLSpanElement>(null);
|
|
const railRef = useRef<HTMLSpanElement>(null);
|
|
const dotRef = useRef<HTMLSpanElement>(null);
|
|
const bodyRef = useRef<HTMLDivElement>(null);
|
|
|
|
useStreamLayoutDebug(
|
|
'sysline',
|
|
{
|
|
root: rootRef,
|
|
timeColumn: timeRef,
|
|
rail: railRef,
|
|
dot: dotRef,
|
|
content: bodyRef,
|
|
},
|
|
true
|
|
);
|
|
|
|
if (layout === 'channel') {
|
|
return <ChannelEventContent iconSrc={iconSrc} content={content} />;
|
|
}
|
|
|
|
// Sysline = thin one-line state-event row that lives ON the rail.
|
|
// Same 2-track grid as message rows (StreamRoot) — track 1 dot column,
|
|
// track 2 body — so the dot's X aligns with the dots above and below it.
|
|
// The timestamp trails the body (content → time), mirroring the message
|
|
// header's nick → time order now that the dot leads the row.
|
|
return (
|
|
<div
|
|
className={classNames(layoutCss.StreamRoot({ compact }), layoutCss.StreamSysline)}
|
|
ref={rootRef}
|
|
>
|
|
<span className={layoutCss.StreamDotColumn} aria-hidden>
|
|
<span
|
|
className={classNames(
|
|
layoutCss.StreamRail,
|
|
railStart && railEnd && layoutCss.StreamRailSingle,
|
|
railStart && !railEnd && layoutCss.StreamSyslineRailStart,
|
|
railEnd && !railStart && layoutCss.StreamSyslineRailEnd
|
|
)}
|
|
ref={railRef}
|
|
/>
|
|
<span
|
|
className={classNames(layoutCss.StreamDotHalo, layoutCss.StreamSyslineDotHalo)}
|
|
ref={dotRef}
|
|
>
|
|
<span
|
|
className={layoutCss.StreamDotFill}
|
|
style={{ backgroundColor: color.Surface.OnContainer, opacity: 0.42 }}
|
|
/>
|
|
</span>
|
|
</span>
|
|
<Box gap="200" alignItems="Center" style={{ minWidth: 0 }} ref={bodyRef}>
|
|
<Icon style={{ opacity: 0.5, flexShrink: 0 }} size="50" src={iconSrc} />
|
|
<div className={layoutCss.StreamSyslineBody}>{content}</div>
|
|
{time && (
|
|
<span className={layoutCss.StreamSyslineTime} ref={timeRef}>
|
|
{time}
|
|
</span>
|
|
)}
|
|
</Box>
|
|
</div>
|
|
);
|
|
}
|