@jamwidgets/astro 0.6.3 → 0.6.6
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/README.md +5 -0
- package/package.json +2 -2
- package/src/Announcements.astro +2 -10
- package/src/Comments.astro +1 -0
- package/src/Embed.astro +3 -12
- package/src/Feedback.astro +6 -19
- package/src/Form.astro +3 -3
- package/src/Poll.astro +3 -12
- package/src/Reactions.astro +10 -6
- package/src/Subscribe.astro +7 -12
- package/src/SubscribeForm.astro +2 -3
- package/src/Theme.astro +7 -0
- package/src/Views.astro +2 -10
- package/src/Waitlist.astro +8 -12
package/README.md
CHANGED
|
@@ -234,6 +234,7 @@ import Subscribe from "@jamwidgets/astro/Subscribe";
|
|
|
234
234
|
- `endpoint` - Base URL (default: `https://jamwidgets.com`)
|
|
235
235
|
- `buttonText` - Submit button text (default: `'Subscribe'`)
|
|
236
236
|
- `placeholder` - Email input placeholder
|
|
237
|
+
- `label` - Accessible name for the email input (default: `'Email address'`)
|
|
237
238
|
- `successMessage` - Custom success message
|
|
238
239
|
- `theme` - `'light'` | `'dark'` | `'auto'` (default: `'light'`)
|
|
239
240
|
- `class` - Additional CSS class
|
|
@@ -317,6 +318,10 @@ Set semantic CSS custom properties on a wrapper or the widget itself to match yo
|
|
|
317
318
|
|
|
318
319
|
Status colors can be customized with `--jamwidgets-color-success`, `--jamwidgets-color-error`, and `--jamwidgets-color-notice`. Components adapt to their container width, so subscribe, waitlist, comments, and feedback controls stack when embedded in a narrow column.
|
|
319
320
|
|
|
321
|
+
### Cascade layers and Tailwind
|
|
322
|
+
|
|
323
|
+
Widget styles live in a `jamwidgets` cascade layer. Every component declares the order `@layer theme, base, components, utilities, jamwidgets;` before its rules, so the widgets rank above Tailwind v4's layers (including Preflight in `base`) whichever stylesheet the browser sees first. Your unlayered CSS still overrides the widgets. If your site declares its own layer order, keep `jamwidgets` after `base` or Preflight will reset the widgets' padding, borders and buttons.
|
|
324
|
+
|
|
320
325
|
## License
|
|
321
326
|
|
|
322
327
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jamwidgets/astro",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
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.
|
|
63
|
+
"@jamwidgets/core": "^0.6.0"
|
|
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;
|
|
@@ -160,6 +151,7 @@ import Theme from "./Theme.astro";
|
|
|
160
151
|
</script>
|
|
161
152
|
|
|
162
153
|
<style is:global>
|
|
154
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
163
155
|
@layer jamwidgets {
|
|
164
156
|
.jamwidgets-announcements {
|
|
165
157
|
display: flex;
|
package/src/Comments.astro
CHANGED
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 { apiError, getVisitorId } from "@jamwidgets/core";
|
|
77
68
|
|
|
78
69
|
class JamwidgetsEmbed extends HTMLElement {
|
|
79
70
|
connectedCallback() {
|
|
@@ -280,8 +271,7 @@ import Theme from "./Theme.astro";
|
|
|
280
271
|
});
|
|
281
272
|
|
|
282
273
|
if (!response.ok) {
|
|
283
|
-
|
|
284
|
-
throw new Error(error.message || "Failed to vote");
|
|
274
|
+
throw await apiError(response, "Failed to vote");
|
|
285
275
|
}
|
|
286
276
|
|
|
287
277
|
const data = await response.json();
|
|
@@ -321,6 +311,7 @@ import Theme from "./Theme.astro";
|
|
|
321
311
|
</script>
|
|
322
312
|
|
|
323
313
|
<style is:global>
|
|
314
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
324
315
|
@layer jamwidgets {
|
|
325
316
|
.jamwidgets-poll {
|
|
326
317
|
font-family: inherit;
|
package/src/Feedback.astro
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Jamwidgets Feedback Component
|
|
4
4
|
*
|
|
5
5
|
* Displays a feedback form for collecting user suggestions.
|
|
6
|
-
* Supports
|
|
6
|
+
* Supports the API's feedback types: feature, bug and general.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* <Feedback siteKey={import.meta.env.JAMWIDGETS_SITE_KEY} />
|
|
@@ -62,11 +62,7 @@ import Theme from "./Theme.astro";
|
|
|
62
62
|
<span>Bug</span>
|
|
63
63
|
</label>
|
|
64
64
|
<label class="jamwidgets-feedback-type">
|
|
65
|
-
<input type="radio" name="feedbackType" value="
|
|
66
|
-
<span>Improvement</span>
|
|
67
|
-
</label>
|
|
68
|
-
<label class="jamwidgets-feedback-type">
|
|
69
|
-
<input type="radio" name="feedbackType" value="other" />
|
|
65
|
+
<input type="radio" name="feedbackType" value="general" />
|
|
70
66
|
<span>Other</span>
|
|
71
67
|
</label>
|
|
72
68
|
</div>
|
|
@@ -90,16 +86,7 @@ import Theme from "./Theme.astro";
|
|
|
90
86
|
</div>
|
|
91
87
|
|
|
92
88
|
<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
|
-
}
|
|
89
|
+
import { apiError, getVisitorId } from "@jamwidgets/core";
|
|
103
90
|
|
|
104
91
|
document.querySelectorAll("[data-jamwidgets-feedback]").forEach((container) => {
|
|
105
92
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
|
@@ -126,7 +113,7 @@ import Theme from "./Theme.astro";
|
|
|
126
113
|
if (!content) return;
|
|
127
114
|
|
|
128
115
|
const typeInput = form.querySelector('input[name="feedbackType"]:checked') as HTMLInputElement | null;
|
|
129
|
-
const feedbackType = typeInput?.value || "
|
|
116
|
+
const feedbackType = typeInput?.value || "general";
|
|
130
117
|
|
|
131
118
|
submitBtn.disabled = true;
|
|
132
119
|
submitBtn.textContent = "Sending...";
|
|
@@ -141,8 +128,7 @@ import Theme from "./Theme.astro";
|
|
|
141
128
|
});
|
|
142
129
|
|
|
143
130
|
if (!response.ok) {
|
|
144
|
-
|
|
145
|
-
throw new Error(error.message || "Failed to submit feedback");
|
|
131
|
+
throw await apiError(response, "Failed to submit feedback");
|
|
146
132
|
}
|
|
147
133
|
|
|
148
134
|
textarea.value = "";
|
|
@@ -172,6 +158,7 @@ import Theme from "./Theme.astro";
|
|
|
172
158
|
</script>
|
|
173
159
|
|
|
174
160
|
<style is:global>
|
|
161
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
175
162
|
@layer jamwidgets {
|
|
176
163
|
.jamwidgets-feedback {
|
|
177
164
|
font-family: inherit;
|
package/src/Form.astro
CHANGED
|
@@ -67,7 +67,7 @@ import Theme from "./Theme.astro";
|
|
|
67
67
|
</form>
|
|
68
68
|
|
|
69
69
|
<script>
|
|
70
|
-
import { generateUUID, getAttributionHeaders, getVisitorId } from "@jamwidgets/core";
|
|
70
|
+
import { apiError, generateUUID, getAttributionHeaders, getVisitorId } from "@jamwidgets/core";
|
|
71
71
|
|
|
72
72
|
interface FormSubmitResponse {
|
|
73
73
|
success: boolean;
|
|
@@ -145,8 +145,7 @@ import Theme from "./Theme.astro";
|
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
if (!response.ok) {
|
|
148
|
-
|
|
149
|
-
throw new Error(errorText || "Submission failed");
|
|
148
|
+
throw await apiError(response, "Submission failed");
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
const result: FormSubmitResponse = await response.json();
|
|
@@ -193,6 +192,7 @@ import Theme from "./Theme.astro";
|
|
|
193
192
|
</script>
|
|
194
193
|
|
|
195
194
|
<style is:global>
|
|
195
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
196
196
|
@layer jamwidgets {
|
|
197
197
|
.jamwidgets-form-message {
|
|
198
198
|
margin-top: 1rem;
|
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 { apiError, getVisitorId } from "@jamwidgets/core";
|
|
102
93
|
|
|
103
94
|
document.querySelectorAll("[data-jamwidgets-poll]").forEach((container) => {
|
|
104
95
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
|
@@ -264,8 +255,7 @@ import Theme from "./Theme.astro";
|
|
|
264
255
|
});
|
|
265
256
|
|
|
266
257
|
if (!response.ok) {
|
|
267
|
-
|
|
268
|
-
throw new Error(error.message || "Failed to vote");
|
|
258
|
+
throw await apiError(response, "Failed to vote");
|
|
269
259
|
}
|
|
270
260
|
|
|
271
261
|
const data = await response.json();
|
|
@@ -302,6 +292,7 @@ import Theme from "./Theme.astro";
|
|
|
302
292
|
</script>
|
|
303
293
|
|
|
304
294
|
<style is:global>
|
|
295
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
305
296
|
@layer jamwidgets {
|
|
306
297
|
.jamwidgets-poll {
|
|
307
298
|
font-family: inherit;
|
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 {
|
|
@@ -218,6 +221,7 @@ import Theme from "./Theme.astro";
|
|
|
218
221
|
</script>
|
|
219
222
|
|
|
220
223
|
<style is:global>
|
|
224
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
221
225
|
@layer jamwidgets {
|
|
222
226
|
.jamwidgets-reactions {
|
|
223
227
|
display: flex;
|
package/src/Subscribe.astro
CHANGED
|
@@ -26,6 +26,8 @@ interface Props {
|
|
|
26
26
|
buttonText?: string;
|
|
27
27
|
/** Email input placeholder (default: 'your@email.com') */
|
|
28
28
|
placeholder?: string;
|
|
29
|
+
/** Accessible name for the email input (default: 'Email address') */
|
|
30
|
+
label?: string;
|
|
29
31
|
/** Success message override (default: uses server response) */
|
|
30
32
|
successMessage?: string;
|
|
31
33
|
/** Theme preset. Defaults to inheriting the host page. */
|
|
@@ -42,6 +44,7 @@ const {
|
|
|
42
44
|
endpoint = DEFAULT_ENDPOINT,
|
|
43
45
|
buttonText = "Subscribe",
|
|
44
46
|
placeholder = "your@email.com",
|
|
47
|
+
label = "Email address",
|
|
45
48
|
successMessage,
|
|
46
49
|
theme = "inherit",
|
|
47
50
|
class: className = "",
|
|
@@ -68,6 +71,7 @@ import Theme from "./Theme.astro";
|
|
|
68
71
|
name="email"
|
|
69
72
|
required
|
|
70
73
|
placeholder={placeholder}
|
|
74
|
+
aria-label={label}
|
|
71
75
|
class="jamwidgets-subscribe-input"
|
|
72
76
|
autocomplete="email"
|
|
73
77
|
/>
|
|
@@ -93,16 +97,7 @@ import Theme from "./Theme.astro";
|
|
|
93
97
|
message: string;
|
|
94
98
|
}
|
|
95
99
|
|
|
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
|
-
}
|
|
100
|
+
import { apiError, getVisitorId } from "@jamwidgets/core";
|
|
106
101
|
|
|
107
102
|
document.querySelectorAll("[data-jamwidgets-subscribe]").forEach((form) => {
|
|
108
103
|
form.addEventListener("submit", async (e) => {
|
|
@@ -150,8 +145,7 @@ import Theme from "./Theme.astro";
|
|
|
150
145
|
});
|
|
151
146
|
|
|
152
147
|
if (!response.ok) {
|
|
153
|
-
|
|
154
|
-
throw new Error(errorText || "Subscription failed");
|
|
148
|
+
throw await apiError(response, "Subscription failed");
|
|
155
149
|
}
|
|
156
150
|
|
|
157
151
|
const result: SubscribeResponse = await response.json();
|
|
@@ -199,6 +193,7 @@ import Theme from "./Theme.astro";
|
|
|
199
193
|
</script>
|
|
200
194
|
|
|
201
195
|
<style is:global>
|
|
196
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
202
197
|
@layer jamwidgets {
|
|
203
198
|
.jamwidgets-subscribe {
|
|
204
199
|
position: relative;
|
package/src/SubscribeForm.astro
CHANGED
|
@@ -71,7 +71,7 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
71
71
|
</form>
|
|
72
72
|
|
|
73
73
|
<script>
|
|
74
|
-
import { getAttributionHeaders, getVisitorId } from "@jamwidgets/core";
|
|
74
|
+
import { apiError, getAttributionHeaders, getVisitorId } from "@jamwidgets/core";
|
|
75
75
|
|
|
76
76
|
interface SubscribeResponse {
|
|
77
77
|
success: boolean;
|
|
@@ -114,8 +114,7 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
if (!response.ok) {
|
|
117
|
-
|
|
118
|
-
throw new Error(errorText || "Subscription failed");
|
|
117
|
+
throw await apiError(response, "Subscription failed");
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
const result: SubscribeResponse = await response.json();
|
package/src/Theme.astro
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
<style is:global>
|
|
2
|
+
/* Whichever stylesheet names a layer first fixes its order. If these widget
|
|
3
|
+
styles load before a Tailwind site's CSS, `jamwidgets` would otherwise
|
|
4
|
+
become the lowest layer and Tailwind's base reset would strip widget
|
|
5
|
+
input borders. Naming Tailwind's layers first, and `jamwidgets` last,
|
|
6
|
+
gives the same order whichever CSS loads first. Every widget repeats
|
|
7
|
+
this statement; unlayered site CSS still wins. */
|
|
8
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
2
9
|
@layer jamwidgets {
|
|
3
10
|
:where(
|
|
4
11
|
.jamwidgets-announcements,
|
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;
|
|
@@ -158,6 +149,7 @@ import Theme from "./Theme.astro";
|
|
|
158
149
|
</script>
|
|
159
150
|
|
|
160
151
|
<style is:global>
|
|
152
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
161
153
|
@layer jamwidgets {
|
|
162
154
|
.jamwidgets-views {
|
|
163
155
|
display: inline-flex;
|
package/src/Waitlist.astro
CHANGED
|
@@ -17,6 +17,8 @@ interface Props {
|
|
|
17
17
|
theme?: "inherit" | "light" | "dark" | "auto";
|
|
18
18
|
/** Placeholder text for the email input (default: 'Enter your email') */
|
|
19
19
|
placeholder?: string;
|
|
20
|
+
/** Accessible name for the email input (default: 'Email address') */
|
|
21
|
+
label?: string;
|
|
20
22
|
/** Button text (default: 'Join Waitlist') */
|
|
21
23
|
buttonText?: string;
|
|
22
24
|
/** Success message (default: "You're on the list!") */
|
|
@@ -33,6 +35,7 @@ const {
|
|
|
33
35
|
endpoint = DEFAULT_ENDPOINT,
|
|
34
36
|
theme = "inherit",
|
|
35
37
|
placeholder = "Enter your email",
|
|
38
|
+
label = "Email address",
|
|
36
39
|
buttonText = "Join Waitlist",
|
|
37
40
|
successMessage = "You're on the list!",
|
|
38
41
|
class: className = "",
|
|
@@ -59,6 +62,8 @@ import Theme from "./Theme.astro";
|
|
|
59
62
|
name="email"
|
|
60
63
|
class="jamwidgets-waitlist-input"
|
|
61
64
|
placeholder={placeholder}
|
|
65
|
+
aria-label={label}
|
|
66
|
+
autocomplete="email"
|
|
62
67
|
required
|
|
63
68
|
/>
|
|
64
69
|
<button type="submit" class="jamwidgets-waitlist-submit">
|
|
@@ -71,16 +76,7 @@ import Theme from "./Theme.astro";
|
|
|
71
76
|
</div>
|
|
72
77
|
|
|
73
78
|
<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
|
-
}
|
|
79
|
+
import { apiError, getVisitorId } from "@jamwidgets/core";
|
|
84
80
|
|
|
85
81
|
document.querySelectorAll("[data-jamwidgets-waitlist]").forEach((container) => {
|
|
86
82
|
const endpoint = (container as HTMLElement).dataset.endpoint;
|
|
@@ -120,8 +116,7 @@ import Theme from "./Theme.astro";
|
|
|
120
116
|
});
|
|
121
117
|
|
|
122
118
|
if (!response.ok) {
|
|
123
|
-
|
|
124
|
-
throw new Error(error.message || "Failed to join waitlist");
|
|
119
|
+
throw await apiError(response, "Failed to join waitlist");
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
// Hide form and show success
|
|
@@ -152,6 +147,7 @@ import Theme from "./Theme.astro";
|
|
|
152
147
|
</script>
|
|
153
148
|
|
|
154
149
|
<style is:global>
|
|
150
|
+
@layer theme, base, components, utilities, jamwidgets;
|
|
155
151
|
@layer jamwidgets {
|
|
156
152
|
.jamwidgets-waitlist {
|
|
157
153
|
font-family: inherit;
|