@sfgrp/pinpoint
Version:
Pinpoint is a engine for displaying hierarchical keys that identify the Earth's species.
454 lines (453 loc) • 13.5 kB
JavaScript
var B = Object.defineProperty;
var D = (o, t, e) => t in o ? B(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
var w = (o, t, e) => D(o, typeof t != "symbol" ? t + "" : t, e);
import { reactive as G, defineComponent as $, inject as L, openBlock as i, createElementBlock as a, createElementVNode as l, unref as u, createTextVNode as y, toDisplayString as v, createCommentVNode as p, Fragment as N, renderList as E, createBlock as k, onMounted as H, onUnmounted as q, withModifiers as O, renderSlot as g, ref as K, withCtx as h, createVNode as T, computed as I, provide as A, watch as J } from "vue";
function W(o) {
return String(o).replace(/(\d+)(\.)?/, (t, e, n) => {
const s = parseInt(e, 10) - 1;
return n ? `${s}.` : `${s}`;
});
}
function z(o, t) {
const e = new URL(o);
return t && Object.entries(t).forEach(([n, s]) => {
e.searchParams.append(n, s.toString());
}), e.toString();
}
async function Q(o, { method: t, data: e, parameters: n } = {}) {
try {
const s = {
method: t || "GET",
headers: {
"Content-Type": "application/json"
},
body: e ? JSON.stringify(e) : void 0
}, r = await fetch(z(o, n), s);
if (!r.ok)
throw new Error(
`Error response: ${r.status} ${r.statusText}`
);
return await r.json();
} catch (s) {
throw console.error("Error:", s), s;
}
}
class S {
constructor(t) {
w(this, "baseUrl");
w(this, "projectToken");
this.baseUrl = t.baseUrl, this.projectToken = t.projectToken;
}
getDichotomousKey(t) {
return Q(`${this.baseUrl}/leads/key/${t}`, {
parameters: {
project_token: this.projectToken
}
});
}
}
function X(o) {
return {
children: o.children || [],
coupletNumber: o.couplet_number,
parentId: o.parent_id,
depth: o.depth,
position: o.position
};
}
function Y(o, { baseUrl: t, projectToken: e }) {
var n;
return {
caption: o.caption,
label: o.label,
position: o.position,
image: o.medium,
original: `${t}/${(n = o.original_png) == null ? void 0 : n.substring(
8
)}?project_token=${e}`
};
}
function Z(o, t) {
var e;
return {
text: o.text,
parentId: o.parent_id,
targetId: o.target_id,
targetLabel: o.target_label,
targetType: o.target_type,
position: o.position,
figures: ((e = o.figures) == null ? void 0 : e.map((n) => Y(n, t))) || []
};
}
function P(o) {
return {
currentNode: null,
metadata: null,
entries: {},
leads: {},
nodes: {},
config: o
};
}
function x(o) {
let t = new S(o);
const e = G(P(o));
function n(d) {
return Object.fromEntries(
Object.entries(d).map(([_, b]) => [_, X(b)])
);
}
function s(d) {
e.config = d, t = new S(d);
}
function r() {
Object.assign(e, P(o));
}
function c(d) {
return Object.fromEntries(
Object.entries(d).map(([_, b]) => [
_,
Z(b, e.config)
])
);
}
function f(d, _) {
const b = {};
for (const [j, R] of Object.entries(_)) {
const U = d[j];
b[j] = {
id: parseInt(j, 10),
...R,
...U
}, U || Object.assign(b[j], { children: [] });
}
return b;
}
return {
state: e,
loadKey: (d) => t.getDichotomousKey(d).then(({ data: _, metadata: b }) => {
e.entries = n(_.entries), e.leads = c(_.leads), e.nodes = f(e.entries, e.leads), e.currentNode = Object.values(e.nodes)[0], e.metadata = b;
}),
setCurrentNode: (d) => {
e.currentNode = e.nodes[d];
},
setConfig: s,
reset: r
};
}
const ee = { class: "pinpoint-tree" }, te = ["innerHTML"], ne = { key: 0 }, V = /* @__PURE__ */ $({
__name: "Tree",
props: {
node: {},
coupletNumber: {}
},
setup(o) {
const t = L("store");
return (e, n) => (i(), a("ul", ee, [
l("li", null, [
l("span", {
onClick: n[0] || (n[0] = () => u(t).setCurrentNode(e.node.parentId))
}, [
y(" [" + v(e.coupletNumber) + "] ", 1),
l("span", {
innerHTML: e.node.text
}, null, 8, te),
isNaN(e.node.targetLabel) ? (i(), a("span", ne, "[" + v(e.node.targetLabel) + "]", 1)) : p("", !0)
]),
(i(!0), a(N, null, E(e.node.children, (s) => (i(), a(N, null, [
u(t).state.nodes[s] ? (i(), k(V, {
key: 0,
node: u(t).state.nodes[s],
"couplet-number": e.node.coupletNumber
}, null, 8, ["node", "couplet-number"])) : p("", !0)
], 64))), 256))
])
]));
}
}), oe = { class: "pinpoint-modal-panel" }, se = {
__name: "Modal",
emits: ["close"],
setup(o, { emit: t }) {
const e = t, n = (s) => {
s.key === "Escape" && (s.stopPropagation(), e("close"));
};
return H(() => {
document.addEventListener("keydown", n), document.body.classList.add("overflow-hidden");
}), q(() => {
document.removeEventListener("keydown", n), document.body.classList.remove("overflow-hidden");
}), (s, r) => (i(), a("div", {
class: "pinpoint-modal-wrapper",
onClick: r[1] || (r[1] = (c) => e("close")),
onKey: r[2] || (r[2] = O((c) => e("close"), ["stop"]))
}, [
l("div", {
class: "pinpoint-modal-container",
onClick: r[0] || (r[0] = O(() => {
}, ["stop"]))
}, [
l("div", oe, [
g(s.$slots, "default")
])
])
], 32));
}
}, re = ["src"], ie = ["src"], ae = /* @__PURE__ */ $({
__name: "FigureItem",
props: {
figure: {}
},
setup(o) {
const t = K(!1);
return (e, n) => (i(), a("div", null, [
l("img", {
src: e.figure.image,
class: "pinpoint-figure",
onClick: n[0] || (n[0] = () => t.value = !t.value)
}, null, 8, re),
t.value ? (i(), k(se, {
key: 0,
onClose: n[2] || (n[2] = () => t.value = !1)
}, {
default: h(() => [
l("img", {
class: "pinpoint-figure-image",
src: e.figure.original,
onClick: n[1] || (n[1] = () => t.value = !0)
}, null, 8, ie)
]),
_: 1
})) : p("", !0)
]));
}
}), le = { class: "pinpoint-figure-list" }, ue = /* @__PURE__ */ $({
__name: "FigureList",
props: {
figures: {}
},
setup(o) {
return (t, e) => (i(), a("div", le, [
(i(!0), a(N, null, E(t.figures, (n) => (i(), k(ae, {
key: n.image,
figure: n
}, null, 8, ["figure"]))), 128))
]));
}
}), de = { class: "pinpoint-node-container" }, pe = { class: "pinpoint-node" }, ce = { class: "pinpoint-node-text" }, me = {
key: 1,
class: "pinpoint-node-target"
}, be = {
key: 0,
class: "pinpoint-node-children-container"
}, ge = { class: "pinpoint-node-next-container" }, _e = /* @__PURE__ */ $({
__name: "Node",
props: {
node: {}
},
setup(o) {
const t = L("store");
return (e, n) => (i(), a("div", de, [
e.node ? (i(), a(N, { key: 0 }, [
l("div", pe, [
e.node.children.length ? (i(), a("button", {
key: 0,
class: "pinpoint-button-go",
type: "button",
onClick: n[0] || (n[0] = () => u(t).state.currentNode = e.node)
}, " Go ")) : p("", !0),
l("p", ce, v(e.node.text), 1),
isNaN(e.node.targetLabel) ? (i(), a("p", me, [
g(e.$slots, "target", {
label: e.node.targetLabel,
id: e.node.targetId
}, () => [
y(v(e.node.targetLabel), 1)
])
])) : p("", !0),
T(ue, {
figures: e.node.figures
}, null, 8, ["figures"])
]),
e.node.children.length ? (i(), a("div", be, [
l("div", ge, [
l("button", {
class: "pinpoint-node-next-button",
type: "button",
onClick: n[1] || (n[1] = (s) => u(t).setCurrentNode(u(t).state.nodes[e.node.children[0]].parentId))
}, [
g(e.$slots, "button-next-label", {}, () => [
n[2] || (n[2] = y(" Next "))
])
])
]),
(i(!0), a(N, null, E(e.node.children.map((s) => u(t).state.nodes[s]), (s) => (i(), k(V, {
"couplet-number": e.node.coupletNumber,
node: s
}, null, 8, ["couplet-number", "node"]))), 256))
])) : p("", !0)
], 64)) : p("", !0)
]));
}
}), ve = { class: "pinpoint-couplet" }, fe = { class: "pinpoint-couplet-container" }, ke = { class: "pinpoint-couplet-node" }, $e = { key: 0 }, he = {
key: 1,
class: "pinpoint-node-target"
}, ye = { class: "pinpoint-couplet-children-container" }, Ne = {
__name: "Couplet",
setup(o) {
const t = L("store"), e = I(() => t.state.currentNode), n = I(() => t.state.currentNode.children.map((r) => t.state.nodes[r]));
return (s, r) => (i(), a("div", ve, [
l("div", fe, [
u(t).state.currentNode.parentId ? (i(), a("button", {
key: 0,
class: "pinpoint-button-up",
type: "button",
onClick: r[0] || (r[0] = () => u(t).state.currentNode = u(t).state.nodes[e.value.parentId])
}, [
g(s.$slots, "button-up-label", {}, () => [
r[1] || (r[1] = y("Up"))
])
])) : p("", !0),
l("div", ke, [
e.value.parentId ? (i(), a("h1", $e, " Couplet " + v(e.value.coupletNumber), 1)) : p("", !0),
isNaN(e.value.targetLabel) && !e.value.parentId ? (i(), a("p", he, [
g(s.$slots, "target", {
label: e.value.targetLabel,
id: e.value.targetId
}, () => [
y(v(e.value.targetLabel), 1)
])
])) : p("", !0)
])
]),
l("div", ye, [
(i(!0), a(N, null, E(n.value, (c) => (i(), k(_e, {
node: c,
key: c.id
}, {
target: h(({ id: f, label: m }) => [
g(s.$slots, "target", {
id: f,
label: m
})
]),
"button-next-label": h(() => [
g(s.$slots, "button-next-label")
]),
_: 2
}, 1032, ["node"]))), 128))
])
]));
}
}, Ce = { key: 0 }, M = /* @__PURE__ */ $({
__name: "PreviousList",
props: {
nodes: {}
},
setup(o) {
const t = L("store");
return (e, n) => {
var s;
return (s = e.nodes) != null && s.length ? (i(), a("ul", Ce, [
l("li", null, [
l("span", {
class: "pinpoint-previous-list-item",
onClick: n[0] || (n[0] = () => u(t).setCurrentNode(e.nodes[0].parentId))
}, "[" + v(u(W)(e.nodes[0].coupletNumber)) + "] " + v(e.nodes[0].text), 1),
T(M, {
nodes: e.nodes.slice(1)
}, null, 8, ["nodes"])
])
])) : p("", !0);
};
}
}), Le = { class: "pinpoint-previous-couplets" }, je = { class: "pinpoint-previous-list" }, Ie = /* @__PURE__ */ $({
__name: "PreviousCouplets",
props: {
node: {}
},
setup(o) {
const t = o, e = L("store"), n = I(() => {
const s = [];
let r = t.node.id;
for (; r !== null; ) {
const c = e.state.nodes[r];
r = c.parentId, s.unshift(c);
}
return s.splice(0, 1), s;
});
return (s, r) => (i(), a("div", Le, [
r[0] || (r[0] = l("h2", null, "Previous couplets", -1)),
l("div", je, [
T(M, { nodes: n.value }, null, 8, ["nodes"])
])
]));
}
}), C = {
Loading: "loading",
Error: "error",
End: "end",
Start: "start"
}, Ee = { class: "pinpoint-app" }, we = {
key: 0,
class: "pinpoint-key-title"
}, Te = { key: 3 }, Se = /* @__PURE__ */ $({
__name: "VuePinpoint",
props: {
leadId: {},
projectToken: {},
baseUrl: {}
},
emits: Object.values(C),
setup(o, { expose: t, emit: e }) {
const n = o, s = e, r = x(n), c = I(() => r.state.currentNode), f = K(null);
return A("store", r), J(
[() => n.leadId, () => n.projectToken, () => n.baseUrl],
() => {
r.reset(), r.setConfig(n), f.value = null, n.leadId && n.baseUrl && n.projectToken && n.baseUrl && (s(C.Start), s(C.Loading), r.loadKey(n.leadId).then((m) => {
s(C.End, m);
}).catch((m) => {
s(C.Error, m), f.value = m;
}));
},
{
immediate: !0
}
), t({
getState: () => r.state
}), (m, F) => {
var d;
return i(), a("div", Ee, [
u(r).state.metadata ? (i(), a("div", we, [
g(m.$slots, "title", {
title: u(r).state.metadata.title,
metadata: u(r).state.metadata
}, () => [
y(v(u(r).state.metadata.title), 1)
])
])) : p("", !0),
(d = c.value) != null && d.parentId ? (i(), k(Ie, {
key: 1,
node: c.value
}, null, 8, ["node"])) : p("", !0),
c.value ? (i(), k(Ne, { key: 2 }, {
target: h(({ id: _, label: b }) => [
g(m.$slots, "target", {
label: b,
id: _
})
]),
"button-up-label": h(() => [
g(m.$slots, "button-up-label")
]),
"button-next-label": h(() => [
g(m.$slots, "button-next-label")
]),
_: 3
})) : p("", !0),
f.value ? (i(), a("div", Te, v(f.value.message), 1)) : p("", !0)
]);
};
}
});
export {
Se as VuePinpoint
};