@leed-ai/cli 0.0.0 → 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.
- package/LICENSE.md +57 -0
- package/README.md +120 -3
- package/dist/LICENSE.md +57 -0
- package/dist/acorn-DAgDT1om.js +5087 -0
- package/dist/angular-l0_4PK8N.js +3598 -0
- package/dist/authShared-Dray38Ls.js +1161 -0
- package/dist/babel-CJeRQd5u.js +10038 -0
- package/dist/buildResults-tiq1nugP.js +21180 -0
- package/dist/chunk-1VJ9lAw7.js +42 -0
- package/dist/cliAuth-38JjD6hw.js +15 -0
- package/dist/env-B0bHiXJJ.js +29 -0
- package/dist/errors-CqKamGCu.js +481 -0
- package/dist/estree-E8WG8UHj.js +6930 -0
- package/dist/flow-6xaRIbPQ.js +52255 -0
- package/dist/glimmer-aJPjsfbT.js +7272 -0
- package/dist/graphql-mcgtPEiZ.js +1901 -0
- package/dist/html--eeea3Kl.js +6553 -0
- package/dist/leed.eleventy.mjs +6525 -0
- package/dist/leed.mjs +88952 -0
- package/dist/leed.sources.json +798 -0
- package/dist/leedLogger-Zkada5aO.js +78 -0
- package/dist/markdown-D73jNKwx.js +6836 -0
- package/dist/meriyah-CMp1nDDW.js +8932 -0
- package/dist/package.json +101 -0
- package/dist/postcss-h4fBr2Fn.js +6760 -0
- package/dist/prettier-CwFSKxfN.js +16821 -0
- package/dist/static/customer-site-worker/package.json +9 -0
- package/dist/static/customer-site-worker/src/assetsHydration.ts +55 -0
- package/dist/static/customer-site-worker/src/constants.ts +20 -0
- package/dist/static/customer-site-worker/src/cors.ts +120 -0
- package/dist/static/customer-site-worker/src/index.ts +242 -0
- package/dist/static/customer-site-worker/src/mcp-proxy.ts +98 -0
- package/dist/static/customer-site-worker/src/proxy.ts +92 -0
- package/dist/static/customer-site-worker/src/proxyHeaders.ts +47 -0
- package/dist/static/customer-site-worker/src/tier.ts +40 -0
- package/dist/static/customer-site-worker/src/types.ts +82 -0
- package/dist/static/customer-site-worker/test/functions-mock.worker.js +50 -0
- package/dist/static/customer-site-worker/tsconfig.json +19 -0
- package/dist/static/customer-site-worker/vitest.workers.config.ts +61 -0
- package/dist/static/install/husky/colors.mjs +5 -0
- package/dist/static/install/husky/hooks/commit-msg +1 -0
- package/dist/static/install/husky/hooks/pre-commit +1 -0
- package/dist/static/install/husky/hooks/pre-push +1 -0
- package/dist/static/install/husky/valid-command.mjs +29 -0
- package/dist/static/install/husky/valid-commit-msg.mjs +20 -0
- package/dist/static/install/package.json +10 -0
- package/dist/static/install/packages.txt +4 -0
- package/dist/static/install/tasks.json +111 -0
- package/dist/static/javascript/detectIncognito.js +195 -0
- package/dist/static/javascript/documentation.js +2781 -0
- package/dist/static/javascript/fp/fp.esm.js +2896 -0
- package/dist/static/javascript/fp/fp.js +3067 -0
- package/dist/static/javascript/live-search.js +986 -0
- package/dist/static/javascript/lunr-search.js +843 -0
- package/dist/static/javascript/timeme.js +451 -0
- package/dist/static/javascript/tracker/webmcp.js +67 -0
- package/dist/static/javascript/tracker/whisper.js +1 -0
- package/dist/static/javascript/utilities.js +819 -0
- package/dist/static/javascript/versions.json +74 -0
- package/dist/static/javascript/zoomable.js +488 -0
- package/dist/static/site/_data/eleventyComputed.js +228 -0
- package/dist/static/site/_data/leed-form-data.json +253 -0
- package/dist/static/site/_includes/leed/api/bits/array-type.hbs +24 -0
- package/dist/static/site/_includes/leed/api/bits/badges.hbs +9 -0
- package/dist/static/site/_includes/leed/api/bits/description.hbs +9 -0
- package/dist/static/site/_includes/leed/api/bits/examples.hbs +42 -0
- package/dist/static/site/_includes/leed/api/bits/scopes.hbs +28 -0
- package/dist/static/site/_includes/leed/api/object.hbs +110 -0
- package/dist/static/site/_includes/leed/api/parameters.hbs +11 -0
- package/dist/static/site/_includes/leed/api/property.hbs +153 -0
- package/dist/static/site/_includes/leed/api/request-body.hbs +51 -0
- package/dist/static/site/_includes/leed/api/responses.hbs +89 -0
- package/dist/static/site/_includes/leed/api/security-constraints.hbs +59 -0
- package/dist/static/site/_includes/leed/api/security.hbs +75 -0
- package/dist/static/site/_includes/leed/components/pagination.hbs +45 -0
- package/dist/static/site/_includes/leed/components/scroll-status-indicator-horizontal.hbs +22 -0
- package/dist/static/site/_includes/leed/docs/alpha/api.hbs +6 -0
- package/dist/static/site/_includes/leed/docs/alpha/base.hbs +26 -0
- package/dist/static/site/_includes/leed/docs/alpha/documentation.hbs +7 -0
- package/dist/static/site/_includes/leed/docs/api-article.hbs +75 -0
- package/dist/static/site/_includes/leed/docs/bravo/api.hbs +5 -0
- package/dist/static/site/_includes/leed/docs/bravo/base.hbs +31 -0
- package/dist/static/site/_includes/leed/docs/bravo/documentation.hbs +7 -0
- package/dist/static/site/_includes/leed/docs/charlie/api.hbs +6 -0
- package/dist/static/site/_includes/leed/docs/charlie/base.hbs +27 -0
- package/dist/static/site/_includes/leed/docs/charlie/documentation.hbs +10 -0
- package/dist/static/site/_includes/leed/docs/doc-article.hbs +40 -0
- package/dist/static/site/_includes/leed/docs/docs-footer.hbs +35 -0
- package/dist/static/site/_includes/leed/docs/docs-header.hbs +59 -0
- package/dist/static/site/_includes/leed/docs/document-search-modal.hbs +36 -0
- package/dist/static/site/_includes/leed/docs/document-search.hbs +23 -0
- package/dist/static/site/_includes/leed/docs/footer.hbs +12 -0
- package/dist/static/site/_includes/leed/docs/header/brand.hbs +19 -0
- package/dist/static/site/_includes/leed/docs/header/chrome.hbs +33 -0
- package/dist/static/site/_includes/leed/docs/header/compact.hbs +19 -0
- package/dist/static/site/_includes/leed/docs/header/cta.hbs +15 -0
- package/dist/static/site/_includes/leed/docs/header/nav.hbs +18 -0
- package/dist/static/site/_includes/leed/docs/header/top-search.hbs +15 -0
- package/dist/static/site/_includes/leed/docs/mini-bar.hbs +53 -0
- package/dist/static/site/_includes/leed/docs/pagination.hbs +19 -0
- package/dist/static/site/_includes/leed/docs/shell.hbs +56 -0
- package/dist/static/site/_includes/leed/docs/sidebar.hbs +52 -0
- package/dist/static/site/_includes/leed/docs/social-icons.hbs +81 -0
- package/dist/static/site/_includes/leed/docs/style.hbs +17 -0
- package/dist/static/site/_includes/leed/docs/toc.hbs +7 -0
- package/dist/static/site/_includes/leed/form.hbs +266 -0
- package/dist/static/site/_includes/leed/head.hbs +67 -0
- package/dist/static/site/_includes/leed/menu/builder.hbs +35 -0
- package/dist/static/site/_includes/leed/menu/item.hbs +67 -0
- package/dist/static/site/_includes/leed/menu/link.hbs +59 -0
- package/dist/static/site/_includes/leed/metadata/ogCard.hbs +40 -0
- package/dist/static/site/_includes/leed/metadata/siteMetadata.hbs +24 -0
- package/dist/static/site/_includes/leed/metadata/twitterCard.hbs +34 -0
- package/dist/static/site/_includes/leed/popup-video.hbs +21 -0
- package/dist/static/site/_includes/leed/stub-template.hbs +17 -0
- package/dist/static/site/_includes/leed/unsubscribe-form.hbs +30 -0
- package/dist/static/site/_layouts/leed-documentation.hbs +12 -0
- package/dist/static/site/leed-feed-atom.hbs +42 -0
- package/dist/static/site/leed-feed-json.hbs +56 -0
- package/dist/static/site/leed-feed-rss.hbs +39 -0
- package/dist/static/site/leed-headers.hbs +38 -0
- package/dist/static/site/leed-redirects.hbs +10 -0
- package/dist/static/site/leed-sitemap-pageType.hbs +28 -0
- package/dist/static/site/leed-sitemap.hbs +19 -0
- package/dist/static/site/leed-unsubscribe.hbs +44 -0
- package/dist/static/site/leed-unsubscribed.hbs +40 -0
- package/dist/static/tailwind/components/alerts.css +132 -0
- package/dist/static/tailwind/components/api-methods.css +39 -0
- package/dist/static/tailwind/components/breadcrumbs.css +31 -0
- package/dist/static/tailwind/components/code.css +88 -0
- package/dist/static/tailwind/components/collapsible.css +38 -0
- package/dist/static/tailwind/components/document-search.css +222 -0
- package/dist/static/tailwind/components/form.css +185 -0
- package/dist/static/tailwind/components/kbd.css +7 -0
- package/dist/static/tailwind/components/pagination.css +81 -0
- package/dist/static/tailwind/components/scroll-status-indicator.css +5 -0
- package/dist/static/tailwind/components/tab-groups.css +117 -0
- package/dist/static/tailwind/components/tables.css +0 -0
- package/dist/static/tailwind/components/toc.css +60 -0
- package/dist/static/tailwind/components.css +248 -0
- package/dist/static/tailwind/defaults.css +260 -0
- package/dist/static/tailwind/docs/api.css +701 -0
- package/dist/static/tailwind/docs/components/blockquote.css +5 -0
- package/dist/static/tailwind/docs/components/button.css +11 -0
- package/dist/static/tailwind/docs/components/docs-pagination.css +71 -0
- package/dist/static/tailwind/docs/components/mobile-bar.css +83 -0
- package/dist/static/tailwind/docs/components/navigation.css +279 -0
- package/dist/static/tailwind/docs/components/table.css +54 -0
- package/dist/static/tailwind/docs/components.css +6 -0
- package/dist/static/tailwind/docs/docs.css +427 -0
- package/dist/static/tailwind/docs/layouts/alpha.css +108 -0
- package/dist/static/tailwind/docs/layouts/bravo.css +218 -0
- package/dist/static/tailwind/docs/layouts/charlie.css +105 -0
- package/dist/static/tailwind/docs/layouts.css +3 -0
- package/dist/static/tailwind/docs/themes/amber.css +113 -0
- package/dist/static/tailwind/docs/themes/blue.css +94 -0
- package/dist/static/tailwind/docs/themes/cyan.css +111 -0
- package/dist/static/tailwind/docs/themes/emerald.css +111 -0
- package/dist/static/tailwind/docs/themes/fuchsia.css +111 -0
- package/dist/static/tailwind/docs/themes/green.css +95 -0
- package/dist/static/tailwind/docs/themes/indigo.css +111 -0
- package/dist/static/tailwind/docs/themes/lime.css +111 -0
- package/dist/static/tailwind/docs/themes/orange.css +111 -0
- package/dist/static/tailwind/docs/themes/pink.css +111 -0
- package/dist/static/tailwind/docs/themes/purple.css +111 -0
- package/dist/static/tailwind/docs/themes/red.css +111 -0
- package/dist/static/tailwind/docs/themes/rose.css +111 -0
- package/dist/static/tailwind/docs/themes/sky.css +111 -0
- package/dist/static/tailwind/docs/themes/teal.css +111 -0
- package/dist/static/tailwind/docs/themes/violet.css +111 -0
- package/dist/static/tailwind/docs/themes/yellow.css +111 -0
- package/dist/static/tailwind/docs/themes.css +84 -0
- package/dist/static/tailwind/font-awesome/free-7.3.1/brands.css +2455 -0
- package/dist/static/tailwind/font-awesome/free-7.3.1/fontawesome.css +8997 -0
- package/dist/static/tailwind/font-awesome/free-7.3.1/fonts.css +45 -0
- package/dist/static/tailwind/font-awesome/free-7.3.1/icons.json +2608 -0
- package/dist/static/tailwind/font-awesome/free-7.3.1.css +3 -0
- package/dist/static/tailwind/font-awesome/pro-7.0.0/brands.css +2215 -0
- package/dist/static/tailwind/font-awesome/pro-7.0.0/fontawesome.css +19281 -0
- package/dist/static/tailwind/font-awesome/pro-7.0.0/fonts.css +445 -0
- package/dist/static/tailwind/font-awesome/pro-7.0.0.css +3 -0
- package/dist/static/tailwind/font-awesome/pro-7.3.1/brands.css +2455 -0
- package/dist/static/tailwind/font-awesome/pro-7.3.1/fontawesome.css +20365 -0
- package/dist/static/tailwind/font-awesome/pro-7.3.1/fonts.css +589 -0
- package/dist/static/tailwind/font-awesome/pro-7.3.1.css +3 -0
- package/dist/static/tailwind/fonts/all.css +6 -0
- package/dist/static/tailwind/fonts/config.jsonc +31 -0
- package/dist/static/tailwind/fonts/geist-mono.css +142 -0
- package/dist/static/tailwind/fonts/geist.css +142 -0
- package/dist/static/tailwind/fonts/inter.css +215 -0
- package/dist/static/tailwind/fonts/jetbrains-mono.css +126 -0
- package/dist/static/tailwind/fonts/noto-sans.css +134 -0
- package/dist/static/tailwind/fonts/open-sans.css +89 -0
- package/dist/static/tailwind/highlighters.css +14 -0
- package/dist/static/tailwind/hljs/README.md +53 -0
- package/dist/static/tailwind/hljs/a11y.css +96 -0
- package/dist/static/tailwind/hljs/atom-fruit.css +90 -0
- package/dist/static/tailwind/hljs/atom-one.css +164 -0
- package/dist/static/tailwind/hljs/default.css +164 -0
- package/dist/static/tailwind/hljs/github.css +101 -0
- package/dist/static/tailwind/hljs/google-code.css +112 -0
- package/dist/static/tailwind/hljs/grayscale.css +115 -0
- package/dist/static/tailwind/hljs/gruvbox-hard.css +115 -0
- package/dist/static/tailwind/hljs/gruvbox-medium.css +115 -0
- package/dist/static/tailwind/hljs/gruvbox-soft.css +115 -0
- package/dist/static/tailwind/hljs/papercolor.css +120 -0
- package/dist/static/tailwind/hljs/qt-creator.css +91 -0
- package/dist/static/tailwind/hljs/summerfruit.css +115 -0
- package/dist/static/tailwind/hljs/tomorrow.css +115 -0
- package/dist/static/tailwind/leed.css +170 -0
- package/dist/static/tailwind/site-tokens.reference.css +105 -0
- package/dist/static/tailwind/utils/icons.css +102 -0
- package/dist/static/tailwind/utils/utilities.css +105 -0
- package/dist/static/templates/pages/PAGE.hbs +27 -0
- package/dist/static/templates/pages/PAGE_LAYOUT.hbs +19 -0
- package/dist/static/templates/pages/PAGE_TYPE_INDEX.hbs +89 -0
- package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_ITEM.hbs +52 -0
- package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_LIST.hbs +39 -0
- package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_PAGINATION.hbs +11 -0
- package/dist/static/templates/raw-content/.ci/build.sh +58 -0
- package/dist/static/templates/raw-content/README.md +179 -0
- package/dist/static/templates/raw-content/_gitignore +50 -0
- package/dist/static/templates/raw-content/src/404.hbs +21 -0
- package/dist/static/templates/raw-content/src/_data/autolink.json +1 -0
- package/dist/static/templates/raw-content/src/_data/ctaList.json +1 -0
- package/dist/static/templates/raw-content/src/_data/leedForms.json +1 -0
- package/dist/static/templates/raw-content/src/_data/menu.json +1 -0
- package/dist/static/templates/raw-content/src/_includes/footer.hbs +18 -0
- package/dist/static/templates/raw-content/src/_includes/header-includes.hbs +25 -0
- package/dist/static/templates/raw-content/src/_includes/header.hbs +5 -0
- package/dist/static/templates/raw-content/src/_includes/site-template.hbs +23 -0
- package/dist/static/templates/raw-content/src/_includes/unsubscribe-DISABLED.hbs +17 -0
- package/dist/static/templates/raw-content/src/_includes/unsubscribed-DISABLED.hbs +13 -0
- package/dist/static/templates/raw-content/src/_layouts/empty.hbs +2 -0
- package/dist/static/templates/raw-content/src/index.hbs +21 -0
- package/dist/static/templates/raw-content/src/robots.hbs +9 -0
- package/dist/static/templates/raw-content/tailwind/site/base.css +44 -0
- package/dist/static/templates/raw-content/tailwind/site.config.css +3 -0
- package/dist/static/templates/sandbox/_gitignore +50 -0
- package/dist/static/templates/sandbox/identity.json +1 -0
- package/dist/static/templates/sandbox/src/404.hbs +21 -0
- package/dist/static/templates/sandbox/src/_data/autolink.json +1 -0
- package/dist/static/templates/sandbox/src/_data/ctaList.json +1 -0
- package/dist/static/templates/sandbox/src/_data/labelList.json +9 -0
- package/dist/static/templates/sandbox/src/_data/leedForms.json +20 -0
- package/dist/static/templates/sandbox/src/_data/menu.json +19 -0
- package/dist/static/templates/sandbox/src/_data/pageTypeList.json +14 -0
- package/dist/static/templates/sandbox/src/_data/searchIndexList.json +1 -0
- package/dist/static/templates/sandbox/src/_data/userList.json +11 -0
- package/dist/static/templates/sandbox/src/_includes/footer.hbs +18 -0
- package/dist/static/templates/sandbox/src/_includes/header-includes.hbs +25 -0
- package/dist/static/templates/sandbox/src/_includes/header.hbs +5 -0
- package/dist/static/templates/sandbox/src/_includes/site-template.hbs +23 -0
- package/dist/static/templates/sandbox/src/_layouts/empty.hbs +2 -0
- package/dist/static/templates/sandbox/src/index.hbs +20 -0
- package/dist/static/templates/sandbox/src/robots.hbs +9 -0
- package/dist/static/templates/sandbox/src/src.11tydata.json +39 -0
- package/dist/static/templates/sandbox/tailwind/site/base.css +44 -0
- package/dist/static/templates/sandbox/tailwind/site.config.css +3 -0
- package/dist/thrown-sukVkp_1.js +113 -0
- package/dist/typescript-D4T0V_Hn.js +23004 -0
- package/dist/yaml-9wR8GxF_.js +5236 -0
- package/package.json +152 -10
|
@@ -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
|
+
});
|