@blogmcp/community 0.2.0 → 0.3.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 (82) hide show
  1. package/README.md +64 -12
  2. package/dist/blogmcp-community.global.js +7 -7
  3. package/dist/chunks/{mount-WadUnaTa.js → mount--2_V2q3M.js} +4724 -1097
  4. package/dist/core/attrs.d.ts +17 -2
  5. package/dist/core/discussion.d.ts +92 -18
  6. package/dist/core/follow.d.ts +26 -0
  7. package/dist/core/forum-category.d.ts +85 -0
  8. package/dist/core/forum-search.d.ts +35 -0
  9. package/dist/core/forum-state.d.ts +30 -0
  10. package/dist/core/forum-words.d.ts +8 -0
  11. package/dist/core/forum.d.ts +21 -0
  12. package/dist/core/moderation.d.ts +80 -0
  13. package/dist/core/onboarding.d.ts +7 -0
  14. package/dist/core/profile.d.ts +6 -1
  15. package/dist/core/realtime.d.ts +13 -2
  16. package/dist/core/topic.d.ts +47 -0
  17. package/dist/element.d.ts +26 -1
  18. package/dist/global.d.ts +7 -6
  19. package/dist/index.d.ts +13 -4
  20. package/dist/index.js +54 -27
  21. package/dist/mount.d.ts +50 -1
  22. package/dist/react.d.ts +17 -4
  23. package/dist/react.js +32 -8
  24. package/dist/ui/FollowButtonView.vue.d.ts +17 -0
  25. package/dist/ui/FollowToggle.vue.d.ts +6 -0
  26. package/dist/ui/ForumCategoryView.vue.d.ts +13 -0
  27. package/dist/ui/ForumModerationView.vue.d.ts +12 -0
  28. package/dist/ui/ForumNotices.vue.d.ts +7 -0
  29. package/dist/ui/ForumSearchView.vue.d.ts +11 -0
  30. package/dist/ui/ForumView.vue.d.ts +12 -0
  31. package/dist/ui/MembersOnly.vue.d.ts +15 -0
  32. package/dist/ui/MessageComposer.vue.d.ts +6 -2
  33. package/dist/ui/MessageMenu.vue.d.ts +2 -0
  34. package/dist/ui/ModeratorDialog.vue.d.ts +11 -0
  35. package/dist/ui/TopicRow.vue.d.ts +10 -0
  36. package/dist/ui/TopicView.vue.d.ts +32 -0
  37. package/dist/ui/context.d.ts +7 -1
  38. package/dist/ui/discussion-context.d.ts +11 -3
  39. package/dist/vue.d.ts +164 -5
  40. package/dist/vue.js +134 -8
  41. package/package.json +3 -3
  42. package/src/core/attrs.ts +22 -2
  43. package/src/core/discussion.ts +309 -43
  44. package/src/core/follow.ts +139 -0
  45. package/src/core/forum-category.ts +323 -0
  46. package/src/core/forum-search.ts +153 -0
  47. package/src/core/forum-state.ts +59 -0
  48. package/src/core/forum-words.ts +38 -0
  49. package/src/core/forum.ts +83 -0
  50. package/src/core/moderation.ts +414 -0
  51. package/src/core/onboarding.ts +16 -4
  52. package/src/core/outcomes.ts +10 -0
  53. package/src/core/profile.ts +12 -1
  54. package/src/core/realtime.ts +15 -2
  55. package/src/core/topic.ts +234 -0
  56. package/src/element.ts +63 -1
  57. package/src/global.ts +27 -5
  58. package/src/index.ts +49 -2
  59. package/src/mount.ts +144 -2
  60. package/src/react.ts +45 -2
  61. package/src/ui/FollowButtonView.vue +85 -0
  62. package/src/ui/FollowToggle.vue +39 -0
  63. package/src/ui/ForumCategoryView.vue +243 -0
  64. package/src/ui/ForumModerationView.vue +309 -0
  65. package/src/ui/ForumNotices.vue +23 -0
  66. package/src/ui/ForumSearchView.vue +171 -0
  67. package/src/ui/ForumView.vue +128 -0
  68. package/src/ui/MembersOnly.vue +59 -0
  69. package/src/ui/MessageComposer.vue +51 -9
  70. package/src/ui/MessageItem.vue +12 -1
  71. package/src/ui/MessageMenu.vue +3 -2
  72. package/src/ui/ModeratorDialog.vue +102 -0
  73. package/src/ui/MyCommunityView.vue +3 -0
  74. package/src/ui/NoticeStatusView.vue +15 -2
  75. package/src/ui/NotificationCentreView.vue +37 -3
  76. package/src/ui/ProfileView.vue +15 -4
  77. package/src/ui/TopicRow.vue +70 -0
  78. package/src/ui/TopicView.vue +395 -0
  79. package/src/ui/context.ts +8 -3
  80. package/src/ui/discussion-context.ts +11 -3
  81. package/src/ui/styles.css +14 -0
  82. package/src/vue.ts +145 -3
package/README.md CHANGED
@@ -26,10 +26,42 @@ With the community module (M2) there are five more:
26
26
  the daily e-mail digest, the quiet night 22:00–7:00), each saved on its own; this browser's notifications;
27
27
  and the digest e-mail's unsubscribe link (below);
28
28
  - `<blogmcp-profile handle="…">`: a member's public profile: name, avatar, since when they are a member, the
29
- bio as text and the trust level as a label („Nový člen", „Člen", „Stálý člen", „Moderátor"), never a number;
29
+ bio as text and the trust level as a label („Nový člen", „Člen", „Stálý člen", „Důvěryhodný člen"), never a
30
+ number; with the forum, „Moderátor" and the categories the member moderates now (an appointment, not a trust
31
+ level);
30
32
  - `<blogmcp-welcome>`: the page after joining: the rules in summary and three links (the discussions, the
31
33
  settings, the member's own profile; a visitor gets your sign-in link instead).
32
34
 
35
+ With the forum (M3) there are six more. The forum is for members only: a visitor reads one sentence and your
36
+ sign-in link, a member short of the onboarding „Vstoupit do komunity" (the onboarding opens in place; a forum write
37
+ needs the art. 9 consent whatever the tenant asks elsewhere).
38
+
39
+ - `<blogmcp-forum>`: the forum's index. The categories in the team's order, each with its count, its latest
40
+ topics and the link to all of them, and a search box that opens your search page with the query in the
41
+ address's fragment (`#q=…`, never the query string);
42
+ - `<blogmcp-forum-category slug="…">`: a category's topics, by activity or newest, pinned first, more a page at
43
+ a time. Where members open topics, the new-topic composer (a title of at most 200 characters, the opening post,
44
+ the link to the rules); a topic that waits for review says so and lists for its author only. In „Články" the
45
+ rows are the article discussions, each with its follow button;
46
+ - `<blogmcp-topic conversation-id="…">`: a topic's page. The header (title, category, closed, pinned, count),
47
+ the thread in the forum's words („příspěvek", where an article's discussion says „komentář"), the composer,
48
+ reactions, reports, the follow button and, for the opening post's author, the title's edit. A moderator of the
49
+ topic's category gets its menu: close or reopen it, pin it, move it, remove a message (with the rule and the
50
+ facts; the author gets a statement of reasons) or pass a message to the team;
51
+ - `<blogmcp-forum-search>`: the forum's search, as text. It reads the query from `#q=…`; a query shorter than two
52
+ characters is said, never sent;
53
+ - `<blogmcp-follow-button target-kind="…" target-id="…">`: follow a topic or an article discussion
54
+ (`conversation`) or a category (`category`). A follow the member may not have reads „not available"; an unfollow
55
+ never fails;
56
+ - `<blogmcp-forum-moderation>`: a category moderator's queue. The package of each case as text, the decision with
57
+ its statement previewed before it is decided, a matter passed to the team, the messages waiting for review
58
+ published or refused. It renders nothing for a member who moderates nothing.
59
+
60
+ A missing title reads one of three ways: „Smazané téma" only when the opening post was deleted, its own words
61
+ while it is withheld from the viewer, and its title with „Čeká na kontrolu" for the author of a topic waiting for
62
+ review. The forum's own brake pauses the forum's writes only, the article discussions' brake the discussions only
63
+ (the module's brake both); while the team is away the forum says so in one sentence.
64
+
33
65
  `<blogmcp-discussion>` also links every `@handle` in a comment to that member's profile page (for a signed-in
34
66
  reader; an anonymous one reads the mention as text), and takes live updates through its `realtime` property
35
67
  (below).
@@ -97,23 +129,27 @@ import { KbDiscussion } from '@blogmcp/community/react' // a client component
97
129
  <KbDiscussion articleId={article.id} apiBase="/api/community" signInHref="/sign-in" />
98
130
  ```
99
131
 
100
- `KbNoticeForm`, `KbMyCommunity`, `KbNotificationCentre`, `KbBadge`, `KbMemberSettings`, `KbProfile` and
101
- `KbWelcome` work the same way. Each wrapper mounts its element after hydration and
132
+ `KbNoticeForm`, `KbMyCommunity`, `KbNotificationCentre`, `KbBadge`, `KbMemberSettings`, `KbProfile`,
133
+ `KbWelcome` and the forum's `KbForum`, `KbForumCategory`, `KbTopic`, `KbForumSearch`, `KbFollowButton` and
134
+ `KbForumModeration` work the same way. Each wrapper mounts its element after hydration and
102
135
  removes it on unmount. It renders a single empty `<div data-blogmcp-community="…">` as the mount point: the
103
136
  discussion is part of the page's flow, so the element goes where the wrapper is.
104
137
 
105
138
  `mountDiscussion(o)`, `mountNoticeForm(o)`, `mountMyCommunity(o)`, `mountNotificationCentre(o)`, `mountBadge(o)`,
106
- `mountMemberSettings(o)`, `mountProfile(o)` and `mountWelcome(o)` do the same from any client-side hook. Each
107
- returns the unmount function.
139
+ `mountMemberSettings(o)`, `mountProfile(o)`, `mountWelcome(o)` and the forum's `mountForum(o)`,
140
+ `mountForumCategory(o)`, `mountTopic(o)`, `mountForumSearch(o)`, `mountFollowButton(o)` and
141
+ `mountForumModeration(o)` do the same from any client-side hook. Each returns the unmount function. The tag names
142
+ are exported too (`DISCUSSION_ELEMENT_TAG` … `FORUM_MODERATION_ELEMENT_TAG`), and `defineForumElement()` and its
143
+ siblings register one element alone.
108
144
 
109
145
  **Plain HTML**
110
146
 
111
147
  ```html
112
148
  <blogmcp-discussion article-id="…" api-base="/api/community" sign-in-href="/prihlaseni"></blogmcp-discussion>
113
- <script src="https://cdn.jsdelivr.net/npm/@blogmcp/community@0.2.0/dist/blogmcp-community.global.js" nonce="…"></script>
149
+ <script src="https://cdn.jsdelivr.net/npm/@blogmcp/community@0.3.0/dist/blogmcp-community.global.js" nonce="…"></script>
114
150
  ```
115
151
 
116
- The script build (`@blogmcp/community/global`) registers all eight elements. It exposes
152
+ The script build (`@blogmcp/community/global`) registers all fourteen elements. It exposes
117
153
  `window.BlogmcpCommunity` and gives the elements its own `nonce`.
118
154
 
119
155
  ## Attributes
@@ -140,10 +176,22 @@ The script build (`@blogmcp/community/global`) registers all eight elements. It
140
176
  | `<blogmcp-profile>` | `handle` | the member's handle (an `@` in front is fine) |
141
177
  | | `sign-in-href` | your sign-in page (profiles are for signed-in readers) |
142
178
  | `<blogmcp-welcome>` | `sign-in-href` | your sign-in page (in the profile link's place, for a visitor) |
179
+ | `<blogmcp-forum>` | `sign-in-href` | your sign-in page (a visitor's link) |
180
+ | `<blogmcp-forum-category>` | `slug` | the category's slug |
181
+ | | `sign-in-href` | your sign-in page |
182
+ | `<blogmcp-topic>` | `conversation-id` | the topic (its conversation id) |
183
+ | | `sign-in-href` | your sign-in page |
184
+ | | `poll-ms` | how often to check for new posts while the topic is in view (default 20000; 0 = off) |
185
+ | `<blogmcp-forum-search>` | `sign-in-href` | your sign-in page |
186
+ | `<blogmcp-follow-button>` | `target-kind` | `conversation` (a topic, an article discussion) or `category` |
187
+ | | `target-id` | its id |
188
+ | | `following` | `true` / `false` when your page knows it (left out: the element reads the member's follows) |
189
+ | `<blogmcp-forum-moderation>` | `category-id` | one of the moderator's categories only (left out: all of them) |
143
190
 
144
191
  `routes` names your community pages: `statementPath` (with `{id}`), `myCommunityPath`, `rulesPath`,
145
192
  `reportPath`, `noticesPath` and, with the module, `profilePath` (with `{handle}`), `settingsPath`,
146
- `notificationsPath`, `welcomePath` and `discussionsPath`. Each is a full path on your site, used as it is. A page you leave out
193
+ `notificationsPath`, `welcomePath` and `discussionsPath`, and with the forum `forumPath`, `categoryPath` (with
194
+ `{slug}`), `topicPath` (with `{id}`, the topic's conversation id) and `searchPath`. Each is a full path on your site, used as it is. A page you leave out
147
195
  falls back to the managed blog's pages: `${site-base}/community/…`. `articlePath` (with `{slug}`; no default)
148
196
  is your article page — the managed blogs' `/blog/articles/{slug}`, a shop's `/blog/{slug}`: the notification
149
197
  centre links a reply or a mention to its message there (`…/<slug>#bcm-msg-<seq>`), and without it those rows stay
@@ -160,7 +208,9 @@ A `transport` property replaces the HTTP layer, for tests.
160
208
  ## Live updates (`realtime`)
161
209
 
162
210
  The discussion keeps itself fresh by polling. For live updates, import the SDK's realtime entry yourself and pass
163
- its `createRealtimeSession` as the discussion's `realtime` property (a property, never an attribute). Your bundle
211
+ its `createRealtimeSession` as the discussion's `realtime` property (a property, never an attribute) — or the
212
+ topic's: `<blogmcp-topic>` takes it the same way (a change of the topic's header, its title or state, reads the
213
+ topic again). Your bundle
164
214
  then needs `centrifuge` (≥ 5.7), the entry's peer dependency; the elements never import either, so a site
165
215
  without it ships no socket code.
166
216
 
@@ -214,7 +264,8 @@ reads it once, clears it from the address bar, and sends it only when the member
214
264
  (`settingsPath`) where kb-api's e-mails point.
215
265
 
216
266
  Events (bubbling, composed):
217
- - `bcm-posted`, `{ state: 'visible' | 'held' }`: the reader's comment went out;
267
+ - `bcm-posted`, `{ state: 'visible' | 'held' }`: the reader's comment (or, in a topic, post) went out;
268
+ - `bcm-topic-created`, `{ conversationId, state: 'visible' | 'held' }`: the member opened a topic;
218
269
  - `bcm-notice-submitted`, `{ contactKept }`: a notice was received.
219
270
 
220
271
  ## Look
@@ -237,8 +288,9 @@ The properties are `--bcm-bg`, `-fg`, `-muted`, `-line`, `-soft`, `-accent`, `-a
237
288
 
238
289
  ```bash
239
290
  npm run build # ESM + the <script> build (+ size budget, 200 KiB gzip)
240
- npm test # vitest (happy-dom): controllers, store, onboarding, outcomes, elements, text-only and closed-path scans
291
+ npm test # vitest (happy-dom): controllers, store, onboarding, outcomes, elements, the forum's six, text-only and closed-path scans
241
292
  npm run test:e2e # Playwright: desktop + iPhone profile + a plain bundler, mocked community API (ports 8286/8287);
242
293
  # m2.e2e.ts drives the centre (its link to a reply's message), the badge, the settings,
243
- # a profile, the welcome page and the composer's mention limit
294
+ # a profile, the welcome page and the composer's mention limit; plain-bundler.e2e.ts mounts
295
+ # M1's, M2's and the forum's elements from dist/ (a topic opened from a category included)
244
296
  ```