@leed-ai/cli 0.0.0-stage → 6.19.0

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 (263) hide show
  1. package/LICENSE.md +57 -0
  2. package/README.md +125 -2
  3. package/dist/LICENSE.md +57 -0
  4. package/dist/acorn-DAgDT1om.js +5087 -0
  5. package/dist/angular-l0_4PK8N.js +3598 -0
  6. package/dist/authShared-Dray38Ls.js +1161 -0
  7. package/dist/babel-CJeRQd5u.js +10038 -0
  8. package/dist/buildResults-tiq1nugP.js +21180 -0
  9. package/dist/chunk-1VJ9lAw7.js +42 -0
  10. package/dist/cliAuth-38JjD6hw.js +15 -0
  11. package/dist/env-B0bHiXJJ.js +29 -0
  12. package/dist/errors-CqKamGCu.js +481 -0
  13. package/dist/estree-E8WG8UHj.js +6930 -0
  14. package/dist/flow-6xaRIbPQ.js +52255 -0
  15. package/dist/glimmer-aJPjsfbT.js +7272 -0
  16. package/dist/graphql-mcgtPEiZ.js +1901 -0
  17. package/dist/html--eeea3Kl.js +6553 -0
  18. package/dist/leed.eleventy.mjs +6525 -0
  19. package/dist/leed.mjs +88952 -0
  20. package/dist/leed.sources.json +798 -0
  21. package/dist/leedLogger-Zkada5aO.js +78 -0
  22. package/dist/markdown-D73jNKwx.js +6836 -0
  23. package/dist/meriyah-CMp1nDDW.js +8932 -0
  24. package/dist/package.json +101 -0
  25. package/dist/postcss-h4fBr2Fn.js +6760 -0
  26. package/dist/prettier-CwFSKxfN.js +16821 -0
  27. package/dist/static/customer-site-worker/package.json +9 -0
  28. package/dist/static/customer-site-worker/src/assetsHydration.ts +55 -0
  29. package/dist/static/customer-site-worker/src/constants.ts +20 -0
  30. package/dist/static/customer-site-worker/src/cors.ts +120 -0
  31. package/dist/static/customer-site-worker/src/index.ts +242 -0
  32. package/dist/static/customer-site-worker/src/mcp-proxy.ts +98 -0
  33. package/dist/static/customer-site-worker/src/proxy.ts +92 -0
  34. package/dist/static/customer-site-worker/src/proxyHeaders.ts +47 -0
  35. package/dist/static/customer-site-worker/src/tier.ts +40 -0
  36. package/dist/static/customer-site-worker/src/types.ts +82 -0
  37. package/dist/static/customer-site-worker/test/functions-mock.worker.js +50 -0
  38. package/dist/static/customer-site-worker/tsconfig.json +19 -0
  39. package/dist/static/customer-site-worker/vitest.workers.config.ts +61 -0
  40. package/dist/static/install/husky/colors.mjs +5 -0
  41. package/dist/static/install/husky/hooks/commit-msg +1 -0
  42. package/dist/static/install/husky/hooks/pre-commit +1 -0
  43. package/dist/static/install/husky/hooks/pre-push +1 -0
  44. package/dist/static/install/husky/valid-command.mjs +29 -0
  45. package/dist/static/install/husky/valid-commit-msg.mjs +20 -0
  46. package/dist/static/install/package.json +10 -0
  47. package/dist/static/install/packages.txt +4 -0
  48. package/dist/static/install/tasks.json +111 -0
  49. package/dist/static/javascript/detectIncognito.js +195 -0
  50. package/dist/static/javascript/documentation.js +2781 -0
  51. package/dist/static/javascript/fp/fp.esm.js +2896 -0
  52. package/dist/static/javascript/fp/fp.js +3067 -0
  53. package/dist/static/javascript/live-search.js +986 -0
  54. package/dist/static/javascript/lunr-search.js +843 -0
  55. package/dist/static/javascript/timeme.js +451 -0
  56. package/dist/static/javascript/tracker/webmcp.js +67 -0
  57. package/dist/static/javascript/tracker/whisper.js +1 -0
  58. package/dist/static/javascript/utilities.js +819 -0
  59. package/dist/static/javascript/versions.json +74 -0
  60. package/dist/static/javascript/zoomable.js +488 -0
  61. package/dist/static/site/_data/eleventyComputed.js +228 -0
  62. package/dist/static/site/_data/leed-form-data.json +253 -0
  63. package/dist/static/site/_includes/leed/api/bits/array-type.hbs +24 -0
  64. package/dist/static/site/_includes/leed/api/bits/badges.hbs +9 -0
  65. package/dist/static/site/_includes/leed/api/bits/description.hbs +9 -0
  66. package/dist/static/site/_includes/leed/api/bits/examples.hbs +42 -0
  67. package/dist/static/site/_includes/leed/api/bits/scopes.hbs +28 -0
  68. package/dist/static/site/_includes/leed/api/object.hbs +110 -0
  69. package/dist/static/site/_includes/leed/api/parameters.hbs +11 -0
  70. package/dist/static/site/_includes/leed/api/property.hbs +153 -0
  71. package/dist/static/site/_includes/leed/api/request-body.hbs +51 -0
  72. package/dist/static/site/_includes/leed/api/responses.hbs +89 -0
  73. package/dist/static/site/_includes/leed/api/security-constraints.hbs +59 -0
  74. package/dist/static/site/_includes/leed/api/security.hbs +75 -0
  75. package/dist/static/site/_includes/leed/components/pagination.hbs +45 -0
  76. package/dist/static/site/_includes/leed/components/scroll-status-indicator-horizontal.hbs +22 -0
  77. package/dist/static/site/_includes/leed/docs/alpha/api.hbs +6 -0
  78. package/dist/static/site/_includes/leed/docs/alpha/base.hbs +26 -0
  79. package/dist/static/site/_includes/leed/docs/alpha/documentation.hbs +7 -0
  80. package/dist/static/site/_includes/leed/docs/api-article.hbs +75 -0
  81. package/dist/static/site/_includes/leed/docs/bravo/api.hbs +5 -0
  82. package/dist/static/site/_includes/leed/docs/bravo/base.hbs +31 -0
  83. package/dist/static/site/_includes/leed/docs/bravo/documentation.hbs +7 -0
  84. package/dist/static/site/_includes/leed/docs/charlie/api.hbs +6 -0
  85. package/dist/static/site/_includes/leed/docs/charlie/base.hbs +27 -0
  86. package/dist/static/site/_includes/leed/docs/charlie/documentation.hbs +10 -0
  87. package/dist/static/site/_includes/leed/docs/doc-article.hbs +40 -0
  88. package/dist/static/site/_includes/leed/docs/docs-footer.hbs +35 -0
  89. package/dist/static/site/_includes/leed/docs/docs-header.hbs +59 -0
  90. package/dist/static/site/_includes/leed/docs/document-search-modal.hbs +36 -0
  91. package/dist/static/site/_includes/leed/docs/document-search.hbs +23 -0
  92. package/dist/static/site/_includes/leed/docs/footer.hbs +12 -0
  93. package/dist/static/site/_includes/leed/docs/header/brand.hbs +19 -0
  94. package/dist/static/site/_includes/leed/docs/header/chrome.hbs +33 -0
  95. package/dist/static/site/_includes/leed/docs/header/compact.hbs +19 -0
  96. package/dist/static/site/_includes/leed/docs/header/cta.hbs +15 -0
  97. package/dist/static/site/_includes/leed/docs/header/nav.hbs +18 -0
  98. package/dist/static/site/_includes/leed/docs/header/top-search.hbs +15 -0
  99. package/dist/static/site/_includes/leed/docs/mini-bar.hbs +53 -0
  100. package/dist/static/site/_includes/leed/docs/pagination.hbs +19 -0
  101. package/dist/static/site/_includes/leed/docs/shell.hbs +56 -0
  102. package/dist/static/site/_includes/leed/docs/sidebar.hbs +52 -0
  103. package/dist/static/site/_includes/leed/docs/social-icons.hbs +81 -0
  104. package/dist/static/site/_includes/leed/docs/style.hbs +17 -0
  105. package/dist/static/site/_includes/leed/docs/toc.hbs +7 -0
  106. package/dist/static/site/_includes/leed/form.hbs +266 -0
  107. package/dist/static/site/_includes/leed/head.hbs +67 -0
  108. package/dist/static/site/_includes/leed/menu/builder.hbs +35 -0
  109. package/dist/static/site/_includes/leed/menu/item.hbs +67 -0
  110. package/dist/static/site/_includes/leed/menu/link.hbs +59 -0
  111. package/dist/static/site/_includes/leed/metadata/ogCard.hbs +40 -0
  112. package/dist/static/site/_includes/leed/metadata/siteMetadata.hbs +24 -0
  113. package/dist/static/site/_includes/leed/metadata/twitterCard.hbs +34 -0
  114. package/dist/static/site/_includes/leed/popup-video.hbs +21 -0
  115. package/dist/static/site/_includes/leed/stub-template.hbs +17 -0
  116. package/dist/static/site/_includes/leed/unsubscribe-form.hbs +30 -0
  117. package/dist/static/site/_layouts/leed-documentation.hbs +12 -0
  118. package/dist/static/site/leed-feed-atom.hbs +42 -0
  119. package/dist/static/site/leed-feed-json.hbs +56 -0
  120. package/dist/static/site/leed-feed-rss.hbs +39 -0
  121. package/dist/static/site/leed-headers.hbs +38 -0
  122. package/dist/static/site/leed-redirects.hbs +10 -0
  123. package/dist/static/site/leed-sitemap-pageType.hbs +28 -0
  124. package/dist/static/site/leed-sitemap.hbs +19 -0
  125. package/dist/static/site/leed-unsubscribe.hbs +44 -0
  126. package/dist/static/site/leed-unsubscribed.hbs +40 -0
  127. package/dist/static/tailwind/components/alerts.css +132 -0
  128. package/dist/static/tailwind/components/api-methods.css +39 -0
  129. package/dist/static/tailwind/components/breadcrumbs.css +31 -0
  130. package/dist/static/tailwind/components/code.css +88 -0
  131. package/dist/static/tailwind/components/collapsible.css +38 -0
  132. package/dist/static/tailwind/components/document-search.css +222 -0
  133. package/dist/static/tailwind/components/form.css +185 -0
  134. package/dist/static/tailwind/components/kbd.css +7 -0
  135. package/dist/static/tailwind/components/pagination.css +81 -0
  136. package/dist/static/tailwind/components/scroll-status-indicator.css +5 -0
  137. package/dist/static/tailwind/components/tab-groups.css +117 -0
  138. package/dist/static/tailwind/components/tables.css +0 -0
  139. package/dist/static/tailwind/components/toc.css +60 -0
  140. package/dist/static/tailwind/components.css +248 -0
  141. package/dist/static/tailwind/defaults.css +260 -0
  142. package/dist/static/tailwind/docs/api.css +701 -0
  143. package/dist/static/tailwind/docs/components/blockquote.css +5 -0
  144. package/dist/static/tailwind/docs/components/button.css +11 -0
  145. package/dist/static/tailwind/docs/components/docs-pagination.css +71 -0
  146. package/dist/static/tailwind/docs/components/mobile-bar.css +83 -0
  147. package/dist/static/tailwind/docs/components/navigation.css +279 -0
  148. package/dist/static/tailwind/docs/components/table.css +54 -0
  149. package/dist/static/tailwind/docs/components.css +6 -0
  150. package/dist/static/tailwind/docs/docs.css +427 -0
  151. package/dist/static/tailwind/docs/layouts/alpha.css +108 -0
  152. package/dist/static/tailwind/docs/layouts/bravo.css +218 -0
  153. package/dist/static/tailwind/docs/layouts/charlie.css +105 -0
  154. package/dist/static/tailwind/docs/layouts.css +3 -0
  155. package/dist/static/tailwind/docs/themes/amber.css +113 -0
  156. package/dist/static/tailwind/docs/themes/blue.css +94 -0
  157. package/dist/static/tailwind/docs/themes/cyan.css +111 -0
  158. package/dist/static/tailwind/docs/themes/emerald.css +111 -0
  159. package/dist/static/tailwind/docs/themes/fuchsia.css +111 -0
  160. package/dist/static/tailwind/docs/themes/green.css +95 -0
  161. package/dist/static/tailwind/docs/themes/indigo.css +111 -0
  162. package/dist/static/tailwind/docs/themes/lime.css +111 -0
  163. package/dist/static/tailwind/docs/themes/orange.css +111 -0
  164. package/dist/static/tailwind/docs/themes/pink.css +111 -0
  165. package/dist/static/tailwind/docs/themes/purple.css +111 -0
  166. package/dist/static/tailwind/docs/themes/red.css +111 -0
  167. package/dist/static/tailwind/docs/themes/rose.css +111 -0
  168. package/dist/static/tailwind/docs/themes/sky.css +111 -0
  169. package/dist/static/tailwind/docs/themes/teal.css +111 -0
  170. package/dist/static/tailwind/docs/themes/violet.css +111 -0
  171. package/dist/static/tailwind/docs/themes/yellow.css +111 -0
  172. package/dist/static/tailwind/docs/themes.css +84 -0
  173. package/dist/static/tailwind/font-awesome/free-7.3.1/brands.css +2455 -0
  174. package/dist/static/tailwind/font-awesome/free-7.3.1/fontawesome.css +8997 -0
  175. package/dist/static/tailwind/font-awesome/free-7.3.1/fonts.css +45 -0
  176. package/dist/static/tailwind/font-awesome/free-7.3.1/icons.json +2608 -0
  177. package/dist/static/tailwind/font-awesome/free-7.3.1.css +3 -0
  178. package/dist/static/tailwind/font-awesome/pro-7.0.0/brands.css +2215 -0
  179. package/dist/static/tailwind/font-awesome/pro-7.0.0/fontawesome.css +19281 -0
  180. package/dist/static/tailwind/font-awesome/pro-7.0.0/fonts.css +445 -0
  181. package/dist/static/tailwind/font-awesome/pro-7.0.0.css +3 -0
  182. package/dist/static/tailwind/font-awesome/pro-7.3.1/brands.css +2455 -0
  183. package/dist/static/tailwind/font-awesome/pro-7.3.1/fontawesome.css +20365 -0
  184. package/dist/static/tailwind/font-awesome/pro-7.3.1/fonts.css +589 -0
  185. package/dist/static/tailwind/font-awesome/pro-7.3.1.css +3 -0
  186. package/dist/static/tailwind/fonts/all.css +6 -0
  187. package/dist/static/tailwind/fonts/config.jsonc +31 -0
  188. package/dist/static/tailwind/fonts/geist-mono.css +142 -0
  189. package/dist/static/tailwind/fonts/geist.css +142 -0
  190. package/dist/static/tailwind/fonts/inter.css +215 -0
  191. package/dist/static/tailwind/fonts/jetbrains-mono.css +126 -0
  192. package/dist/static/tailwind/fonts/noto-sans.css +134 -0
  193. package/dist/static/tailwind/fonts/open-sans.css +89 -0
  194. package/dist/static/tailwind/highlighters.css +14 -0
  195. package/dist/static/tailwind/hljs/README.md +53 -0
  196. package/dist/static/tailwind/hljs/a11y.css +96 -0
  197. package/dist/static/tailwind/hljs/atom-fruit.css +90 -0
  198. package/dist/static/tailwind/hljs/atom-one.css +164 -0
  199. package/dist/static/tailwind/hljs/default.css +164 -0
  200. package/dist/static/tailwind/hljs/github.css +101 -0
  201. package/dist/static/tailwind/hljs/google-code.css +112 -0
  202. package/dist/static/tailwind/hljs/grayscale.css +115 -0
  203. package/dist/static/tailwind/hljs/gruvbox-hard.css +115 -0
  204. package/dist/static/tailwind/hljs/gruvbox-medium.css +115 -0
  205. package/dist/static/tailwind/hljs/gruvbox-soft.css +115 -0
  206. package/dist/static/tailwind/hljs/papercolor.css +120 -0
  207. package/dist/static/tailwind/hljs/qt-creator.css +91 -0
  208. package/dist/static/tailwind/hljs/summerfruit.css +115 -0
  209. package/dist/static/tailwind/hljs/tomorrow.css +115 -0
  210. package/dist/static/tailwind/leed.css +170 -0
  211. package/dist/static/tailwind/site-tokens.reference.css +105 -0
  212. package/dist/static/tailwind/utils/icons.css +102 -0
  213. package/dist/static/tailwind/utils/utilities.css +105 -0
  214. package/dist/static/templates/pages/PAGE.hbs +27 -0
  215. package/dist/static/templates/pages/PAGE_LAYOUT.hbs +19 -0
  216. package/dist/static/templates/pages/PAGE_TYPE_INDEX.hbs +89 -0
  217. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_ITEM.hbs +52 -0
  218. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_LIST.hbs +39 -0
  219. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_PAGINATION.hbs +11 -0
  220. package/dist/static/templates/raw-content/.ci/build.sh +58 -0
  221. package/dist/static/templates/raw-content/README.md +179 -0
  222. package/dist/static/templates/raw-content/_gitignore +50 -0
  223. package/dist/static/templates/raw-content/src/404.hbs +21 -0
  224. package/dist/static/templates/raw-content/src/_data/autolink.json +1 -0
  225. package/dist/static/templates/raw-content/src/_data/ctaList.json +1 -0
  226. package/dist/static/templates/raw-content/src/_data/leedForms.json +1 -0
  227. package/dist/static/templates/raw-content/src/_data/menu.json +1 -0
  228. package/dist/static/templates/raw-content/src/_includes/footer.hbs +18 -0
  229. package/dist/static/templates/raw-content/src/_includes/header-includes.hbs +25 -0
  230. package/dist/static/templates/raw-content/src/_includes/header.hbs +5 -0
  231. package/dist/static/templates/raw-content/src/_includes/site-template.hbs +23 -0
  232. package/dist/static/templates/raw-content/src/_includes/unsubscribe-DISABLED.hbs +17 -0
  233. package/dist/static/templates/raw-content/src/_includes/unsubscribed-DISABLED.hbs +13 -0
  234. package/dist/static/templates/raw-content/src/_layouts/empty.hbs +2 -0
  235. package/dist/static/templates/raw-content/src/index.hbs +21 -0
  236. package/dist/static/templates/raw-content/src/robots.hbs +9 -0
  237. package/dist/static/templates/raw-content/tailwind/site/base.css +44 -0
  238. package/dist/static/templates/raw-content/tailwind/site.config.css +3 -0
  239. package/dist/static/templates/sandbox/_gitignore +50 -0
  240. package/dist/static/templates/sandbox/identity.json +1 -0
  241. package/dist/static/templates/sandbox/src/404.hbs +21 -0
  242. package/dist/static/templates/sandbox/src/_data/autolink.json +1 -0
  243. package/dist/static/templates/sandbox/src/_data/ctaList.json +1 -0
  244. package/dist/static/templates/sandbox/src/_data/labelList.json +9 -0
  245. package/dist/static/templates/sandbox/src/_data/leedForms.json +20 -0
  246. package/dist/static/templates/sandbox/src/_data/menu.json +19 -0
  247. package/dist/static/templates/sandbox/src/_data/pageTypeList.json +14 -0
  248. package/dist/static/templates/sandbox/src/_data/searchIndexList.json +1 -0
  249. package/dist/static/templates/sandbox/src/_data/userList.json +11 -0
  250. package/dist/static/templates/sandbox/src/_includes/footer.hbs +18 -0
  251. package/dist/static/templates/sandbox/src/_includes/header-includes.hbs +25 -0
  252. package/dist/static/templates/sandbox/src/_includes/header.hbs +5 -0
  253. package/dist/static/templates/sandbox/src/_includes/site-template.hbs +23 -0
  254. package/dist/static/templates/sandbox/src/_layouts/empty.hbs +2 -0
  255. package/dist/static/templates/sandbox/src/index.hbs +20 -0
  256. package/dist/static/templates/sandbox/src/robots.hbs +9 -0
  257. package/dist/static/templates/sandbox/src/src.11tydata.json +39 -0
  258. package/dist/static/templates/sandbox/tailwind/site/base.css +44 -0
  259. package/dist/static/templates/sandbox/tailwind/site.config.css +3 -0
  260. package/dist/thrown-sukVkp_1.js +113 -0
  261. package/dist/typescript-D4T0V_Hn.js +23004 -0
  262. package/dist/yaml-9wR8GxF_.js +5236 -0
  263. package/package.json +157 -4
@@ -0,0 +1,74 @@
1
+ [
2
+ {
3
+ "name": "leedUtilsJS",
4
+ "path": "static/javascript",
5
+ "originalName": "utilities.js",
6
+ "destinationName": "utils",
7
+ "version": 32
8
+ },
9
+ {
10
+ "name": "searchJS",
11
+ "path": "static/javascript",
12
+ "originalName": "lunr-search.js",
13
+ "destinationName": "search",
14
+ "version": 10
15
+ },
16
+ {
17
+ "name": "liveSearchJS",
18
+ "path": "static/javascript",
19
+ "originalName": "live-search.js",
20
+ "destinationName": "livesearch",
21
+ "version": 3
22
+ },
23
+ {
24
+ "name": "privacyJS",
25
+ "path": "static/javascript",
26
+ "originalName": "detectIncognito.js",
27
+ "destinationName": "priv",
28
+ "version": 2
29
+ },
30
+ {
31
+ "name": "fingerprintJS",
32
+ "path": "static/javascript/fp",
33
+ "originalName": "fp.js",
34
+ "destinationName": "fp",
35
+ "version": 1
36
+ },
37
+ {
38
+ "name": "timerJS",
39
+ "path": "static/javascript",
40
+ "originalName": "timeme.js",
41
+ "destinationName": "timer",
42
+ "version": 2
43
+ },
44
+ {
45
+ "name": "trackerJS",
46
+ "entryPoint": "src/trackers/whisper.ts",
47
+ "path": "static/javascript/tracker",
48
+ "originalName": "whisper.js",
49
+ "destinationName": "whisper",
50
+ "version": 24
51
+ },
52
+ {
53
+ "name": "webmcpJS",
54
+ "entryPoint": "src/trackers/webmcp.ts",
55
+ "path": "static/javascript/tracker",
56
+ "originalName": "webmcp.js",
57
+ "destinationName": "webmcp",
58
+ "version": 3
59
+ },
60
+ {
61
+ "name": "documentationJS",
62
+ "path": "static/javascript",
63
+ "originalName": "documentation.js",
64
+ "destinationName": "docs",
65
+ "version": 23
66
+ },
67
+ {
68
+ "name": "zoomableJS",
69
+ "path": "static/javascript",
70
+ "originalName": "zoomable.js",
71
+ "destinationName": "zoomable",
72
+ "version": 5
73
+ }
74
+ ]
@@ -0,0 +1,488 @@
1
+ /**
2
+ * Forked from https://github.com/benbjurstrom/alpinejs-zoomable/commit/8f3b023a4d08d23bb3169df2a95273bd71689c0f
3
+ * baseScale has a bug. We need to fix it. So two lines have been commented out.
4
+ */
5
+ /**
6
+ * `openImage`, once Alpine has initialized and the container exists.
7
+ *
8
+ * Delegated handlers below need to open a diagram without an Alpine directive
9
+ * on it, and `alpine:init` may fire after `DOMContentLoaded` — so this is read
10
+ * at click time rather than captured at bind time, and is null until then.
11
+ */
12
+ let openZoomable = null;
13
+
14
+ function setupZoomable(Alpine) {
15
+ let isFullscreen = false;
16
+ let isDragging = false;
17
+ let startX = 0;
18
+ let startY = 0;
19
+ let translateX = 0;
20
+ let translateY = 0;
21
+ let currentScale = 1;
22
+ const baseScale = 1;
23
+
24
+ // Attempt to find existing container in the DOM
25
+ let container = document.querySelector(".zoomable-fullscreen-container");
26
+ if (!container) {
27
+ container = document.createElement("div");
28
+ container.className = "zoomable-fullscreen-container";
29
+ container.setAttribute("role", "dialog");
30
+ container.setAttribute("aria-modal", "true");
31
+ container.setAttribute("aria-label", "Image fullscreen modal");
32
+ document.body.appendChild(container);
33
+ }
34
+
35
+ // Make sure we have the loading indicator
36
+ let loadingIndicator = container.querySelector(".zoomable-loading-indicator");
37
+ if (!loadingIndicator) {
38
+ loadingIndicator = document.createElement("div");
39
+ loadingIndicator.className = "zoomable-loading-indicator";
40
+ loadingIndicator.setAttribute("role", "status");
41
+ loadingIndicator.setAttribute("aria-live", "polite");
42
+
43
+ const spinner = document.createElement("div");
44
+ spinner.className = "zoomable-spinner";
45
+ const loadingText = document.createElement("div");
46
+ loadingText.textContent = "Loading Image...";
47
+ loadingIndicator.appendChild(spinner);
48
+ loadingIndicator.appendChild(loadingText);
49
+ container.appendChild(loadingIndicator);
50
+ }
51
+
52
+ // Make sure we have the controls panel
53
+ let controlsPanel = container.querySelector(".zoomable-controls-panel");
54
+ if (!controlsPanel) {
55
+ controlsPanel = document.createElement("div");
56
+ controlsPanel.className = "zoomable-controls-panel";
57
+
58
+ const zoomInBtn = document.createElement("button");
59
+ zoomInBtn.className = "zoomable-control-button zoomable-zoom-in";
60
+ zoomInBtn.innerHTML =
61
+ '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" ' +
62
+ 'stroke-width="1.5" stroke="currentColor">' +
63
+ '<path stroke-linecap="round" stroke-linejoin="round" ' +
64
+ 'd="M12 4.5v15m7.5-7.5h-15" />' +
65
+ "</svg>";
66
+ zoomInBtn.setAttribute("aria-label", "Zoom in");
67
+ zoomInBtn.setAttribute("tabindex", "0");
68
+
69
+ const zoomOutBtn = document.createElement("button");
70
+ zoomOutBtn.className = "zoomable-control-button zoomable-zoom-out";
71
+ zoomOutBtn.innerHTML =
72
+ '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" ' +
73
+ 'stroke-width="1.5" stroke="currentColor">' +
74
+ '<path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14" />' +
75
+ "</svg>";
76
+ zoomOutBtn.setAttribute("aria-label", "Zoom out");
77
+ zoomOutBtn.setAttribute("tabindex", "0");
78
+
79
+ const closeBtn = document.createElement("button");
80
+ closeBtn.className = "zoomable-control-button zoomable-close";
81
+ closeBtn.innerHTML =
82
+ '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" ' +
83
+ 'stroke-width="1.5" stroke="currentColor">' +
84
+ '<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />' +
85
+ "</svg>";
86
+ closeBtn.setAttribute("aria-label", "Close fullscreen view");
87
+ closeBtn.setAttribute("tabindex", "0");
88
+
89
+ controlsPanel.appendChild(zoomInBtn);
90
+ controlsPanel.appendChild(zoomOutBtn);
91
+ controlsPanel.appendChild(closeBtn);
92
+ container.appendChild(controlsPanel);
93
+ }
94
+
95
+ // Make sure we have the fullscreen <img>
96
+ let fullscreenImg = container.querySelector("img.zoomable-fullscreen-image");
97
+ if (!fullscreenImg) {
98
+ fullscreenImg = document.createElement("img");
99
+ fullscreenImg.className = "zoomable-fullscreen-image";
100
+ fullscreenImg.setAttribute("alt", "");
101
+ container.appendChild(fullscreenImg);
102
+ }
103
+
104
+ /**
105
+ * The second stage, for inline SVG — a Mermaid diagram, in practice.
106
+ *
107
+ * An SVG cannot go through the <img> above. `img.src` needs a URL, and
108
+ * serializing the diagram to a data: URI would make it a separate document:
109
+ * every `var(--token)` in it would stop resolving, because the page's custom
110
+ * properties are not in scope there. A themed diagram would arrive unstyled.
111
+ *
112
+ * So the node is cloned into the page instead, where the cascade still
113
+ * reaches it. It shares `.zoomable-fullscreen-image` so the positioning,
114
+ * sizing and transition CSS is the same one rule; the second class is only
115
+ * a hook for the parts that differ.
116
+ */
117
+ let fullscreenSvg = container.querySelector(".zoomable-fullscreen-svg");
118
+ if (!fullscreenSvg) {
119
+ fullscreenSvg = document.createElement("div");
120
+ fullscreenSvg.className = "zoomable-fullscreen-image zoomable-fullscreen-svg";
121
+ container.appendChild(fullscreenSvg);
122
+ }
123
+
124
+ /**
125
+ * Whichever of the two is showing. Zoom, drag and the transform all act on
126
+ * this rather than on the <img>, which is the whole reason they did not need
127
+ * to learn about SVG.
128
+ */
129
+ let stage = fullscreenImg;
130
+
131
+ // -----------------------------
132
+ // Focus trapping helpers
133
+ // -----------------------------
134
+ const focusableSelectors = "button";
135
+ let focusableElements = [];
136
+ let firstFocusableElement = null;
137
+ let lastFocusableElement = null;
138
+
139
+ function trapFocus(e) {
140
+ if (!isFullscreen) return;
141
+ if (e.key === "Tab") {
142
+ if (focusableElements.length === 0) return;
143
+ if (e.shiftKey) {
144
+ if (document.activeElement === firstFocusableElement) {
145
+ lastFocusableElement.focus();
146
+ e.preventDefault();
147
+ }
148
+ } else {
149
+ if (document.activeElement === lastFocusableElement) {
150
+ firstFocusableElement.focus();
151
+ e.preventDefault();
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ function setFocusTrap() {
158
+ // Skip for touch devices
159
+ if ("ontouchstart" in window || navigator.maxTouchPoints > 0) {
160
+ return;
161
+ }
162
+ focusableElements = container.querySelectorAll(focusableSelectors);
163
+ if (focusableElements.length > 0) {
164
+ firstFocusableElement = focusableElements[0];
165
+ lastFocusableElement = focusableElements[focusableElements.length - 1];
166
+ firstFocusableElement.focus();
167
+ }
168
+ }
169
+
170
+ // -----------------------------
171
+ // Opening/closing image logic
172
+ // -----------------------------
173
+ /**
174
+ * Fit the active stage to the window, given the source's aspect ratio.
175
+ *
176
+ * The same arithmetic for both kinds — only where the ratio comes from
177
+ * differs, which is the one thing an <img> and an <svg> genuinely disagree
178
+ * about.
179
+ */
180
+ function fitStage(ratio) {
181
+ const windowRatio = window.innerWidth / window.innerHeight;
182
+ // const ratioMismatch = Math.abs(windowRatio - ratio)
183
+ // baseScale = ratioMismatch > 0.75 ? 1.75 : 1
184
+ currentScale = baseScale;
185
+
186
+ if (ratio > windowRatio) {
187
+ stage.style.width = `${window.innerWidth}px`;
188
+ stage.style.height = "auto";
189
+ } else {
190
+ stage.style.height = `${window.innerHeight}px`;
191
+ stage.style.width = "auto";
192
+ }
193
+
194
+ updateImagePosition();
195
+ loadingIndicator.hidden = true;
196
+ setFocusTrap();
197
+ }
198
+
199
+ /** Show one stage and put the other away, so only one is ever transformed. */
200
+ function useStage(next) {
201
+ stage = next;
202
+ const idle = next === fullscreenImg ? fullscreenSvg : fullscreenImg;
203
+ idle.hidden = true;
204
+ next.hidden = false;
205
+ }
206
+
207
+ function openImage(source) {
208
+ // If container was removed from DOM (e.g. due to wire:navigate),
209
+ // re-append it and re-attach event listeners.
210
+ if (!document.body.contains(container)) {
211
+ document.body.appendChild(container);
212
+ attachContainerListeners();
213
+ }
214
+
215
+ const isSvg = source.tagName.toLowerCase() === "svg";
216
+ useStage(isSvg ? fullscreenSvg : fullscreenImg);
217
+
218
+ container.style.display = "block";
219
+ isFullscreen = true;
220
+ document.body.style.overflow = "hidden";
221
+ document.addEventListener("keydown", trapFocus);
222
+
223
+ // Nothing is fetched for an SVG, so there is nothing to wait for and a
224
+ // spinner would flash for one frame and leave.
225
+ loadingIndicator.hidden = isSvg;
226
+ translateX = 0;
227
+ translateY = 0;
228
+ currentScale = 1;
229
+ updateImagePosition();
230
+
231
+ if (isSvg) {
232
+ const copy = source.cloneNode(true);
233
+ // Mermaid writes an inline `max-width` sized for the column it rendered
234
+ // into. Left on, the diagram would refuse to grow past that however far
235
+ // it is zoomed, which is the entire point of being here.
236
+ copy.style.removeProperty("max-width");
237
+ copy.removeAttribute("width");
238
+ copy.removeAttribute("height");
239
+ copy.setAttribute("width", "100%");
240
+ copy.setAttribute("height", "100%");
241
+
242
+ /**
243
+ * The diagram's own container comes along with it.
244
+ *
245
+ * Cloning the <svg> by itself is enough for `var(--token)` — those
246
+ * resolve against :root, which is why the note above says the cascade
247
+ * still reaches it. Selectors are the half that does not survive. A site
248
+ * correcting Mermaid's hardcoded colors writes them against the element
249
+ * the diagram sits in — `pre.mermaid svg { ... }` — and against a bare
250
+ * copy those rules match nothing. The zoomed diagram then quietly loses
251
+ * every correction while the one on the page keeps them, which reads as
252
+ * "zoom changes the colors" rather than as a missing rule.
253
+ *
254
+ * A shallow clone of the parent carries its tag and its classes and none
255
+ * of its children, so the site's own selectors match here exactly as
256
+ * they do in the document. The id does not come: it is still on the
257
+ * element in the page, and two of them would break `getElementById` and
258
+ * any `#id` rule pointing at the original.
259
+ *
260
+ * The carrier gives up its box in defaults.css — it is here to be
261
+ * matched, not to lay anything out.
262
+ */
263
+ const host = source.parentElement?.cloneNode(false) ?? null;
264
+ if (host) {
265
+ host.removeAttribute("id");
266
+ host.appendChild(copy);
267
+ }
268
+ fullscreenSvg.replaceChildren(host ?? copy);
269
+
270
+ // The viewBox is the SVG's own idea of its proportions and is what
271
+ // `naturalWidth`/`naturalHeight` would have told us about a bitmap. Fall
272
+ // back to the rendered box for an SVG that carries no viewBox.
273
+ const box = source.viewBox?.baseVal;
274
+ const rect = source.getBoundingClientRect();
275
+ const ratio = box?.width && box.height ? box.width / box.height : rect.width / rect.height || 1;
276
+
277
+ fitStage(ratio);
278
+ return;
279
+ }
280
+
281
+ fullscreenImg.src = source.src;
282
+ fullscreenImg.alt = source.alt || "Enlarged image view";
283
+
284
+ fullscreenImg.onload = () => {
285
+ fitStage(fullscreenImg.naturalWidth / fullscreenImg.naturalHeight);
286
+ };
287
+
288
+ fullscreenImg.onerror = () => {
289
+ loadingIndicator.hidden = true;
290
+ setFocusTrap();
291
+ };
292
+ }
293
+
294
+ function closeImage() {
295
+ container.style.display = "none";
296
+ isFullscreen = false;
297
+ document.body.style.overflow = "";
298
+ document.removeEventListener("keydown", trapFocus);
299
+ }
300
+
301
+ // -----------------------------
302
+ // Zoom & drag logic
303
+ // -----------------------------
304
+ function updateImagePosition() {
305
+ stage.style.transform = `translate(calc(-50% + ${translateX}px), calc(-50% + ${translateY}px)) scale(${currentScale})`;
306
+ }
307
+
308
+ function zoomIn() {
309
+ currentScale = Math.min(currentScale * 1.5, baseScale * 4);
310
+ updateImagePosition();
311
+ }
312
+
313
+ function zoomOut() {
314
+ currentScale = Math.max(currentScale / 1.5, baseScale * 0.5);
315
+ updateImagePosition();
316
+ }
317
+
318
+ function startDragging(e) {
319
+ if (!isFullscreen) return;
320
+ // If user clicked inside the controls panel, don’t drag the image
321
+ if (e.target.closest(".controls-panel")) {
322
+ return;
323
+ }
324
+ // If user clicked the blank area behind the image, treat that as close
325
+ if (e.target === container) {
326
+ closeImage();
327
+ return;
328
+ }
329
+
330
+ isDragging = true;
331
+ stage.classList.add("dragging");
332
+
333
+ const clientX = e.clientX || e.touches?.[0].clientX;
334
+ const clientY = e.clientY || e.touches?.[0].clientY;
335
+
336
+ startX = clientX - translateX;
337
+ startY = clientY - translateY;
338
+ e.preventDefault();
339
+ }
340
+
341
+ function stopDragging() {
342
+ isDragging = false;
343
+ stage.classList.remove("dragging");
344
+ }
345
+
346
+ function drag(e) {
347
+ if (!isDragging) return;
348
+
349
+ const clientX = e.clientX || e.touches?.[0].clientX;
350
+ const clientY = e.clientY || e.touches?.[0].clientY;
351
+
352
+ translateX = clientX - startX;
353
+ translateY = clientY - startY;
354
+
355
+ updateImagePosition();
356
+ e.preventDefault();
357
+ }
358
+
359
+ function onKeyDown(e) {
360
+ if (isFullscreen && e.key === "Escape") {
361
+ closeImage();
362
+ }
363
+ }
364
+
365
+ function preventDefault(e) {
366
+ if (isFullscreen) {
367
+ e.preventDefault();
368
+ }
369
+ }
370
+
371
+ // -----------------------------
372
+ // Helper to attach button & global listeners
373
+ // -----------------------------
374
+ function addButtonListeners(button, handler) {
375
+ const handleTouch = (e) => {
376
+ e.preventDefault();
377
+ handler(e);
378
+ };
379
+ button.addEventListener("click", handler);
380
+ button.addEventListener("touchend", handleTouch);
381
+
382
+ // Return a cleanup function if needed
383
+ return () => {
384
+ button.removeEventListener("click", handler);
385
+ button.removeEventListener("touchend", handleTouch);
386
+ };
387
+ }
388
+
389
+ function attachContainerListeners() {
390
+ // If we've already attached them and container is still in the DOM, skip
391
+ if (container.dataset.hasListeners === "true") return;
392
+
393
+ // Mark as attached
394
+ container.dataset.hasListeners = "true";
395
+
396
+ // Attach button listeners
397
+ const zoomInBtn = container.querySelector(".zoomable-zoom-in");
398
+ const zoomOutBtn = container.querySelector(".zoomable-zoom-out");
399
+ const closeBtn = container.querySelector(".zoomable-close");
400
+
401
+ addButtonListeners(zoomInBtn, zoomIn);
402
+ addButtonListeners(zoomOutBtn, zoomOut);
403
+ addButtonListeners(closeBtn, closeImage);
404
+ // Attach global event listeners
405
+ container.addEventListener("mousedown", startDragging);
406
+ window.addEventListener("mousemove", drag);
407
+ window.addEventListener("mouseup", stopDragging);
408
+
409
+ container.addEventListener("touchstart", startDragging, { passive: false });
410
+ container.addEventListener("touchmove", drag, { passive: false });
411
+ container.addEventListener("touchend", stopDragging);
412
+ container.addEventListener("touchmove", preventDefault, { passive: false });
413
+
414
+ document.addEventListener("keydown", onKeyDown);
415
+ }
416
+
417
+ // Attach them once on page load
418
+ attachContainerListeners();
419
+
420
+ // Hand the opener to the delegated listeners at the foot of this file.
421
+ openZoomable = openImage;
422
+
423
+ // -----------------------------
424
+ // Alpine directive
425
+ // -----------------------------
426
+ Alpine.directive("zoomable", (el, { expression }, { cleanup }) => {
427
+ const tag = el.tagName.toLowerCase();
428
+ if (tag !== "img" && tag !== "svg") {
429
+ console.error("The x-zoomable directive can only be used on an <img> or <svg> element, but found:", el.tagName);
430
+ return;
431
+ }
432
+
433
+ const onClick = () => openImage(el);
434
+ el.addEventListener("click", onClick);
435
+
436
+ // On directive cleanup, only remove the <img> click event
437
+ // Do NOT remove the container’s global event listeners here—
438
+ // those are meant to be persistent throughout.
439
+ cleanup(() => {
440
+ el.removeEventListener("click", onClick);
441
+ });
442
+ });
443
+ }
444
+
445
+ document.addEventListener("DOMContentLoaded", () => {
446
+ document.querySelectorAll("#leed-docs-copy img").forEach((img) => {
447
+ if (img.parentElement.tagName !== "A") {
448
+ img.setAttribute("x-zoomable", "");
449
+ }
450
+ });
451
+
452
+ /**
453
+ * Mermaid diagrams open on a delegated click rather than the directive.
454
+ *
455
+ * They do not exist yet. Mermaid renders after this event and replaces each
456
+ * `<pre>`'s contents, and again on every `prefers-color-scheme` change — so
457
+ * anything bound to the SVG here would be bound to a node that is about to
458
+ * be thrown away. Delegation has nothing to rebind.
459
+ *
460
+ * `closest` rather than the target itself, because a click lands on whatever
461
+ * rect or text is under the pointer, never on the `<svg>`.
462
+ */
463
+ document.addEventListener("click", (event) => {
464
+ if (event.target.closest?.(".zoomable-fullscreen-container")) return;
465
+ const diagram = event.target.closest?.("pre.mermaid svg");
466
+ if (diagram && openZoomable) {
467
+ openZoomable(diagram);
468
+ }
469
+ });
470
+
471
+ document.addEventListener("click", (event) => {
472
+ // The <img> stage is the target itself; on the SVG stage the target is
473
+ // some node inside the cloned diagram, so ask what it sits in.
474
+ const onStage =
475
+ event.target.classList?.contains("zoomable-fullscreen-image") ||
476
+ event.target.closest?.(".zoomable-fullscreen-svg");
477
+ if (onStage) {
478
+ const closeButton = document.querySelector(".zoomable-close");
479
+ if (closeButton) {
480
+ closeButton.click();
481
+ }
482
+ }
483
+ });
484
+ });
485
+
486
+ document.addEventListener("alpine:init", () => {
487
+ setupZoomable(Alpine);
488
+ });