@openrails/contentkit-ui 0.97.1 → 0.98.1
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/README.md +57 -4
- package/dist/client/beacons.d.ts +17 -7
- package/dist/client/beacons.js +205 -41
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/browser-reader-preferences.d.ts +15 -2
- package/dist/client/browser-reader-preferences.js +67 -30
- package/dist/client/browser-reader-preferences.js.map +1 -1
- package/dist/client/discovery.d.ts +13 -3
- package/dist/client/discovery.js +31 -16
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/generated/routes.d.ts +14 -1
- package/dist/client/generated/routes.js +18 -0
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +47 -4
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/http.d.ts +7 -3
- package/dist/client/http.js +26 -7
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/reader-preferences.d.ts +7 -0
- package/dist/client/reader-preferences.js +16 -4
- package/dist/client/reader-preferences.js.map +1 -1
- package/dist/client.js +17 -17
- package/dist/components/content/card.js +50 -40
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/filters.d.ts +5 -0
- package/dist/components/content/filters.js +61 -52
- package/dist/components/content/filters.js.map +1 -1
- package/dist/components/content/popular.d.ts +1 -1
- package/dist/components/content/popular.js.map +1 -1
- package/dist/components/content/reader-settings.d.ts +4 -0
- package/dist/components/content/reader-settings.js +3 -1
- package/dist/components/content/reader-settings.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/react/discovery.d.ts +7 -2
- package/dist/react/discovery.js +208 -87
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/provider.js +4 -1
- package/dist/react/provider.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -102,10 +102,10 @@ export interface UseContentFilters {
|
|
|
102
102
|
loading: boolean;
|
|
103
103
|
error?: ContentKitError;
|
|
104
104
|
saving: boolean;
|
|
105
|
-
/** Replaces
|
|
105
|
+
/** Replaces offered settings for the supplied kinds; other kinds remain unchanged. */
|
|
106
106
|
save: (update: ContentFiltersUpdate) => Promise<ContentFilters>;
|
|
107
107
|
/** Shows or hides one filter's group, keeping the other settings. */
|
|
108
|
-
setVisible: (
|
|
108
|
+
setVisible: (kind: string, entityId: string, visible: boolean) => Promise<ContentFilters>;
|
|
109
109
|
setIncludeDeleted: (include: boolean) => Promise<ContentFilters>;
|
|
110
110
|
}
|
|
111
111
|
/** Current-domain toggles: browser choices for guests, server choices for accounts. */
|
|
@@ -148,6 +148,7 @@ export interface ExposureOptions {
|
|
|
148
148
|
client?: ContentKitClient;
|
|
149
149
|
}
|
|
150
150
|
export interface UseExposure {
|
|
151
|
+
/** The first bounded segment; click() selects the matching segment for later positions. */
|
|
151
152
|
render_id: string;
|
|
152
153
|
/** A card's ref: reports it shown once at least half of it is in view. */
|
|
153
154
|
track: (content: string, position: number) => (el: Element | null) => void;
|
|
@@ -157,4 +158,8 @@ export interface UseExposure {
|
|
|
157
158
|
/** A rendered result list: each page rendered, each card shown, clicks attributed to the render. */
|
|
158
159
|
export declare function useExposure(items: readonly {
|
|
159
160
|
id: string;
|
|
161
|
+
version_id?: string;
|
|
162
|
+
version?: {
|
|
163
|
+
id: string;
|
|
164
|
+
} | null;
|
|
160
165
|
}[], o: ExposureOptions): UseExposure;
|
package/dist/react/discovery.js
CHANGED
|
@@ -192,17 +192,21 @@ function I(t = {}) {
|
|
|
192
192
|
guest: m,
|
|
193
193
|
data: T.data
|
|
194
194
|
};
|
|
195
|
-
let E = d((e, t = b
|
|
196
|
-
let n = new Map(t.map((e) => [e.
|
|
195
|
+
let E = d((e, t = b) => {
|
|
196
|
+
let n = new Map(t.legacy_filters.map((e) => [e.entity_id, e.visible]));
|
|
197
197
|
return {
|
|
198
198
|
include_deleted: !1,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
kinds: Object.fromEntries(Object.entries(e.kinds).map(([e, r]) => {
|
|
200
|
+
let i = new Map(n);
|
|
201
|
+
for (let n of t.kinds[e] ?? []) i.set(n.entity_id, n.default ? void 0 : n.visible);
|
|
202
|
+
return [e, r.map((e) => ({
|
|
203
|
+
...e,
|
|
204
|
+
visible: i.get(e.entity.id) ?? e.default_visible,
|
|
205
|
+
overridden: i.get(e.entity.id) !== void 0
|
|
206
|
+
}))];
|
|
203
207
|
}))
|
|
204
208
|
};
|
|
205
|
-
}, [b
|
|
209
|
+
}, [b]), D = h(() => T.data && m ? E(T.data) : T.data, [
|
|
206
210
|
T.data,
|
|
207
211
|
m,
|
|
208
212
|
E
|
|
@@ -213,12 +217,28 @@ function I(t = {}) {
|
|
|
213
217
|
let N = d(async (t) => {
|
|
214
218
|
if (!k()) throw new e("aborted", "The account changed.");
|
|
215
219
|
if (m) {
|
|
216
|
-
let
|
|
217
|
-
if (!
|
|
218
|
-
let
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
let r = M.current;
|
|
221
|
+
if (!r) throw new e("invalid_request", "Content filters have not loaded.");
|
|
222
|
+
let i = y.snapshot(), a = { ...i.kinds }, o = new Set(i.legacy_filters.map((e) => e.entity_id));
|
|
223
|
+
for (let [n, s] of Object.entries(t.kinds)) {
|
|
224
|
+
let t = r.kinds[n];
|
|
225
|
+
if (!t) throw new e("invalid_request", "This content kind has no configurable filters.");
|
|
226
|
+
let c = new Set(t.map((e) => e.entity.id));
|
|
227
|
+
if (s.some((e) => !c.has(e.entity_id))) throw new e("invalid_request", "This content filter is not configured.");
|
|
228
|
+
let l = new Set(s.map((e) => e.entity_id)), u = t.filter((e) => o.has(e.entity.id) && !l.has(e.entity.id)).map((e) => ({
|
|
229
|
+
entity_id: e.entity.id,
|
|
230
|
+
default: !0
|
|
231
|
+
}));
|
|
232
|
+
a[n] = [
|
|
233
|
+
...(i.kinds[n] ?? []).filter((e) => !c.has(e.entity_id)),
|
|
234
|
+
...s,
|
|
235
|
+
...u
|
|
236
|
+
];
|
|
237
|
+
}
|
|
238
|
+
return n.preferences.setGuestFilters(a), E(r, {
|
|
239
|
+
...i,
|
|
240
|
+
kinds: a
|
|
241
|
+
});
|
|
222
242
|
}
|
|
223
243
|
j((e) => e + 1);
|
|
224
244
|
try {
|
|
@@ -240,25 +260,46 @@ function I(t = {}) {
|
|
|
240
260
|
m,
|
|
241
261
|
y,
|
|
242
262
|
E
|
|
243
|
-
]), P = (e) => e.
|
|
244
|
-
|
|
263
|
+
]), P = (e) => Object.fromEntries(Object.entries(e.kinds).map(([e, t]) => [e, t.filter((e) => e.overridden).map((e) => ({
|
|
264
|
+
entity_id: e.entity.id,
|
|
245
265
|
visible: e.visible
|
|
246
|
-
})), F = d((
|
|
247
|
-
let
|
|
248
|
-
return
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
266
|
+
}))])), F = d(async (t, r, i) => {
|
|
267
|
+
let a = M.current;
|
|
268
|
+
if (!a) return Promise.reject(/* @__PURE__ */ Error("contentkit-ui: the content filters have not loaded"));
|
|
269
|
+
if (m) {
|
|
270
|
+
if (!k()) return Promise.reject(new e("aborted", "The account changed."));
|
|
271
|
+
if (!a.kinds[t]?.some((e) => e.entity.id === r)) return Promise.reject(new e("invalid_request", "This content filter is not configured."));
|
|
272
|
+
let o = y.snapshot(), s = {
|
|
273
|
+
...o.kinds,
|
|
274
|
+
[t]: [...(o.kinds[t] ?? []).filter((e) => e.entity_id !== r), {
|
|
275
|
+
entity_id: r,
|
|
276
|
+
visible: i
|
|
277
|
+
}]
|
|
278
|
+
};
|
|
279
|
+
return n.preferences.setGuestFilters(s), Promise.resolve(E(a, {
|
|
280
|
+
...o,
|
|
281
|
+
kinds: s
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
let o = P(a)[t] ?? [];
|
|
285
|
+
return N({
|
|
286
|
+
kinds: { [t]: [...o.filter((e) => e.entity_id !== r), {
|
|
287
|
+
entity_id: r,
|
|
288
|
+
visible: i
|
|
289
|
+
}] },
|
|
290
|
+
include_deleted: a.include_deleted
|
|
291
|
+
});
|
|
292
|
+
}, [
|
|
293
|
+
N,
|
|
294
|
+
m,
|
|
295
|
+
k,
|
|
296
|
+
y,
|
|
297
|
+
E,
|
|
298
|
+
n
|
|
299
|
+
]), I = d((e) => M.current ? N({
|
|
300
|
+
kinds: {},
|
|
301
|
+
include_deleted: e
|
|
302
|
+
}) : Promise.reject(/* @__PURE__ */ Error("contentkit-ui: the content filters have not loaded")), [N]);
|
|
262
303
|
return {
|
|
263
304
|
filters: D ?? null,
|
|
264
305
|
loading: T.loading || !T.loaded,
|
|
@@ -361,82 +402,162 @@ function V(e = {}) {
|
|
|
361
402
|
return B(t);
|
|
362
403
|
}
|
|
363
404
|
function H(e, t, n = {}) {
|
|
364
|
-
let
|
|
405
|
+
let { client: r, scope: i, viewer: o, language: s } = a(n.client), c = B(r), l = x(r, i), u = h(() => ({ session: void 0 }), [
|
|
406
|
+
c,
|
|
407
|
+
e,
|
|
408
|
+
t,
|
|
409
|
+
i
|
|
410
|
+
]);
|
|
411
|
+
return d((i) => {
|
|
412
|
+
e && l() && (o === void 0 || r.preferences.identity() === o) && (u.session ??= c.view(e, t, {
|
|
413
|
+
render_id: n.render_id,
|
|
414
|
+
surface: n.surface,
|
|
415
|
+
position: n.position,
|
|
416
|
+
language: n.language ?? s
|
|
417
|
+
}), u.session.update(i));
|
|
418
|
+
}, [
|
|
419
|
+
c,
|
|
365
420
|
r,
|
|
366
421
|
e,
|
|
367
|
-
t
|
|
422
|
+
t,
|
|
423
|
+
o,
|
|
424
|
+
s,
|
|
425
|
+
n.language,
|
|
426
|
+
n.render_id,
|
|
427
|
+
n.surface,
|
|
428
|
+
n.position,
|
|
429
|
+
u,
|
|
430
|
+
l
|
|
368
431
|
]);
|
|
369
|
-
return d((e) => o?.update(e), [o]);
|
|
370
432
|
}
|
|
371
433
|
function U(e, t) {
|
|
372
|
-
let n =
|
|
373
|
-
render_id: r,
|
|
434
|
+
let { client: n, scope: r, language: i } = a(t.client), o = B(n), s = x(n, r), c = h(() => u(), [t.render, r]), l = h(() => ({
|
|
374
435
|
surface: t.surface,
|
|
375
436
|
ranker: t.ranker,
|
|
376
437
|
query_id: t.query_id,
|
|
377
|
-
language: t.language
|
|
438
|
+
language: t.language ?? i
|
|
378
439
|
}), [
|
|
379
|
-
r,
|
|
380
440
|
t.surface,
|
|
381
441
|
t.ranker,
|
|
382
442
|
t.query_id,
|
|
383
|
-
t.language
|
|
384
|
-
|
|
443
|
+
t.language,
|
|
444
|
+
i
|
|
445
|
+
]), f = h(() => ({
|
|
446
|
+
segments: /* @__PURE__ */ new Map(),
|
|
447
|
+
pending: /* @__PURE__ */ new Set(),
|
|
448
|
+
timer: void 0
|
|
449
|
+
}), [c]), m = d((e) => e === 0 ? c : `${c}-${e}`, [c]), g = d((e) => {
|
|
450
|
+
let t = f.segments.get(e);
|
|
451
|
+
return t || (t = {
|
|
452
|
+
rendered: /* @__PURE__ */ new Map(),
|
|
453
|
+
visible: /* @__PURE__ */ new Map(),
|
|
454
|
+
renderedRevision: 0,
|
|
455
|
+
visibleRevision: 0
|
|
456
|
+
}, f.segments.set(e, t)), t;
|
|
457
|
+
}, [f]);
|
|
385
458
|
p(() => {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
let
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
459
|
+
if (!s()) return;
|
|
460
|
+
let t = /* @__PURE__ */ new Set();
|
|
461
|
+
for (let [n, r] of e.entries()) {
|
|
462
|
+
let e = Math.floor(n / W), i = g(e);
|
|
463
|
+
i.rendered.has(r.id) || (i.rendered.set(r.id, {
|
|
464
|
+
content_id: r.id,
|
|
465
|
+
version_id: r.version_id ?? r.version?.id,
|
|
466
|
+
position: n + 1
|
|
467
|
+
}), t.add(e));
|
|
468
|
+
}
|
|
469
|
+
for (let e of t) {
|
|
470
|
+
let t = g(e);
|
|
471
|
+
o.exposure({
|
|
472
|
+
...l,
|
|
473
|
+
render_id: m(e),
|
|
474
|
+
stage: "rendered",
|
|
475
|
+
revision: ++t.renderedRevision,
|
|
476
|
+
occurred_at: t.renderedAt ??= (/* @__PURE__ */ new Date()).toISOString(),
|
|
477
|
+
shown: [...t.rendered.values()]
|
|
478
|
+
});
|
|
479
|
+
}
|
|
399
480
|
}, [
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
e
|
|
481
|
+
o,
|
|
482
|
+
l,
|
|
483
|
+
e,
|
|
484
|
+
f,
|
|
485
|
+
g,
|
|
486
|
+
m,
|
|
487
|
+
s
|
|
403
488
|
]);
|
|
404
|
-
let
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
489
|
+
let _ = h(() => typeof IntersectionObserver == "function" ? new IntersectionObserver((e) => {
|
|
490
|
+
if (s()) {
|
|
491
|
+
for (let t of e) {
|
|
492
|
+
if (!t.isIntersecting) continue;
|
|
493
|
+
let e = t.target, n = e.dataset.exposureContent, r = Number(e.dataset.exposurePosition), i = Math.floor((r - 1) / W), a = g(i);
|
|
494
|
+
a.visible.has(n) || (a.visible.set(n, a.rendered.get(n) ?? {
|
|
495
|
+
content_id: n,
|
|
496
|
+
position: r
|
|
497
|
+
}), f.pending.add(i));
|
|
498
|
+
}
|
|
499
|
+
f.pending.size && (f.timer ??= setTimeout(() => {
|
|
500
|
+
if (f.timer = void 0, s()) {
|
|
501
|
+
for (let e of f.pending) {
|
|
502
|
+
let t = g(e);
|
|
503
|
+
o.exposure({
|
|
504
|
+
...l,
|
|
505
|
+
render_id: m(e),
|
|
506
|
+
stage: "visible",
|
|
507
|
+
revision: ++t.visibleRevision,
|
|
508
|
+
occurred_at: t.visibleAt ??= (/* @__PURE__ */ new Date()).toISOString(),
|
|
509
|
+
shown: [...t.visible.values()]
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
f.pending.clear();
|
|
513
|
+
}
|
|
514
|
+
}, 300));
|
|
412
515
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
},
|
|
424
|
-
|
|
425
|
-
|
|
516
|
+
}, { threshold: .5 }) : null, [
|
|
517
|
+
o,
|
|
518
|
+
l,
|
|
519
|
+
f,
|
|
520
|
+
g,
|
|
521
|
+
m,
|
|
522
|
+
s
|
|
523
|
+
]);
|
|
524
|
+
return p(() => () => {
|
|
525
|
+
_?.disconnect(), clearTimeout(f.timer);
|
|
526
|
+
}, [_, f]), p(() => {
|
|
527
|
+
for (let e of f.segments.keys()) o.beginExposure(m(e));
|
|
528
|
+
return () => {
|
|
529
|
+
for (let e of f.segments.keys()) o.endExposure(m(e));
|
|
530
|
+
};
|
|
531
|
+
}, [
|
|
532
|
+
o,
|
|
533
|
+
f,
|
|
534
|
+
m
|
|
535
|
+
]), {
|
|
536
|
+
render_id: c,
|
|
426
537
|
track: d((e, t) => (n) => {
|
|
427
|
-
n &&
|
|
428
|
-
}, [
|
|
429
|
-
click: d((
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
538
|
+
n && _ && (n.dataset.exposureContent = e, n.dataset.exposurePosition = String(t), _.observe(n));
|
|
539
|
+
}, [_]),
|
|
540
|
+
click: d((n, r) => {
|
|
541
|
+
if (!s()) return;
|
|
542
|
+
let i = Math.floor((r - 1) / W), a = e.find((e) => e.id === n), c = a?.version_id ?? a?.version?.id;
|
|
543
|
+
o.click(n, {
|
|
544
|
+
render_id: m(i),
|
|
545
|
+
surface: t.surface,
|
|
546
|
+
position: r,
|
|
547
|
+
version_id: c,
|
|
548
|
+
language: l.language
|
|
549
|
+
});
|
|
550
|
+
}, [
|
|
551
|
+
o,
|
|
552
|
+
e,
|
|
553
|
+
m,
|
|
554
|
+
t.surface,
|
|
555
|
+
l.language,
|
|
556
|
+
s
|
|
437
557
|
])
|
|
438
558
|
};
|
|
439
559
|
}
|
|
560
|
+
var W = 32;
|
|
440
561
|
//#endregion
|
|
441
562
|
export { B as beaconsFor, V as useBeacons, I as useContentFilters, C as useContents, A as useDailyReleases, U as useExposure, j as useHistory, w as useLockedCount, P as useMyFavorites, F as useMyReactions, M as useRecentSearches, O as useRecommendations, k as useReleaseDates, T as useSearch, D as useSimilar, R as useTypeahead, H as useViewSignal };
|
|
442
563
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","names":[],"sources":["../../src/react/discovery.ts"],"sourcesContent":["import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Beacons, eventId, type Attribution, type BeaconOptions, type ViewSession } from \"../client/beacons.js\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { MineQuery } from \"../client/content/favorites.js\";\nimport type { AccessMode, ContentQuery, DailyReleasesQuery, HistoryQuery, RailQuery, ReleaseDatesQuery, SearchQuery, TypeaheadQuery } from \"../client/discovery.js\";\nimport { ContentKitError, toContentKitError } from \"../client/errors.js\";\nimport type { Card, ContentFilters, ContentFiltersUpdate, ContentPage, DailyReleases, DateCount, GroupCard, Interaction, InteractionPage, RecentSearch } from \"../client/generated/wire.js\";\nimport { ContentKitContext, useGuarded } from \"./context.js\";\nimport { keyOf, useContentScope, useList, useResource, type UseList } from \"./use-resource.js\";\nimport { recentSearchLimit } from \"../client/browser-search-history.js\";\n\nconst page = (p: ContentPage) => ({ items: p.contents, next: p.next_cursor ?? null });\nconst NO_SEARCHES: RecentSearch[] = [];\n\n// A new identity even after A → B → A, so late requests cannot write into the new visit.\nfunction useCurrentDiscoveryScope(client: ContentKitClient, scope: string): () => boolean {\n const owner = useMemo(() => ({ client, scope }), [client, scope]);\n const current = useRef<typeof owner | null>(owner);\n useLayoutEffect(() => {\n current.current = owner;\n return () => { current.current = null; };\n }, [owner]);\n return useCallback(() => current.current === owner, [owner]);\n}\n\n/** Titles, names and paths in the provider's language unless the query says otherwise. */\nfunction useDisplay<T extends { display_language?: string }>(q: T | null): T | null {\n const language = useContext(ContentKitContext)?.language;\n return useMemo(() => (q && !q.display_language && language ? { ...q, display_language: language } : q), [q, language]);\n}\n\n/** Contents as cards, a cursor page at a time; null reads nothing. */\nexport function useContents(q: ContentQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q);\n return useList(store, query ? keyOf(\"cards\", scope, \"list\", query) : null, { type: \"cards\" }, async (cursor, signal) =>\n page(await client.discovery.list({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/**\n * How many contents of a list the reader doesn't open: its filters' count\n * with locked cards less without them (sort and paging aside); null reads\n * nothing.\n */\nexport function useLockedCount(q: ContentQuery | null, o: { client?: ContentKitClient } = {}): { count?: number; loading: boolean } {\n const { client, store, scope } = useContentScope(o.client);\n const filter = useMemo(() => {\n if (!q) return null;\n const { sort: _s, cursor: _c, limit: _l, card_entities: _g, mode: _m, ...f } = q;\n return f;\n }, [q]);\n const query = useDisplay(filter);\n const r = useResource<number>(store, query ? keyOf(\"release-dates\", scope, \"locked\", query) : null, { type: \"release-dates\" }, async (signal) => {\n const count = async (mode: AccessMode) =>\n (await client.discovery.releaseDates({ ...query, mode, by: \"month\", limit: 1000 }, signal)).dates.reduce((n, d) => n + d.count, 0);\n const [all, open] = await Promise.all([count(\"lock\"), count(\"hide\")]);\n return Math.max(0, all - open);\n });\n return { count: r.data, loading: r.loading };\n}\n\n/** Keyword search results as cards; nothing while q.q is empty. */\nexport function useSearch(q: SearchQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q?.q.trim() ? q : null);\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n return useList(store, query ? keyOf(\"cards\", scope, \"search\", query) : null, { type: \"cards\" }, async (cursor, signal) => {\n const out = await client.discovery.search({ ...query!, cursor: cursor as string | undefined }, signal);\n if (!cursor && viewer === null && !signal.aborted && isCurrent()) client.discovery.browserSearches.record(query!.q, out.contents.length);\n return page(out);\n });\n}\n\nexport interface UseRail {\n items: Card[];\n loading: boolean;\n error?: ContentKitError;\n /** The site runs without the signal plane (not_configured): leave the rail out. */\n unavailable: boolean;\n reload: () => void;\n}\n\nfunction useRail(key: string | null, fetch: (signal: AbortSignal) => Promise<ContentPage>, o: { client?: ContentKitClient }): UseRail {\n const { store } = useContentScope(o.client);\n const r = useResource<Card[]>(store, key, { type: \"cards\" }, async (signal) => (await fetch(signal)).contents);\n const unavailable = r.error?.code === \"not_configured\";\n return { items: r.data ?? [], loading: !!key && (r.loading || !r.loaded), error: unavailable ? undefined : r.error, unavailable, reload: r.reload };\n}\n\n/** Contents like one: co-engagement, or the site's configured source. */\nexport function useSimilar(id: string | null | undefined, q: RailQuery = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useRail(id ? keyOf(\"cards\", scope, \"similar\", id, query) : null, (s) => client.discovery.similar(id!, query, s), o);\n}\n\n/** Contents for the signed-in reader; nothing signed out, or when q is null. */\nexport function useRecommendations(q: RailQuery | null = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n return useRail(viewer === null || !query ? null : keyOf(\"cards\", scope, \"recommended\", query), (s) => client.discovery.recommendations(query!, s), o);\n}\n\n/** A release date bucket, keyed by its date. */\nexport type ReleaseDate = DateCount & { id: string };\n\n/** The release date index: per month or day, newest first. */\nexport function useReleaseDates(q: ReleaseDatesQuery = {}, o: { client?: ContentKitClient } = {}): UseList<ReleaseDate> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, keyOf(\"release-dates\", scope, query), { type: \"release-dates\" }, async (cursor, signal) => {\n const r = await client.discovery.releaseDates({ ...query, cursor: cursor as string | undefined }, signal);\n return { items: r.dates.map((d) => ({ ...d, id: d.date })), next: r.next_cursor ?? null };\n });\n}\n\nexport interface UseDailyReleases {\n data?: DailyReleases;\n loading: boolean;\n error?: ContentKitError;\n reload: () => void;\n}\n\n/** One complete calendar window, shared by all readers of the same query. */\nexport function useDailyReleases(q: DailyReleasesQuery | null = {}, o: { client?: ContentKitClient } = {}): UseDailyReleases {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q);\n const r = useResource<DailyReleases>(store, query ? keyOf(\"daily-releases\", scope, query) : null, { type: \"daily-releases\" }, (signal) => client.discovery.releases(query!, signal));\n return { data: r.data, loading: !!query && (r.loading || !r.loaded), error: r.error, reload: r.reload };\n}\n\nexport interface UseHistory extends UseList<Card> {\n /** Erases the reader's history: of one content item, one kind, or (no argument) everything. */\n forget: (o?: { kind?: string; content_id?: string }) => Promise<void>;\n}\n\n/** What the signed-in reader engaged with, most recent first; nothing signed out, or when q is null. */\nexport function useHistory(q: HistoryQuery | null = {}, o: { client?: ContentKitClient } = {}): UseHistory {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n const guarded = useGuarded();\n const list = useList(store, viewer === null || !query ? null : keyOf(\"history\", scope, query), { type: \"history\" }, async (cursor, signal) =>\n page(await client.discovery.history({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n const forget = useCallback((f: { kind?: string; content_id?: string } = {}) => guarded(() => client.discovery.forgetHistory(f)), [client, guarded]);\n return { ...list, forget };\n}\n\nexport interface UseRecentSearches {\n searches: RecentSearch[];\n loading: boolean;\n error?: ContentKitError;\n /** Clears one query, or every recent search. */\n clear: (query?: string) => Promise<void>;\n}\n\n/** Guest history stays in this browser; account history comes only from the server. enabled false reads nothing yet. */\nexport function useRecentSearches(o: { limit?: number; enabled?: boolean; client?: ContentKitClient } = {}): UseRecentSearches {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const guarded = useGuarded();\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n const guest = viewer === null;\n const enabled = o.enabled !== false;\n const browser = client.discovery.browserSearches;\n const subscribe = useCallback((listener: () => void) => guest && enabled ? browser.subscribe(listener) : () => {}, [browser, guest, enabled]);\n const snapshot = useCallback(() => guest && enabled ? browser.snapshot() : NO_SEARCHES, [browser, guest, enabled]);\n const local = useSyncExternalStore(subscribe, snapshot, () => NO_SEARCHES);\n const searches = useMemo(() => local.slice(0, recentSearchLimit(o.limit)), [local, o.limit]);\n const key = !enabled || guest ? null : keyOf(\"searches\", scope, o.limit ?? 10);\n const r = useResource<RecentSearch[]>(store, key, { type: \"searches\" }, async (s) => (await client.discovery.recentSearches({ limit: o.limit }, s)).searches);\n useEffect(() => {\n if (!key) return;\n const reload = () => { if (!store.snapshot(key).loading) store.load(key, true); };\n // Reopening a panel must not leave an already-cached account list stale.\n if (store.snapshot(key).loaded) reload();\n const visible = () => { if (document.visibilityState === \"visible\") reload(); };\n if (typeof window !== \"undefined\") window.addEventListener(\"focus\", reload);\n if (typeof document !== \"undefined\") document.addEventListener(\"visibilitychange\", visible);\n return () => {\n if (typeof window !== \"undefined\") window.removeEventListener(\"focus\", reload);\n if (typeof document !== \"undefined\") document.removeEventListener(\"visibilitychange\", visible);\n };\n }, [key, store]);\n const clear = useCallback(async (query?: string) => {\n if (!isCurrent()) return;\n if (guest) { browser.clear(query); return; }\n await guarded(() => isCurrent() ? client.discovery.clearSearches(query ? { query } : {}) : Promise.resolve());\n }, [browser, client, guest, guarded, isCurrent]);\n return guest\n ? { searches: enabled ? searches : NO_SEARCHES, loading: false, clear }\n : { searches: r.data ?? NO_SEARCHES, loading: !!key && (r.loading || !r.loaded), error: r.error, clear };\n}\n\n/** A favorite or reaction with its content's or group's id. */\nexport type MyInteraction = Interaction & { id: string };\n\nconst interactions = (p: InteractionPage) => ({ items: p.items.map((x) => ({ ...x, id: x.content?.id ?? x.entity?.id ?? \"\" })), next: p.next_cursor ?? null });\n\n/** The signed-in reader's favorites, most recent first: content cards or groups. */\nexport function useMyFavorites(q: MineQuery = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"favorites\", scope, query), { type: \"favorites\" }, async (cursor, signal) =>\n interactions(await client.favorites.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/** What the signed-in reader liked (or, with value, disliked), most recent first. */\nexport function useMyReactions(q: MineQuery & { value?: \"like\" | \"dislike\" } = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"reactions\", scope, query), { type: \"reactions\" }, async (cursor, signal) =>\n interactions(await client.reactions.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\nexport interface UseContentFilters {\n /** null until the configured filters have loaded. */\n filters: ContentFilters | null;\n loading: boolean;\n error?: ContentKitError;\n saving: boolean;\n /** Replaces every setting; the lists showing re-read. */\n save: (update: ContentFiltersUpdate) => Promise<ContentFilters>;\n /** Shows or hides one filter's group, keeping the other settings. */\n setVisible: (groupId: string, visible: boolean) => Promise<ContentFilters>;\n setIncludeDeleted: (include: boolean) => Promise<ContentFilters>;\n}\n\n/** Current-domain toggles: browser choices for guests, server choices for accounts. */\nexport function useContentFilters(o: { language?: string; client?: ContentKitClient } = {}): UseContentFilters {\n const { client, store, scope, viewer, language: provided } = useContentScope(o.client);\n const language = o.language ?? provided;\n const guest = viewer === null;\n const browser = client.preferences.browser;\n const local = useSyncExternalStore(browser.subscribe, browser.snapshot, browser.snapshot);\n const key = keyOf(\"content-filters\", scope, language);\n const previous = useRef<{ client: ContentKitClient; language?: string; guest: boolean; data?: ContentFilters } | null>(null);\n const initial = guest && previous.current?.guest && previous.current.client === client && previous.current.language === language ? previous.current.data : undefined;\n const r = useResource<ContentFilters>(store, key, { type: \"content-filters\" }, (s) => client.discovery.contentFilters(language, s), { initial });\n previous.current = { client, language, guest, data: r.data };\n const applyGuest = useCallback((source: ContentFilters, settings = local.filters): ContentFilters => {\n const values = new Map(settings.map((f) => [f.group_id, f.visible]));\n return { include_deleted: false, filters: source.filters.map((f) => ({ ...f, visible: values.get(f.entity.id) ?? f.default_visible, overridden: values.has(f.entity.id) })) };\n }, [local.filters]);\n const displayed = useMemo(() => r.data && guest ? applyGuest(r.data) : r.data, [r.data, guest, applyGuest]);\n const guarded = useGuarded();\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n const [inflight, setInflight] = useState(0);\n const current = useRef(displayed);\n current.current = displayed;\n useEffect(() => { setInflight(0); }, [client, scope]);\n const save = useCallback(\n async (update: ContentFiltersUpdate) => {\n if (!isCurrent()) throw new ContentKitError(\"aborted\", \"The account changed.\");\n if (guest) {\n const source = current.current;\n if (!source) throw new ContentKitError(\"invalid_request\", \"Content filters have not loaded.\");\n const allowed = new Set(source.filters.map((f) => f.entity.id));\n if (update.filters.some((f) => !allowed.has(f.group_id))) throw new ContentKitError(\"invalid_request\", \"This content filter is not configured.\");\n const merged = [...browser.snapshot().filters.filter((f) => !allowed.has(f.group_id)), ...update.filters];\n browser.setFilters(merged);\n return applyGuest(source, merged);\n }\n setInflight((n) => n + 1);\n try {\n const out = await guarded(() => {\n if (!isCurrent()) throw new ContentKitError(\"aborted\", \"The account changed.\");\n return client.discovery.setContentFilters(update, language);\n });\n if (isCurrent()) store.set(key, out);\n return out;\n } finally {\n setInflight((n) => Math.max(0, n - 1));\n }\n },\n [client, guarded, language, key, store, isCurrent, guest, browser, applyGuest],\n );\n const settings = (f: ContentFilters) => f.filters.filter((x) => x.overridden).map((x) => ({ group_id: x.entity.id, visible: x.visible }));\n const setVisible = useCallback(\n (groupId: string, visible: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n return save({ filters: [...settings(f).filter((x) => x.group_id !== groupId), { group_id: groupId, visible }], include_deleted: f.include_deleted });\n },\n [save],\n );\n const setIncludeDeleted = useCallback(\n (include: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n return save({ filters: settings(f), include_deleted: include });\n },\n [save],\n );\n return { filters: displayed ?? null, loading: r.loading || !r.loaded, error: r.error, saving: inflight > 0, save, setVisible, setIncludeDeleted };\n}\n\nexport interface UseTypeahead {\n contents: Card[];\n entities: GroupCard[];\n /** The query the suggestions answer (trimmed). */\n query: string;\n loading: boolean;\n error?: ContentKitError;\n}\n\nconst NONE: Pick<UseTypeahead, \"contents\" | \"entities\"> = { contents: [], entities: [] };\n\n/** Suggestions while the reader types: debounced, the stale ones abandoned. */\nexport function useTypeahead(\n text: string,\n o: Omit<TypeaheadQuery, \"q\"> & { debounce?: number; minLength?: number; client?: ContentKitClient; management?: boolean } = {},\n): UseTypeahead {\n const { client, language, scope: viewerScope } = useContentScope(o.client);\n const { debounce = 150, minLength = 1, client: _own, management = false, ...rest } = o;\n const scope = JSON.stringify([viewerScope, management]);\n const q = text.trim();\n const query = useMemo(() => ({ display_language: language, ...rest, q }), [language, q, JSON.stringify(rest)]); // eslint-disable-line react-hooks/exhaustive-deps\n const [state, setState] = useState<UseTypeahead & { scope: string }>({ ...NONE, query: \"\", loading: false, scope });\n useEffect(() => {\n if (q.length < minLength) {\n setState({ ...NONE, query: \"\", loading: false, scope });\n return;\n }\n setState((s) => ({ ...(s.scope === scope ? s : { ...NONE, query: \"\" }), loading: true, scope }));\n const ctl = new AbortController();\n const timer = setTimeout(() => {\n const request = management\n ? client.entities.manage({ q, kind: query.entity_kinds?.[0], language: query.display_language, limit: query.limit ?? 10 }, ctl.signal)\n .then((page) => ({ contents: [], entities: page.entities }))\n : client.discovery.typeahead(query, ctl.signal);\n request.then(\n (r) => { if (!ctl.signal.aborted) setState({ contents: r.contents, entities: r.entities, query: q, loading: false, scope }); },\n (e) => {\n const error = toContentKitError(e);\n if (!ctl.signal.aborted && error.code !== \"aborted\") setState({ ...NONE, query: q, loading: false, error, scope });\n },\n );\n }, debounce);\n return () => {\n clearTimeout(timer);\n ctl.abort();\n };\n }, [client, query, q, debounce, minLength, management, scope]);\n return state.scope === scope ? state : { ...NONE, query: \"\", loading: q.length >= minLength };\n}\n\nconst beacons = new WeakMap<ContentKitClient, Beacons>();\n\n/** The client's signal and exposure batcher: one per client. */\nexport function beaconsFor(client: ContentKitClient, o?: BeaconOptions): Beacons {\n let b = beacons.get(client);\n if (!b) beacons.set(client, (b = new Beacons(client, o)));\n return b;\n}\n\nexport function useBeacons(o: { client?: ContentKitClient } = {}): Beacons {\n const { client } = useContentScope(o.client);\n return beaconsFor(client);\n}\n\n/** A view of a content (or one version) while it is shown: report its progress as it changes. */\nexport function useViewSignal(content: string | null | undefined, version?: string, o: Attribution & { client?: ContentKitClient } = {}): ViewSession[\"update\"] {\n const b = useBeacons(o);\n const { client: _c, ...attribution } = o;\n const session = useMemo(() => (content ? b.view(content, version, attribution) : null), [b, content, version]); // eslint-disable-line react-hooks/exhaustive-deps\n return useCallback((u) => session?.update(u), [session]);\n}\n\nexport interface ExposureOptions {\n /** Where the list is: \"home\", \"search\", \"similar\". */\n surface: string;\n /** Changes with what the list shows: a new render id. */\n render: string;\n ranker?: string;\n query_id?: string;\n language?: string;\n client?: ContentKitClient;\n}\n\nexport interface UseExposure {\n render_id: string;\n /** A card's ref: reports it shown once at least half of it is in view. */\n track: (content: string, position: number) => (el: Element | null) => void;\n /** Reports a click on the card at position. */\n click: (content: string, position: number) => void;\n}\n\n/** A rendered result list: each page rendered, each card shown, clicks attributed to the render. */\nexport function useExposure(items: readonly { id: string }[], o: ExposureOptions): UseExposure {\n const b = useBeacons(o);\n const renderId = useMemo(() => eventId(), [o.render]); // eslint-disable-line react-hooks/exhaustive-deps\n const base = useMemo(() => ({ render_id: renderId, surface: o.surface, ranker: o.ranker, query_id: o.query_id, language: o.language }), [renderId, o.surface, o.ranker, o.query_id, o.language]);\n const rendered = useRef(new Set<string>());\n const visible = useRef(new Set<string>());\n useEffect(() => {\n rendered.current = new Set();\n visible.current = new Set();\n }, [renderId]);\n useEffect(() => {\n const shown = items.flatMap((it, i) => (rendered.current.has(it.id) ? [] : [{ content_id: it.id, position: i + 1 }]));\n for (const s of shown) rendered.current.add(s.content_id);\n if (shown.length) b.exposure({ ...base, stage: \"rendered\", occurred_at: new Date().toISOString(), shown });\n }, [b, base, items]);\n const pending = useRef<{ content_id: string; position: number }[]>([]);\n const timer = useRef<ReturnType<typeof setTimeout>>(undefined);\n const observer = useMemo(() => {\n if (typeof IntersectionObserver !== \"function\") return null;\n return new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n if (!e.isIntersecting) continue;\n const el = e.target as HTMLElement;\n const content = el.dataset.exposureContent!;\n if (visible.current.has(content)) continue;\n visible.current.add(content);\n pending.current.push({ content_id: content, position: Number(el.dataset.exposurePosition) });\n }\n timer.current ??= setTimeout(() => {\n timer.current = undefined;\n const shown = pending.current.splice(0);\n if (shown.length) b.exposure({ ...base, stage: \"visible\", occurred_at: new Date().toISOString(), shown });\n }, 300);\n },\n { threshold: 0.5 },\n );\n }, [b, base]);\n useEffect(() => () => observer?.disconnect(), [observer]);\n const track = useCallback(\n (content: string, position: number) => (el: Element | null) => {\n if (!el || !observer) return;\n (el as HTMLElement).dataset.exposureContent = content;\n (el as HTMLElement).dataset.exposurePosition = String(position);\n observer.observe(el);\n },\n [observer],\n );\n const click = useCallback((content: string, position: number) => b.click(content, { render_id: renderId, surface: o.surface, position }), [b, renderId, o.surface]);\n return { render_id: renderId, track, click };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"discovery.js","names":[],"sources":["../../src/react/discovery.ts"],"sourcesContent":["import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport { Beacons, eventId, type Attribution, type BeaconOptions, type ViewSession } from \"../client/beacons.js\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { MineQuery } from \"../client/content/favorites.js\";\nimport type { AccessMode, ContentQuery, DailyReleasesQuery, HistoryQuery, RailQuery, ReleaseDatesQuery, SearchQuery, TypeaheadQuery } from \"../client/discovery.js\";\nimport { ContentKitError, toContentKitError } from \"../client/errors.js\";\nimport type { Card, ContentFilters, ContentFiltersUpdate, ContentPage, DailyReleases, DateCount, GroupCard, Interaction, InteractionPage, RecentSearch } from \"../client/generated/wire.js\";\nimport { ContentKitContext, useGuarded } from \"./context.js\";\nimport { keyOf, useContentScope, useList, useResource, type UseList } from \"./use-resource.js\";\nimport { recentSearchLimit } from \"../client/browser-search-history.js\";\n\nconst page = (p: ContentPage) => ({ items: p.contents, next: p.next_cursor ?? null });\nconst NO_SEARCHES: RecentSearch[] = [];\n\n// A new identity even after A → B → A, so late requests cannot write into the new visit.\nfunction useCurrentDiscoveryScope(client: ContentKitClient, scope: string): () => boolean {\n const owner = useMemo(() => ({ client, scope }), [client, scope]);\n const current = useRef<typeof owner | null>(owner);\n useLayoutEffect(() => {\n current.current = owner;\n return () => { current.current = null; };\n }, [owner]);\n return useCallback(() => current.current === owner, [owner]);\n}\n\n/** Titles, names and paths in the provider's language unless the query says otherwise. */\nfunction useDisplay<T extends { display_language?: string }>(q: T | null): T | null {\n const language = useContext(ContentKitContext)?.language;\n return useMemo(() => (q && !q.display_language && language ? { ...q, display_language: language } : q), [q, language]);\n}\n\n/** Contents as cards, a cursor page at a time; null reads nothing. */\nexport function useContents(q: ContentQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q);\n return useList(store, query ? keyOf(\"cards\", scope, \"list\", query) : null, { type: \"cards\" }, async (cursor, signal) =>\n page(await client.discovery.list({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/**\n * How many contents of a list the reader doesn't open: its filters' count\n * with locked cards less without them (sort and paging aside); null reads\n * nothing.\n */\nexport function useLockedCount(q: ContentQuery | null, o: { client?: ContentKitClient } = {}): { count?: number; loading: boolean } {\n const { client, store, scope } = useContentScope(o.client);\n const filter = useMemo(() => {\n if (!q) return null;\n const { sort: _s, cursor: _c, limit: _l, card_entities: _g, mode: _m, ...f } = q;\n return f;\n }, [q]);\n const query = useDisplay(filter);\n const r = useResource<number>(store, query ? keyOf(\"release-dates\", scope, \"locked\", query) : null, { type: \"release-dates\" }, async (signal) => {\n const count = async (mode: AccessMode) =>\n (await client.discovery.releaseDates({ ...query, mode, by: \"month\", limit: 1000 }, signal)).dates.reduce((n, d) => n + d.count, 0);\n const [all, open] = await Promise.all([count(\"lock\"), count(\"hide\")]);\n return Math.max(0, all - open);\n });\n return { count: r.data, loading: r.loading };\n}\n\n/** Keyword search results as cards; nothing while q.q is empty. */\nexport function useSearch(q: SearchQuery | null, o: { client?: ContentKitClient } = {}): UseList<Card> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q?.q.trim() ? q : null);\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n return useList(store, query ? keyOf(\"cards\", scope, \"search\", query) : null, { type: \"cards\" }, async (cursor, signal) => {\n const out = await client.discovery.search({ ...query!, cursor: cursor as string | undefined }, signal);\n if (!cursor && viewer === null && !signal.aborted && isCurrent()) client.discovery.browserSearches.record(query!.q, out.contents.length);\n return page(out);\n });\n}\n\nexport interface UseRail {\n items: Card[];\n loading: boolean;\n error?: ContentKitError;\n /** The site runs without the signal plane (not_configured): leave the rail out. */\n unavailable: boolean;\n reload: () => void;\n}\n\nfunction useRail(key: string | null, fetch: (signal: AbortSignal) => Promise<ContentPage>, o: { client?: ContentKitClient }): UseRail {\n const { store } = useContentScope(o.client);\n const r = useResource<Card[]>(store, key, { type: \"cards\" }, async (signal) => (await fetch(signal)).contents);\n const unavailable = r.error?.code === \"not_configured\";\n return { items: r.data ?? [], loading: !!key && (r.loading || !r.loaded), error: unavailable ? undefined : r.error, unavailable, reload: r.reload };\n}\n\n/** Contents like one: co-engagement, or the site's configured source. */\nexport function useSimilar(id: string | null | undefined, q: RailQuery = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useRail(id ? keyOf(\"cards\", scope, \"similar\", id, query) : null, (s) => client.discovery.similar(id!, query, s), o);\n}\n\n/** Contents for the signed-in reader; nothing signed out, or when q is null. */\nexport function useRecommendations(q: RailQuery | null = {}, o: { client?: ContentKitClient } = {}): UseRail {\n const { client, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n return useRail(viewer === null || !query ? null : keyOf(\"cards\", scope, \"recommended\", query), (s) => client.discovery.recommendations(query!, s), o);\n}\n\n/** A release date bucket, keyed by its date. */\nexport type ReleaseDate = DateCount & { id: string };\n\n/** The release date index: per month or day, newest first. */\nexport function useReleaseDates(q: ReleaseDatesQuery = {}, o: { client?: ContentKitClient } = {}): UseList<ReleaseDate> {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, keyOf(\"release-dates\", scope, query), { type: \"release-dates\" }, async (cursor, signal) => {\n const r = await client.discovery.releaseDates({ ...query, cursor: cursor as string | undefined }, signal);\n return { items: r.dates.map((d) => ({ ...d, id: d.date })), next: r.next_cursor ?? null };\n });\n}\n\nexport interface UseDailyReleases {\n data?: DailyReleases;\n loading: boolean;\n error?: ContentKitError;\n reload: () => void;\n}\n\n/** One complete calendar window, shared by all readers of the same query. */\nexport function useDailyReleases(q: DailyReleasesQuery | null = {}, o: { client?: ContentKitClient } = {}): UseDailyReleases {\n const { client, store, scope } = useContentScope(o.client);\n const query = useDisplay(q);\n const r = useResource<DailyReleases>(store, query ? keyOf(\"daily-releases\", scope, query) : null, { type: \"daily-releases\" }, (signal) => client.discovery.releases(query!, signal));\n return { data: r.data, loading: !!query && (r.loading || !r.loaded), error: r.error, reload: r.reload };\n}\n\nexport interface UseHistory extends UseList<Card> {\n /** Erases the reader's history: of one content item, one kind, or (no argument) everything. */\n forget: (o?: { kind?: string; content_id?: string }) => Promise<void>;\n}\n\n/** What the signed-in reader engaged with, most recent first; nothing signed out, or when q is null. */\nexport function useHistory(q: HistoryQuery | null = {}, o: { client?: ContentKitClient } = {}): UseHistory {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q);\n const guarded = useGuarded();\n const list = useList(store, viewer === null || !query ? null : keyOf(\"history\", scope, query), { type: \"history\" }, async (cursor, signal) =>\n page(await client.discovery.history({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n const forget = useCallback((f: { kind?: string; content_id?: string } = {}) => guarded(() => client.discovery.forgetHistory(f)), [client, guarded]);\n return { ...list, forget };\n}\n\nexport interface UseRecentSearches {\n searches: RecentSearch[];\n loading: boolean;\n error?: ContentKitError;\n /** Clears one query, or every recent search. */\n clear: (query?: string) => Promise<void>;\n}\n\n/** Guest history stays in this browser; account history comes only from the server. enabled false reads nothing yet. */\nexport function useRecentSearches(o: { limit?: number; enabled?: boolean; client?: ContentKitClient } = {}): UseRecentSearches {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const guarded = useGuarded();\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n const guest = viewer === null;\n const enabled = o.enabled !== false;\n const browser = client.discovery.browserSearches;\n const subscribe = useCallback((listener: () => void) => guest && enabled ? browser.subscribe(listener) : () => {}, [browser, guest, enabled]);\n const snapshot = useCallback(() => guest && enabled ? browser.snapshot() : NO_SEARCHES, [browser, guest, enabled]);\n const local = useSyncExternalStore(subscribe, snapshot, () => NO_SEARCHES);\n const searches = useMemo(() => local.slice(0, recentSearchLimit(o.limit)), [local, o.limit]);\n const key = !enabled || guest ? null : keyOf(\"searches\", scope, o.limit ?? 10);\n const r = useResource<RecentSearch[]>(store, key, { type: \"searches\" }, async (s) => (await client.discovery.recentSearches({ limit: o.limit }, s)).searches);\n useEffect(() => {\n if (!key) return;\n const reload = () => { if (!store.snapshot(key).loading) store.load(key, true); };\n // Reopening a panel must not leave an already-cached account list stale.\n if (store.snapshot(key).loaded) reload();\n const visible = () => { if (document.visibilityState === \"visible\") reload(); };\n if (typeof window !== \"undefined\") window.addEventListener(\"focus\", reload);\n if (typeof document !== \"undefined\") document.addEventListener(\"visibilitychange\", visible);\n return () => {\n if (typeof window !== \"undefined\") window.removeEventListener(\"focus\", reload);\n if (typeof document !== \"undefined\") document.removeEventListener(\"visibilitychange\", visible);\n };\n }, [key, store]);\n const clear = useCallback(async (query?: string) => {\n if (!isCurrent()) return;\n if (guest) { browser.clear(query); return; }\n await guarded(() => isCurrent() ? client.discovery.clearSearches(query ? { query } : {}) : Promise.resolve());\n }, [browser, client, guest, guarded, isCurrent]);\n return guest\n ? { searches: enabled ? searches : NO_SEARCHES, loading: false, clear }\n : { searches: r.data ?? NO_SEARCHES, loading: !!key && (r.loading || !r.loaded), error: r.error, clear };\n}\n\n/** A favorite or reaction with its content's or group's id. */\nexport type MyInteraction = Interaction & { id: string };\n\nconst interactions = (p: InteractionPage) => ({ items: p.items.map((x) => ({ ...x, id: x.content?.id ?? x.entity?.id ?? \"\" })), next: p.next_cursor ?? null });\n\n/** The signed-in reader's favorites, most recent first: content cards or groups. */\nexport function useMyFavorites(q: MineQuery = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"favorites\", scope, query), { type: \"favorites\" }, async (cursor, signal) =>\n interactions(await client.favorites.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\n/** What the signed-in reader liked (or, with value, disliked), most recent first. */\nexport function useMyReactions(q: MineQuery & { value?: \"like\" | \"dislike\" } = {}, o: { client?: ContentKitClient } = {}): UseList<MyInteraction> {\n const { client, store, scope, viewer } = useContentScope(o.client);\n const query = useDisplay(q)!;\n return useList(store, viewer === null ? null : keyOf(\"reactions\", scope, query), { type: \"reactions\" }, async (cursor, signal) =>\n interactions(await client.reactions.mine({ ...query, cursor: cursor as string | undefined }, signal)),\n );\n}\n\nexport interface UseContentFilters {\n /** null until the configured filters have loaded. */\n filters: ContentFilters | null;\n loading: boolean;\n error?: ContentKitError;\n saving: boolean;\n /** Replaces offered settings for the supplied kinds; other kinds remain unchanged. */\n save: (update: ContentFiltersUpdate) => Promise<ContentFilters>;\n /** Shows or hides one filter's group, keeping the other settings. */\n setVisible: (kind: string, entityId: string, visible: boolean) => Promise<ContentFilters>;\n setIncludeDeleted: (include: boolean) => Promise<ContentFilters>;\n}\n\n/** Current-domain toggles: browser choices for guests, server choices for accounts. */\nexport function useContentFilters(o: { language?: string; client?: ContentKitClient } = {}): UseContentFilters {\n const { client, store, scope, viewer, language: provided } = useContentScope(o.client);\n const language = o.language ?? provided;\n const guest = viewer === null;\n const browser = client.preferences.browser;\n const local = useSyncExternalStore(browser.subscribe, browser.snapshot, browser.snapshot);\n const key = keyOf(\"content-filters\", scope, language);\n const previous = useRef<{ client: ContentKitClient; language?: string; guest: boolean; data?: ContentFilters } | null>(null);\n const initial = guest && previous.current?.guest && previous.current.client === client && previous.current.language === language ? previous.current.data : undefined;\n const r = useResource<ContentFilters>(store, key, { type: \"content-filters\" }, (s) => client.discovery.contentFilters(language, s), { initial });\n previous.current = { client, language, guest, data: r.data };\n const applyGuest = useCallback((source: ContentFilters, choices = local): ContentFilters => {\n const legacy = new Map(choices.legacy_filters.map((f) => [f.entity_id, f.visible]));\n return { include_deleted: false, kinds: Object.fromEntries(Object.entries(source.kinds).map(([kind, rows]) => {\n const values = new Map<string, boolean | undefined>(legacy);\n for (const f of choices.kinds[kind] ?? []) values.set(f.entity_id, f.default ? undefined : f.visible);\n return [kind, rows.map((f) => ({ ...f, visible: values.get(f.entity.id) ?? f.default_visible, overridden: values.get(f.entity.id) !== undefined }))];\n })) };\n }, [local]);\n const displayed = useMemo(() => r.data && guest ? applyGuest(r.data) : r.data, [r.data, guest, applyGuest]);\n const guarded = useGuarded();\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n const [inflight, setInflight] = useState(0);\n const current = useRef(displayed);\n current.current = displayed;\n useEffect(() => { setInflight(0); }, [client, scope]);\n const save = useCallback(\n async (update: ContentFiltersUpdate) => {\n if (!isCurrent()) throw new ContentKitError(\"aborted\", \"The account changed.\");\n if (guest) {\n const source = current.current;\n if (!source) throw new ContentKitError(\"invalid_request\", \"Content filters have not loaded.\");\n const snapshot = browser.snapshot();\n const merged = { ...snapshot.kinds };\n const legacy = new Set(snapshot.legacy_filters.map((row) => row.entity_id));\n for (const [kind, updates] of Object.entries(update.kinds)) {\n const offered = source.kinds[kind];\n if (!offered) throw new ContentKitError(\"invalid_request\", \"This content kind has no configurable filters.\");\n const allowed = new Set(offered.map((f) => f.entity.id));\n if (updates.some((f) => !allowed.has(f.entity_id))) throw new ContentKitError(\"invalid_request\", \"This content filter is not configured.\");\n const explicit = new Set(updates.map((f) => f.entity_id));\n // Resets follow whichever domain default is current, while suppressing\n // an old unscoped preference for only this kind/entity pair.\n const defaults = offered.filter((f) => legacy.has(f.entity.id) && !explicit.has(f.entity.id))\n .map((f) => ({ entity_id: f.entity.id, default: true as const }));\n merged[kind] = [...(snapshot.kinds[kind] ?? []).filter((f) => !allowed.has(f.entity_id)), ...updates, ...defaults];\n }\n client.preferences.setGuestFilters(merged);\n return applyGuest(source, { ...snapshot, kinds: merged });\n }\n setInflight((n) => n + 1);\n try {\n const out = await guarded(() => {\n if (!isCurrent()) throw new ContentKitError(\"aborted\", \"The account changed.\");\n return client.discovery.setContentFilters(update, language);\n });\n if (isCurrent()) store.set(key, out);\n return out;\n } finally {\n setInflight((n) => Math.max(0, n - 1));\n }\n },\n [client, guarded, language, key, store, isCurrent, guest, browser, applyGuest],\n );\n const settings = (f: ContentFilters) => Object.fromEntries(Object.entries(f.kinds).map(([kind, rows]) =>\n [kind, rows.filter((x) => x.overridden).map((x) => ({ entity_id: x.entity.id, visible: x.visible }))]));\n const setVisible = useCallback(\n async (kind: string, entityId: string, visible: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n if (guest) {\n if (!isCurrent()) return Promise.reject(new ContentKitError(\"aborted\", \"The account changed.\"));\n if (!f.kinds[kind]?.some((row) => row.entity.id === entityId)) return Promise.reject(new ContentKitError(\"invalid_request\", \"This content filter is not configured.\"));\n const snapshot = browser.snapshot();\n const kinds = { ...snapshot.kinds, [kind]: [...(snapshot.kinds[kind] ?? []).filter((row) => row.entity_id !== entityId), { entity_id: entityId, visible }] };\n client.preferences.setGuestFilters(kinds);\n return Promise.resolve(applyGuest(f, { ...snapshot, kinds }));\n }\n const rows = settings(f)[kind] ?? [];\n return save({ kinds: { [kind]: [...rows.filter((x) => x.entity_id !== entityId), { entity_id: entityId, visible }] }, include_deleted: f.include_deleted });\n },\n [save, guest, isCurrent, browser, applyGuest, client],\n );\n const setIncludeDeleted = useCallback(\n (include: boolean) => {\n const f = current.current;\n if (!f) return Promise.reject(new Error(\"contentkit-ui: the content filters have not loaded\"));\n return save({ kinds: {}, include_deleted: include });\n },\n [save],\n );\n return { filters: displayed ?? null, loading: r.loading || !r.loaded, error: r.error, saving: inflight > 0, save, setVisible, setIncludeDeleted };\n}\n\nexport interface UseTypeahead {\n contents: Card[];\n entities: GroupCard[];\n /** The query the suggestions answer (trimmed). */\n query: string;\n loading: boolean;\n error?: ContentKitError;\n}\n\nconst NONE: Pick<UseTypeahead, \"contents\" | \"entities\"> = { contents: [], entities: [] };\n\n/** Suggestions while the reader types: debounced, the stale ones abandoned. */\nexport function useTypeahead(\n text: string,\n o: Omit<TypeaheadQuery, \"q\"> & { debounce?: number; minLength?: number; client?: ContentKitClient; management?: boolean } = {},\n): UseTypeahead {\n const { client, language, scope: viewerScope } = useContentScope(o.client);\n const { debounce = 150, minLength = 1, client: _own, management = false, ...rest } = o;\n const scope = JSON.stringify([viewerScope, management]);\n const q = text.trim();\n const query = useMemo(() => ({ display_language: language, ...rest, q }), [language, q, JSON.stringify(rest)]); // eslint-disable-line react-hooks/exhaustive-deps\n const [state, setState] = useState<UseTypeahead & { scope: string }>({ ...NONE, query: \"\", loading: false, scope });\n useEffect(() => {\n if (q.length < minLength) {\n setState({ ...NONE, query: \"\", loading: false, scope });\n return;\n }\n setState((s) => ({ ...(s.scope === scope ? s : { ...NONE, query: \"\" }), loading: true, scope }));\n const ctl = new AbortController();\n const timer = setTimeout(() => {\n const request = management\n ? client.entities.manage({ q, kind: query.entity_kinds?.[0], language: query.display_language, limit: query.limit ?? 10 }, ctl.signal)\n .then((page) => ({ contents: [], entities: page.entities }))\n : client.discovery.typeahead(query, ctl.signal);\n request.then(\n (r) => { if (!ctl.signal.aborted) setState({ contents: r.contents, entities: r.entities, query: q, loading: false, scope }); },\n (e) => {\n const error = toContentKitError(e);\n if (!ctl.signal.aborted && error.code !== \"aborted\") setState({ ...NONE, query: q, loading: false, error, scope });\n },\n );\n }, debounce);\n return () => {\n clearTimeout(timer);\n ctl.abort();\n };\n }, [client, query, q, debounce, minLength, management, scope]);\n return state.scope === scope ? state : { ...NONE, query: \"\", loading: q.length >= minLength };\n}\n\nconst beacons = new WeakMap<ContentKitClient, Beacons>();\n\n/** The client's signal and exposure batcher: one per client. */\nexport function beaconsFor(client: ContentKitClient, o?: BeaconOptions): Beacons {\n let b = beacons.get(client);\n if (!b) beacons.set(client, (b = new Beacons(client, o)));\n return b;\n}\n\nexport function useBeacons(o: { client?: ContentKitClient } = {}): Beacons {\n const { client } = useContentScope(o.client);\n return beaconsFor(client);\n}\n\n/** A view of a content (or one version) while it is shown: report its progress as it changes. */\nexport function useViewSignal(content: string | null | undefined, version?: string, o: Attribution & { client?: ContentKitClient } = {}): ViewSession[\"update\"] {\n const { client, scope, viewer, language } = useContentScope(o.client);\n const b = beaconsFor(client);\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n // Retire the mutable session whenever its owner or read scope changes.\n const holder = useMemo(() => ({ session: undefined as ViewSession | undefined }), [b, content, version, scope]); // eslint-disable-line react-hooks/exhaustive-deps\n return useCallback((u) => {\n if (!content || !isCurrent() || (viewer !== undefined && client.preferences.identity() !== viewer)) return;\n // Create after the committed provider has configured authentication, not\n // during render while the transport can still belong to the old account.\n holder.session ??= b.view(content, version, { render_id: o.render_id, surface: o.surface, position: o.position, language: o.language ?? language });\n holder.session.update(u);\n }, [b, client, content, version, viewer, language, o.language, o.render_id, o.surface, o.position, holder, isCurrent]);\n}\n\nexport interface ExposureOptions {\n /** Where the list is: \"home\", \"search\", \"similar\". */\n surface: string;\n /** Changes with what the list shows: a new render id. */\n render: string;\n ranker?: string;\n query_id?: string;\n language?: string;\n client?: ContentKitClient;\n}\n\nexport interface UseExposure {\n /** The first bounded segment; click() selects the matching segment for later positions. */\n render_id: string;\n /** A card's ref: reports it shown once at least half of it is in view. */\n track: (content: string, position: number) => (el: Element | null) => void;\n /** Reports a click on the card at position. */\n click: (content: string, position: number) => void;\n}\n\n/** A rendered result list: each page rendered, each card shown, clicks attributed to the render. */\nexport function useExposure(items: readonly { id: string; version_id?: string; version?: { id: string } | null }[], o: ExposureOptions): UseExposure {\n const { client, scope, language } = useContentScope(o.client);\n const b = beaconsFor(client);\n const isCurrent = useCurrentDiscoveryScope(client, scope);\n const renderId = useMemo(() => eventId(), [o.render, scope]); // eslint-disable-line react-hooks/exhaustive-deps\n const base = useMemo(() => ({ surface: o.surface, ranker: o.ranker, query_id: o.query_id, language: o.language ?? language }), [o.surface, o.ranker, o.query_id, o.language, language]);\n const state = useMemo(() => ({ segments: new Map<number, ExposureSegment>(), pending: new Set<number>(), timer: undefined as ReturnType<typeof setTimeout> | undefined }), [renderId]); // eslint-disable-line react-hooks/exhaustive-deps\n const segmentID = useCallback((index: number) => index === 0 ? renderId : `${renderId}-${index}`, [renderId]);\n const segmentFor = useCallback((index: number) => {\n let segment = state.segments.get(index);\n if (!segment) {\n segment = { rendered: new Map(), visible: new Map(), renderedRevision: 0, visibleRevision: 0 };\n state.segments.set(index, segment);\n }\n return segment;\n }, [state]);\n useEffect(() => {\n if (!isCurrent()) return;\n const changed = new Set<number>();\n for (const [i, item] of items.entries()) {\n const index = Math.floor(i / EXPOSURE_SEGMENT_SIZE), segment = segmentFor(index);\n if (segment.rendered.has(item.id)) continue;\n segment.rendered.set(item.id, { content_id: item.id, version_id: item.version_id ?? item.version?.id, position: i + 1 });\n changed.add(index);\n }\n for (const index of changed) {\n const segment = segmentFor(index);\n b.exposure({ ...base, render_id: segmentID(index), stage: \"rendered\", revision: ++segment.renderedRevision,\n occurred_at: segment.renderedAt ??= new Date().toISOString(), shown: [...segment.rendered.values()] });\n }\n }, [b, base, items, state, segmentFor, segmentID, isCurrent]);\n const observer = useMemo(() => {\n if (typeof IntersectionObserver !== \"function\") return null;\n return new IntersectionObserver((entries) => {\n if (!isCurrent()) return;\n for (const e of entries) {\n if (!e.isIntersecting) continue;\n const el = e.target as HTMLElement, content = el.dataset.exposureContent!;\n const position = Number(el.dataset.exposurePosition), index = Math.floor((position - 1) / EXPOSURE_SEGMENT_SIZE);\n const segment = segmentFor(index);\n if (segment.visible.has(content)) continue;\n segment.visible.set(content, segment.rendered.get(content) ?? { content_id: content, position });\n state.pending.add(index);\n }\n if (!state.pending.size) return;\n state.timer ??= setTimeout(() => {\n state.timer = undefined;\n if (!isCurrent()) return;\n for (const index of state.pending) {\n const segment = segmentFor(index);\n b.exposure({ ...base, render_id: segmentID(index), stage: \"visible\", revision: ++segment.visibleRevision,\n occurred_at: segment.visibleAt ??= new Date().toISOString(), shown: [...segment.visible.values()] });\n }\n state.pending.clear();\n }, 300);\n }, { threshold: 0.5 });\n }, [b, base, state, segmentFor, segmentID, isCurrent]);\n useEffect(() => () => { observer?.disconnect(); clearTimeout(state.timer); }, [observer, state]);\n useEffect(() => {\n for (const index of state.segments.keys()) b.beginExposure(segmentID(index));\n return () => { for (const index of state.segments.keys()) b.endExposure(segmentID(index)); };\n }, [b, state, segmentID]);\n const track = useCallback((content: string, position: number) => (el: Element | null) => {\n if (!el || !observer) return;\n (el as HTMLElement).dataset.exposureContent = content;\n (el as HTMLElement).dataset.exposurePosition = String(position);\n observer.observe(el);\n }, [observer]);\n const click = useCallback((content: string, position: number) => {\n if (!isCurrent()) return;\n const index = Math.floor((position - 1) / EXPOSURE_SEGMENT_SIZE);\n const item = items.find((item) => item.id === content);\n const version = item?.version_id ?? item?.version?.id;\n b.click(content, { render_id: segmentID(index), surface: o.surface, position, version_id: version, language: base.language });\n }, [b, items, segmentID, o.surface, base.language, isCurrent]);\n return { render_id: renderId, track, click };\n}\n\ntype ObservedPlacement = { content_id: string; version_id?: string; position: number };\ntype ExposureSegment = {\n rendered: Map<string, ObservedPlacement>;\n visible: Map<string, ObservedPlacement>;\n renderedRevision: number;\n visibleRevision: number;\n renderedAt?: string;\n visibleAt?: string;\n};\nconst EXPOSURE_SEGMENT_SIZE = 32;\n"],"mappings":"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"}
|
package/dist/react/provider.js
CHANGED
|
@@ -8,7 +8,10 @@ function c({ client: c, viewer: l, language: u, languagePreference: d, accessRev
|
|
|
8
8
|
viewer: l,
|
|
9
9
|
language: u,
|
|
10
10
|
accessRevision: f,
|
|
11
|
-
guestFilters: l === null ?
|
|
11
|
+
guestFilters: l === null ? {
|
|
12
|
+
kinds: b.kinds,
|
|
13
|
+
legacy_filters: b.legacy_filters
|
|
14
|
+
} : void 0
|
|
12
15
|
});
|
|
13
16
|
r(() => {
|
|
14
17
|
c.preferences.configure(l, d);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","names":[],"sources":["../../src/react/provider.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useMemo, useRef, useSyncExternalStore, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { ContentKitChange } from \"../client/http.js\";\nimport type { ContentURLs } from \"../urls/index.js\";\nimport { ContentKitContext, type ContentKitErrorHandler, type Navigate } from \"./context.js\";\nimport { storeFor } from \"./store.js\";\nimport type { LanguagePreference } from \"../client/reader-preferences.js\";\n\nexport interface ContentKitProviderProps {\n client: ContentKitClient;\n /** The signed-in user's id as ContentKit sees it (the actor id), or null when signed out. */\n viewer?: string | null;\n /** Request language; keep it in sync with the client's language callback. */\n language?: string;\n /** Account storage for the preferred language; return null when unset. */\n languagePreference?: LanguagePreference;\n /** Change when the current viewer's permissions or entitlements change. */\n accessRevision?: string | number;\n /** Asks the visitor to sign in: comments, reactions, favorites and votes prompt with it rather than act anonymously. */\n onSignIn?: () => void;\n /** Content URL helpers (createContentURLs from `/urls`). */\n urls?: ContentURLs;\n /** Host router for in-app navigation (a canonical replace). */\n navigate?: Navigate;\n /** Every successful mutation; null scope means refetch instead of applying its data. */\n onChange?: (change: ContentKitChange, scope: string | null) => void;\n /** Receives every failure the components show (a component's own `onError` wins). */\n onError?: ContentKitErrorHandler;\n children?: ReactNode;\n}\n\n/** Client, URL config, callbacks and the shared read store for every hook below. Renders no DOM. */\nexport function ContentKitProvider({ client, viewer, language, languagePreference, accessRevision, onSignIn, urls, navigate, onChange, onError, children }: ContentKitProviderProps) {\n const browser = client.preferences.browser;\n const preferences = useSyncExternalStore(browser.subscribe, browser.snapshot, browser.snapshot);\n const readScope = JSON.stringify({ viewer, language, accessRevision, guestFilters: viewer === null ? preferences.
|
|
1
|
+
{"version":3,"file":"provider.js","names":[],"sources":["../../src/react/provider.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useMemo, useRef, useSyncExternalStore, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport type { ContentKitChange } from \"../client/http.js\";\nimport type { ContentURLs } from \"../urls/index.js\";\nimport { ContentKitContext, type ContentKitErrorHandler, type Navigate } from \"./context.js\";\nimport { storeFor } from \"./store.js\";\nimport type { LanguagePreference } from \"../client/reader-preferences.js\";\n\nexport interface ContentKitProviderProps {\n client: ContentKitClient;\n /** The signed-in user's id as ContentKit sees it (the actor id), or null when signed out. */\n viewer?: string | null;\n /** Request language; keep it in sync with the client's language callback. */\n language?: string;\n /** Account storage for the preferred language; return null when unset. */\n languagePreference?: LanguagePreference;\n /** Change when the current viewer's permissions or entitlements change. */\n accessRevision?: string | number;\n /** Asks the visitor to sign in: comments, reactions, favorites and votes prompt with it rather than act anonymously. */\n onSignIn?: () => void;\n /** Content URL helpers (createContentURLs from `/urls`). */\n urls?: ContentURLs;\n /** Host router for in-app navigation (a canonical replace). */\n navigate?: Navigate;\n /** Every successful mutation; null scope means refetch instead of applying its data. */\n onChange?: (change: ContentKitChange, scope: string | null) => void;\n /** Receives every failure the components show (a component's own `onError` wins). */\n onError?: ContentKitErrorHandler;\n children?: ReactNode;\n}\n\n/** Client, URL config, callbacks and the shared read store for every hook below. Renders no DOM. */\nexport function ContentKitProvider({ client, viewer, language, languagePreference, accessRevision, onSignIn, urls, navigate, onChange, onError, children }: ContentKitProviderProps) {\n const browser = client.preferences.browser;\n const preferences = useSyncExternalStore(browser.subscribe, browser.snapshot, browser.snapshot);\n const readScope = JSON.stringify({ viewer, language, accessRevision, guestFilters: viewer === null ? { kinds: preferences.kinds, legacy_filters: preferences.legacy_filters } : undefined });\n useLayoutEffect(() => { client.preferences.configure(viewer, languagePreference); }, [client, viewer, languagePreference]);\n useLayoutEffect(() => { client.setReadScope(readScope); }, [client, readScope]);\n const changed = useRef(onChange);\n useEffect(() => {\n changed.current = onChange;\n });\n useEffect(() => client.subscribe((c, scope) => changed.current?.(c, scope)), [client]);\n const value = useMemo(\n () => ({ client, viewer, language, accessRevision, readScope, onSignIn, urls, navigate, onError, store: storeFor(client) }),\n [client, viewer, language, accessRevision, readScope, onSignIn, urls, navigate, onError],\n );\n return <ContentKitContext.Provider value={value}>{children}</ContentKitContext.Provider>;\n}\n"],"mappings":";;;;;AAgCA,SAAgB,EAAmB,EAAE,WAAQ,WAAQ,aAAU,uBAAoB,mBAAgB,aAAU,SAAM,aAAU,aAAU,YAAS,eAAqC;CACnL,IAAM,IAAU,EAAO,YAAY,SAC7B,IAAc,EAAqB,EAAQ,WAAW,EAAQ,UAAU,EAAQ,QAAQ,GACxF,IAAY,KAAK,UAAU;EAAE;EAAQ;EAAU;EAAgB,cAAc,MAAW,OAAO;GAAE,OAAO,EAAY;GAAO,gBAAgB,EAAY;EAAe,IAAI,KAAA;CAAU,CAAC;CAE3L,AADA,QAAsB;EAAE,EAAO,YAAY,UAAU,GAAQ,CAAkB;CAAG,GAAG;EAAC;EAAQ;EAAQ;CAAkB,CAAC,GACzH,QAAsB;EAAE,EAAO,aAAa,CAAS;CAAG,GAAG,CAAC,GAAQ,CAAS,CAAC;CAC9E,IAAM,IAAU,EAAO,CAAQ;CAI/B,AAHA,QAAgB;EACd,EAAQ,UAAU;CACpB,CAAC,GACD,QAAgB,EAAO,WAAW,GAAG,MAAU,EAAQ,UAAU,GAAG,CAAK,CAAC,GAAG,CAAC,CAAM,CAAC;CACrF,IAAM,IAAQ,SACL;EAAE;EAAQ;EAAQ;EAAU;EAAgB;EAAW;EAAU;EAAM;EAAU;EAAS,OAAO,EAAS,CAAM;CAAE,IACzH;EAAC;EAAQ;EAAQ;EAAU;EAAgB;EAAW;EAAU;EAAM;EAAU;CAAO,CACzF;CACA,OAAO,kBAAC,EAAkB,UAAnB;EAAmC;EAAQ;CAAqC,CAAA;AACzF"}
|