async function PersistentTable(
tableName = "data",
{
value = [],
tableOptions,
storageName = "PersistentTable",
keyName = "data",
label = (widget) =>
`PersistentTable: ${tableName} (${widget.value.length})`,
exportFormat = "csv",
summaryWidget = Inputs.table,
confirm = false
} = {}
) {
tableOptions = { select: false, layout: "fixed", ...tableOptions };
const db = IndexedDBStorage({ storageName, tableName });
let table;
const labelHolder = htl.html`<label></label>`;
const tableHolder = htl.html`<div></div>`;
const clearButton = htl.html`<button>Clear</button>`;
const exportButtonHolder = htl.html`<span></span>`;
const importButton = await dataInput({ value: value, label: "Import" });
const target = htl.html`<div>${labelHolder}
<div style="display: flex"> ${importButton} ${exportButtonHolder} ${clearButton}</div>
${tableHolder}</div>`;
value = (await db.get(keyName)) || value;
const widget = ReactiveWidget(target, { value, showValue });
async function cacheValue(data) {
await db.set(keyName, data);
widget.setValue(data);
}
async function showValue() {
exportButtonHolder.innerHTML = "";
exportButtonHolder.appendChild(
DOM.download(
exportFormat.toLowerCase() === "csv"
? new Blob([d3.csvFormat(widget.value)], { type: "text/csv" })
: new Blob([JSON.stringify(widget.value)], {
type: "application/json"
}),
`${tableName}.${exportFormat}`,
"Export"
)
);
labelHolder.innerHTML = "";
labelHolder.appendChild(htl.html`${label(widget)}`);
tableHolder.innerHTML = "";
table = await summaryWidget(widget.value, {
...tableOptions,
value: table?.value
});
table.addEventListener("input", (evt) => {
evt.preventDefault();
evt.stopPropagation();
});
tableHolder.appendChild(table);
}
clearButton.addEventListener("click", async () => {
const doClear = async () => {
await db.clear(keyName);
cacheValue([]);
};
try {
if (
confirm &&
!window.confirm("Do you want to delete your whole selection?")
) {
return;
}
doClear();
} catch {
doClear();
}
});
importButton.addEventListener("input", () => {
cacheValue(importButton.value);
});
widget.update = cacheValue;
widget.push = (val) => cacheValue(target.value.concat(val));
widget.value = value;
return target;
}