@jamwidgets/astro 0.1.0 → 0.2.3
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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/loader.d.ts +2 -19
- package/dist/loader.js +5 -2
- package/package.json +11 -9
- package/src/Comments.astro +4 -0
- package/src/Feedback.astro +4 -0
- package/src/Form.astro +4 -0
- package/src/Poll.astro +4 -0
- package/src/PoweredBy.astro +83 -0
- package/src/Subscribe.astro +95 -94
- package/src/Waitlist.astro +4 -0
- package/src/index.ts +6 -0
- package/src/loader.ts +7 -16
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { DEFAULT_ENDPOINT, API_PATH, VISITOR_STORAGE_KEY, type JamWidgetsConfig, type SeriphConfig, // deprecated alias
|
|
8
8
|
type Comment, type ReactionCounts, type FormSubmitResponse, type SubscribeResponse, type JamwidgetsPost, type SeriphPost, // deprecated alias
|
|
9
|
-
type Announcement, type AnnouncementType, type Poll, type PollOption, type PollSettings, type PollWithResults, type ShowResultsMode, type FeedbackType, buildUrl, getSiteKey, getVisitorId, setVisitorId, type SubmitFormOptions, submitForm, type FetchCommentsOptions, fetchComments, type PostCommentOptions, postComment, type FetchReactionsOptions, type FetchReactionsResponse, fetchReactions, type AddReactionOptions, addReaction, type RemoveReactionOptions, removeReaction, type SubscribeOptions, subscribe, type JoinWaitlistOptions, type JoinWaitlistResponse, joinWaitlist, type ViewCountsOptions, type ViewCounts, type RecordViewResponse, getViewCounts, recordView, type SubmitFeedbackOptions, type SubmitFeedbackResponse, submitFeedback, type FetchPollOptions, fetchPoll, type VotePollOptions, type VotePollResponse, votePoll, type FetchAnnouncementsOptions, fetchAnnouncements, type DismissAnnouncementOptions, dismissAnnouncement, type FetchPostsOptions, fetchPosts, type FetchPostOptions, fetchPost, type ControllerStatus, type ControllerListener, type SubscribeState, type FormState, type ReactionsState, type CommentsState, type WaitlistState, type ViewCountsState, type FeedbackState, type PollState, type AnnouncementsState, SubscribeController, WaitlistController, FormController, ReactionsController, CommentsController, ViewCountsController, FeedbackController, PollController, AnnouncementsController, } from "@jamwidgets/core";
|
|
9
|
+
type Announcement, type AnnouncementType, type Poll, type PollOption, type PollSettings, type PollWithResults, type ShowResultsMode, type FeedbackType, buildUrl, getSiteKey, getVisitorId, setVisitorId, type SubmitFormOptions, submitForm, type FetchCommentsOptions, fetchComments, type PostCommentOptions, postComment, type FetchReactionsOptions, type FetchReactionsResponse, fetchReactions, type AddReactionOptions, addReaction, type RemoveReactionOptions, removeReaction, type SubscribeOptions, subscribe, type JoinWaitlistOptions, type JoinWaitlistResponse, joinWaitlist, type ViewCountsOptions, type ViewCounts, type RecordViewResponse, getViewCounts, recordView, type SubmitFeedbackOptions, type SubmitFeedbackResponse, submitFeedback, type FetchPollOptions, fetchPoll, type VotePollOptions, type VotePollResponse, votePoll, type FetchAnnouncementsOptions, fetchAnnouncements, type DismissAnnouncementOptions, dismissAnnouncement, type FetchPostsOptions, fetchPosts, type FetchPostOptions, fetchPost, type SiteConfig, fetchSiteConfig, POWERED_BY_URL, POWERED_BY_LABEL, type ControllerStatus, type ControllerListener, type SubscribeState, type FormState, type ReactionsState, type CommentsState, type WaitlistState, type ViewCountsState, type FeedbackState, type PollState, type AnnouncementsState, SubscribeController, WaitlistController, FormController, ReactionsController, CommentsController, ViewCountsController, FeedbackController, PollController, AnnouncementsController, } from "@jamwidgets/core";
|
|
10
10
|
export { jamwidgetsPostsLoader, seriphPostsLoader, // deprecated alias
|
|
11
11
|
type JamwidgetsPostsLoaderOptions, type SeriphPostsLoaderOptions, } from "./loader.js";
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ export {
|
|
|
9
9
|
// Constants
|
|
10
10
|
DEFAULT_ENDPOINT, API_PATH, VISITOR_STORAGE_KEY,
|
|
11
11
|
// Helpers
|
|
12
|
-
buildUrl, getSiteKey, getVisitorId, setVisitorId, submitForm, fetchComments, postComment, fetchReactions, addReaction, removeReaction, subscribe, joinWaitlist, getViewCounts, recordView, submitFeedback, fetchPoll, votePoll, fetchAnnouncements, dismissAnnouncement, fetchPosts, fetchPost, SubscribeController, WaitlistController, FormController, ReactionsController, CommentsController, ViewCountsController, FeedbackController, PollController, AnnouncementsController, } from "@jamwidgets/core";
|
|
12
|
+
buildUrl, getSiteKey, getVisitorId, setVisitorId, submitForm, fetchComments, postComment, fetchReactions, addReaction, removeReaction, subscribe, joinWaitlist, getViewCounts, recordView, submitFeedback, fetchPoll, votePoll, fetchAnnouncements, dismissAnnouncement, fetchPosts, fetchPost, fetchSiteConfig, POWERED_BY_URL, POWERED_BY_LABEL, SubscribeController, WaitlistController, FormController, ReactionsController, CommentsController, ViewCountsController, FeedbackController, PollController, AnnouncementsController, } from "@jamwidgets/core";
|
|
13
13
|
// Re-export loader (Astro-specific)
|
|
14
14
|
export { jamwidgetsPostsLoader, seriphPostsLoader, // deprecated alias
|
|
15
15
|
} from "./loader.js";
|
package/dist/loader.d.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { fetchPosts as coreFetchPosts, fetchPost as coreFetchPost, type JamwidgetsPost, type SeriphPost, // deprecated alias
|
|
20
20
|
type FetchPostsOptions, type FetchPostOptions } from "@jamwidgets/core";
|
|
21
|
+
import type { Loader } from "astro/loaders";
|
|
21
22
|
export type { JamwidgetsPost, SeriphPost, FetchPostsOptions, FetchPostOptions };
|
|
22
23
|
export { coreFetchPosts as fetchPosts, coreFetchPost as fetchPost };
|
|
23
24
|
export interface JamwidgetsPostsLoaderOptions {
|
|
@@ -34,29 +35,11 @@ export interface JamwidgetsPostsLoaderOptions {
|
|
|
34
35
|
}
|
|
35
36
|
/** @deprecated Use JamwidgetsPostsLoaderOptions instead */
|
|
36
37
|
export type SeriphPostsLoaderOptions = JamwidgetsPostsLoaderOptions;
|
|
37
|
-
interface LoaderContext {
|
|
38
|
-
store: {
|
|
39
|
-
set: (entry: {
|
|
40
|
-
id: string;
|
|
41
|
-
data: JamwidgetsPost;
|
|
42
|
-
}) => void;
|
|
43
|
-
clear: () => void;
|
|
44
|
-
};
|
|
45
|
-
logger: {
|
|
46
|
-
info: (message: string) => void;
|
|
47
|
-
warn: (message: string) => void;
|
|
48
|
-
error: (message: string) => void;
|
|
49
|
-
};
|
|
50
|
-
generateDigest: (data: unknown) => string;
|
|
51
|
-
}
|
|
52
38
|
/**
|
|
53
39
|
* Creates an Astro content loader that fetches posts from Jamwidgets.
|
|
54
40
|
*
|
|
55
41
|
* Posts are fetched at build time and cached by Astro.
|
|
56
42
|
*/
|
|
57
|
-
export declare function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions):
|
|
58
|
-
name: string;
|
|
59
|
-
load(context: LoaderContext): Promise<void>;
|
|
60
|
-
};
|
|
43
|
+
export declare function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions): Loader;
|
|
61
44
|
/** @deprecated Use jamwidgetsPostsLoader instead */
|
|
62
45
|
export declare const seriphPostsLoader: typeof jamwidgetsPostsLoader;
|
package/dist/loader.js
CHANGED
|
@@ -41,7 +41,10 @@ export function jamwidgetsPostsLoader(options) {
|
|
|
41
41
|
const response = await fetch(url.toString(), {
|
|
42
42
|
headers: {
|
|
43
43
|
"X-Jamwidgets-Key": siteKey,
|
|
44
|
-
|
|
44
|
+
// Legacy headers for backward compatibility
|
|
45
|
+
"X-Seriph-Key": siteKey,
|
|
46
|
+
// User-Agent to avoid bot detection (Cloudflare, etc.)
|
|
47
|
+
"User-Agent": "JamwidgetsAstroLoader/1.0",
|
|
45
48
|
},
|
|
46
49
|
});
|
|
47
50
|
if (!response.ok) {
|
|
@@ -52,7 +55,7 @@ export function jamwidgetsPostsLoader(options) {
|
|
|
52
55
|
for (const post of data.posts) {
|
|
53
56
|
store.set({
|
|
54
57
|
id: post.slug,
|
|
55
|
-
data: post,
|
|
58
|
+
data: { ...post },
|
|
56
59
|
});
|
|
57
60
|
}
|
|
58
61
|
logger.info(`Loaded ${data.posts.length} posts from Jamwidgets`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jamwidgets/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Astro components and content loader for Jamwidgets (forms, comments, reactions, posts)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"./Form": "./src/Form.astro",
|
|
25
25
|
"./Comments": "./src/Comments.astro",
|
|
26
|
+
"./PoweredBy": "./src/PoweredBy.astro",
|
|
26
27
|
"./Reactions": "./src/Reactions.astro",
|
|
27
28
|
"./Views": "./src/Views.astro",
|
|
28
29
|
"./Poll": "./src/Poll.astro",
|
|
@@ -37,6 +38,10 @@
|
|
|
37
38
|
"src",
|
|
38
39
|
"dist"
|
|
39
40
|
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsc",
|
|
43
|
+
"dev": "tsc --watch"
|
|
44
|
+
},
|
|
40
45
|
"keywords": [
|
|
41
46
|
"astro",
|
|
42
47
|
"jamwidgets",
|
|
@@ -50,16 +55,13 @@
|
|
|
50
55
|
],
|
|
51
56
|
"license": "MIT",
|
|
52
57
|
"dependencies": {
|
|
53
|
-
"@jamwidgets/core": "0.
|
|
58
|
+
"@jamwidgets/core": "^0.2.2"
|
|
54
59
|
},
|
|
55
60
|
"peerDependencies": {
|
|
56
|
-
"astro": "^5.0.0"
|
|
61
|
+
"astro": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
57
62
|
},
|
|
58
63
|
"devDependencies": {
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
"scripts": {
|
|
62
|
-
"build": "tsc",
|
|
63
|
-
"dev": "tsc --watch"
|
|
64
|
+
"astro": "^7.1.3",
|
|
65
|
+
"typescript": "^5.9.3"
|
|
64
66
|
}
|
|
65
|
-
}
|
|
67
|
+
}
|
package/src/Comments.astro
CHANGED
|
@@ -35,6 +35,8 @@ const {
|
|
|
35
35
|
|
|
36
36
|
// Build the API URL
|
|
37
37
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
38
|
+
|
|
39
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
38
40
|
---
|
|
39
41
|
|
|
40
42
|
<div
|
|
@@ -85,6 +87,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
85
87
|
<div class="jamwidgets-comment-replies"></div>
|
|
86
88
|
</div>
|
|
87
89
|
</template>
|
|
90
|
+
|
|
91
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
88
92
|
</div>
|
|
89
93
|
|
|
90
94
|
<script>
|
package/src/Feedback.astro
CHANGED
|
@@ -38,6 +38,8 @@ const {
|
|
|
38
38
|
|
|
39
39
|
// Build the API URL
|
|
40
40
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
41
|
+
|
|
42
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
41
43
|
---
|
|
42
44
|
|
|
43
45
|
<div
|
|
@@ -81,6 +83,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
81
83
|
</button>
|
|
82
84
|
</div>
|
|
83
85
|
</form>
|
|
86
|
+
|
|
87
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
84
88
|
</div>
|
|
85
89
|
|
|
86
90
|
<script>
|
package/src/Form.astro
CHANGED
|
@@ -40,6 +40,8 @@ const {
|
|
|
40
40
|
|
|
41
41
|
// Build the API URL
|
|
42
42
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
43
|
+
|
|
44
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
43
45
|
---
|
|
44
46
|
|
|
45
47
|
<form
|
|
@@ -58,6 +60,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
58
60
|
|
|
59
61
|
<!-- Success/Error message container (hidden by default) -->
|
|
60
62
|
<div class="jamwidgets-form-message" style="display: none;" aria-live="polite"></div>
|
|
63
|
+
|
|
64
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
61
65
|
</form>
|
|
62
66
|
|
|
63
67
|
<script>
|
package/src/Poll.astro
CHANGED
|
@@ -38,6 +38,8 @@ const {
|
|
|
38
38
|
|
|
39
39
|
// Build the API URL
|
|
40
40
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
41
|
+
|
|
42
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
41
43
|
---
|
|
42
44
|
|
|
43
45
|
<div
|
|
@@ -60,6 +62,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
60
62
|
<button type="button" class="jamwidgets-poll-submit" style="display: none;">Vote</button>
|
|
61
63
|
</div>
|
|
62
64
|
<div class="jamwidgets-poll-error" style="display: none;"></div>
|
|
65
|
+
|
|
66
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
63
67
|
</div>
|
|
64
68
|
|
|
65
69
|
<script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* JamWidgets "Powered by" footer.
|
|
4
|
+
*
|
|
5
|
+
* Rendered at the bottom of a drop-in widget. It hydrates hidden and only
|
|
6
|
+
* reveals itself when the site is on the Free tier (no custom branding) — the
|
|
7
|
+
* gate is the `hasCustomBranding` flag from `GET /api/v1/site`. Paid tiers
|
|
8
|
+
* (Pro/Team) keep it hidden, and if the config fetch fails we stay hidden so a
|
|
9
|
+
* paying site is never wrongly branded.
|
|
10
|
+
*
|
|
11
|
+
* Included by the block widgets (Comments, Form, Subscribe, Poll, Feedback,
|
|
12
|
+
* Waitlist); not the ambient ones (Reactions, Views, Announcements).
|
|
13
|
+
*/
|
|
14
|
+
interface Props {
|
|
15
|
+
/** Your site key (required) */
|
|
16
|
+
siteKey: string;
|
|
17
|
+
/** Base URL of your JamWidgets instance (default: 'https://jamwidgets.com') */
|
|
18
|
+
endpoint?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const DEFAULT_ENDPOINT = "https://jamwidgets.com";
|
|
22
|
+
const API_PATH = "/api/v1";
|
|
23
|
+
|
|
24
|
+
const { siteKey, endpoint = DEFAULT_ENDPOINT } = Astro.props;
|
|
25
|
+
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
<div
|
|
29
|
+
class="jamwidgets-powered-by"
|
|
30
|
+
data-jamwidgets-branding
|
|
31
|
+
data-endpoint={baseUrl}
|
|
32
|
+
data-site-key={siteKey}
|
|
33
|
+
hidden
|
|
34
|
+
>
|
|
35
|
+
<a href="https://jamwidgets.com/?utm_source=powered_by" target="_blank" rel="noopener noreferrer">
|
|
36
|
+
Powered by JamWidgets
|
|
37
|
+
</a>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<script>
|
|
41
|
+
// Reveal the footer only for sites without custom branding (Free tier).
|
|
42
|
+
// Site config is fetched once per (endpoint, siteKey); on any failure we
|
|
43
|
+
// leave the footer hidden (fail closed — never brand a paying site).
|
|
44
|
+
const brandingCache = new Map<string, Promise<boolean>>();
|
|
45
|
+
|
|
46
|
+
function hasCustomBranding(baseUrl: string, siteKey: string): Promise<boolean> {
|
|
47
|
+
const key = `${baseUrl}::${siteKey}`;
|
|
48
|
+
let pending = brandingCache.get(key);
|
|
49
|
+
if (!pending) {
|
|
50
|
+
pending = fetch(`${baseUrl}/site`, { headers: { "X-JamWidgets-Key": siteKey } })
|
|
51
|
+
.then((res) => (res.ok ? res.json() : null))
|
|
52
|
+
.then((data) => data?.site_config?.hasCustomBranding === true)
|
|
53
|
+
.catch(() => true);
|
|
54
|
+
brandingCache.set(key, pending);
|
|
55
|
+
}
|
|
56
|
+
return pending;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
document.querySelectorAll<HTMLElement>("[data-jamwidgets-branding]").forEach((el) => {
|
|
60
|
+
const baseUrl = el.dataset.endpoint;
|
|
61
|
+
const siteKey = el.dataset.siteKey;
|
|
62
|
+
if (!baseUrl || !siteKey) return;
|
|
63
|
+
hasCustomBranding(baseUrl, siteKey).then((custom) => {
|
|
64
|
+
if (!custom) el.removeAttribute("hidden");
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
.jamwidgets-powered-by {
|
|
71
|
+
margin-top: 0.75rem;
|
|
72
|
+
text-align: center;
|
|
73
|
+
font-size: 0.75rem;
|
|
74
|
+
line-height: 1;
|
|
75
|
+
}
|
|
76
|
+
.jamwidgets-powered-by a {
|
|
77
|
+
color: var(--jamwidgets-muted-color, #9ca3af);
|
|
78
|
+
text-decoration: none;
|
|
79
|
+
}
|
|
80
|
+
.jamwidgets-powered-by a:hover {
|
|
81
|
+
text-decoration: underline;
|
|
82
|
+
}
|
|
83
|
+
</style>
|
package/src/Subscribe.astro
CHANGED
|
@@ -49,6 +49,8 @@ const {
|
|
|
49
49
|
|
|
50
50
|
// Build the API URL
|
|
51
51
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
52
|
+
|
|
53
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
52
54
|
---
|
|
53
55
|
|
|
54
56
|
<form
|
|
@@ -79,6 +81,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
79
81
|
|
|
80
82
|
<!-- Success/Error message container (hidden by default) -->
|
|
81
83
|
<div class="jamwidgets-subscribe-message" style="display: none;" aria-live="polite"></div>
|
|
84
|
+
|
|
85
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
82
86
|
</form>
|
|
83
87
|
|
|
84
88
|
<script>
|
|
@@ -193,27 +197,41 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
193
197
|
</script>
|
|
194
198
|
|
|
195
199
|
<style is:global>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
position: relative;
|
|
213
|
-
}
|
|
200
|
+
.jamwidgets-subscribe {
|
|
201
|
+
--jamwidgets-border-color: #d1d5db;
|
|
202
|
+
--jamwidgets-input-bg: #ffffff;
|
|
203
|
+
--jamwidgets-input-text: #111827;
|
|
204
|
+
--jamwidgets-button-bg: #4f46e5;
|
|
205
|
+
--jamwidgets-button-text: #ffffff;
|
|
206
|
+
--jamwidgets-button-hover: #4338ca;
|
|
207
|
+
--jamwidgets-success-bg: #dcfce7;
|
|
208
|
+
--jamwidgets-success-text: #166534;
|
|
209
|
+
--jamwidgets-success-border: #bbf7d0;
|
|
210
|
+
--jamwidgets-error-bg: #fef2f2;
|
|
211
|
+
--jamwidgets-error-text: #991b1b;
|
|
212
|
+
--jamwidgets-error-border: #fecaca;
|
|
213
|
+
--jamwidgets-focus-ring: rgba(79, 70, 229, 0.5);
|
|
214
|
+
position: relative;
|
|
215
|
+
}
|
|
214
216
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
+
/* Dark theme */
|
|
218
|
+
.jamwidgets-subscribe.jamwidgets-theme-dark {
|
|
219
|
+
--jamwidgets-border-color: #4b5563;
|
|
220
|
+
--jamwidgets-input-bg: #1f2937;
|
|
221
|
+
--jamwidgets-input-text: #f9fafb;
|
|
222
|
+
--jamwidgets-button-bg: #6366f1;
|
|
223
|
+
--jamwidgets-button-hover: #818cf8;
|
|
224
|
+
--jamwidgets-success-bg: rgba(34, 197, 94, 0.15);
|
|
225
|
+
--jamwidgets-success-text: #86efac;
|
|
226
|
+
--jamwidgets-success-border: rgba(34, 197, 94, 0.3);
|
|
227
|
+
--jamwidgets-error-bg: rgba(239, 68, 68, 0.15);
|
|
228
|
+
--jamwidgets-error-text: #fca5a5;
|
|
229
|
+
--jamwidgets-error-border: rgba(239, 68, 68, 0.3);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Auto theme - follows prefers-color-scheme */
|
|
233
|
+
@media (prefers-color-scheme: dark) {
|
|
234
|
+
.jamwidgets-subscribe.jamwidgets-theme-auto {
|
|
217
235
|
--jamwidgets-border-color: #4b5563;
|
|
218
236
|
--jamwidgets-input-bg: #1f2937;
|
|
219
237
|
--jamwidgets-input-text: #f9fafb;
|
|
@@ -226,89 +244,72 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
226
244
|
--jamwidgets-error-text: #fca5a5;
|
|
227
245
|
--jamwidgets-error-border: rgba(239, 68, 68, 0.3);
|
|
228
246
|
}
|
|
247
|
+
}
|
|
229
248
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
--jamwidgets-input-bg: #1f2937;
|
|
235
|
-
--jamwidgets-input-text: #f9fafb;
|
|
236
|
-
--jamwidgets-button-bg: #6366f1;
|
|
237
|
-
--jamwidgets-button-hover: #818cf8;
|
|
238
|
-
--jamwidgets-success-bg: rgba(34, 197, 94, 0.15);
|
|
239
|
-
--jamwidgets-success-text: #86efac;
|
|
240
|
-
--jamwidgets-success-border: rgba(34, 197, 94, 0.3);
|
|
241
|
-
--jamwidgets-error-bg: rgba(239, 68, 68, 0.15);
|
|
242
|
-
--jamwidgets-error-text: #fca5a5;
|
|
243
|
-
--jamwidgets-error-border: rgba(239, 68, 68, 0.3);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.jamwidgets-subscribe-input-group {
|
|
248
|
-
display: flex;
|
|
249
|
-
gap: 0.5rem;
|
|
250
|
-
}
|
|
249
|
+
.jamwidgets-subscribe-input-group {
|
|
250
|
+
display: flex;
|
|
251
|
+
gap: 0.5rem;
|
|
252
|
+
}
|
|
251
253
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
254
|
+
.jamwidgets-subscribe-input {
|
|
255
|
+
flex: 1;
|
|
256
|
+
padding: 0.625rem 0.875rem;
|
|
257
|
+
border: 1px solid var(--jamwidgets-border-color);
|
|
258
|
+
border-radius: 0.375rem;
|
|
259
|
+
background-color: var(--jamwidgets-input-bg);
|
|
260
|
+
color: var(--jamwidgets-input-text);
|
|
261
|
+
font-size: 0.875rem;
|
|
262
|
+
line-height: 1.25rem;
|
|
263
|
+
}
|
|
262
264
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
.jamwidgets-subscribe-input:focus {
|
|
266
|
+
outline: none;
|
|
267
|
+
border-color: var(--jamwidgets-button-bg);
|
|
268
|
+
box-shadow: 0 0 0 3px var(--jamwidgets-focus-ring);
|
|
269
|
+
}
|
|
268
270
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
271
|
+
.jamwidgets-subscribe-input::placeholder {
|
|
272
|
+
color: #9ca3af;
|
|
273
|
+
}
|
|
272
274
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
275
|
+
.jamwidgets-subscribe-button {
|
|
276
|
+
padding: 0.625rem 1rem;
|
|
277
|
+
border: none;
|
|
278
|
+
border-radius: 0.375rem;
|
|
279
|
+
background-color: var(--jamwidgets-button-bg);
|
|
280
|
+
color: var(--jamwidgets-button-text);
|
|
281
|
+
font-size: 0.875rem;
|
|
282
|
+
font-weight: 500;
|
|
283
|
+
cursor: pointer;
|
|
284
|
+
transition: background-color 0.15s ease;
|
|
285
|
+
white-space: nowrap;
|
|
286
|
+
}
|
|
285
287
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
288
|
+
.jamwidgets-subscribe-button:hover:not(:disabled) {
|
|
289
|
+
background-color: var(--jamwidgets-button-hover);
|
|
290
|
+
}
|
|
289
291
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
.jamwidgets-subscribe-button:disabled {
|
|
293
|
+
opacity: 0.6;
|
|
294
|
+
cursor: not-allowed;
|
|
295
|
+
}
|
|
294
296
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
.jamwidgets-subscribe-message {
|
|
298
|
+
margin-top: 0.75rem;
|
|
299
|
+
padding: 0.625rem 0.875rem;
|
|
300
|
+
border-radius: 0.375rem;
|
|
301
|
+
font-size: 0.875rem;
|
|
302
|
+
}
|
|
301
303
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
304
|
+
.jamwidgets-subscribe-success {
|
|
305
|
+
background-color: var(--jamwidgets-success-bg);
|
|
306
|
+
color: var(--jamwidgets-success-text);
|
|
307
|
+
border: 1px solid var(--jamwidgets-success-border);
|
|
308
|
+
}
|
|
307
309
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
310
|
+
.jamwidgets-subscribe-error {
|
|
311
|
+
background-color: var(--jamwidgets-error-bg);
|
|
312
|
+
color: var(--jamwidgets-error-text);
|
|
313
|
+
border: 1px solid var(--jamwidgets-error-border);
|
|
313
314
|
}
|
|
314
315
|
</style>
|
package/src/Waitlist.astro
CHANGED
|
@@ -40,6 +40,8 @@ const {
|
|
|
40
40
|
|
|
41
41
|
// Build the API URL
|
|
42
42
|
const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
43
|
+
|
|
44
|
+
import PoweredBy from "./PoweredBy.astro";
|
|
43
45
|
---
|
|
44
46
|
|
|
45
47
|
<div
|
|
@@ -62,6 +64,8 @@ const baseUrl = endpoint.replace(/\/+$/, "") + API_PATH;
|
|
|
62
64
|
</button>
|
|
63
65
|
</form>
|
|
64
66
|
<div class="jamwidgets-waitlist-message" style="display: none;"></div>
|
|
67
|
+
|
|
68
|
+
<PoweredBy siteKey={siteKey} endpoint={endpoint} />
|
|
65
69
|
</div>
|
|
66
70
|
|
|
67
71
|
<script>
|
package/src/index.ts
CHANGED
package/src/loader.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
type FetchPostsOptions,
|
|
29
29
|
type FetchPostOptions,
|
|
30
30
|
} from "@jamwidgets/core";
|
|
31
|
+
import type { Loader, LoaderContext } from "astro/loaders";
|
|
31
32
|
|
|
32
33
|
// Re-export types and functions from core
|
|
33
34
|
export type { JamwidgetsPost, SeriphPost, FetchPostsOptions, FetchPostOptions };
|
|
@@ -49,19 +50,6 @@ export interface JamwidgetsPostsLoaderOptions {
|
|
|
49
50
|
/** @deprecated Use JamwidgetsPostsLoaderOptions instead */
|
|
50
51
|
export type SeriphPostsLoaderOptions = JamwidgetsPostsLoaderOptions;
|
|
51
52
|
|
|
52
|
-
interface LoaderContext {
|
|
53
|
-
store: {
|
|
54
|
-
set: (entry: { id: string; data: JamwidgetsPost }) => void;
|
|
55
|
-
clear: () => void;
|
|
56
|
-
};
|
|
57
|
-
logger: {
|
|
58
|
-
info: (message: string) => void;
|
|
59
|
-
warn: (message: string) => void;
|
|
60
|
-
error: (message: string) => void;
|
|
61
|
-
};
|
|
62
|
-
generateDigest: (data: unknown) => string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
53
|
interface ApiResponse {
|
|
66
54
|
posts: JamwidgetsPost[];
|
|
67
55
|
total: number;
|
|
@@ -72,7 +60,7 @@ interface ApiResponse {
|
|
|
72
60
|
*
|
|
73
61
|
* Posts are fetched at build time and cached by Astro.
|
|
74
62
|
*/
|
|
75
|
-
export function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions) {
|
|
63
|
+
export function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions): Loader {
|
|
76
64
|
const {
|
|
77
65
|
endpoint = DEFAULT_ENDPOINT,
|
|
78
66
|
tag,
|
|
@@ -101,7 +89,10 @@ export function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions) {
|
|
|
101
89
|
const response = await fetch(url.toString(), {
|
|
102
90
|
headers: {
|
|
103
91
|
"X-Jamwidgets-Key": siteKey,
|
|
104
|
-
|
|
92
|
+
// Legacy headers for backward compatibility
|
|
93
|
+
"X-Seriph-Key": siteKey,
|
|
94
|
+
// User-Agent to avoid bot detection (Cloudflare, etc.)
|
|
95
|
+
"User-Agent": "JamwidgetsAstroLoader/1.0",
|
|
105
96
|
},
|
|
106
97
|
});
|
|
107
98
|
|
|
@@ -118,7 +109,7 @@ export function jamwidgetsPostsLoader(options: JamwidgetsPostsLoaderOptions) {
|
|
|
118
109
|
for (const post of data.posts) {
|
|
119
110
|
store.set({
|
|
120
111
|
id: post.slug,
|
|
121
|
-
data: post,
|
|
112
|
+
data: { ...post },
|
|
122
113
|
});
|
|
123
114
|
}
|
|
124
115
|
|