Skip to content

Commit 1874b64

Browse files
committed
refactor hightable demo
1 parent 8770f17 commit 1874b64

File tree

10 files changed

+180
-92
lines changed

10 files changed

+180
-92
lines changed

apps/hightable-demo/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<meta name="viewport" content="width=device-width, initial-scale=1.0">
99
</head>
1010
<body>
11-
<nav>
11+
<nav class="sidebar">
1212
<a class="brand" href='https://hyparam.github.io/hightable/'>
1313
HighTable
1414
</a>

apps/hightable-demo/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"dependencies": {
1717
"hightable": "../../../hightable",
1818
"react": "18.3.1",
19-
"react-dom": "18.3.1"
19+
"react-dom": "18.3.1",
20+
"react-router": "7.1.3"
2021
}
2122
}

apps/hightable-demo/src/App.tsx

Lines changed: 0 additions & 87 deletions
This file was deleted.

apps/hightable-demo/src/Basic.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Layout from './Layout'
2+
3+
import { HighTable } from 'hightable'
4+
import { data } from './data'
5+
6+
export default function Basic() {
7+
return <Layout>
8+
<HighTable data={data} />
9+
</Layout>
10+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { HighTable, OrderBy, Selection } from 'hightable'
2+
import { useState } from 'react'
3+
import { data } from './data'
4+
import Layout from './Layout'
5+
6+
function createRandomSelection(): Selection {
7+
const maxStep = 8
8+
const maxLength = 5
9+
const minRanges = 1
10+
const maxRanges = 5
11+
const numRanges = Math.floor(Math.random() * (maxRanges - minRanges + 1) + minRanges)
12+
const ranges = []
13+
let start = 0
14+
for (let i = 0; i < numRanges; i++) {
15+
const length = Math.floor(Math.random() * maxLength + 1)
16+
const step = Math.floor(Math.random() * maxStep + 1)
17+
start += step
18+
const end = start + length
19+
ranges.push({ start, end })
20+
start = end
21+
}
22+
return { ranges }
23+
}
24+
25+
function createRandomOrderBy(): OrderBy {
26+
const columns = data.header
27+
const column = columns[Math.floor(Math.random() * columns.length)]
28+
return { column }
29+
}
30+
31+
function getNumSelected(selection: Selection): number {
32+
return selection.ranges.reduce((acc, range) => acc + (range.end - range.start), 0)
33+
}
34+
35+
export default function Controlled() {
36+
const [selection, setSelection] = useState<Selection>({ ranges: [] })
37+
const [orderBy, setOrderBy] = useState<OrderBy>({})
38+
39+
const numSelectedRows = getNumSelected(selection)
40+
41+
return <Layout>
42+
<div>{/* <- to collapse margins */}
43+
<section>
44+
<button onClick={() => { setSelection(createRandomSelection()) }}>Set random selection</button>
45+
<button onClick={() => { setSelection({ ranges: [] }) }}>Clear selection</button>
46+
<span>{numSelectedRows.toLocaleString('en-US')} selected {numSelectedRows === 1 ? 'row' : 'rows'}</span>
47+
</section>
48+
<section>
49+
<button onClick={() => { setOrderBy(createRandomOrderBy()) }}>Order by a random column</button>
50+
<button onClick={() => { setOrderBy({}) }}>Clear order</button>
51+
<span>{orderBy.column ? `Ordered by '${orderBy.column}'` : 'Unordered'}</span>
52+
</section>
53+
</div>
54+
<HighTable data={data} selection={selection} onSelectionChange={setSelection} orderBy={orderBy} onOrderByChange={setOrderBy} />
55+
</Layout>
56+
}

apps/hightable-demo/src/Layout.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ReactNode } from 'react'
2+
import { NavLink } from 'react-router'
3+
4+
export default function Layout({ children }: { children: ReactNode }) {
5+
return <div className="layout">
6+
<nav className="topbar">
7+
<span className="title">HighTable demos</span>
8+
{/* NavLink makes it easy to show active states */}
9+
{
10+
[
11+
['Basic', '/'],
12+
['Selection', '/selection'],
13+
['Controlled', '/controlled'],
14+
['Mirror', '/mirror'],
15+
].map(([label, path]) => <NavLink key={path} to={path}
16+
className={ ({ isActive }) => isActive ? 'link active' : 'link' }
17+
>{label}</NavLink>,
18+
)
19+
}
20+
</nav>
21+
<div className="content">
22+
{children}
23+
</div>
24+
</div>
25+
}

apps/hightable-demo/src/Mirror.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { HighTable, OrderBy, Selection } from 'hightable'
2+
import { useState } from 'react'
3+
import Layout from './Layout'
4+
import { data } from './data'
5+
6+
export default function App() {
7+
const [selection, setSelection] = useState<Selection>({ ranges: [] })
8+
const [orderBy, setOrderBy] = useState<OrderBy>({})
9+
10+
return <Layout>
11+
<HighTable data={data} cacheKey='demo' onSelectionChange={setSelection} onOrderByChange={setOrderBy} />
12+
<HighTable data={data} cacheKey='demo' selection={selection} orderBy={orderBy} />
13+
</Layout>
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { HighTable, Selection } from 'hightable'
2+
import { useState } from 'react'
3+
import { data } from './data'
4+
import Layout from './Layout'
5+
6+
export default function SelectionPage() {
7+
const [selection, setSelection] = useState<Selection | undefined>(undefined)
8+
return <Layout>
9+
<section>
10+
Current selection: {JSON.stringify(selection)}
11+
</section>
12+
<HighTable data={data} onSelectionChange={setSelection} />
13+
</Layout>
14+
}

apps/hightable-demo/src/index.css

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ body {
66
}
77

88
/* sidebar */
9-
nav {
9+
nav.sidebar {
1010
height: 100vh;
1111
width: 48px;
1212
background-image: linear-gradient(to bottom, #667, #585669);
@@ -53,4 +53,48 @@ nav {
5353

5454
.table-corner {
5555
background: url('https://hyperparam.app/assets/table/hightable.svg') #e4e4e6 no-repeat center 6px;
56+
}
57+
58+
.layout {
59+
display: flex;
60+
flex: 1;
61+
flex-direction: column;
62+
}
63+
64+
.topbar {
65+
background-color: #fff;
66+
box-shadow: 0 1px 2px rgba(10, 10, 10, 0.1);
67+
display: flex;
68+
//height: 3em;
69+
width: 100%;
70+
71+
padding: 0.5em;
72+
position: sticky;
73+
top: 0;
74+
z-index: 10;
75+
gap: 1em;
76+
}
77+
.topbar .title {
78+
color: #444;
79+
font-weight: bold;
80+
}
81+
.topbar .link {
82+
color: #888;
83+
cursor: pointer;
84+
}
85+
.topbar .link.active {
86+
color: #706fb1;
87+
font-weight: bold;
88+
}
89+
90+
.content {
91+
overflow: hidden;
92+
flex: 1;
93+
display: flex;
94+
flex-direction: column;
95+
}
96+
.content section {
97+
margin: 1em;
98+
display: flex;
99+
gap: 0.5em;
56100
}

apps/hightable-demo/src/main.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
import 'hightable/src/HighTable.css'
22
import ReactDOM from 'react-dom/client'
3-
import App from './App.js'
3+
import { BrowserRouter, Route, Routes } from 'react-router'
4+
import Basic from './Basic.js'
5+
import Controlled from './Controlled.js'
6+
import Mirror from './Mirror.js'
7+
import Selection from './Selection.js'
48
import './index.css'
59

610
const app = document.getElementById('app')
711
if (!app) throw new Error('missing app element')
8-
ReactDOM.createRoot(app).render(<App></App>)
12+
ReactDOM.createRoot(app).render(<BrowserRouter>
13+
<Routes>
14+
<Route path="/" element={<Basic />} />
15+
<Route path="/selection" element={<Selection />} />
16+
<Route path="/controlled" element={<Controlled />} />
17+
<Route path="/mirror" element={<Mirror />} />
18+
</Routes>
19+
</BrowserRouter>)

0 commit comments

Comments
 (0)