@hexclave/next 1.0.74 → 1.0.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{admin-app-impl-FZdANO62.d.ts → admin-app-impl-CsH-gVGz.d.ts} +2 -2
- package/dist/{admin-app-impl-FZdANO62.d.ts.map → admin-app-impl-CsH-gVGz.d.ts.map} +1 -1
- package/dist/components/api-key-dialogs.d.ts +1 -1
- package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/dev-tool/dev-tool-core.js +2 -2
- package/dist/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/dev-tool/index.d.ts.map +1 -1
- package/dist/dev-tool/index.js +2 -8
- package/dist/dev-tool/index.js.map +1 -1
- package/dist/esm/components/api-key-dialogs.d.ts +1 -1
- package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/esm/dev-tool/dev-tool-core.js +1 -1
- package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/esm/dev-tool/index.d.ts.map +1 -1
- package/dist/esm/dev-tool/index.js +2 -8
- package/dist/esm/dev-tool/index.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.d.ts +2 -2
- package/dist/esm/in-page-ui/dev-environment.d.ts +5 -0
- package/dist/esm/in-page-ui/dev-environment.d.ts.map +1 -0
- package/dist/esm/in-page-ui/dev-environment.js +18 -0
- package/dist/esm/in-page-ui/dev-environment.js.map +1 -0
- package/dist/esm/in-page-ui/issue-card.d.ts +52 -0
- package/dist/esm/in-page-ui/issue-card.d.ts.map +1 -0
- package/dist/esm/in-page-ui/issue-card.js +392 -0
- package/dist/esm/in-page-ui/issue-card.js.map +1 -0
- package/dist/esm/in-page-ui/issue-card.test.d.ts +1 -0
- package/dist/esm/in-page-ui/issue-card.test.js +60 -0
- package/dist/esm/in-page-ui/issue-card.test.js.map +1 -0
- package/dist/esm/in-page-ui/logo.d.ts +5 -0
- package/dist/esm/in-page-ui/logo.d.ts.map +1 -0
- package/dist/esm/in-page-ui/logo.js +6 -0
- package/dist/esm/in-page-ui/logo.js.map +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +140 -15
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +95 -12
- package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +1 -0
- package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
- package/dist/esm/pushed-config-error-overlay/index.d.ts.map +1 -1
- package/dist/esm/pushed-config-error-overlay/index.js +42 -343
- package/dist/esm/pushed-config-error-overlay/index.js.map +1 -1
- package/dist/esm/setup-error-overlay/index.d.ts +16 -0
- package/dist/esm/setup-error-overlay/index.d.ts.map +1 -0
- package/dist/esm/setup-error-overlay/index.js +106 -0
- package/dist/esm/setup-error-overlay/index.js.map +1 -0
- package/dist/esm/setup-error-overlay/index.test.d.ts +1 -0
- package/dist/esm/setup-error-overlay/index.test.js +125 -0
- package/dist/esm/setup-error-overlay/index.test.js.map +1 -0
- package/dist/generated/quetzal-translations.d.ts +1 -1
- package/dist/{hexclave-provider-BKxi3Vy-.d.ts → hexclave-provider-BA97jMlx.d.ts} +2 -2
- package/dist/{hexclave-provider-BKxi3Vy-.d.ts.map → hexclave-provider-BA97jMlx.d.ts.map} +1 -1
- package/dist/in-page-ui/dev-environment.d.ts +5 -0
- package/dist/in-page-ui/dev-environment.d.ts.map +1 -0
- package/dist/in-page-ui/dev-environment.js +19 -0
- package/dist/in-page-ui/dev-environment.js.map +1 -0
- package/dist/in-page-ui/issue-card.d.ts +52 -0
- package/dist/in-page-ui/issue-card.d.ts.map +1 -0
- package/dist/in-page-ui/issue-card.js +397 -0
- package/dist/in-page-ui/issue-card.js.map +1 -0
- package/dist/in-page-ui/issue-card.test.d.ts +1 -0
- package/dist/in-page-ui/issue-card.test.js +59 -0
- package/dist/in-page-ui/issue-card.test.js.map +1 -0
- package/dist/in-page-ui/logo.d.ts +5 -0
- package/dist/in-page-ui/logo.d.ts.map +1 -0
- package/dist/in-page-ui/logo.js +7 -0
- package/dist/in-page-ui/logo.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +140 -15
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +94 -11
- package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
- package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
- package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +1 -0
- package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
- package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
- package/dist/providers/hexclave-provider.d.ts +1 -1
- package/dist/providers/translation-provider.d.ts +1 -1
- package/dist/pushed-config-error-overlay/index.d.ts.map +1 -1
- package/dist/pushed-config-error-overlay/index.js +41 -342
- package/dist/pushed-config-error-overlay/index.js.map +1 -1
- package/dist/{quetzal-translations-XeH3zQ9l.d.ts → quetzal-translations-CK45_4Dm.d.ts} +3 -3
- package/dist/{quetzal-translations-XeH3zQ9l.d.ts.map → quetzal-translations-CK45_4Dm.d.ts.map} +1 -1
- package/dist/setup-error-overlay/index.d.ts +16 -0
- package/dist/setup-error-overlay/index.d.ts.map +1 -0
- package/dist/setup-error-overlay/index.js +108 -0
- package/dist/setup-error-overlay/index.js.map +1 -0
- package/dist/setup-error-overlay/index.test.d.ts +1 -0
- package/dist/setup-error-overlay/index.test.js +124 -0
- package/dist/setup-error-overlay/index.test.js.map +1 -0
- package/dist/{translation-provider-WOaZXqAz.d.ts → translation-provider-DQ3BJepJ.d.ts} +2 -2
- package/dist/{translation-provider-WOaZXqAz.d.ts.map → translation-provider-DQ3BJepJ.d.ts.map} +1 -1
- package/package.json +4 -4
- package/src/dev-tool/dev-tool-core.ts +1 -4
- package/src/dev-tool/index.ts +4 -15
- package/src/in-page-ui/dev-environment.ts +33 -0
- package/src/in-page-ui/issue-card.test.ts +67 -0
- package/src/in-page-ui/issue-card.ts +500 -0
- package/src/in-page-ui/logo.ts +8 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +158 -0
- package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +125 -17
- package/src/lib/hexclave-app/apps/implementations/redirect-page-urls.test.ts +1 -0
- package/src/pushed-config-error-overlay/index.ts +45 -386
- package/src/setup-error-overlay/index.test.ts +133 -0
- package/src/setup-error-overlay/index.ts +150 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { canMountIntoDom, getGlobalUiInstance, h, setGlobalUiInstance } from "../in-page-ui/dom.js";
|
|
2
|
+
import { HexclaveSetupError, captureError, errorToNiceString } from "@hexclave/shared/dist/utils/errors";
|
|
3
|
+
import { isLikelyDevelopmentEnvironment } from "../in-page-ui/dev-environment.js";
|
|
4
|
+
import { getIssueCardCSS, renderIssueCard, renderIssuePill, trapFocusInIssueCard } from "../in-page-ui/issue-card.js";
|
|
5
|
+
//#region src/setup-error-overlay/index.ts
|
|
6
|
+
/** Exported so tests can drop the singleton; every other consumer should go through `showSetupErrorOverlay`. */
|
|
7
|
+
const SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY = "__hexclave-setup-error-overlay";
|
|
8
|
+
const css = getIssueCardCSS(".hexclave-setup-error-overlay");
|
|
9
|
+
const unexpectedErrorHowToFix = [
|
|
10
|
+
"Check the browser console and your Hexclave dashboard's logs for the full error.",
|
|
11
|
+
"Make sure your Hexclave SDK packages are up to date.",
|
|
12
|
+
"If the error looks like a bug in Hexclave, report it at https://github.com/hexclave/hexclave/issues."
|
|
13
|
+
];
|
|
14
|
+
function toSetupIssue(error) {
|
|
15
|
+
if (HexclaveSetupError.isSetupError(error)) return {
|
|
16
|
+
title: error.title,
|
|
17
|
+
message: error.message,
|
|
18
|
+
howToFix: error.howToFix,
|
|
19
|
+
isFatal: true
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
title: "Hexclave could not finish an authentication flow",
|
|
23
|
+
message: errorToNiceString(error),
|
|
24
|
+
howToFix: unexpectedErrorHowToFix,
|
|
25
|
+
isFatal: false
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function buildAiPrompt(issue) {
|
|
29
|
+
return [
|
|
30
|
+
"Help me fix this Hexclave setup error.",
|
|
31
|
+
"",
|
|
32
|
+
"Hexclave reminder:",
|
|
33
|
+
"This error was thrown by the Hexclave SDK in the browser while it was resolving an authentication flow, and the flow was aborted because of it. It is a problem with how my project is set up, not something my users can work around. Use your web fetch tool to read https://skill.hexclave.com to learn more about Hexclave.",
|
|
34
|
+
"",
|
|
35
|
+
"Error message:",
|
|
36
|
+
issue.message,
|
|
37
|
+
"",
|
|
38
|
+
"Hexclave suggests:",
|
|
39
|
+
...issue.howToFix.map((step) => `- ${step}`),
|
|
40
|
+
"",
|
|
41
|
+
"Please explain the likely cause and suggest the smallest safe fix."
|
|
42
|
+
].join("\n");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Shows `error` as an error card on the current page.
|
|
46
|
+
*
|
|
47
|
+
* Setup errors are always shown, because the flow they aborted cannot complete no matter what the end user does, and
|
|
48
|
+
* their messages are written for exactly this purpose. Any other error is only shown while developing — those messages
|
|
49
|
+
* are internal diagnostics, so in production they stay in captureError's hands.
|
|
50
|
+
*
|
|
51
|
+
* Returns a cleanup function that removes the card again.
|
|
52
|
+
*/
|
|
53
|
+
function showSetupErrorOverlay(error) {
|
|
54
|
+
if (!canMountIntoDom()) return () => {};
|
|
55
|
+
if (!HexclaveSetupError.isSetupError(error) && !isLikelyDevelopmentEnvironment()) return () => {};
|
|
56
|
+
const issue = toSetupIssue(error);
|
|
57
|
+
if (getGlobalUiInstance("__hexclave-setup-error-overlay") != null) return () => {};
|
|
58
|
+
const root = h("div", { className: "hexclave-setup-error-overlay" });
|
|
59
|
+
const style = h("style", null, css);
|
|
60
|
+
root.appendChild(style);
|
|
61
|
+
document.body.appendChild(root);
|
|
62
|
+
let focusTrap = null;
|
|
63
|
+
const render = (minimized) => {
|
|
64
|
+
focusTrap?.release();
|
|
65
|
+
focusTrap = null;
|
|
66
|
+
root.replaceChildren(style);
|
|
67
|
+
if (minimized) {
|
|
68
|
+
root.appendChild(renderIssuePill({
|
|
69
|
+
kind: "error",
|
|
70
|
+
label: "Setup error",
|
|
71
|
+
ariaLabel: "Show Hexclave setup error",
|
|
72
|
+
onClick: () => render(false)
|
|
73
|
+
}));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
root.appendChild(renderIssueCard({
|
|
77
|
+
kind: "error",
|
|
78
|
+
badge: "Setup error",
|
|
79
|
+
title: issue.title,
|
|
80
|
+
bodyText: issue.isFatal ? "Hexclave stopped the authentication flow that ran into this error, so nobody can sign in through it until it is fixed." : "Hexclave aborted the authentication flow that ran into this error. Errors like this one may also be transient, in which case retrying the flow works.",
|
|
81
|
+
messageLabel: "Error message",
|
|
82
|
+
message: issue.message,
|
|
83
|
+
howToFix: issue.howToFix,
|
|
84
|
+
footerText: issue.isFatal ? "This card is shown by the Hexclave SDK. Fix the problem above and reload the page to try the flow again." : "This card is shown by the Hexclave SDK while developing, and never in production.",
|
|
85
|
+
ariaLabel: "Hexclave setup error",
|
|
86
|
+
aiPrompt: buildAiPrompt(issue),
|
|
87
|
+
onCopyError: (copyError) => captureError("setup-error-overlay-copy", copyError),
|
|
88
|
+
onCopyAiPromptError: (copyError) => captureError("setup-error-overlay-copy-ai-prompt", copyError),
|
|
89
|
+
onMinimize: () => render(true)
|
|
90
|
+
}));
|
|
91
|
+
focusTrap = trapFocusInIssueCard(root);
|
|
92
|
+
};
|
|
93
|
+
render(false);
|
|
94
|
+
const cleanup = () => {
|
|
95
|
+
focusTrap?.release();
|
|
96
|
+
focusTrap = null;
|
|
97
|
+
root.remove();
|
|
98
|
+
if (getGlobalUiInstance("__hexclave-setup-error-overlay")?.cleanup === cleanup) setGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, null);
|
|
99
|
+
};
|
|
100
|
+
setGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, { cleanup });
|
|
101
|
+
return cleanup;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, showSetupErrorOverlay };
|
|
105
|
+
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/setup-error-overlay/index.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n\n// Renders an error card on the page when an auth flow dies because of a setup problem in the developer's project (a\n// domain missing from the trusted domains, for example). Those failures used to be logged with captureError only, which\n// meant the flow just quietly stopped: the developer saw a page that never signed anybody in, with the explanation\n// buried in the console or in Sentry. Setup errors are always the developer's to fix and never recoverable at runtime,\n// so they get the same treatment as a broken pushed config: a card that is impossible to miss.\n\nimport { HexclaveSetupError, captureError, errorToNiceString } from \"@hexclave/shared/dist/utils/errors\";\nimport { isLikelyDevelopmentEnvironment } from \"../in-page-ui/dev-environment\";\nimport { canMountIntoDom, getGlobalUiInstance, h, setGlobalUiInstance } from \"../in-page-ui/dom\";\nimport { getIssueCardCSS, renderIssueCard, renderIssuePill, trapFocusInIssueCard, type IssueCardFocusTrap } from \"../in-page-ui/issue-card\";\n\n/** Exported so tests can drop the singleton; every other consumer should go through `showSetupErrorOverlay`. */\nexport const SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY = \"__hexclave-setup-error-overlay\";\n\nconst css = getIssueCardCSS(\".hexclave-setup-error-overlay\");\n\nconst unexpectedErrorHowToFix = [\n \"Check the browser console and your Hexclave dashboard's logs for the full error.\",\n \"Make sure your Hexclave SDK packages are up to date.\",\n \"If the error looks like a bug in Hexclave, report it at https://github.com/hexclave/hexclave/issues.\",\n] as const;\n\ntype SetupIssue = {\n title: string,\n message: string,\n howToFix: readonly string[],\n // Setup errors are known to be fatal for their flow, so the card says so. Anything else may well be transient (a\n // network blip while resolving a session, say), and claiming that nobody can sign in anymore would be misleading.\n isFatal: boolean,\n};\n\nfunction toSetupIssue(error: unknown): SetupIssue {\n if (HexclaveSetupError.isSetupError(error)) {\n return {\n title: error.title,\n message: error.message,\n howToFix: error.howToFix,\n isFatal: true,\n };\n }\n return {\n title: \"Hexclave could not finish an authentication flow\",\n message: errorToNiceString(error),\n howToFix: unexpectedErrorHowToFix,\n isFatal: false,\n };\n}\n\nfunction buildAiPrompt(issue: SetupIssue): string {\n return [\n \"Help me fix this Hexclave setup error.\",\n \"\",\n \"Hexclave reminder:\",\n \"This error was thrown by the Hexclave SDK in the browser while it was resolving an authentication flow, and the flow was aborted because of it. It is a problem with how my project is set up, not something my users can work around. Use your web fetch tool to read https://skill.hexclave.com to learn more about Hexclave.\",\n \"\",\n \"Error message:\",\n issue.message,\n \"\",\n \"Hexclave suggests:\",\n ...issue.howToFix.map((step) => `- ${step}`),\n \"\",\n \"Please explain the likely cause and suggest the smallest safe fix.\",\n ].join(\"\\n\");\n}\n\n/**\n * Shows `error` as an error card on the current page.\n *\n * Setup errors are always shown, because the flow they aborted cannot complete no matter what the end user does, and\n * their messages are written for exactly this purpose. Any other error is only shown while developing — those messages\n * are internal diagnostics, so in production they stay in captureError's hands.\n *\n * Returns a cleanup function that removes the card again.\n */\nexport function showSetupErrorOverlay(error: unknown): () => void {\n if (!canMountIntoDom()) {\n return () => {};\n }\n if (!HexclaveSetupError.isSetupError(error) && !isLikelyDevelopmentEnvironment()) {\n return () => {};\n }\n\n const issue = toSetupIssue(error);\n const existingInstance = getGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY);\n if (existingInstance != null) {\n // A single broken setup usually throws the same error on every page load and sometimes from several flows at once.\n // Stacking cards on top of each other would only hide the first (and most relevant) one, so later errors keep to\n // captureError and leave the card that is already up alone.\n return () => {};\n }\n\n const root = h(\"div\", { className: \"hexclave-setup-error-overlay\" });\n const style = h(\"style\", null, css);\n root.appendChild(style);\n document.body.appendChild(root);\n\n let focusTrap: IssueCardFocusTrap | null = null;\n const render = (minimized: boolean) => {\n focusTrap?.release();\n focusTrap = null;\n root.replaceChildren(style);\n if (minimized) {\n root.appendChild(renderIssuePill({\n kind: \"error\",\n label: \"Setup error\",\n ariaLabel: \"Show Hexclave setup error\",\n onClick: () => render(false),\n }));\n return;\n }\n root.appendChild(renderIssueCard({\n kind: \"error\",\n badge: \"Setup error\",\n title: issue.title,\n bodyText: issue.isFatal\n ? \"Hexclave stopped the authentication flow that ran into this error, so nobody can sign in through it until it is fixed.\"\n : \"Hexclave aborted the authentication flow that ran into this error. Errors like this one may also be transient, in which case retrying the flow works.\",\n messageLabel: \"Error message\",\n message: issue.message,\n howToFix: issue.howToFix,\n footerText: issue.isFatal\n ? \"This card is shown by the Hexclave SDK. Fix the problem above and reload the page to try the flow again.\"\n : \"This card is shown by the Hexclave SDK while developing, and never in production.\",\n ariaLabel: \"Hexclave setup error\",\n aiPrompt: buildAiPrompt(issue),\n onCopyError: (copyError) => captureError(\"setup-error-overlay-copy\", copyError),\n onCopyAiPromptError: (copyError) => captureError(\"setup-error-overlay-copy-ai-prompt\", copyError),\n onMinimize: () => render(true),\n }));\n focusTrap = trapFocusInIssueCard(root);\n };\n render(false);\n\n const cleanup = () => {\n focusTrap?.release();\n focusTrap = null;\n root.remove();\n if (getGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY)?.cleanup === cleanup) {\n setGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, null);\n }\n };\n setGlobalUiInstance(SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, { cleanup });\n return cleanup;\n}\n\n"],"mappings":";;;;;;AAiBA,MAAa,0CAA0C;AAEvD,MAAM,MAAM,gBAAgB,+BAA+B;AAE3D,MAAM,0BAA0B;CAC9B;CACA;CACA;AACF;AAWA,SAAS,aAAa,OAA4B;CAChD,IAAI,mBAAmB,aAAa,KAAK,GACvC,OAAO;EACL,OAAO,MAAM;EACb,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,SAAS;CACX;CAEF,OAAO;EACL,OAAO;EACP,SAAS,kBAAkB,KAAK;EAChC,UAAU;EACV,SAAS;CACX;AACF;AAEA,SAAS,cAAc,OAA2B;CAChD,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,MAAM;EACN;EACA;EACA,GAAG,MAAM,SAAS,KAAK,SAAS,KAAK,MAAM;EAC3C;EACA;CACF,CAAC,CAAC,KAAK,IAAI;AACb;;;;;;;;;;AAWA,SAAgB,sBAAsB,OAA4B;CAChE,IAAI,CAAC,gBAAgB,GACnB,aAAa,CAAC;CAEhB,IAAI,CAAC,mBAAmB,aAAa,KAAK,KAAK,CAAC,+BAA+B,GAC7E,aAAa,CAAC;CAGhB,MAAM,QAAQ,aAAa,KAAK;CAEhC,IADyB,oBAAA,gCACN,KAAK,MAItB,aAAa,CAAC;CAGhB,MAAM,OAAO,EAAE,OAAO,EAAE,WAAW,+BAA+B,CAAC;CACnE,MAAM,QAAQ,EAAE,SAAS,MAAM,GAAG;CAClC,KAAK,YAAY,KAAK;CACtB,SAAS,KAAK,YAAY,IAAI;CAE9B,IAAI,YAAuC;CAC3C,MAAM,UAAU,cAAuB;EACrC,WAAW,QAAQ;EACnB,YAAY;EACZ,KAAK,gBAAgB,KAAK;EAC1B,IAAI,WAAW;GACb,KAAK,YAAY,gBAAgB;IAC/B,MAAM;IACN,OAAO;IACP,WAAW;IACX,eAAe,OAAO,KAAK;GAC7B,CAAC,CAAC;GACF;EACF;EACA,KAAK,YAAY,gBAAgB;GAC/B,MAAM;GACN,OAAO;GACP,OAAO,MAAM;GACb,UAAU,MAAM,UACZ,2HACA;GACJ,cAAc;GACd,SAAS,MAAM;GACf,UAAU,MAAM;GAChB,YAAY,MAAM,UACd,6GACA;GACJ,WAAW;GACX,UAAU,cAAc,KAAK;GAC7B,cAAc,cAAc,aAAa,4BAA4B,SAAS;GAC9E,sBAAsB,cAAc,aAAa,sCAAsC,SAAS;GAChG,kBAAkB,OAAO,IAAI;EAC/B,CAAC,CAAC;EACF,YAAY,qBAAqB,IAAI;CACvC;CACA,OAAO,KAAK;CAEZ,MAAM,gBAAgB;EACpB,WAAW,QAAQ;EACnB,YAAY;EACZ,KAAK,OAAO;EACZ,IAAI,oBAAA,gCAA2D,CAAC,EAAE,YAAY,SAC5E,oBAAoB,yCAAyC,IAAI;CAErE;CACA,oBAAoB,yCAAyC,EAAE,QAAQ,CAAC;CACxE,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { HexclaveSetupError } from "@hexclave/shared/dist/utils/errors";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, showSetupErrorOverlay } from "./index.js";
|
|
4
|
+
//#region src/setup-error-overlay/index.test.ts
|
|
5
|
+
// @vitest-environment jsdom
|
|
6
|
+
function createSetupError() {
|
|
7
|
+
return new HexclaveSetupError({
|
|
8
|
+
title: "A domain in your authentication flow is not one of your project's trusted domains",
|
|
9
|
+
message: "Nested cross-domain auth callback URL https://demo.example.test/ is not trusted.",
|
|
10
|
+
howToFix: ["Add https://demo.example.test to your project's trusted domains."]
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function overlayRoots() {
|
|
14
|
+
return document.querySelectorAll(".hexclave-setup-error-overlay");
|
|
15
|
+
}
|
|
16
|
+
describe("setup error overlay", () => {
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
vi.unstubAllEnvs();
|
|
19
|
+
for (const root of overlayRoots()) root.remove();
|
|
20
|
+
Reflect.deleteProperty(window, SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY);
|
|
21
|
+
});
|
|
22
|
+
it("renders setup errors with their fix instructions, even outside development", () => {
|
|
23
|
+
vi.stubEnv("NODE_ENV", "production");
|
|
24
|
+
const error = createSetupError();
|
|
25
|
+
const cleanup = showSetupErrorOverlay(error);
|
|
26
|
+
try {
|
|
27
|
+
expect(overlayRoots()).toHaveLength(1);
|
|
28
|
+
const text = document.body.textContent;
|
|
29
|
+
expect(text).toContain(error.title);
|
|
30
|
+
expect(text).toContain(error.message);
|
|
31
|
+
expect(text).toContain(error.howToFix[0]);
|
|
32
|
+
expect(document.querySelector("[role='alertdialog']")).not.toBeNull();
|
|
33
|
+
} finally {
|
|
34
|
+
cleanup();
|
|
35
|
+
}
|
|
36
|
+
expect(overlayRoots()).toHaveLength(0);
|
|
37
|
+
});
|
|
38
|
+
it("minimizes into a pill and back", () => {
|
|
39
|
+
vi.stubEnv("NODE_ENV", "production");
|
|
40
|
+
const cleanup = showSetupErrorOverlay(createSetupError());
|
|
41
|
+
try {
|
|
42
|
+
const minimizeButton = document.querySelector("[aria-label='Minimize Hexclave setup error']");
|
|
43
|
+
expect(minimizeButton).not.toBeNull();
|
|
44
|
+
minimizeButton?.click();
|
|
45
|
+
expect(document.querySelector("[role='alertdialog']")).toBeNull();
|
|
46
|
+
const pill = document.querySelector("[aria-label='Show Hexclave setup error']");
|
|
47
|
+
expect(pill).not.toBeNull();
|
|
48
|
+
pill?.click();
|
|
49
|
+
expect(document.querySelector("[role='alertdialog']")).not.toBeNull();
|
|
50
|
+
} finally {
|
|
51
|
+
cleanup();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
it("keeps keyboard focus inside the card and gives it back afterwards", () => {
|
|
55
|
+
vi.stubEnv("NODE_ENV", "production");
|
|
56
|
+
const pageButton = document.body.appendChild(document.createElement("button"));
|
|
57
|
+
pageButton.focus();
|
|
58
|
+
const cleanup = showSetupErrorOverlay(createSetupError());
|
|
59
|
+
try {
|
|
60
|
+
const card = document.querySelector("[role='alertdialog']");
|
|
61
|
+
expect(document.activeElement).toBe(card);
|
|
62
|
+
const cardButtons = [...card?.querySelectorAll("button") ?? []];
|
|
63
|
+
expect(cardButtons.length).toBeGreaterThan(1);
|
|
64
|
+
cardButtons[cardButtons.length - 1].focus();
|
|
65
|
+
document.dispatchEvent(new KeyboardEvent("keydown", {
|
|
66
|
+
key: "Tab",
|
|
67
|
+
bubbles: true,
|
|
68
|
+
cancelable: true
|
|
69
|
+
}));
|
|
70
|
+
expect(document.activeElement).toBe(cardButtons[0]);
|
|
71
|
+
document.dispatchEvent(new KeyboardEvent("keydown", {
|
|
72
|
+
key: "Tab",
|
|
73
|
+
bubbles: true,
|
|
74
|
+
cancelable: true,
|
|
75
|
+
shiftKey: true
|
|
76
|
+
}));
|
|
77
|
+
expect(document.activeElement).toBe(cardButtons[cardButtons.length - 1]);
|
|
78
|
+
pageButton.focus();
|
|
79
|
+
document.dispatchEvent(new KeyboardEvent("keydown", {
|
|
80
|
+
key: "Tab",
|
|
81
|
+
bubbles: true,
|
|
82
|
+
cancelable: true
|
|
83
|
+
}));
|
|
84
|
+
expect(document.activeElement).toBe(cardButtons[0]);
|
|
85
|
+
} finally {
|
|
86
|
+
cleanup();
|
|
87
|
+
}
|
|
88
|
+
expect(document.activeElement).toBe(pageButton);
|
|
89
|
+
pageButton.remove();
|
|
90
|
+
});
|
|
91
|
+
it("keeps the first card instead of stacking later errors on top of it", () => {
|
|
92
|
+
vi.stubEnv("NODE_ENV", "production");
|
|
93
|
+
const firstError = createSetupError();
|
|
94
|
+
const cleanup = showSetupErrorOverlay(firstError);
|
|
95
|
+
try {
|
|
96
|
+
showSetupErrorOverlay(new HexclaveSetupError({
|
|
97
|
+
title: "Another setup error",
|
|
98
|
+
message: "Another setup error happened.",
|
|
99
|
+
howToFix: ["Fix the other thing."]
|
|
100
|
+
}))();
|
|
101
|
+
expect(overlayRoots()).toHaveLength(1);
|
|
102
|
+
expect(document.body.textContent).toContain(firstError.message);
|
|
103
|
+
expect(document.body.textContent).not.toContain("Another setup error happened.");
|
|
104
|
+
} finally {
|
|
105
|
+
cleanup();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
it("only shows errors that are not setup errors while developing", () => {
|
|
109
|
+
vi.stubEnv("NODE_ENV", "production");
|
|
110
|
+
showSetupErrorOverlay(/* @__PURE__ */ new Error("Some internal failure."))();
|
|
111
|
+
expect(overlayRoots()).toHaveLength(0);
|
|
112
|
+
vi.stubEnv("NODE_ENV", "development");
|
|
113
|
+
const cleanup = showSetupErrorOverlay(/* @__PURE__ */ new Error("Some internal failure."));
|
|
114
|
+
try {
|
|
115
|
+
expect(overlayRoots()).toHaveLength(1);
|
|
116
|
+
expect(document.body.textContent).toContain("Some internal failure.");
|
|
117
|
+
} finally {
|
|
118
|
+
cleanup();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
//#endregion
|
|
123
|
+
export {};
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","names":[],"sources":["../../../src/setup-error-overlay/index.test.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n// @vitest-environment jsdom\n\nimport { HexclaveSetupError } from \"@hexclave/shared/dist/utils/errors\";\nimport { afterEach, describe, expect, it, vi } from \"vitest\";\nimport { SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY, showSetupErrorOverlay } from \".\";\n\nfunction createSetupError() {\n return new HexclaveSetupError({\n title: \"A domain in your authentication flow is not one of your project's trusted domains\",\n message: \"Nested cross-domain auth callback URL https://demo.example.test/ is not trusted.\",\n howToFix: [\"Add https://demo.example.test to your project's trusted domains.\"],\n });\n}\n\nfunction overlayRoots() {\n return document.querySelectorAll(\".hexclave-setup-error-overlay\");\n}\n\ndescribe(\"setup error overlay\", () => {\n afterEach(() => {\n vi.unstubAllEnvs();\n for (const root of overlayRoots()) {\n root.remove();\n }\n Reflect.deleteProperty(window, SETUP_ERROR_OVERLAY_GLOBAL_INSTANCE_KEY);\n });\n\n it(\"renders setup errors with their fix instructions, even outside development\", () => {\n vi.stubEnv(\"NODE_ENV\", \"production\");\n const error = createSetupError();\n\n const cleanup = showSetupErrorOverlay(error);\n try {\n expect(overlayRoots()).toHaveLength(1);\n const text = document.body.textContent;\n expect(text).toContain(error.title);\n expect(text).toContain(error.message);\n expect(text).toContain(error.howToFix[0]);\n expect(document.querySelector(\"[role='alertdialog']\")).not.toBeNull();\n } finally {\n cleanup();\n }\n\n expect(overlayRoots()).toHaveLength(0);\n });\n\n it(\"minimizes into a pill and back\", () => {\n vi.stubEnv(\"NODE_ENV\", \"production\");\n const cleanup = showSetupErrorOverlay(createSetupError());\n try {\n const minimizeButton = document.querySelector<HTMLButtonElement>(\"[aria-label='Minimize Hexclave setup error']\");\n expect(minimizeButton).not.toBeNull();\n minimizeButton?.click();\n expect(document.querySelector(\"[role='alertdialog']\")).toBeNull();\n\n const pill = document.querySelector<HTMLButtonElement>(\"[aria-label='Show Hexclave setup error']\");\n expect(pill).not.toBeNull();\n pill?.click();\n expect(document.querySelector(\"[role='alertdialog']\")).not.toBeNull();\n } finally {\n cleanup();\n }\n });\n\n it(\"keeps keyboard focus inside the card and gives it back afterwards\", () => {\n vi.stubEnv(\"NODE_ENV\", \"production\");\n const pageButton = document.body.appendChild(document.createElement(\"button\"));\n pageButton.focus();\n\n const cleanup = showSetupErrorOverlay(createSetupError());\n try {\n const card = document.querySelector<HTMLElement>(\"[role='alertdialog']\");\n expect(document.activeElement).toBe(card);\n\n const cardButtons = [...(card?.querySelectorAll(\"button\") ?? [])];\n expect(cardButtons.length).toBeGreaterThan(1);\n cardButtons[cardButtons.length - 1].focus();\n document.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"Tab\", bubbles: true, cancelable: true }));\n expect(document.activeElement).toBe(cardButtons[0]);\n document.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"Tab\", bubbles: true, cancelable: true, shiftKey: true }));\n expect(document.activeElement).toBe(cardButtons[cardButtons.length - 1]);\n\n // Tabbing away from the card is what the trap exists to prevent, even when the page itself moves focus.\n pageButton.focus();\n document.dispatchEvent(new KeyboardEvent(\"keydown\", { key: \"Tab\", bubbles: true, cancelable: true }));\n expect(document.activeElement).toBe(cardButtons[0]);\n } finally {\n cleanup();\n }\n\n expect(document.activeElement).toBe(pageButton);\n pageButton.remove();\n });\n\n it(\"keeps the first card instead of stacking later errors on top of it\", () => {\n vi.stubEnv(\"NODE_ENV\", \"production\");\n const firstError = createSetupError();\n const cleanup = showSetupErrorOverlay(firstError);\n try {\n const secondCleanup = showSetupErrorOverlay(new HexclaveSetupError({\n title: \"Another setup error\",\n message: \"Another setup error happened.\",\n howToFix: [\"Fix the other thing.\"],\n }));\n secondCleanup();\n\n expect(overlayRoots()).toHaveLength(1);\n expect(document.body.textContent).toContain(firstError.message);\n expect(document.body.textContent).not.toContain(\"Another setup error happened.\");\n } finally {\n cleanup();\n }\n });\n\n it(\"only shows errors that are not setup errors while developing\", () => {\n vi.stubEnv(\"NODE_ENV\", \"production\");\n showSetupErrorOverlay(new Error(\"Some internal failure.\"))();\n expect(overlayRoots()).toHaveLength(0);\n\n vi.stubEnv(\"NODE_ENV\", \"development\");\n const cleanup = showSetupErrorOverlay(new Error(\"Some internal failure.\"));\n try {\n expect(overlayRoots()).toHaveLength(1);\n expect(document.body.textContent).toContain(\"Some internal failure.\");\n } finally {\n cleanup();\n }\n });\n});\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as quetzalLocales, t as quetzalKeys } from "../quetzal-translations-
|
|
1
|
+
import { n as quetzalLocales, t as quetzalKeys } from "../quetzal-translations-CK45_4Dm.js";
|
|
2
2
|
export { quetzalKeys, quetzalLocales };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { N as StackAdminApp, a as StackClientApp, z as StackServerApp } from "./client-app-BCT5p_70.js";
|
|
2
|
-
import { t as TranslationProvider } from "./translation-provider-
|
|
2
|
+
import { t as TranslationProvider } from "./translation-provider-DQ3BJepJ.js";
|
|
3
3
|
import React from "react";
|
|
4
4
|
|
|
5
5
|
//#region src/providers/hexclave-provider.d.ts
|
|
@@ -26,4 +26,4 @@ declare const HexclaveProvider: typeof NextStackProvider;
|
|
|
26
26
|
declare const StackProvider: typeof NextStackProvider;
|
|
27
27
|
//#endregion
|
|
28
28
|
export { HexclaveProvider as n, StackProvider as r, ActiveProvider as t };
|
|
29
|
-
//# sourceMappingURL=hexclave-provider-
|
|
29
|
+
//# sourceMappingURL=hexclave-provider-BA97jMlx.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hexclave-provider-
|
|
1
|
+
{"version":3,"file":"hexclave-provider-BA97jMlx.d.ts","names":[],"sources":["../src/providers/hexclave-provider.tsx"],"mappings":";;;;;iBASS,iBAAA;EACP,QAAA;EACA,GAAA;EACA,IAAA;EACA;AAAA;EAEA,IAAA,GAAO,KAAA,CAAM,cAAA,QAAsB,mBAAA;;AARwB;;;;;EAe3D,oBAAA,GAAuB,MAAA;EACvB,QAAA,EAAU,KAAA,CAAM,SAAA;EAEhB,GAAA,EAAK,cAAA,SAAuB,cAAA,SAAuB,aAAA;AAAA,gCACpD,GAAA,CAAA,OAAA;AAAA,cAcK,cAAA,SAAc,iBAAoB;AAAA,cAI3B,gBAAA,SAAgB,iBAAiB;;cAEjC,aAAA,SAAa,iBAAiB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-environment.d.ts","names":[],"sources":["../../src/in-page-ui/dev-environment.ts"],"mappings":";iBAWgB,8BAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _hexclave_shared_dist_utils_urls = require("@hexclave/shared/dist/utils/urls");
|
|
3
|
+
let ___generated_env_js = require("../generated/env.js");
|
|
4
|
+
//#region src/in-page-ui/dev-environment.ts
|
|
5
|
+
function isLikelyDevelopmentEnvironment() {
|
|
6
|
+
const nodeEnv = ___generated_env_js.envVars.NODE_ENV;
|
|
7
|
+
if (nodeEnv !== void 0) return nodeEnv === "development";
|
|
8
|
+
if (typeof window === "undefined") return false;
|
|
9
|
+
try {
|
|
10
|
+
if (new URL(window.location.href).protocol === "file:") return true;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return (0, _hexclave_shared_dist_utils_urls.isLocalhost)(window.location.href);
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.isLikelyDevelopmentEnvironment = isLikelyDevelopmentEnvironment;
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=dev-environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-environment.js","names":["envVars"],"sources":["../../src/in-page-ui/dev-environment.ts"],"sourcesContent":["\n//===========================================\n// THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template\n//===========================================\n// Shared \"are we in a development-like environment?\" check for Hexclave's in-page UIs. Some of them (eg. surfacing an\n// unexpected internal error) are only appropriate while developing, and the SDK cannot ask the server about it because\n// the check has to work synchronously and before the app is authenticated.\n\nimport { isLocalhost } from \"@hexclave/shared/dist/utils/urls\";\nimport { envVars } from \"../generated/env\";\n\nexport function isLikelyDevelopmentEnvironment(): boolean {\n // NODE_ENV is the most reliable signal, but plenty of bundlers (eg. Vite-based ones) don't define it in the browser\n // bundle at all, so fall back to guessing from the current URL.\n const nodeEnv = envVars.NODE_ENV;\n if (nodeEnv !== undefined) {\n return nodeEnv === \"development\";\n }\n\n if (typeof window === \"undefined\") {\n return false;\n }\n\n try {\n const url = new URL(window.location.href);\n if (url.protocol === \"file:\") {\n return true;\n }\n } catch {\n return false;\n }\n return isLocalhost(window.location.href);\n}\n"],"mappings":";;;;AAWA,SAAgB,iCAA0C;CAGxD,MAAM,UAAUA,oBAAAA,QAAQ;CACxB,IAAI,YAAY,KAAA,GACd,OAAO,YAAY;CAGrB,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EAEF,IAAI,IADY,IAAI,OAAO,SAAS,IAC9B,CAAC,CAAC,aAAa,SACnB,OAAO;CAEX,QAAQ;EACN,OAAO;CACT;CACA,QAAA,GAAA,iCAAA,YAAA,CAAmB,OAAO,SAAS,IAAI;AACzC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/in-page-ui/issue-card.d.ts
|
|
2
|
+
type IssueCardKind = "error" | "warning";
|
|
3
|
+
declare function getIssueCardCSS(scopeSelector: string): string;
|
|
4
|
+
declare function copyTextToClipboard(text: string): Promise<void>;
|
|
5
|
+
type IssueCardOptions = {
|
|
6
|
+
kind: IssueCardKind; /** Short uppercase label in the card's badge, eg. "Config error". */
|
|
7
|
+
badge: string;
|
|
8
|
+
title: string; /** One or two sentences on what this means for the running app. */
|
|
9
|
+
bodyText: string;
|
|
10
|
+
messageLabel: string;
|
|
11
|
+
message: string; /** Concrete steps the developer should take; rendered as a list above the footer. */
|
|
12
|
+
howToFix?: readonly string[];
|
|
13
|
+
footerText: string;
|
|
14
|
+
ariaLabel: string; /** Prompt for the "copy AI prompt" button, ie. the message plus enough context for a coding agent to fix it. */
|
|
15
|
+
aiPrompt: string;
|
|
16
|
+
onCopyError: (error: unknown) => void;
|
|
17
|
+
onCopyAiPromptError: (error: unknown) => void;
|
|
18
|
+
onMinimize: () => void;
|
|
19
|
+
};
|
|
20
|
+
declare function renderIssueCard(options: IssueCardOptions): HTMLElement;
|
|
21
|
+
type IssueCardFocusTrap = {
|
|
22
|
+
/**
|
|
23
|
+
* Whatever had focus before the card first appeared. Callers that rebind the trap to a re-rendered card pass it back
|
|
24
|
+
* in, so focus still returns to where the developer left it once the card is gone for good.
|
|
25
|
+
*/
|
|
26
|
+
previouslyFocused: HTMLElement | null;
|
|
27
|
+
release: (releaseOptions?: {
|
|
28
|
+
restoreFocus?: boolean;
|
|
29
|
+
}) => void;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Keeps keyboard focus inside a mounted card, which claims to be an `aria-modal` alertdialog and therefore has to behave
|
|
33
|
+
* like one: the flow behind the card is dead until the problem is fixed, so tabbing into it would only let a keyboard
|
|
34
|
+
* user wander through a page that cannot work while the card stays invisible to them.
|
|
35
|
+
*
|
|
36
|
+
* Call right after mounting the card, and release the trap when the card is minimized, replaced or removed. Releasing
|
|
37
|
+
* hands focus back to `previouslyFocused` unless `restoreFocus: false` is passed, which is what a caller that is about
|
|
38
|
+
* to rebind the trap to a freshly rendered card wants.
|
|
39
|
+
*/
|
|
40
|
+
declare function trapFocusInIssueCard(cardRoot: HTMLElement, options?: {
|
|
41
|
+
moveFocusIntoCard?: boolean;
|
|
42
|
+
previouslyFocused?: HTMLElement | null;
|
|
43
|
+
}): IssueCardFocusTrap;
|
|
44
|
+
declare function renderIssuePill(options: {
|
|
45
|
+
kind: IssueCardKind;
|
|
46
|
+
label: string;
|
|
47
|
+
ariaLabel: string;
|
|
48
|
+
onClick: () => void;
|
|
49
|
+
}): HTMLElement;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { IssueCardFocusTrap, IssueCardKind, IssueCardOptions, copyTextToClipboard, getIssueCardCSS, renderIssueCard, renderIssuePill, trapFocusInIssueCard };
|
|
52
|
+
//# sourceMappingURL=issue-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-card.d.ts","names":[],"sources":["../../src/in-page-ui/issue-card.ts"],"mappings":";KAcY,aAAA;AAAA,iBAII,eAAA,CAAgB,aAAqB;AAAA,iBAyP/B,mBAAA,CAAoB,IAAA,WAAe,OAAO;AAAA,KAkEpD,gBAAA;EACV,IAAA,EAAM,aAAa,EAhUI;EAkUvB,KAAA;EACA,KAAA;EAEA,QAAA;EACA,YAAA;EACA,OAAA,UA1EuC;EA4EvC,QAAA;EACA,UAAA;EACA,SAAA,UAZU;EAcV,QAAA;EACA,WAAA,GAAc,KAAA;EACd,mBAAA,GAAsB,KAAA;EACtB,UAAA;AAAA;AAAA,iBAGc,eAAA,CAAgB,OAAA,EAAS,gBAAA,GAAmB,WAAW;AAAA,KA+D3D,kBAAA;EA7EV;;;;EAkFA,iBAAA,EAAmB,WAAW;EAC9B,OAAA,GAAU,cAAA;IAAmB,YAAA;EAAA;AAAA;;;;;AAxEnB;AAGZ;;;;iBAiFgB,oBAAA,CAAqB,QAAA,EAAU,WAAA,EAAa,OAAA;EAC1D,iBAAA;EACA,iBAAA,GAAoB,WAAA;AAAA,IACb,kBAAA;AAAA,iBA6CO,eAAA,CAAgB,OAAA;EAC9B,IAAA,EAAM,aAAA;EACN,KAAA;EACA,SAAA;EACA,OAAA;AAAA,IACE,WAAW"}
|