Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { useMemo } from "react";
import { flexRender, getCoreRowModel, useReactTable, createColumnHelper } from "@tanstack/react-table";
import { cnm } from "@humansignal/ui";
import { Chip } from "./Chip";
import { ResizeHandler } from "./ResizeHandler";
import type { ObjectTypes } from "./types";
 
export const DataSummary = ({ data_types }: { data_types: ObjectTypes }) => {
  const data: Record<string, any> = useMemo(() => {
    return Object.fromEntries(Object.entries(data_types).map(([field, { value }]) => [field, value]));
  }, [data_types]);
 
  const columns = useMemo(() => {
    const columnHelper = createColumnHelper<Record<string, any>>();
 
    return Object.entries(data_types).map(([field, { type }]) =>
      columnHelper.accessor(field, {
        id: field,
        header: () => (
          <>
            {field} <Chip>{type}</Chip>
          </>
        ),
        cell: ({ getValue }) => {
          const value = getValue();
 
          // super simple support for images, audio, and video
          // @todo create a proper data type handler for all data types
          if (type === "image") {
            return <img src={value} alt={field} className="w-full" />;
          }
 
          if (type === "audio") {
            // biome-ignore lint/a11y/useMediaCaption: that's user's media, captions can't be used
            return <audio src={value} controls className="w-full" />;
          }
 
          if (type === "video") {
            // biome-ignore lint/a11y/useMediaCaption: that's user's media, captions can't be used
            return <video src={value} controls className="w-full" />;
          }
 
          // List: [{ id: <id>, body: text, title: text }, ...]
          // Paragraphs: [{ <nameKey>: name, <textKey>: text }, ...]
          if (Array.isArray(value)) {
            return JSON.stringify(value);
          }
 
          // Timeseries: <channel name>: [array of values]
          // Table: <key>: <value>
          if (typeof value === "object") {
            return Object.entries(value)
              .map(([key, value]) => `${key}: ${String(value).substring(0, 300)}`)
              .join("\n");
          }
 
          return value;
        },
        size: 300,
        maxSize: 800,
      }),
    );
  }, [data_types]);
 
  const table = useReactTable({
    data: [data],
    columns,
    getCoreRowModel: getCoreRowModel(),
    columnResizeMode: "onChange",
    enableColumnResizing: true,
    defaultColumn: {
      minSize: 80,
      maxSize: 800,
    },
  });
 
  return (
    <div className="overflow-x-auto pb-tight mb-base">
      <div className="border border-neutral-border rounded-small border-collapse overflow-hidden w-max">
        <div>
          {table.getHeaderGroups().map((headerGroup) => (
            <div
              key={headerGroup.id}
              className={cnm(
                "flex [&>*]:flex-shrink-0 [&>*]:px-4 [&>*]:py-2 bg-neutral-surface",
                "[&>*]:overflow-hidden [&>*]:text-ellipsis [&>*]:text-left [&>*]:whitespace-nowrap",
              )}
            >
              {headerGroup.headers.map((header) => (
                <div
                  key={header.id}
                  style={{
                    width: header.getSize(),
                    position: "relative",
                  }}
                >
                  {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
                  <ResizeHandler header={header} />
                </div>
              ))}
            </div>
          ))}
        </div>
        <div>
          {table.getRowModel().rows.map((row) => (
            <div
              key={row.id}
              className={cnm(
                "flex [&>*]:flex-shrink-0 even:bg-neutral-surface [&_td]:align-top [&>*]:px-4 [&>*]:py-2",
                "[&>*]:overflow-hidden [&>*]:text-ellipsis",
              )}
            >
              {row.getVisibleCells().map((cell) => (
                <div key={cell.id} style={{ width: cell.column.getSize() }}>
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </div>
              ))}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};