@scalemule/news-publication 0.0.61 → 0.0.62
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/chunk-3QU6BJVF.js +540 -0
- package/dist/chunk-4WVAT5M2.js +213 -0
- package/dist/chunk-6SBK3D3B.js +347 -0
- package/dist/chunk-CHF3YPDV.js +314 -0
- package/dist/chunk-FHRO2Z3F.js +174 -0
- package/dist/chunk-SKG5C3MS.js +379 -0
- package/dist/index.cjs +1 -0
- package/dist/index.js +3 -2
- package/dist/meet-view.d.cts +1 -1
- package/dist/meet-view.d.ts +1 -1
- package/dist/pets-plugin.js +4 -347
- package/dist/toys-forms.cjs +609 -0
- package/dist/toys-forms.d.cts +35 -0
- package/dist/toys-forms.d.ts +35 -0
- package/dist/toys-forms.js +4 -0
- package/dist/toys-interactions.cjs +594 -0
- package/dist/toys-interactions.d.cts +54 -0
- package/dist/toys-interactions.d.ts +54 -0
- package/dist/toys-interactions.js +520 -0
- package/dist/toys-plugin.cjs +713 -0
- package/dist/toys-plugin.d.cts +88 -0
- package/dist/toys-plugin.d.ts +88 -0
- package/dist/toys-plugin.js +10 -0
- package/dist/toys-publication.cjs +437 -0
- package/dist/toys-publication.d.cts +26 -0
- package/dist/toys-publication.d.ts +26 -0
- package/dist/toys-publication.js +72 -0
- package/dist/toys-server.cjs +275 -0
- package/dist/toys-server.d.cts +28 -0
- package/dist/toys-server.d.ts +28 -0
- package/dist/toys-server.js +4 -0
- package/dist/toys-view.cjs +420 -0
- package/dist/toys-view.d.cts +55 -0
- package/dist/toys-view.d.ts +55 -0
- package/dist/toys-view.js +2 -0
- package/dist/toys.cjs +196 -0
- package/dist/toys.d.cts +278 -0
- package/dist/toys.d.ts +278 -0
- package/dist/toys.js +1 -0
- package/package.json +40 -3
- package/toys.css +823 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { safeToyLink, toyOptionLabel, TOY_AGE_RANGES, TOY_CONDITIONS, TOY_CATEGORIES, hoursSummary, TOY_HOW_IT_WORKS, TOY_SAFETY, TOY_EXCLUSIONS, TOY_BRAND, TOY_STATUS_LABELS } from './chunk-FHRO2Z3F.js';
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
function ToyRoundMark({ size = 40 }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("svg", { className: "toy-mark", width: size, height: size, viewBox: "0 0 64 64", "aria-hidden": "true", focusable: "false", children: [
|
|
6
|
+
/* @__PURE__ */ jsx("circle", { cx: "32", cy: "32", r: "24", fill: "none", stroke: "var(--toy-logo-ring, #1f2a44)", strokeWidth: "7" }),
|
|
7
|
+
/* @__PURE__ */ jsx("circle", { cx: "32", cy: "32", r: "24", fill: "none", stroke: "var(--toy-logo-arc, #ffb703)", strokeWidth: "7", strokeDasharray: "52 200", strokeLinecap: "round", transform: "rotate(-70 32 32)" }),
|
|
8
|
+
/* @__PURE__ */ jsx("rect", { x: "40", y: "6", width: "16", height: "16", rx: "4", fill: "var(--toy-logo-block, #ef6351)", transform: "rotate(14 48 14)" }),
|
|
9
|
+
/* @__PURE__ */ jsx("circle", { cx: "32", cy: "32", r: "8", fill: "var(--toy-logo-core, #2a9d8f)" })
|
|
10
|
+
] });
|
|
11
|
+
}
|
|
12
|
+
function ToyWordmark({ size = 34, href = "/" }) {
|
|
13
|
+
return /* @__PURE__ */ jsxs("a", { className: "toy-brand", href: safeToyLink(href) || "/", children: [
|
|
14
|
+
/* @__PURE__ */ jsx(ToyRoundMark, { size }),
|
|
15
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
16
|
+
"Toy",
|
|
17
|
+
/* @__PURE__ */ jsx("em", { children: "Round" })
|
|
18
|
+
] })
|
|
19
|
+
] });
|
|
20
|
+
}
|
|
21
|
+
function ToyPhoto({ listing, mediaUrl, large = false, index = 0 }) {
|
|
22
|
+
const photo = listing.media[index];
|
|
23
|
+
const src = photo && safeToyLink(mediaUrl(listing.id, photo.id));
|
|
24
|
+
if (!src)
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { className: "toy-photo-empty", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ToyRoundMark, { size: 48 }) });
|
|
26
|
+
const separator = src.includes("?") ? "&" : "?";
|
|
27
|
+
return /* @__PURE__ */ jsx("figure", { className: "toy-photo", children: /* @__PURE__ */ jsxs("picture", { children: [
|
|
28
|
+
/* @__PURE__ */ jsx("source", { type: "image/webp", srcSet: `${src}${separator}width=640&format=webp 640w, ${src}${separator}width=1280&format=webp 1280w`, sizes: large ? "(max-width: 700px) 100vw, 60vw" : "(max-width: 700px) 100vw, 30vw" }),
|
|
29
|
+
/* @__PURE__ */ jsx("img", { src: `${src}${separator}width=${large ? 1280 : 640}&format=jpeg`, alt: photo.caption || listing.content.title, width: large ? 1200 : 640, height: large ? 900 : 480, loading: large ? "eager" : "lazy" })
|
|
30
|
+
] }) });
|
|
31
|
+
}
|
|
32
|
+
function ToyBadges({ listing }) {
|
|
33
|
+
return /* @__PURE__ */ jsxs("p", { className: "toy-badges", children: [
|
|
34
|
+
/* @__PURE__ */ jsx("span", { className: `toy-badge toy-badge-${listing.exchange_type}`, children: listing.exchange_type === "swap" ? "Swap" : "Free" }),
|
|
35
|
+
/* @__PURE__ */ jsx("span", { className: "toy-badge", children: toyOptionLabel(TOY_AGE_RANGES, listing.age_range) }),
|
|
36
|
+
/* @__PURE__ */ jsx("span", { className: "toy-badge", children: toyOptionLabel(TOY_CONDITIONS, listing.condition) }),
|
|
37
|
+
listing.status === "reserved" && /* @__PURE__ */ jsx("span", { className: "toy-badge toy-badge-reserved", children: "Reserved" })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
function ToyListingCard(props) {
|
|
41
|
+
const href = safeToyLink(props.href);
|
|
42
|
+
const { listing } = props;
|
|
43
|
+
return /* @__PURE__ */ jsxs("article", { className: `toy-card${listing.status === "reserved" ? " toy-card-reserved" : ""}`, children: [
|
|
44
|
+
/* @__PURE__ */ jsx(ToyPhoto, { ...props }),
|
|
45
|
+
/* @__PURE__ */ jsxs("div", { className: "toy-card-copy", children: [
|
|
46
|
+
/* @__PURE__ */ jsx(ToyBadges, { listing }),
|
|
47
|
+
/* @__PURE__ */ jsx("h3", { children: href ? /* @__PURE__ */ jsx("a", { href, children: listing.content.title }) : listing.content.title }),
|
|
48
|
+
/* @__PURE__ */ jsxs("p", { className: "toy-context", children: [
|
|
49
|
+
toyOptionLabel(TOY_CATEGORIES, listing.category),
|
|
50
|
+
listing.community ? ` \xB7 ${listing.community}` : ""
|
|
51
|
+
] }),
|
|
52
|
+
listing.content.completeness === "missing_parts" && /* @__PURE__ */ jsx("p", { className: "toy-note", children: "Missing parts disclosed" })
|
|
53
|
+
] })
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
function ToyLocationCard({ location }) {
|
|
57
|
+
const map = safeToyLink(location.map_url);
|
|
58
|
+
const source = safeToyLink(location.source_url);
|
|
59
|
+
const kind = location.kind === "official_exchange_zone" ? "Official exchange zone" : location.kind === "participating_business" ? "Participating business" : "Public meeting place";
|
|
60
|
+
return /* @__PURE__ */ jsxs("article", { className: "toy-location", children: [
|
|
61
|
+
/* @__PURE__ */ jsx("p", { className: "toy-context", children: kind }),
|
|
62
|
+
/* @__PURE__ */ jsx("h3", { children: location.name }),
|
|
63
|
+
/* @__PURE__ */ jsx("p", { children: location.address }),
|
|
64
|
+
/* @__PURE__ */ jsxs("p", { className: "toy-note", children: [
|
|
65
|
+
"Hours: ",
|
|
66
|
+
hoursSummary(location.hours) || "See source"
|
|
67
|
+
] }),
|
|
68
|
+
location.restrictions && /* @__PURE__ */ jsx("p", { className: "toy-note", children: location.restrictions }),
|
|
69
|
+
Object.entries(location.verified_facts).map(([key, fact]) => /* @__PURE__ */ jsxs("p", { className: "toy-note", children: [
|
|
70
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
71
|
+
key,
|
|
72
|
+
":"
|
|
73
|
+
] }),
|
|
74
|
+
" ",
|
|
75
|
+
fact.text,
|
|
76
|
+
fact.source_url && safeToyLink(fact.source_url) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
" ",
|
|
78
|
+
/* @__PURE__ */ jsx("a", { href: safeToyLink(fact.source_url), rel: "noopener noreferrer", children: "source" })
|
|
79
|
+
] })
|
|
80
|
+
] }, key)),
|
|
81
|
+
location.hosting_partnership && /* @__PURE__ */ jsxs("p", { className: "toy-note", children: [
|
|
82
|
+
"Hosting partner: ",
|
|
83
|
+
location.partnership_note
|
|
84
|
+
] }),
|
|
85
|
+
/* @__PURE__ */ jsxs("p", { className: "toy-location-links", children: [
|
|
86
|
+
map && /* @__PURE__ */ jsx("a", { href: map, rel: "noopener noreferrer", children: "Map" }),
|
|
87
|
+
source && /* @__PURE__ */ jsx("a", { href: source, rel: "noopener noreferrer", children: "Source" }),
|
|
88
|
+
location.last_checked_on && /* @__PURE__ */ jsxs("small", { children: [
|
|
89
|
+
"Last checked ",
|
|
90
|
+
location.last_checked_on
|
|
91
|
+
] })
|
|
92
|
+
] })
|
|
93
|
+
] });
|
|
94
|
+
}
|
|
95
|
+
function ToyHowItWorks() {
|
|
96
|
+
return /* @__PURE__ */ jsxs("section", { className: "toy-how", "aria-labelledby": "toy-how-title", children: [
|
|
97
|
+
/* @__PURE__ */ jsx("h2", { id: "toy-how-title", children: "How it works" }),
|
|
98
|
+
/* @__PURE__ */ jsx("ol", { children: TOY_HOW_IT_WORKS.map((step, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
99
|
+
/* @__PURE__ */ jsx("span", { className: "toy-step-number", "aria-hidden": "true", children: index + 1 }),
|
|
100
|
+
/* @__PURE__ */ jsx("strong", { children: step.title }),
|
|
101
|
+
/* @__PURE__ */ jsx("p", { children: step.detail })
|
|
102
|
+
] }, step.title)) }),
|
|
103
|
+
/* @__PURE__ */ jsx("p", { className: "toy-safety", children: TOY_SAFETY.summary })
|
|
104
|
+
] });
|
|
105
|
+
}
|
|
106
|
+
function ToyRulesContent() {
|
|
107
|
+
return /* @__PURE__ */ jsxs("div", { className: "toy-rules", children: [
|
|
108
|
+
/* @__PURE__ */ jsxs("section", { children: [
|
|
109
|
+
/* @__PURE__ */ jsx("h2", { children: "Community rules" }),
|
|
110
|
+
/* @__PURE__ */ jsxs("ul", { children: [
|
|
111
|
+
/* @__PURE__ */ jsx("li", { children: "Adults only. Posting and requesting need an 18+ statement plus a verified email and phone. Browsing is open to everyone." }),
|
|
112
|
+
/* @__PURE__ */ jsx("li", { children: "Free giveaways and direct swaps only. No sales, payments, deposits, shipping or delivery fees \u2014 ever." }),
|
|
113
|
+
/* @__PURE__ */ jsx("li", { children: "Real photos of the actual toy, with wear, damage and missing pieces disclosed." }),
|
|
114
|
+
/* @__PURE__ */ jsx("li", { children: "Exchanges happen at listed public places, during the day, with both neighbors confirming the time. No home or porch pickups." }),
|
|
115
|
+
/* @__PURE__ */ jsx("li", { children: "Keep coordination inside ToyRound. Use report and block if anything feels off." }),
|
|
116
|
+
/* @__PURE__ */ jsx("li", { children: "Editors review every listing before it appears, and may decline, edit or remove listings and suspend accounts." })
|
|
117
|
+
] })
|
|
118
|
+
] }),
|
|
119
|
+
/* @__PURE__ */ jsxs("section", { children: [
|
|
120
|
+
/* @__PURE__ */ jsx("h2", { children: "Prohibited items" }),
|
|
121
|
+
/* @__PURE__ */ jsx("p", { children: "ToyRound is for ordinary toys, puzzles, games and play sets. These are not accepted:" }),
|
|
122
|
+
/* @__PURE__ */ jsx("ul", { children: TOY_EXCLUSIONS.map((item) => /* @__PURE__ */ jsx("li", { children: item.label }, item.key)) }),
|
|
123
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
124
|
+
"Before listing, search the",
|
|
125
|
+
" ",
|
|
126
|
+
/* @__PURE__ */ jsx("a", { href: "https://www.cpsc.gov/Recalls", rel: "noopener noreferrer", children: "CPSC recall database" }),
|
|
127
|
+
" ",
|
|
128
|
+
"for the brand and model. ",
|
|
129
|
+
TOY_SAFETY.recall
|
|
130
|
+
] })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs("section", { children: [
|
|
133
|
+
/* @__PURE__ */ jsx("h2", { children: "Privacy and safety" }),
|
|
134
|
+
/* @__PURE__ */ jsxs("ul", { children: [
|
|
135
|
+
/* @__PURE__ */ jsx("li", { children: "Public profiles show a first name or chosen display name, community, join month and participant-confirmed completed exchanges. Nothing else." }),
|
|
136
|
+
/* @__PURE__ */ jsx("li", { children: "Legal names, phone numbers, email addresses and home addresses are never shown. ToyRound does not collect identity documents." }),
|
|
137
|
+
/* @__PURE__ */ jsx("li", { children: "Location data and other metadata are removed from uploaded photos." }),
|
|
138
|
+
/* @__PURE__ */ jsx("li", { children: TOY_SAFETY.children }),
|
|
139
|
+
/* @__PURE__ */ jsx("li", { children: TOY_SAFETY.verification }),
|
|
140
|
+
/* @__PURE__ */ jsx("li", { children: "Conversations, appointments and drafts are private to the two neighbors involved. Reported conversations may be reviewed by editors as moderation evidence." }),
|
|
141
|
+
/* @__PURE__ */ jsx("li", { children: "You can delete your ToyRound account from your account page. Listings are withdrawn, open exchanges are cancelled, and your profile is anonymized. Reports and blocks are retained under the platform's moderation retention policy." }),
|
|
142
|
+
/* @__PURE__ */ jsx("li", { children: TOY_SAFETY.summary })
|
|
143
|
+
] })
|
|
144
|
+
] })
|
|
145
|
+
] });
|
|
146
|
+
}
|
|
147
|
+
function ToysSection({
|
|
148
|
+
communities,
|
|
149
|
+
community,
|
|
150
|
+
listings,
|
|
151
|
+
basePath = "/toys",
|
|
152
|
+
mediaUrl,
|
|
153
|
+
listingBasePath,
|
|
154
|
+
browsePath,
|
|
155
|
+
submitUrl,
|
|
156
|
+
accountUrl,
|
|
157
|
+
locationsUrl,
|
|
158
|
+
rulesUrl,
|
|
159
|
+
regionLabel,
|
|
160
|
+
nextUrl,
|
|
161
|
+
unavailable,
|
|
162
|
+
submissionsOpen = true,
|
|
163
|
+
locationCount,
|
|
164
|
+
filters = {},
|
|
165
|
+
embedded = false,
|
|
166
|
+
signedIn = false
|
|
167
|
+
}) {
|
|
168
|
+
const link = (id) => `${listingBasePath || basePath}/${encodeURIComponent(id)}`;
|
|
169
|
+
const location = community?.name || regionLabel || "the Bay Area";
|
|
170
|
+
const browse = browsePath || basePath;
|
|
171
|
+
const query = new URLSearchParams(Object.entries(filters).filter((e) => typeof e[1] === "string" && e[1] !== ""));
|
|
172
|
+
if (community) query.set("community", community.slug);
|
|
173
|
+
const find = browse + (query.size ? "?" + query : "");
|
|
174
|
+
return /* @__PURE__ */ jsxs("div", { className: `toy${embedded ? " toy-embedded" : ""}`, children: [
|
|
175
|
+
/* @__PURE__ */ jsxs("header", { className: "toy-masthead", children: [
|
|
176
|
+
/* @__PURE__ */ jsx(ToyWordmark, { href: embedded ? basePath : "/" }),
|
|
177
|
+
/* @__PURE__ */ jsx("p", { className: "toy-tagline", children: TOY_BRAND.tagline }),
|
|
178
|
+
/* @__PURE__ */ jsxs("nav", { className: "toy-masthead-links", "aria-label": "ToyRound", children: [
|
|
179
|
+
rulesUrl && /* @__PURE__ */ jsx("a", { href: safeToyLink(rulesUrl), children: "Rules & safety" }),
|
|
180
|
+
locationsUrl && /* @__PURE__ */ jsx("a", { href: safeToyLink(locationsUrl), children: "Where to meet" }),
|
|
181
|
+
accountUrl && /* @__PURE__ */ jsx("a", { href: safeToyLink(accountUrl), children: signedIn ? "My toys" : "Sign in" })
|
|
182
|
+
] })
|
|
183
|
+
] }),
|
|
184
|
+
unavailable ? /* @__PURE__ */ jsxs("div", { role: "status", className: "toy-empty", children: [
|
|
185
|
+
/* @__PURE__ */ jsx("h1", { children: "ToyRound is taking a short break." }),
|
|
186
|
+
/* @__PURE__ */ jsx("p", { children: "We can't load the exchange right now. Please try again shortly." })
|
|
187
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
188
|
+
/* @__PURE__ */ jsxs("section", { className: "toy-hero", "aria-labelledby": "toy-hero-title", children: [
|
|
189
|
+
/* @__PURE__ */ jsxs("div", { className: "toy-hero-copy", children: [
|
|
190
|
+
/* @__PURE__ */ jsxs("p", { className: "toy-eyebrow", children: [
|
|
191
|
+
"Free giveaways and swaps in ",
|
|
192
|
+
location
|
|
193
|
+
] }),
|
|
194
|
+
/* @__PURE__ */ jsxs("h1", { id: "toy-hero-title", children: [
|
|
195
|
+
"Pass along",
|
|
196
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
197
|
+
"the play."
|
|
198
|
+
] }),
|
|
199
|
+
/* @__PURE__ */ jsx("p", { className: "toy-hero-detail", children: "Outgrown toys find new homes with neighbors. No money changes hands, and exchanges happen at public places during the day." }),
|
|
200
|
+
/* @__PURE__ */ jsxs("div", { className: "toy-hero-actions", children: [
|
|
201
|
+
/* @__PURE__ */ jsx("a", { className: "toy-button", href: find, children: "Find a toy" }),
|
|
202
|
+
submitUrl && /* @__PURE__ */ jsx("a", { className: "toy-button toy-button-secondary", href: safeToyLink(submitUrl), children: "Give or swap a toy" })
|
|
203
|
+
] }),
|
|
204
|
+
!submissionsOpen && /* @__PURE__ */ jsx("p", { className: "toy-note", children: "New listings are paused while our review team gets ready. Browsing stays open." })
|
|
205
|
+
] }),
|
|
206
|
+
/* @__PURE__ */ jsx("div", { className: "toy-hero-art", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ToyRoundMark, { size: 180 }) })
|
|
207
|
+
] }),
|
|
208
|
+
/* @__PURE__ */ jsxs("section", { className: "toy-community", "aria-label": "Choose your community", children: [
|
|
209
|
+
/* @__PURE__ */ jsxs("form", { action: browse, method: "get", className: "toy-filters", children: [
|
|
210
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
211
|
+
"Community",
|
|
212
|
+
/* @__PURE__ */ jsxs("select", { name: "community", defaultValue: community?.slug || "", children: [
|
|
213
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "All communities" }),
|
|
214
|
+
communities.map((c) => /* @__PURE__ */ jsx("option", { value: c.slug, children: c.name }, c.id))
|
|
215
|
+
] })
|
|
216
|
+
] }),
|
|
217
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
218
|
+
"Category",
|
|
219
|
+
/* @__PURE__ */ jsxs("select", { name: "category", defaultValue: filters.category || "", children: [
|
|
220
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Any category" }),
|
|
221
|
+
TOY_CATEGORIES.map((c) => /* @__PURE__ */ jsx("option", { value: c.key, children: c.label }, c.key))
|
|
222
|
+
] })
|
|
223
|
+
] }),
|
|
224
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
225
|
+
"Age guidance",
|
|
226
|
+
/* @__PURE__ */ jsxs("select", { name: "age_range", defaultValue: filters.age_range || "", children: [
|
|
227
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Any age" }),
|
|
228
|
+
TOY_AGE_RANGES.map((c) => /* @__PURE__ */ jsx("option", { value: c.key, children: c.label }, c.key))
|
|
229
|
+
] })
|
|
230
|
+
] }),
|
|
231
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
232
|
+
"Condition",
|
|
233
|
+
/* @__PURE__ */ jsxs("select", { name: "condition", defaultValue: filters.condition || "", children: [
|
|
234
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Any condition" }),
|
|
235
|
+
TOY_CONDITIONS.map((c) => /* @__PURE__ */ jsx("option", { value: c.key, children: c.label }, c.key))
|
|
236
|
+
] })
|
|
237
|
+
] }),
|
|
238
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
239
|
+
"Type",
|
|
240
|
+
/* @__PURE__ */ jsxs("select", { name: "exchange_type", defaultValue: filters.exchange_type || "", children: [
|
|
241
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Free or swap" }),
|
|
242
|
+
/* @__PURE__ */ jsx("option", { value: "giveaway", children: "Free giveaways" }),
|
|
243
|
+
/* @__PURE__ */ jsx("option", { value: "swap", children: "Swaps" })
|
|
244
|
+
] })
|
|
245
|
+
] }),
|
|
246
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
247
|
+
"Availability",
|
|
248
|
+
/* @__PURE__ */ jsxs("select", { name: "availability", defaultValue: filters.availability || "", children: [
|
|
249
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Include reserved" }),
|
|
250
|
+
/* @__PURE__ */ jsx("option", { value: "available", children: "Available now" })
|
|
251
|
+
] })
|
|
252
|
+
] }),
|
|
253
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
254
|
+
"Search",
|
|
255
|
+
/* @__PURE__ */ jsx("input", { name: "q", maxLength: 80, defaultValue: filters.q || "", placeholder: "Train set, puzzle, Brio\u2026" })
|
|
256
|
+
] }),
|
|
257
|
+
/* @__PURE__ */ jsx("button", { type: "submit", children: "Show toys" })
|
|
258
|
+
] }),
|
|
259
|
+
locationCount === 0 && community && /* @__PURE__ */ jsxs("p", { className: "toy-note toy-location-warning", children: [
|
|
260
|
+
"No checked meeting places are listed for ",
|
|
261
|
+
community.name,
|
|
262
|
+
" yet, so exchanges can't be arranged there until one is added. You can still browse, list, and",
|
|
263
|
+
" ",
|
|
264
|
+
locationsUrl ? /* @__PURE__ */ jsx("a", { href: safeToyLink(locationsUrl), children: "suggest a public meeting place" }) : "suggest a public meeting place",
|
|
265
|
+
"."
|
|
266
|
+
] })
|
|
267
|
+
] }),
|
|
268
|
+
/* @__PURE__ */ jsxs("section", { className: "toy-section", "aria-labelledby": "toy-listings-title", children: [
|
|
269
|
+
/* @__PURE__ */ jsxs("div", { className: "toy-section-heading", children: [
|
|
270
|
+
/* @__PURE__ */ jsx("h2", { id: "toy-listings-title", children: community ? `Toys in ${community.name}` : "Toys across the network" }),
|
|
271
|
+
/* @__PURE__ */ jsx("p", { children: "Every listing is reviewed by a local editor before it appears." })
|
|
272
|
+
] }),
|
|
273
|
+
listings.length ? /* @__PURE__ */ jsx("div", { className: "toy-grid", children: listings.map((listing) => /* @__PURE__ */ jsx(ToyListingCard, { listing, href: link(listing.id), mediaUrl }, listing.id)) }) : /* @__PURE__ */ jsxs("div", { className: "toy-board-invitation", children: [
|
|
274
|
+
/* @__PURE__ */ jsx(ToyRoundMark, { size: 56 }),
|
|
275
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
276
|
+
/* @__PURE__ */ jsxs("h3", { children: [
|
|
277
|
+
"Be the first to pass along the play in ",
|
|
278
|
+
location,
|
|
279
|
+
"."
|
|
280
|
+
] }),
|
|
281
|
+
/* @__PURE__ */ jsx("p", { children: "No approved listings match yet. When neighbors list toys here, they'll appear after review." })
|
|
282
|
+
] }),
|
|
283
|
+
submitUrl && /* @__PURE__ */ jsx("a", { className: "toy-text-link", href: safeToyLink(submitUrl), children: "List a toy" })
|
|
284
|
+
] }),
|
|
285
|
+
nextUrl && /* @__PURE__ */ jsx("a", { className: "toy-button toy-button-secondary", href: safeToyLink(nextUrl), children: "More toys" })
|
|
286
|
+
] }),
|
|
287
|
+
/* @__PURE__ */ jsx(ToyHowItWorks, {})
|
|
288
|
+
] }),
|
|
289
|
+
/* @__PURE__ */ jsxs("footer", { className: "toy-footer", children: [
|
|
290
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
291
|
+
/* @__PURE__ */ jsx(ToyWordmark, { size: 28, href: embedded ? TOY_BRAND.origin : "/" }),
|
|
292
|
+
/* @__PURE__ */ jsx("p", { children: TOY_BRAND.tagline })
|
|
293
|
+
] }),
|
|
294
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
295
|
+
embedded ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
296
|
+
/* @__PURE__ */ jsx("a", { href: TOY_BRAND.origin, children: TOY_BRAND.poweredBy }),
|
|
297
|
+
/* @__PURE__ */ jsx("br", {})
|
|
298
|
+
] }) : null,
|
|
299
|
+
"A community toy exchange by ",
|
|
300
|
+
/* @__PURE__ */ jsx("a", { href: TOY_BRAND.networkUrl, children: "Bay Area News Network" }),
|
|
301
|
+
"."
|
|
302
|
+
] }),
|
|
303
|
+
/* @__PURE__ */ jsxs("p", { className: "toy-footer-links", children: [
|
|
304
|
+
rulesUrl && /* @__PURE__ */ jsx("a", { href: safeToyLink(rulesUrl), children: "Rules, prohibited items, privacy & safety" }),
|
|
305
|
+
locationsUrl && /* @__PURE__ */ jsx("a", { href: safeToyLink(locationsUrl), children: "Meeting places" })
|
|
306
|
+
] })
|
|
307
|
+
] })
|
|
308
|
+
] });
|
|
309
|
+
}
|
|
310
|
+
function toyStatusLabel(status) {
|
|
311
|
+
return TOY_STATUS_LABELS[status] || status;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export { ToyBadges, ToyHowItWorks, ToyListingCard, ToyLocationCard, ToyPhoto, ToyRoundMark, ToyRulesContent, ToyWordmark, ToysSection, toyStatusLabel };
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// src/toys.ts
|
|
2
|
+
var TOY_BRAND = {
|
|
3
|
+
name: "ToyRound",
|
|
4
|
+
tagline: "Pass along the play.",
|
|
5
|
+
attribution: "A community toy exchange by Bay Area News Network.",
|
|
6
|
+
poweredBy: "Powered by ToyRound",
|
|
7
|
+
publicationLabel: "Toy Swap",
|
|
8
|
+
origin: "https://toyround.com",
|
|
9
|
+
networkUrl: "https://bayareanewsnetwork.com"
|
|
10
|
+
};
|
|
11
|
+
var TOY_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;
|
|
12
|
+
var TOY_SLUG = /^[a-z0-9][a-z0-9-]{0,190}$/;
|
|
13
|
+
var TOY_EXCHANGE_TYPES = [
|
|
14
|
+
{ key: "giveaway", label: "Free giveaway" },
|
|
15
|
+
{ key: "swap", label: "Direct swap" }
|
|
16
|
+
];
|
|
17
|
+
var TOY_CATEGORIES = [
|
|
18
|
+
{ key: "building", label: "Building & construction" },
|
|
19
|
+
{ key: "puzzles", label: "Puzzles" },
|
|
20
|
+
{ key: "games", label: "Board & card games" },
|
|
21
|
+
{ key: "dolls_figures", label: "Dolls & action figures" },
|
|
22
|
+
{ key: "vehicles", label: "Vehicles & trains" },
|
|
23
|
+
{ key: "outdoor", label: "Outdoor & active play" },
|
|
24
|
+
{ key: "arts_crafts", label: "Arts & crafts" },
|
|
25
|
+
{ key: "pretend_play", label: "Pretend play & play sets" },
|
|
26
|
+
{ key: "stem_learning", label: "STEM & learning" },
|
|
27
|
+
{ key: "plush", label: "Plush & soft toys" },
|
|
28
|
+
{ key: "books_media", label: "Books & media" },
|
|
29
|
+
{ key: "baby_toddler", label: "Baby & toddler toys" },
|
|
30
|
+
{ key: "musical", label: "Musical toys" },
|
|
31
|
+
{ key: "other", label: "Other toys" }
|
|
32
|
+
];
|
|
33
|
+
var TOY_AGE_RANGES = [
|
|
34
|
+
{ key: "0-12m", label: "0\u201312 months" },
|
|
35
|
+
{ key: "1-2", label: "1\u20132 years" },
|
|
36
|
+
{ key: "3-5", label: "3\u20135 years" },
|
|
37
|
+
{ key: "6-8", label: "6\u20138 years" },
|
|
38
|
+
{ key: "9-12", label: "9\u201312 years" },
|
|
39
|
+
{ key: "13+", label: "13 and up" },
|
|
40
|
+
{ key: "unknown", label: "Not stated on the item" }
|
|
41
|
+
];
|
|
42
|
+
var TOY_CONDITIONS = [
|
|
43
|
+
{ key: "like_new", label: "Like new" },
|
|
44
|
+
{ key: "good", label: "Good \u2014 normal wear" },
|
|
45
|
+
{ key: "fair", label: "Fair \u2014 visible wear, works" }
|
|
46
|
+
];
|
|
47
|
+
var TOY_EXCLUSIONS = [
|
|
48
|
+
{ key: "car_seats", label: "Car seats and booster seats" },
|
|
49
|
+
{ key: "cribs_sleep", label: "Cribs, bassinets and infant sleep equipment" },
|
|
50
|
+
{ key: "helmets", label: "Helmets and protective gear" },
|
|
51
|
+
{ key: "weapons", label: "Weapons, replica weapons and hard-tipped projectile toys" },
|
|
52
|
+
{ key: "water_beads", label: "Water beads" },
|
|
53
|
+
{ key: "magnets", label: "Loose high-powered magnets and magnet sets" },
|
|
54
|
+
{ key: "recalled", label: "Anything subject to a CPSC recall" },
|
|
55
|
+
{ key: "broken", label: "Visibly unsafe, broken or sharp-edged items" },
|
|
56
|
+
{ key: "batteries", label: "Items with loose button or coin batteries" }
|
|
57
|
+
];
|
|
58
|
+
var TOY_REPORT_REASONS = [
|
|
59
|
+
{ key: "recalled_or_unsafe", label: "Recalled or unsafe item" },
|
|
60
|
+
{ key: "child_safety", label: "Child safety concern" },
|
|
61
|
+
{ key: "harassment", label: "Harassment or threats" },
|
|
62
|
+
{ key: "scam_or_payment", label: "Asked for money, deposits or codes" },
|
|
63
|
+
{ key: "prohibited_item", label: "Prohibited item" },
|
|
64
|
+
{ key: "inappropriate_photo", label: "Inappropriate photo" },
|
|
65
|
+
{ key: "no_show", label: "No-show" },
|
|
66
|
+
{ key: "misleading_listing", label: "Misleading listing" },
|
|
67
|
+
{ key: "spam", label: "Spam" },
|
|
68
|
+
{ key: "other", label: "Something else" }
|
|
69
|
+
];
|
|
70
|
+
var TOY_CPSC_RECALLS_URL = "https://www.cpsc.gov/Recalls";
|
|
71
|
+
var TOY_STATUS_LABELS = {
|
|
72
|
+
draft: "Draft",
|
|
73
|
+
pending_review: "Waiting for review",
|
|
74
|
+
available: "Available",
|
|
75
|
+
reserved: "Reserved",
|
|
76
|
+
completed: "Completed",
|
|
77
|
+
rejected: "Needs changes",
|
|
78
|
+
withdrawn: "Withdrawn",
|
|
79
|
+
expired: "Expired",
|
|
80
|
+
suspended: "Suspended for safety review"
|
|
81
|
+
};
|
|
82
|
+
var TOY_REQUEST_STATUS_LABELS = {
|
|
83
|
+
pending: "Waiting for the owner",
|
|
84
|
+
accepted: "Accepted \u2014 arrange a meeting",
|
|
85
|
+
declined: "Declined",
|
|
86
|
+
cancelled: "Cancelled",
|
|
87
|
+
completed: "Completed",
|
|
88
|
+
expired: "Expired"
|
|
89
|
+
};
|
|
90
|
+
var TOY_SAFETY = {
|
|
91
|
+
summary: "Public places and account verification reduce risk but do not guarantee safety. ToyRound is not supervised and no one is on call.",
|
|
92
|
+
verification: "\u201CPhone verified\u201D and \u201Cemail verified\u201D mean a working contact method was confirmed. They are not an identity check, a background check or a statement that someone is trustworthy.",
|
|
93
|
+
meeting: "Meet only at a listed public place during the day, keep arrangements in this thread, and bring someone along if you like. Never share your home address.",
|
|
94
|
+
money: "ToyRound never involves payments, deposits, shipping fees or verification codes. Anyone asking for them is breaking the rules \u2014 report them.",
|
|
95
|
+
recall: "A member's recall check is their own statement after searching the CPSC database. It is not a safety certification, and ToyRound never labels an item recall-free or certified.",
|
|
96
|
+
children: "Do not share children's names, photos, schools or schedules. Manufacturer age guidance is reported as printed; ToyRound never decides what is safe for a particular child."
|
|
97
|
+
};
|
|
98
|
+
var TOY_HOW_IT_WORKS = [
|
|
99
|
+
{ title: "List a toy", detail: "Real photos, honest condition, a quick CPSC recall search. Editors review every listing before it appears." },
|
|
100
|
+
{ title: "Agree on an exchange", detail: "Neighbors ask for the toy or propose a swap. You decide, and the toy is reserved for one person at a time." },
|
|
101
|
+
{ title: "Meet in public", detail: "Pick a listed public place and a daytime slot that both of you confirm. No home or porch pickups." },
|
|
102
|
+
{ title: "Pass along the play", detail: "Both of you mark the exchange complete. Private feedback helps keep the exchange friendly." }
|
|
103
|
+
];
|
|
104
|
+
function toyOptionLabel(options, key) {
|
|
105
|
+
return options.find((o) => o.key === key)?.label || key;
|
|
106
|
+
}
|
|
107
|
+
function resolveToyCommunity(areas, selected, preference, publicationDefault) {
|
|
108
|
+
if (selected === "" || selected === void 0 && preference === "all") return void 0;
|
|
109
|
+
for (const candidate of [selected, preference, publicationDefault]) {
|
|
110
|
+
const found = areas.find((area) => area.id === candidate || area.slug === candidate);
|
|
111
|
+
if (found) return found;
|
|
112
|
+
}
|
|
113
|
+
return void 0;
|
|
114
|
+
}
|
|
115
|
+
function safeToyLink(raw) {
|
|
116
|
+
if (!raw) return void 0;
|
|
117
|
+
if (raw.startsWith("/") && !raw.startsWith("//") && !/[\\\r\n]/.test(raw)) return raw;
|
|
118
|
+
try {
|
|
119
|
+
const url = new URL(raw);
|
|
120
|
+
return url.protocol === "https:" && !url.username && !url.password ? url.href : void 0;
|
|
121
|
+
} catch {
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function toyListingMetadata(listing, canonicalUrl, photoUrl) {
|
|
126
|
+
const canonical = safeToyLink(canonicalUrl);
|
|
127
|
+
if (!listing || !canonical?.startsWith("https://"))
|
|
128
|
+
return { title: "Listing unavailable", robots: { index: false, follow: false } };
|
|
129
|
+
const title = `${listing.content.title} \u2014 ${listing.exchange_type === "swap" ? "swap" : "free"} on ToyRound`;
|
|
130
|
+
const description = Array.from(listing.content.description).slice(0, 180).join("");
|
|
131
|
+
return {
|
|
132
|
+
title,
|
|
133
|
+
description,
|
|
134
|
+
alternates: { canonical },
|
|
135
|
+
openGraph: {
|
|
136
|
+
title,
|
|
137
|
+
description,
|
|
138
|
+
url: canonical,
|
|
139
|
+
...photoUrl && safeToyLink(photoUrl) ? { images: [{ url: photoUrl, alt: listing.content.title }] } : {}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function formatLocalStart(localStart, timezone) {
|
|
144
|
+
const [date, time] = localStart.split("T");
|
|
145
|
+
if (!date || !time) return localStart;
|
|
146
|
+
try {
|
|
147
|
+
const day = (/* @__PURE__ */ new Date(date + "T12:00:00Z")).toLocaleDateString("en-US", {
|
|
148
|
+
weekday: "short",
|
|
149
|
+
month: "short",
|
|
150
|
+
day: "numeric",
|
|
151
|
+
timeZone: "UTC"
|
|
152
|
+
});
|
|
153
|
+
const [h, m] = time.split(":").map(Number);
|
|
154
|
+
const hour12 = (h + 11) % 12 + 1;
|
|
155
|
+
const zone = timezone.split("/").pop()?.replaceAll("_", " ") || timezone;
|
|
156
|
+
return `${day}, ${hour12}:${String(m).padStart(2, "0")} ${h >= 12 ? "PM" : "AM"} (${zone} time)`;
|
|
157
|
+
} catch {
|
|
158
|
+
return localStart;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
var TOY_DAY_LABELS = {
|
|
162
|
+
mon: "Mon",
|
|
163
|
+
tue: "Tue",
|
|
164
|
+
wed: "Wed",
|
|
165
|
+
thu: "Thu",
|
|
166
|
+
fri: "Fri",
|
|
167
|
+
sat: "Sat",
|
|
168
|
+
sun: "Sun"
|
|
169
|
+
};
|
|
170
|
+
function hoursSummary(hours) {
|
|
171
|
+
return Object.entries(hours).map(([day, ranges]) => `${TOY_DAY_LABELS[day] || day} ${ranges.map(([o, c]) => `${o}\u2013${c}`).join(", ")}`).join(" \xB7 ");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { TOY_AGE_RANGES, TOY_BRAND, TOY_CATEGORIES, TOY_CONDITIONS, TOY_CPSC_RECALLS_URL, TOY_DAY_LABELS, TOY_EXCHANGE_TYPES, TOY_EXCLUSIONS, TOY_HOW_IT_WORKS, TOY_REPORT_REASONS, TOY_REQUEST_STATUS_LABELS, TOY_SAFETY, TOY_SLUG, TOY_STATUS_LABELS, TOY_UUID, formatLocalStart, hoursSummary, resolveToyCommunity, safeToyLink, toyListingMetadata, toyOptionLabel };
|