@scalemule/news-publication 0.0.49 → 0.0.51

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 (39) hide show
  1. package/README.md +26 -0
  2. package/dist/{chunk-ZXH3O537.js → chunk-ABPJMDUG.js} +1 -1
  3. package/dist/{chunk-MBBPEFDA.js → chunk-AFJ6S5WJ.js} +1 -1
  4. package/dist/{chunk-2MEYHM7M.js → chunk-AMLVCZDP.js} +1 -1
  5. package/dist/{chunk-TTLM7YOH.js → chunk-QW3OZB22.js} +183 -11
  6. package/dist/index.js +3 -3
  7. package/dist/meet-forms.js +2 -2
  8. package/dist/meet-view.d.cts +1 -1
  9. package/dist/meet-view.d.ts +1 -1
  10. package/dist/meet-view.js +2 -2
  11. package/dist/pets-auth-server.cjs +59 -14
  12. package/dist/pets-auth-server.d.cts +7 -1
  13. package/dist/pets-auth-server.d.ts +7 -1
  14. package/dist/pets-auth-server.js +60 -17
  15. package/dist/pets-forms.cjs +8 -4
  16. package/dist/pets-forms.d.cts +4 -2
  17. package/dist/pets-forms.d.ts +4 -2
  18. package/dist/pets-forms.js +10 -6
  19. package/dist/pets-interactions.cjs +6 -5
  20. package/dist/pets-interactions.d.cts +5 -2
  21. package/dist/pets-interactions.d.ts +5 -2
  22. package/dist/pets-interactions.js +7 -6
  23. package/dist/pets-plugin.cjs +551 -0
  24. package/dist/pets-plugin.d.cts +50 -0
  25. package/dist/pets-plugin.d.ts +50 -0
  26. package/dist/pets-plugin.js +317 -0
  27. package/dist/pets-publication.cjs +230 -34
  28. package/dist/pets-publication.d.cts +7 -3
  29. package/dist/pets-publication.d.ts +7 -3
  30. package/dist/pets-publication.js +51 -27
  31. package/dist/pets-server.js +2 -2
  32. package/dist/pets-view.cjs +182 -9
  33. package/dist/pets-view.d.cts +3 -1
  34. package/dist/pets-view.d.ts +3 -1
  35. package/dist/pets-view.js +2 -2
  36. package/dist/pets.cjs +1 -1
  37. package/dist/pets.js +1 -1
  38. package/package.json +6 -1
  39. package/pets.css +215 -7
@@ -0,0 +1,551 @@
1
+ 'use strict';
2
+
3
+ var sdk = require('@scalemule/sdk');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var petsForms = require('@scalemule/news-publication/pets-forms');
6
+ var petsInteractions = require('@scalemule/news-publication/pets-interactions');
7
+
8
+ // src/pets-server.ts
9
+
10
+ // src/pets.ts
11
+ var PET_SAFETY = {
12
+ recovery: "Bay Area Paw does not independently verify pet ownership. A report is a contributor\u2019s account. Never send money or verification codes to someone claiming to have found a pet. Keep microchip numbers and ownership evidence private."};
13
+ var PET_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
14
+ var PET_SLUG = /^[a-z0-9][a-z0-9-]{0,190}$/;
15
+ function resolvePetCommunity(areas, selected, preference, publicationDefault) {
16
+ if (selected === "" || selected === void 0 && preference === "all") return void 0;
17
+ for (const candidate of [selected, preference, publicationDefault]) {
18
+ const found = areas.find(
19
+ (area) => area.id === candidate || area.slug === candidate
20
+ );
21
+ if (found) return found;
22
+ }
23
+ return void 0;
24
+ }
25
+ function safePetLink(raw) {
26
+ if (raw.startsWith("/") && !raw.startsWith("//") && !/[\\\r\n]/.test(raw))
27
+ return raw;
28
+ try {
29
+ const url = new URL(raw);
30
+ return url.protocol === "https:" && !url.username && !url.password ? url.href : void 0;
31
+ } catch {
32
+ return void 0;
33
+ }
34
+ }
35
+ function adoptionAvailability(source, now = Date.now()) {
36
+ const at = source?.verified_at ? Date.parse(source.verified_at) : NaN;
37
+ return source?.availability_confirmed && Number.isFinite(at) && at <= now && now - at <= 864e5 ? "confirmed" : "check_with_organization";
38
+ }
39
+
40
+ // src/pets-server.ts
41
+ var PetRequestError = class extends Error {
42
+ constructor(status, message) {
43
+ super(message);
44
+ this.status = status;
45
+ }
46
+ status;
47
+ };
48
+ function config(scope) {
49
+ const url = new URL(scope.gatewayUrl);
50
+ if (!scope.apiKey || !PET_SLUG.test(scope.collectionSlug) || url.username || url.password || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1"].includes(url.hostname)))
51
+ throw new PetRequestError(503, "The pet community is not available yet.");
52
+ return url.origin;
53
+ }
54
+ async function petRequest(scope, path, init = {}, fetcher = fetch) {
55
+ const gateway = config(scope);
56
+ if (!path.startsWith("/v1/") || path.includes("..") || /[\\\r\n]/.test(path))
57
+ throw new Error("Invalid platform path");
58
+ const response = await fetcher(gateway + path, {
59
+ method: init.method || "GET",
60
+ headers: {
61
+ ...sdk.buildClientContextHeaders(scope.clientContext),
62
+ "x-api-key": scope.apiKey,
63
+ "content-type": "application/json",
64
+ ...scope.accessToken ? { authorization: `Bearer ${scope.accessToken}` } : {}
65
+ },
66
+ body: init.body === void 0 ? void 0 : JSON.stringify(init.body),
67
+ cache: "no-store",
68
+ redirect: "error",
69
+ signal: AbortSignal.timeout(15e3)
70
+ });
71
+ if (!response.ok)
72
+ throw new PetRequestError(
73
+ response.status,
74
+ response.status === 401 ? "Please sign in to continue." : response.status === 404 ? "This pet resource is not available." : response.status === 409 ? "This contribution changed. Reload before saving." : response.status === 429 ? "Please wait before trying again." : "We couldn\u2019t complete that request. Please try again."
75
+ );
76
+ const json = await response.json();
77
+ return json?.data ?? json;
78
+ }
79
+ function PawMark({ size = 36 }) {
80
+ return /* @__PURE__ */ jsxRuntime.jsxs(
81
+ "svg",
82
+ {
83
+ width: size,
84
+ height: size,
85
+ viewBox: "0 0 48 48",
86
+ fill: "currentColor",
87
+ "aria-hidden": "true",
88
+ children: [
89
+ /* @__PURE__ */ jsxRuntime.jsx(
90
+ "ellipse",
91
+ {
92
+ cx: "10",
93
+ cy: "19",
94
+ rx: "5.1",
95
+ ry: "6.5",
96
+ transform: "rotate(-25 10 19)"
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "20", cy: "10", rx: "5", ry: "6.5", transform: "rotate(-8 20 10)" }),
100
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "32", cy: "12", rx: "5", ry: "6.5", transform: "rotate(14 32 12)" }),
101
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "40", cy: "23", rx: "4.7", ry: "6.2", transform: "rotate(30 40 23)" }),
102
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11 35c0-5 7-16 13-16s14 11 14 16c0 6-6 9-11 6-2-1-4-1-6 0-5 3-10 0-10-6Z" })
103
+ ]
104
+ }
105
+ );
106
+ }
107
+ function Photo({
108
+ resource,
109
+ mediaUrl,
110
+ large = false
111
+ }) {
112
+ const photo = resource.media.find((m) => m.status === "PUBLISHED");
113
+ const src = photo && safePetLink(mediaUrl(resource.id, photo.id));
114
+ if (!src)
115
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-photo-empty", children: [
116
+ /* @__PURE__ */ jsxRuntime.jsx(PawMark, { size: 64 }),
117
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "A story from your community" })
118
+ ] });
119
+ const separator = src.includes("?") ? "&" : "?";
120
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
121
+ /* @__PURE__ */ jsxRuntime.jsxs("picture", { children: [
122
+ /* @__PURE__ */ jsxRuntime.jsx(
123
+ "source",
124
+ {
125
+ type: "image/webp",
126
+ srcSet: `${src}${separator}width=640&format=webp 640w, ${src}${separator}width=1280&format=webp 1280w`,
127
+ sizes: large ? "(max-width: 700px) 100vw, 65vw" : "(max-width: 700px) 100vw, 33vw"
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsxRuntime.jsx(
131
+ "img",
132
+ {
133
+ src: `${src}${separator}width=1280&format=jpeg`,
134
+ srcSet: `${src}${separator}width=640&format=jpeg 640w, ${src}${separator}width=1280&format=jpeg 1280w`,
135
+ sizes: large ? "(max-width: 700px) 100vw, 65vw" : "(max-width: 700px) 100vw, 33vw",
136
+ alt: photo.caption || resource.content.name,
137
+ width: large ? 1200 : 640,
138
+ height: large ? 900 : 480,
139
+ loading: large ? "eager" : "lazy"
140
+ }
141
+ )
142
+ ] }),
143
+ photo.attribution && /* @__PURE__ */ jsxRuntime.jsxs("figcaption", { children: [
144
+ "Photograph: ",
145
+ photo.attribution
146
+ ] })
147
+ ] });
148
+ }
149
+ function ResourceCard(props) {
150
+ const href = safePetLink(props.href);
151
+ return /* @__PURE__ */ jsxRuntime.jsxs("article", { className: `paw-resource${props.memorial ? " paw-memorial" : ""}`, children: [
152
+ /* @__PURE__ */ jsxRuntime.jsx(Photo, { ...props }),
153
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-resource-copy", children: [
154
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-context", children: [
155
+ props.label,
156
+ " \xB7 ",
157
+ props.community
158
+ ] }),
159
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: href ? /* @__PURE__ */ jsxRuntime.jsx("a", { href, children: props.resource.content.name }) : props.resource.content.name }),
160
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: props.resource.content.story }),
161
+ props.resource.content.attribution && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-credit", children: [
162
+ "Shared by ",
163
+ props.resource.content.attribution
164
+ ] })
165
+ ] })
166
+ ] });
167
+ }
168
+ function PetProfileCard(props) {
169
+ return /* @__PURE__ */ jsxRuntime.jsx(ResourceCard, { ...props, label: "Meet a neighbor" });
170
+ }
171
+ function PetCelebrationCard(props) {
172
+ return /* @__PURE__ */ jsxRuntime.jsx(
173
+ ResourceCard,
174
+ {
175
+ ...props,
176
+ memorial: props.resource.content.category === "memorial",
177
+ label: props.resource.content.category === "memorial" ? "In loving memory" : "A little joy worth sharing"
178
+ }
179
+ );
180
+ }
181
+ function LostPetNotice(props) {
182
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-notice", children: [
183
+ /* @__PURE__ */ jsxRuntime.jsx(
184
+ ResourceCard,
185
+ {
186
+ ...props,
187
+ label: props.resource.reunited_at ? "Reported reunited" : props.resource.kind === "found" ? "Found pet" : "Lost pet"
188
+ }
189
+ ),
190
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-safety", children: PET_SAFETY.recovery })
191
+ ] });
192
+ }
193
+ function AdoptionListingCard(props) {
194
+ const source = props.resource.content.source;
195
+ const url = source && safePetLink(source.official_url);
196
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
197
+ /* @__PURE__ */ jsxRuntime.jsx(ResourceCard, { ...props, label: "Adoption discovery" }),
198
+ source && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-source", children: [
199
+ adoptionAvailability(source) === "confirmed" ? "Availability recently confirmed." : "Check current availability with the organization.",
200
+ " ",
201
+ url && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: url, rel: "noopener noreferrer", children: [
202
+ "Visit ",
203
+ source.organization
204
+ ] }),
205
+ source.verified_at && /* @__PURE__ */ jsxRuntime.jsxs("small", { children: [
206
+ "Source checked",
207
+ " ",
208
+ new Date(source.verified_at).toLocaleDateString("en-US", {
209
+ timeZone: "America/Los_Angeles"
210
+ })
211
+ ] })
212
+ ] })
213
+ ] });
214
+ }
215
+ function PetEventCard(props) {
216
+ const event = props.resource.content.event, source = props.resource.content.source;
217
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
218
+ /* @__PURE__ */ jsxRuntime.jsx(ResourceCard, { ...props, label: "Pet community event" }),
219
+ event && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-source", children: [
220
+ /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: event.starts_at, children: new Date(event.starts_at).toLocaleString("en-US", {
221
+ timeZone: "America/Los_Angeles",
222
+ dateStyle: "medium",
223
+ timeStyle: "short"
224
+ }) }),
225
+ " ",
226
+ "\xB7 Pacific time",
227
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
228
+ event.cost_verified && event.cost === "free" ? "Verified free event" : event.cost_verified && event.cost === "paid" ? "Paid event \u2014 check official pricing" : "Check the official organization for cost"
229
+ ] }),
230
+ source && /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: safePetLink(source.official_url), rel: "noopener noreferrer", children: [
231
+ "Official details from ",
232
+ source.organization
233
+ ] }) })
234
+ ] });
235
+ }
236
+ var publicationPetPaths = {
237
+ home: "/pets",
238
+ account: "/pets/account",
239
+ submit: "/pets/submit",
240
+ resource: "/pets",
241
+ browse: "/pets/browse"
242
+ };
243
+ var standalonePetPaths = {
244
+ home: "/",
245
+ account: "/account",
246
+ submit: "/submit",
247
+ resource: "/pets",
248
+ browse: "/browse"
249
+ };
250
+ function petCollectionRequest(scope, suffix = "") {
251
+ return petRequest(
252
+ scope,
253
+ `/v1/knowledge/community-maps/collections/${scope.collectionSlug}${suffix}`
254
+ );
255
+ }
256
+ async function petReaderAuthenticated(scope) {
257
+ if (!scope.accessToken) return false;
258
+ try {
259
+ const me = await petRequest(
260
+ scope,
261
+ "/v1/auth/me"
262
+ );
263
+ return Boolean(me.id && me.email_verified);
264
+ } catch {
265
+ return false;
266
+ }
267
+ }
268
+ function Shell({
269
+ paths,
270
+ children,
271
+ signedIn
272
+ }) {
273
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw", children: [
274
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "paw-page-heading", children: [
275
+ /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "paw-brand", href: paths.home, children: [
276
+ /* @__PURE__ */ jsxRuntime.jsx(PawMark, {}),
277
+ "Bay Area Paw"
278
+ ] }),
279
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-actions", children: [
280
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: paths.account, children: "My pets" }),
281
+ signedIn && /* @__PURE__ */ jsxRuntime.jsx(petsInteractions.PetSignOut, { returnTo: paths.home })
282
+ ] })
283
+ ] }),
284
+ children
285
+ ] });
286
+ }
287
+ async function PetAccountPage({
288
+ scope,
289
+ signedIn,
290
+ paths = publicationPetPaths,
291
+ after,
292
+ signInEnabled = true
293
+ }) {
294
+ let body;
295
+ if (!signedIn)
296
+ body = signInEnabled ? /* @__PURE__ */ jsxRuntime.jsx(petsForms.PetSignIn, { returnTo: paths.account }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Community sign-in is being prepared. Public browsing is open." });
297
+ else
298
+ try {
299
+ const [own, preferences, collection] = await Promise.all([
300
+ petCollectionRequest(
301
+ scope,
302
+ "/pets/mine" + (after && PET_UUID.test(after) ? "?after=" + after : "")
303
+ ),
304
+ petCollectionRequest(scope, "/pets/preferences"),
305
+ petCollectionRequest(scope)
306
+ ]);
307
+ body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
308
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-intro", children: "A home for their stories, wherever you read your local news." }),
309
+ !own.items.length && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Your pet\u2019s story starts here. Create a private profile or share a contribution with the community." }),
310
+ own.items.map((resource) => /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "paw-account-row", children: [
311
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: resource.content.name }),
312
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: resource.visibility === "private" ? "Private \u2014 only you" : resource.status === "published" ? "Editorially published; visibility follows its scheduled dates" : resource.status.replaceAll("_", " ") }),
313
+ resource.review_note && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
314
+ "Editorial note: ",
315
+ resource.review_note
316
+ ] }),
317
+ /* @__PURE__ */ jsxRuntime.jsx(petsForms.PetOwnerActions, { resource, submitUrl: paths.submit })
318
+ ] }, resource.id)),
319
+ own.next_cursor && /* @__PURE__ */ jsxRuntime.jsx("a", { href: paths.account + "?after=" + own.next_cursor, children: "More contributions" }),
320
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { className: "paw-button", href: paths.submit, children: "Add a pet or story" }) }),
321
+ /* @__PURE__ */ jsxRuntime.jsx(
322
+ petsInteractions.PetPreferencesForm,
323
+ {
324
+ record: preferences,
325
+ communities: preferences.communities || collection.areas
326
+ }
327
+ )
328
+ ] });
329
+ } catch (error) {
330
+ body = error && typeof error === "object" && "status" in error && error.status === 403 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
331
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Connect your network sign-in to open this pet community." }),
332
+ /* @__PURE__ */ jsxRuntime.jsx(petsForms.PetSignIn, { returnTo: paths.account })
333
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "Your pets could not be loaded. Please try again shortly." });
334
+ }
335
+ return /* @__PURE__ */ jsxRuntime.jsx(Shell, { paths, signedIn, children: /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "paw-story", children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-eyebrow", children: "Your community account" }),
337
+ /* @__PURE__ */ jsxRuntime.jsxs("h1", { children: [
338
+ "Your pets.",
339
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
340
+ "Your little corner."
341
+ ] }),
342
+ body
343
+ ] }) });
344
+ }
345
+ async function PetSubmitPage({
346
+ scope,
347
+ signedIn,
348
+ paths = publicationPetPaths,
349
+ edit,
350
+ community,
351
+ submissionsEnabled = true
352
+ }) {
353
+ let form;
354
+ const next = paths.submit + "?" + new URLSearchParams({
355
+ ...edit ? { edit } : {},
356
+ ...community ? { community } : {}
357
+ });
358
+ if (!submissionsEnabled)
359
+ form = /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "paw-form", children: [
360
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: "We\u2019re getting ready to meet your pets." }),
361
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Contributions will open when our local review team and photo-sharing experience are ready." })
362
+ ] });
363
+ else if (!signedIn)
364
+ form = /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "paw-form", children: [
365
+ /* @__PURE__ */ jsxRuntime.jsxs("h1", { children: [
366
+ "A familiar sign-in.",
367
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
368
+ "A new place to belong."
369
+ ] }),
370
+ /* @__PURE__ */ jsxRuntime.jsx(petsForms.PetSignIn, { returnTo: next })
371
+ ] });
372
+ else
373
+ try {
374
+ const [collection, own, initial, preferences] = await Promise.all([
375
+ petCollectionRequest(scope),
376
+ petCollectionRequest(scope, "/pets/mine"),
377
+ edit && PET_UUID.test(edit) ? petCollectionRequest(scope, "/pets/mine/" + edit) : void 0,
378
+ edit ? petCollectionRequest(scope, "/pets/preferences") : void 0
379
+ ]);
380
+ const currentHome = preferences?.communities?.find(
381
+ (a) => a.id === initial?.area_id
382
+ );
383
+ const editCommunities = currentHome && !collection.areas.some((a) => a.id === currentHome.id) ? [...collection.areas, currentHome] : collection.areas;
384
+ form = edit && !initial ? /* @__PURE__ */ jsxRuntime.jsx("p", { children: "This contribution is unavailable. Open it from My pets." }) : /* @__PURE__ */ jsxRuntime.jsx(
385
+ petsForms.PetSubmissionForm,
386
+ {
387
+ communities: editCommunities,
388
+ policy: collection.submission_policy,
389
+ profiles: own.items.filter((p) => p.kind === "profile"),
390
+ initial,
391
+ defaultCommunity: collection.areas.find((a) => a.slug === community)?.id,
392
+ accountUrl: paths.account
393
+ }
394
+ );
395
+ } catch {
396
+ form = /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "This contribution could not be loaded. Open it from My pets or try again shortly." });
397
+ }
398
+ return /* @__PURE__ */ jsxRuntime.jsx(Shell, { paths, children: form });
399
+ }
400
+ function PetStoryPage({
401
+ resource,
402
+ communities,
403
+ signedIn,
404
+ paths = publicationPetPaths,
405
+ canonicalOrigin
406
+ }) {
407
+ const c = resource.content, photoUrl = (photo) => `/api/pets/${resource.id}/media/${photo}`, source = c.source && safePetLink(c.source.official_url);
408
+ return /* @__PURE__ */ jsxRuntime.jsx(Shell, { paths, children: /* @__PURE__ */ jsxRuntime.jsxs(
409
+ "article",
410
+ {
411
+ className: `paw-story${c.category === "memorial" ? " paw-memorial" : ""}`,
412
+ children: [
413
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-context", children: communities.find((a) => a.id === resource.area_id)?.name }),
414
+ /* @__PURE__ */ jsxRuntime.jsxs("h1", { children: [
415
+ c.category === "memorial" ? "Remembering " : "Meet ",
416
+ c.name,
417
+ "."
418
+ ] }),
419
+ resource.media.map((photo, index) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { children: [
420
+ /* @__PURE__ */ jsxRuntime.jsxs("picture", { children: [
421
+ /* @__PURE__ */ jsxRuntime.jsx(
422
+ "source",
423
+ {
424
+ type: "image/webp",
425
+ srcSet: `${photoUrl(photo.id)}?width=640&format=webp 640w, ${photoUrl(photo.id)}?width=1280&format=webp 1280w`,
426
+ sizes: "(max-width: 850px) 100vw, 800px"
427
+ }
428
+ ),
429
+ /* @__PURE__ */ jsxRuntime.jsx(
430
+ "img",
431
+ {
432
+ src: `${photoUrl(photo.id)}?width=1280&format=jpeg`,
433
+ alt: photo.caption || c.name,
434
+ width: 1200,
435
+ height: 900,
436
+ loading: index ? "lazy" : "eager"
437
+ }
438
+ )
439
+ ] }),
440
+ /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: photo.attribution })
441
+ ] }, photo.id)),
442
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: c.story }),
443
+ c.personality && /* @__PURE__ */ jsxRuntime.jsx("p", { children: c.personality }),
444
+ c.activities.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
445
+ "Favorite things: ",
446
+ c.activities.join(", "),
447
+ "."
448
+ ] }),
449
+ c.attribution && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-credit", children: [
450
+ "Shared by ",
451
+ c.attribution
452
+ ] }),
453
+ ["lost", "found"].includes(resource.kind) && /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "paw-safety", children: [
454
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: resource.reunited_at ? "Reported reunited." : "A community report." }),
455
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: PET_SAFETY.recovery }),
456
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Private recovery contact is not available yet. Do not post contact details in public." })
457
+ ] }),
458
+ source && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: source, rel: "noopener noreferrer", children: [
459
+ "Visit ",
460
+ c.source.organization,
461
+ " for current information"
462
+ ] }),
463
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: canonicalOrigin + "/pets/" + resource.id, children: "Permanent link to this story" }) }),
464
+ /* @__PURE__ */ jsxRuntime.jsx(
465
+ petsInteractions.PetResourceActions,
466
+ {
467
+ resource,
468
+ signedIn,
469
+ accountUrl: paths.account
470
+ }
471
+ ),
472
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: paths.home, children: "More community pets" })
473
+ ]
474
+ }
475
+ ) });
476
+ }
477
+ var petBrowseLabels = {
478
+ neighbors: "Friends around the corner",
479
+ profile: "Meet our pets",
480
+ photo: "The community photo board",
481
+ lost_found: "Let\u2019s help them get home.",
482
+ celebration: "Little milestones. Lasting memories.",
483
+ adoption: "A new chapter starts with hello.",
484
+ event: "Good things to get together for."
485
+ };
486
+ async function PetBrowsePage({
487
+ scope,
488
+ kind,
489
+ query,
490
+ paths = publicationPetPaths
491
+ }) {
492
+ let body;
493
+ try {
494
+ const collection = await petCollectionRequest(scope), chosen = resolvePetCommunity(collection.areas, query.community);
495
+ const filter = new URLSearchParams({ kind });
496
+ if (chosen) filter.set("area_id", chosen.id);
497
+ for (const key of ["after", "species", "category"])
498
+ if (query[key]) filter.set(key, query[key]);
499
+ const result = await petCollectionRequest(scope, "/pets?" + filter);
500
+ const Card = kind === "lost_found" ? LostPetNotice : kind === "celebration" ? PetCelebrationCard : kind === "adoption" ? AdoptionListingCard : kind === "event" ? PetEventCard : PetProfileCard;
501
+ const next = new URLSearchParams(
502
+ Object.entries(query).filter(
503
+ (e) => typeof e[1] === "string"
504
+ )
505
+ );
506
+ if (result.next_cursor) next.set("after", result.next_cursor);
507
+ body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
508
+ /* @__PURE__ */ jsxRuntime.jsxs("form", { className: "paw-filters", method: "get", children: [
509
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
510
+ "Community",
511
+ /* @__PURE__ */ jsxRuntime.jsxs("select", { name: "community", defaultValue: chosen?.slug || "", children: [
512
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "All local communities" }),
513
+ collection.areas.map((a) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: a.slug, children: a.name }, a.id))
514
+ ] })
515
+ ] }),
516
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
517
+ "Species",
518
+ /* @__PURE__ */ jsxRuntime.jsx("input", { name: "species", maxLength: 50, defaultValue: query.species })
519
+ ] }),
520
+ /* @__PURE__ */ jsxRuntime.jsx("button", { children: "Browse" })
521
+ ] }),
522
+ result.items.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "paw-gallery", children: result.items.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
523
+ Card,
524
+ {
525
+ resource: r,
526
+ community: collection.areas.find((a) => a.id === r.area_id)?.name || "Our community",
527
+ href: paths.resource + "/" + r.id,
528
+ mediaUrl: (id, media) => `/api/pets/${id}/media/${media}`
529
+ },
530
+ r.id
531
+ )) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-empty", children: "No reviewed public contributions match these filters." }),
532
+ result.next_cursor && /* @__PURE__ */ jsxRuntime.jsx("a", { className: "paw-button", href: "?" + next, children: "Next page" })
533
+ ] });
534
+ } catch {
535
+ body = /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", children: "The community board is temporarily unavailable. Please try again shortly." });
536
+ }
537
+ return /* @__PURE__ */ jsxRuntime.jsx(Shell, { paths, children: /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "paw-section", children: [
538
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: petBrowseLabels[kind] || "Community pets" }),
539
+ body
540
+ ] }) });
541
+ }
542
+
543
+ exports.PetAccountPage = PetAccountPage;
544
+ exports.PetBrowsePage = PetBrowsePage;
545
+ exports.PetStoryPage = PetStoryPage;
546
+ exports.PetSubmitPage = PetSubmitPage;
547
+ exports.petBrowseLabels = petBrowseLabels;
548
+ exports.petCollectionRequest = petCollectionRequest;
549
+ exports.petReaderAuthenticated = petReaderAuthenticated;
550
+ exports.publicationPetPaths = publicationPetPaths;
551
+ exports.standalonePetPaths = standalonePetPaths;
@@ -0,0 +1,50 @@
1
+ import React__default from 'react';
2
+ import { PetScope } from './pets-server.cjs';
3
+ import { PetResource, PetCommunity } from './pets.cjs';
4
+ import '@scalemule/sdk';
5
+ import './sponsorships-CtnBe3S8.cjs';
6
+
7
+ /** Native server-rendered pet pages. The host supplies its existing reader session. */
8
+
9
+ type PetPluginPaths = {
10
+ home: string;
11
+ account: string;
12
+ submit: string;
13
+ resource: string;
14
+ browse: string;
15
+ };
16
+ declare const publicationPetPaths: PetPluginPaths;
17
+ declare const standalonePetPaths: PetPluginPaths;
18
+ declare function petCollectionRequest<T>(scope: PetScope, suffix?: string): Promise<T>;
19
+ declare function petReaderAuthenticated(scope: PetScope): Promise<boolean>;
20
+ declare function PetAccountPage({ scope, signedIn, paths, after, signInEnabled, }: {
21
+ scope: PetScope;
22
+ signedIn: boolean;
23
+ paths?: PetPluginPaths;
24
+ after?: string;
25
+ signInEnabled?: boolean;
26
+ }): Promise<React__default.JSX.Element>;
27
+ declare function PetSubmitPage({ scope, signedIn, paths, edit, community, submissionsEnabled, }: {
28
+ scope: PetScope;
29
+ signedIn: boolean;
30
+ paths?: PetPluginPaths;
31
+ edit?: string;
32
+ community?: string;
33
+ submissionsEnabled?: boolean;
34
+ }): Promise<React__default.JSX.Element>;
35
+ declare function PetStoryPage({ resource, communities, signedIn, paths, canonicalOrigin, }: {
36
+ resource: PetResource;
37
+ communities: PetCommunity[];
38
+ signedIn: boolean;
39
+ paths?: PetPluginPaths;
40
+ canonicalOrigin: string;
41
+ }): React__default.JSX.Element;
42
+ declare const petBrowseLabels: Record<string, string>;
43
+ declare function PetBrowsePage({ scope, kind, query, paths, }: {
44
+ scope: PetScope;
45
+ kind: string;
46
+ query: Record<string, string | undefined>;
47
+ paths?: PetPluginPaths;
48
+ }): Promise<React__default.JSX.Element>;
49
+
50
+ export { PetAccountPage, PetBrowsePage, type PetPluginPaths, PetStoryPage, PetSubmitPage, petBrowseLabels, petCollectionRequest, petReaderAuthenticated, publicationPetPaths, standalonePetPaths };
@@ -0,0 +1,50 @@
1
+ import React__default from 'react';
2
+ import { PetScope } from './pets-server.js';
3
+ import { PetResource, PetCommunity } from './pets.js';
4
+ import '@scalemule/sdk';
5
+ import './sponsorships-CtnBe3S8.js';
6
+
7
+ /** Native server-rendered pet pages. The host supplies its existing reader session. */
8
+
9
+ type PetPluginPaths = {
10
+ home: string;
11
+ account: string;
12
+ submit: string;
13
+ resource: string;
14
+ browse: string;
15
+ };
16
+ declare const publicationPetPaths: PetPluginPaths;
17
+ declare const standalonePetPaths: PetPluginPaths;
18
+ declare function petCollectionRequest<T>(scope: PetScope, suffix?: string): Promise<T>;
19
+ declare function petReaderAuthenticated(scope: PetScope): Promise<boolean>;
20
+ declare function PetAccountPage({ scope, signedIn, paths, after, signInEnabled, }: {
21
+ scope: PetScope;
22
+ signedIn: boolean;
23
+ paths?: PetPluginPaths;
24
+ after?: string;
25
+ signInEnabled?: boolean;
26
+ }): Promise<React__default.JSX.Element>;
27
+ declare function PetSubmitPage({ scope, signedIn, paths, edit, community, submissionsEnabled, }: {
28
+ scope: PetScope;
29
+ signedIn: boolean;
30
+ paths?: PetPluginPaths;
31
+ edit?: string;
32
+ community?: string;
33
+ submissionsEnabled?: boolean;
34
+ }): Promise<React__default.JSX.Element>;
35
+ declare function PetStoryPage({ resource, communities, signedIn, paths, canonicalOrigin, }: {
36
+ resource: PetResource;
37
+ communities: PetCommunity[];
38
+ signedIn: boolean;
39
+ paths?: PetPluginPaths;
40
+ canonicalOrigin: string;
41
+ }): React__default.JSX.Element;
42
+ declare const petBrowseLabels: Record<string, string>;
43
+ declare function PetBrowsePage({ scope, kind, query, paths, }: {
44
+ scope: PetScope;
45
+ kind: string;
46
+ query: Record<string, string | undefined>;
47
+ paths?: PetPluginPaths;
48
+ }): Promise<React__default.JSX.Element>;
49
+
50
+ export { PetAccountPage, PetBrowsePage, type PetPluginPaths, PetStoryPage, PetSubmitPage, petBrowseLabels, petCollectionRequest, petReaderAuthenticated, publicationPetPaths, standalonePetPaths };