handsontable = (options = {}, update) => {
const height = Math.min(options.data.length * 22 + 42, 642);
const element = html`<div ${
options.style ? `style="${options.style}"` : ""
} />`;
const hot = Handsontable(element, {
width: "100%",
height: 0,
rowHeights: 22,
licenseKey: "non-commercial-and-evaluation",
data: options.data,
outsideClickDeselects: false,
...options
});
const getValue = () => {
const sourceData = hot.getSourceData();
const headers = Array.from(
sourceData.reduce((result, row) => {
for (let header in row) {
result.add(header);
}
return result;
}, new Set())
);
const currentData = hot
.getData()
.map((row) =>
row.reduce(
(result, value, index) => ({ ...result, [headers[index]]: value }),
{}
)
);
if (options.value) {
return options.value(sourceData, currentData);
}
return currentData;
};
const updateElement = () => {
element.value = getValue();
element.dispatchEvent(new CustomEvent("input"));
};
hot.updateSettings({
afterRender: () => {
hot.view.activeWt.wtOverlays?.updateMainScrollableElements();
},
afterChange: (changes, source) => {
updateElement(changes, source);
}
});
element.hot = hot;
element.value = getValue();
invalidation.then(() => element.hot.destroy());
setTimeout(() => {
element.style.height = `${height}px`;
element.hot.refreshDimensions();
}, 300);
return element;
}