@openrails/contentkit-ui 0.94.0 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +43 -1
  2. package/dist/client/discovery.d.ts +14 -1
  3. package/dist/client/discovery.js +27 -14
  4. package/dist/client/discovery.js.map +1 -1
  5. package/dist/client/generated/routes.d.ts +18 -5
  6. package/dist/client/generated/routes.js +39 -0
  7. package/dist/client/generated/routes.js.map +1 -1
  8. package/dist/client/generated/wire.d.ts +10 -0
  9. package/dist/client/generated/wire.js.map +1 -1
  10. package/dist/client/index.d.ts +1 -1
  11. package/dist/client.js +17 -17
  12. package/dist/components/content/card.d.ts +21 -5
  13. package/dist/components/content/card.js +80 -67
  14. package/dist/components/content/card.js.map +1 -1
  15. package/dist/components/content/daily-releases.d.ts +15 -0
  16. package/dist/components/content/daily-releases.js +167 -0
  17. package/dist/components/content/daily-releases.js.map +1 -0
  18. package/dist/components/content/grid.d.ts +14 -1
  19. package/dist/components/content/grid.js +58 -32
  20. package/dist/components/content/grid.js.map +1 -1
  21. package/dist/components/content/index.d.ts +4 -2
  22. package/dist/components/content/popular.d.ts +11 -0
  23. package/dist/components/content/popular.js +49 -0
  24. package/dist/components/content/popular.js.map +1 -0
  25. package/dist/index.js +22 -20
  26. package/dist/locales/discovery/de.js +4 -0
  27. package/dist/locales/discovery/de.js.map +1 -1
  28. package/dist/locales/discovery/en.d.ts +4 -0
  29. package/dist/locales/discovery/en.js +4 -0
  30. package/dist/locales/discovery/en.js.map +1 -1
  31. package/dist/locales/discovery/es.js +4 -0
  32. package/dist/locales/discovery/es.js.map +1 -1
  33. package/dist/locales/discovery/ja.js +4 -0
  34. package/dist/locales/discovery/ja.js.map +1 -1
  35. package/dist/locales/discovery/ko.js +4 -0
  36. package/dist/locales/discovery/ko.js.map +1 -1
  37. package/dist/locales/discovery/zh.js +4 -0
  38. package/dist/locales/discovery/zh.js.map +1 -1
  39. package/dist/locales/en.d.ts +4 -0
  40. package/dist/react/discovery.d.ts +12 -2
  41. package/dist/react/discovery.js +32 -23
  42. package/dist/react/discovery.js.map +1 -1
  43. package/dist/react/index.d.ts +1 -1
  44. package/dist/react/resources.js +11 -11
  45. package/dist/react/resources.js.map +1 -1
  46. package/dist/react.js +10 -10
  47. package/dist/styles.css +1 -1
  48. package/package.json +1 -1
@@ -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, HistoryQuery, RailQuery, ReleaseDatesQuery, SearchQuery, TypeaheadQuery } from \"../client/discovery.js\";\nimport { ContentKitError, toContentKitError } from \"../client/errors.js\";\nimport type { Card, ContentFilters, ContentFiltersUpdate, ContentPage, 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 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/** Configured filters: 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 browser.setFilters(update.filters);\n return applyGuest(source, update.filters);\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 } = {},\n): UseTypeahead {\n const { client, language } = useContentScope(o.client);\n const { debounce = 150, minLength = 1, client: _own, ...rest } = o;\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>({ ...NONE, query: \"\", loading: false });\n useEffect(() => {\n if (q.length < minLength) {\n setState({ ...NONE, query: \"\", loading: false });\n return;\n }\n setState((s) => ({ ...s, loading: true }));\n const ctl = new AbortController();\n const timer = setTimeout(() => {\n client.discovery.typeahead(query, ctl.signal).then(\n (r) => setState({ contents: r.contents, entities: r.entities, query: q, loading: false }),\n (e) => {\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") setState({ ...NONE, query: q, loading: false, error });\n },\n );\n }, debounce);\n return () => {\n clearTimeout(timer);\n ctl.abort();\n };\n }, [client, query, q, debounce, minLength]);\n return state;\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":";;;;;;;AAWA,IAAM,KAAQ,OAAoB;CAAE,OAAO,EAAE;CAAU,MAAM,EAAE,eAAe;AAAK,IAC7E,IAA8B,CAAC;AAGrC,SAAS,EAAyB,GAA0B,GAA8B;CACxF,IAAM,IAAQ,SAAe;EAAE;EAAQ;CAAM,IAAI,CAAC,GAAQ,CAAK,CAAC,GAC1D,IAAU,EAA4B,CAAK;CAKjD,OAJA,SACE,EAAQ,UAAU,SACL;EAAE,EAAQ,UAAU;CAAM,IACtC,CAAC,CAAK,CAAC,GACH,QAAkB,EAAQ,YAAY,GAAO,CAAC,CAAK,CAAC;AAC7D;AAGA,SAAS,EAAoD,GAAuB;CAClF,IAAM,IAAW,EAAW,CAAiB,CAAC,EAAE;CAChD,OAAO,QAAe,KAAK,CAAC,EAAE,oBAAoB,IAAW;EAAE,GAAG;EAAG,kBAAkB;CAAS,IAAI,GAAI,CAAC,GAAG,CAAQ,CAAC;AACvH;AAGA,SAAgB,EAAY,GAAwB,IAAmC,CAAC,GAAkB;CACxG,IAAM,EAAE,WAAQ,UAAO,aAAU,EAAgB,EAAE,MAAM,GACnD,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,GAAO,IAAQ,EAAM,SAAS,GAAO,QAAQ,CAAK,IAAI,MAAM,EAAE,MAAM,QAAQ,GAAG,OAAO,GAAQ,MAC3G,EAAK,MAAM,EAAO,UAAU,KAAK;EAAE,GAAG;EAAe;CAA6B,GAAG,CAAM,CAAC,CAC9F;AACF;AAOA,SAAgB,EAAe,GAAwB,IAAmC,CAAC,GAAyC;CAClI,IAAM,EAAE,WAAQ,UAAO,aAAU,EAAgB,EAAE,MAAM,GAMnD,IAAQ,EALC,QAAc;EAC3B,IAAI,CAAC,GAAG,OAAO;EACf,IAAM,EAAE,MAAM,GAAI,QAAQ,GAAI,OAAO,GAAI,eAAe,GAAI,MAAM,GAAI,GAAG,MAAM;EAC/E,OAAO;CACT,GAAG,CAAC,CAAC,CACoB,CAAM,GACzB,IAAI,EAAoB,GAAO,IAAQ,EAAM,iBAAiB,GAAO,UAAU,CAAK,IAAI,MAAM,EAAE,MAAM,gBAAgB,GAAG,OAAO,MAAW;EAC/I,IAAM,IAAQ,OAAO,OAClB,MAAM,EAAO,UAAU,aAAa;GAAE,GAAG;GAAO;GAAM,IAAI;GAAS,OAAO;EAAK,GAAG,CAAM,EAAA,CAAG,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,GAC7H,CAAC,GAAK,KAAQ,MAAM,QAAQ,IAAI,CAAC,EAAM,MAAM,GAAG,EAAM,MAAM,CAAC,CAAC;EACpE,OAAO,KAAK,IAAI,GAAG,IAAM,CAAI;CAC/B,CAAC;CACD,OAAO;EAAE,OAAO,EAAE;EAAM,SAAS,EAAE;CAAQ;AAC7C;AAGA,SAAgB,EAAU,GAAuB,IAAmC,CAAC,GAAkB;CACrG,IAAM,EAAE,WAAQ,UAAO,UAAO,cAAW,EAAgB,EAAE,MAAM,GAC3D,IAAQ,EAAW,GAAG,EAAE,KAAK,IAAI,IAAI,IAAI,GACzC,IAAY,EAAyB,GAAQ,CAAK;CACxD,OAAO,EAAQ,GAAO,IAAQ,EAAM,SAAS,GAAO,UAAU,CAAK,IAAI,MAAM,EAAE,MAAM,QAAQ,GAAG,OAAO,GAAQ,MAAW;EACxH,IAAM,IAAM,MAAM,EAAO,UAAU,OAAO;GAAE,GAAG;GAAgB;EAA6B,GAAG,CAAM;EAErG,OADI,CAAC,KAAU,MAAW,QAAQ,CAAC,EAAO,WAAW,EAAU,KAAG,EAAO,UAAU,gBAAgB,OAAO,EAAO,GAAG,EAAI,SAAS,MAAM,GAChI,EAAK,CAAG;CACjB,CAAC;AACH;AAWA,SAAS,EAAQ,GAAoB,GAAsD,GAA2C;CACpI,IAAM,EAAE,aAAU,EAAgB,EAAE,MAAM,GACpC,IAAI,EAAoB,GAAO,GAAK,EAAE,MAAM,QAAQ,GAAG,OAAO,OAAY,MAAM,EAAM,CAAM,EAAA,CAAG,QAAQ,GACvG,IAAc,EAAE,OAAO,SAAS;CACtC,OAAO;EAAE,OAAO,EAAE,QAAQ,CAAC;EAAG,SAAS,CAAC,CAAC,MAAQ,EAAE,WAAW,CAAC,EAAE;EAAS,OAAO,IAAc,KAAA,IAAY,EAAE;EAAO;EAAa,QAAQ,EAAE;CAAO;AACpJ;AAGA,SAAgB,EAAW,GAA+B,IAAe,CAAC,GAAG,IAAmC,CAAC,GAAY;CAC3H,IAAM,EAAE,WAAQ,aAAU,EAAgB,EAAE,MAAM,GAC5C,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,IAAK,EAAM,SAAS,GAAO,WAAW,GAAI,CAAK,IAAI,OAAO,MAAM,EAAO,UAAU,QAAQ,GAAK,GAAO,CAAC,GAAG,CAAC;AAC3H;AAGA,SAAgB,EAAmB,IAAsB,CAAC,GAAG,IAAmC,CAAC,GAAY;CAC3G,IAAM,EAAE,WAAQ,UAAO,cAAW,EAAgB,EAAE,MAAM,GACpD,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,MAAW,QAAQ,CAAC,IAAQ,OAAO,EAAM,SAAS,GAAO,eAAe,CAAK,IAAI,MAAM,EAAO,UAAU,gBAAgB,GAAQ,CAAC,GAAG,CAAC;AACtJ;AAMA,SAAgB,EAAgB,IAAuB,CAAC,GAAG,IAAmC,CAAC,GAAyB;CACtH,IAAM,EAAE,WAAQ,UAAO,aAAU,EAAgB,EAAE,MAAM,GACnD,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,GAAO,EAAM,iBAAiB,GAAO,CAAK,GAAG,EAAE,MAAM,gBAAgB,GAAG,OAAO,GAAQ,MAAW;EAC/G,IAAM,IAAI,MAAM,EAAO,UAAU,aAAa;GAAE,GAAG;GAAe;EAA6B,GAAG,CAAM;EACxG,OAAO;GAAE,OAAO,EAAE,MAAM,KAAK,OAAO;IAAE,GAAG;IAAG,IAAI,EAAE;GAAK,EAAE;GAAG,MAAM,EAAE,eAAe;EAAK;CAC1F,CAAC;AACH;AAQA,SAAgB,EAAW,IAAyB,CAAC,GAAG,IAAmC,CAAC,GAAe;CACzG,IAAM,EAAE,WAAQ,UAAO,UAAO,cAAW,EAAgB,EAAE,MAAM,GAC3D,IAAQ,EAAW,CAAC,GACpB,IAAU,EAAW,GACrB,IAAO,EAAQ,GAAO,MAAW,QAAQ,CAAC,IAAQ,OAAO,EAAM,WAAW,GAAO,CAAK,GAAG,EAAE,MAAM,UAAU,GAAG,OAAO,GAAQ,MACjI,EAAK,MAAM,EAAO,UAAU,QAAQ;EAAE,GAAG;EAAe;CAA6B,GAAG,CAAM,CAAC,CACjG,GACM,IAAS,GAAa,IAA4C,CAAC,MAAM,QAAc,EAAO,UAAU,cAAc,CAAC,CAAC,GAAG,CAAC,GAAQ,CAAO,CAAC;CAClJ,OAAO;EAAE,GAAG;EAAM;CAAO;AAC3B;AAWA,SAAgB,EAAkB,IAAsE,CAAC,GAAsB;CAC7H,IAAM,EAAE,WAAQ,UAAO,UAAO,cAAW,EAAgB,EAAE,MAAM,GAC3D,IAAU,EAAW,GACrB,IAAY,EAAyB,GAAQ,CAAK,GAClD,IAAQ,MAAW,MACnB,IAAU,EAAE,YAAY,IACxB,IAAU,EAAO,UAAU,iBAC3B,IAAY,GAAa,MAAyB,KAAS,IAAU,EAAQ,UAAU,CAAQ,UAAU,CAAC,GAAG;EAAC;EAAS;EAAO;CAAO,CAAC,GACtI,IAAW,QAAkB,KAAS,IAAU,EAAQ,SAAS,IAAI,GAAa;EAAC;EAAS;EAAO;CAAO,CAAC,GAC3G,IAAQ,EAAqB,GAAW,SAAgB,CAAW,GACnE,IAAW,QAAc,EAAM,MAAM,GAAG,EAAkB,EAAE,KAAK,CAAC,GAAG,CAAC,GAAO,EAAE,KAAK,CAAC,GACrF,IAAM,CAAC,KAAW,IAAQ,OAAO,EAAM,YAAY,GAAO,EAAE,SAAS,EAAE,GACvE,IAAI,EAA4B,GAAO,GAAK,EAAE,MAAM,WAAW,GAAG,OAAO,OAAO,MAAM,EAAO,UAAU,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,EAAA,CAAG,QAAQ;CAC5J,QAAgB;EACd,IAAI,CAAC,GAAK;EACV,IAAM,UAAe;GAAE,AAAK,EAAM,SAAS,CAAG,CAAC,CAAC,WAAS,EAAM,KAAK,GAAK,EAAI;EAAG;EAEhF,AAAI,EAAM,SAAS,CAAG,CAAC,CAAC,UAAQ,EAAO;EACvC,IAAM,UAAgB;GAAE,AAAI,SAAS,oBAAoB,aAAW,EAAO;EAAG;EAG9E,OAFI,OAAO,SAAW,OAAa,OAAO,iBAAiB,SAAS,CAAM,GACtE,OAAO,WAAa,OAAa,SAAS,iBAAiB,oBAAoB,CAAO,SAC7E;GAEX,AADI,OAAO,SAAW,OAAa,OAAO,oBAAoB,SAAS,CAAM,GACzE,OAAO,WAAa,OAAa,SAAS,oBAAoB,oBAAoB,CAAO;EAC/F;CACF,GAAG,CAAC,GAAK,CAAK,CAAC;CACf,IAAM,IAAQ,EAAY,OAAO,MAAmB;EAC7C,MAAU,GACf;OAAI,GAAO;IAAE,EAAQ,MAAM,CAAK;IAAG;GAAQ;GAC3C,MAAM,QAAc,EAAU,IAAI,EAAO,UAAU,cAAc,IAAQ,EAAE,SAAM,IAAI,CAAC,CAAC,IAAI,QAAQ,QAAQ,CAAC;EADjE;CAE7C,GAAG;EAAC;EAAS;EAAQ;EAAO;EAAS;CAAS,CAAC;CAC/C,OAAO,IACH;EAAE,UAAU,IAAU,IAAW;EAAa,SAAS;EAAO;CAAM,IACpE;EAAE,UAAU,EAAE,QAAQ;EAAa,SAAS,CAAC,CAAC,MAAQ,EAAE,WAAW,CAAC,EAAE;EAAS,OAAO,EAAE;EAAO;CAAM;AAC3G;AAKA,IAAM,KAAgB,OAAwB;CAAE,OAAO,EAAE,MAAM,KAAK,OAAO;EAAE,GAAG;EAAG,IAAI,EAAE,SAAS,MAAM,EAAE,QAAQ,MAAM;CAAG,EAAE;CAAG,MAAM,EAAE,eAAe;AAAK;AAG5J,SAAgB,EAAe,IAAe,CAAC,GAAG,IAAmC,CAAC,GAA2B;CAC/G,IAAM,EAAE,WAAQ,UAAO,UAAO,cAAW,EAAgB,EAAE,MAAM,GAC3D,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,GAAO,MAAW,OAAO,OAAO,EAAM,aAAa,GAAO,CAAK,GAAG,EAAE,MAAM,YAAY,GAAG,OAAO,GAAQ,MACrH,EAAa,MAAM,EAAO,UAAU,KAAK;EAAE,GAAG;EAAe;CAA6B,GAAG,CAAM,CAAC,CACtG;AACF;AAGA,SAAgB,EAAe,IAAgD,CAAC,GAAG,IAAmC,CAAC,GAA2B;CAChJ,IAAM,EAAE,WAAQ,UAAO,UAAO,cAAW,EAAgB,EAAE,MAAM,GAC3D,IAAQ,EAAW,CAAC;CAC1B,OAAO,EAAQ,GAAO,MAAW,OAAO,OAAO,EAAM,aAAa,GAAO,CAAK,GAAG,EAAE,MAAM,YAAY,GAAG,OAAO,GAAQ,MACrH,EAAa,MAAM,EAAO,UAAU,KAAK;EAAE,GAAG;EAAe;CAA6B,GAAG,CAAM,CAAC,CACtG;AACF;AAgBA,SAAgB,EAAkB,IAAsD,CAAC,GAAsB;CAC7G,IAAM,EAAE,WAAQ,UAAO,UAAO,WAAQ,UAAU,MAAa,EAAgB,EAAE,MAAM,GAC/E,IAAW,EAAE,YAAY,GACzB,IAAQ,MAAW,MACnB,IAAU,EAAO,YAAY,SAC7B,IAAQ,EAAqB,EAAQ,WAAW,EAAQ,UAAU,EAAQ,QAAQ,GAClF,IAAM,EAAM,mBAAmB,GAAO,CAAQ,GAC9C,IAAW,EAAsG,IAAI,GACrH,IAAU,KAAS,EAAS,SAAS,SAAS,EAAS,QAAQ,WAAW,KAAU,EAAS,QAAQ,aAAa,IAAW,EAAS,QAAQ,OAAO,KAAA,GACrJ,IAAI,EAA4B,GAAO,GAAK,EAAE,MAAM,kBAAkB,IAAI,MAAM,EAAO,UAAU,eAAe,GAAU,CAAC,GAAG,EAAE,WAAQ,CAAC;CAC/I,EAAS,UAAU;EAAE;EAAQ;EAAU;EAAO,MAAM,EAAE;CAAK;CAC3D,IAAM,IAAa,GAAa,GAAwB,IAAW,EAAM,YAA4B;EACnG,IAAM,IAAS,IAAI,IAAI,EAAS,KAAK,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;EACnE,OAAO;GAAE,iBAAiB;GAAO,SAAS,EAAO,QAAQ,KAAK,OAAO;IAAE,GAAG;IAAG,SAAS,EAAO,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;IAAiB,YAAY,EAAO,IAAI,EAAE,OAAO,EAAE;GAAE,EAAE;EAAE;CAC9K,GAAG,CAAC,EAAM,OAAO,CAAC,GACZ,IAAY,QAAc,EAAE,QAAQ,IAAQ,EAAW,EAAE,IAAI,IAAI,EAAE,MAAM;EAAC,EAAE;EAAM;EAAO;CAAU,CAAC,GACpG,IAAU,EAAW,GACrB,IAAY,EAAyB,GAAQ,CAAK,GAClD,CAAC,GAAU,KAAe,EAAS,CAAC,GACpC,IAAU,EAAO,CAAS;CAEhC,AADA,EAAQ,UAAU,GAClB,QAAgB;EAAE,EAAY,CAAC;CAAG,GAAG,CAAC,GAAQ,CAAK,CAAC;CACpD,IAAM,IAAO,EACX,OAAO,MAAiC;EACtC,IAAI,CAAC,EAAU,GAAG,MAAM,IAAI,EAAgB,WAAW,sBAAsB;EAC7E,IAAI,GAAO;GACT,IAAM,IAAS,EAAQ;GACvB,IAAI,CAAC,GAAQ,MAAM,IAAI,EAAgB,mBAAmB,kCAAkC;GAC5F,IAAM,IAAU,IAAI,IAAI,EAAO,QAAQ,KAAK,MAAM,EAAE,OAAO,EAAE,CAAC;GAC9D,IAAI,EAAO,QAAQ,MAAM,MAAM,CAAC,EAAQ,IAAI,EAAE,QAAQ,CAAC,GAAG,MAAM,IAAI,EAAgB,mBAAmB,wCAAwC;GAE/I,OADA,EAAQ,WAAW,EAAO,OAAO,GAC1B,EAAW,GAAQ,EAAO,OAAO;EAC1C;EACA,GAAa,MAAM,IAAI,CAAC;EACxB,IAAI;GACF,IAAM,IAAM,MAAM,QAAc;IAC9B,IAAI,CAAC,EAAU,GAAG,MAAM,IAAI,EAAgB,WAAW,sBAAsB;IAC7E,OAAO,EAAO,UAAU,kBAAkB,GAAQ,CAAQ;GAC5D,CAAC;GAED,OADI,EAAU,KAAG,EAAM,IAAI,GAAK,CAAG,GAC5B;EACT,UAAU;GACR,GAAa,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;EACvC;CACF,GACA;EAAC;EAAQ;EAAS;EAAU;EAAK;EAAO;EAAW;EAAO;EAAS;CAAU,CAC/E,GACM,KAAY,MAAsB,EAAE,QAAQ,QAAQ,MAAM,EAAE,UAAU,CAAC,CAAC,KAAK,OAAO;EAAE,UAAU,EAAE,OAAO;EAAI,SAAS,EAAE;CAAQ,EAAE,GAClI,IAAa,GAChB,GAAiB,MAAqB;EACrC,IAAM,IAAI,EAAQ;EAElB,OADK,IACE,EAAK;GAAE,SAAS,CAAC,GAAG,EAAS,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,aAAa,CAAO,GAAG;IAAE,UAAU;IAAS;GAAQ,CAAC;GAAG,iBAAiB,EAAE;EAAgB,CAAC,IADpI,QAAQ,OAAO,gBAAI,MAAM,oDAAoD,CAAC;CAE/F,GACA,CAAC,CAAI,CACP,GACM,IAAoB,GACvB,MAAqB;EACpB,IAAM,IAAI,EAAQ;EAElB,OADK,IACE,EAAK;GAAE,SAAS,EAAS,CAAC;GAAG,iBAAiB;EAAQ,CAAC,IAD/C,QAAQ,OAAO,gBAAI,MAAM,oDAAoD,CAAC;CAE/F,GACA,CAAC,CAAI,CACP;CACA,OAAO;EAAE,SAAS,KAAa;EAAM,SAAS,EAAE,WAAW,CAAC,EAAE;EAAQ,OAAO,EAAE;EAAO,QAAQ,IAAW;EAAG;EAAM;EAAY;CAAkB;AAClJ;AAWA,IAAM,IAAoD;CAAE,UAAU,CAAC;CAAG,UAAU,CAAC;AAAE;AAGvF,SAAgB,EACd,GACA,IAAsG,CAAC,GACzF;CACd,IAAM,EAAE,WAAQ,gBAAa,EAAgB,EAAE,MAAM,GAC/C,EAAE,cAAW,KAAK,eAAY,GAAG,QAAQ,GAAM,GAAG,MAAS,GAC3D,IAAI,EAAK,KAAK,GACd,IAAQ,SAAe;EAAE,kBAAkB;EAAU,GAAG;EAAM;CAAE,IAAI;EAAC;EAAU;EAAG,KAAK,UAAU,CAAI;CAAC,CAAC,GACvG,CAAC,GAAO,KAAY,EAAuB;EAAE,GAAG;EAAM,OAAO;EAAI,SAAS;CAAM,CAAC;CAsBvF,OArBA,QAAgB;EACd,IAAI,EAAE,SAAS,GAAW;GACxB,EAAS;IAAE,GAAG;IAAM,OAAO;IAAI,SAAS;GAAM,CAAC;GAC/C;EACF;EACA,GAAU,OAAO;GAAE,GAAG;GAAG,SAAS;EAAK,EAAE;EACzC,IAAM,IAAM,IAAI,gBAAgB,GAC1B,IAAQ,iBAAiB;GAC7B,EAAO,UAAU,UAAU,GAAO,EAAI,MAAM,CAAC,CAAC,MAC3C,MAAM,EAAS;IAAE,UAAU,EAAE;IAAU,UAAU,EAAE;IAAU,OAAO;IAAG,SAAS;GAAM,CAAC,IACvF,MAAM;IACL,IAAM,IAAQ,EAAkB,CAAC;IACjC,AAAI,EAAM,SAAS,aAAW,EAAS;KAAE,GAAG;KAAM,OAAO;KAAG,SAAS;KAAO;IAAM,CAAC;GACrF,CACF;EACF,GAAG,CAAQ;EACX,aAAa;GAEX,AADA,aAAa,CAAK,GAClB,EAAI,MAAM;EACZ;CACF,GAAG;EAAC;EAAQ;EAAO;EAAG;EAAU;CAAS,CAAC,GACnC;AACT;AAEA,IAAM,oBAAU,IAAI,QAAmC;AAGvD,SAAgB,EAAW,GAA0B,GAA4B;CAC/E,IAAI,IAAI,EAAQ,IAAI,CAAM;CAE1B,OADK,KAAG,EAAQ,IAAI,GAAS,IAAI,IAAI,EAAQ,GAAQ,CAAC,CAAE,GACjD;AACT;AAEA,SAAgB,EAAW,IAAmC,CAAC,GAAY;CACzE,IAAM,EAAE,cAAW,EAAgB,EAAE,MAAM;CAC3C,OAAO,EAAW,CAAM;AAC1B;AAGA,SAAgB,EAAc,GAAoC,GAAkB,IAAiD,CAAC,GAA0B;CAC9J,IAAM,IAAI,EAAW,CAAC,GAChB,EAAE,QAAQ,GAAI,GAAG,MAAgB,GACjC,IAAU,QAAe,IAAU,EAAE,KAAK,GAAS,GAAS,CAAW,IAAI,MAAO;EAAC;EAAG;EAAS;CAAO,CAAC;CAC7G,OAAO,GAAa,MAAM,GAAS,OAAO,CAAC,GAAG,CAAC,CAAO,CAAC;AACzD;AAsBA,SAAgB,EAAY,GAAkC,GAAiC;CAC7F,IAAM,IAAI,EAAW,CAAC,GAChB,IAAW,QAAc,EAAQ,GAAG,CAAC,EAAE,MAAM,CAAC,GAC9C,IAAO,SAAe;EAAE,WAAW;EAAU,SAAS,EAAE;EAAS,QAAQ,EAAE;EAAQ,UAAU,EAAE;EAAU,UAAU,EAAE;CAAS,IAAI;EAAC;EAAU,EAAE;EAAS,EAAE;EAAQ,EAAE;EAAU,EAAE;CAAQ,CAAC,GACzL,IAAW,kBAAO,IAAI,IAAY,CAAC,GACnC,IAAU,kBAAO,IAAI,IAAY,CAAC;CAKxC,AAJA,QAAgB;EAEd,AADA,EAAS,0BAAU,IAAI,IAAI,GAC3B,EAAQ,0BAAU,IAAI,IAAI;CAC5B,GAAG,CAAC,CAAQ,CAAC,GACb,QAAgB;EACd,IAAM,IAAQ,EAAM,SAAS,GAAI,MAAO,EAAS,QAAQ,IAAI,EAAG,EAAE,IAAI,CAAC,IAAI,CAAC;GAAE,YAAY,EAAG;GAAI,UAAU,IAAI;EAAE,CAAC,CAAE;EACpH,KAAK,IAAM,KAAK,GAAO,EAAS,QAAQ,IAAI,EAAE,UAAU;EACxD,AAAI,EAAM,UAAQ,EAAE,SAAS;GAAE,GAAG;GAAM,OAAO;GAAY,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY;GAAG;EAAM,CAAC;CAC3G,GAAG;EAAC;EAAG;EAAM;CAAK,CAAC;CACnB,IAAM,IAAU,EAAmD,CAAC,CAAC,GAC/D,IAAQ,EAAsC,KAAA,CAAS,GACvD,IAAW,QACX,OAAO,wBAAyB,aAC7B,IAAI,sBACR,MAAY;EACX,KAAK,IAAM,KAAK,GAAS;GACvB,IAAI,CAAC,EAAE,gBAAgB;GACvB,IAAM,IAAK,EAAE,QACP,IAAU,EAAG,QAAQ;GACvB,EAAQ,QAAQ,IAAI,CAAO,MAC/B,EAAQ,QAAQ,IAAI,CAAO,GAC3B,EAAQ,QAAQ,KAAK;IAAE,YAAY;IAAS,UAAU,OAAO,EAAG,QAAQ,gBAAgB;GAAE,CAAC;EAC7F;EACA,EAAM,YAAY,iBAAiB;GACjC,EAAM,UAAU,KAAA;GAChB,IAAM,IAAQ,EAAQ,QAAQ,OAAO,CAAC;GACtC,AAAI,EAAM,UAAQ,EAAE,SAAS;IAAE,GAAG;IAAM,OAAO;IAAW,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY;IAAG;GAAM,CAAC;EAC1G,GAAG,GAAG;CACR,GACA,EAAE,WAAW,GAAI,CACnB,IAlBuD,MAmBtD,CAAC,GAAG,CAAI,CAAC;CAYZ,OAXA,cAAsB,GAAU,WAAW,GAAG,CAAC,CAAQ,CAAC,GAWjD;EAAE,WAAW;EAAU,OAVhB,GACX,GAAiB,OAAsB,MAAuB;GACzD,AAAC,KAAO,MACZ,EAAoB,QAAQ,kBAAkB,GAC9C,EAAoB,QAAQ,mBAAmB,OAAO,CAAQ,GAC9D,EAAS,QAAQ,CAAE;EACrB,GACA,CAAC,CAAQ,CAGmB;EAAO,OADvB,GAAa,GAAiB,MAAqB,EAAE,MAAM,GAAS;GAAE,WAAW;GAAU,SAAS,EAAE;GAAS;EAAS,CAAC,GAAG;GAAC;GAAG;GAAU,EAAE;EAAO,CAC5H;CAAM;AAC7C"}
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/** Configured filters: 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 browser.setFilters(update.filters);\n return applyGuest(source, update.filters);\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 } = {},\n): UseTypeahead {\n const { client, language } = useContentScope(o.client);\n const { debounce = 150, minLength = 1, client: _own, ...rest } = o;\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>({ ...NONE, query: \"\", loading: false });\n useEffect(() => {\n if (q.length < minLength) {\n setState({ ...NONE, query: \"\", loading: false });\n return;\n }\n setState((s) => ({ ...s, loading: true }));\n const ctl = new AbortController();\n const timer = setTimeout(() => {\n client.discovery.typeahead(query, ctl.signal).then(\n (r) => setState({ contents: r.contents, entities: r.entities, query: q, loading: false }),\n (e) => {\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") setState({ ...NONE, query: q, loading: false, error });\n },\n );\n }, debounce);\n return () => {\n clearTimeout(timer);\n ctl.abort();\n };\n }, [client, query, q, debounce, minLength]);\n return state;\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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"}
@@ -17,7 +17,7 @@ export { useActivity, useMyStats, useTopContents, type UseStats } from './stats.
17
17
  export { defaultVersion, editionOf, findVersion, liveVersions, useContentDetail, type ContentDetailOptions, type UseContentDetail } from './detail.js';
18
18
  export { useVersionParam } from './location.js';
19
19
  export { memberId, useContentGroups, useGroup, useGroupMembers, useGroups, useKinds, useMyGroups, type GroupFilter, type GroupSort, type Member, type UseContentGroups, type UseGroup, type UseGroupMembers, type UseKinds, } from './groups.js';
20
- export { beaconsFor, useBeacons, useContentFilters, useContents, useExposure, useHistory, useLockedCount, useMyFavorites, useMyReactions, useRecentSearches, useRecommendations, useReleaseDates, useSearch, useSimilar, useTypeahead, useViewSignal, type ExposureOptions, type MyInteraction, type ReleaseDate, type UseContentFilters, type UseExposure, type UseHistory, type UseRail, type UseRecentSearches, type UseTypeahead, } from './discovery.js';
20
+ export { beaconsFor, useBeacons, useContentFilters, useContents, useExposure, useHistory, useLockedCount, useMyFavorites, useMyReactions, useRecentSearches, useRecommendations, useReleaseDates, useDailyReleases, type UseDailyReleases, useSearch, useSimilar, useTypeahead, useViewSignal, type ExposureOptions, type MyInteraction, type ReleaseDate, type UseContentFilters, type UseExposure, type UseHistory, type UseRail, type UseRecentSearches, type UseTypeahead, } from './discovery.js';
21
21
  export { downloadMessage, nextRelease, startDownload, useReaderPlan, useSegmentPages, useVersionDownload, type ReaderPage, type UseReaderPlan, type UseSegmentPages, type UseVersionDownload, } from './versions.js';
22
22
  export { useContentScope, usePaged, type UseList, type UsePaged } from './use-resource.js';
23
23
  export { ResourceStore, resourcesFor, type Page, type Resource } from './resources.js';
@@ -195,20 +195,20 @@ var n = {
195
195
  this.invalidate((e) => a.includes(e.type));
196
196
  break;
197
197
  case "reaction.changed":
198
- r((n) => n.type === "reaction" && t(n.target, e.target), () => e.counts), e.target.type === "contents" && o(e.target.id, (t) => ({
198
+ r((n) => n.type === "reaction" && t(n.target, e.target), () => e.counts), e.target.type === "contents" && (o(e.target.id, (t) => ({
199
199
  ...t,
200
200
  counts: {
201
201
  ...t.counts,
202
202
  likes: e.counts.likes,
203
203
  dislikes: e.counts.dislikes
204
204
  }
205
- })), this.invalidate((e) => e.type === "reactions");
205
+ })), this.invalidate((e) => e.type === "daily-releases")), this.invalidate((e) => e.type === "reactions");
206
206
  break;
207
207
  case "favorite.changed":
208
208
  r((n) => n.type === "favorite" && t(n.target, e.target), () => ({
209
209
  favorited: e.favorited,
210
210
  count: e.count
211
- })), e.target.type === "contents" && o(e.target.id, (t) => ({
211
+ })), e.target.type === "contents" && (o(e.target.id, (t) => ({
212
212
  ...t,
213
213
  counts: {
214
214
  ...t.counts,
@@ -218,20 +218,20 @@ var n = {
218
218
  ...t.viewer,
219
219
  favorited: e.favorited
220
220
  }
221
- })), this.invalidate((e) => e.type === "favorites");
221
+ })), this.invalidate((e) => e.type === "daily-releases")), this.invalidate((e) => e.type === "favorites");
222
222
  break;
223
223
  case "content.saved":
224
- r((t) => t.type === "content" && t.id === e.content.id, () => e.content), this.invalidate((t) => t.type === "contents" || t.type === "cards" || t.type === "content-detail" && t.id === e.content.id);
224
+ r((t) => t.type === "content" && t.id === e.content.id, () => e.content), this.invalidate((t) => t.type === "contents" || t.type === "cards" || t.type === "daily-releases" || t.type === "content-detail" && t.id === e.content.id);
225
225
  break;
226
226
  case "content.changed":
227
- this.invalidate((t) => (t.type === "content" || t.type === "content-detail") && t.id === e.id || t.type === "contents" || t.type === "cards");
227
+ this.invalidate((t) => (t.type === "content" || t.type === "content-detail") && t.id === e.id || t.type === "contents" || t.type === "cards" || t.type === "daily-releases");
228
228
  break;
229
229
  case "content.deleted":
230
230
  i([
231
231
  "contents",
232
232
  "cards",
233
233
  "history"
234
- ], (t) => t.id === e.id ? null : t), this.invalidate((t) => (t.type === "content" || t.type === "content-detail") && t.id === e.id || t.type === "contents" && t.scope === "deleted");
234
+ ], (t) => t.id === e.id ? null : t), this.invalidate((t) => (t.type === "content" || t.type === "content-detail") && t.id === e.id || t.type === "contents" && t.scope === "deleted" || t.type === "daily-releases");
235
235
  break;
236
236
  case "poll.created":
237
237
  this.invalidate((e) => e.type === "polls" || e.type === "poll" && !e.id);
@@ -250,16 +250,16 @@ var n = {
250
250
  this.invalidate((t) => t.type === "bans" && t.scope === e.scope || t.type === "standing");
251
251
  break;
252
252
  case "entities.changed":
253
- this.invalidate((e) => e.type.startsWith("group"));
253
+ this.invalidate((e) => e.type.startsWith("group") || e.type === "daily-releases");
254
254
  break;
255
255
  case "contentFilters.changed":
256
- this.invalidate((e) => e.type === "cards" || e.type === "history" || e.type === "release-dates");
256
+ this.invalidate((e) => e.type === "cards" || e.type === "history" || e.type === "release-dates" || e.type === "daily-releases");
257
257
  break;
258
258
  case "access.changed":
259
- this.invalidate((e) => e.type === "cards" || e.type === "history" || e.type === "content-detail" || e.type === "reader-plan" || e.type.startsWith("group"));
259
+ this.invalidate((e) => e.type === "cards" || e.type === "history" || e.type === "content-detail" || e.type === "reader-plan" || e.type.startsWith("group") || e.type === "daily-releases");
260
260
  break;
261
261
  case "history.changed":
262
- this.invalidate((e) => e.type === "history" || e.type === "cards");
262
+ this.invalidate((e) => e.type === "history" || e.type === "cards" || e.type === "daily-releases");
263
263
  break;
264
264
  case "searches.changed":
265
265
  this.invalidate((e) => e.type === "searches");
@@ -1 +1 @@
1
- {"version":3,"file":"resources.js","names":[],"sources":["../../src/react/resources.ts"],"sourcesContent":["import type { ContentKitClient } from \"../client/client.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport { sameTarget, type Target } from \"../client/content/types.js\";\nimport type { Card, Comment, Content, Item, Poll } from \"../client/generated/wire.js\";\nimport type { ContentKitChange } from \"../client/http.js\";\n\n/** One shared read: its data, whether a fetch is in flight, and its last failure. */\nexport interface Resource<T> {\n data: T | undefined;\n loading: boolean;\n /** A fetch or set has completed. */\n loaded: boolean;\n /** A list's next page is in flight. */\n loadingMore?: boolean;\n error?: ContentKitError;\n}\n\n/** A page of a list and how to get the next one (null: no more). */\nexport interface Page<T> {\n items: T[];\n next: string | number | null;\n}\n\nexport type Fetcher<T> = (signal: AbortSignal) => Promise<T>;\n\n/** What a slot holds, for matching changes: its resource type and the ids it depends on. */\nexport interface Tag {\n type: string;\n readScope?: string;\n target?: Target;\n id?: string;\n scope?: string;\n}\n\ninterface Slot {\n tag: Tag;\n listeners: Set<() => void>;\n entry: Resource<unknown>;\n fetcher?: Fetcher<unknown>;\n more?: (cursor: string | number, signal: AbortSignal) => Promise<Page<unknown>>;\n ctl?: AbortController;\n moreCtl?: AbortController;\n /** Bumped by mark(): an optimistic write rolls back only if no newer one started. */\n version: number;\n /** Identifies the full read; item patches and appended pages retain it. */\n readVersion: number;\n}\n\nconst IDLE: Resource<never> = { data: undefined, loading: false, loaded: false };\n\n/**\n * The content reads hooks share, per client: one request per key while any\n * hook shows it, optimistic writes with rollback, and every change the client\n * makes applied in place (or refetched) for every hook showing it.\n */\nexport class ResourceStore {\n private readonly slots = new Map<string, Slot>();\n // Tokens must remain unique when a scope leaves and its slots are recreated.\n private version = 0;\n\n constructor(client: ContentKitClient) {\n client.subscribe((c, scope) => this.apply(c, scope));\n }\n\n subscribe(key: string, tag: Tag, listener: () => void): () => void {\n let s = this.slots.get(key);\n if (!s) this.slots.set(key, (s = { tag, listeners: new Set(), entry: IDLE, version: 0, readVersion: ++this.version }));\n const slot = s;\n slot.listeners.add(listener);\n return () => {\n slot.listeners.delete(listener);\n // Kept across a StrictMode remount; dropped once no hook shows it.\n queueMicrotask(() => {\n if (slot.listeners.size || this.slots.get(key) !== slot) return;\n slot.ctl?.abort();\n slot.moreCtl?.abort();\n this.slots.delete(key);\n });\n };\n }\n\n snapshot<T>(key: string): Resource<T> {\n return (this.slots.get(key)?.entry ?? IDLE) as Resource<T>;\n }\n\n /** The latest fetchers of a key: its first read, and a list's next page. */\n bind(key: string, fetcher: Fetcher<unknown>, more?: Slot[\"more\"]): void {\n const s = this.slots.get(key);\n if (s) Object.assign(s, { fetcher, more });\n }\n\n /** Fetches unless loaded or in flight; force refetches (a list from its first page). */\n load(key: string, force = false): void {\n const s = this.slots.get(key);\n if (!s?.fetcher || (!force && (s.entry.loaded || s.ctl))) return;\n s.ctl?.abort();\n s.moreCtl?.abort();\n s.moreCtl = undefined;\n const ctl = (s.ctl = new AbortController());\n this.update(s, { loading: true, loadingMore: false, error: undefined });\n s.fetcher(ctl.signal).then(\n (data) => {\n if (s.ctl !== ctl) return;\n s.ctl = undefined;\n s.readVersion = ++this.version;\n this.update(s, { data, loading: false, loaded: true, error: undefined });\n },\n (e) => {\n if (s.ctl !== ctl) return;\n s.ctl = undefined;\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") this.update(s, { loading: false, loaded: true, error });\n },\n );\n }\n\n /** Appends a list's next page; resolves once it landed. */\n async loadMore(key: string): Promise<void> {\n const s = this.slots.get(key);\n const page = s?.entry.data as Page<{ id: string }> | undefined;\n if (!s?.more || !page || page.next === null || s.moreCtl || s.ctl) return;\n const ctl = (s.moreCtl = new AbortController());\n this.update(s, { loadingMore: true });\n try {\n const next = (await s.more(page.next, ctl.signal)) as Page<{ id: string }>;\n if (s.moreCtl !== ctl) return;\n const cur = s.entry.data as Page<{ id: string }>;\n const seen = new Set(cur.items.map((x) => x.id));\n this.update(s, { data: { items: [...cur.items, ...next.items.filter((x) => !seen.has(x.id))], next: next.next }, error: undefined });\n } catch (e) {\n const error = toContentKitError(e);\n if (s.moreCtl === ctl && error.code !== \"aborted\") this.update(s, { error });\n } finally {\n if (s.moreCtl === ctl) {\n s.moreCtl = undefined;\n this.update(s, { loadingMore: false });\n }\n }\n }\n\n /** Replaces a key's data for every hook showing it. */\n set<T>(key: string, data: T | ((prev: T | undefined) => T)): void {\n const s = this.slots.get(key);\n if (!s) return;\n const next = typeof data === \"function\" ? (data as (p: T | undefined) => T)(s.entry.data as T | undefined) : data;\n s.readVersion = ++this.version;\n this.update(s, { data: next, loaded: true, error: undefined });\n }\n\n /** Starts an optimistic write on key: the token rollback() checks. */\n mark(key: string): number {\n const s = this.slots.get(key);\n return s ? (s.version = ++this.version) : 0;\n }\n\n /** Restores data unless a newer optimistic write started since mark(). */\n rollback<T>(key: string, token: number, data: T): void {\n const s = this.slots.get(key);\n if (s && s.version === token) this.update(s, { data, loaded: true });\n }\n\n /** Applies fn to matching slots, with the read identity for scoped rollback. */\n patch<T>(match: (tag: Tag) => boolean, fn: (data: T, readVersion: number) => T): void {\n for (const s of this.slots.values()) {\n if (s.entry.data !== undefined && match(s.tag)) this.update(s, { data: fn(s.entry.data as T, s.readVersion) });\n }\n }\n\n /** Refetches every shown slot whose tag matches. */\n invalidate(match: (tag: Tag) => boolean): void {\n for (const [key, s] of this.slots) if (match(s.tag) && s.listeners.size) this.load(key, true);\n }\n\n private apply(c: ContentKitChange, scope: string | null): void {\n const patch = <T>(match: (tag: Tag) => boolean, fn: (data: T) => T) => {\n this.patch<T>((t) => match(t) && (t.readScope ?? \"{}\") === scope, fn);\n this.invalidate((t) => match(t) && (t.readScope ?? \"{}\") !== scope);\n };\n const items = <T extends { id: string }>(types: string[], fn: (item: T) => T | null) =>\n patch<Page<T>>(\n (t) => types.includes(t.type),\n (page) => {\n let changed = false;\n const out: T[] = [];\n for (const it of page.items) {\n const next = fn(it);\n if (next !== it) changed = true;\n if (next) out.push(next);\n }\n return changed ? { ...page, items: out } : page;\n },\n );\n const comments = [\"comments\", \"replies\", \"latest\", \"admin-comments\"];\n // Cards in lists (pages) and rails (arrays) show a content's counts and the viewer's state.\n const cards = (id: string, fn: (card: Card) => Card) =>\n patch<Page<Card> | Card[]>(\n (t) => t.type === \"cards\" || t.type === \"history\",\n (data) => {\n const each = (list: Card[]) => (list.some((x) => x.id === id) ? list.map((x) => (x.id === id ? fn(x) : x)) : list);\n if (Array.isArray(data)) return each(data);\n const items = each(data.items);\n return items === data.items ? data : { ...data, items };\n },\n );\n switch (c.type) {\n case \"notifications.updated\":\n this.updateNotification(c.item, scope);\n break;\n case \"notifications.changed\":\n this.invalidate((t) => t.type === \"notifications\");\n break;\n case \"comment.created\": {\n const parent = c.comment.reply_to_id;\n const published = !c.comment.moderation;\n const add = (t: Tag) => (parent ? t.type === \"replies\" && t.id === parent : t.type === \"comments\" && sameTarget(t.target, c.target));\n patch<Page<Comment>>(add, (p) => (p.items.some((x) => x.id === c.comment.id) ? p : { ...p, items: parent ? [...p.items, c.comment] : [c.comment, ...p.items] }));\n if (parent && published) items<Comment>([\"comments\"], (x) => (x.id === parent ? { ...x, reply_count: x.reply_count + 1 } : x));\n this.invalidate((t) => t.type === \"latest\" || t.type === \"admin-comments\");\n break;\n }\n case \"comment.updated\":\n items<Comment>(comments, (x) => (x.id === c.comment.id ? { ...x, ...c.comment, author: c.comment.author ?? x.author } : x));\n break;\n case \"comment.reacted\":\n items<Comment>(comments, (x) => (x.id === c.id ? { ...x, ...c.counts } : x));\n break;\n case \"comment.deleted\": {\n let parent: string | undefined;\n items<Comment>([\"comments\", \"replies\"], (x) => {\n if (x.id !== c.id || x.deleted) return x;\n if (!x.moderation) parent = x.reply_to_id;\n return { ...x, deleted: true, body: \"[deleted]\", author: undefined, user_id: undefined, anon_name: undefined };\n });\n if (parent) items<Comment>([\"comments\"], (x) => (x.id === parent ? { ...x, reply_count: Math.max(0, x.reply_count - 1) } : x));\n items<Comment>([\"latest\"], (x) => (x.id === c.id ? null : x));\n items<Comment & { deleted_at?: string }>([\"admin-comments\"], (x) => (x.id === c.id ? { ...x, deleted: true, deleted_at: new Date().toISOString() } : x));\n break;\n }\n case \"comment.restored\":\n this.invalidate((t) => comments.includes(t.type));\n break;\n case \"reaction.changed\":\n patch((t) => t.type === \"reaction\" && sameTarget(t.target, c.target), () => c.counts);\n if (c.target.type === \"contents\") cards(c.target.id, (x) => ({ ...x, counts: { ...x.counts, likes: c.counts.likes, dislikes: c.counts.dislikes } }));\n this.invalidate((t) => t.type === \"reactions\");\n break;\n case \"favorite.changed\":\n patch((t) => t.type === \"favorite\" && sameTarget(t.target, c.target), () => ({ favorited: c.favorited, count: c.count }));\n if (c.target.type === \"contents\")\n cards(c.target.id, (x) => ({ ...x, counts: { ...x.counts, favorites: c.count }, viewer: x.viewer && { ...x.viewer, favorited: c.favorited } }));\n this.invalidate((t) => t.type === \"favorites\");\n break;\n case \"content.saved\":\n patch<Content | null>((t) => t.type === \"content\" && t.id === c.content.id, () => c.content);\n // A state, kind or text change can move it between lists: refetch them.\n this.invalidate((t) => t.type === \"contents\" || t.type === \"cards\" || (t.type === \"content-detail\" && t.id === c.content.id));\n break;\n case \"content.changed\":\n this.invalidate((t) => ((t.type === \"content\" || t.type === \"content-detail\") && t.id === c.id) || t.type === \"contents\" || t.type === \"cards\");\n break;\n case \"content.deleted\":\n items<{ id: string }>([\"contents\", \"cards\", \"history\"], (x) => (x.id === c.id ? null : x));\n this.invalidate((t) => ((t.type === \"content\" || t.type === \"content-detail\") && t.id === c.id) || (t.type === \"contents\" && t.scope === \"deleted\"));\n break;\n case \"poll.created\":\n this.invalidate((t) => t.type === \"polls\" || (t.type === \"poll\" && !t.id));\n break;\n case \"poll.updated\":\n // A latest-poll slot has no id in its tag: match by the poll it holds.\n patch<Poll | null>((t) => t.type === \"poll\", (p) => (p?.id === c.poll.id ? c.poll : p));\n items<Poll>([\"polls\"], (x) => (x.id === c.poll.id ? c.poll : x));\n break;\n case \"poll.changed\":\n this.invalidate((t) => (t.type === \"poll\" && (t.id === c.id || !t.id)) || t.type === \"polls\");\n break;\n case \"poll.deleted\":\n items<Poll>([\"polls\"], (x) => (x.id === c.id ? null : x));\n this.invalidate((t) => t.type === \"poll\" && !t.id);\n break;\n case \"ban.saved\":\n case \"ban.lifted\":\n this.invalidate((t) => (t.type === \"bans\" && t.scope === c.scope) || t.type === \"standing\");\n break;\n case \"entities.changed\":\n this.invalidate((t) => t.type.startsWith(\"group\"));\n break;\n case \"contentFilters.changed\":\n this.invalidate((t) => t.type === \"cards\" || t.type === \"history\" || t.type === \"release-dates\");\n break;\n case \"access.changed\":\n this.invalidate((t) => t.type === \"cards\" || t.type === \"history\" || t.type === \"content-detail\" || t.type === \"reader-plan\" || t.type.startsWith(\"group\"));\n break;\n case \"history.changed\":\n this.invalidate((t) => t.type === \"history\" || t.type === \"cards\");\n break;\n case \"searches.changed\":\n this.invalidate((t) => t.type === \"searches\");\n break;\n case \"rules.changed\":\n this.invalidate((t) => t.type === \"moderation-rules\" && t.scope === c.rules);\n break;\n case \"reader.changed\":\n this.invalidate((t) => t.type === \"reader-plan\" && t.id === c.version);\n break;\n case \"moderation.resolved\":\n items<{ id: string }>([\"held\"], (x) => (x.id === c.id ? null : x));\n if (c.kind === \"comment\") this.invalidate((t) => comments.includes(t.type));\n else this.invalidate((t) => (t.type === \"content\" && t.id === c.id) || t.type === \"contents\");\n break;\n }\n }\n\n // Preserve loaded pages and canonical receipt revisions. Reads that started\n // before a successful mutation cannot overwrite it when they finish later.\n private updateNotification(item: Item, scope: string | null): void {\n for (const [key, slot] of this.slots) {\n if (slot.tag.type !== \"notifications\" || !slot.listeners.size) continue;\n const page = slot.entry.data as Page<Item> | undefined;\n const cached = page?.items.find((n) => n.id === item.id);\n // Mutations from separate mounted views can complete out of order.\n // In particular, an old active receipt must not evict a newer archive.\n if ((slot.tag.readScope ?? \"{}\") === scope && cached && cached.revision > item.revision) continue;\n const archived = slot.tag.scope?.startsWith(\"archived:\") ?? false;\n const matches = archived === !!item.dismissed_at;\n if ((slot.tag.readScope ?? \"{}\") !== scope || !page || slot.tag.scope?.endsWith(\":unread\") || (matches && !page.items.some((n) => n.id === item.id))) {\n this.load(key, true);\n continue;\n }\n if (!matches && !page.items.some((n) => n.id === item.id)) continue;\n slot.ctl?.abort();\n slot.moreCtl?.abort();\n slot.ctl = slot.moreCtl = undefined;\n this.update(slot, { loading: false, loadingMore: false, data: { ...page, items: page.items.flatMap((n) => n.id === item.id ? matches ? [item] : [] : [n]) } });\n }\n }\n\n // A new entry per change: useSyncExternalStore compares snapshots by identity.\n private update(s: Slot, patch: Partial<Resource<unknown>>): void {\n s.entry = { ...s.entry, ...patch };\n for (const l of s.listeners) l();\n }\n}\n\nconst stores = new WeakMap<ContentKitClient, ResourceStore>();\n\n/** The client's shared content store. */\nexport function resourcesFor(client: ContentKitClient): ResourceStore {\n let s = stores.get(client);\n if (!s) stores.set(client, (s = new ResourceStore(client)));\n return s;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resources.js","names":[],"sources":["../../src/react/resources.ts"],"sourcesContent":["import type { ContentKitClient } from \"../client/client.js\";\nimport { toContentKitError, type ContentKitError } from \"../client/errors.js\";\nimport { sameTarget, type Target } from \"../client/content/types.js\";\nimport type { Card, Comment, Content, Item, Poll } from \"../client/generated/wire.js\";\nimport type { ContentKitChange } from \"../client/http.js\";\n\n/** One shared read: its data, whether a fetch is in flight, and its last failure. */\nexport interface Resource<T> {\n data: T | undefined;\n loading: boolean;\n /** A fetch or set has completed. */\n loaded: boolean;\n /** A list's next page is in flight. */\n loadingMore?: boolean;\n error?: ContentKitError;\n}\n\n/** A page of a list and how to get the next one (null: no more). */\nexport interface Page<T> {\n items: T[];\n next: string | number | null;\n}\n\nexport type Fetcher<T> = (signal: AbortSignal) => Promise<T>;\n\n/** What a slot holds, for matching changes: its resource type and the ids it depends on. */\nexport interface Tag {\n type: string;\n readScope?: string;\n target?: Target;\n id?: string;\n scope?: string;\n}\n\ninterface Slot {\n tag: Tag;\n listeners: Set<() => void>;\n entry: Resource<unknown>;\n fetcher?: Fetcher<unknown>;\n more?: (cursor: string | number, signal: AbortSignal) => Promise<Page<unknown>>;\n ctl?: AbortController;\n moreCtl?: AbortController;\n /** Bumped by mark(): an optimistic write rolls back only if no newer one started. */\n version: number;\n /** Identifies the full read; item patches and appended pages retain it. */\n readVersion: number;\n}\n\nconst IDLE: Resource<never> = { data: undefined, loading: false, loaded: false };\n\n/**\n * The content reads hooks share, per client: one request per key while any\n * hook shows it, optimistic writes with rollback, and every change the client\n * makes applied in place (or refetched) for every hook showing it.\n */\nexport class ResourceStore {\n private readonly slots = new Map<string, Slot>();\n // Tokens must remain unique when a scope leaves and its slots are recreated.\n private version = 0;\n\n constructor(client: ContentKitClient) {\n client.subscribe((c, scope) => this.apply(c, scope));\n }\n\n subscribe(key: string, tag: Tag, listener: () => void): () => void {\n let s = this.slots.get(key);\n if (!s) this.slots.set(key, (s = { tag, listeners: new Set(), entry: IDLE, version: 0, readVersion: ++this.version }));\n const slot = s;\n slot.listeners.add(listener);\n return () => {\n slot.listeners.delete(listener);\n // Kept across a StrictMode remount; dropped once no hook shows it.\n queueMicrotask(() => {\n if (slot.listeners.size || this.slots.get(key) !== slot) return;\n slot.ctl?.abort();\n slot.moreCtl?.abort();\n this.slots.delete(key);\n });\n };\n }\n\n snapshot<T>(key: string): Resource<T> {\n return (this.slots.get(key)?.entry ?? IDLE) as Resource<T>;\n }\n\n /** The latest fetchers of a key: its first read, and a list's next page. */\n bind(key: string, fetcher: Fetcher<unknown>, more?: Slot[\"more\"]): void {\n const s = this.slots.get(key);\n if (s) Object.assign(s, { fetcher, more });\n }\n\n /** Fetches unless loaded or in flight; force refetches (a list from its first page). */\n load(key: string, force = false): void {\n const s = this.slots.get(key);\n if (!s?.fetcher || (!force && (s.entry.loaded || s.ctl))) return;\n s.ctl?.abort();\n s.moreCtl?.abort();\n s.moreCtl = undefined;\n const ctl = (s.ctl = new AbortController());\n this.update(s, { loading: true, loadingMore: false, error: undefined });\n s.fetcher(ctl.signal).then(\n (data) => {\n if (s.ctl !== ctl) return;\n s.ctl = undefined;\n s.readVersion = ++this.version;\n this.update(s, { data, loading: false, loaded: true, error: undefined });\n },\n (e) => {\n if (s.ctl !== ctl) return;\n s.ctl = undefined;\n const error = toContentKitError(e);\n if (error.code !== \"aborted\") this.update(s, { loading: false, loaded: true, error });\n },\n );\n }\n\n /** Appends a list's next page; resolves once it landed. */\n async loadMore(key: string): Promise<void> {\n const s = this.slots.get(key);\n const page = s?.entry.data as Page<{ id: string }> | undefined;\n if (!s?.more || !page || page.next === null || s.moreCtl || s.ctl) return;\n const ctl = (s.moreCtl = new AbortController());\n this.update(s, { loadingMore: true });\n try {\n const next = (await s.more(page.next, ctl.signal)) as Page<{ id: string }>;\n if (s.moreCtl !== ctl) return;\n const cur = s.entry.data as Page<{ id: string }>;\n const seen = new Set(cur.items.map((x) => x.id));\n this.update(s, { data: { items: [...cur.items, ...next.items.filter((x) => !seen.has(x.id))], next: next.next }, error: undefined });\n } catch (e) {\n const error = toContentKitError(e);\n if (s.moreCtl === ctl && error.code !== \"aborted\") this.update(s, { error });\n } finally {\n if (s.moreCtl === ctl) {\n s.moreCtl = undefined;\n this.update(s, { loadingMore: false });\n }\n }\n }\n\n /** Replaces a key's data for every hook showing it. */\n set<T>(key: string, data: T | ((prev: T | undefined) => T)): void {\n const s = this.slots.get(key);\n if (!s) return;\n const next = typeof data === \"function\" ? (data as (p: T | undefined) => T)(s.entry.data as T | undefined) : data;\n s.readVersion = ++this.version;\n this.update(s, { data: next, loaded: true, error: undefined });\n }\n\n /** Starts an optimistic write on key: the token rollback() checks. */\n mark(key: string): number {\n const s = this.slots.get(key);\n return s ? (s.version = ++this.version) : 0;\n }\n\n /** Restores data unless a newer optimistic write started since mark(). */\n rollback<T>(key: string, token: number, data: T): void {\n const s = this.slots.get(key);\n if (s && s.version === token) this.update(s, { data, loaded: true });\n }\n\n /** Applies fn to matching slots, with the read identity for scoped rollback. */\n patch<T>(match: (tag: Tag) => boolean, fn: (data: T, readVersion: number) => T): void {\n for (const s of this.slots.values()) {\n if (s.entry.data !== undefined && match(s.tag)) this.update(s, { data: fn(s.entry.data as T, s.readVersion) });\n }\n }\n\n /** Refetches every shown slot whose tag matches. */\n invalidate(match: (tag: Tag) => boolean): void {\n for (const [key, s] of this.slots) if (match(s.tag) && s.listeners.size) this.load(key, true);\n }\n\n private apply(c: ContentKitChange, scope: string | null): void {\n const patch = <T>(match: (tag: Tag) => boolean, fn: (data: T) => T) => {\n this.patch<T>((t) => match(t) && (t.readScope ?? \"{}\") === scope, fn);\n this.invalidate((t) => match(t) && (t.readScope ?? \"{}\") !== scope);\n };\n const items = <T extends { id: string }>(types: string[], fn: (item: T) => T | null) =>\n patch<Page<T>>(\n (t) => types.includes(t.type),\n (page) => {\n let changed = false;\n const out: T[] = [];\n for (const it of page.items) {\n const next = fn(it);\n if (next !== it) changed = true;\n if (next) out.push(next);\n }\n return changed ? { ...page, items: out } : page;\n },\n );\n const comments = [\"comments\", \"replies\", \"latest\", \"admin-comments\"];\n // Cards in lists (pages) and rails (arrays) show a content's counts and the viewer's state.\n const cards = (id: string, fn: (card: Card) => Card) =>\n patch<Page<Card> | Card[]>(\n (t) => t.type === \"cards\" || t.type === \"history\",\n (data) => {\n const each = (list: Card[]) => (list.some((x) => x.id === id) ? list.map((x) => (x.id === id ? fn(x) : x)) : list);\n if (Array.isArray(data)) return each(data);\n const items = each(data.items);\n return items === data.items ? data : { ...data, items };\n },\n );\n switch (c.type) {\n case \"notifications.updated\":\n this.updateNotification(c.item, scope);\n break;\n case \"notifications.changed\":\n this.invalidate((t) => t.type === \"notifications\");\n break;\n case \"comment.created\": {\n const parent = c.comment.reply_to_id;\n const published = !c.comment.moderation;\n const add = (t: Tag) => (parent ? t.type === \"replies\" && t.id === parent : t.type === \"comments\" && sameTarget(t.target, c.target));\n patch<Page<Comment>>(add, (p) => (p.items.some((x) => x.id === c.comment.id) ? p : { ...p, items: parent ? [...p.items, c.comment] : [c.comment, ...p.items] }));\n if (parent && published) items<Comment>([\"comments\"], (x) => (x.id === parent ? { ...x, reply_count: x.reply_count + 1 } : x));\n this.invalidate((t) => t.type === \"latest\" || t.type === \"admin-comments\");\n break;\n }\n case \"comment.updated\":\n items<Comment>(comments, (x) => (x.id === c.comment.id ? { ...x, ...c.comment, author: c.comment.author ?? x.author } : x));\n break;\n case \"comment.reacted\":\n items<Comment>(comments, (x) => (x.id === c.id ? { ...x, ...c.counts } : x));\n break;\n case \"comment.deleted\": {\n let parent: string | undefined;\n items<Comment>([\"comments\", \"replies\"], (x) => {\n if (x.id !== c.id || x.deleted) return x;\n if (!x.moderation) parent = x.reply_to_id;\n return { ...x, deleted: true, body: \"[deleted]\", author: undefined, user_id: undefined, anon_name: undefined };\n });\n if (parent) items<Comment>([\"comments\"], (x) => (x.id === parent ? { ...x, reply_count: Math.max(0, x.reply_count - 1) } : x));\n items<Comment>([\"latest\"], (x) => (x.id === c.id ? null : x));\n items<Comment & { deleted_at?: string }>([\"admin-comments\"], (x) => (x.id === c.id ? { ...x, deleted: true, deleted_at: new Date().toISOString() } : x));\n break;\n }\n case \"comment.restored\":\n this.invalidate((t) => comments.includes(t.type));\n break;\n case \"reaction.changed\":\n patch((t) => t.type === \"reaction\" && sameTarget(t.target, c.target), () => c.counts);\n if (c.target.type === \"contents\") {\n cards(c.target.id, (x) => ({ ...x, counts: { ...x.counts, likes: c.counts.likes, dislikes: c.counts.dislikes } }));\n this.invalidate((t) => t.type === \"daily-releases\");\n }\n this.invalidate((t) => t.type === \"reactions\");\n break;\n case \"favorite.changed\":\n patch((t) => t.type === \"favorite\" && sameTarget(t.target, c.target), () => ({ favorited: c.favorited, count: c.count }));\n if (c.target.type === \"contents\") {\n cards(c.target.id, (x) => ({ ...x, counts: { ...x.counts, favorites: c.count }, viewer: x.viewer && { ...x.viewer, favorited: c.favorited } }));\n this.invalidate((t) => t.type === \"daily-releases\");\n }\n this.invalidate((t) => t.type === \"favorites\");\n break;\n case \"content.saved\":\n patch<Content | null>((t) => t.type === \"content\" && t.id === c.content.id, () => c.content);\n // A state, kind or text change can move it between lists: refetch them.\n this.invalidate((t) => t.type === \"contents\" || t.type === \"cards\" || t.type === \"daily-releases\" || (t.type === \"content-detail\" && t.id === c.content.id));\n break;\n case \"content.changed\":\n this.invalidate((t) => ((t.type === \"content\" || t.type === \"content-detail\") && t.id === c.id) || t.type === \"contents\" || t.type === \"cards\" || t.type === \"daily-releases\");\n break;\n case \"content.deleted\":\n items<{ id: string }>([\"contents\", \"cards\", \"history\"], (x) => (x.id === c.id ? null : x));\n this.invalidate((t) => ((t.type === \"content\" || t.type === \"content-detail\") && t.id === c.id) || (t.type === \"contents\" && t.scope === \"deleted\") || t.type === \"daily-releases\");\n break;\n case \"poll.created\":\n this.invalidate((t) => t.type === \"polls\" || (t.type === \"poll\" && !t.id));\n break;\n case \"poll.updated\":\n // A latest-poll slot has no id in its tag: match by the poll it holds.\n patch<Poll | null>((t) => t.type === \"poll\", (p) => (p?.id === c.poll.id ? c.poll : p));\n items<Poll>([\"polls\"], (x) => (x.id === c.poll.id ? c.poll : x));\n break;\n case \"poll.changed\":\n this.invalidate((t) => (t.type === \"poll\" && (t.id === c.id || !t.id)) || t.type === \"polls\");\n break;\n case \"poll.deleted\":\n items<Poll>([\"polls\"], (x) => (x.id === c.id ? null : x));\n this.invalidate((t) => t.type === \"poll\" && !t.id);\n break;\n case \"ban.saved\":\n case \"ban.lifted\":\n this.invalidate((t) => (t.type === \"bans\" && t.scope === c.scope) || t.type === \"standing\");\n break;\n case \"entities.changed\":\n this.invalidate((t) => t.type.startsWith(\"group\") || t.type === \"daily-releases\");\n break;\n case \"contentFilters.changed\":\n this.invalidate((t) => t.type === \"cards\" || t.type === \"history\" || t.type === \"release-dates\" || t.type === \"daily-releases\");\n break;\n case \"access.changed\":\n this.invalidate((t) => t.type === \"cards\" || t.type === \"history\" || t.type === \"content-detail\" || t.type === \"reader-plan\" || t.type.startsWith(\"group\") || t.type === \"daily-releases\");\n break;\n case \"history.changed\":\n this.invalidate((t) => t.type === \"history\" || t.type === \"cards\" || t.type === \"daily-releases\");\n break;\n case \"searches.changed\":\n this.invalidate((t) => t.type === \"searches\");\n break;\n case \"rules.changed\":\n this.invalidate((t) => t.type === \"moderation-rules\" && t.scope === c.rules);\n break;\n case \"reader.changed\":\n this.invalidate((t) => t.type === \"reader-plan\" && t.id === c.version);\n break;\n case \"moderation.resolved\":\n items<{ id: string }>([\"held\"], (x) => (x.id === c.id ? null : x));\n if (c.kind === \"comment\") this.invalidate((t) => comments.includes(t.type));\n else this.invalidate((t) => (t.type === \"content\" && t.id === c.id) || t.type === \"contents\");\n break;\n }\n }\n\n // Preserve loaded pages and canonical receipt revisions. Reads that started\n // before a successful mutation cannot overwrite it when they finish later.\n private updateNotification(item: Item, scope: string | null): void {\n for (const [key, slot] of this.slots) {\n if (slot.tag.type !== \"notifications\" || !slot.listeners.size) continue;\n const page = slot.entry.data as Page<Item> | undefined;\n const cached = page?.items.find((n) => n.id === item.id);\n // Mutations from separate mounted views can complete out of order.\n // In particular, an old active receipt must not evict a newer archive.\n if ((slot.tag.readScope ?? \"{}\") === scope && cached && cached.revision > item.revision) continue;\n const archived = slot.tag.scope?.startsWith(\"archived:\") ?? false;\n const matches = archived === !!item.dismissed_at;\n if ((slot.tag.readScope ?? \"{}\") !== scope || !page || slot.tag.scope?.endsWith(\":unread\") || (matches && !page.items.some((n) => n.id === item.id))) {\n this.load(key, true);\n continue;\n }\n if (!matches && !page.items.some((n) => n.id === item.id)) continue;\n slot.ctl?.abort();\n slot.moreCtl?.abort();\n slot.ctl = slot.moreCtl = undefined;\n this.update(slot, { loading: false, loadingMore: false, data: { ...page, items: page.items.flatMap((n) => n.id === item.id ? matches ? [item] : [] : [n]) } });\n }\n }\n\n // A new entry per change: useSyncExternalStore compares snapshots by identity.\n private update(s: Slot, patch: Partial<Resource<unknown>>): void {\n s.entry = { ...s.entry, ...patch };\n for (const l of s.listeners) l();\n }\n}\n\nconst stores = new WeakMap<ContentKitClient, ResourceStore>();\n\n/** The client's shared content store. */\nexport function resourcesFor(client: ContentKitClient): ResourceStore {\n let s = stores.get(client);\n if (!s) stores.set(client, (s = new ResourceStore(client)));\n return s;\n}\n"],"mappings":"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"}
package/dist/react.js CHANGED
@@ -18,13 +18,13 @@ import { useFavorite as se, useReaction as ce } from "./react/engagement.js";
18
18
  import { usePoll as le, usePollEditor as ue, usePolls as de, withVote as fe } from "./react/polls.js";
19
19
  import { useVersionParam as pe } from "./react/location.js";
20
20
  import { useAdminLocation as me, useFlowClient as he, useStaffAccess as ge } from "./react/admin.js";
21
- import { beaconsFor as _e, useBeacons as ve, useContentFilters as ye, useContents as be, useExposure as xe, useHistory as Se, useLockedCount as Ce, useMyFavorites as we, useMyReactions as Te, useRecentSearches as Ee, useRecommendations as De, useReleaseDates as Oe, useSearch as ke, useSimilar as Ae, useTypeahead as je, useViewSignal as Me } from "./react/discovery.js";
22
- import { defaultVersion as Ne, editionOf as Pe, findVersion as Fe, liveVersions as Ie, useContentDetail as Le } from "./react/detail.js";
23
- import { downloadMessage as Re, nextRelease as ze, startDownload as Be, useReaderPlan as Ve, useSegmentPages as He, useVersionDownload as Ue } from "./react/versions.js";
24
- import { useActivity as We, useMyStats as Ge, useTopContents as Ke } from "./react/stats.js";
25
- import { useContent as qe, useManagedContents as Je } from "./react/contents.js";
26
- import { useNotificationUnread as Ye, useNotifications as Xe } from "./react/notifications.js";
27
- import { ContentKitProvider as Ze } from "./react/provider.js";
28
- import { useReaderPreferences as Qe } from "./react/reader-preferences.js";
29
- import { useCanonicalContent as $e } from "./react/canonical.js";
30
- export { Ze as ContentKitProvider, R as GALLERY_VIEW_KEY, i as GuardContext, e as HOVER_DELAY, t as InlinePreviewContext, z as PLAYER_QUALITY_KEY, h as ResourceStore, _e as beaconsFor, Ne as defaultVersion, Re as downloadMessage, A as editOutput, Pe as editionOf, Fe as findVersion, Ie as liveVersions, y as memberId, G as nameIn, ze as nextRelease, g as resourcesFor, N as round3, Be as startDownload, K as thumbnailOf, We as useActivity, Y as useAdminComments, me as useAdminLocation, D as useAvatar, X as useBannedWords, ve as useBeacons, Z as useCanComment, $e as useCanonicalContent, B as useCarousel, Q as useCommentBans, $ as useCommentReplies, ee as useComments, qe as useContent, oe as useContentConfig, Le as useContentDetail, ye as useContentFilters, b as useContentGroups, a as useContentKit, o as useContentKitClient, _ as useContentScope, s as useContentURLs, be as useContents, d as useCrop, W as useEditorCrop, f as useEncodeProgress, c as useErrorReporter, xe as useExposure, se as useFavorite, he as useFlowClient, P as useFrameStrip, V as useGalleryView, te as useGlobalCommentBan, x as useGroup, S as useGroupMembers, C as useGroups, l as useGuarded, Se as useHistory, H as useHlsPlayer, ne as useIPBans, n as useInlinePreview, w as useKinds, re as useLatestComments, Ce as useLockedCount, Je as useManagedContents, q as useMediaFolder, E as useMediaRead, ie as useModerationQueue, we as useMyFavorites, T as useMyGroups, Te as useMyReactions, Ge as useMyStats, J as useNearViewport, Ye as useNotificationUnread, Xe as useNotifications, u as useOptionalContentKitClient, v as usePaged, le as usePoll, ue as usePollEditor, de as usePolls, O as usePresets, k as usePublicImage, ce as useReaction, Ve as useReaderPlan, Qe as useReaderPreferences, Ee as useRecentSearches, De as useRecommendations, r as useReducedMotion, U as useRefreshBeforeExpiry, Oe as useReleaseDates, ke as useSearch, He as useSegmentPages, Ae as useSimilar, j as useSlotCrop, M as useSlotImage, ge as useStaffAccess, Ke as useTopContents, je as useTypeahead, p as useUpload, m as useUploadQueue, Ue as useVersionDownload, pe as useVersionParam, F as useVideoFrame, I as useVideoImages, L as useVideoPoster, Me as useViewSignal, ae as withReaction, fe as withVote };
21
+ import { beaconsFor as _e, useBeacons as ve, useContentFilters as ye, useContents as be, useDailyReleases as xe, useExposure as Se, useHistory as Ce, useLockedCount as we, useMyFavorites as Te, useMyReactions as Ee, useRecentSearches as De, useRecommendations as Oe, useReleaseDates as ke, useSearch as Ae, useSimilar as je, useTypeahead as Me, useViewSignal as Ne } from "./react/discovery.js";
22
+ import { defaultVersion as Pe, editionOf as Fe, findVersion as Ie, liveVersions as Le, useContentDetail as Re } from "./react/detail.js";
23
+ import { downloadMessage as ze, nextRelease as Be, startDownload as Ve, useReaderPlan as He, useSegmentPages as Ue, useVersionDownload as We } from "./react/versions.js";
24
+ import { useActivity as Ge, useMyStats as Ke, useTopContents as qe } from "./react/stats.js";
25
+ import { useContent as Je, useManagedContents as Ye } from "./react/contents.js";
26
+ import { useNotificationUnread as Xe, useNotifications as Ze } from "./react/notifications.js";
27
+ import { ContentKitProvider as Qe } from "./react/provider.js";
28
+ import { useReaderPreferences as $e } from "./react/reader-preferences.js";
29
+ import { useCanonicalContent as et } from "./react/canonical.js";
30
+ export { Qe as ContentKitProvider, R as GALLERY_VIEW_KEY, i as GuardContext, e as HOVER_DELAY, t as InlinePreviewContext, z as PLAYER_QUALITY_KEY, h as ResourceStore, _e as beaconsFor, Pe as defaultVersion, ze as downloadMessage, A as editOutput, Fe as editionOf, Ie as findVersion, Le as liveVersions, y as memberId, G as nameIn, Be as nextRelease, g as resourcesFor, N as round3, Ve as startDownload, K as thumbnailOf, Ge as useActivity, Y as useAdminComments, me as useAdminLocation, D as useAvatar, X as useBannedWords, ve as useBeacons, Z as useCanComment, et as useCanonicalContent, B as useCarousel, Q as useCommentBans, $ as useCommentReplies, ee as useComments, Je as useContent, oe as useContentConfig, Re as useContentDetail, ye as useContentFilters, b as useContentGroups, a as useContentKit, o as useContentKitClient, _ as useContentScope, s as useContentURLs, be as useContents, d as useCrop, xe as useDailyReleases, W as useEditorCrop, f as useEncodeProgress, c as useErrorReporter, Se as useExposure, se as useFavorite, he as useFlowClient, P as useFrameStrip, V as useGalleryView, te as useGlobalCommentBan, x as useGroup, S as useGroupMembers, C as useGroups, l as useGuarded, Ce as useHistory, H as useHlsPlayer, ne as useIPBans, n as useInlinePreview, w as useKinds, re as useLatestComments, we as useLockedCount, Ye as useManagedContents, q as useMediaFolder, E as useMediaRead, ie as useModerationQueue, Te as useMyFavorites, T as useMyGroups, Ee as useMyReactions, Ke as useMyStats, J as useNearViewport, Xe as useNotificationUnread, Ze as useNotifications, u as useOptionalContentKitClient, v as usePaged, le as usePoll, ue as usePollEditor, de as usePolls, O as usePresets, k as usePublicImage, ce as useReaction, He as useReaderPlan, $e as useReaderPreferences, De as useRecentSearches, Oe as useRecommendations, r as useReducedMotion, U as useRefreshBeforeExpiry, ke as useReleaseDates, Ae as useSearch, Ue as useSegmentPages, je as useSimilar, j as useSlotCrop, M as useSlotImage, ge as useStaffAccess, qe as useTopContents, Me as useTypeahead, p as useUpload, m as useUploadQueue, We as useVersionDownload, pe as useVersionParam, F as useVideoFrame, I as useVideoImages, L as useVideoPoster, Ne as useViewSignal, ae as withReaction, fe as withVote };