@motion-core/motion-gpu
Version:
Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte, React, and Vue adapter entrypoints.
195 lines (194 loc) • 8.29 kB
JavaScript
import { createMotionGPUErrorOverlayModel } from "../core/error-overlay-model.js";
import { registerErrorOverlay } from "../core/error-overlay-stack.js";
/* empty css */
import { Portal } from "./Portal.js";
import { useEffect, useId, useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/lib/react/MotionGPUErrorOverlay.tsx
var FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), summary, input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])";
function ChevronDownIcon() {
return /* @__PURE__ */ jsx("svg", {
className: "motiongpu-error-details-chevron",
viewBox: "0 0 18 18",
fill: "none",
"aria-hidden": "true",
focusable: "false",
children: /* @__PURE__ */ jsx("polyline", {
points: "15.25 6.5 9 12.75 2.75 6.5",
stroke: "currentColor",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round"
})
});
}
function MotionGPUErrorOverlay({ report, onDismiss }) {
const model = createMotionGPUErrorOverlayModel(report);
const detailsSummary = report.source ? "Additional diagnostics" : "Technical details";
const componentId = useId();
const titleId = `${componentId}-title`;
const descriptionId = `${componentId}-description`;
const sourceTitleId = `${componentId}-source-title`;
const overlayElement = useRef(null);
const [dialogElement, setDialogElement] = useState(null);
const getFocusableElements = () => {
if (!dialogElement) return [];
return Array.from(dialogElement.querySelectorAll(FOCUSABLE_SELECTOR)).filter((element) => element.getAttribute("aria-hidden") !== "true");
};
const handleDialogKeyDown = (event) => {
if (event.key !== "Tab" || !dialogElement) return;
const focusableElements = getFocusableElements();
if (focusableElements.length === 0) {
event.preventDefault();
dialogElement.focus({ preventScroll: true });
return;
}
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
const activeElement = document.activeElement;
const focusIsOutsideDialog = !(activeElement instanceof Node) || !dialogElement.contains(activeElement);
if (event.shiftKey && (activeElement === firstElement || activeElement === dialogElement || focusIsOutsideDialog)) {
event.preventDefault();
lastElement.focus();
return;
}
if (!event.shiftKey && (activeElement === lastElement || activeElement === dialogElement || focusIsOutsideDialog)) {
event.preventDefault();
firstElement.focus();
}
};
useEffect(() => {
if (!dialogElement) return;
const portalRoot = overlayElement.current?.parentElement;
if (!portalRoot) return;
return registerErrorOverlay({
dialog: dialogElement,
portalRoot,
onDismiss
});
}, [dialogElement, onDismiss]);
return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx("div", {
ref: overlayElement,
className: "motiongpu-error-overlay",
role: "presentation",
children: /* @__PURE__ */ jsx("div", {
className: "motiongpu-error-dialog-shell",
role: "presentation",
children: /* @__PURE__ */ jsxs("div", {
ref: setDialogElement,
className: "motiongpu-error-dialog",
role: "alertdialog",
"aria-modal": "true",
"aria-labelledby": titleId,
"aria-describedby": descriptionId,
tabIndex: -1,
"data-testid": "motiongpu-error",
onKeyDown: handleDialogKeyDown,
children: [
/* @__PURE__ */ jsx("header", {
className: "motiongpu-error-header",
children: /* @__PURE__ */ jsxs("div", {
className: "motiongpu-error-header-top",
children: [/* @__PURE__ */ jsxs("div", {
className: "motiongpu-error-header-copy",
children: [/* @__PURE__ */ jsx("h2", {
id: titleId,
className: "motiongpu-error-title",
children: report.title
}), /* @__PURE__ */ jsxs("p", {
className: "motiongpu-error-recoverable",
children: ["Recoverable: ", /* @__PURE__ */ jsx("span", { children: report.recoverable ? "yes" : "no" })]
})]
}), /* @__PURE__ */ jsxs("div", {
className: "motiongpu-error-badges",
children: [/* @__PURE__ */ jsx("div", {
className: "motiongpu-error-badge-wrap",
children: /* @__PURE__ */ jsx("p", {
className: "motiongpu-error-badge motiongpu-error-badge-phase",
children: report.phase
})
}), /* @__PURE__ */ jsx("div", {
className: "motiongpu-error-badge-wrap",
children: /* @__PURE__ */ jsx("p", {
className: "motiongpu-error-badge motiongpu-error-badge-severity",
children: report.severity
})
})]
})]
})
}),
/* @__PURE__ */ jsxs("div", {
id: descriptionId,
className: "motiongpu-error-body",
children: [model.displayMessage.length > 0 ? /* @__PURE__ */ jsx("p", {
className: "motiongpu-error-message",
children: model.displayMessage
}) : null, /* @__PURE__ */ jsx("p", {
className: "motiongpu-error-hint",
children: report.hint
})]
}),
report.source ? /* @__PURE__ */ jsxs("section", {
className: "motiongpu-error-source",
"aria-labelledby": sourceTitleId,
children: [/* @__PURE__ */ jsx("h3", {
id: sourceTitleId,
className: "motiongpu-error-source-title",
children: "Source"
}), /* @__PURE__ */ jsxs("figure", {
className: "motiongpu-error-source-frame",
children: [/* @__PURE__ */ jsxs("figcaption", {
className: "motiongpu-error-source-tabs",
children: [/* @__PURE__ */ jsxs("span", {
className: "motiongpu-error-source-tab motiongpu-error-source-tab-active",
children: [report.source.location, report.source.column ? `, col ${report.source.column}` : ""]
}), /* @__PURE__ */ jsx("span", {
className: "motiongpu-error-source-tab-spacer",
"aria-hidden": "true"
})]
}), /* @__PURE__ */ jsx("div", {
className: "motiongpu-error-source-snippet",
role: "region",
"aria-label": `Source code from ${report.source.location}`,
children: report.source.snippet.map((snippetLine) => /* @__PURE__ */ jsxs("div", {
className: snippetLine.highlight ? "motiongpu-error-source-row motiongpu-error-source-row-active" : "motiongpu-error-source-row",
children: [/* @__PURE__ */ jsxs("span", {
className: "motiongpu-error-source-line",
children: [snippetLine.highlight ? /* @__PURE__ */ jsx("span", {
className: "motiongpu-sr-only",
children: "Error line: "
}) : null, snippetLine.number]
}), /* @__PURE__ */ jsx("span", {
className: "motiongpu-error-source-code",
children: snippetLine.code || " "
})]
}, `snippet-${snippetLine.number}`))
})]
})]
}) : null,
/* @__PURE__ */ jsxs("div", {
className: "motiongpu-error-sections",
children: [
report.details.length > 0 ? /* @__PURE__ */ jsxs("details", {
className: "motiongpu-error-details",
open: true,
children: [/* @__PURE__ */ jsxs("summary", { children: [/* @__PURE__ */ jsx(ChevronDownIcon, {}), /* @__PURE__ */ jsx("span", { children: detailsSummary })] }), /* @__PURE__ */ jsx("pre", { children: report.details.join("\n") })]
}) : null,
report.stack.length > 0 ? /* @__PURE__ */ jsxs("details", {
className: "motiongpu-error-details",
children: [/* @__PURE__ */ jsxs("summary", { children: [/* @__PURE__ */ jsx(ChevronDownIcon, {}), /* @__PURE__ */ jsx("span", { children: "Stack trace" })] }), /* @__PURE__ */ jsx("pre", { children: report.stack.join("\n") })]
}) : null,
report.context ? /* @__PURE__ */ jsxs("details", {
className: "motiongpu-error-details",
children: [/* @__PURE__ */ jsxs("summary", { children: [/* @__PURE__ */ jsx(ChevronDownIcon, {}), /* @__PURE__ */ jsx("span", { children: "Runtime context" })] }), /* @__PURE__ */ jsx("pre", { children: model.runtimeContextText })]
}) : null
]
})
]
})
})
}) });
}
//#endregion
export { MotionGPUErrorOverlay };
//# sourceMappingURL=MotionGPUErrorOverlay.js.map