@scalemule/news-publication 0.0.8 → 0.0.10

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.
@@ -17,6 +17,9 @@ var CLASSIFIED_CATEGORIES = [
17
17
  { value: "community", label: "Community" },
18
18
  { value: "wanted", label: "Wanted" }
19
19
  ];
20
+ function dealDollars(cents) {
21
+ return cents != null ? `$${(cents / 100).toFixed(2)}` : null;
22
+ }
20
23
  function employmentLabel(value) {
21
24
  return JOB_EMPLOYMENT_TYPES.find((item) => item.value === value)?.label ?? "";
22
25
  }
@@ -62,11 +65,29 @@ function JobArticle({ job }) {
62
65
  ] })
63
66
  ] });
64
67
  }
68
+ function DealsBlock({ deals }) {
69
+ if (deals.length === 0) return null;
70
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "deals", "aria-label": "Deals", children: [
71
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Deals" }),
72
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: "We may earn a commission when you use these links." }),
73
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "list", children: deals.map((deal) => {
74
+ const offer = deal.offers[0];
75
+ if (!offer) return null;
76
+ const stores = deal.offers.map((item) => item.merchant).filter(Boolean).join(", ");
77
+ return /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "item", href: `/classifieds/out/${encodeURIComponent(offer.id)}`, children: [
78
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: deal.title }),
79
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: [stores, dealDollars(deal.price_cents ?? offer.price_cents), deal.coupon_code ? `Code ${deal.coupon_code}` : null, deal.locality].filter(Boolean).join(" \xB7 ") })
80
+ ] }, deal.id);
81
+ }) })
82
+ ] });
83
+ }
65
84
  function ClassifiedsBoard({
66
85
  region,
67
86
  listings,
68
- category
87
+ category,
88
+ deals = []
69
89
  }) {
90
+ const dealsFirst = listings.length < 8;
70
91
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "np-market", children: [
71
92
  /* @__PURE__ */ jsxRuntime.jsx("h1", { children: "Classifieds" }),
72
93
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "lead", children: [
@@ -82,13 +103,19 @@ function ClassifiedsBoard({
82
103
  /* @__PURE__ */ jsxRuntime.jsx("a", { className: !category ? "on" : void 0, href: "/classifieds", children: "All" }),
83
104
  CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsxRuntime.jsx("a", { className: category === item.value ? "on" : void 0, href: `/classifieds?category=${item.value}`, children: item.label }, item.value))
84
105
  ] }),
85
- listings.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "empty", children: [
106
+ dealsFirst ? /* @__PURE__ */ jsxRuntime.jsx(DealsBlock, { deals }) : null,
107
+ listings.length === 0 ? deals.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "empty", children: [
86
108
  /* @__PURE__ */ jsxRuntime.jsx("h2", { children: "No classifieds yet." }),
87
109
  /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Post something neighbors might need." })
110
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "meta", children: [
111
+ "No neighbor listings yet. ",
112
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: "/classifieds/post", children: "Place a listing" }),
113
+ "."
88
114
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "list", children: listings.map((listing) => /* @__PURE__ */ jsxRuntime.jsxs("a", { className: "item", href: `/classifieds/${encodeURIComponent(listing.id)}`, children: [
89
115
  /* @__PURE__ */ jsxRuntime.jsx("h2", { children: listing.title }),
90
116
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") })
91
- ] }, listing.id)) })
117
+ ] }, listing.id)) }),
118
+ dealsFirst ? null : /* @__PURE__ */ jsxRuntime.jsx(DealsBlock, { deals })
92
119
  ] });
93
120
  }
94
121
  function ClassifiedArticle({ listing }) {
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { b as ClassifiedListing, d as PublicJob } from './marketplace-Ch7mdJZv.cjs';
2
+ import { b as ClassifiedListing, d as PublicDeal, f as PublicJob } from './marketplace-CpGWPbFk.cjs';
3
3
 
4
4
  declare function JobsBoard({ region, jobs, query }: {
5
5
  region: string;
@@ -9,10 +9,11 @@ declare function JobsBoard({ region, jobs, query }: {
9
9
  declare function JobArticle({ job }: {
10
10
  job: PublicJob;
11
11
  }): react.JSX.Element;
12
- declare function ClassifiedsBoard({ region, listings, category, }: {
12
+ declare function ClassifiedsBoard({ region, listings, category, deals, }: {
13
13
  region: string;
14
14
  listings: ClassifiedListing[];
15
15
  category: string;
16
+ deals?: PublicDeal[];
16
17
  }): react.JSX.Element;
17
18
  declare function ClassifiedArticle({ listing }: {
18
19
  listing: ClassifiedListing;
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { b as ClassifiedListing, d as PublicJob } from './marketplace-Ch7mdJZv.js';
2
+ import { b as ClassifiedListing, d as PublicDeal, f as PublicJob } from './marketplace-CpGWPbFk.js';
3
3
 
4
4
  declare function JobsBoard({ region, jobs, query }: {
5
5
  region: string;
@@ -9,10 +9,11 @@ declare function JobsBoard({ region, jobs, query }: {
9
9
  declare function JobArticle({ job }: {
10
10
  job: PublicJob;
11
11
  }): react.JSX.Element;
12
- declare function ClassifiedsBoard({ region, listings, category, }: {
12
+ declare function ClassifiedsBoard({ region, listings, category, deals, }: {
13
13
  region: string;
14
14
  listings: ClassifiedListing[];
15
15
  category: string;
16
+ deals?: PublicDeal[];
16
17
  }): react.JSX.Element;
17
18
  declare function ClassifiedArticle({ listing }: {
18
19
  listing: ClassifiedListing;
@@ -1,4 +1,4 @@
1
- import { employmentLabel, CLASSIFIED_CATEGORIES, categoryLabel } from './chunk-YQXS2KQI.js';
1
+ import { employmentLabel, CLASSIFIED_CATEGORIES, categoryLabel, dealDollars } from './chunk-C7ZPLH2K.js';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
 
4
4
  function money(price) {
@@ -40,11 +40,29 @@ function JobArticle({ job }) {
40
40
  ] })
41
41
  ] });
42
42
  }
43
+ function DealsBlock({ deals }) {
44
+ if (deals.length === 0) return null;
45
+ return /* @__PURE__ */ jsxs("section", { className: "deals", "aria-label": "Deals", children: [
46
+ /* @__PURE__ */ jsx("h2", { children: "Deals" }),
47
+ /* @__PURE__ */ jsx("p", { className: "meta", children: "We may earn a commission when you use these links." }),
48
+ /* @__PURE__ */ jsx("div", { className: "list", children: deals.map((deal) => {
49
+ const offer = deal.offers[0];
50
+ if (!offer) return null;
51
+ const stores = deal.offers.map((item) => item.merchant).filter(Boolean).join(", ");
52
+ return /* @__PURE__ */ jsxs("a", { className: "item", href: `/classifieds/out/${encodeURIComponent(offer.id)}`, children: [
53
+ /* @__PURE__ */ jsx("h2", { children: deal.title }),
54
+ /* @__PURE__ */ jsx("p", { className: "meta", children: [stores, dealDollars(deal.price_cents ?? offer.price_cents), deal.coupon_code ? `Code ${deal.coupon_code}` : null, deal.locality].filter(Boolean).join(" \xB7 ") })
55
+ ] }, deal.id);
56
+ }) })
57
+ ] });
58
+ }
43
59
  function ClassifiedsBoard({
44
60
  region,
45
61
  listings,
46
- category
62
+ category,
63
+ deals = []
47
64
  }) {
65
+ const dealsFirst = listings.length < 8;
48
66
  return /* @__PURE__ */ jsxs("div", { className: "np-market", children: [
49
67
  /* @__PURE__ */ jsx("h1", { children: "Classifieds" }),
50
68
  /* @__PURE__ */ jsxs("p", { className: "lead", children: [
@@ -60,13 +78,19 @@ function ClassifiedsBoard({
60
78
  /* @__PURE__ */ jsx("a", { className: !category ? "on" : void 0, href: "/classifieds", children: "All" }),
61
79
  CLASSIFIED_CATEGORIES.map((item) => /* @__PURE__ */ jsx("a", { className: category === item.value ? "on" : void 0, href: `/classifieds?category=${item.value}`, children: item.label }, item.value))
62
80
  ] }),
63
- listings.length === 0 ? /* @__PURE__ */ jsxs("section", { className: "empty", children: [
81
+ dealsFirst ? /* @__PURE__ */ jsx(DealsBlock, { deals }) : null,
82
+ listings.length === 0 ? deals.length === 0 ? /* @__PURE__ */ jsxs("section", { className: "empty", children: [
64
83
  /* @__PURE__ */ jsx("h2", { children: "No classifieds yet." }),
65
84
  /* @__PURE__ */ jsx("p", { children: "Post something neighbors might need." })
85
+ ] }) : /* @__PURE__ */ jsxs("p", { className: "meta", children: [
86
+ "No neighbor listings yet. ",
87
+ /* @__PURE__ */ jsx("a", { href: "/classifieds/post", children: "Place a listing" }),
88
+ "."
66
89
  ] }) : /* @__PURE__ */ jsx("div", { className: "list", children: listings.map((listing) => /* @__PURE__ */ jsxs("a", { className: "item", href: `/classifieds/${encodeURIComponent(listing.id)}`, children: [
67
90
  /* @__PURE__ */ jsx("h2", { children: listing.title }),
68
91
  /* @__PURE__ */ jsx("p", { className: "meta", children: [categoryLabel(listing.category), listing.location?.town, money(listing.price)].filter(Boolean).join(" \xB7 ") })
69
- ] }, listing.id)) })
92
+ ] }, listing.id)) }),
93
+ dealsFirst ? null : /* @__PURE__ */ jsx(DealsBlock, { deals })
70
94
  ] });
71
95
  }
72
96
  function ClassifiedArticle({ listing }) {
@@ -0,0 +1,258 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/theme.ts
8
+ var THEME_COOKIE = "news_publication_theme";
9
+ var THEME_STORAGE_KEY = "news_publication_theme";
10
+ var THEME_EVENT = "news_publication_theme_change";
11
+ var THEME_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;
12
+ var memoryTheme = "system";
13
+ function getSystemTheme() {
14
+ if (typeof window === "undefined" || !window.matchMedia) return "light";
15
+ try {
16
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
17
+ } catch {
18
+ return "light";
19
+ }
20
+ }
21
+ function resolveEffectiveTheme(mode) {
22
+ if (mode === "system") return getSystemTheme();
23
+ return mode;
24
+ }
25
+ function getStoredTheme() {
26
+ if (typeof window === "undefined") return memoryTheme;
27
+ try {
28
+ const stored = window.localStorage?.getItem?.(THEME_STORAGE_KEY);
29
+ if (stored === "light" || stored === "dark" || stored === "system") {
30
+ memoryTheme = stored;
31
+ return stored;
32
+ }
33
+ } catch {
34
+ }
35
+ if (typeof document !== "undefined" && document.cookie) {
36
+ try {
37
+ const match = document.cookie.match(new RegExp(`(?:^|; )${THEME_COOKIE}=([^;]*)`));
38
+ if (match) {
39
+ const decoded = decodeURIComponent(match[1]);
40
+ if (decoded === "light" || decoded === "dark" || decoded === "system") {
41
+ memoryTheme = decoded;
42
+ return decoded;
43
+ }
44
+ }
45
+ } catch {
46
+ }
47
+ }
48
+ return memoryTheme;
49
+ }
50
+ function applyTheme(mode) {
51
+ if (typeof document === "undefined") return;
52
+ try {
53
+ document.documentElement.setAttribute("data-theme", mode);
54
+ const elements = document.querySelectorAll(".publication");
55
+ elements.forEach((el) => el.setAttribute("data-theme", mode));
56
+ } catch {
57
+ }
58
+ }
59
+ var memoryListeners = /* @__PURE__ */ new Set();
60
+ function setTheme(mode) {
61
+ memoryTheme = mode;
62
+ if (typeof window !== "undefined") {
63
+ try {
64
+ window.localStorage?.setItem?.(THEME_STORAGE_KEY, mode);
65
+ } catch {
66
+ }
67
+ if (typeof document !== "undefined") {
68
+ try {
69
+ document.cookie = `${THEME_COOKIE}=${encodeURIComponent(mode)}; path=/; max-age=${THEME_MAX_AGE_SECONDS}; SameSite=Lax`;
70
+ } catch {
71
+ }
72
+ }
73
+ applyTheme(mode);
74
+ const effective = resolveEffectiveTheme(mode);
75
+ try {
76
+ window.dispatchEvent(
77
+ new CustomEvent(THEME_EVENT, {
78
+ detail: { mode, effective }
79
+ })
80
+ );
81
+ } catch {
82
+ }
83
+ }
84
+ memoryListeners.forEach((listener) => {
85
+ try {
86
+ listener();
87
+ } catch {
88
+ }
89
+ });
90
+ }
91
+ function subscribeTheme(listener) {
92
+ memoryListeners.add(listener);
93
+ if (typeof window === "undefined") {
94
+ return () => {
95
+ memoryListeners.delete(listener);
96
+ };
97
+ }
98
+ const onStorage = (e) => {
99
+ if (e.key === THEME_STORAGE_KEY) {
100
+ applyTheme(getStoredTheme());
101
+ listener();
102
+ }
103
+ };
104
+ const onCustom = () => {
105
+ listener();
106
+ };
107
+ window.addEventListener("storage", onStorage);
108
+ window.addEventListener(THEME_EVENT, onCustom);
109
+ let mediaQuery;
110
+ let onMediaChange;
111
+ if (window.matchMedia) {
112
+ try {
113
+ mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
114
+ onMediaChange = () => {
115
+ if (getStoredTheme() === "system") {
116
+ applyTheme("system");
117
+ listener();
118
+ }
119
+ };
120
+ if (mediaQuery.addEventListener) {
121
+ mediaQuery.addEventListener("change", onMediaChange);
122
+ } else if (mediaQuery.addListener) {
123
+ mediaQuery.addListener(onMediaChange);
124
+ }
125
+ } catch {
126
+ }
127
+ }
128
+ return () => {
129
+ window.removeEventListener("storage", onStorage);
130
+ window.removeEventListener(THEME_EVENT, onCustom);
131
+ if (mediaQuery && onMediaChange) {
132
+ if (mediaQuery.removeEventListener) {
133
+ mediaQuery.removeEventListener("change", onMediaChange);
134
+ } else if (mediaQuery.removeListener) {
135
+ mediaQuery.removeListener(onMediaChange);
136
+ }
137
+ }
138
+ };
139
+ }
140
+ function SunIcon() {
141
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
142
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "4" }),
143
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" })
144
+ ] });
145
+ }
146
+ function MoonIcon() {
147
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" }) });
148
+ }
149
+ function SystemIcon() {
150
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
151
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "20", height: "14", x: "2", y: "3", rx: "2" }),
152
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", x2: "16", y1: "21", y2: "21" }),
153
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", x2: "12", y1: "17", y2: "21" })
154
+ ] });
155
+ }
156
+ function ThemeToggle({
157
+ variant = "compact",
158
+ className = "",
159
+ showPromotion = false,
160
+ accountUrl = "/account"
161
+ }) {
162
+ const currentTheme = react.useSyncExternalStore(subscribeTheme, getStoredTheme, () => "system");
163
+ const [mounted, setMounted] = react.useState(false);
164
+ const [promoVisible, setPromoVisible] = react.useState(false);
165
+ react.useEffect(() => {
166
+ setMounted(true);
167
+ }, []);
168
+ const handleSelect = (mode) => {
169
+ setTheme(mode);
170
+ if (showPromotion) {
171
+ setPromoVisible(true);
172
+ }
173
+ };
174
+ const active = mounted ? currentTheme : "system";
175
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `pub-theme-toggle-container ${className}`.trim(), children: [
176
+ /* @__PURE__ */ jsxRuntime.jsxs(
177
+ "div",
178
+ {
179
+ className: "pub-theme-toggle",
180
+ "data-variant": variant,
181
+ role: "group",
182
+ "aria-label": "Display theme selection",
183
+ children: [
184
+ /* @__PURE__ */ jsxRuntime.jsxs(
185
+ "button",
186
+ {
187
+ type: "button",
188
+ onClick: () => handleSelect("light"),
189
+ "aria-pressed": active === "light",
190
+ "data-active": active === "light",
191
+ title: "Light theme (broadsheet day edition)",
192
+ "aria-label": "Light theme",
193
+ children: [
194
+ /* @__PURE__ */ jsxRuntime.jsx(SunIcon, {}),
195
+ variant !== "compact" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Light" })
196
+ ]
197
+ }
198
+ ),
199
+ /* @__PURE__ */ jsxRuntime.jsxs(
200
+ "button",
201
+ {
202
+ type: "button",
203
+ onClick: () => handleSelect("dark"),
204
+ "aria-pressed": active === "dark",
205
+ "data-active": active === "dark",
206
+ title: "Dark theme (broadsheet evening edition)",
207
+ "aria-label": "Dark theme",
208
+ children: [
209
+ /* @__PURE__ */ jsxRuntime.jsx(MoonIcon, {}),
210
+ variant !== "compact" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Dark" })
211
+ ]
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsxRuntime.jsxs(
215
+ "button",
216
+ {
217
+ type: "button",
218
+ onClick: () => handleSelect("system"),
219
+ "aria-pressed": active === "system",
220
+ "data-active": active === "system",
221
+ title: "System preference (matches device setting)",
222
+ "aria-label": "System theme",
223
+ children: [
224
+ /* @__PURE__ */ jsxRuntime.jsx(SystemIcon, {}),
225
+ variant !== "compact" && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "System" })
226
+ ]
227
+ }
228
+ )
229
+ ]
230
+ }
231
+ ),
232
+ promoVisible && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pub-theme-promo", role: "status", children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Theme saved for this browser. " }),
234
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: accountUrl, children: "Create a free reader account" }),
235
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: " to sync preferences across all your devices." }),
236
+ /* @__PURE__ */ jsxRuntime.jsx(
237
+ "button",
238
+ {
239
+ type: "button",
240
+ onClick: () => setPromoVisible(false),
241
+ "aria-label": "Dismiss note",
242
+ style: {
243
+ marginLeft: "8px",
244
+ background: "none",
245
+ border: "none",
246
+ cursor: "pointer",
247
+ color: "var(--pub-muted)",
248
+ fontSize: "12px",
249
+ padding: "0 4px"
250
+ },
251
+ children: "\xD7"
252
+ }
253
+ )
254
+ ] })
255
+ ] });
256
+ }
257
+
258
+ exports.ThemeToggle = ThemeToggle;
@@ -0,0 +1,22 @@
1
+ import react__default from 'react';
2
+
3
+ interface ThemeToggleProps {
4
+ /**
5
+ * "compact": Micro-pill with icons only (ideal for header utility bar).
6
+ * "inline": Broadsheet rectangular tabs with text and icons (ideal for article reading tools).
7
+ * "segmented": Pill with icons and labels (ideal for account, settings, or footer).
8
+ */
9
+ variant?: "compact" | "inline" | "segmented";
10
+ /** Optional extra class name applied to container */
11
+ className?: string;
12
+ /**
13
+ * When true, displays a subtle, tasteful message when the user changes the theme:
14
+ * "Theme saved on this browser. Create a free reader account to sync across devices."
15
+ */
16
+ showPromotion?: boolean;
17
+ /** Link for reader account / sync. Default: "/account" */
18
+ accountUrl?: string;
19
+ }
20
+ declare function ThemeToggle({ variant, className, showPromotion, accountUrl, }: ThemeToggleProps): react__default.JSX.Element;
21
+
22
+ export { ThemeToggle, type ThemeToggleProps };
@@ -0,0 +1,22 @@
1
+ import react__default from 'react';
2
+
3
+ interface ThemeToggleProps {
4
+ /**
5
+ * "compact": Micro-pill with icons only (ideal for header utility bar).
6
+ * "inline": Broadsheet rectangular tabs with text and icons (ideal for article reading tools).
7
+ * "segmented": Pill with icons and labels (ideal for account, settings, or footer).
8
+ */
9
+ variant?: "compact" | "inline" | "segmented";
10
+ /** Optional extra class name applied to container */
11
+ className?: string;
12
+ /**
13
+ * When true, displays a subtle, tasteful message when the user changes the theme:
14
+ * "Theme saved on this browser. Create a free reader account to sync across devices."
15
+ */
16
+ showPromotion?: boolean;
17
+ /** Link for reader account / sync. Default: "/account" */
18
+ accountUrl?: string;
19
+ }
20
+ declare function ThemeToggle({ variant, className, showPromotion, accountUrl, }: ThemeToggleProps): react__default.JSX.Element;
21
+
22
+ export { ThemeToggle, type ThemeToggleProps };
@@ -0,0 +1,2 @@
1
+ "use client";
2
+ export { ThemeToggle } from './chunk-NQD3M7ZY.js';
package/marketplace.css CHANGED
@@ -59,3 +59,5 @@
59
59
  color: inherit;
60
60
  }
61
61
  .np-market .filter a.on, .np-market .filter a:hover { border-color: var(--pub-ink, #171917); color: var(--pub-accent, #bb171d); }
62
+ .np-market .deals { margin: 0 0 28px; }
63
+ .np-market .deals h2 { font: 600 22px/1.2 var(--pub-serif); margin: 0 0 8px; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalemule/news-publication",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Shared server framework for ScaleMule local news publications. Walnut Creek Times is the broadsheet default; each paper supplies its own identity and feature flags.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -49,7 +49,12 @@
49
49
  "import": "./dist/cookie-settings-view.js",
50
50
  "require": "./dist/cookie-settings-view.cjs"
51
51
  },
52
- "./cookie-consent.css": "./cookie-consent.css"
52
+ "./cookie-consent.css": "./cookie-consent.css",
53
+ "./theme-toggle": {
54
+ "types": "./dist/theme-toggle.d.ts",
55
+ "import": "./dist/theme-toggle.js",
56
+ "require": "./dist/theme-toggle.cjs"
57
+ }
53
58
  },
54
59
  "files": [
55
60
  "dist",