function Pack(data, {
path,
id = Array.isArray(data) ? d => d.id : null,
parentId = Array.isArray(data) ? d => d.parentId : null,
children,
value,
sort = (a, b) => d3.descending(a.value, b.value),
label,
title,
cat,
sci_name,
link,
linkTarget = "_blank",
width = 640,
height = 400,
margin = 1,
marginTop = margin,
marginRight = margin,
marginBottom = margin,
marginLeft = margin,
padding = 3,
fill = "#ddd",
fillOpacity,
stroke = "#bbb",
strokeWidth,
strokeOpacity,
} = {}) {
const slugify = str =>
str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
// If id and parentId options are specified, or the path option, use d3.stratify
// to convert tabular data to a hierarchy; otherwise we assume that the data is
// specified as an object {children} with nested objects (a.k.a. the “flare.json”
// format), and use d3.hierarchy.
const root = path != null ? d3.stratify().path(path)(data)
: id != null || parentId != null ? d3.stratify().id(id).parentId(parentId)(data)
: d3.hierarchy(data, children);
// Compute the values of internal nodes by aggregating from the leaves.
value == null ? root.count() : root.sum(d => Math.max(0, value(d)));
// Compute labels and titles.
const descendants = root.descendants();
const leaves = descendants.filter(d => !d.children);
leaves.forEach((d, i) => d.index = i);
const L = label == null ? null : leaves.map(d => label(d.data, d));
const T = title == null ? null : descendants.map(d => title(d.data, d));
const C = cat == null ? null : descendants.map(d => cat(d.data, d));
const SN = sci_name == null ? null : descendants.map(d => sci_name(d.data, d));
// Sort the leaves (typically by descending value for a pleasing layout).
// if (sort != null) root.sort(sort);
// colors
const colors = ["#22AAC9", "#BCCF54", "#8B54D4", "#EF841F", "#BB35B6", "#228C4C", "#F3D053", "#8fa0aa", "#8fa0aa"];
const cats = ['observations-birds', 'observations-fungi-and-lichens', 'observations-insects-and-arachnids', 'observations-mammals-and-other-animals', 'observations-mollusks', 'observations-plants', 'observations-reptiles-and-amphibians', 'observations-ray-finned-fishes', 'observations-chromista-and-protozoa'];
const scale = d3.scaleOrdinal(colors).domain(cats).range(colors);
// Compute the layout.
d3.pack()
.size([width - marginLeft - marginRight, height - marginTop - marginBottom])
.padding(padding)
(root);
const svg = d3.create("svg")
.attr("viewBox", [-marginLeft, -marginTop, width, height])
.attr("width", width)
.attr("height", height)
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle");
const node = svg.selectAll("g")
.data(descendants)
.join("g")
// .attr("xlink:href", link == null ? null : (d, i) => link(d.data, d))
// .attr("target", link == null ? null : linkTarget)
.attr("transform", d => `translate(${d.x},${d.y})`);
node.append("circle")
.attr("fill", (d,i) => d.children ? "#fff" : scale( slugify(C[i]) ) )
.attr("fill-opacity", d => d.children ? null : fillOpacity)
.attr("stroke", d => d.children ? stroke : null)
.attr("stroke-width", d => d.children ? strokeWidth : null)
.attr("stroke-opacity", d => d.children ? strokeOpacity : null)
.attr("r", d => d.r)
.attr("class", (d,i) => slugify(C[i]))
.attr("id", (d,i) => slugify(SN[i]));
if (T) node.append("title").text((d, i) => T[i]);
// if (L) {
// // A unique identifier for clip paths (to avoid conflicts).
// const uid = `O-${Math.random().toString(16).slice(2)}`;
// const leaf = node
// .filter(d => !d.children && d.r > 10 && L[d.index] != null);
// leaf.append("clipPath")
// // .attr("id", d => `${d.category}`)
// .append("circle")
// .attr("r", d => d.r);
// leaf.append("text")
// .attr("clip-path", d => `url(${new URL(`#${uid}-clip-${d.index}`, location)})`)
// .selectAll("tspan")
// .data(d => `${L[d.index]}`.split(/\n/g))
// .join("tspan")
// .attr("x", 0)
// .attr("y", (d, i, D) => `${(i - D.length / 2) + 0.85}em`)
// .attr("fill-opacity", (d, i, D) => i === D.length - 1 ? 0.7 : null)
// .text(d => d);
// }
return svg.node();
}