UNPKG

@airplane/views

Version:

A React library for building Airplane views. Views components are optimized in style and functionality to produce internal apps that are easy to build and maintain.

189 lines (188 loc) 4.96 kB
import { useState, useRef, useEffect } from "react"; import { EVALUATE_TEMPLATE } from "../../client/endpoints.js"; import { Fetcher } from "../../client/fetcher.js"; const newTemplate = (s) => { if (s.length === 0) { return []; } const fragments = []; let next = ""; for (let i = 0; i < s.length; i++) { const c = s[i]; const isLast = i + 1 == s.length; if (isLast) { next += c; continue; } const nc = s[i + 1]; if (c == "{") { if (nc != "{") { next += c; continue; } if (next.length > 0) { fragments.push(next); next = ""; } const n = measureTemplateExpression(s.substring(i)); fragments.push(s.substring(i, i + n + 1)); i += n; } else if (c == "\\") { if (nc === "{" || nc === "}" || nc === "\\") { next += nc; i++; } else { next += c; } } else { next += c; } } if (next.length > 0) { fragments.push(next); } return fragments; }; const measureTemplateExpression = (s) => { let depth = 0; let qm = "none"; let pc = ""; let lastdci = -1; for (let i = 0; i < s.length; i++) { const c = s[i]; if (c === "\\") { if (i + 1 < s.length) { const nc = s[i + 1]; if (nc === '"' || nc === "'" || nc === "`") { i++; } } } else if (c === '"') { if (qm === "none") { qm = "double"; } else if (qm === "double") { qm = "none"; } } else if (c === "'") { if (qm === "none") { qm = "single"; } else if (qm === "single") { qm = "none"; } } else if (c === "`") { if (qm === "none") { qm = "backtick"; } else if (qm === "backtick") { qm = "none"; } } else if (c === "{") { if (qm === "none") { depth++; } } else if (c === "}") { if (qm === "none") { depth--; } if (pc === "}") { lastdci = i; if (depth === 0) { return i; } } } pc = c; } if (lastdci > -1) { return lastdci; } throw new Error("Invalid template"); }; const unpackTemplate = (v) => isTemplate(v) ? v.raw : v; const useEvaluateTemplate = (template, args, opts = {}) => { const { results, errors, loading, initialLoading } = useEvaluateTemplates([template], args, opts); return { result: results[0], error: errors[0], loading, initialLoading }; }; const useEvaluateTemplates = (templates, args, opts = {}) => { const [results, setResults] = useState([]); const cacheRef = useRef({}); const numLoadingRef = useRef(0); const addResult = (result, i) => { setResults((r) => r ? [...r.slice(0, i), result, ...r.slice(i + 1)] : r); }; const templatesStr = JSON.stringify(templates); const argsStr = JSON.stringify(args); useEffect(() => { const evaluateServer = async (t, i, cacheKey) => { let response = void 0; let errString = ""; let raw = unpackTemplate(t); if (opts.forceEvaluate && !raw.startsWith("{{")) { raw = `{{${raw}}}`; } try { const fetcher = new Fetcher(); response = await fetcher.post(EVALUATE_TEMPLATE, { value: raw, lookupMaps: args, disableDefaultLookupMaps: true }); } catch (e) { if (e instanceof Error) { errString = e.message; } else { errString = "Unknown error"; } } cacheRef.current[cacheKey] = { result: response == null ? void 0 : response.value, error: errString }; numLoadingRef.current--; addResult({ result: response == null ? void 0 : response.value, error: errString }, i); }; templates == null ? void 0 : templates.forEach((t, i) => { const cacheKey = JSON.stringify({ t, args }); if (!t) { addResult(void 0, i); } else if (cacheRef.current[cacheKey]) { addResult(cacheRef.current[cacheKey], i); } else if (!opts.forceEvaluate && !newTemplate(unpackTemplate(t)).some((f) => f.startsWith("{{"))) { addResult({ result: unpackTemplate(t) }, i); } else { numLoadingRef.current++; evaluateServer(t, i, cacheKey); } }); }, [argsStr, templatesStr, opts.forceEvaluate]); const initialLoading = (templates == null ? void 0 : templates.length) && results.length !== templates.length; return { results: results.map((r) => r == null ? void 0 : r.result), errors: results.map((r) => (r == null ? void 0 : r.error) ?? ""), initialLoading, loading: initialLoading || numLoadingRef.current > 0 }; }; const isTemplate = (v) => v != null && typeof v === "object" && v["__airplaneType"] === "template"; export { useEvaluateTemplate, useEvaluateTemplates }; //# sourceMappingURL=jst.js.map