@openrails/contentkit-ui 0.83.0 → 0.85.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +11 -3
  2. package/dist/client/beacons.d.ts +8 -5
  3. package/dist/client/beacons.js +15 -7
  4. package/dist/client/beacons.js.map +1 -1
  5. package/dist/client/content/moderation.d.ts +14 -2
  6. package/dist/client/content/moderation.js +34 -0
  7. package/dist/client/content/moderation.js.map +1 -1
  8. package/dist/client/content/types.d.ts +13 -0
  9. package/dist/client/content/types.js.map +1 -1
  10. package/dist/client/discovery.d.ts +6 -0
  11. package/dist/client/discovery.js.map +1 -1
  12. package/dist/client/generated/error-codes.d.ts +1 -1
  13. package/dist/client/generated/error-codes.js +8 -0
  14. package/dist/client/generated/error-codes.js.map +1 -1
  15. package/dist/client/generated/routes.d.ts +77 -12
  16. package/dist/client/generated/routes.js +106 -1
  17. package/dist/client/generated/routes.js.map +1 -1
  18. package/dist/client/generated/wire.d.ts +52 -0
  19. package/dist/client/generated/wire.js.map +1 -1
  20. package/dist/client/index.d.ts +2 -1
  21. package/dist/client/reader-meta.d.ts +27 -0
  22. package/dist/client/reader-meta.js +99 -0
  23. package/dist/client/reader-meta.js.map +1 -0
  24. package/dist/client/versions.d.ts +1 -1
  25. package/dist/client/versions.js +7 -2
  26. package/dist/client/versions.js.map +1 -1
  27. package/dist/client.js +2 -1
  28. package/dist/components/admin/reader-manifest.d.ts +18 -0
  29. package/dist/components/admin/reader-manifest.js +490 -0
  30. package/dist/components/admin/reader-manifest.js.map +1 -0
  31. package/dist/components/content/card.js +1 -1
  32. package/dist/components/content/card.js.map +1 -1
  33. package/dist/components/content/editors.d.ts +2 -1
  34. package/dist/components/content/editors.js +291 -256
  35. package/dist/components/content/editors.js.map +1 -1
  36. package/dist/components/groups/banner.d.ts +1 -1
  37. package/dist/components/groups/banner.js +1 -1
  38. package/dist/components/groups/banner.js.map +1 -1
  39. package/dist/components/groups/editor.js +3 -3
  40. package/dist/components/groups/editor.js.map +1 -1
  41. package/dist/components/groups/parts.d.ts +2 -2
  42. package/dist/components/groups/parts.js +71 -72
  43. package/dist/components/groups/parts.js.map +1 -1
  44. package/dist/components/social/comments.js +59 -45
  45. package/dist/components/social/comments.js.map +1 -1
  46. package/dist/components/social/index.d.ts +1 -0
  47. package/dist/components/social/moderation.d.ts +5 -4
  48. package/dist/components/social/moderation.js +143 -130
  49. package/dist/components/social/moderation.js.map +1 -1
  50. package/dist/components/social/parts.js +22 -14
  51. package/dist/components/social/parts.js.map +1 -1
  52. package/dist/components/social/rules.d.ts +23 -0
  53. package/dist/components/social/rules.js +261 -0
  54. package/dist/components/social/rules.js.map +1 -0
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +26 -24
  57. package/dist/locales/admin/de.js +78 -0
  58. package/dist/locales/admin/de.js.map +1 -1
  59. package/dist/locales/admin/en.d.ts +78 -0
  60. package/dist/locales/admin/en.js +78 -0
  61. package/dist/locales/admin/en.js.map +1 -1
  62. package/dist/locales/admin/es.js +78 -0
  63. package/dist/locales/admin/es.js.map +1 -1
  64. package/dist/locales/admin/ja.js +78 -0
  65. package/dist/locales/admin/ja.js.map +1 -1
  66. package/dist/locales/admin/ko.js +78 -0
  67. package/dist/locales/admin/ko.js.map +1 -1
  68. package/dist/locales/admin/zh.js +78 -0
  69. package/dist/locales/admin/zh.js.map +1 -1
  70. package/dist/locales/de.js +3 -1
  71. package/dist/locales/de.js.map +1 -1
  72. package/dist/locales/discovery/de.js +1 -0
  73. package/dist/locales/discovery/de.js.map +1 -1
  74. package/dist/locales/discovery/en.d.ts +1 -0
  75. package/dist/locales/discovery/en.js +1 -0
  76. package/dist/locales/discovery/en.js.map +1 -1
  77. package/dist/locales/discovery/es.js +1 -0
  78. package/dist/locales/discovery/es.js.map +1 -1
  79. package/dist/locales/discovery/ja.js +1 -0
  80. package/dist/locales/discovery/ja.js.map +1 -1
  81. package/dist/locales/discovery/ko.js +1 -0
  82. package/dist/locales/discovery/ko.js.map +1 -1
  83. package/dist/locales/discovery/zh.js +1 -0
  84. package/dist/locales/discovery/zh.js.map +1 -1
  85. package/dist/locales/en.d.ts +84 -0
  86. package/dist/locales/en.js +3 -1
  87. package/dist/locales/en.js.map +1 -1
  88. package/dist/locales/es.js +3 -1
  89. package/dist/locales/es.js.map +1 -1
  90. package/dist/locales/ja.js +3 -1
  91. package/dist/locales/ja.js.map +1 -1
  92. package/dist/locales/ko.js +3 -1
  93. package/dist/locales/ko.js.map +1 -1
  94. package/dist/locales/social/de.js +3 -0
  95. package/dist/locales/social/de.js.map +1 -1
  96. package/dist/locales/social/en.d.ts +3 -0
  97. package/dist/locales/social/en.js +3 -0
  98. package/dist/locales/social/en.js.map +1 -1
  99. package/dist/locales/social/es.js +3 -0
  100. package/dist/locales/social/es.js.map +1 -1
  101. package/dist/locales/social/ja.js +3 -0
  102. package/dist/locales/social/ja.js.map +1 -1
  103. package/dist/locales/social/ko.js +3 -0
  104. package/dist/locales/social/ko.js.map +1 -1
  105. package/dist/locales/social/zh.js +3 -0
  106. package/dist/locales/social/zh.js.map +1 -1
  107. package/dist/locales/zh.js +3 -1
  108. package/dist/locales/zh.js.map +1 -1
  109. package/dist/react/admin.d.ts +1 -1
  110. package/dist/react/admin.js +2 -0
  111. package/dist/react/admin.js.map +1 -1
  112. package/dist/react/comments.d.ts +29 -1
  113. package/dist/react/comments.js +30 -2
  114. package/dist/react/comments.js.map +1 -1
  115. package/dist/react/context.d.ts +1 -1
  116. package/dist/react/context.js.map +1 -1
  117. package/dist/react/discovery.js +1 -1
  118. package/dist/react/discovery.js.map +1 -1
  119. package/dist/react/index.d.ts +1 -1
  120. package/dist/react/resources.js +6 -0
  121. package/dist/react/resources.js.map +1 -1
  122. package/dist/react.js +14 -14
  123. package/dist/styles.css +1 -1
  124. package/package.json +1 -1
@@ -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 \"groups.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 \"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":";;;AAgDA,IAAM,IAAwB;CAAE,MAAM,KAAA;CAAW,SAAS;CAAO,QAAQ;AAAM,GAOlE,IAAb,MAA2B;CACzB,wBAAyB,IAAI,IAAkB;CAE/C,UAAkB;CAElB,YAAY,GAA0B;EACpC,EAAO,WAAW,GAAG,MAAU,KAAK,MAAM,GAAG,CAAK,CAAC;CACrD;CAEA,UAAU,GAAa,GAAU,GAAkC;EACjE,IAAI,IAAI,KAAK,MAAM,IAAI,CAAG;EAC1B,AAAK,KAAG,KAAK,MAAM,IAAI,GAAM,IAAI;GAAE;GAAK,2BAAW,IAAI,IAAI;GAAG,OAAO;GAAM,SAAS;GAAG,aAAa,EAAE,KAAK;EAAQ,CAAE;EACrH,IAAM,IAAO;EAEb,OADA,EAAK,UAAU,IAAI,CAAQ,SACd;GAGX,AAFA,EAAK,UAAU,OAAO,CAAQ,GAE9B,qBAAqB;IACf,EAAK,UAAU,QAAQ,KAAK,MAAM,IAAI,CAAG,MAAM,MACnD,EAAK,KAAK,MAAM,GAChB,EAAK,SAAS,MAAM,GACpB,KAAK,MAAM,OAAO,CAAG;GACvB,CAAC;EACH;CACF;CAEA,SAAY,GAA0B;EACpC,OAAQ,KAAK,MAAM,IAAI,CAAG,CAAC,EAAE,SAAS;CACxC;CAGA,KAAK,GAAa,GAA2B,GAA2B;EACtE,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG;EAC5B,AAAI,KAAG,OAAO,OAAO,GAAG;GAAE;GAAS;EAAK,CAAC;CAC3C;CAGA,KAAK,GAAa,IAAQ,IAAa;EACrC,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG;EAC5B,IAAI,CAAC,GAAG,WAAY,CAAC,MAAU,EAAE,MAAM,UAAU,EAAE,MAAO;EAG1D,AAFA,EAAE,KAAK,MAAM,GACb,EAAE,SAAS,MAAM,GACjB,EAAE,UAAU,KAAA;EACZ,IAAM,IAAO,EAAE,MAAM,IAAI,gBAAgB;EAEzC,AADA,KAAK,OAAO,GAAG;GAAE,SAAS;GAAM,aAAa;GAAO,OAAO,KAAA;EAAU,CAAC,GACtE,EAAE,QAAQ,EAAI,MAAM,CAAC,CAAC,MACnB,MAAS;GACJ,EAAE,QAAQ,MACd,EAAE,MAAM,KAAA,GACR,EAAE,cAAc,EAAE,KAAK,SACvB,KAAK,OAAO,GAAG;IAAE;IAAM,SAAS;IAAO,QAAQ;IAAM,OAAO,KAAA;GAAU,CAAC;EACzE,IACC,MAAM;GACL,IAAI,EAAE,QAAQ,GAAK;GACnB,EAAE,MAAM,KAAA;GACR,IAAM,IAAQ,EAAkB,CAAC;GACjC,AAAI,EAAM,SAAS,aAAW,KAAK,OAAO,GAAG;IAAE,SAAS;IAAO,QAAQ;IAAM;GAAM,CAAC;EACtF,CACF;CACF;CAGA,MAAM,SAAS,GAA4B;EACzC,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG,GACtB,IAAO,GAAG,MAAM;EACtB,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAQ,EAAK,SAAS,QAAQ,EAAE,WAAW,EAAE,KAAK;EACnE,IAAM,IAAO,EAAE,UAAU,IAAI,gBAAgB;EAC7C,KAAK,OAAO,GAAG,EAAE,aAAa,GAAK,CAAC;EACpC,IAAI;GACF,IAAM,IAAQ,MAAM,EAAE,KAAK,EAAK,MAAM,EAAI,MAAM;GAChD,IAAI,EAAE,YAAY,GAAK;GACvB,IAAM,IAAM,EAAE,MAAM,MACd,IAAO,IAAI,IAAI,EAAI,MAAM,KAAK,MAAM,EAAE,EAAE,CAAC;GAC/C,KAAK,OAAO,GAAG;IAAE,MAAM;KAAE,OAAO,CAAC,GAAG,EAAI,OAAO,GAAG,EAAK,MAAM,QAAQ,MAAM,CAAC,EAAK,IAAI,EAAE,EAAE,CAAC,CAAC;KAAG,MAAM,EAAK;IAAK;IAAG,OAAO,KAAA;GAAU,CAAC;EACrI,SAAS,GAAG;GACV,IAAM,IAAQ,EAAkB,CAAC;GACjC,AAAI,EAAE,YAAY,KAAO,EAAM,SAAS,aAAW,KAAK,OAAO,GAAG,EAAE,SAAM,CAAC;EAC7E,UAAU;GACR,AAAI,EAAE,YAAY,MAChB,EAAE,UAAU,KAAA,GACZ,KAAK,OAAO,GAAG,EAAE,aAAa,GAAM,CAAC;EAEzC;CACF;CAGA,IAAO,GAAa,GAA8C;EAChE,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG;EAC5B,IAAI,CAAC,GAAG;EACR,IAAM,IAAO,OAAO,KAAS,aAAc,EAAiC,EAAE,MAAM,IAAqB,IAAI;EAE7G,AADA,EAAE,cAAc,EAAE,KAAK,SACvB,KAAK,OAAO,GAAG;GAAE,MAAM;GAAM,QAAQ;GAAM,OAAO,KAAA;EAAU,CAAC;CAC/D;CAGA,KAAK,GAAqB;EACxB,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG;EAC5B,OAAO,IAAK,EAAE,UAAU,EAAE,KAAK,UAAW;CAC5C;CAGA,SAAY,GAAa,GAAe,GAAe;EACrD,IAAM,IAAI,KAAK,MAAM,IAAI,CAAG;EAC5B,AAAI,KAAK,EAAE,YAAY,KAAO,KAAK,OAAO,GAAG;GAAE;GAAM,QAAQ;EAAK,CAAC;CACrE;CAGA,MAAS,GAA8B,GAA+C;EACpF,KAAK,IAAM,KAAK,KAAK,MAAM,OAAO,GAChC,AAAI,EAAE,MAAM,SAAS,KAAA,KAAa,EAAM,EAAE,GAAG,KAAG,KAAK,OAAO,GAAG,EAAE,MAAM,EAAG,EAAE,MAAM,MAAW,EAAE,WAAW,EAAE,CAAC;CAEjH;CAGA,WAAW,GAAoC;EAC7C,KAAK,IAAM,CAAC,GAAK,MAAM,KAAK,OAAO,AAAI,EAAM,EAAE,GAAG,KAAK,EAAE,UAAU,QAAM,KAAK,KAAK,GAAK,EAAI;CAC9F;CAEA,MAAc,GAAqB,GAA4B;EAC7D,IAAM,KAAY,GAA8B,MAAuB;GAErE,AADA,KAAK,OAAU,MAAM,EAAM,CAAC,MAAM,EAAE,aAAa,UAAU,GAAO,CAAE,GACpE,KAAK,YAAY,MAAM,EAAM,CAAC,MAAM,EAAE,aAAa,UAAU,CAAK;EACpE,GACM,KAAmC,GAAiB,MACxD,GACG,MAAM,EAAM,SAAS,EAAE,IAAI,IAC3B,MAAS;GACR,IAAI,IAAU,IACR,IAAW,CAAC;GAClB,KAAK,IAAM,KAAM,EAAK,OAAO;IAC3B,IAAM,IAAO,EAAG,CAAE;IAElB,AADI,MAAS,MAAI,IAAU,KACvB,KAAM,EAAI,KAAK,CAAI;GACzB;GACA,OAAO,IAAU;IAAE,GAAG;IAAM,OAAO;GAAI,IAAI;EAC7C,CACF,GACI,IAAW;GAAC;GAAY;GAAW;GAAU;EAAgB,GAE7D,KAAS,GAAY,MACzB,GACG,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,YACvC,MAAS;GACR,IAAM,KAAQ,MAAkB,EAAK,MAAM,MAAM,EAAE,OAAO,CAAE,IAAI,EAAK,KAAK,MAAO,EAAE,OAAO,IAAK,EAAG,CAAC,IAAI,CAAE,IAAI;GAC7G,IAAI,MAAM,QAAQ,CAAI,GAAG,OAAO,EAAK,CAAI;GACzC,IAAM,IAAQ,EAAK,EAAK,KAAK;GAC7B,OAAO,MAAU,EAAK,QAAQ,IAAO;IAAE,GAAG;IAAM;GAAM;EACxD,CACF;EACF,QAAQ,EAAE,MAAV;GACE,KAAK;IACH,KAAK,mBAAmB,EAAE,MAAM,CAAK;IACrC;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,eAAe;IACjD;GACF,KAAK,mBAAmB;IACtB,IAAM,IAAS,EAAE,QAAQ,aACnB,IAAY,CAAC,EAAE,QAAQ;IAI7B,AAFA,GADa,MAAY,IAAS,EAAE,SAAS,aAAa,EAAE,OAAO,IAAS,EAAE,SAAS,cAAc,EAAW,EAAE,QAAQ,EAAE,MAAM,IACvG,MAAO,EAAE,MAAM,MAAM,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI;KAAE,GAAG;KAAG,OAAO,IAAS,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,SAAS,GAAG,EAAE,KAAK;IAAE,CAAE,GAC3J,KAAU,KAAW,EAAe,CAAC,UAAU,IAAI,MAAO,EAAE,OAAO,IAAS;KAAE,GAAG;KAAG,aAAa,EAAE,cAAc;IAAE,IAAI,CAAE,GAC7H,KAAK,YAAY,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,gBAAgB;IACzE;GACF;GACA,KAAK;IACH,EAAe,IAAW,MAAO,EAAE,OAAO,EAAE,QAAQ,KAAK;KAAE,GAAG;KAAG,GAAG,EAAE;KAAS,QAAQ,EAAE,QAAQ,UAAU,EAAE;IAAO,IAAI,CAAE;IAC1H;GACF,KAAK;IACH,EAAe,IAAW,MAAO,EAAE,OAAO,EAAE,KAAK;KAAE,GAAG;KAAG,GAAG,EAAE;IAAO,IAAI,CAAE;IAC3E;GACF,KAAK,mBAAmB;IACtB,IAAI;IAQJ,AAPA,EAAe,CAAC,YAAY,SAAS,IAAI,MACnC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAgB,KAClC,EAAE,eAAY,IAAS,EAAE,cACvB;KAAE,GAAG;KAAG,SAAS;KAAM,MAAM;KAAa,QAAQ,KAAA;KAAW,SAAS,KAAA;KAAW,WAAW,KAAA;IAAU,EAC9G,GACG,KAAQ,EAAe,CAAC,UAAU,IAAI,MAAO,EAAE,OAAO,IAAS;KAAE,GAAG;KAAG,aAAa,KAAK,IAAI,GAAG,EAAE,cAAc,CAAC;IAAE,IAAI,CAAE,GAC7H,EAAe,CAAC,QAAQ,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAE,GAC5D,EAAyC,CAAC,gBAAgB,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK;KAAE,GAAG;KAAG,SAAS;KAAM,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;IAAE,IAAI,CAAE;IACvJ;GACF;GACA,KAAK;IACH,KAAK,YAAY,MAAM,EAAS,SAAS,EAAE,IAAI,CAAC;IAChD;GACF,KAAK;IAGH,AAFA,GAAO,MAAM,EAAE,SAAS,cAAc,EAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,EAAE,MAAM,GAChF,EAAE,OAAO,SAAS,cAAY,EAAM,EAAE,OAAO,KAAK,OAAO;KAAE,GAAG;KAAG,QAAQ;MAAE,GAAG,EAAE;MAAQ,OAAO,EAAE,OAAO;MAAO,UAAU,EAAE,OAAO;KAAS;IAAE,EAAE,GACnJ,KAAK,YAAY,MAAM,EAAE,SAAS,WAAW;IAC7C;GACF,KAAK;IAIH,AAHA,GAAO,MAAM,EAAE,SAAS,cAAc,EAAW,EAAE,QAAQ,EAAE,MAAM,UAAU;KAAE,WAAW,EAAE;KAAW,OAAO,EAAE;IAAM,EAAE,GACpH,EAAE,OAAO,SAAS,cACpB,EAAM,EAAE,OAAO,KAAK,OAAO;KAAE,GAAG;KAAG,QAAQ;MAAE,GAAG,EAAE;MAAQ,WAAW,EAAE;KAAM;KAAG,QAAQ,EAAE,UAAU;MAAE,GAAG,EAAE;MAAQ,WAAW,EAAE;KAAU;IAAE,EAAE,GAChJ,KAAK,YAAY,MAAM,EAAE,SAAS,WAAW;IAC7C;GACF,KAAK;IAGH,AAFA,GAAuB,MAAM,EAAE,SAAS,aAAa,EAAE,OAAO,EAAE,QAAQ,UAAU,EAAE,OAAO,GAE3F,KAAK,YAAY,MAAM,EAAE,SAAS,cAAc,EAAE,SAAS,WAAY,EAAE,SAAS,oBAAoB,EAAE,OAAO,EAAE,QAAQ,EAAG;IAC5H;GACF,KAAK;IACH,KAAK,YAAY,OAAQ,EAAE,SAAS,aAAa,EAAE,SAAS,qBAAqB,EAAE,OAAO,EAAE,MAAO,EAAE,SAAS,cAAc,EAAE,SAAS,OAAO;IAC9I;GACF,KAAK;IAEH,AADA,EAAsB;KAAC;KAAY;KAAS;IAAS,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAE,GACzF,KAAK,YAAY,OAAQ,EAAE,SAAS,aAAa,EAAE,SAAS,qBAAqB,EAAE,OAAO,EAAE,MAAQ,EAAE,SAAS,cAAc,EAAE,UAAU,SAAU;IACnJ;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,WAAY,EAAE,SAAS,UAAU,CAAC,EAAE,EAAG;IACzE;GACF,KAAK;IAGH,AADA,GAAoB,MAAM,EAAE,SAAS,SAAS,MAAO,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,OAAO,CAAE,GACtF,EAAY,CAAC,OAAO,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK,KAAK,EAAE,OAAO,CAAE;IAC/D;GACF,KAAK;IACH,KAAK,YAAY,MAAO,EAAE,SAAS,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAQ,EAAE,SAAS,OAAO;IAC5F;GACF,KAAK;IAEH,AADA,EAAY,CAAC,OAAO,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAE,GACxD,KAAK,YAAY,MAAM,EAAE,SAAS,UAAU,CAAC,EAAE,EAAE;IACjD;GACF,KAAK;GACL,KAAK;IACH,KAAK,YAAY,MAAO,EAAE,SAAS,UAAU,EAAE,UAAU,EAAE,SAAU,EAAE,SAAS,UAAU;IAC1F;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,KAAK,WAAW,OAAO,CAAC;IACjD;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,aAAa,EAAE,SAAS,eAAe;IAC/F;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,aAAa,EAAE,SAAS,oBAAoB,EAAE,SAAS,iBAAiB,EAAE,KAAK,WAAW,OAAO,CAAC;IAC1J;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,aAAa,EAAE,SAAS,OAAO;IACjE;GACF,KAAK;IACH,KAAK,YAAY,MAAM,EAAE,SAAS,UAAU;IAC5C;GACF,KAAK,uBAEH,AADA,EAAsB,CAAC,MAAM,IAAI,MAAO,EAAE,OAAO,EAAE,KAAK,OAAO,CAAE,GAC7D,EAAE,SAAS,YAAW,KAAK,YAAY,MAAM,EAAS,SAAS,EAAE,IAAI,CAAC,IACrE,KAAK,YAAY,MAAO,EAAE,SAAS,aAAa,EAAE,OAAO,EAAE,MAAO,EAAE,SAAS,UAAU;EAEhG;CACF;CAIA,mBAA2B,GAAY,GAA4B;EACjE,KAAK,IAAM,CAAC,GAAK,MAAS,KAAK,OAAO;GACpC,IAAI,EAAK,IAAI,SAAS,mBAAmB,CAAC,EAAK,UAAU,MAAM;GAC/D,IAAM,IAAO,EAAK,MAAM,MAClB,IAAS,GAAM,MAAM,MAAM,MAAM,EAAE,OAAO,EAAK,EAAE;GAGvD,KAAK,EAAK,IAAI,aAAa,UAAU,KAAS,KAAU,EAAO,WAAW,EAAK,UAAU;GAEzF,IAAM,KADW,EAAK,IAAI,OAAO,WAAW,WAAW,KAAK,QAC/B,CAAC,CAAC,EAAK;GACpC,KAAK,EAAK,IAAI,aAAa,UAAU,KAAS,CAAC,KAAQ,EAAK,IAAI,OAAO,SAAS,SAAS,KAAM,KAAW,CAAC,EAAK,MAAM,MAAM,MAAM,EAAE,OAAO,EAAK,EAAE,GAAI;IACpJ,KAAK,KAAK,GAAK,EAAI;IACnB;GACF;GACI,CAAC,KAAY,EAAK,MAAM,MAAM,MAAM,EAAE,OAAO,EAAK,EAAE,OACxD,EAAK,KAAK,MAAM,GAChB,EAAK,SAAS,MAAM,GACpB,EAAK,MAAM,EAAK,UAAU,KAAA,GAC1B,KAAK,OAAO,GAAM;IAAE,SAAS;IAAO,aAAa;IAAO,MAAM;KAAE,GAAG;KAAM,OAAO,EAAK,MAAM,SAAS,MAAM,EAAE,OAAO,EAAK,KAAK,IAAU,CAAC,CAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAAE;GAAE,CAAC;EAC/J;CACF;CAGA,OAAe,GAAS,GAAyC;EAC/D,EAAE,QAAQ;GAAE,GAAG,EAAE;GAAO,GAAG;EAAM;EACjC,KAAK,IAAM,KAAK,EAAE,WAAW,EAAE;CACjC;AACF,GAEM,oBAAS,IAAI,QAAyC;AAG5D,SAAgB,EAAa,GAAyC;CACpE,IAAI,IAAI,EAAO,IAAI,CAAM;CAEzB,OADK,KAAG,EAAO,IAAI,GAAS,IAAI,IAAI,EAAc,CAAM,CAAE,GACnD;AACT"}
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 \"groups.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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"}
package/dist/react.js CHANGED
@@ -11,17 +11,17 @@ import { nameIn as N, thumbnailOf as P, useMediaFolder as F } from "./react/fold
11
11
  import { useNearViewport as I } from "./react/viewport.js";
12
12
  import { ResourceStore as L, resourcesFor as R } from "./react/resources.js";
13
13
  import { useContentScope as z, usePaged as B } from "./react/use-resource.js";
14
- import { useAdminComments as V, useCanComment as H, useCommentBans as U, useCommentReplies as W, useComments as G, useGlobalCommentBan as K, useLatestComments as q, useModerationQueue as J, withReaction as Y } from "./react/comments.js";
15
- import { useContentConfig as X } from "./react/config.js";
16
- import { useFavorite as Z, useReaction as Q } from "./react/engagement.js";
17
- import { usePoll as $, usePollEditor as ee, usePolls as te, withVote as ne } from "./react/polls.js";
18
- import { useAdminLocation as re, useFlowClient as ie, useStaffAccess as ae } from "./react/admin.js";
19
- import { memberId as oe, useContentGroups as se, useGroup as ce, useGroupMembers as le, useGroups as ue, useKinds as de, useMyGroups as fe } from "./react/groups.js";
20
- import { beaconsFor as pe, useBeacons as me, useContentFilters as he, useContents as ge, useExposure as _e, useHistory as ve, useMyFavorites as ye, useMyReactions as be, useRecentSearches as xe, useRecommendations as Se, useReleaseDates as Ce, useSearch as we, useSimilar as Te, useTypeahead as Ee, useViewSignal as De } from "./react/discovery.js";
21
- import { useContent as Oe, useManagedContents as ke } from "./react/contents.js";
22
- import { useNotificationUnread as Ae, useNotifications as je } from "./react/notifications.js";
23
- import { ContentKitProvider as Me } from "./react/provider.js";
24
- import { useCanonicalContent as Ne } from "./react/canonical.js";
25
- import { defaultVersion as Pe, liveVersions as Fe, useContentDetail as Ie } from "./react/detail.js";
26
- import { nextRelease as Le, useReaderPlan as Re, useSegmentPages as ze, useVersionDownload as Be } from "./react/versions.js";
27
- export { Me as ContentKitProvider, E as GALLERY_VIEW_KEY, i as GuardContext, e as HOVER_DELAY, t as InlinePreviewContext, D as PLAYER_QUALITY_KEY, L as ResourceStore, pe as beaconsFor, Pe as defaultVersion, v as editOutput, Fe as liveVersions, oe as memberId, N as nameIn, Le as nextRelease, R as resourcesFor, x as round3, P as thumbnailOf, V as useAdminComments, re as useAdminLocation, me as useBeacons, H as useCanComment, Ne as useCanonicalContent, O as useCarousel, U as useCommentBans, W as useCommentReplies, G as useComments, Oe as useContent, X as useContentConfig, Ie as useContentDetail, he as useContentFilters, se as useContentGroups, a as useContentKit, o as useContentKitClient, z as useContentScope, s as useContentURLs, ge as useContents, d as useCrop, M as useEditorCrop, f as useEncodeProgress, c as useErrorReporter, _e as useExposure, Z as useFavorite, ie as useFlowClient, S as useFrameStrip, k as useGalleryView, K as useGlobalCommentBan, ce as useGroup, le as useGroupMembers, ue as useGroups, l as useGuarded, ve as useHistory, A as useHlsPlayer, n as useInlinePreview, de as useKinds, q as useLatestComments, ke as useManagedContents, F as useMediaFolder, h as useMediaRead, J as useModerationQueue, ye as useMyFavorites, fe as useMyGroups, be as useMyReactions, I as useNearViewport, Ae as useNotificationUnread, je as useNotifications, u as useOptionalContentKitClient, B as usePaged, $ as usePoll, ee as usePollEditor, te as usePolls, g as usePresets, _ as usePublicImage, Q as useReaction, Re as useReaderPlan, xe as useRecentSearches, Se as useRecommendations, r as useReducedMotion, j as useRefreshBeforeExpiry, Ce as useReleaseDates, we as useSearch, ze as useSegmentPages, Te as useSimilar, y as useSlotCrop, b as useSlotImage, ae as useStaffAccess, Ee as useTypeahead, p as useUpload, m as useUploadQueue, Be as useVersionDownload, C as useVideoFrame, w as useVideoImages, T as useVideoPoster, De as useViewSignal, Y as withReaction, ne as withVote };
14
+ import { useAdminComments as V, useBannedWords as H, useCanComment as U, useCommentBans as W, useCommentReplies as G, useComments as K, useGlobalCommentBan as q, useIPBans as J, useLatestComments as Y, useModerationQueue as X, withReaction as Z } from "./react/comments.js";
15
+ import { useContentConfig as Q } from "./react/config.js";
16
+ import { useFavorite as $, useReaction as ee } from "./react/engagement.js";
17
+ import { usePoll as te, usePollEditor as ne, usePolls as re, withVote as ie } from "./react/polls.js";
18
+ import { useAdminLocation as ae, useFlowClient as oe, useStaffAccess as se } from "./react/admin.js";
19
+ import { memberId as ce, useContentGroups as le, useGroup as ue, useGroupMembers as de, useGroups as fe, useKinds as pe, useMyGroups as me } from "./react/groups.js";
20
+ import { beaconsFor as he, useBeacons as ge, useContentFilters as _e, useContents as ve, useExposure as ye, useHistory as be, useMyFavorites as xe, useMyReactions as Se, useRecentSearches as Ce, useRecommendations as we, useReleaseDates as Te, useSearch as Ee, useSimilar as De, useTypeahead as Oe, useViewSignal as ke } from "./react/discovery.js";
21
+ import { nextRelease as Ae, useReaderPlan as je, useSegmentPages as Me, useVersionDownload as Ne } from "./react/versions.js";
22
+ import { useContent as Pe, useManagedContents as Fe } from "./react/contents.js";
23
+ import { useNotificationUnread as Ie, useNotifications as Le } from "./react/notifications.js";
24
+ import { ContentKitProvider as Re } from "./react/provider.js";
25
+ import { useCanonicalContent as ze } from "./react/canonical.js";
26
+ import { defaultVersion as Be, liveVersions as Ve, useContentDetail as He } from "./react/detail.js";
27
+ export { Re as ContentKitProvider, E as GALLERY_VIEW_KEY, i as GuardContext, e as HOVER_DELAY, t as InlinePreviewContext, D as PLAYER_QUALITY_KEY, L as ResourceStore, he as beaconsFor, Be as defaultVersion, v as editOutput, Ve as liveVersions, ce as memberId, N as nameIn, Ae as nextRelease, R as resourcesFor, x as round3, P as thumbnailOf, V as useAdminComments, ae as useAdminLocation, H as useBannedWords, ge as useBeacons, U as useCanComment, ze as useCanonicalContent, O as useCarousel, W as useCommentBans, G as useCommentReplies, K as useComments, Pe as useContent, Q as useContentConfig, He as useContentDetail, _e as useContentFilters, le as useContentGroups, a as useContentKit, o as useContentKitClient, z as useContentScope, s as useContentURLs, ve as useContents, d as useCrop, M as useEditorCrop, f as useEncodeProgress, c as useErrorReporter, ye as useExposure, $ as useFavorite, oe as useFlowClient, S as useFrameStrip, k as useGalleryView, q as useGlobalCommentBan, ue as useGroup, de as useGroupMembers, fe as useGroups, l as useGuarded, be as useHistory, A as useHlsPlayer, J as useIPBans, n as useInlinePreview, pe as useKinds, Y as useLatestComments, Fe as useManagedContents, F as useMediaFolder, h as useMediaRead, X as useModerationQueue, xe as useMyFavorites, me as useMyGroups, Se as useMyReactions, I as useNearViewport, Ie as useNotificationUnread, Le as useNotifications, u as useOptionalContentKitClient, B as usePaged, te as usePoll, ne as usePollEditor, re as usePolls, g as usePresets, _ as usePublicImage, ee as useReaction, je as useReaderPlan, Ce as useRecentSearches, we as useRecommendations, r as useReducedMotion, j as useRefreshBeforeExpiry, Te as useReleaseDates, Ee as useSearch, Me as useSegmentPages, De as useSimilar, y as useSlotCrop, b as useSlotImage, se as useStaffAccess, Oe as useTypeahead, p as useUpload, m as useUploadQueue, Ne as useVersionDownload, C as useVideoFrame, w as useVideoImages, T as useVideoPoster, ke as useViewSignal, Z as withReaction, ie as withVote };