@hexclave/js 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.
Files changed (98) hide show
  1. package/dist/{admin-app-impl-BgUMxiV3.d.ts → admin-app-impl-B86v7B0O.d.ts} +2 -2
  2. package/dist/{admin-app-impl-BgUMxiV3.d.ts.map → admin-app-impl-B86v7B0O.d.ts.map} +1 -1
  3. package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
  4. package/dist/dev-tool/dev-tool-core.js +2 -2
  5. package/dist/dev-tool/dev-tool-core.js.map +1 -1
  6. package/dist/dev-tool/index.d.ts.map +1 -1
  7. package/dist/dev-tool/index.js +2 -8
  8. package/dist/dev-tool/index.js.map +1 -1
  9. package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
  10. package/dist/esm/dev-tool/dev-tool-core.js +1 -1
  11. package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
  12. package/dist/esm/dev-tool/index.d.ts.map +1 -1
  13. package/dist/esm/dev-tool/index.js +2 -8
  14. package/dist/esm/dev-tool/index.js.map +1 -1
  15. package/dist/esm/in-page-ui/dev-environment.d.ts +5 -0
  16. package/dist/esm/in-page-ui/dev-environment.d.ts.map +1 -0
  17. package/dist/esm/in-page-ui/dev-environment.js +18 -0
  18. package/dist/esm/in-page-ui/dev-environment.js.map +1 -0
  19. package/dist/esm/in-page-ui/issue-card.d.ts +52 -0
  20. package/dist/esm/in-page-ui/issue-card.d.ts.map +1 -0
  21. package/dist/esm/in-page-ui/issue-card.js +392 -0
  22. package/dist/esm/in-page-ui/issue-card.js.map +1 -0
  23. package/dist/esm/in-page-ui/issue-card.test.d.ts +1 -0
  24. package/dist/esm/in-page-ui/issue-card.test.js +60 -0
  25. package/dist/esm/in-page-ui/issue-card.test.js.map +1 -0
  26. package/dist/esm/in-page-ui/logo.d.ts +5 -0
  27. package/dist/esm/in-page-ui/logo.d.ts.map +1 -0
  28. package/dist/esm/in-page-ui/logo.js +6 -0
  29. package/dist/esm/in-page-ui/logo.js.map +1 -0
  30. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  31. package/dist/esm/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
  32. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +140 -15
  33. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  34. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.d.ts.map +1 -1
  35. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js +95 -12
  36. package/dist/esm/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  37. package/dist/esm/lib/hexclave-app/apps/implementations/common.js +2 -2
  38. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +1 -0
  39. package/dist/esm/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
  40. package/dist/esm/pushed-config-error-overlay/index.d.ts.map +1 -1
  41. package/dist/esm/pushed-config-error-overlay/index.js +42 -343
  42. package/dist/esm/pushed-config-error-overlay/index.js.map +1 -1
  43. package/dist/esm/setup-error-overlay/index.d.ts +16 -0
  44. package/dist/esm/setup-error-overlay/index.d.ts.map +1 -0
  45. package/dist/esm/setup-error-overlay/index.js +106 -0
  46. package/dist/esm/setup-error-overlay/index.js.map +1 -0
  47. package/dist/esm/setup-error-overlay/index.test.d.ts +1 -0
  48. package/dist/esm/setup-error-overlay/index.test.js +125 -0
  49. package/dist/esm/setup-error-overlay/index.test.js.map +1 -0
  50. package/dist/in-page-ui/dev-environment.d.ts +5 -0
  51. package/dist/in-page-ui/dev-environment.d.ts.map +1 -0
  52. package/dist/in-page-ui/dev-environment.js +19 -0
  53. package/dist/in-page-ui/dev-environment.js.map +1 -0
  54. package/dist/in-page-ui/issue-card.d.ts +52 -0
  55. package/dist/in-page-ui/issue-card.d.ts.map +1 -0
  56. package/dist/in-page-ui/issue-card.js +397 -0
  57. package/dist/in-page-ui/issue-card.js.map +1 -0
  58. package/dist/in-page-ui/issue-card.test.d.ts +1 -0
  59. package/dist/in-page-ui/issue-card.test.js +59 -0
  60. package/dist/in-page-ui/issue-card.test.js.map +1 -0
  61. package/dist/in-page-ui/logo.d.ts +5 -0
  62. package/dist/in-page-ui/logo.d.ts.map +1 -0
  63. package/dist/in-page-ui/logo.js +7 -0
  64. package/dist/in-page-ui/logo.js.map +1 -0
  65. package/dist/lib/hexclave-app/apps/implementations/admin-app-impl.d.ts +1 -1
  66. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js +140 -15
  67. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
  68. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.d.ts +1 -1
  69. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js +94 -11
  70. package/dist/lib/hexclave-app/apps/implementations/client-app-impl.js.map +1 -1
  71. package/dist/lib/hexclave-app/apps/implementations/common.js +2 -2
  72. package/dist/lib/hexclave-app/apps/implementations/index.d.ts +1 -1
  73. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js +1 -0
  74. package/dist/lib/hexclave-app/apps/implementations/redirect-page-urls.test.js.map +1 -1
  75. package/dist/lib/hexclave-app/apps/implementations/server-app-impl.d.ts +1 -1
  76. package/dist/pushed-config-error-overlay/index.d.ts.map +1 -1
  77. package/dist/pushed-config-error-overlay/index.js +41 -342
  78. package/dist/pushed-config-error-overlay/index.js.map +1 -1
  79. package/dist/setup-error-overlay/index.d.ts +16 -0
  80. package/dist/setup-error-overlay/index.d.ts.map +1 -0
  81. package/dist/setup-error-overlay/index.js +108 -0
  82. package/dist/setup-error-overlay/index.js.map +1 -0
  83. package/dist/setup-error-overlay/index.test.d.ts +1 -0
  84. package/dist/setup-error-overlay/index.test.js +124 -0
  85. package/dist/setup-error-overlay/index.test.js.map +1 -0
  86. package/package.json +2 -2
  87. package/src/dev-tool/dev-tool-core.ts +1 -4
  88. package/src/dev-tool/index.ts +4 -15
  89. package/src/in-page-ui/dev-environment.ts +33 -0
  90. package/src/in-page-ui/issue-card.test.ts +67 -0
  91. package/src/in-page-ui/issue-card.ts +500 -0
  92. package/src/in-page-ui/logo.ts +8 -0
  93. package/src/lib/hexclave-app/apps/implementations/client-app-impl.cross-domain.test.ts +158 -0
  94. package/src/lib/hexclave-app/apps/implementations/client-app-impl.ts +125 -17
  95. package/src/lib/hexclave-app/apps/implementations/redirect-page-urls.test.ts +1 -0
  96. package/src/pushed-config-error-overlay/index.ts +45 -386
  97. package/src/setup-error-overlay/index.test.ts +133 -0
  98. package/src/setup-error-overlay/index.ts +150 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/dev-tool/index.ts"],"mappings":";;;;;AA2GA;;;;;;;;AAAwF;;;iBAAxE,YAAA,CAAa,GAAA,EAAK,cAAc,QAAQ,aAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/dev-tool/index.ts"],"mappings":";;;;;AAgGA;;;;;;;;AAAwF;;;iBAAxE,YAAA,CAAa,GAAA,EAAK,cAAc,QAAQ,aAAA"}
@@ -1,8 +1,7 @@
1
1
  import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
2
2
  import { canMountIntoDom } from "../in-page-ui/dom.js";
3
3
  import { captureError } from "@hexclave/shared/dist/utils/errors";
4
- import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
5
- import { envVars } from "../generated/env.js";
4
+ import { isLikelyDevelopmentEnvironment } from "../in-page-ui/dev-environment.js";
6
5
  //#region src/dev-tool/index.ts
7
6
  const OVERRIDE_KEY = "__hexclave-dev-tool-override";
8
7
  function getOverride() {
@@ -21,12 +20,7 @@ function shouldShow() {
21
20
  if (!canMountIntoDom()) return false;
22
21
  if (activeDevToolOption === true) return true;
23
22
  if (activeProjectIsDevelopmentEnvironment) return true;
24
- const nodeEnv = envVars.NODE_ENV;
25
- if (nodeEnv !== void 0) return nodeEnv === "development";
26
- try {
27
- if (new URL(window.location.href).protocol === "file:") return true;
28
- } catch {}
29
- return isLocalhost(window.location.href);
23
+ return isLikelyDevelopmentEnvironment();
30
24
  }
31
25
  let activeCleanup = null;
32
26
  let activeApp = null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/dev-tool/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\nimport type { StackClientApp } from \"../lib/hexclave-app\";\nimport { captureError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { isLocalhost } from \"@hexclave/shared/dist/utils/urls\";\nimport { canMountIntoDom } from \"../in-page-ui/dom\";\nimport { envVars } from \"../generated/env\";\nimport type { createDevTool as CreateDevToolFn } from \"./dev-tool-core\";\n\n// Hexclave rebrand: UI-only local pref — straight rename (one-time reset is harmless)\nconst OVERRIDE_KEY = '__hexclave-dev-tool-override';\n\nfunction getOverride(): boolean | null {\n try {\n const val = localStorage.getItem(OVERRIDE_KEY);\n if (val === 'true') return true;\n if (val === 'false') return false;\n } catch {}\n return null;\n}\n\nlet activeDevToolOption: true | \"auto\" | undefined = undefined;\nlet activeProjectIsDevelopmentEnvironment = false;\n\nfunction shouldShow(): boolean {\n const override = getOverride();\n if (override !== null) return override;\n if (!canMountIntoDom()) return false;\n\n // If devTool was explicitly set to true, always show\n if (activeDevToolOption === true) return true;\n\n // Development environment projects should expose the tool even when the\n // consuming app itself was built or hosted as production.\n if (activeProjectIsDevelopmentEnvironment) return true;\n\n // \"auto\" behavior (the default):\n const nodeEnv = envVars.NODE_ENV;\n if (nodeEnv !== undefined) {\n // NODE_ENV is available (bundler/process env exists) — only show in development\n return nodeEnv === \"development\";\n }\n\n // NODE_ENV not found (no process.env/import.meta) — show on localhost or file: protocol\n try {\n const url = new URL(window.location.href);\n if (url.protocol === \"file:\") return true;\n } catch {}\n return isLocalhost(window.location.href);\n}\n\nlet activeCleanup: (() => void) | null = null;\nlet activeApp: StackClientApp<true> | null = null;\nlet mountGeneration = 0;\n\nlet createDevToolPromise: Promise<typeof CreateDevToolFn> | null = null;\nfunction loadCreateDevTool(): Promise<typeof CreateDevToolFn> {\n if (!createDevToolPromise) {\n createDevToolPromise = import(\"./dev-tool-core\").then(m => m.createDevTool).catch((err) => {\n createDevToolPromise = null;\n throw err;\n });\n }\n return createDevToolPromise;\n}\n\nfunction tryMount() {\n if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n\n if (!shouldShow() || !activeApp || !canMountIntoDom()) return;\n\n const generation = ++mountGeneration;\n const app = activeApp;\n\n runAsynchronously(async () => {\n const createDevTool = await loadCreateDevTool();\n if (generation !== mountGeneration) return;\n if (!shouldShow() || activeApp !== app || !canMountIntoDom()) return;\n activeCleanup = createDevTool(app);\n }, {\n noErrorLogging: true,\n onError: (error) => {\n captureError(\"dev-tool-mount\", error);\n },\n });\n}\n\n/**\n * Mounts the Hexclave dev tool on the page.\n *\n * Visibility is determined by the `devTool` option:\n * - `true`: always show\n * - `false`: never show (caller gates this — mountDevTool won't be called)\n * - `\"auto\"` / `undefined`: show based on NODE_ENV or localhost/file: heuristics\n *\n * Console commands (also work in production):\n * HexclaveDevTool.enable() — force-show the dev tool\n * HexclaveDevTool.disable() — force-hide the dev tool\n * HexclaveDevTool.reset() — revert to auto behavior\n */\nexport function mountDevTool(app: StackClientApp<true>, devToolOption?: boolean | \"auto\"): () => void {\n activeApp = app;\n activeDevToolOption = devToolOption === false ? undefined : devToolOption ?? undefined;\n activeProjectIsDevelopmentEnvironment = false;\n tryMount();\n\n // The project endpoint is also the source of config warnings, so this uses\n // the backend's development-environment flag instead of inferring it from\n // the SDK's build or the current page's origin.\n queueMicrotask(() => {\n runAsynchronously(async () => {\n const project = await app.getProject();\n if (activeApp !== app) return;\n activeProjectIsDevelopmentEnvironment = project.isDevelopmentEnvironment;\n if (activeProjectIsDevelopmentEnvironment && activeCleanup === null) {\n tryMount();\n }\n }, {\n noErrorLogging: true,\n onError: (error) => {\n captureError(\"dev-tool-project-detection\", error);\n },\n });\n });\n\n // Capture the cleanup created by THIS specific mount call so that React\n // StrictMode's double-invoke doesn't let the first effect's cleanup tear\n // down the second mount (which would cause the tool to disappear silently).\n const myCleanup = activeCleanup;\n\n return () => {\n activeApp = null;\n activeProjectIsDevelopmentEnvironment = false;\n if (activeCleanup === myCleanup && myCleanup != null) {\n activeCleanup = null;\n myCleanup();\n }\n };\n}\n\n// Expose console commands: HexclaveDevTool.enable() / .disable() / .reset()\nif (typeof window !== 'undefined') {\n // Hexclave rebrand: expose under both the legacy and new global names.\n (window as any).HexclaveDevTool = (window as any).HexclaveDevTool = {\n enable() {\n try {\n localStorage.setItem(OVERRIDE_KEY, 'true');\n } catch {}\n tryMount();\n console.log('[Stack DevTool] Enabled. Refresh if the panel does not appear.');\n },\n disable() {\n try {\n localStorage.setItem(OVERRIDE_KEY, 'false');\n } catch {}\n if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n console.log('[Stack DevTool] Disabled.');\n },\n reset() {\n try {\n localStorage.removeItem(OVERRIDE_KEY);\n } catch {}\n if (shouldShow()) {\n tryMount();\n } else if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n console.log('[Stack DevTool] Reset to default (auto-detect based on project, NODE_ENV, or localhost/file: origin).');\n },\n };\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/dev-tool/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\nimport type { StackClientApp } from \"../lib/hexclave-app\";\nimport { captureError } from \"@hexclave/shared/dist/utils/errors\";\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { isLikelyDevelopmentEnvironment } from \"../in-page-ui/dev-environment\";\nimport { canMountIntoDom } from \"../in-page-ui/dom\";\nimport type { createDevTool as CreateDevToolFn } from \"./dev-tool-core\";\n\n// Hexclave rebrand: UI-only local pref — straight rename (one-time reset is harmless)\nconst OVERRIDE_KEY = '__hexclave-dev-tool-override';\n\nfunction getOverride(): boolean | null {\n try {\n const val = localStorage.getItem(OVERRIDE_KEY);\n if (val === 'true') return true;\n if (val === 'false') return false;\n } catch {}\n return null;\n}\n\nlet activeDevToolOption: true | \"auto\" | undefined = undefined;\nlet activeProjectIsDevelopmentEnvironment = false;\n\nfunction shouldShow(): boolean {\n const override = getOverride();\n if (override !== null) return override;\n if (!canMountIntoDom()) return false;\n\n // If devTool was explicitly set to true, always show\n if (activeDevToolOption === true) return true;\n\n // Development environment projects should expose the tool even when the\n // consuming app itself was built or hosted as production.\n if (activeProjectIsDevelopmentEnvironment) return true;\n\n // \"auto\" behavior (the default): every in-page UI that is only appropriate while developing shares one heuristic, so\n // the dev tool and the error cards can never disagree about whether this looks like a development environment.\n return isLikelyDevelopmentEnvironment();\n}\n\nlet activeCleanup: (() => void) | null = null;\nlet activeApp: StackClientApp<true> | null = null;\nlet mountGeneration = 0;\n\nlet createDevToolPromise: Promise<typeof CreateDevToolFn> | null = null;\nfunction loadCreateDevTool(): Promise<typeof CreateDevToolFn> {\n if (!createDevToolPromise) {\n createDevToolPromise = import(\"./dev-tool-core\").then(m => m.createDevTool).catch((err) => {\n createDevToolPromise = null;\n throw err;\n });\n }\n return createDevToolPromise;\n}\n\nfunction tryMount() {\n if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n\n if (!shouldShow() || !activeApp || !canMountIntoDom()) return;\n\n const generation = ++mountGeneration;\n const app = activeApp;\n\n runAsynchronously(async () => {\n const createDevTool = await loadCreateDevTool();\n if (generation !== mountGeneration) return;\n if (!shouldShow() || activeApp !== app || !canMountIntoDom()) return;\n activeCleanup = createDevTool(app);\n }, {\n noErrorLogging: true,\n onError: (error) => {\n captureError(\"dev-tool-mount\", error);\n },\n });\n}\n\n/**\n * Mounts the Hexclave dev tool on the page.\n *\n * Visibility is determined by the `devTool` option:\n * - `true`: always show\n * - `false`: never show (caller gates this — mountDevTool won't be called)\n * - `\"auto\"` / `undefined`: show based on NODE_ENV or localhost/file: heuristics\n *\n * Console commands (also work in production):\n * HexclaveDevTool.enable() — force-show the dev tool\n * HexclaveDevTool.disable() — force-hide the dev tool\n * HexclaveDevTool.reset() — revert to auto behavior\n */\nexport function mountDevTool(app: StackClientApp<true>, devToolOption?: boolean | \"auto\"): () => void {\n activeApp = app;\n activeDevToolOption = devToolOption === false ? undefined : devToolOption ?? undefined;\n activeProjectIsDevelopmentEnvironment = false;\n tryMount();\n\n // The project endpoint is also the source of config warnings, so this uses\n // the backend's development-environment flag instead of inferring it from\n // the SDK's build or the current page's origin.\n queueMicrotask(() => {\n runAsynchronously(async () => {\n const project = await app.getProject();\n if (activeApp !== app) return;\n activeProjectIsDevelopmentEnvironment = project.isDevelopmentEnvironment;\n if (activeProjectIsDevelopmentEnvironment && activeCleanup === null) {\n tryMount();\n }\n }, {\n noErrorLogging: true,\n onError: (error) => {\n captureError(\"dev-tool-project-detection\", error);\n },\n });\n });\n\n // Capture the cleanup created by THIS specific mount call so that React\n // StrictMode's double-invoke doesn't let the first effect's cleanup tear\n // down the second mount (which would cause the tool to disappear silently).\n const myCleanup = activeCleanup;\n\n return () => {\n activeApp = null;\n activeProjectIsDevelopmentEnvironment = false;\n if (activeCleanup === myCleanup && myCleanup != null) {\n activeCleanup = null;\n myCleanup();\n }\n };\n}\n\n// Expose console commands: HexclaveDevTool.enable() / .disable() / .reset()\nif (typeof window !== 'undefined') {\n // Hexclave rebrand: expose under both the legacy and new global names.\n (window as any).HexclaveDevTool = (window as any).HexclaveDevTool = {\n enable() {\n try {\n localStorage.setItem(OVERRIDE_KEY, 'true');\n } catch {}\n tryMount();\n console.log('[Stack DevTool] Enabled. Refresh if the panel does not appear.');\n },\n disable() {\n try {\n localStorage.setItem(OVERRIDE_KEY, 'false');\n } catch {}\n if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n console.log('[Stack DevTool] Disabled.');\n },\n reset() {\n try {\n localStorage.removeItem(OVERRIDE_KEY);\n } catch {}\n if (shouldShow()) {\n tryMount();\n } else if (activeCleanup) {\n activeCleanup();\n activeCleanup = null;\n }\n console.log('[Stack DevTool] Reset to default (auto-detect based on project, NODE_ENV, or localhost/file: origin).');\n },\n };\n}\n\n"],"mappings":";;;;;AAaA,MAAM,eAAe;AAErB,SAAS,cAA8B;CACrC,IAAI;EACF,MAAM,MAAM,aAAa,QAAQ,YAAY;EAC7C,IAAI,QAAQ,QAAQ,OAAO;EAC3B,IAAI,QAAQ,SAAS,OAAO;CAC9B,QAAQ,CAAC;CACT,OAAO;AACT;AAEA,IAAI,sBAAiD,KAAA;AACrD,IAAI,wCAAwC;AAE5C,SAAS,aAAsB;CAC7B,MAAM,WAAW,YAAY;CAC7B,IAAI,aAAa,MAAM,OAAO;CAC9B,IAAI,CAAC,gBAAgB,GAAG,OAAO;CAG/B,IAAI,wBAAwB,MAAM,OAAO;CAIzC,IAAI,uCAAuC,OAAO;CAIlD,OAAO,+BAA+B;AACxC;AAEA,IAAI,gBAAqC;AACzC,IAAI,YAAyC;AAC7C,IAAI,kBAAkB;AAEtB,IAAI,uBAA+D;AACnE,SAAS,oBAAqD;CAC5D,IAAI,CAAC,sBACH,uBAAuB,OAAO,qBAAkB,CAAC,MAAK,MAAK,EAAE,aAAa,CAAC,CAAC,OAAO,QAAQ;EACzF,uBAAuB;EACvB,MAAM;CACR,CAAC;CAEH,OAAO;AACT;AAEA,SAAS,WAAW;CAClB,IAAI,eAAe;EACjB,cAAc;EACd,gBAAgB;CAClB;CAEA,IAAI,CAAC,WAAW,KAAK,CAAC,aAAa,CAAC,gBAAgB,GAAG;CAEvD,MAAM,aAAa,EAAE;CACrB,MAAM,MAAM;CAEZ,kBAAkB,YAAY;EAC5B,MAAM,gBAAgB,MAAM,kBAAkB;EAC9C,IAAI,eAAe,iBAAiB;EACpC,IAAI,CAAC,WAAW,KAAK,cAAc,OAAO,CAAC,gBAAgB,GAAG;EAC9D,gBAAgB,cAAc,GAAG;CACnC,GAAG;EACD,gBAAgB;EAChB,UAAU,UAAU;GAClB,aAAa,kBAAkB,KAAK;EACtC;CACF,CAAC;AACH;;;;;;;;;;;;;;AAeA,SAAgB,aAAa,KAA2B,eAA8C;CACpG,YAAY;CACZ,sBAAsB,kBAAkB,QAAQ,KAAA,IAAY,iBAAiB,KAAA;CAC7E,wCAAwC;CACxC,SAAS;CAKT,qBAAqB;EACnB,kBAAkB,YAAY;GAC5B,MAAM,UAAU,MAAM,IAAI,WAAW;GACrC,IAAI,cAAc,KAAK;GACvB,wCAAwC,QAAQ;GAChD,IAAI,yCAAyC,kBAAkB,MAC7D,SAAS;EAEb,GAAG;GACD,gBAAgB;GAChB,UAAU,UAAU;IAClB,aAAa,8BAA8B,KAAK;GAClD;EACF,CAAC;CACH,CAAC;CAKD,MAAM,YAAY;CAElB,aAAa;EACX,YAAY;EACZ,wCAAwC;EACxC,IAAI,kBAAkB,aAAa,aAAa,MAAM;GACpD,gBAAgB;GAChB,UAAU;EACZ;CACF;AACF;AAGA,IAAI,OAAO,WAAW,aAEpB,OAAgB,kBAAkB,OAAgB,kBAAkB;CAClE,SAAS;EACP,IAAI;GACF,aAAa,QAAQ,cAAc,MAAM;EAC3C,QAAQ,CAAC;EACT,SAAS;EACT,QAAQ,IAAI,gEAAgE;CAC9E;CACA,UAAU;EACR,IAAI;GACF,aAAa,QAAQ,cAAc,OAAO;EAC5C,QAAQ,CAAC;EACT,IAAI,eAAe;GACjB,cAAc;GACd,gBAAgB;EAClB;EACA,QAAQ,IAAI,2BAA2B;CACzC;CACA,QAAQ;EACN,IAAI;GACF,aAAa,WAAW,YAAY;EACtC,QAAQ,CAAC;EACT,IAAI,WAAW,GACb,SAAS;OACJ,IAAI,eAAe;GACxB,cAAc;GACd,gBAAgB;EAClB;EACA,QAAQ,IAAI,uGAAuG;CACrH;AACF"}
@@ -0,0 +1,5 @@
1
+ //#region src/in-page-ui/dev-environment.d.ts
2
+ declare function isLikelyDevelopmentEnvironment(): boolean;
3
+ //#endregion
4
+ export { isLikelyDevelopmentEnvironment };
5
+ //# sourceMappingURL=dev-environment.d.ts.map
@@ -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,18 @@
1
+ import { isLocalhost } from "@hexclave/shared/dist/utils/urls";
2
+ import { envVars } from "../generated/env.js";
3
+ //#region src/in-page-ui/dev-environment.ts
4
+ function isLikelyDevelopmentEnvironment() {
5
+ const nodeEnv = envVars.NODE_ENV;
6
+ if (nodeEnv !== void 0) return nodeEnv === "development";
7
+ if (typeof window === "undefined") return false;
8
+ try {
9
+ if (new URL(window.location.href).protocol === "file:") return true;
10
+ } catch {
11
+ return false;
12
+ }
13
+ return isLocalhost(window.location.href);
14
+ }
15
+ //#endregion
16
+ export { isLikelyDevelopmentEnvironment };
17
+
18
+ //# sourceMappingURL=dev-environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-environment.js","names":[],"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,UAAU,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,OAAO,YAAY,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"}
@@ -0,0 +1,392 @@
1
+ import { runAsynchronously } from "@hexclave/shared/dist/utils/promises";
2
+ import { getInPageUiBaseCSS } from "./base-styles.js";
3
+ import { h, setHtml } from "./dom.js";
4
+ import { HEXCLAVE_LOGO_SVG } from "./logo.js";
5
+ //#region src/in-page-ui/issue-card.ts
6
+ const COPY_ICON_SVG = "<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>";
7
+ function getIssueCardCSS(scopeSelector) {
8
+ return getInPageUiBaseCSS(scopeSelector) + `
9
+ ${scopeSelector} .hic-backdrop {
10
+ position: fixed;
11
+ inset: 0;
12
+ z-index: 2147483647;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ padding: 24px;
17
+ background: rgba(0, 0, 0, 0.46);
18
+ backdrop-filter: blur(6px);
19
+ overflow: auto;
20
+ }
21
+
22
+ ${scopeSelector} .hic-card {
23
+ --hic-status: var(--sdt-error);
24
+ width: min(720px, calc(100vw - 32px));
25
+ max-height: min(640px, calc(100dvh - 48px));
26
+ border: 1px solid color-mix(in srgb, var(--hic-status) 35%, var(--sdt-border));
27
+ border-radius: 18px;
28
+ background: var(--sdt-overlay-bg);
29
+ box-shadow: var(--sdt-shadow);
30
+ backdrop-filter: blur(18px);
31
+ display: flex;
32
+ overflow: hidden;
33
+ }
34
+
35
+ ${scopeSelector} .hic-card-warning {
36
+ --hic-status: var(--sdt-warning);
37
+ }
38
+
39
+ ${scopeSelector} .hic-card-inner {
40
+ padding: 18px;
41
+ width: 100%;
42
+ overflow: auto;
43
+ }
44
+
45
+ ${scopeSelector} .hic-header {
46
+ display: flex;
47
+ align-items: flex-start;
48
+ justify-content: space-between;
49
+ gap: 12px;
50
+ margin-bottom: 12px;
51
+ }
52
+
53
+ ${scopeSelector} .hic-title-row {
54
+ display: flex;
55
+ align-items: flex-start;
56
+ gap: 10px;
57
+ min-width: 0;
58
+ }
59
+
60
+ ${scopeSelector} .hic-logo {
61
+ flex-shrink: 0;
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ width: 34px;
66
+ height: 34px;
67
+ border-radius: 10px;
68
+ background: var(--hic-status);
69
+ color: white;
70
+ box-shadow: 0 10px 30px color-mix(in srgb, var(--hic-status) 32%, transparent);
71
+ }
72
+
73
+ ${scopeSelector} .hic-badge {
74
+ display: inline-flex;
75
+ flex-shrink: 0;
76
+ padding: 2px 6px;
77
+ border-radius: 999px;
78
+ background: var(--hic-status);
79
+ color: white;
80
+ font-size: 10px;
81
+ font-weight: 700;
82
+ letter-spacing: 0.06em;
83
+ text-transform: uppercase;
84
+ }
85
+
86
+ ${scopeSelector} .hic-title {
87
+ color: var(--sdt-text);
88
+ margin-top: 4px;
89
+ font-size: 18px;
90
+ font-weight: 700;
91
+ line-height: 1.25;
92
+ }
93
+
94
+ ${scopeSelector} .hic-actions {
95
+ display: flex;
96
+ gap: 4px;
97
+ }
98
+
99
+ ${scopeSelector} .hic-icon-btn {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ justify-content: center;
103
+ width: 28px;
104
+ height: 28px;
105
+ border: 1px solid var(--sdt-border);
106
+ border-radius: 8px;
107
+ background: var(--sdt-bg-elevated);
108
+ color: var(--sdt-text-secondary);
109
+ cursor: pointer;
110
+ font: inherit;
111
+ line-height: 1;
112
+ vertical-align: top;
113
+ }
114
+
115
+ ${scopeSelector} .hic-icon-btn svg {
116
+ display: block;
117
+ flex-shrink: 0;
118
+ }
119
+
120
+ ${scopeSelector} .hic-text-btn {
121
+ align-items: center;
122
+ gap: 6px;
123
+ min-height: 28px;
124
+ padding: 0 10px;
125
+ width: auto;
126
+ font-size: 12px;
127
+ line-height: 1;
128
+ }
129
+
130
+ ${scopeSelector} .hic-icon-btn:hover {
131
+ background: var(--sdt-bg-hover);
132
+ color: var(--sdt-text);
133
+ }
134
+
135
+ ${scopeSelector} .hic-body {
136
+ color: var(--sdt-text-secondary);
137
+ font-size: 14px;
138
+ line-height: 1.5;
139
+ }
140
+
141
+ ${scopeSelector} .hic-message-header {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: space-between;
145
+ gap: 10px;
146
+ margin-top: 14px;
147
+ margin-bottom: 8px;
148
+ }
149
+
150
+ ${scopeSelector} .hic-message-label {
151
+ color: var(--sdt-text);
152
+ font-size: 12px;
153
+ font-weight: 650;
154
+ }
155
+
156
+ ${scopeSelector} .hic-message {
157
+ padding: 12px;
158
+ max-height: min(260px, max(96px, 30dvh));
159
+ overflow: auto;
160
+ border: 1px solid var(--sdt-border-subtle);
161
+ border-radius: 10px;
162
+ background: var(--sdt-bg-subtle);
163
+ color: var(--sdt-text);
164
+ font-family: var(--sdt-font-mono);
165
+ font-size: 12px;
166
+ white-space: pre-wrap;
167
+ overflow-wrap: anywhere;
168
+ }
169
+
170
+ ${scopeSelector} .hic-fix-list {
171
+ margin: 8px 0 0;
172
+ padding-left: 18px;
173
+ color: var(--sdt-text);
174
+ font-size: 13px;
175
+ }
176
+
177
+ ${scopeSelector} .hic-fix-list li + li {
178
+ margin-top: 4px;
179
+ }
180
+
181
+ ${scopeSelector} .hic-footer {
182
+ margin-top: 10px;
183
+ color: var(--sdt-text-tertiary);
184
+ font-size: 12px;
185
+ }
186
+
187
+ ${scopeSelector} .hic-pill {
188
+ position: fixed;
189
+ right: 18px;
190
+ bottom: 18px;
191
+ z-index: 2147483647;
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 8px;
195
+ padding: 8px 12px 8px 8px;
196
+ --hic-status: var(--sdt-error);
197
+ border: 1px solid color-mix(in srgb, var(--hic-status) 35%, var(--sdt-border));
198
+ border-radius: 999px;
199
+ background: var(--sdt-overlay-bg);
200
+ box-shadow: var(--sdt-trigger-shadow);
201
+ color: var(--sdt-text);
202
+ cursor: pointer;
203
+ font: inherit;
204
+ backdrop-filter: blur(18px);
205
+ }
206
+
207
+ ${scopeSelector} .hic-pill-warning {
208
+ --hic-status: var(--sdt-warning);
209
+ }
210
+
211
+ ${scopeSelector} .hic-pill-logo {
212
+ display: flex;
213
+ align-items: center;
214
+ justify-content: center;
215
+ width: 26px;
216
+ height: 26px;
217
+ border-radius: 999px;
218
+ background: var(--hic-status);
219
+ color: white;
220
+ }
221
+
222
+ @media (max-height: 520px) {
223
+ ${scopeSelector} .hic-backdrop {
224
+ align-items: flex-start;
225
+ padding: 12px;
226
+ }
227
+
228
+ ${scopeSelector} .hic-card {
229
+ width: min(720px, calc(100vw - 24px));
230
+ max-height: calc(100dvh - 24px);
231
+ }
232
+
233
+ ${scopeSelector} .hic-card-inner {
234
+ padding: 12px;
235
+ }
236
+
237
+ ${scopeSelector} .hic-header {
238
+ margin-bottom: 8px;
239
+ }
240
+
241
+ ${scopeSelector} .hic-title {
242
+ font-size: 16px;
243
+ }
244
+
245
+ ${scopeSelector} .hic-body {
246
+ font-size: 13px;
247
+ }
248
+
249
+ ${scopeSelector} .hic-message {
250
+ max-height: max(80px, 24dvh);
251
+ }
252
+ }
253
+ `;
254
+ }
255
+ async function copyTextToClipboard(text) {
256
+ const clipboard = Reflect.get(navigator, "clipboard");
257
+ const writeText = clipboard != null && typeof clipboard === "object" ? Reflect.get(clipboard, "writeText") : null;
258
+ if (typeof writeText === "function") {
259
+ await writeText.call(clipboard, text);
260
+ return;
261
+ }
262
+ const textarea = h("textarea", {
263
+ style: {
264
+ position: "fixed",
265
+ left: "-9999px",
266
+ top: "0",
267
+ opacity: "0"
268
+ },
269
+ readonly: "true"
270
+ });
271
+ textarea.value = text;
272
+ document.body.appendChild(textarea);
273
+ textarea.select();
274
+ const copied = document.execCommand("copy");
275
+ textarea.remove();
276
+ if (!copied) throw new Error("Browser refused to copy the message.");
277
+ }
278
+ /**
279
+ * A button that copies `getText()` and briefly reports the outcome in its own label. Copying can fail for reasons
280
+ * outside our control (permissions, insecure contexts), so the failure is reported inline instead of being thrown into
281
+ * a click handler where nothing would show it.
282
+ */
283
+ function renderCopyButton(options) {
284
+ const idleHtml = options.variant === "text" ? `${COPY_ICON_SVG}Copy` : COPY_ICON_SVG;
285
+ const button = h("button", {
286
+ className: options.variant === "text" ? "hic-icon-btn hic-text-btn" : "hic-icon-btn",
287
+ type: "button",
288
+ title: options.title,
289
+ "aria-label": options.ariaLabel,
290
+ onClick: () => {
291
+ runAsynchronously(async () => {
292
+ await copyTextToClipboard(options.getText());
293
+ button.textContent = options.variant === "text" ? "Copied" : "✓";
294
+ setTimeout(() => setHtml(button, idleHtml), 1500);
295
+ }, {
296
+ noErrorLogging: true,
297
+ onError: (error) => {
298
+ options.onCopyError(error);
299
+ button.textContent = options.variant === "text" ? "Copy failed" : "!";
300
+ setTimeout(() => setHtml(button, idleHtml), 1500);
301
+ }
302
+ });
303
+ }
304
+ });
305
+ setHtml(button, idleHtml);
306
+ return button;
307
+ }
308
+ function renderIssueCard(options) {
309
+ const logoSpan = h("span", { className: "hic-logo" });
310
+ setHtml(logoSpan, HEXCLAVE_LOGO_SVG);
311
+ return h("div", { className: "hic-backdrop" }, h("div", {
312
+ className: options.kind === "error" ? "hic-card" : "hic-card hic-card-warning",
313
+ role: "alertdialog",
314
+ "aria-modal": "true",
315
+ "aria-label": options.ariaLabel,
316
+ tabindex: "-1"
317
+ }, h("div", { className: "hic-card-inner" }, h("div", { className: "hic-header" }, h("div", { className: "hic-title-row" }, logoSpan, h("div", null, h("span", { className: "hic-badge" }, options.badge), h("div", { className: "hic-title" }, options.title))), h("div", { className: "hic-actions" }, renderCopyButton({
318
+ variant: "icon",
319
+ title: "Copy AI prompt",
320
+ ariaLabel: `Copy AI prompt for ${options.ariaLabel}`,
321
+ getText: () => options.aiPrompt,
322
+ onCopyError: options.onCopyAiPromptError
323
+ }), h("button", {
324
+ className: "hic-icon-btn",
325
+ type: "button",
326
+ title: "Minimize",
327
+ "aria-label": `Minimize ${options.ariaLabel}`,
328
+ onClick: options.onMinimize
329
+ }, "–"))), h("div", { className: "hic-body" }, options.bodyText, h("div", { className: "hic-message-header" }, h("div", { className: "hic-message-label" }, options.messageLabel), renderCopyButton({
330
+ variant: "text",
331
+ title: `Copy ${options.messageLabel.toLowerCase()}`,
332
+ ariaLabel: `Copy ${options.ariaLabel} message`,
333
+ getText: () => options.message,
334
+ onCopyError: options.onCopyError
335
+ })), h("div", { className: "hic-message" }, options.message), options.howToFix == null || options.howToFix.length === 0 ? null : h("div", null, h("div", { className: "hic-message-header" }, h("div", { className: "hic-message-label" }, "How to fix")), h("ul", { className: "hic-fix-list" }, ...options.howToFix.map((step) => h("li", null, step)))), h("div", { className: "hic-footer" }, options.footerText)))));
336
+ }
337
+ const FOCUSABLE_SELECTOR = "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])";
338
+ /**
339
+ * Keeps keyboard focus inside a mounted card, which claims to be an `aria-modal` alertdialog and therefore has to behave
340
+ * like one: the flow behind the card is dead until the problem is fixed, so tabbing into it would only let a keyboard
341
+ * user wander through a page that cannot work while the card stays invisible to them.
342
+ *
343
+ * Call right after mounting the card, and release the trap when the card is minimized, replaced or removed. Releasing
344
+ * hands focus back to `previouslyFocused` unless `restoreFocus: false` is passed, which is what a caller that is about
345
+ * to rebind the trap to a freshly rendered card wants.
346
+ */
347
+ function trapFocusInIssueCard(cardRoot, options = {}) {
348
+ const previouslyFocused = options.previouslyFocused !== void 0 ? options.previouslyFocused : document.activeElement instanceof HTMLElement ? document.activeElement : null;
349
+ const card = cardRoot.querySelector(".hic-card");
350
+ if (!(card instanceof HTMLElement)) return {
351
+ previouslyFocused,
352
+ release: () => {}
353
+ };
354
+ const onKeyDown = (event) => {
355
+ if (event.key !== "Tab") return;
356
+ const focusable = [...card.querySelectorAll(FOCUSABLE_SELECTOR)].filter((element) => element instanceof HTMLElement);
357
+ const first = focusable[0] ?? card;
358
+ const last = focusable[focusable.length - 1] ?? card;
359
+ const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;
360
+ let target = null;
361
+ if (active == null || !card.contains(active)) target = event.shiftKey ? last : first;
362
+ else if (active === last && !event.shiftKey) target = first;
363
+ else if (active === first && event.shiftKey) target = last;
364
+ if (target == null) return;
365
+ event.preventDefault();
366
+ target.focus();
367
+ };
368
+ document.addEventListener("keydown", onKeyDown, true);
369
+ if (options.moveFocusIntoCard !== false) card.focus();
370
+ return {
371
+ previouslyFocused,
372
+ release: (releaseOptions) => {
373
+ document.removeEventListener("keydown", onKeyDown, true);
374
+ if (releaseOptions?.restoreFocus === false) return;
375
+ if (previouslyFocused != null && previouslyFocused.isConnected) previouslyFocused.focus();
376
+ }
377
+ };
378
+ }
379
+ function renderIssuePill(options) {
380
+ const logoSpan = h("span", { className: "hic-pill-logo" });
381
+ setHtml(logoSpan, HEXCLAVE_LOGO_SVG);
382
+ return h("button", {
383
+ className: options.kind === "error" ? "hic-pill" : "hic-pill hic-pill-warning",
384
+ type: "button",
385
+ "aria-label": options.ariaLabel,
386
+ onClick: options.onClick
387
+ }, logoSpan, h("span", null, options.label));
388
+ }
389
+ //#endregion
390
+ export { copyTextToClipboard, getIssueCardCSS, renderIssueCard, renderIssuePill, trapFocusInIssueCard };
391
+
392
+ //# sourceMappingURL=issue-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-card.js","names":[],"sources":["../../../src/in-page-ui/issue-card.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 renderer for Hexclave's in-page issue cards: the modal-style card (plus its minimized pill) that the SDK uses\n// to tell developers about problems it cannot recover from, like a broken pushed config or an untrusted auth domain.\n// Every issue surface renders the same shape, so the markup, styles and clipboard handling live here and each feature\n// only supplies its copy and callbacks.\n\nimport { runAsynchronously } from \"@hexclave/shared/dist/utils/promises\";\nimport { getInPageUiBaseCSS } from \"./base-styles\";\nimport { h, setHtml } from \"./dom\";\nimport { HEXCLAVE_LOGO_SVG } from \"./logo\";\n\nexport type IssueCardKind = \"error\" | \"warning\";\n\nconst COPY_ICON_SVG = '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.25\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>';\n\nexport function getIssueCardCSS(scopeSelector: string): string {\n return getInPageUiBaseCSS(scopeSelector) + `\n ${scopeSelector} .hic-backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(0, 0, 0, 0.46);\n backdrop-filter: blur(6px);\n overflow: auto;\n }\n\n ${scopeSelector} .hic-card {\n --hic-status: var(--sdt-error);\n width: min(720px, calc(100vw - 32px));\n max-height: min(640px, calc(100dvh - 48px));\n border: 1px solid color-mix(in srgb, var(--hic-status) 35%, var(--sdt-border));\n border-radius: 18px;\n background: var(--sdt-overlay-bg);\n box-shadow: var(--sdt-shadow);\n backdrop-filter: blur(18px);\n display: flex;\n overflow: hidden;\n }\n\n ${scopeSelector} .hic-card-warning {\n --hic-status: var(--sdt-warning);\n }\n\n ${scopeSelector} .hic-card-inner {\n padding: 18px;\n width: 100%;\n overflow: auto;\n }\n\n ${scopeSelector} .hic-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n ${scopeSelector} .hic-title-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n }\n\n ${scopeSelector} .hic-logo {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n border-radius: 10px;\n background: var(--hic-status);\n color: white;\n box-shadow: 0 10px 30px color-mix(in srgb, var(--hic-status) 32%, transparent);\n }\n\n ${scopeSelector} .hic-badge {\n display: inline-flex;\n flex-shrink: 0;\n padding: 2px 6px;\n border-radius: 999px;\n background: var(--hic-status);\n color: white;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n }\n\n ${scopeSelector} .hic-title {\n color: var(--sdt-text);\n margin-top: 4px;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n ${scopeSelector} .hic-actions {\n display: flex;\n gap: 4px;\n }\n\n ${scopeSelector} .hic-icon-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 1px solid var(--sdt-border);\n border-radius: 8px;\n background: var(--sdt-bg-elevated);\n color: var(--sdt-text-secondary);\n cursor: pointer;\n font: inherit;\n line-height: 1;\n vertical-align: top;\n }\n\n ${scopeSelector} .hic-icon-btn svg {\n display: block;\n flex-shrink: 0;\n }\n\n ${scopeSelector} .hic-text-btn {\n align-items: center;\n gap: 6px;\n min-height: 28px;\n padding: 0 10px;\n width: auto;\n font-size: 12px;\n line-height: 1;\n }\n\n ${scopeSelector} .hic-icon-btn:hover {\n background: var(--sdt-bg-hover);\n color: var(--sdt-text);\n }\n\n ${scopeSelector} .hic-body {\n color: var(--sdt-text-secondary);\n font-size: 14px;\n line-height: 1.5;\n }\n\n ${scopeSelector} .hic-message-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-top: 14px;\n margin-bottom: 8px;\n }\n\n ${scopeSelector} .hic-message-label {\n color: var(--sdt-text);\n font-size: 12px;\n font-weight: 650;\n }\n\n ${scopeSelector} .hic-message {\n padding: 12px;\n max-height: min(260px, max(96px, 30dvh));\n overflow: auto;\n border: 1px solid var(--sdt-border-subtle);\n border-radius: 10px;\n background: var(--sdt-bg-subtle);\n color: var(--sdt-text);\n font-family: var(--sdt-font-mono);\n font-size: 12px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n }\n\n ${scopeSelector} .hic-fix-list {\n margin: 8px 0 0;\n padding-left: 18px;\n color: var(--sdt-text);\n font-size: 13px;\n }\n\n ${scopeSelector} .hic-fix-list li + li {\n margin-top: 4px;\n }\n\n ${scopeSelector} .hic-footer {\n margin-top: 10px;\n color: var(--sdt-text-tertiary);\n font-size: 12px;\n }\n\n ${scopeSelector} .hic-pill {\n position: fixed;\n right: 18px;\n bottom: 18px;\n z-index: 2147483647;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px 8px 8px;\n --hic-status: var(--sdt-error);\n border: 1px solid color-mix(in srgb, var(--hic-status) 35%, var(--sdt-border));\n border-radius: 999px;\n background: var(--sdt-overlay-bg);\n box-shadow: var(--sdt-trigger-shadow);\n color: var(--sdt-text);\n cursor: pointer;\n font: inherit;\n backdrop-filter: blur(18px);\n }\n\n ${scopeSelector} .hic-pill-warning {\n --hic-status: var(--sdt-warning);\n }\n\n ${scopeSelector} .hic-pill-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border-radius: 999px;\n background: var(--hic-status);\n color: white;\n }\n\n @media (max-height: 520px) {\n ${scopeSelector} .hic-backdrop {\n align-items: flex-start;\n padding: 12px;\n }\n\n ${scopeSelector} .hic-card {\n width: min(720px, calc(100vw - 24px));\n max-height: calc(100dvh - 24px);\n }\n\n ${scopeSelector} .hic-card-inner {\n padding: 12px;\n }\n\n ${scopeSelector} .hic-header {\n margin-bottom: 8px;\n }\n\n ${scopeSelector} .hic-title {\n font-size: 16px;\n }\n\n ${scopeSelector} .hic-body {\n font-size: 13px;\n }\n\n ${scopeSelector} .hic-message {\n max-height: max(80px, 24dvh);\n }\n }\n`;\n}\n\nexport async function copyTextToClipboard(text: string): Promise<void> {\n const clipboard: unknown = Reflect.get(navigator, \"clipboard\");\n const writeText = clipboard != null && typeof clipboard === \"object\"\n ? Reflect.get(clipboard, \"writeText\")\n : null;\n if (typeof writeText === \"function\") {\n await writeText.call(clipboard, text);\n return;\n }\n\n const textarea = h(\"textarea\", {\n style: {\n position: \"fixed\",\n left: \"-9999px\",\n top: \"0\",\n opacity: \"0\",\n },\n readonly: \"true\",\n });\n textarea.value = text;\n document.body.appendChild(textarea);\n textarea.select();\n const copied = document.execCommand(\"copy\");\n textarea.remove();\n if (!copied) {\n throw new Error(\"Browser refused to copy the message.\");\n }\n}\n\n/**\n * A button that copies `getText()` and briefly reports the outcome in its own label. Copying can fail for reasons\n * outside our control (permissions, insecure contexts), so the failure is reported inline instead of being thrown into\n * a click handler where nothing would show it.\n */\nfunction renderCopyButton(options: {\n variant: \"icon\" | \"text\",\n title: string,\n ariaLabel: string,\n getText: () => string,\n onCopyError: (error: unknown) => void,\n}): HTMLElement {\n const idleHtml = options.variant === \"text\" ? `${COPY_ICON_SVG}Copy` : COPY_ICON_SVG;\n const button = h(\"button\", {\n className: options.variant === \"text\" ? \"hic-icon-btn hic-text-btn\" : \"hic-icon-btn\",\n type: \"button\",\n title: options.title,\n \"aria-label\": options.ariaLabel,\n onClick: () => {\n runAsynchronously(async () => {\n await copyTextToClipboard(options.getText());\n button.textContent = options.variant === \"text\" ? \"Copied\" : \"✓\";\n setTimeout(() => setHtml(button, idleHtml), 1500);\n }, {\n noErrorLogging: true,\n onError: (error) => {\n options.onCopyError(error);\n button.textContent = options.variant === \"text\" ? \"Copy failed\" : \"!\";\n setTimeout(() => setHtml(button, idleHtml), 1500);\n },\n });\n },\n });\n setHtml(button, idleHtml);\n return button;\n}\n\nexport type IssueCardOptions = {\n kind: IssueCardKind,\n /** Short uppercase label in the card's badge, eg. \"Config error\". */\n badge: string,\n title: string,\n /** One or two sentences on what this means for the running app. */\n bodyText: string,\n messageLabel: string,\n message: string,\n /** Concrete steps the developer should take; rendered as a list above the footer. */\n howToFix?: readonly string[],\n footerText: string,\n ariaLabel: string,\n /** Prompt for the \"copy AI prompt\" button, ie. the message plus enough context for a coding agent to fix it. */\n aiPrompt: string,\n onCopyError: (error: unknown) => void,\n onCopyAiPromptError: (error: unknown) => void,\n onMinimize: () => void,\n};\n\nexport function renderIssueCard(options: IssueCardOptions): HTMLElement {\n const logoSpan = h(\"span\", { className: \"hic-logo\" });\n setHtml(logoSpan, HEXCLAVE_LOGO_SVG);\n\n return h(\"div\", { className: \"hic-backdrop\" },\n h(\"div\", { className: options.kind === \"error\" ? \"hic-card\" : \"hic-card hic-card-warning\", role: \"alertdialog\", \"aria-modal\": \"true\", \"aria-label\": options.ariaLabel, tabindex: \"-1\" },\n h(\"div\", { className: \"hic-card-inner\" },\n h(\"div\", { className: \"hic-header\" },\n h(\"div\", { className: \"hic-title-row\" },\n logoSpan,\n h(\"div\", null,\n h(\"span\", { className: \"hic-badge\" }, options.badge),\n h(\"div\", { className: \"hic-title\" }, options.title),\n ),\n ),\n h(\"div\", { className: \"hic-actions\" },\n renderCopyButton({\n variant: \"icon\",\n title: \"Copy AI prompt\",\n ariaLabel: `Copy AI prompt for ${options.ariaLabel}`,\n getText: () => options.aiPrompt,\n onCopyError: options.onCopyAiPromptError,\n }),\n h(\"button\", {\n className: \"hic-icon-btn\",\n type: \"button\",\n title: \"Minimize\",\n \"aria-label\": `Minimize ${options.ariaLabel}`,\n onClick: options.onMinimize,\n }, \"–\"),\n ),\n ),\n h(\"div\", { className: \"hic-body\" },\n options.bodyText,\n h(\"div\", { className: \"hic-message-header\" },\n h(\"div\", { className: \"hic-message-label\" }, options.messageLabel),\n renderCopyButton({\n variant: \"text\",\n title: `Copy ${options.messageLabel.toLowerCase()}`,\n ariaLabel: `Copy ${options.ariaLabel} message`,\n getText: () => options.message,\n onCopyError: options.onCopyError,\n }),\n ),\n h(\"div\", { className: \"hic-message\" }, options.message),\n options.howToFix == null || options.howToFix.length === 0 ? null : h(\"div\", null,\n h(\"div\", { className: \"hic-message-header\" },\n h(\"div\", { className: \"hic-message-label\" }, \"How to fix\"),\n ),\n h(\"ul\",\n { className: \"hic-fix-list\" },\n ...options.howToFix.map((step) => h(\"li\", null, step)),\n ),\n ),\n h(\"div\", { className: \"hic-footer\" }, options.footerText),\n ),\n ),\n ),\n );\n}\n\nconst FOCUSABLE_SELECTOR = \"a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])\";\n\nexport type IssueCardFocusTrap = {\n /**\n * Whatever had focus before the card first appeared. Callers that rebind the trap to a re-rendered card pass it back\n * in, so focus still returns to where the developer left it once the card is gone for good.\n */\n previouslyFocused: HTMLElement | null,\n release: (releaseOptions?: { restoreFocus?: boolean }) => void,\n};\n\n/**\n * Keeps keyboard focus inside a mounted card, which claims to be an `aria-modal` alertdialog and therefore has to behave\n * like one: the flow behind the card is dead until the problem is fixed, so tabbing into it would only let a keyboard\n * user wander through a page that cannot work while the card stays invisible to them.\n *\n * Call right after mounting the card, and release the trap when the card is minimized, replaced or removed. Releasing\n * hands focus back to `previouslyFocused` unless `restoreFocus: false` is passed, which is what a caller that is about\n * to rebind the trap to a freshly rendered card wants.\n */\nexport function trapFocusInIssueCard(cardRoot: HTMLElement, options: {\n moveFocusIntoCard?: boolean,\n previouslyFocused?: HTMLElement | null,\n} = {}): IssueCardFocusTrap {\n const previouslyFocused = options.previouslyFocused !== undefined\n ? options.previouslyFocused\n : document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const card = cardRoot.querySelector(\".hic-card\");\n if (!(card instanceof HTMLElement)) return { previouslyFocused, release: () => {} };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Tab\") return;\n const focusable = [...card.querySelectorAll(FOCUSABLE_SELECTOR)].filter((element): element is HTMLElement => element instanceof HTMLElement);\n const first = focusable[0] ?? card;\n const last = focusable[focusable.length - 1] ?? card;\n const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n\n let target: HTMLElement | null = null;\n if (active == null || !card.contains(active)) {\n // Focus is outside the card (the page moved it, or it never got in): pull it back to the card's near end.\n target = event.shiftKey ? last : first;\n } else if (active === last && !event.shiftKey) {\n target = first;\n } else if (active === first && event.shiftKey) {\n target = last;\n }\n if (target == null) return;\n event.preventDefault();\n target.focus();\n };\n\n document.addEventListener(\"keydown\", onKeyDown, true);\n if (options.moveFocusIntoCard !== false) {\n card.focus();\n }\n\n return {\n previouslyFocused,\n release: (releaseOptions) => {\n document.removeEventListener(\"keydown\", onKeyDown, true);\n if (releaseOptions?.restoreFocus === false) return;\n if (previouslyFocused != null && previouslyFocused.isConnected) {\n previouslyFocused.focus();\n }\n },\n };\n}\n\nexport function renderIssuePill(options: {\n kind: IssueCardKind,\n label: string,\n ariaLabel: string,\n onClick: () => void,\n}): HTMLElement {\n const logoSpan = h(\"span\", { className: \"hic-pill-logo\" });\n setHtml(logoSpan, HEXCLAVE_LOGO_SVG);\n return h(\"button\", {\n className: options.kind === \"error\" ? \"hic-pill\" : \"hic-pill hic-pill-warning\",\n type: \"button\",\n \"aria-label\": options.ariaLabel,\n onClick: options.onClick,\n },\n logoSpan,\n h(\"span\", null, options.label),\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };