hightable
Version:
A dynamic windowed scrolling table component for react
968 lines (967 loc) • 30.4 kB
JavaScript
import { jsx as m, jsxs as A } from "react/jsx-runtime";
import { useState as O, useCallback as x, createContext as Je, useContext as Xe, useMemo as H, useEffect as T, useRef as K } from "react";
import { flushSync as Ue } from "react-dom";
function Ge(e) {
const n = e.then((t) => (n.resolved = t, t)).catch((t) => {
throw n.rejected = t, t;
});
return n;
}
function we(e) {
const n = Promise.resolve(e);
return n.resolved = e, n;
}
function ge() {
let e, n;
const t = Ge(new Promise((r, o) => {
e = r, n = o;
}));
return t.resolve = e, t.reject = n, t;
}
function Qe(e) {
return {
index: ge(),
cells: Object.fromEntries(e.map((n) => [n, ge()]))
};
}
function Ye(e, n, t) {
const r = new Array(n).fill(null).map(() => Qe(t));
return e.then((o) => {
o.length !== n && console.warn(`Expected ${n} rows, got ${o.length}`), o.forEach(
(i, a) => {
const u = r[a];
if (u === void 0)
throw new Error(`Expected row ${a} to exist`);
for (const s of t) {
const l = u.cells[s];
if (l === void 0)
throw new Error(`Expected cell ${s} to exist in row ${a}`);
i.cells[s] instanceof Promise ? i.cells[s].then((c) => {
l.resolve(c);
}).catch((c) => {
l.reject(c);
}) : l.resolve(i.cells[s]);
}
i.index instanceof Promise ? i.index.then((s) => {
u.index.resolve(s);
}).catch((s) => {
u.index.reject(s);
}) : u.index.resolve(i.index);
}
);
}).catch((o) => {
r.forEach((i) => {
for (const a of Object.values(i.cells))
a.reject(o);
i.index.reject(o);
});
}), r;
}
async function Ze(e) {
const n = e.index, t = Object.values(e.cells), r = Object.keys(e.cells), [o, ...i] = await Promise.all([n, ...t]);
return {
index: o,
cells: Object.fromEntries(r.map((a, u) => [a, i[u]]))
};
}
function Mn(e) {
return Promise.all(e.map(Ze));
}
function en(e) {
return e.getColumn ? e.getColumn : function({ column: t, start: r = 0, end: o = e.numRows }) {
if (!e.header.includes(t))
throw new Error(`Invalid column: ${t}`);
return Promise.all(e.rows({ start: r, end: o }).map((i) => i.cells[t]));
};
}
async function Ee({ data: e, column: n }) {
if (!e.header.includes(n))
throw new Error(`Invalid column: ${n}`);
const r = (await en(e)({ column: n })).map((u, s) => ({ value: u, index: s })), o = Array.from(r).sort(({ value: u }, { value: s }) => u < s ? -1 : u > s ? 1 : 0), i = o.length;
return o.reduce(({ lastValue: u, lastRank: s, ranks: l }, { value: c, index: h }, w) => c === u ? (l[h] = s, { ranks: l, lastValue: u, lastRank: s }) : (l[h] = w, { ranks: l, lastValue: c, lastRank: w }), { ranks: Array(i).fill(-1), lastValue: void 0, lastRank: 0 }).ranks;
}
function Ie(e) {
if (!(0 in e))
throw new Error("orderBy should have at least one element");
const n = e[0].ranks.length;
return Array.from({ length: n }, (o, i) => i).sort((o, i) => {
for (const { direction: a, ranks: u } of e) {
const s = u[o], l = u[i];
if (s === void 0 || l === void 0)
throw new Error("Invalid ranks");
const c = a === "ascending" ? 1 : -1;
if (s < l) return -c;
if (s > l) return c;
}
return 0;
});
}
function Se({ data: e }) {
const { numRows: n } = e, t = Array.from({ length: n }, (r, o) => o);
return Promise.resolve(t);
}
function Nn(e) {
if (e.sortable) return e;
const n = /* @__PURE__ */ new Map();
return {
...e,
rows({ start: t, end: r, orderBy: o }) {
if (o && o.length > 0) {
if (o.some(({ column: c }) => !e.header.includes(c)))
throw new Error(`Invalid orderBy field: ${o.map(({ column: c }) => c).join(", ")}`);
const a = [...o, { column: "", direction: "ascending" }].map(async ({ column: c, direction: h }) => {
const w = n.get(c) ?? (c === "" ? Se({ data: e }) : Ee({ data: e, column: c }));
n.has(c) || n.set(c, w);
const R = await w;
return { column: c, direction: h, ranks: R };
}), l = Promise.all(a).then(Ie).then((c) => c.slice(t, r)).then((c) => Promise.all(
// TODO(SL): optimize to fetch groups of rows instead of individual rows?
// if so: maybe the 'reverse' above should be done after fetching the rows
c.map((h) => {
const w = e.rows({ start: h, end: h + 1 });
if (!(0 in w))
throw new Error("data.rows should have return one async row");
return w[0];
})
));
return Ye(l, r - t, e.header);
} else
return e.rows({ start: t, end: r });
},
sortable: !0
};
}
function Ln(e) {
if (!(0 in e))
return { header: [], numRows: 0, rows: () => [], getColumn: () => Promise.resolve([]) };
const n = Object.keys(e[0]);
return {
header: n,
numRows: e.length,
rows({ start: t, end: r }) {
return e.slice(t, r).map((o, i) => ({
index: we(t + i),
cells: Object.fromEntries(Object.entries(o).map(([a, u]) => [a, we(u)]))
}));
},
getColumn({ column: t, start: r = 0, end: o = e.length }) {
if (!n.includes(t))
throw new Error(`Invalid column: ${t}`);
return Promise.resolve(e.slice(r, o).map((i) => i[t]));
}
};
}
function N(e) {
return Number.isInteger(e) && e >= 0;
}
function Q(e) {
return N(e.start) && N(e.end) && e.end > e.start;
}
function z(e) {
if (e.length === 0)
return !0;
if (e.some((n) => !Q(n)))
return !1;
for (let n = 0; n < e.length - 1; n++) {
const t = e[n], r = e[n + 1];
if (!t || !r || t.end >= r.start)
return !1;
}
return !0;
}
function re({ ranges: e, index: n }) {
if (!N(n))
throw new Error("Invalid index");
if (!z(e))
throw new Error("Invalid ranges");
return e.some((t) => t.start <= n && n < t.end);
}
function ne({ ranges: e, length: n }) {
if (!z(e))
throw new Error("Invalid ranges");
if (n && !N(n))
throw new Error("Invalid length");
return e.length === 1 && 0 in e && e[0].start === 0 && e[0].end === n;
}
function nn({ ranges: e, length: n }) {
if (!z(e))
throw new Error("Invalid ranges");
if (n && !N(n))
throw new Error("Invalid length");
return ne({ ranges: e, length: n }) ? [] : [{ start: 0, end: n }];
}
function oe({ ranges: e, range: n }) {
if (!z(e))
throw new Error("Invalid ranges");
if (!Q(n))
throw new Error("Invalid range");
const t = [], { start: r, end: o } = n;
let i = 0;
for (; i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
if (a.end >= r)
break;
t.push({ ...a }), i++;
}
for (; i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
if (a.start > o)
break;
n.start = Math.min(n.start, a.start), n.end = Math.max(n.end, a.end), i++;
}
for (t.push(n); i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
t.push({ ...a }), i++;
}
return t;
}
function tn({ ranges: e, index: n }) {
return oe({ ranges: e, range: { start: n, end: n + 1 } });
}
function Ce({ ranges: e, range: n }) {
if (!z(e))
throw new Error("Invalid ranges");
if (!Q(n))
throw new Error("Invalid range");
const t = [], { start: r, end: o } = n;
let i = 0;
for (; i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
if (a.end >= r)
break;
t.push({ ...a }), i++;
}
for (; i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
if (a.start >= o)
break;
a.start < r && t.push({ start: a.start, end: r }), a.end > o && t.push({ start: o, end: a.end }), i++;
}
for (; i < e.length; ) {
const a = e[i];
if (!a)
throw new Error("Invalid range");
t.push({ ...a }), i++;
}
return t;
}
function ke({ ranges: e, anchor: n, index: t }) {
if (!z(e))
throw new Error("Invalid ranges");
if (n === void 0)
return e;
if (!N(n))
throw new Error("Invalid anchor");
if (!N(t))
throw new Error("Invalid index");
if (n === t)
return e;
const r = n < t ? { start: n, end: t + 1 } : { start: t, end: n + 1 };
if (!Q(r))
throw new Error("Invalid range");
return re({ ranges: e, index: n }) ? oe({ ranges: e, range: r }) : Ce({ ranges: e, range: r });
}
function rn({ ranges: e, index: n }) {
if (!N(n))
throw new Error("Invalid index");
const t = { start: n, end: n + 1 };
return re({ ranges: e, index: n }) ? Ce({ ranges: e, range: t }) : oe({ ranges: e, range: t });
}
function on({ selection: e, index: n }) {
return { ranges: rn({ ranges: e.ranges, index: n }), anchor: n };
}
function sn({ selection: e, index: n }) {
return { ranges: ke({ ranges: e.ranges, anchor: e.anchor, index: n }), anchor: e.anchor };
}
function ln(e) {
const n = e.length, t = Array(n).fill(-1);
return e.forEach((r, o) => {
if (r < 0 || r >= n)
throw new Error("Invalid index: out of bounds");
if (!Number.isInteger(r))
throw new Error("Invalid index: not an integer");
if (t[r] !== -1)
throw new Error("Duplicate index");
t[r] = o;
}), t;
}
function ve({ index: e, array: n }) {
const t = n[e];
if (t === void 0)
throw new Error("Data index not found in the data frame");
return t;
}
function me({ selection: e, permutationIndexes: n }) {
const t = n.length, { ranges: r, anchor: o } = e;
if (!z(e.ranges))
throw new Error("Invalid ranges");
if (o !== void 0 && !N(o))
throw new Error("Invalid anchor");
let i = [];
if (r.length === 0)
i = [];
else if (r.length === 1 && 0 in r && r[0].start === 0 && r[0].end === t)
i = [{ start: 0, end: t }];
else
for (const u of r) {
const { start: s, end: l } = u;
for (let c = s; c < l; c++)
i = tn({ ranges: i, index: ve({ index: c, array: n }) });
}
const a = o !== void 0 ? ve({ index: o, array: n }) : void 0;
return { ranges: i, anchor: a };
}
async function cn({
tableIndex: e,
selection: n,
orderBy: t,
data: r,
ranksMap: o,
setRanksMap: i
}) {
if (!r.sortable)
throw new Error("Data frame is not sortable");
const u = [...t, { column: "", direction: "ascending" }].map(({ column: f, direction: S }) => ({
column: f,
direction: S,
ranks: o.get(f) ?? (f === "" ? Se({ data: r }) : Ee({ data: r, column: f }))
}));
u.some(({ column: f }) => !o.has(f)) && i((f) => {
const S = new Map(f);
return u.forEach(({ column: E, ranks: P }) => S.set(E, P)), S;
});
const s = await Promise.all(u.map(async ({ column: f, direction: S, ranks: E }) => ({ column: f, direction: S, ranks: await E }))), l = Ie(s), c = ln(l), h = me({ selection: n, permutationIndexes: c }), { ranges: w, anchor: R } = h, L = { ranges: ke({ ranges: w, anchor: R, index: e }), anchor: R };
return me({ selection: L, permutationIndexes: l });
}
function an(e, n) {
return e.length !== n.length ? !1 : e.every((t, r) => {
const o = n[r];
return o ? t.column === o.column && t.direction === o.direction : !1;
});
}
function un(e, n) {
const t = [];
let r;
const o = [];
for (const i of e)
r ? o.push(i) : i.column === n ? r = i : t.push(i);
return { prefix: t, item: r, suffix: o };
}
function fn(e, n) {
const { prefix: t, item: r, suffix: o } = un(n, e);
return r && t.length === 0 ? r.direction === "ascending" ? [{ column: e, direction: "descending" }, ...o] : [...o] : [{ column: e, direction: "ascending" }, ...t, ...o];
}
function dn(e) {
const n = e ? `${e}px` : void 0;
return { minWidth: n, maxWidth: n };
}
function hn(e) {
return { minWidth: e ? `${e}px` : void 0 };
}
function pe(e) {
const n = window.getComputedStyle(e), t = parseInt(n.paddingLeft) + parseInt(n.paddingRight);
return e.offsetWidth - t;
}
function Re(e) {
const n = localStorage.getItem(e);
return n ? JSON.parse(n) : void 0;
}
function be({ key: e, value: n }) {
e !== void 0 && (n === void 0 ? localStorage.removeItem(e) : localStorage.setItem(e, JSON.stringify(n)));
}
function wn({ key: e } = {}) {
const [n, t] = O(void 0), [r, o] = O(void 0);
e !== r && (e !== void 0 && t(Re(e)), o(e));
const i = x((a) => {
if (typeof a == "function") {
const u = a;
if (e === void 0)
t(u);
else {
const s = Re(e), l = u(s);
t(l), be({ key: e, value: l });
}
} else {
const u = a;
t(u), be({ key: e, value: u });
}
}, [e]);
return [n, i];
}
const $e = Je({});
function gn({ children: e, localStorageKey: n }) {
const [t, r] = wn({ key: n }), o = x((s) => {
const l = t == null ? void 0 : t[s];
if (l != null) {
if (isNaN(l) || l < 0) {
console.warn(`Invalid column width for column index ${s}: ${l}. Ignoring it.`);
return;
}
return l;
}
}, [t]), i = x((s) => dn(o(s)), [o]), a = x(({ columnIndex: s, width: l }) => {
r((c) => {
if (l !== void 0 && (isNaN(l) || l < 0))
throw new Error(`Invalid column width: ${l}`);
if ((c == null ? void 0 : c[s]) === l)
return c;
const h = [...c ?? []];
return l === void 0 ? h[s] = void 0 : h[s] = l, h;
});
}, [r]), u = H(() => ({
getColumnWidth: o,
getColumnStyle: i,
setColumnWidth: a
}), [o, i, a]);
return /* @__PURE__ */ m($e.Provider, { value: u, children: e });
}
function Oe() {
return Xe($e);
}
function ye(e) {
const { value: n, onChange: t, defaultValue: r, disabled: o } = e, [i] = O(n), [a] = O(o ?? !1), [u, s] = O(r), l = i !== void 0;
let c = !0, h;
a ? (h = void 0, c = !1) : l ? (n === void 0 ? (console.warn("The value is controlled (it has no local state) because the property was initially defined. It cannot be set to undefined now (it is set back to the initial value)."), h = i) : h = n, c = t !== void 0) : (n !== void 0 && console.warn("The value is uncontrolled (it only has a local state) because the property was initially undefined. It cannot be set to a value now and is ignored."), h = u, c = !0);
const w = x((R) => {
c && (t == null || t(R), l || s(R));
}, [t, l, c]);
return { value: h, onChange: w, enableInteractions: c, isControlled: l };
}
function te(e) {
return typeof e == "string" ? e : typeof e == "number" || typeof e == "bigint" ? e.toLocaleString("en-US") : typeof e == "boolean" ? e.toString() : Array.isArray(e) ? `[
${e.map((n) => vn(te(n), 2)).join(`,
`)}
]` : e == null ? JSON.stringify(e) : e instanceof Date ? e.toISOString() : typeof e == "object" ? `{${Object.entries(e).filter((n) => n[1] !== void 0).map(([n, t]) => `${n}: ${te(t)}`).join(", ")}}` : JSON.stringify(e);
}
function vn(e, n) {
return e == null ? void 0 : e.split(`
`).map((t) => " ".repeat(n) + t).join(`
`);
}
function mn(e, n) {
let t = !1, r = !1;
function o() {
e(), r = !1, t = !0, setTimeout(() => {
t = !1, r && o();
}, n);
}
return () => {
t ? r = !0 : o();
};
}
function pn({ onDoubleClick: e, onMouseDown: n, stringify: t, columnIndex: r, value: o, hasResolved: i, className: a }) {
const { getColumnStyle: u } = Oe(), s = u == null ? void 0 : u(r), l = H(() => t(o), [t, o]), c = H(() => {
if (l !== void 0) {
if (l.length > 400)
return `${l.slice(0, 397)}…`;
if (l.length > 100)
return l;
}
}, [l]);
return /* @__PURE__ */ m(
"td",
{
role: "cell",
"aria-busy": !i,
onDoubleClick: e,
onMouseDown: n,
style: s,
className: a,
title: c,
children: l
}
);
}
function U({
children: e,
selected: n,
ariaRowIndex: t,
title: r
}) {
return /* @__PURE__ */ m(
"tr",
{
role: "row",
"aria-rowindex": t,
title: r,
"aria-selected": n,
children: e
}
);
}
function ee({ children: e, checked: n, onClick: t, showCheckBox: r, style: o }) {
return /* @__PURE__ */ A("th", { scope: "row", role: "rowheader", style: o, onClick: t, children: [
/* @__PURE__ */ m("span", { children: e }),
r && /* @__PURE__ */ m("input", { type: "checkbox", disabled: !t, checked: n, readOnly: !0 })
] });
}
function Rn({ children: e, checked: n, onClick: t, showCheckBox: r, style: o }) {
return /* @__PURE__ */ A("td", { "aria-disabled": !r, style: o, onClick: t, children: [
/* @__PURE__ */ m("span", { children: e }),
r && /* @__PURE__ */ m("input", { type: "checkbox", checked: n, readOnly: !0 })
] });
}
function bn({ onDoubleClick: e, setWidth: n, width: t }) {
const [r, o] = O(void 0), i = x((u) => {
u.stopPropagation();
}, []), a = x((u) => {
u.stopPropagation();
const s = t ?? 0;
o(u.clientX - s), n == null || n(s);
}, [n, t]);
return T(() => {
if (r !== void 0) {
const s = function(l) {
return function(c) {
n == null || n(Math.max(1, c.clientX - l));
};
}(r);
return window.addEventListener("mousemove", s), () => {
window.removeEventListener("mousemove", s);
};
}
}, [r, n]), T(() => {
if (r !== void 0) {
const s = function(l) {
return function(c) {
n == null || n(Math.max(1, c.clientX - l)), o(void 0);
};
}(r);
return window.addEventListener("mouseup", s), () => {
window.removeEventListener("mouseup", s);
};
}
}, [r, n]), /* @__PURE__ */ m(
"span",
{
role: "separator",
"aria-orientation": "vertical",
onDoubleClick: e,
onMouseDown: a,
onClick: i
}
);
}
function yn({ columnIndex: e, dataReady: n, direction: t, onClick: r, title: o, sortable: i, ariaPosInSet: a, ariaSetSize: u, className: s, children: l }) {
const c = K(null), { getColumnStyle: h, setColumnWidth: w, getColumnWidth: R } = Oe(), L = h == null ? void 0 : h(e), j = R == null ? void 0 : R(e), f = x((E) => {
w == null || w({ columnIndex: e, width: E });
}, [w, e]);
T(() => {
const E = c.current;
if (n && E) {
const P = pe(E);
isNaN(P) || f(P);
}
}, [n, f]);
const S = x(() => {
const E = c.current;
if (E) {
Ue(() => {
f(void 0);
});
const P = pe(E);
isNaN(P) || f(P);
}
}, [f]);
return /* @__PURE__ */ A(
"th",
{
ref: c,
scope: "col",
role: "columnheader",
"aria-sort": t ?? "none",
"aria-disabled": !i,
"aria-posinset": u !== void 0 ? a : void 0,
"aria-setsize": u,
onClick: r,
style: L,
title: o,
className: s,
children: [
l,
/* @__PURE__ */ m(
bn,
{
setWidth: f,
onDoubleClick: S,
width: j
}
)
]
}
);
}
function xn({
header: e,
orderBy: n,
onOrderByChange: t,
dataReady: r,
sortable: o = !0,
columnClassNames: i = []
}) {
const a = x(
(s) => {
if (!(!t || !n))
return () => {
t(fn(s, n));
};
},
[n, t]
), u = H(() => new Map((n ?? []).map(({ column: s, direction: l }, c) => [s, { direction: l, index: c }])), [n]);
return e.map((s, l) => {
var c, h;
return (
// The ColumnHeader component width is controlled by the parent
/* @__PURE__ */ m(
yn,
{
dataReady: r,
direction: (c = u.get(s)) == null ? void 0 : c.direction,
ariaPosInSet: (h = u.get(s)) == null ? void 0 : h.index,
ariaSetSize: n == null ? void 0 : n.length,
onClick: a(s),
sortable: o,
title: s,
columnIndex: l,
className: i[l],
children: s
},
l
)
);
});
}
function je(e) {
return e === void 0 ? "" : (e + 1).toLocaleString("en-US");
}
function En(e, n) {
const t = Object.keys(e.cells).length;
if (t > 0 && t !== n)
return `Row ${je(e.index)} length ${t} does not match header length ${n}`;
}
const In = "_hightable_o6cvp_1", Sn = "_table-scroll_o6cvp_15", Cn = "_mock-row-label_o6cvp_143", kn = "_styled_o6cvp_155", G = {
hightable: In,
tableScroll: Sn,
mockRowLabel: Cn,
styled: kn
}, xe = 33;
function Vn({
data: e,
cacheKey: n,
overscan: t = 20,
padding: r = 20,
focus: o = !0,
orderBy: i,
onOrderByChange: a,
selection: u,
onSelectionChange: s,
onDoubleClickCell: l,
onMouseDownCell: c,
onError: h = console.error,
stringify: w = te,
className: R = "",
columnClassNames: L = [],
styled: j = !0
}) {
const [f, S] = O(void 0), [E, P] = O({ start: 0, end: 0 }), [Y, ie] = O(!1), [se, le] = O(() => /* @__PURE__ */ new Map()), {
value: D,
onChange: Pe,
enableInteractions: Me
} = ye({
value: i,
onChange: a,
defaultValue: [],
disabled: !e.sortable
}), Ne = u === void 0 && s === void 0, {
value: p,
onChange: _,
enableInteractions: Le,
isControlled: Ve
} = ye({
value: u,
onChange: s,
defaultValue: { ranges: [], anchor: void 0 },
disabled: Ne
}), Z = p !== void 0, ce = Z && Le, Ae = ce || Z && ne({ ranges: p.ranges, length: e.numRows }), De = x(() => {
if (!p) return;
const { ranges: d } = p;
return () => {
_({
ranges: nn({ ranges: d, length: e.numRows }),
anchor: void 0
});
};
}, [_, e.numRows, p]), ae = K(0), _e = x(({ tableIndex: d, dataIndex: g }) => {
if (!p) return;
async function v(b) {
if (!p) return;
if (!(b.shiftKey && p.anchor !== void 0)) {
_(on({ selection: p, index: g }));
return;
}
if (!D || D.length === 0) {
_(sn({ selection: p, index: g }));
return;
}
const $ = ++ae.current, C = await cn({
selection: p,
tableIndex: d,
orderBy: D,
data: e,
ranksMap: se,
setRanksMap: le
});
$ === ae.current && _(C);
}
return (b) => {
v(b);
};
}, [e, _, D, se, p]), ze = H(() => {
if (!p) return !1;
const { ranges: d } = p;
return ne({ ranges: d, length: e.numRows });
}, [p, e.numRows]), Te = x((d) => {
if (!p || d === void 0) return;
const { ranges: g } = p;
return re({ ranges: g, index: d });
}, [p]), W = (e.numRows + 1) * xe, He = f ? Math.max(0, f.offset - r) * xe : 0, F = K(null), ue = K(null), fe = K(0);
f && e !== f.data && (S(void 0), ie(!1), le(/* @__PURE__ */ new Map()), Ve || _({ ranges: [], anchor: void 0 })), T(() => {
function d() {
var M, V;
const v = (M = F.current) == null ? void 0 : M.clientHeight, b = v === void 0 || v === 0 ? 100 : v, k = ((V = F.current) == null ? void 0 : V.scrollTop) ?? 0, $ = Math.floor(e.numRows * k / W), C = Math.ceil(e.numRows * (k + b) / W), y = Math.max(0, $ - t), I = Math.min(e.numRows, C + t);
if (isNaN(y)) throw new Error(`invalid start row ${y}`);
if (isNaN(I)) throw new Error(`invalid end row ${I}`);
if (I - y > 1e3) throw new Error(`attempted to render too many rows ${I - y} table must be contained in a scrollable div`);
P({ start: y, end: I });
}
d();
const g = F.current;
return g == null || g.addEventListener("scroll", d), window.addEventListener("resize", d), () => {
g == null || g.removeEventListener("scroll", d), window.removeEventListener("resize", d);
};
}, [e.numRows, t, r, W]), T(() => {
async function d() {
const { start: g, end: v } = E, b = D ?? [];
if (!(f && f.data === e && g === f.offset && v === f.offset + f.rows.length && an(f.orderedBy, b))) {
if (g === v) {
S({
offset: g,
rows: [],
orderedBy: b,
data: e
});
return;
}
try {
const k = ++fe.current, $ = e.rows({ start: g, end: v, orderBy: b }), C = mn(() => {
const y = [];
for (const M of $) {
const V = { cells: {} };
for (const [J, X] of Object.entries(M.cells))
"resolved" in X && (V.cells[J] = X.resolved);
"resolved" in M.index && (V.index = M.index.resolved), y.push(V);
}
const I = {
offset: g,
rows: y,
orderedBy: b,
data: e
};
if (S(I), !Y) {
const M = new Set(I.data.header);
I.rows.some((V) => {
const J = Object.keys(V.cells);
return J.length === M.size && J.every((X) => M.has(X));
}) && ie(!0);
}
}, 10);
C();
for (const y of $)
for (const I of [y.index, ...Object.values(y.cells)])
I.then(() => {
fe.current === k && C();
});
await Promise.all($.flatMap((y) => [y.index, ...Object.values(y.cells)]));
} catch (k) {
h(k);
}
}
}
d();
}, [e, h, D, f, E, Y]);
const Be = x((d, g) => {
if (!(!l || g === void 0))
return (v) => {
l(v, d, g);
};
}, [l]), Ke = x((d, g) => {
if (!(!c || g === void 0))
return (v) => {
c(v, d, g);
};
}, [c]);
T(() => {
var d;
o && ((d = ue.current) == null || d.focus());
}, [o]);
const q = (f == null ? void 0 : f.offset) ?? 0, de = (f == null ? void 0 : f.rows.length) ?? 0, he = Array.from({ length: Math.min(r, q) }, () => []), We = Array.from({
length: Math.min(r, e.numRows - q - de)
}, () => []), B = H(() => {
const d = Math.ceil(Math.log10(e.numRows + 1)) * 4 + 22;
return hn(d);
}, [e.numRows]);
if (!e.header.length) return;
const Fe = e.header.length + 1, qe = e.numRows + 1;
return /* @__PURE__ */ m(gn, { localStorageKey: `${n}:column-widths`, children: /* @__PURE__ */ A("div", { className: `${G.hightable} ${j ? G.styled : ""} ${R}`, children: [
/* @__PURE__ */ m("div", { className: G.tableScroll, ref: F, children: /* @__PURE__ */ m("div", { style: { height: `${W}px` }, children: /* @__PURE__ */ A(
"table",
{
"aria-readonly": !0,
"aria-colcount": Fe,
"aria-rowcount": qe,
"aria-multiselectable": ce,
ref: ue,
role: "grid",
style: { top: `${He}px` },
tabIndex: 0,
children: [
/* @__PURE__ */ m("thead", { role: "rowgroup", children: /* @__PURE__ */ A(U, { ariaRowIndex: 1, children: [
/* @__PURE__ */ m(
Rn,
{
onClick: De(),
checked: ze,
showCheckBox: Ae,
style: B,
children: " "
}
),
/* @__PURE__ */ m(
xn,
{
dataReady: Y,
header: e.header,
orderBy: D,
onOrderByChange: Pe,
sortable: Me,
columnClassNames: L
}
)
] }) }),
/* @__PURE__ */ A("tbody", { role: "rowgroup", children: [
he.map((d, g) => {
const v = q - he.length + g;
return /* @__PURE__ */ m(U, { ariaRowIndex: v + 2, children: /* @__PURE__ */ m(ee, { style: B }) }, v);
}),
f == null ? void 0 : f.rows.map((d, g) => {
const v = f.offset + g, b = d.index, k = Te(d.index) ?? !1;
return /* @__PURE__ */ A(
U,
{
selected: k,
ariaRowIndex: v + 2,
title: En(d, e.header.length),
children: [
/* @__PURE__ */ m(
ee,
{
style: B,
onClick: b === void 0 ? void 0 : _e({ tableIndex: v, dataIndex: b }),
checked: k,
showCheckBox: Z,
children: je(b)
}
),
e.header.map(($, C) => {
const y = $ in d.cells, I = d.cells[$];
return /* @__PURE__ */ m(
pn,
{
onDoubleClick: Be(C, b),
onMouseDown: Ke(C, b),
stringify: w,
value: I,
columnIndex: C,
hasResolved: y,
className: L[C]
},
C
);
})
]
},
v
);
}),
We.map((d, g) => {
const v = q + de + g;
return /* @__PURE__ */ m(U, { ariaRowIndex: v + 2, children: /* @__PURE__ */ m(ee, { style: B }) }, v);
})
] })
]
}
) }) }),
/* @__PURE__ */ m("div", { className: G.mockRowLabel, style: B, children: " " })
] }) });
}
function An(e) {
const n = {};
let t = 0, r = 0;
return {
...e,
rows({ start: o, end: i, orderBy: a }) {
const u = $n(a), s = n[u] ?? new Array(e.numRows);
u in n || (n[u] = s);
const l = t + r;
l && !(l % 10) && console.log(`Cache hits: ${t} / ${t + r} (${(100 * t / (t + r)).toFixed(1)}%)`);
let c, h = !1;
for (let w = o; w <= i; w++)
if (w < i && !s[w])
c ?? (c = w);
else if (c !== void 0) {
const R = w, L = e.rows({ start: c, end: R, orderBy: a });
for (let j = 0; j < R - c; j++)
s[c + j] = L[j];
c = void 0, h = !0;
}
return h ? r++ : t++, s.slice(o, i).map((w) => {
if (!w)
throw new Error("Row not cached");
return w;
});
}
};
}
function $n(e) {
if (!e || e.length === 0)
return "";
if (!(0 in e))
throw new Error("orderBy should have at least one element");
return JSON.stringify(e);
}
export {
Vn as HighTable,
Ln as arrayDataFrame,
Ye as asyncRows,
Ze as awaitRow,
Mn as awaitRows,
Vn as default,
ge as resolvablePromise,
Qe as resolvableRow,
An as rowCache,
Nn as sortableDataFrame,
te as stringify,
Ge as wrapPromise,
we as wrapResolved
};
//# sourceMappingURL=HighTable.js.map