@jamwidgets/astro 0.6.1 → 0.6.4
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/package.json +2 -2
- package/src/Announcements.astro +25 -18
- package/src/Embed.astro +8 -14
- package/src/Feedback.astro +1 -10
- package/src/Poll.astro +8 -14
- package/src/Reactions.astro +9 -6
- package/src/Subscribe.astro +1 -10
- package/src/Views.astro +1 -10
- package/src/Waitlist.astro +1 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jamwidgets/astro",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Astro components and content loaders for Jamwidgets",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
],
|
|
61
61
|
"license": "MIT",
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@jamwidgets/core": "^0.5.
|
|
63
|
+
"@jamwidgets/core": "^0.5.3"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"astro": "^5.9.0 || ^6.0.0 || ^7.0.0"
|
package/src/Announcements.astro
CHANGED
|
@@ -54,16 +54,7 @@ import Theme from "./Theme.astro";
|
|
|
54
54
|
isDismissible: boolean;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
59
|
-
function getVisitorId(): string {
|
|
60
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
61
|
-
if (!id) {
|
|
62
|
-
id = crypto.randomUUID();
|
|
63
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
64
|
-
}
|
|
65
|
-
return id;
|
|
66
|
-
}
|
|
57
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
67
58
|
|
|
68
59
|
document.querySelectorAll("[data-jamwidgets-announcements]").forEach((container) => {
|
|
69
60
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
|
@@ -89,6 +80,16 @@ import Theme from "./Theme.astro";
|
|
|
89
80
|
}
|
|
90
81
|
}
|
|
91
82
|
|
|
83
|
+
function safeLinkUrl(value?: string): string | null {
|
|
84
|
+
if (!value) return null;
|
|
85
|
+
try {
|
|
86
|
+
const url = new URL(value, window.location.href);
|
|
87
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url.href : null;
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
92
93
|
function renderAnnouncements(announcements: Announcement[]) {
|
|
93
94
|
container.innerHTML = "";
|
|
94
95
|
|
|
@@ -97,25 +98,31 @@ import Theme from "./Theme.astro";
|
|
|
97
98
|
el.className = `jamwidgets-announcement jamwidgets-announcement-${announcement.announcementType}`;
|
|
98
99
|
el.dataset.announcementId = announcement.id;
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
const contentEl = document.createElement("span");
|
|
102
|
+
contentEl.className = "jamwidgets-announcement-content";
|
|
103
|
+
contentEl.textContent = announcement.content;
|
|
104
|
+
el.append(contentEl);
|
|
105
|
+
|
|
106
|
+
const linkUrl = safeLinkUrl(announcement.linkUrl);
|
|
107
|
+
if (linkUrl) {
|
|
108
|
+
const link = document.createElement("a");
|
|
109
|
+
link.className = "jamwidgets-announcement-link";
|
|
110
|
+
link.href = linkUrl;
|
|
111
|
+
link.textContent = announcement.linkText || "Learn more";
|
|
112
|
+
el.append(" ", link);
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
if (announcement.isDismissible) {
|
|
107
|
-
|
|
116
|
+
el.insertAdjacentHTML("beforeend", `
|
|
108
117
|
<button type="button" class="jamwidgets-announcement-dismiss" aria-label="Dismiss">
|
|
109
118
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
110
119
|
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
111
120
|
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
112
121
|
</svg>
|
|
113
122
|
</button>
|
|
114
|
-
|
|
123
|
+
`);
|
|
115
124
|
}
|
|
116
125
|
|
|
117
|
-
el.innerHTML = content;
|
|
118
|
-
|
|
119
126
|
// Handle dismiss
|
|
120
127
|
const dismissBtn = el.querySelector(".jamwidgets-announcement-dismiss");
|
|
121
128
|
dismissBtn?.addEventListener("click", async () => {
|
package/src/Embed.astro
CHANGED
|
@@ -64,16 +64,7 @@ import Theme from "./Theme.astro";
|
|
|
64
64
|
userVotes?: string[];
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
69
|
-
function getVisitorId(): string {
|
|
70
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
71
|
-
if (!id) {
|
|
72
|
-
id = crypto.randomUUID();
|
|
73
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
74
|
-
}
|
|
75
|
-
return id;
|
|
76
|
-
}
|
|
67
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
77
68
|
|
|
78
69
|
class JamwidgetsEmbed extends HTMLElement {
|
|
79
70
|
connectedCallback() {
|
|
@@ -188,11 +179,13 @@ import Theme from "./Theme.astro";
|
|
|
188
179
|
const inputType = poll!.settings.multiSelect ? "checkbox" : "radio";
|
|
189
180
|
optionEl.innerHTML = `
|
|
190
181
|
<label class="jamwidgets-poll-label ${isSelected ? "jamwidgets-selected" : ""}">
|
|
191
|
-
<input type="${inputType}"
|
|
192
|
-
<span class="jamwidgets-poll-text"
|
|
182
|
+
<input type="${inputType}" ${isSelected ? "checked" : ""} />
|
|
183
|
+
<span class="jamwidgets-poll-text"></span>
|
|
193
184
|
</label>
|
|
194
185
|
`;
|
|
195
186
|
const input = optionEl.querySelector("input")!;
|
|
187
|
+
input.name = `poll-${poll!.id}`;
|
|
188
|
+
input.value = option.id;
|
|
196
189
|
input.addEventListener("change", () => {
|
|
197
190
|
if (poll!.settings.multiSelect) {
|
|
198
191
|
if (input.checked) {
|
|
@@ -215,7 +208,7 @@ import Theme from "./Theme.astro";
|
|
|
215
208
|
optionEl.innerHTML = `
|
|
216
209
|
<div class="jamwidgets-poll-result ${isSelected ? "jamwidgets-voted" : ""}">
|
|
217
210
|
<div class="jamwidgets-poll-bar" style="width: ${percent}%"></div>
|
|
218
|
-
<span class="jamwidgets-poll-text"
|
|
211
|
+
<span class="jamwidgets-poll-text"></span>
|
|
219
212
|
<span class="jamwidgets-poll-percent">${percent}%</span>
|
|
220
213
|
</div>
|
|
221
214
|
`;
|
|
@@ -223,10 +216,11 @@ import Theme from "./Theme.astro";
|
|
|
223
216
|
// Show without results (voted but results hidden)
|
|
224
217
|
optionEl.innerHTML = `
|
|
225
218
|
<div class="jamwidgets-poll-result jamwidgets-no-results ${isSelected ? "jamwidgets-voted" : ""}">
|
|
226
|
-
<span class="jamwidgets-poll-text"
|
|
219
|
+
<span class="jamwidgets-poll-text"></span>
|
|
227
220
|
</div>
|
|
228
221
|
`;
|
|
229
222
|
}
|
|
223
|
+
optionEl.querySelector(".jamwidgets-poll-text")!.textContent = option.text;
|
|
230
224
|
optionsEl.appendChild(optionEl);
|
|
231
225
|
});
|
|
232
226
|
|
package/src/Feedback.astro
CHANGED
|
@@ -90,16 +90,7 @@ import Theme from "./Theme.astro";
|
|
|
90
90
|
</div>
|
|
91
91
|
|
|
92
92
|
<script>
|
|
93
|
-
|
|
94
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
95
|
-
function getVisitorId(): string {
|
|
96
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
97
|
-
if (!id) {
|
|
98
|
-
id = crypto.randomUUID();
|
|
99
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
100
|
-
}
|
|
101
|
-
return id;
|
|
102
|
-
}
|
|
93
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
103
94
|
|
|
104
95
|
document.querySelectorAll("[data-jamwidgets-feedback]").forEach((container) => {
|
|
105
96
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
package/src/Poll.astro
CHANGED
|
@@ -89,16 +89,7 @@ import Theme from "./Theme.astro";
|
|
|
89
89
|
userVotes?: string[];
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
94
|
-
function getVisitorId(): string {
|
|
95
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
96
|
-
if (!id) {
|
|
97
|
-
id = crypto.randomUUID();
|
|
98
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
99
|
-
}
|
|
100
|
-
return id;
|
|
101
|
-
}
|
|
92
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
102
93
|
|
|
103
94
|
document.querySelectorAll("[data-jamwidgets-poll]").forEach((container) => {
|
|
104
95
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
|
@@ -172,11 +163,13 @@ import Theme from "./Theme.astro";
|
|
|
172
163
|
const inputType = poll!.settings.multiSelect ? "checkbox" : "radio";
|
|
173
164
|
optionEl.innerHTML = `
|
|
174
165
|
<label class="jamwidgets-poll-label ${isSelected ? "jamwidgets-selected" : ""}">
|
|
175
|
-
<input type="${inputType}"
|
|
176
|
-
<span class="jamwidgets-poll-text"
|
|
166
|
+
<input type="${inputType}" ${isSelected ? "checked" : ""} />
|
|
167
|
+
<span class="jamwidgets-poll-text"></span>
|
|
177
168
|
</label>
|
|
178
169
|
`;
|
|
179
170
|
const input = optionEl.querySelector("input")!;
|
|
171
|
+
input.name = `poll-${poll!.id}`;
|
|
172
|
+
input.value = option.id;
|
|
180
173
|
input.addEventListener("change", () => {
|
|
181
174
|
if (poll!.settings.multiSelect) {
|
|
182
175
|
if (input.checked) {
|
|
@@ -199,7 +192,7 @@ import Theme from "./Theme.astro";
|
|
|
199
192
|
optionEl.innerHTML = `
|
|
200
193
|
<div class="jamwidgets-poll-result ${isSelected ? "jamwidgets-voted" : ""}">
|
|
201
194
|
<div class="jamwidgets-poll-bar" style="width: ${percent}%"></div>
|
|
202
|
-
<span class="jamwidgets-poll-text"
|
|
195
|
+
<span class="jamwidgets-poll-text"></span>
|
|
203
196
|
<span class="jamwidgets-poll-percent">${percent}%</span>
|
|
204
197
|
</div>
|
|
205
198
|
`;
|
|
@@ -207,10 +200,11 @@ import Theme from "./Theme.astro";
|
|
|
207
200
|
// Show without results (voted but results hidden)
|
|
208
201
|
optionEl.innerHTML = `
|
|
209
202
|
<div class="jamwidgets-poll-result jamwidgets-no-results ${isSelected ? "jamwidgets-voted" : ""}">
|
|
210
|
-
<span class="jamwidgets-poll-text"
|
|
203
|
+
<span class="jamwidgets-poll-text"></span>
|
|
211
204
|
</div>
|
|
212
205
|
`;
|
|
213
206
|
}
|
|
207
|
+
optionEl.querySelector(".jamwidgets-poll-text")!.textContent = option.text;
|
|
214
208
|
optionsEl.appendChild(optionEl);
|
|
215
209
|
});
|
|
216
210
|
|
package/src/Reactions.astro
CHANGED
|
@@ -106,11 +106,14 @@ import Theme from "./Theme.astro";
|
|
|
106
106
|
"X-Jamwidgets-Visitor": visitorId,
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
// Track which reactions the user has made (stored in localStorage)
|
|
110
109
|
const storageKey = `jamwidgets-reactions-${pageId}`;
|
|
111
|
-
const userReactions = new Set<string>(
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const userReactions = new Set<string>();
|
|
111
|
+
try {
|
|
112
|
+
const stored = JSON.parse(localStorage.getItem(storageKey) || "[]");
|
|
113
|
+
if (Array.isArray(stored)) {
|
|
114
|
+
for (const type of stored) if (typeof type === "string") userReactions.add(type);
|
|
115
|
+
}
|
|
116
|
+
} catch {}
|
|
114
117
|
|
|
115
118
|
// Apply initial "reacted" state
|
|
116
119
|
container.querySelectorAll(".jamwidgets-reaction-btn").forEach((btn) => {
|
|
@@ -134,7 +137,7 @@ import Theme from "./Theme.astro";
|
|
|
134
137
|
|
|
135
138
|
// Sync with server's user reactions
|
|
136
139
|
serverUserReactions.forEach((type: string) => userReactions.add(type));
|
|
137
|
-
localStorage.setItem(storageKey, JSON.stringify([...userReactions]));
|
|
140
|
+
try { localStorage.setItem(storageKey, JSON.stringify([...userReactions])); } catch {}
|
|
138
141
|
|
|
139
142
|
container.querySelectorAll(".jamwidgets-reaction-btn").forEach((btn) => {
|
|
140
143
|
const type = (btn as HTMLElement).dataset.reactionType;
|
|
@@ -204,7 +207,7 @@ import Theme from "./Theme.astro";
|
|
|
204
207
|
}),
|
|
205
208
|
);
|
|
206
209
|
}
|
|
207
|
-
localStorage.setItem(storageKey, JSON.stringify([...userReactions]));
|
|
210
|
+
try { localStorage.setItem(storageKey, JSON.stringify([...userReactions])); } catch {}
|
|
208
211
|
} catch (e) {
|
|
209
212
|
console.error(isReacted ? "Failed to remove reaction:" : "Failed to add reaction:", e);
|
|
210
213
|
} finally {
|
package/src/Subscribe.astro
CHANGED
|
@@ -93,16 +93,7 @@ import Theme from "./Theme.astro";
|
|
|
93
93
|
message: string;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
98
|
-
function getVisitorId(): string {
|
|
99
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
100
|
-
if (!id) {
|
|
101
|
-
id = crypto.randomUUID();
|
|
102
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
103
|
-
}
|
|
104
|
-
return id;
|
|
105
|
-
}
|
|
96
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
106
97
|
|
|
107
98
|
document.querySelectorAll("[data-jamwidgets-subscribe]").forEach((form) => {
|
|
108
99
|
form.addEventListener("submit", async (e) => {
|
package/src/Views.astro
CHANGED
|
@@ -65,16 +65,7 @@ import Theme from "./Theme.astro";
|
|
|
65
65
|
</div>
|
|
66
66
|
|
|
67
67
|
<script>
|
|
68
|
-
|
|
69
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
70
|
-
function getVisitorId(): string {
|
|
71
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
72
|
-
if (!id) {
|
|
73
|
-
id = crypto.randomUUID();
|
|
74
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
75
|
-
}
|
|
76
|
-
return id;
|
|
77
|
-
}
|
|
68
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
78
69
|
|
|
79
70
|
document.querySelectorAll("[data-jamwidgets-views]").forEach((container) => {
|
|
80
71
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
package/src/Waitlist.astro
CHANGED
|
@@ -71,16 +71,7 @@ import Theme from "./Theme.astro";
|
|
|
71
71
|
</div>
|
|
72
72
|
|
|
73
73
|
<script>
|
|
74
|
-
|
|
75
|
-
const VISITOR_KEY = "jamwidgets_visitor_id";
|
|
76
|
-
function getVisitorId(): string {
|
|
77
|
-
let id = localStorage.getItem(VISITOR_KEY);
|
|
78
|
-
if (!id) {
|
|
79
|
-
id = crypto.randomUUID();
|
|
80
|
-
localStorage.setItem(VISITOR_KEY, id);
|
|
81
|
-
}
|
|
82
|
-
return id;
|
|
83
|
-
}
|
|
74
|
+
import { getVisitorId } from "@jamwidgets/core";
|
|
84
75
|
|
|
85
76
|
document.querySelectorAll("[data-jamwidgets-waitlist]").forEach((container) => {
|
|
86
77
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|