summaryrefslogtreecommitdiff
path: root/packages/tweetdeck/src/components/ColumnBoard.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tweetdeck/src/components/ColumnBoard.tsx')
-rw-r--r--packages/tweetdeck/src/components/ColumnBoard.tsx93
1 files changed, 93 insertions, 0 deletions
diff --git a/packages/tweetdeck/src/components/ColumnBoard.tsx b/packages/tweetdeck/src/components/ColumnBoard.tsx
new file mode 100644
index 0000000..87da3e1
--- /dev/null
+++ b/packages/tweetdeck/src/components/ColumnBoard.tsx
@@ -0,0 +1,93 @@
+import { useMemo } from "react";
+import type {
+ ColumnSnapshot,
+ ColumnState,
+ DeckAccount,
+ DeckColumn,
+ FullscreenState,
+} from "../types/app";
+import { TimelineColumn, type TimelineConfig } from "./TimelineColumn";
+import { ChatColumn } from "./ChatColumn";
+
+interface ColumnBoardProps {
+ columns: DeckColumn[];
+ accounts: DeckAccount[];
+ onRemove: (id: string) => void;
+ onStateChange: (columnId: string, state: ColumnState) => void;
+ onSnapshot: (columnId: string, snapshot: ColumnSnapshot) => void;
+ onEnterFullscreen: (payload: FullscreenState) => void;
+}
+
+export function ColumnBoard({
+ columns,
+ accounts,
+ onRemove,
+ onStateChange,
+ onSnapshot,
+ onEnterFullscreen,
+}: ColumnBoardProps) {
+ const accountMap = useMemo(
+ () => Object.fromEntries(accounts.map(account => [account.id, account])),
+ [accounts],
+ );
+
+ if (!columns.length) {
+ return (
+ <section className="empty-board">
+ <p className="eyebrow">No columns yet</p>
+ <h2>Build your deck</h2>
+ <p>Add some columns from the left panel to start streaming timelines.</p>
+ </section>
+ );
+ }
+
+ return (
+ <section className="column-board">
+ {columns.map((column, columnIndex) => {
+ const account = accountMap[column.accountId];
+ if (!account) {
+ return (
+ <div className="column missing" key={column.id}>
+ <header>
+ <div>
+ <p className="eyebrow">Account missing</p>
+ <h3>{column.title}</h3>
+ </div>
+ <button className="ghost" onClick={() => onRemove(column.id)}>
+ Remove
+ </button>
+ </header>
+ <p className="muted">The account for this column was removed.</p>
+ </div>
+ );
+ }
+ if (isChatColumn(column)) {
+ return (
+ <ChatColumn
+ key={column.id}
+ column={column}
+ account={account}
+ onRemove={() => onRemove(column.id)}
+ />
+ );
+ }
+ return (
+ <TimelineColumn
+ key={column.id}
+ column={column as TimelineConfig}
+ account={account}
+ onRemove={() => onRemove(column.id)}
+ onStateChange={onStateChange}
+ onSnapshot={onSnapshot}
+ onEnterFullscreen={onEnterFullscreen}
+ columnIndex={columnIndex}
+ />
+ );
+ })}
+ </section>
+ );
+}
+
+function isChatColumn(column: DeckColumn): column is DeckColumn & { kind: "chat" } {
+ return column.kind === "chat";
+}