import React from 'react'; // import dynamic from 'next/dynamic' // import {buildURI} from 'react-csv'; // /** // * See https://github.com/react-csv/react-csv/issues/87 // */ export const isSafari = () => /^((?!chrome|android).)*safari/i.test(navigator.userAgent); export const isJsons = ((array) => Array.isArray(array) && array.every( row => (typeof row === 'object' && !(row instanceof Array)) )); export const isArrays = ((array) => Array.isArray(array) && array.every( row => Array.isArray(row) )); export const jsonsHeaders = ((array) => Array.from( array.map(json => Object.keys(json)) .reduce((a, b) => new Set([...a, ...b]), []) )); export const jsons2arrays = (jsons, headers) => { headers = headers || jsonsHeaders(jsons); // allow headers to have custom labels, defaulting to having the header data key be the label let headerLabels = headers; let headerKeys = headers; if (isJsons(headers)) { headerLabels = headers.map((header) => header.label); headerKeys = headers.map((header) => header.key); } const data = jsons.map((object) => headerKeys.map((header) => getHeaderValue(header, object))); return [headerLabels, ...data]; }; export const getHeaderValue = (property, obj) => { const foundValue = property .replace(/\[([^\]]+)]/g, ".$1") .split(".") .reduce(function (o, p, i, arr) { // if at any point the nested keys passed do not exist, splice the array so it doesnt keep reducing const value = o[p]; if (value === undefined || value === null) { arr.splice(1); } else { return value; } }, obj); // if at any point the nested keys passed do not exist then looks for key `property` in object obj return (foundValue === undefined) ? ((property in obj) ? obj[property] : '') : foundValue; } export const elementOrEmpty = (element) => (typeof element === 'undefined' || element === null) ? '' : element; export const joiner = ((data, separator = ',', enclosingCharacter = '"') => { return data .filter(e => e) .map( row => row .map((element) => elementOrEmpty(element)) .map(column => `${enclosingCharacter}${column}${enclosingCharacter}`) .join(separator) ) .join(`\n`); }); export const arrays2csv = ((data, headers, separator, enclosingCharacter) => joiner(headers ? [headers, ...data] : data, separator, enclosingCharacter) ); export const jsons2csv = ((data, headers, separator, enclosingCharacter) => joiner(jsons2arrays(data, headers), separator, enclosingCharacter) ); export const string2csv = ((data, headers, separator) => (headers) ? `${headers.join(separator)}\n${data}` : data.replace(/"/g, '""') ); export const toCSV = (data, headers, separator, enclosingCharacter) => { if (isJsons(data)) return jsons2csv(data, headers, separator, enclosingCharacter); if (isArrays(data)) return arrays2csv(data, headers, separator, enclosingCharacter); if (typeof data === 'string') return string2csv(data, headers, separator); throw new TypeError(`Data should be a "String", "Array of arrays" OR "Array of objects" `); }; const CSVLink = ({filename, data, children, ...rest}) => { const buildURI = ((data, uFEFF, headers, separator, enclosingCharacter) => { const csv = toCSV(data, headers, separator, enclosingCharacter); const type = isSafari() ? 'application/csv' : 'text/csv'; const blob = new Blob([uFEFF ? '\uFEFF' : '', csv], {type}); const dataURI = `data:${type};charset=utf-8,${uFEFF ? '\uFEFF' : ''}${csv}`; const URL = window.URL || window.webkitURL; return (typeof URL.createObjectURL === 'undefined') ? dataURI : URL.createObjectURL(blob); }); const isNodeEnvironment = typeof window === 'undefined'; const uFEFF = true; const headers = undefined; const separator = ","; const enclosingCharacter = '"'; const href = isNodeEnvironment ? '' : buildURI(data, uFEFF, headers, separator, enclosingCharacter) return ( {children} ); } export default CSVLink;