@altano/astro-opengraph 0.1.0-alpha.3 → 0.1.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 (34) hide show
  1. package/README.md +9 -0
  2. package/components/meta.astro +1 -1
  3. package/dist/config-CzK0JuaO.js +45 -0
  4. package/dist/config.d.ts +8 -3
  5. package/dist/config.js +3 -0
  6. package/dist/endpoint.d.ts +25 -11
  7. package/dist/endpoint.js +62 -126
  8. package/dist/index.d.ts +8 -2
  9. package/dist/index.js +41 -58
  10. package/dist/toolbar/index.d.ts +7 -2
  11. package/dist/toolbar/index.js +364 -396
  12. package/dist/types-Lk5HqHkQ.d.ts +71 -0
  13. package/package.json +28 -26
  14. package/dist/image.d.ts +0 -7
  15. package/dist/integration.d.ts +0 -5
  16. package/dist/toolbar/components/CopyImageUrlButton.d.ts +0 -3
  17. package/dist/toolbar/components/ExternalLinkicon.d.ts +0 -7
  18. package/dist/toolbar/components/Image.d.ts +0 -5
  19. package/dist/toolbar/components/ImageSection.d.ts +0 -4
  20. package/dist/toolbar/components/ImageZoomToolbar.d.ts +0 -7
  21. package/dist/toolbar/components/LinkOrText.d.ts +0 -7
  22. package/dist/toolbar/components/MetaTags.d.ts +0 -3
  23. package/dist/toolbar/components/Summary.d.ts +0 -5
  24. package/dist/toolbar/components/ToolbarApp.d.ts +0 -3
  25. package/dist/toolbar/components/ToolbarAppWindow.d.ts +0 -3
  26. package/dist/toolbar/components/ToolbarSection.d.ts +0 -6
  27. package/dist/toolbar/components/ZoomButton.d.ts +0 -7
  28. package/dist/toolbar/components/ZoomLabel.d.ts +0 -4
  29. package/dist/toolbar/hooks/useHoverState.d.ts +0 -3
  30. package/dist/toolbar/hooks/useImageURL.d.ts +0 -3
  31. package/dist/toolbar/hooks/useMetaTagInfo.d.ts +0 -3
  32. package/dist/toolbar/styles.d.ts +0 -2
  33. package/dist/types.d.ts +0 -67
  34. package/dist/virtual-user-config.d.ts +0 -8
@@ -1,11 +1,10 @@
1
- // src/toolbar/index.tsx
2
- import { createRoot } from "react-dom/client";
1
+ import { render } from "preact";
3
2
  import { defineToolbarApp } from "astro/toolbar";
3
+ import { useCallback, useEffect, useRef, useState } from "preact/hooks";
4
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
4
5
 
5
- // src/toolbar/styles.tsx
6
- var styles = (
7
- /* css */
8
- `
6
+ //#region src/toolbar/styles.tsx
7
+ const styles = `
9
8
  :host astro-dev-toolbar-window {
10
9
  max-height: calc(100vh - 80px);
11
10
  overflow-y: auto;
@@ -34,439 +33,408 @@ var styles = (
34
33
  .image img {
35
34
  transition: max-width 0.1s;
36
35
  }
37
- `
38
- );
36
+ `;
39
37
 
40
- // src/toolbar/components/ToolbarApp.tsx
41
- import { useState as useState4 } from "react";
42
-
43
- // src/toolbar/components/Summary.tsx
44
- import { jsx } from "react/jsx-runtime";
38
+ //#endregion
39
+ //#region src/toolbar/components/Summary.tsx
45
40
  function Summary({ children }) {
46
- return /* @__PURE__ */ jsx(
47
- "summary",
48
- {
49
- style: {
50
- cursor: "pointer",
51
- fontWeight: 700,
52
- color: "white"
53
- },
54
- children
55
- }
56
- );
41
+ return /* @__PURE__ */ jsx("summary", {
42
+ style: {
43
+ cursor: "pointer",
44
+ fontWeight: 700,
45
+ color: "white"
46
+ },
47
+ children
48
+ });
57
49
  }
58
50
 
59
- // src/toolbar/components/ExternalLinkicon.tsx
60
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
61
- function ExternalLinkicon({
62
- width = 27,
63
- height = 27,
64
- fill = "#020202"
65
- }) {
66
- return /* @__PURE__ */ jsx2(
67
- "span",
68
- {
69
- style: {
70
- display: "inline-block",
71
- width,
72
- height
73
- },
74
- children: /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 120 120", children: [
75
- /* @__PURE__ */ jsx2("path", { d: "M120.09 16.696H60.256V.096L120.09.09z", fill }),
76
- /* @__PURE__ */ jsx2(
77
- "path",
78
- {
79
- d: "M57.99 48.64l42.573-42.574 13.475 13.475-42.574 42.58z",
80
- fill
81
- }
82
- ),
83
- /* @__PURE__ */ jsx2(
84
- "path",
85
- {
86
- d: "M119.98.107l.02 59.83-16.59.013-.02-59.846zM3 23.5h17v87H3zm83.49 52.56h17V113h-17z",
87
- fill
88
- }
89
- ),
90
- /* @__PURE__ */ jsx2("path", { d: "M3 16.692h40.655v17H3zM3 96h100.49v17H3z", fill })
91
- ] })
92
- }
93
- );
51
+ //#endregion
52
+ //#region src/toolbar/components/ExternalLinkicon.tsx
53
+ function ExternalLinkicon({ width = 27, height = 27, fill = "#020202" }) {
54
+ return /* @__PURE__ */ jsx("span", {
55
+ style: {
56
+ display: "inline-block",
57
+ width,
58
+ height
59
+ },
60
+ children: /* @__PURE__ */ jsxs("svg", {
61
+ xmlns: "http://www.w3.org/2000/svg",
62
+ viewBox: "0 0 120 120",
63
+ children: [
64
+ /* @__PURE__ */ jsx("path", {
65
+ d: "M120.09 16.696H60.256V.096L120.09.09z",
66
+ fill
67
+ }),
68
+ /* @__PURE__ */ jsx("path", {
69
+ d: "M57.99 48.64l42.573-42.574 13.475 13.475-42.574 42.58z",
70
+ fill
71
+ }),
72
+ /* @__PURE__ */ jsx("path", {
73
+ d: "M119.98.107l.02 59.83-16.59.013-.02-59.846zM3 23.5h17v87H3zm83.49 52.56h17V113h-17z",
74
+ fill
75
+ }),
76
+ /* @__PURE__ */ jsx("path", {
77
+ d: "M3 16.692h40.655v17H3zM3 96h100.49v17H3z",
78
+ fill
79
+ })
80
+ ]
81
+ })
82
+ });
94
83
  }
95
84
 
96
- // src/toolbar/components/LinkOrText.tsx
97
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
98
- function LinkOrText({
99
- maybeLinkText
100
- }) {
101
- let parsedMaybeLink = null;
102
- try {
103
- if (maybeLinkText != null) {
104
- const url = new URL(maybeLinkText);
105
- parsedMaybeLink = /* @__PURE__ */ jsxs2("a", { href: url.toString(), target: "_blank", children: [
106
- maybeLinkText,
107
- " ",
108
- /* @__PURE__ */ jsx3(ExternalLinkicon, { width: 10, height: 10, fill: "white" })
109
- ] });
110
- }
111
- } catch (_) {
112
- parsedMaybeLink = maybeLinkText;
113
- }
114
- return parsedMaybeLink;
85
+ //#endregion
86
+ //#region src/toolbar/components/LinkOrText.tsx
87
+ function LinkOrText({ maybeLinkText }) {
88
+ let parsedMaybeLink = null;
89
+ try {
90
+ if (maybeLinkText != null) {
91
+ const url = new URL(maybeLinkText);
92
+ parsedMaybeLink = /* @__PURE__ */ jsxs("a", {
93
+ href: url.toString(),
94
+ target: "_blank",
95
+ children: [
96
+ maybeLinkText,
97
+ " ",
98
+ /* @__PURE__ */ jsx(ExternalLinkicon, {
99
+ width: 10,
100
+ height: 10,
101
+ fill: "white"
102
+ })
103
+ ]
104
+ });
105
+ }
106
+ } catch (_) {
107
+ parsedMaybeLink = maybeLinkText;
108
+ }
109
+ return parsedMaybeLink;
115
110
  }
116
111
 
117
- // src/toolbar/hooks/useMetaTagInfo.tsx
112
+ //#endregion
113
+ //#region src/toolbar/hooks/useMetaTagInfo.tsx
114
+ const useHeadObserver = () => {
115
+ const [_generation, setGeneration] = useState(0);
116
+ const forceRerender = () => setGeneration((old) => ++old);
117
+ const headRef = useRef(document.querySelector("head"));
118
+ useEffect(() => {
119
+ if (headRef.current == null) return;
120
+ const observer = new MutationObserver(forceRerender);
121
+ observer.observe(headRef.current, {
122
+ attributes: true,
123
+ characterData: true,
124
+ childList: true,
125
+ subtree: true
126
+ });
127
+ return () => observer.disconnect();
128
+ }, []);
129
+ return headRef;
130
+ };
118
131
  function useMetaTagInfo() {
119
- return Array.from(document.querySelectorAll("meta[property^='og:']")).map(
120
- (tag) => [
121
- tag.getAttribute("content"),
122
- tag.getAttribute("property")
123
- ]
124
- );
132
+ const headRef = useHeadObserver();
133
+ const opengraphMetaTags = headRef?.current?.querySelectorAll("meta[property^='og:']") ?? [];
134
+ return Array.from(opengraphMetaTags).map((tag) => [tag.getAttribute("content"), tag.getAttribute("property")]);
125
135
  }
126
136
 
127
- // src/toolbar/components/MetaTags.tsx
128
- import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
137
+ //#endregion
138
+ //#region src/toolbar/components/MetaTags.tsx
129
139
  function MetaTags() {
130
- const tags = useMetaTagInfo();
131
- return /* @__PURE__ */ jsx4(
132
- "dl",
133
- {
134
- "data-testid": "astro-opengraph-toolbar",
135
- style: {
136
- margin: 0,
137
- display: "grid",
138
- gridTemplateColumns: "max-content 1fr",
139
- gap: 7,
140
- columnGap: 13
141
- },
142
- children: tags.map((tag) => /* @__PURE__ */ jsx4(MetaTagContent, { tag }, tag[1]))
143
- }
144
- );
140
+ const tags = useMetaTagInfo();
141
+ return /* @__PURE__ */ jsx("dl", {
142
+ "data-testid": "astro-opengraph-toolbar",
143
+ style: {
144
+ margin: 0,
145
+ display: "grid",
146
+ gridTemplateColumns: "max-content 1fr",
147
+ gap: 7,
148
+ columnGap: 13
149
+ },
150
+ children: tags.map((tag) => /* @__PURE__ */ jsx(MetaTagContent, { tag }, tag[1]))
151
+ });
145
152
  }
146
153
  function MetaTagContent({ tag }) {
147
- const [content, property] = tag;
148
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
149
- /* @__PURE__ */ jsx4(
150
- "dt",
151
- {
152
- style: {
153
- color: "white",
154
- textAlign: "right",
155
- fontWeight: 500
156
- },
157
- children: property
158
- }
159
- ),
160
- /* @__PURE__ */ jsx4("dd", { style: { margin: 0 }, children: /* @__PURE__ */ jsx4(LinkOrText, { maybeLinkText: content }) })
161
- ] });
154
+ const [content, property] = tag;
155
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("dt", {
156
+ style: {
157
+ color: "white",
158
+ textAlign: "right",
159
+ fontWeight: 500
160
+ },
161
+ children: property
162
+ }), /* @__PURE__ */ jsx("dd", {
163
+ style: { margin: 0 },
164
+ children: /* @__PURE__ */ jsx(LinkOrText, { maybeLinkText: content })
165
+ })] });
162
166
  }
163
167
 
164
- // src/toolbar/hooks/useHoverState.tsx
165
- import { useRef, useEffect } from "react";
168
+ //#endregion
169
+ //#region src/toolbar/hooks/useHoverState.tsx
166
170
  function useHoverState(setHoverState) {
167
- const ref = useRef(null);
168
- useEffect(() => {
169
- const controller = new AbortController();
170
- const { signal } = controller;
171
- ref.current?.addEventListener("mouseenter", () => setHoverState(true), {
172
- signal
173
- });
174
- ref.current?.addEventListener("mouseleave", () => setHoverState(false), {
175
- signal
176
- });
177
- return () => controller.abort();
178
- }, [setHoverState]);
179
- return ref;
171
+ const ref = useRef(null);
172
+ useEffect(() => {
173
+ const controller = new AbortController();
174
+ const { signal } = controller;
175
+ ref.current?.addEventListener("mouseenter", () => setHoverState(true), { signal });
176
+ ref.current?.addEventListener("mouseleave", () => setHoverState(false), { signal });
177
+ return () => controller.abort();
178
+ }, [setHoverState]);
179
+ return ref;
180
180
  }
181
181
 
182
- // src/toolbar/hooks/useImageURL.tsx
183
- import { useState } from "react";
182
+ //#endregion
183
+ //#region src/toolbar/hooks/useImageURL.tsx
184
184
  function useImageURL() {
185
- const imageUrl = useImageURLIfAvailable();
186
- if (imageUrl == null) {
187
- throw new Error(
188
- `Shouldn't be rendering this component without an image URL`
189
- );
190
- }
191
- return imageUrl;
185
+ const imageUrl = useImageURLIfAvailable();
186
+ if (imageUrl == null) throw new Error(`Shouldn't be rendering this component without an image URL`);
187
+ return imageUrl;
192
188
  }
193
189
  function useImageURLIfAvailable() {
194
- const [imageUrlRef] = useState(() => {
195
- const meta = document.querySelector('meta[property="og:image"]');
196
- return meta?.getAttribute("content") ?? null;
197
- });
198
- return imageUrlRef;
190
+ const [imageUrlRef] = useState(() => {
191
+ const meta = document.querySelector("meta[property=\"og:image\"]");
192
+ return meta?.getAttribute("content") ?? null;
193
+ });
194
+ return imageUrlRef;
199
195
  }
200
196
 
201
- // src/toolbar/components/Image.tsx
202
- import { jsx as jsx5 } from "react/jsx-runtime";
203
- function Image({ imageSize }) {
204
- const imageUrl = useImageURL();
205
- return /* @__PURE__ */ jsx5("div", { className: "image", children: /* @__PURE__ */ jsx5("a", { href: imageUrl, target: "_blank", title: "Open image in new tab", children: /* @__PURE__ */ jsx5(
206
- "img",
207
- {
208
- alt: "Open Graph",
209
- src: imageUrl,
210
- style: {
211
- maxHeight: "100%",
212
- maxWidth: `${imageSize}%`
213
- }
214
- }
215
- ) }) });
197
+ //#endregion
198
+ //#region src/toolbar/components/Image.tsx
199
+ function Image({ imageSize, handleLoadError }) {
200
+ const imageUrl = useImageURL();
201
+ return /* @__PURE__ */ jsx("div", {
202
+ className: "image",
203
+ children: /* @__PURE__ */ jsx("a", {
204
+ href: imageUrl,
205
+ target: "_blank",
206
+ title: "Open image in new tab",
207
+ children: /* @__PURE__ */ jsx("img", {
208
+ onError: handleLoadError,
209
+ alt: "Open Graph",
210
+ src: imageUrl,
211
+ style: {
212
+ maxHeight: "100%",
213
+ maxWidth: `${imageSize}%`
214
+ }
215
+ })
216
+ })
217
+ });
216
218
  }
217
219
 
218
- // src/toolbar/components/ZoomLabel.tsx
220
+ //#endregion
221
+ //#region src/toolbar/components/ZoomLabel.tsx
219
222
  function ZoomLabel({ imageSize }) {
220
- const formattedNumber = (imageSize / 100).toLocaleString(void 0, {
221
- minimumFractionDigits: 2
222
- });
223
- return `${formattedNumber}x`;
223
+ const formattedNumber = (imageSize / 100).toLocaleString(void 0, { minimumFractionDigits: 2 });
224
+ return `${formattedNumber}x`;
224
225
  }
225
226
 
226
- // src/toolbar/components/ZoomButton.tsx
227
- import { jsx as jsx6 } from "react/jsx-runtime";
228
- function ZoomButton({
229
- value,
230
- imageSize,
231
- setImageSize
232
- }) {
233
- const isSelected = value === imageSize;
234
- return /* @__PURE__ */ jsx6(
235
- "astro-dev-toolbar-button",
236
- {
237
- size: "small",
238
- style: { padding: 0, margin: 0 },
239
- buttonStyle: isSelected ? "gray" : "ghost",
240
- className: "zoom-button",
241
- role: "radio",
242
- onClick: () => setImageSize(value),
243
- children: /* @__PURE__ */ jsx6(ZoomLabel, { imageSize: value })
244
- }
245
- );
227
+ //#endregion
228
+ //#region src/toolbar/components/ZoomButton.tsx
229
+ function ZoomButton({ value, imageSize, setImageSize }) {
230
+ const isSelected = value === imageSize;
231
+ return /* @__PURE__ */ jsx("astro-dev-toolbar-button", {
232
+ size: "small",
233
+ style: {
234
+ padding: 0,
235
+ margin: 0
236
+ },
237
+ buttonStyle: isSelected ? "gray" : "ghost",
238
+ className: "zoom-button",
239
+ role: "radio",
240
+ onClick: () => setImageSize(value),
241
+ children: /* @__PURE__ */ jsx(ZoomLabel, { imageSize: value })
242
+ });
246
243
  }
247
244
 
248
- // src/toolbar/components/ToolbarSection.tsx
249
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
250
- function ToolbarSection({
251
- icon,
252
- children
253
- }) {
254
- return /* @__PURE__ */ jsxs4(
255
- "div",
256
- {
257
- style: {
258
- fontSize: 12,
259
- display: "flex",
260
- alignItems: "center",
261
- columnGap: 5
262
- },
263
- children: [
264
- /* @__PURE__ */ jsx7(
265
- "div",
266
- {
267
- style: {
268
- display: "inline-block",
269
- width: 12,
270
- height: 12
271
- },
272
- children: icon
273
- }
274
- ),
275
- children
276
- ]
277
- }
278
- );
245
+ //#endregion
246
+ //#region src/toolbar/components/ToolbarSection.tsx
247
+ function ToolbarSection({ icon, children }) {
248
+ return /* @__PURE__ */ jsxs("div", {
249
+ style: {
250
+ fontSize: 12,
251
+ display: "flex",
252
+ alignItems: "center",
253
+ columnGap: 5
254
+ },
255
+ children: [/* @__PURE__ */ jsx("div", {
256
+ style: {
257
+ display: "inline-block",
258
+ width: 12,
259
+ height: 12
260
+ },
261
+ children: icon
262
+ }), children]
263
+ });
279
264
  }
280
265
 
281
- // src/toolbar/components/ImageZoomToolbar.tsx
282
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
283
- function ImageZoomToolbar({
284
- isHovered,
285
- imageSize,
286
- setImageSize
287
- }) {
288
- return /* @__PURE__ */ jsx8(ToolbarSection, { icon: /* @__PURE__ */ jsx8("astro-dev-toolbar-icon", { icon: "gear" }), children: !isHovered ? /* @__PURE__ */ jsx8(
289
- ZoomButton,
290
- {
291
- value: imageSize,
292
- imageSize,
293
- setImageSize
294
- }
295
- ) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
296
- /* @__PURE__ */ jsx8(
297
- ZoomButton,
298
- {
299
- value: 25,
300
- imageSize,
301
- setImageSize
302
- }
303
- ),
304
- /* @__PURE__ */ jsx8(
305
- ZoomButton,
306
- {
307
- value: 50,
308
- imageSize,
309
- setImageSize
310
- }
311
- ),
312
- /* @__PURE__ */ jsx8(
313
- ZoomButton,
314
- {
315
- value: 75,
316
- imageSize,
317
- setImageSize
318
- }
319
- ),
320
- /* @__PURE__ */ jsx8(
321
- ZoomButton,
322
- {
323
- value: 100,
324
- imageSize,
325
- setImageSize
326
- }
327
- )
328
- ] }) });
266
+ //#endregion
267
+ //#region src/toolbar/components/ImageZoomToolbar.tsx
268
+ function ImageZoomToolbar({ isHovered, imageSize, setImageSize }) {
269
+ return /* @__PURE__ */ jsx(ToolbarSection, {
270
+ icon: /* @__PURE__ */ jsx("astro-dev-toolbar-icon", { icon: "gear" }),
271
+ children: !isHovered ? /* @__PURE__ */ jsx(ZoomButton, {
272
+ value: imageSize,
273
+ imageSize,
274
+ setImageSize
275
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [
276
+ /* @__PURE__ */ jsx(ZoomButton, {
277
+ value: 25,
278
+ imageSize,
279
+ setImageSize
280
+ }),
281
+ /* @__PURE__ */ jsx(ZoomButton, {
282
+ value: 50,
283
+ imageSize,
284
+ setImageSize
285
+ }),
286
+ /* @__PURE__ */ jsx(ZoomButton, {
287
+ value: 75,
288
+ imageSize,
289
+ setImageSize
290
+ }),
291
+ /* @__PURE__ */ jsx(ZoomButton, {
292
+ value: 100,
293
+ imageSize,
294
+ setImageSize
295
+ })
296
+ ] })
297
+ });
329
298
  }
330
299
 
331
- // src/toolbar/components/CopyImageUrlButton.tsx
332
- import React2, {
333
- useState as useState2,
334
- useRef as useRef2,
335
- useEffect as useEffect2
336
- } from "react";
337
- import { jsx as jsx9 } from "react/jsx-runtime";
300
+ //#endregion
301
+ //#region src/toolbar/components/CopyImageUrlButton.tsx
338
302
  function CopyImageUrlButton() {
339
- const imageUrl = useImageURL();
340
- const [wasRecentlyClicked, setWasRecentlyClicked] = useState2(false);
341
- const checkTimer = useRef2(null);
342
- useEffect2(() => {
343
- if (wasRecentlyClicked && checkTimer.current == null) {
344
- checkTimer.current = setTimeout(() => {
345
- setWasRecentlyClicked(false);
346
- checkTimer.current = null;
347
- }, 3e3);
348
- }
349
- }, [wasRecentlyClicked]);
350
- const handleClick = React2.useCallback(
351
- (evt) => {
352
- void navigator.clipboard.writeText(imageUrl);
353
- setWasRecentlyClicked(true);
354
- evt.stopPropagation();
355
- evt.preventDefault();
356
- },
357
- [imageUrl]
358
- );
359
- return /* @__PURE__ */ jsx9(ToolbarSection, { icon: /* @__PURE__ */ jsx9("astro-dev-toolbar-icon", { icon: "copy" }), children: /* @__PURE__ */ jsx9("div", { style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx9(
360
- "astro-dev-toolbar-button",
361
- {
362
- size: "small",
363
- buttonStyle: "gray",
364
- onClick: handleClick,
365
- children: wasRecentlyClicked ? "Copied to clipboard" : "Copy image URL"
366
- }
367
- ) }) });
303
+ const imageUrl = useImageURL();
304
+ const [wasRecentlyClicked, setWasRecentlyClicked] = useState(false);
305
+ const checkTimer = useRef(null);
306
+ useEffect(() => {
307
+ if (wasRecentlyClicked && checkTimer.current == null) checkTimer.current = setTimeout(() => {
308
+ setWasRecentlyClicked(false);
309
+ checkTimer.current = null;
310
+ }, 3e3);
311
+ }, [wasRecentlyClicked]);
312
+ const handleClick = useCallback((evt) => {
313
+ navigator.clipboard.writeText(imageUrl);
314
+ setWasRecentlyClicked(true);
315
+ evt.stopPropagation();
316
+ evt.preventDefault();
317
+ }, [imageUrl]);
318
+ return /* @__PURE__ */ jsx(ToolbarSection, {
319
+ icon: /* @__PURE__ */ jsx("astro-dev-toolbar-icon", { icon: "copy" }),
320
+ children: /* @__PURE__ */ jsx("div", {
321
+ style: {
322
+ display: "flex",
323
+ alignItems: "center"
324
+ },
325
+ children: /* @__PURE__ */ jsx("astro-dev-toolbar-button", {
326
+ size: "small",
327
+ buttonStyle: "gray",
328
+ onClick: handleClick,
329
+ children: wasRecentlyClicked ? "Copied to clipboard" : "Copy image URL"
330
+ })
331
+ })
332
+ });
333
+ }
334
+
335
+ //#endregion
336
+ //#region src/toolbar/components/ImageSection.tsx
337
+ function ImageSection({ isHovered, handleLoadError }) {
338
+ const [imageSize, setImageSize] = useState(100);
339
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Image, {
340
+ imageSize,
341
+ handleLoadError
342
+ }), /* @__PURE__ */ jsxs("div", {
343
+ "data-testid": "image-section-toolbar",
344
+ style: {
345
+ display: "flex",
346
+ flexDirection: "row",
347
+ alignItems: "center",
348
+ columnGap: 15
349
+ },
350
+ children: [/* @__PURE__ */ jsx(CopyImageUrlButton, {}), /* @__PURE__ */ jsx(ImageZoomToolbar, {
351
+ isHovered,
352
+ imageSize,
353
+ setImageSize
354
+ })]
355
+ })] });
368
356
  }
369
357
 
370
- // src/toolbar/components/ImageSection.tsx
371
- import { useState as useState3 } from "react";
372
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
373
- function ImageSection({
374
- isHovered
375
- }) {
376
- const [imageSize, setImageSize] = useState3(100);
377
- return /* @__PURE__ */ jsxs6(Fragment3, { children: [
378
- /* @__PURE__ */ jsx10(Image, { imageSize }),
379
- /* @__PURE__ */ jsxs6(
380
- "div",
381
- {
382
- "data-testid": "image-section-toolbar",
383
- style: {
384
- display: "flex",
385
- flexDirection: "row",
386
- alignItems: "center",
387
- columnGap: 15
388
- },
389
- children: [
390
- /* @__PURE__ */ jsx10(CopyImageUrlButton, {}),
391
- /* @__PURE__ */ jsx10(
392
- ImageZoomToolbar,
393
- {
394
- isHovered,
395
- imageSize,
396
- setImageSize
397
- }
398
- )
399
- ]
400
- }
401
- )
402
- ] });
358
+ //#endregion
359
+ //#region src/toolbar/components/Error.tsx
360
+ function Error$1({ message, icon }) {
361
+ return /* @__PURE__ */ jsxs("div", {
362
+ style: {
363
+ display: "flex",
364
+ gap: 10,
365
+ alignItems: "center"
366
+ },
367
+ children: [
368
+ /* @__PURE__ */ jsx("astro-dev-toolbar-icon", {
369
+ style: {
370
+ width: 24,
371
+ height: 24
372
+ },
373
+ icon
374
+ }),
375
+ " ",
376
+ message
377
+ ]
378
+ });
403
379
  }
404
380
 
405
- // src/toolbar/components/ToolbarApp.tsx
406
- import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
381
+ //#endregion
382
+ //#region src/toolbar/components/getRelativeUrl.tsx
383
+ function getRelativeUrl(absoluteUrl) {
384
+ const url = new URL(absoluteUrl);
385
+ return url.pathname;
386
+ }
387
+
388
+ //#endregion
389
+ //#region src/toolbar/components/ToolbarApp.tsx
407
390
  function ToolbarApp() {
408
- const [isImageDetailsHovered, setIsImageDetailsHovered] = useState4(false);
409
- const imageDetailsRef = useHoverState(
410
- setIsImageDetailsHovered
411
- );
412
- const imageUrl = useImageURLIfAvailable();
413
- if (imageUrl == null) {
414
- return /* @__PURE__ */ jsxs7("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [
415
- /* @__PURE__ */ jsx11(
416
- "astro-dev-toolbar-icon",
417
- {
418
- style: { width: 24, height: 24 },
419
- icon: "warning"
420
- }
421
- ),
422
- " ",
423
- "No Open Graph image found on this page"
424
- ] });
425
- }
426
- return /* @__PURE__ */ jsxs7(Fragment4, { children: [
427
- /* @__PURE__ */ jsxs7("details", { open: true, className: "image", ref: imageDetailsRef, children: [
428
- /* @__PURE__ */ jsx11(Summary, { children: "Image" }),
429
- /* @__PURE__ */ jsx11(ImageSection, { isHovered: isImageDetailsHovered })
430
- ] }),
431
- /* @__PURE__ */ jsxs7("details", { children: [
432
- /* @__PURE__ */ jsx11(Summary, { children: "Meta Tags" }),
433
- /* @__PURE__ */ jsx11(MetaTags, {})
434
- ] })
435
- ] });
391
+ const [isImageDetailsHovered, setIsImageDetailsHovered] = useState(false);
392
+ const imageDetailsRef = useHoverState(setIsImageDetailsHovered);
393
+ const imageUrl = useImageURLIfAvailable();
394
+ const [imageLoadStatus, setImageLoadStatus] = useState("pending");
395
+ if (imageUrl == null) return /* @__PURE__ */ jsx(Error$1, {
396
+ icon: "warning",
397
+ message: "No Open Graph image found on this page"
398
+ });
399
+ else if (imageLoadStatus === "error") return /* @__PURE__ */ jsx(Error$1, {
400
+ icon: "bug",
401
+ message: `Error loading image at ${getRelativeUrl(imageUrl)}`
402
+ });
403
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("details", {
404
+ open: true,
405
+ className: "image",
406
+ ref: imageDetailsRef,
407
+ children: [/* @__PURE__ */ jsx(Summary, { children: "Image" }), /* @__PURE__ */ jsx(ImageSection, {
408
+ isHovered: isImageDetailsHovered,
409
+ handleLoadError: () => setImageLoadStatus("error")
410
+ })]
411
+ }), /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx(Summary, { children: "Meta Tags" }), /* @__PURE__ */ jsx(MetaTags, {})] })] });
436
412
  }
437
413
 
438
- // src/toolbar/components/ToolbarAppWindow.tsx
439
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
414
+ //#endregion
415
+ //#region src/toolbar/components/ToolbarAppWindow.tsx
440
416
  function ToolbarAppWindow() {
441
- return /* @__PURE__ */ jsxs8("astro-dev-toolbar-window", { children: [
442
- /* @__PURE__ */ jsx12("style", { children: styles }),
443
- /* @__PURE__ */ jsx12(ToolbarApp, {})
444
- ] });
417
+ return /* @__PURE__ */ jsxs("astro-dev-toolbar-window", { children: [/* @__PURE__ */ jsx("style", { children: styles }), /* @__PURE__ */ jsx(ToolbarApp, {})] });
445
418
  }
446
419
 
447
- // src/toolbar/index.tsx
448
- import { jsx as jsx13 } from "react/jsx-runtime";
449
- var SESSION_KEY_OPEN = "@altano/astro-opengraph/toolbar:is-open";
450
- var toolbar_default = defineToolbarApp({
451
- init(canvas, app) {
452
- const root = createRoot(canvas);
453
- app.onToggled((event) => {
454
- if (event.state) {
455
- sessionStorage.setItem(SESSION_KEY_OPEN, "true");
456
- root.render(/* @__PURE__ */ jsx13(ToolbarAppWindow, {}));
457
- } else {
458
- sessionStorage.removeItem(SESSION_KEY_OPEN);
459
- }
460
- });
461
- app.toggleNotification({
462
- state: document.querySelector('meta[property="og:image"]') != null,
463
- level: "info"
464
- });
465
- if (sessionStorage.getItem(SESSION_KEY_OPEN) != null) {
466
- app.toggleState({ state: true });
467
- }
468
- }
469
- });
470
- export {
471
- toolbar_default as default
472
- };
420
+ //#endregion
421
+ //#region src/toolbar/index.tsx
422
+ const SESSION_KEY_OPEN = "@altano/astro-opengraph/toolbar:is-open";
423
+ const app = defineToolbarApp({ init(canvas, app$1) {
424
+ app$1.onToggled((event) => {
425
+ if (event.state) {
426
+ sessionStorage.setItem(SESSION_KEY_OPEN, "true");
427
+ render(/* @__PURE__ */ jsx(ToolbarAppWindow, {}), canvas);
428
+ } else sessionStorage.removeItem(SESSION_KEY_OPEN);
429
+ });
430
+ app$1.toggleNotification({
431
+ state: document.querySelector("meta[property=\"og:image\"]") != null,
432
+ level: "info"
433
+ });
434
+ if (sessionStorage.getItem(SESSION_KEY_OPEN) != null) app$1.toggleState({ state: true });
435
+ } });
436
+ var toolbar_default = app;
437
+
438
+ //#endregion
439
+ export { toolbar_default as default };
440
+ //# sourceMappingURL=index.js.map