@scalemule/news-publication 0.0.48 → 0.0.49

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 (72) hide show
  1. package/README.md +28 -0
  2. package/dist/{chunk-GB36YM56.js → chunk-2MEYHM7M.js} +11 -1
  3. package/dist/chunk-4JRWZXAP.js +62 -0
  4. package/dist/chunk-MBBPEFDA.js +124 -0
  5. package/dist/chunk-TTLM7YOH.js +444 -0
  6. package/dist/chunk-ZXH3O537.js +251 -0
  7. package/dist/community-maps-view.d.cts +3 -3
  8. package/dist/community-maps-view.d.ts +3 -3
  9. package/dist/cookie-consent-banner.d.cts +2 -2
  10. package/dist/cookie-consent-banner.d.ts +2 -2
  11. package/dist/cookie-settings-view.d.cts +2 -2
  12. package/dist/cookie-settings-view.d.ts +2 -2
  13. package/dist/index.cjs +29 -1
  14. package/dist/index.d.cts +4 -3
  15. package/dist/index.d.ts +4 -3
  16. package/dist/index.js +4 -3
  17. package/dist/marketplace-forms.d.cts +3 -3
  18. package/dist/marketplace-forms.d.ts +3 -3
  19. package/dist/marketplace-view.d.cts +5 -5
  20. package/dist/marketplace-view.d.ts +5 -5
  21. package/dist/{meet-RWmfj3I3.d.cts → meet-BWpxY20X.d.ts} +5 -0
  22. package/dist/{meet-RWmfj3I3.d.ts → meet-CO9Unz5M.d.cts} +5 -0
  23. package/dist/meet-forms.d.cts +7 -6
  24. package/dist/meet-forms.d.ts +7 -6
  25. package/dist/meet-forms.js +2 -1
  26. package/dist/meet-view.cjs +22 -2
  27. package/dist/meet-view.d.cts +7 -5
  28. package/dist/meet-view.d.ts +7 -5
  29. package/dist/meet-view.js +21 -4
  30. package/dist/network-bar.d.cts +2 -2
  31. package/dist/network-bar.d.ts +2 -2
  32. package/dist/network-copyright.d.cts +2 -2
  33. package/dist/network-copyright.d.ts +2 -2
  34. package/dist/pets-auth-server.cjs +212 -0
  35. package/dist/pets-auth-server.d.cts +17 -0
  36. package/dist/pets-auth-server.d.ts +17 -0
  37. package/dist/pets-auth-server.js +155 -0
  38. package/dist/pets-forms.cjs +762 -0
  39. package/dist/pets-forms.d.cts +26 -0
  40. package/dist/pets-forms.d.ts +26 -0
  41. package/dist/pets-forms.js +712 -0
  42. package/dist/pets-interactions.cjs +332 -0
  43. package/dist/pets-interactions.d.cts +20 -0
  44. package/dist/pets-interactions.d.ts +20 -0
  45. package/dist/pets-interactions.js +319 -0
  46. package/dist/pets-publication.cjs +818 -0
  47. package/dist/pets-publication.d.cts +36 -0
  48. package/dist/pets-publication.d.ts +36 -0
  49. package/dist/pets-publication.js +177 -0
  50. package/dist/pets-server.cjs +289 -0
  51. package/dist/pets-server.d.cts +42 -0
  52. package/dist/pets-server.d.ts +42 -0
  53. package/dist/pets-server.js +2 -0
  54. package/dist/pets-view.cjs +541 -0
  55. package/dist/pets-view.d.cts +56 -0
  56. package/dist/pets-view.d.ts +56 -0
  57. package/dist/pets-view.js +4 -0
  58. package/dist/pets.cjs +138 -0
  59. package/dist/pets.d.cts +127 -0
  60. package/dist/pets.d.ts +127 -0
  61. package/dist/pets.js +1 -0
  62. package/dist/sponsorship-view.d.cts +2 -2
  63. package/dist/sponsorship-view.d.ts +2 -2
  64. package/dist/sponsorship-view.js +2 -62
  65. package/dist/story-review.d.cts +6 -6
  66. package/dist/story-review.d.ts +6 -6
  67. package/dist/theme-toggle.d.cts +2 -2
  68. package/dist/theme-toggle.d.ts +2 -2
  69. package/dist/verified-card.d.cts +3 -3
  70. package/dist/verified-card.d.ts +3 -3
  71. package/package.json +40 -3
  72. package/pets.css +538 -0
@@ -0,0 +1,762 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/pets.ts
8
+ var PET_PHOTO_CATEGORIES = [
9
+ ["cute", "Cute pets"],
10
+ ["funny", "Funny moments"],
11
+ ["adventures", "Adventures"],
12
+ ["senior", "Senior pets"],
13
+ ["rescue", "Rescue stories"],
14
+ ["young", "Puppies & kittens"],
15
+ ["unusual", "Unusual pets"],
16
+ ["friends", "Best friends"],
17
+ ["holiday", "Holiday pets"]
18
+ ];
19
+ var PET_CELEBRATIONS = [
20
+ ["birthday", "Pet birthday"],
21
+ ["adoption_anniversary", "Adoption anniversary"],
22
+ ["welcome_home", "Welcome home"],
23
+ ["rescue_story", "Rescue story"],
24
+ ["happy_reunion", "Happy reunion"],
25
+ ["memorial", "Memorial tribute"]
26
+ ];
27
+ var PET_SAFETY = {
28
+ 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."};
29
+ function PawMark({ size = 36 }) {
30
+ return /* @__PURE__ */ jsxRuntime.jsxs(
31
+ "svg",
32
+ {
33
+ width: size,
34
+ height: size,
35
+ viewBox: "0 0 48 48",
36
+ fill: "currentColor",
37
+ "aria-hidden": "true",
38
+ children: [
39
+ /* @__PURE__ */ jsxRuntime.jsx(
40
+ "ellipse",
41
+ {
42
+ cx: "10",
43
+ cy: "19",
44
+ rx: "5.1",
45
+ ry: "6.5",
46
+ transform: "rotate(-25 10 19)"
47
+ }
48
+ ),
49
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "20", cy: "10", rx: "5", ry: "6.5", transform: "rotate(-8 20 10)" }),
50
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "32", cy: "12", rx: "5", ry: "6.5", transform: "rotate(14 32 12)" }),
51
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "40", cy: "23", rx: "4.7", ry: "6.2", transform: "rotate(30 40 23)" }),
52
+ /* @__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" })
53
+ ]
54
+ }
55
+ );
56
+ }
57
+ function localDateTime(value) {
58
+ const date = new Date(value);
59
+ if (!Number.isFinite(date.getTime())) return "";
60
+ return new Date(date.getTime() - date.getTimezoneOffset() * 6e4).toISOString().slice(0, 16);
61
+ }
62
+ var empty = {
63
+ name: "",
64
+ species: "Dog",
65
+ story: "",
66
+ breed: "",
67
+ personality: "",
68
+ activities: [],
69
+ category: "cute",
70
+ attribution: ""
71
+ };
72
+ async function call(url, method, data) {
73
+ const response = await fetch(url, {
74
+ method,
75
+ credentials: "same-origin",
76
+ headers: data instanceof FormData ? void 0 : { "content-type": "application/json" },
77
+ body: data === void 0 ? void 0 : data instanceof FormData ? data : JSON.stringify(data)
78
+ });
79
+ const body = await response.json();
80
+ if (!response.ok)
81
+ throw new Error(
82
+ typeof body.error === "string" ? body.error : body.error?.message || "We couldn\u2019t save this contribution. Please try again."
83
+ );
84
+ return body.data ?? body;
85
+ }
86
+ function PetSignIn({ returnTo = "/account" }) {
87
+ const [busy, setBusy] = react.useState(false), [error, setError] = react.useState("");
88
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
89
+ /* @__PURE__ */ jsxRuntime.jsx(
90
+ "button",
91
+ {
92
+ disabled: busy,
93
+ onClick: async () => {
94
+ setBusy(true);
95
+ setError("");
96
+ try {
97
+ const { url } = await call(
98
+ "/api/paw-auth/start?" + new URLSearchParams({ next: returnTo }),
99
+ "POST"
100
+ );
101
+ window.location.assign(url);
102
+ } catch (e) {
103
+ setError(
104
+ e instanceof Error ? e.message : "Sign-in is unavailable."
105
+ );
106
+ setBusy(false);
107
+ }
108
+ },
109
+ children: busy ? "Opening sign-in\u2026" : "Continue with your network sign-in"
110
+ }
111
+ ),
112
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "paw-error", children: error }),
113
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-safety", children: "Your existing network sign-in works here. Public browsing is always open." })
114
+ ] });
115
+ }
116
+ function PetSubmissionForm({
117
+ communities,
118
+ policy,
119
+ profiles = [],
120
+ initial,
121
+ defaultCommunity,
122
+ apiPath = "/api/pets",
123
+ onSaved
124
+ }) {
125
+ const [deviceReady, setDeviceReady] = react.useState(false);
126
+ react.useEffect(() => setDeviceReady(true), []);
127
+ const [kind, setKind] = react.useState(initial?.kind || "spotlight"), [content, setContent] = react.useState(initial?.content || empty);
128
+ const [community, setCommunity] = react.useState(
129
+ initial?.area_id || defaultCommunity || ""
130
+ ), [visibility, setVisibility] = react.useState(
131
+ initial?.visibility || "private"
132
+ );
133
+ const [profileId, setProfileId] = react.useState(
134
+ initial?.profile_id || null
135
+ );
136
+ const [files, setFiles] = react.useState([]);
137
+ const [step, setStep] = react.useState(0), [consent, setConsent] = react.useState(false), [busy, setBusy] = react.useState(false), [error, setError] = react.useState(""), [progress, setProgress] = react.useState(0), [saved, setSaved] = react.useState();
138
+ const receipt = react.useRef(
139
+ initial ? { id: initial.id, revision: initial.revision } : null
140
+ );
141
+ const key = react.useRef("");
142
+ const uploads = react.useRef(/* @__PURE__ */ new Set());
143
+ react.useEffect(
144
+ () => () => files.forEach((f) => URL.revokeObjectURL(f.preview)),
145
+ [files]
146
+ );
147
+ const change = (field, value) => setContent((previous) => ({ ...previous, [field]: value }));
148
+ const needsPermission = kind !== "profile" || visibility === "public" || files.length > 0;
149
+ async function save() {
150
+ setBusy(true);
151
+ setError("");
152
+ try {
153
+ if (!community || !content.name.trim())
154
+ throw new Error("Choose a community and enter your pet\u2019s name.");
155
+ if (needsPermission && !consent)
156
+ throw new Error("Read and accept the publication permission.");
157
+ if (["spotlight", "photo", "adoption"].includes(kind) && !files.length && !initial?.media.length)
158
+ throw new Error("Choose at least one authentic photograph.");
159
+ const permission = consent ? { version: policy.version, accepted: true } : null;
160
+ const input = {
161
+ area_id: community,
162
+ kind,
163
+ content: {
164
+ ...content,
165
+ activities: content.activities.filter((v) => v.trim())
166
+ },
167
+ profile_id: kind === "profile" ? null : profileId,
168
+ visibility: kind === "profile" ? visibility : "public",
169
+ consent: permission
170
+ };
171
+ if (!key.current) key.current = crypto.randomUUID();
172
+ if (!receipt.current) {
173
+ const result2 = await call(
174
+ apiPath,
175
+ "POST",
176
+ { ...input, submit: false, idempotency_key: key.current }
177
+ );
178
+ receipt.current = { id: result2.id, revision: result2.revision || 1 };
179
+ } else if (initial && progress === 0) {
180
+ const result2 = await call(
181
+ `${apiPath}/${receipt.current.id}`,
182
+ "PUT",
183
+ {
184
+ ...input,
185
+ submit: false,
186
+ expected_revision: receipt.current.revision
187
+ }
188
+ );
189
+ receipt.current = result2;
190
+ }
191
+ setProgress(1);
192
+ for (const [index, photo] of files.entries()) {
193
+ if (!uploads.current.has(photo.key)) {
194
+ const form = new FormData();
195
+ form.set("file", photo.file);
196
+ form.set("caption", content.name);
197
+ form.set("attribution", content.attribution);
198
+ form.set("rights_confirmed", "true");
199
+ form.set("consent_version", policy.version);
200
+ form.set("idempotency_key", photo.key);
201
+ await call(
202
+ `${apiPath}/submissions/${receipt.current.id}/media`,
203
+ "POST",
204
+ form
205
+ );
206
+ uploads.current.add(photo.key);
207
+ }
208
+ setProgress(index + 2);
209
+ }
210
+ const result = await call(
211
+ `${apiPath}/${receipt.current.id}`,
212
+ "PUT",
213
+ {
214
+ ...input,
215
+ submit: input.visibility === "public",
216
+ expected_revision: receipt.current.revision
217
+ }
218
+ );
219
+ receipt.current = result;
220
+ setSaved(result.id);
221
+ onSaved?.(result.id);
222
+ } catch (e) {
223
+ setError(
224
+ e instanceof Error ? e.message : "We couldn\u2019t save this contribution. Please try again."
225
+ );
226
+ } finally {
227
+ setBusy(false);
228
+ }
229
+ }
230
+ if (saved)
231
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "paw-form", role: "status", children: [
232
+ /* @__PURE__ */ jsxRuntime.jsx(PawMark, { size: 56 }),
233
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: kind === "profile" && visibility === "private" ? "A little home for your pet." : "Your story is in good hands." }),
234
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: kind === "profile" && visibility === "private" ? "Your profile is saved privately. Only you can see it." : "Your contribution is saved for editorial review. It will appear publicly only after approval." }),
235
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/account", children: "View your pets and submissions" })
236
+ ] });
237
+ return /* @__PURE__ */ jsxRuntime.jsxs(
238
+ "form",
239
+ {
240
+ className: "paw-form",
241
+ onSubmit: (event) => {
242
+ event.preventDefault();
243
+ if (step === 0) {
244
+ setError("");
245
+ setStep(1);
246
+ } else void save();
247
+ },
248
+ children: [
249
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-context", children: step === 0 ? "Your pet\u2019s story" : "Your private preview" }),
250
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: kind === "celebration" && content.category === "memorial" ? "Remember a beloved companion." : "Someone worth meeting." }),
251
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-safety", children: "Choose a community, never a home address. Keep phone numbers, email addresses and microchip details out of your story." }),
252
+ step === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
253
+ !initial && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
254
+ "What would you like to share?",
255
+ /* @__PURE__ */ jsxRuntime.jsxs(
256
+ "select",
257
+ {
258
+ value: kind,
259
+ onChange: (e) => {
260
+ const k = e.target.value;
261
+ setKind(k);
262
+ setContent((c) => ({
263
+ ...c,
264
+ source: ["event", "adoption"].includes(k) ? {
265
+ organization: "",
266
+ official_url: "",
267
+ availability_confirmed: false
268
+ } : null,
269
+ event: k === "event" ? {
270
+ starts_at: "",
271
+ ends_at: "",
272
+ event_type: "adoption",
273
+ cost: "unknown",
274
+ cost_verified: false
275
+ } : null
276
+ }));
277
+ change(
278
+ "category",
279
+ k === "celebration" ? "birthday" : k === "photo" ? "cute" : ""
280
+ );
281
+ },
282
+ children: [
283
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "spotlight", children: "Paw of the Week submission" }),
284
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "profile", children: "Pet profile" }),
285
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "photo", children: "Photo board" }),
286
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "celebration", children: "Pet celebration" }),
287
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "lost", children: "Lost pet report" }),
288
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "found", children: "Found pet report" }),
289
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "event", children: "Organization event" }),
290
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "adoption", children: "Shelter or rescue adoption listing" })
291
+ ]
292
+ }
293
+ )
294
+ ] }),
295
+ !initial && kind !== "profile" && profiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
296
+ "Start with one of your pets",
297
+ /* @__PURE__ */ jsxRuntime.jsxs(
298
+ "select",
299
+ {
300
+ value: profileId || "",
301
+ onChange: (e) => {
302
+ const p = profiles.find((p2) => p2.id === e.target.value);
303
+ setProfileId(p?.id || null);
304
+ if (p) {
305
+ setContent({
306
+ ...p.content,
307
+ category: content.category,
308
+ source: content.source,
309
+ event: content.event
310
+ });
311
+ setCommunity(p.area_id);
312
+ }
313
+ },
314
+ children: [
315
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Enter pet details" }),
316
+ profiles.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, children: p.content.name }, p.id))
317
+ ]
318
+ }
319
+ )
320
+ ] }),
321
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
322
+ kind === "event" ? "Event title" : "Pet name",
323
+ /* @__PURE__ */ jsxRuntime.jsx(
324
+ "input",
325
+ {
326
+ required: true,
327
+ maxLength: 100,
328
+ value: content.name,
329
+ onChange: (e) => change("name", e.target.value),
330
+ autoComplete: "off"
331
+ }
332
+ )
333
+ ] }),
334
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
335
+ "Species",
336
+ /* @__PURE__ */ jsxRuntime.jsx(
337
+ "input",
338
+ {
339
+ required: true,
340
+ maxLength: 50,
341
+ value: content.species,
342
+ onChange: (e) => change("species", e.target.value)
343
+ }
344
+ )
345
+ ] }),
346
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
347
+ "Home community",
348
+ /* @__PURE__ */ jsxRuntime.jsxs(
349
+ "select",
350
+ {
351
+ required: true,
352
+ value: community,
353
+ onChange: (e) => setCommunity(e.target.value),
354
+ children: [
355
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Choose a community" }),
356
+ communities.map((c) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: c.id, children: c.name }, c.id))
357
+ ]
358
+ }
359
+ )
360
+ ] }),
361
+ kind === "profile" && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
362
+ /* @__PURE__ */ jsxRuntime.jsx("legend", { children: "A few favorite things" }),
363
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
364
+ "Breed or mix (optional)",
365
+ /* @__PURE__ */ jsxRuntime.jsx(
366
+ "input",
367
+ {
368
+ value: content.breed,
369
+ maxLength: 100,
370
+ onChange: (e) => change("breed", e.target.value)
371
+ }
372
+ )
373
+ ] }),
374
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
375
+ "Birthday (optional)",
376
+ /* @__PURE__ */ jsxRuntime.jsx(
377
+ "input",
378
+ {
379
+ type: "date",
380
+ value: content.birthday || "",
381
+ onChange: (e) => change("birthday", e.target.value || null)
382
+ }
383
+ )
384
+ ] }),
385
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
386
+ "Adoption anniversary (optional)",
387
+ /* @__PURE__ */ jsxRuntime.jsx(
388
+ "input",
389
+ {
390
+ type: "date",
391
+ value: content.adoption_anniversary || "",
392
+ onChange: (e) => change("adoption_anniversary", e.target.value || null)
393
+ }
394
+ )
395
+ ] }),
396
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
397
+ "Personality",
398
+ /* @__PURE__ */ jsxRuntime.jsx(
399
+ "input",
400
+ {
401
+ maxLength: 300,
402
+ value: content.personality,
403
+ onChange: (e) => change("personality", e.target.value)
404
+ }
405
+ )
406
+ ] }),
407
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
408
+ "Favorite activities, separated by commas",
409
+ /* @__PURE__ */ jsxRuntime.jsx(
410
+ "input",
411
+ {
412
+ value: content.activities.join(", "),
413
+ onChange: (e) => change(
414
+ "activities",
415
+ e.target.value.split(",").map((v) => v.trim()).slice(0, 8)
416
+ )
417
+ }
418
+ )
419
+ ] }),
420
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
421
+ "Profile privacy",
422
+ /* @__PURE__ */ jsxRuntime.jsxs(
423
+ "select",
424
+ {
425
+ value: visibility,
426
+ onChange: (e) => setVisibility(e.target.value),
427
+ children: [
428
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "private", children: "Private \u2014 only me" }),
429
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "public", children: "Public \u2014 after editorial review" })
430
+ ]
431
+ }
432
+ )
433
+ ] })
434
+ ] }),
435
+ (kind === "photo" || kind === "celebration") && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
436
+ kind === "photo" ? "Photo category" : "Celebration",
437
+ /* @__PURE__ */ jsxRuntime.jsx(
438
+ "select",
439
+ {
440
+ value: content.category,
441
+ onChange: (e) => change("category", e.target.value),
442
+ children: (kind === "photo" ? PET_PHOTO_CATEGORIES : PET_CELEBRATIONS).map(([value, label]) => /* @__PURE__ */ jsxRuntime.jsx("option", { value, children: label }, value))
443
+ }
444
+ )
445
+ ] }),
446
+ ["lost", "found", "celebration"].includes(kind) && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
447
+ kind === "lost" ? "Date last seen" : kind === "found" ? "Date found" : "Celebration date (optional)",
448
+ /* @__PURE__ */ jsxRuntime.jsx(
449
+ "input",
450
+ {
451
+ required: kind !== "celebration",
452
+ type: "date",
453
+ value: content.date || "",
454
+ onChange: (e) => change("date", e.target.value || null)
455
+ }
456
+ )
457
+ ] }),
458
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
459
+ kind === "profile" ? "A little biography" : "Your story",
460
+ /* @__PURE__ */ jsxRuntime.jsx(
461
+ "textarea",
462
+ {
463
+ required: kind !== "profile",
464
+ maxLength: 4e3,
465
+ value: content.story,
466
+ onChange: (e) => change("story", e.target.value)
467
+ }
468
+ )
469
+ ] }),
470
+ kind === "adoption" && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
471
+ "Approximate age (optional)",
472
+ /* @__PURE__ */ jsxRuntime.jsx(
473
+ "input",
474
+ {
475
+ value: content.age_description || "",
476
+ maxLength: 80,
477
+ onChange: (e) => change("age_description", e.target.value)
478
+ }
479
+ )
480
+ ] }),
481
+ content.source && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
482
+ /* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Official organization and source" }),
483
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
484
+ "Organization name",
485
+ /* @__PURE__ */ jsxRuntime.jsx(
486
+ "input",
487
+ {
488
+ required: true,
489
+ maxLength: 200,
490
+ value: content.source.organization,
491
+ onChange: (e) => change("source", {
492
+ ...content.source,
493
+ organization: e.target.value
494
+ })
495
+ }
496
+ )
497
+ ] }),
498
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
499
+ "Official listing or registration link",
500
+ /* @__PURE__ */ jsxRuntime.jsx(
501
+ "input",
502
+ {
503
+ required: true,
504
+ type: "url",
505
+ pattern: "https://.*",
506
+ value: content.source.official_url,
507
+ onChange: (e) => change("source", {
508
+ ...content.source,
509
+ official_url: e.target.value
510
+ })
511
+ }
512
+ )
513
+ ] }),
514
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Editors verify the organization, permission to use photographs, and listing information. Availability and event costs are never assumed." })
515
+ ] }),
516
+ content.event && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { children: [
517
+ /* @__PURE__ */ jsxRuntime.jsx("legend", { children: "Event schedule" }),
518
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
519
+ "Enter times in your device\u2019s timezone (",
520
+ deviceReady ? Intl.DateTimeFormat().resolvedOptions().timeZone : "your device timezone",
521
+ "). They display in Pacific time."
522
+ ] }),
523
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
524
+ "Starts",
525
+ /* @__PURE__ */ jsxRuntime.jsx(
526
+ "input",
527
+ {
528
+ type: "datetime-local",
529
+ required: true,
530
+ value: deviceReady ? localDateTime(content.event.starts_at) : "",
531
+ onChange: (e) => {
532
+ if (e.target.value)
533
+ change("event", {
534
+ ...content.event,
535
+ starts_at: new Date(e.target.value).toISOString()
536
+ });
537
+ }
538
+ }
539
+ )
540
+ ] }),
541
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
542
+ "Ends",
543
+ /* @__PURE__ */ jsxRuntime.jsx(
544
+ "input",
545
+ {
546
+ type: "datetime-local",
547
+ required: true,
548
+ value: deviceReady ? localDateTime(content.event.ends_at) : "",
549
+ onChange: (e) => {
550
+ if (e.target.value)
551
+ change("event", {
552
+ ...content.event,
553
+ ends_at: new Date(e.target.value).toISOString()
554
+ });
555
+ }
556
+ }
557
+ )
558
+ ] }),
559
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
560
+ "Event type",
561
+ /* @__PURE__ */ jsxRuntime.jsx(
562
+ "select",
563
+ {
564
+ value: content.event.event_type,
565
+ onChange: (e) => change("event", {
566
+ ...content.event,
567
+ event_type: e.target.value
568
+ }),
569
+ children: [
570
+ "adoption",
571
+ "veterinary",
572
+ "vaccination",
573
+ "walk",
574
+ "festival",
575
+ "fundraiser",
576
+ "workshop",
577
+ "celebration"
578
+ ].map((type) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: type, children: type }, type))
579
+ }
580
+ )
581
+ ] }),
582
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
583
+ "Reported cost",
584
+ /* @__PURE__ */ jsxRuntime.jsxs(
585
+ "select",
586
+ {
587
+ value: content.event.cost,
588
+ onChange: (e) => change("event", {
589
+ ...content.event,
590
+ cost: e.target.value
591
+ }),
592
+ children: [
593
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "unknown", children: "Check with organization" }),
594
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "free", children: "Submitted as free \u2014 requires verification" }),
595
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "paid", children: "Paid registration" })
596
+ ]
597
+ }
598
+ )
599
+ ] })
600
+ ] }),
601
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
602
+ "Your public photo credit",
603
+ /* @__PURE__ */ jsxRuntime.jsx(
604
+ "input",
605
+ {
606
+ maxLength: 100,
607
+ value: content.attribution,
608
+ onChange: (e) => change("attribution", e.target.value),
609
+ placeholder: "Name you want published"
610
+ }
611
+ )
612
+ ] }),
613
+ initial?.media.map((photo) => /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
614
+ /* @__PURE__ */ jsxRuntime.jsx(
615
+ "img",
616
+ {
617
+ src: `${apiPath}/submissions/${initial.id}/media/${photo.id}`,
618
+ alt: photo.caption || content.name,
619
+ width: 640,
620
+ height: 480
621
+ }
622
+ ),
623
+ /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: photo.attribution })
624
+ ] }, photo.id)),
625
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
626
+ "Authentic photographs",
627
+ /* @__PURE__ */ jsxRuntime.jsx(
628
+ "input",
629
+ {
630
+ type: "file",
631
+ accept: "image/jpeg,image/png,image/webp",
632
+ multiple: true,
633
+ onChange: (e) => {
634
+ const selected = Array.from(e.target.files || []);
635
+ if (selected.length + (initial?.media.length || 0) > 10 || selected.some((f) => f.size > 8 * 1024 * 1024)) {
636
+ setError(
637
+ "Choose up to ten JPEG, PNG or WebP photographs, each under 8 MB."
638
+ );
639
+ return;
640
+ }
641
+ setError("");
642
+ setFiles(
643
+ selected.map((file) => ({
644
+ file,
645
+ key: crypto.randomUUID(),
646
+ preview: URL.createObjectURL(file)
647
+ }))
648
+ );
649
+ }
650
+ }
651
+ )
652
+ ] }),
653
+ /* @__PURE__ */ jsxRuntime.jsx("small", { children: "JPEG, PNG or WebP, up to 8 MB each. Photos are checked before publication and location metadata is removed." }),
654
+ ["lost", "found"].includes(kind) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "paw-safety", children: [
655
+ PET_SAFETY.recovery,
656
+ " Private recovery contact is not available yet."
657
+ ] })
658
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
659
+ /* @__PURE__ */ jsxRuntime.jsxs(
660
+ "article",
661
+ {
662
+ className: content.category === "memorial" ? "paw-memorial" : "",
663
+ children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "paw-context", children: communities.find((c) => c.id === community)?.name }),
665
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: content.name }),
666
+ !files.length && initial?.media[0] && /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
667
+ /* @__PURE__ */ jsxRuntime.jsx(
668
+ "img",
669
+ {
670
+ src: `${apiPath}/submissions/${initial.id}/media/${initial.media[0].id}`,
671
+ alt: initial.media[0].caption || content.name,
672
+ width: 800,
673
+ height: 600
674
+ }
675
+ ),
676
+ /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: initial.media[0].attribution })
677
+ ] }),
678
+ files[0] && /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: "paw-photo", children: [
679
+ /* @__PURE__ */ jsxRuntime.jsx(
680
+ "img",
681
+ {
682
+ src: files[0].preview,
683
+ alt: `Private preview of ${content.name}`,
684
+ width: 800,
685
+ height: 600
686
+ }
687
+ ),
688
+ /* @__PURE__ */ jsxRuntime.jsx("figcaption", { children: content.attribution })
689
+ ] }),
690
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { whiteSpace: "pre-wrap" }, children: content.story })
691
+ ]
692
+ }
693
+ ),
694
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: kind === "profile" && visibility === "private" ? "This profile will remain private." : "This is a private preview. Editors will review your contribution before anyone else can see it." }),
695
+ needsPermission && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
696
+ /* @__PURE__ */ jsxRuntime.jsxs("details", { children: [
697
+ /* @__PURE__ */ jsxRuntime.jsx("summary", { children: "Publication permission and guidelines" }),
698
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: policy.text }),
699
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: policy.guidelines })
700
+ ] }),
701
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "paw-consent", children: [
702
+ /* @__PURE__ */ jsxRuntime.jsx(
703
+ "input",
704
+ {
705
+ type: "checkbox",
706
+ required: true,
707
+ checked: consent,
708
+ onChange: (e) => setConsent(e.target.checked)
709
+ }
710
+ ),
711
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "I have read and accept the publication permission. These are authentic photographs I have permission to share." })
712
+ ] })
713
+ ] })
714
+ ] }),
715
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "paw-error", children: error }),
716
+ busy && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
717
+ "Saving your contribution",
718
+ /* @__PURE__ */ jsxRuntime.jsx("progress", { value: progress, max: files.length + 2 })
719
+ ] }),
720
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-actions", children: [
721
+ step === 1 && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: busy, onClick: () => setStep(0), children: "Keep editing" }),
722
+ /* @__PURE__ */ jsxRuntime.jsx("button", { disabled: busy, type: "submit", children: busy ? "Saving\u2026" : step === 0 ? "Preview your story" : kind === "profile" && visibility === "private" ? "Save private profile" : "Submit for editorial review" })
723
+ ] })
724
+ ]
725
+ }
726
+ );
727
+ }
728
+ function PetOwnerActions({
729
+ resource,
730
+ apiPath = "/api/pets"
731
+ }) {
732
+ const [error, setError] = react.useState(""), [confirm, setConfirm] = react.useState(false), [busy, setBusy] = react.useState(false);
733
+ async function act(action) {
734
+ setBusy(true);
735
+ setError("");
736
+ try {
737
+ await call(
738
+ `${apiPath}/${resource.id}${action === "reunited" ? "/reunited" : ""}`,
739
+ action === "delete" ? "DELETE" : "POST",
740
+ { expected_revision: resource.revision }
741
+ );
742
+ window.location.reload();
743
+ } catch (e) {
744
+ setError(e instanceof Error ? e.message : "Please try again.");
745
+ setBusy(false);
746
+ }
747
+ }
748
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "paw-form-actions", children: [
749
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: `/submit?edit=${resource.id}`, children: "Edit details or privacy" }),
750
+ ["lost", "found"].includes(resource.kind) && !resource.reunited_at && /* @__PURE__ */ jsxRuntime.jsx("button", { disabled: busy, onClick: () => void act("reunited"), children: "Mark reunited" }),
751
+ confirm ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
752
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Remove this contribution and its public photographs?" }),
753
+ /* @__PURE__ */ jsxRuntime.jsx("button", { disabled: busy, onClick: () => void act("delete"), children: "Yes, remove" }),
754
+ /* @__PURE__ */ jsxRuntime.jsx("button", { disabled: busy, onClick: () => setConfirm(false), children: "Keep it" })
755
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("button", { disabled: busy, onClick: () => setConfirm(true), children: "Delete" }),
756
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", children: error })
757
+ ] });
758
+ }
759
+
760
+ exports.PetOwnerActions = PetOwnerActions;
761
+ exports.PetSignIn = PetSignIn;
762
+ exports.PetSubmissionForm = PetSubmissionForm;