react-konva-grid
Version:
Declarative React Canvas Grid primitive for Data table, Pivot table, Excel Worksheets
164 lines • 6.83 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const helpers_1 = require("./../helpers");
const types_1 = require("../types");
/**
* Copy paste hook
* Usage
*
* useCopyPaste ({
* onPaste: (text) => {
* }
* })
*/
const useCopyPaste = ({ selections = [], activeCell = null, getValue, gridRef, onPaste, onCut, }) => {
const selectionRef = react_1.useRef({ selections, activeCell, getValue });
const cutSelections = react_1.useRef(null);
/* Keep selections and activeCell upto date */
react_1.useEffect(() => {
selectionRef.current = { selections, activeCell, getValue };
});
const currentSelections = () => {
const sel = selectionRef.current.selections.length
? selectionRef.current.selections
: helpers_1.selectionFromActiveCell(selectionRef.current.activeCell);
return sel[sel.length - 1];
};
react_1.useEffect(() => {
if (!gridRef.current)
return;
document.addEventListener("copy", (e) => {
var _a;
if (((_a = gridRef.current) === null || _a === void 0 ? void 0 : _a.container) !== document.activeElement)
return;
handleCopy(e);
});
document.addEventListener("paste", (e) => {
var _a;
if (((_a = gridRef.current) === null || _a === void 0 ? void 0 : _a.container) !== document.activeElement)
return;
handlePaste(e);
});
document.addEventListener("cut", (e) => {
var _a;
if (((_a = gridRef.current) === null || _a === void 0 ? void 0 : _a.container) !== document.activeElement)
return;
cutSelections.current = currentSelections();
handleCopy(e);
});
}, []);
const handleCopy = react_1.useCallback((e) => {
var _a, _b, _c, _d, _e;
/* Only copy the last selection */
const { bounds } = currentSelections();
const { top, left, right, bottom } = bounds;
const rows = [];
for (let i = top; i <= bottom; i++) {
const row = [];
for (let j = left; j <= right; j++) {
const value = (_a = selectionRef.current.getValue({ rowIndex: i, columnIndex: j })) !== null && _a !== void 0 ? _a : "";
row.push(value);
}
rows.push(row);
}
const [html, csv] = helpers_1.prepareClipboardData(rows);
(_b = e.clipboardData) === null || _b === void 0 ? void 0 : _b.setData(types_1.MimeType.html, html);
(_c = e.clipboardData) === null || _c === void 0 ? void 0 : _c.setData(types_1.MimeType.plain, csv);
(_d = e.clipboardData) === null || _d === void 0 ? void 0 : _d.setData(types_1.MimeType.csv, csv);
(_e = e.clipboardData) === null || _e === void 0 ? void 0 : _e.setData(types_1.MimeType.json, JSON.stringify(rows));
e.preventDefault();
}, [currentSelections]);
const handlePaste = (e) => {
var _a, _b;
const items = (_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.items;
if (!items)
return;
const mimeTypes = [types_1.MimeType.html, types_1.MimeType.csv, types_1.MimeType.plain];
let type;
let value;
for (type of mimeTypes) {
value = (_b = e.clipboardData) === null || _b === void 0 ? void 0 : _b.getData(type);
if (value)
break;
}
if (!type || !value) {
console.warn("No clipboard data to paste");
return;
}
const rows = [];
if (/^text\/html/.test(type)) {
const domparser = new DOMParser();
const doc = domparser.parseFromString(value, type);
const supportedNodes = "table, p, h1, h2, h3, h4, h5, h6";
const nodes = doc.querySelectorAll(supportedNodes);
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node.nodeName === "TABLE") {
const tableRows = doc.querySelectorAll("tr");
for (const tableRow of tableRows) {
const row = [];
const cells = tableRow.querySelectorAll("td");
for (const cell of cells) {
row.push(cell.textContent);
}
rows.push(row);
}
}
else {
// Single nodes
rows.push([node.textContent]);
}
}
}
else {
const values = value.split("\n");
for (const val of values) {
const row = [];
for (const cell of val.split(",")) {
row.push(cell.replace(/^\"|\"$/gi, ""));
}
rows.push(row);
}
}
onPaste && onPaste(rows, selectionRef.current.activeCell);
/* Clear all values in cut */
if (cutSelections.current) {
onCut && onCut(cutSelections.current);
cutSelections.current = null;
}
};
/**
* User is trying to copy from outisde the app
*/
const handleProgramaticCopy = react_1.useCallback(() => {
gridRef.current.focus();
document.execCommand("copy");
}, []);
/**
* User is trying to paste from outisde the app
*/
const handleProgramaticPaste = react_1.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
gridRef.current.focus();
const text = yield navigator.clipboard.readText();
const clipboardData = new DataTransfer();
clipboardData.setData(types_1.MimeType.plain, text);
const event = new ClipboardEvent("paste", { clipboardData });
handlePaste(event);
}), []);
return {
copy: handleProgramaticCopy,
paste: handleProgramaticPaste,
};
};
exports.default = useCopyPaste;
//# sourceMappingURL=useCopyPaste.js.map