Published
Edited
Sep 19, 2022
3 forks
Importers
10 stars
Insert cell
Insert cell
HyperGrid(randomData, { columnWidth: 150 })
Insert cell
Insert cell
Insert cell
HyperGrid(randomData)
Insert cell
Insert cell
HyperGrid(randomData, { tableHeight: 220, itemHeight: 38, columnWidth: 120 })
Insert cell
Insert cell
HyperGrid(randomData, { showHeader: false })
Insert cell
md`## Tall rows / cards`
Insert cell
HyperGrid(randomData, {
showHeader: false,
tableHeight: 450,
itemHeight: 150,
columnWidth: width * .5,
columns: [
{
name: "card",
formatter: row => html`
<div style="background-color: papayawhip; border-radius: 15px; padding: 10px 20px;">
<p><strong>col 1:</strong> ${row.column_one}</p>
<p><strong>col 4:</strong> ${row.column_four}</p>
</div>
`
}
]
})
Insert cell
Insert cell
Insert cell
Insert cell
HyperGrid([])
Insert cell
Insert cell
function HyperGrid(
data,
{
tableHeight = 320,
itemHeight = 28,
showHeader = true,
columns = null,
columnWidth = 120,
columnMargin = 5
} = {}
) {
if (!data) {
return "No data";
} else if (!data.length) {
return "Empty data";
}

const renderColumns = columns
? columns.map(c => {
c.width = c.hasOwnProperty("width") ? c.width : columnWidth;
c.margin = c.hasOwnProperty("margin") ? c.margin : columnMargin;
return c;
})
: Object.keys(data[0]).map(key => ({
name: key,
formatter: defaultFormatter,
width: columnWidth,
margin: columnMargin
}));

// Create a container element or find one that already exists in the DOM.
const parentElement = html`<div class="vtable" style="height: ${tableHeight}px;"></div>`;
const innerElement = document.createElement('div');
parentElement.append(innerElement);

const headerWidth = renderColumns.reduce(
(acc, column) => acc + column.width + column.margin,
0
);

const list = HyperList.create(innerElement, {
width,
itemHeight,
height: tableHeight,
total: data.length,
scrollerElement: "div",

// Handle fixed header by injecting
applyPatch: (element, fragment) => {
// Remove all nodes *but* fixed header
while (
element.lastElementChild &&
!element.lastElementChild.className.includes("vrow-header")
) {
element.removeChild(element.lastElementChild);
}

// Add header once
if (showHeader && !element.lastElementChild) {
element.appendChild(html`
<div class="vrow-inner vrow-header" style="width: ${headerWidth}px;">
${renderColumns.map(column =>
hypergridCell(html`${column.name}`, column, false, itemHeight)
)}
</div>
`);
}
element.appendChild(fragment);
},

// Wire up the data to the index. The index is then mapped to a Y position
// in the container.
generate(index) {
return html`
<div class="vrow-inner">
${renderColumns.map(column =>
hypergridCell(
html`${column.formatter(data[index], column, index, data)}`,
column,
showHeader,
itemHeight
)
)}
</div>`;
}
});

parentElement.append(hypergridStyle());
return parentElement;
}
Insert cell
// Render a single cell
hypergridCell = (content, column, showHeader, itemHeight) => html`
<div style="height: ${itemHeight}px; width: ${column.width}px; margin-right: ${
column.margin
}px; transform: translateY(${showHeader ? itemHeight : 0}px);">
<span>${content}</span>
</div>`
Insert cell
// Default formatter
defaultFormatter = (row, column) => row[column.name]
Insert cell
fontSize = 13
Insert cell
hypergridStyle = () => html`<style>
.vtable {
font-size: 12px;
line-height: 14px;
overflow-x: hidden;
overflow-y: hidden;
font-family: Helvetica Neue, Helvetica, sans-serif;
}
.vrow-inner {
display: flex;
}
.vrow-inner > div {
display: flex;
align-items: center;
}
.vrow-inner > div > span {
display: inline-block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.vrow-header {
position: sticky;
z-index: 99;
left: 0;
top: 0;
background: rgb(221,221,221);
background: linear-gradient(0deg, rgba(255,255,255,1) 15%, rgba(248,248,248,1) 90%);
border-bottom: 1px solid #666;
font-weight: bold;
}
</style>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more