@blogmcp/community 0.1.0 → 0.2.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.
- package/README.md +108 -11
- package/dist/blogmcp-community.global.js +8 -8
- package/dist/chunks/{mount-DzjwnHyx.js → mount-WadUnaTa.js} +3909 -2070
- package/dist/core/attrs.d.ts +27 -1
- package/dist/core/badge.d.ts +30 -0
- package/dist/core/centre.d.ts +28 -0
- package/dist/core/digest-token.d.ts +2 -0
- package/dist/core/discussion.d.ts +36 -5
- package/dist/core/format.d.ts +7 -0
- package/dist/core/onboarding.d.ts +42 -2
- package/dist/core/outcomes.d.ts +2 -1
- package/dist/core/panel.d.ts +17 -1
- package/dist/core/profile.d.ts +40 -0
- package/dist/core/push.d.ts +63 -0
- package/dist/core/realtime.d.ts +35 -0
- package/dist/core/settings.d.ts +53 -0
- package/dist/core/text.d.ts +13 -0
- package/dist/element.d.ts +22 -1
- package/dist/global.d.ts +7 -4
- package/dist/index.d.ts +10 -2
- package/dist/index.js +34 -11
- package/dist/mount.d.ts +40 -0
- package/dist/react.d.ts +14 -3
- package/dist/react.js +24 -4
- package/dist/ui/BadgeView.vue.d.ts +13 -0
- package/dist/ui/DiscussionView.vue.d.ts +11 -0
- package/dist/ui/LinkedText.vue.d.ts +1 -0
- package/dist/ui/MemberSettingsView.vue.d.ts +13 -0
- package/dist/ui/MessageComposer.vue.d.ts +2 -0
- package/dist/ui/NotificationCentreView.vue.d.ts +12 -0
- package/dist/ui/OnboardingSteps.vue.d.ts +1 -1
- package/dist/ui/ProfileView.vue.d.ts +13 -0
- package/dist/ui/WelcomeView.vue.d.ts +12 -0
- package/dist/vue.d.ts +114 -3
- package/dist/vue.js +109 -5
- package/package.json +3 -3
- package/src/core/attrs.ts +41 -2
- package/src/core/badge.ts +120 -0
- package/src/core/centre.ts +136 -0
- package/src/core/digest-token.ts +26 -0
- package/src/core/discussion.ts +203 -18
- package/src/core/format.ts +22 -0
- package/src/core/onboarding.ts +165 -18
- package/src/core/outcomes.ts +13 -1
- package/src/core/panel.ts +39 -4
- package/src/core/profile.ts +144 -0
- package/src/core/push.ts +174 -0
- package/src/core/realtime.ts +39 -0
- package/src/core/settings.ts +363 -0
- package/src/core/text.ts +32 -0
- package/src/element.ts +62 -6
- package/src/global.ts +18 -4
- package/src/index.ts +36 -1
- package/src/mount.ts +108 -1
- package/src/react.ts +47 -3
- package/src/ui/BadgeView.vue +51 -0
- package/src/ui/DiscussionView.vue +43 -3
- package/src/ui/LinkedText.vue +11 -5
- package/src/ui/MemberSettingsView.vue +175 -0
- package/src/ui/MessageComposer.vue +15 -4
- package/src/ui/MessageItem.vue +24 -6
- package/src/ui/MyCommunityView.vue +9 -0
- package/src/ui/NotificationCentreView.vue +159 -0
- package/src/ui/OnboardingSteps.vue +17 -6
- package/src/ui/ProfileView.vue +91 -0
- package/src/ui/WelcomeView.vue +72 -0
- package/src/ui/styles.css +16 -0
- package/src/vue.ts +129 -3
package/dist/core/attrs.d.ts
CHANGED
|
@@ -30,6 +30,25 @@ export interface CommunityRoutes {
|
|
|
30
30
|
* becomes a link to it (m1-contracts.md §7.6). No default — without it the note stays text.
|
|
31
31
|
*/
|
|
32
32
|
consultationPath?: string;
|
|
33
|
+
/**
|
|
34
|
+
* M2 (m2-contracts.md §3.10): a member's public profile; `{handle}` is the handle (`/komunita/u/{handle}`) — a
|
|
35
|
+
* template, as statementPath is. A mention in a message links to it.
|
|
36
|
+
*/
|
|
37
|
+
profilePath?: string;
|
|
38
|
+
/** M2: the member's notification settings (where the digest's unsubscribe link lands with `#u=`). */
|
|
39
|
+
settingsPath?: string;
|
|
40
|
+
/** M2: the notification centre (the badge links to it). */
|
|
41
|
+
notificationsPath?: string;
|
|
42
|
+
/** M2: the welcome page after joining. */
|
|
43
|
+
welcomePath?: string;
|
|
44
|
+
/** M2: the discussions overview. */
|
|
45
|
+
discussionsPath?: string;
|
|
46
|
+
/**
|
|
47
|
+
* M2 T10: an article's page; `{slug}` is the article's slug (`/blog/articles/{slug}`, the storefront `/blog/{slug}`)
|
|
48
|
+
* — a template, as profilePath is. The notification centre links a reply's or a mention's message on it (the
|
|
49
|
+
* message's anchor in the fragment). No default: without it those rows stay unlinked.
|
|
50
|
+
*/
|
|
51
|
+
articlePath?: string;
|
|
33
52
|
}
|
|
34
53
|
/** A path on the host's own site (the SDK's links.ts rule). */
|
|
35
54
|
export declare function isSitePath(path: unknown): path is string;
|
|
@@ -42,7 +61,8 @@ export declare function parseRoutes(value: unknown): CommunityRoutes;
|
|
|
42
61
|
*/
|
|
43
62
|
export declare function siteBaseOf(value: unknown): string | null;
|
|
44
63
|
/**
|
|
45
|
-
* The pages with the managed blog's defaults filled in under the site's base (statementPath
|
|
64
|
+
* The pages with the managed blog's defaults filled in under the site's base (statementPath and profilePath stay
|
|
65
|
+
* templates; articlePath, a template too, has no default).
|
|
46
66
|
* A page the host or the tenant names is its own full path.
|
|
47
67
|
*/
|
|
48
68
|
export declare function routesWithDefaults(routes: CommunityRoutes, tenant?: {
|
|
@@ -55,6 +75,12 @@ export declare function routesWithDefaults(routes: CommunityRoutes, tenant?: {
|
|
|
55
75
|
reportPath: string;
|
|
56
76
|
noticesPath: string;
|
|
57
77
|
consultationPath: string | null;
|
|
78
|
+
profilePath: string;
|
|
79
|
+
settingsPath: string;
|
|
80
|
+
notificationsPath: string;
|
|
81
|
+
welcomePath: string;
|
|
82
|
+
discussionsPath: string;
|
|
83
|
+
articlePath: string | null;
|
|
58
84
|
};
|
|
59
85
|
/** A notice target of one of kb-api's four shapes, or null (the form then has nothing to report). */
|
|
60
86
|
export declare function parseTarget(value: unknown): NoticeTarget | null;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CommunityClient } from '@blogmcp/sdk/community';
|
|
2
|
+
/** The badge's poll (the contract's 60 s). */
|
|
3
|
+
export declare const BADGE_INTERVAL_MS = 60000;
|
|
4
|
+
/** A count above it reads `99+`. */
|
|
5
|
+
export declare const BADGE_MAX = 99;
|
|
6
|
+
export interface BadgeUi {
|
|
7
|
+
/** `hidden`: nothing to show (a visitor, no member, a dark module, or not decided yet). */
|
|
8
|
+
phase: 'pending' | 'hidden' | 'shown';
|
|
9
|
+
count: number;
|
|
10
|
+
}
|
|
11
|
+
export interface BadgeController {
|
|
12
|
+
readonly state: BadgeUi;
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
/** Read the count now (coalesced with one on its way). */
|
|
15
|
+
refresh(): Promise<void>;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
}
|
|
18
|
+
export interface BadgeOptions {
|
|
19
|
+
client: CommunityClient;
|
|
20
|
+
/**
|
|
21
|
+
* Default 60 s, and never more often (a smaller value above 0 reads as 60 s: the contract's rate per open tab);
|
|
22
|
+
* 0 or less = no poll (the count is read once and on visibility).
|
|
23
|
+
*/
|
|
24
|
+
intervalMs?: number;
|
|
25
|
+
/** Whether the page is visible now (default: document.visibilityState). */
|
|
26
|
+
visible?: () => boolean;
|
|
27
|
+
}
|
|
28
|
+
/** The count as the badge shows it. */
|
|
29
|
+
export declare const badgeText: (count: number) => string;
|
|
30
|
+
export declare function createBadge(o: BadgeOptions): BadgeController;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type CommunityClient, type CommunityFailure, type NotificationItem } from '@blogmcp/sdk/community';
|
|
2
|
+
import type { TextRef } from './i18n';
|
|
3
|
+
export type CentrePhase = 'idle' | 'loading' | 'ready' | 'failed' | 'signIn';
|
|
4
|
+
export interface CentreUi {
|
|
5
|
+
phase: CentrePhase;
|
|
6
|
+
failure: CommunityFailure | null;
|
|
7
|
+
/** Known codes only (a code a newer kb-api sends is skipped, never shown raw). */
|
|
8
|
+
items: NotificationItem[];
|
|
9
|
+
nextCursor: string | null;
|
|
10
|
+
unreadOnly: boolean;
|
|
11
|
+
loadingMore: boolean;
|
|
12
|
+
busy: Record<string, boolean>;
|
|
13
|
+
announcement: TextRef | null;
|
|
14
|
+
announceId: number;
|
|
15
|
+
}
|
|
16
|
+
export interface NotificationCentreController {
|
|
17
|
+
readonly state: CentreUi;
|
|
18
|
+
load(): Promise<void>;
|
|
19
|
+
loadMore(): Promise<void>;
|
|
20
|
+
setUnreadOnly(on: boolean): Promise<void>;
|
|
21
|
+
markRead(id: string): Promise<void>;
|
|
22
|
+
markAllRead(): Promise<void>;
|
|
23
|
+
unread(): number;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createNotificationCentre(o: {
|
|
27
|
+
client: CommunityClient;
|
|
28
|
+
}): NotificationCentreController;
|
|
@@ -10,6 +10,7 @@ import { type ShallowRef } from 'vue';
|
|
|
10
10
|
import { type CaseCategory, type CommunityClient, type CommunityFailure, type CommunityRule, type DiscussionMessage, type DiscussionState, type DiscussionStore, type MyState, type ReactionTarget, type ViewerNeeds } from '@blogmcp/sdk/community';
|
|
11
11
|
import type { Lang, TextRef } from './i18n';
|
|
12
12
|
import { type OnboardingModel } from './onboarding';
|
|
13
|
+
import type { DiscussionRealtime } from './realtime';
|
|
13
14
|
export type DiscussionPhase = 'loading' | 'ready' | 'failed' | 'hidden';
|
|
14
15
|
/** One composer's text and what happened to it. */
|
|
15
16
|
export interface Draft {
|
|
@@ -52,9 +53,13 @@ export interface ReportDraft {
|
|
|
52
53
|
* onboarding waits); `ageRefused` (the age band declared in it was below the minimum: reading only, the
|
|
53
54
|
* onboarding is not offered again); `sanction` (a restriction, suspension or ban in effect); `notMoved` (the
|
|
54
55
|
* discussion takes no writes yet — one sentence); `restricted` (the member is read-only or deleting their
|
|
55
|
-
* profile); `
|
|
56
|
+
* profile); `braked` (M2: the community is paused — `me/get`'s `module.brake`, or a write refused BRAKED: reading
|
|
57
|
+
* goes on, every member write waits — one sentence); `pending` (being decided).
|
|
58
|
+
*
|
|
59
|
+
* A module that is `read_only` changes nothing here (m2-contracts.md §3.1: the discussions under articles keep
|
|
60
|
+
* taking writes; only live updates, push and the Pro surfaces stop) — the discussion polls instead of a socket.
|
|
56
61
|
*/
|
|
57
|
-
export type ComposerMode = 'write' | 'signIn' | 'onboarding' | 'ageRefused' | 'sanction' | 'notMoved' | 'restricted' | 'pending';
|
|
62
|
+
export type ComposerMode = 'write' | 'signIn' | 'onboarding' | 'ageRefused' | 'sanction' | 'notMoved' | 'restricted' | 'braked' | 'pending';
|
|
58
63
|
export interface DiscussionUi {
|
|
59
64
|
phase: DiscussionPhase;
|
|
60
65
|
/** Why the first load failed (`failed`). */
|
|
@@ -65,8 +70,8 @@ export interface DiscussionUi {
|
|
|
65
70
|
/** A head poll saw messages the page does not show yet. */
|
|
66
71
|
newMessages: boolean;
|
|
67
72
|
me: MyState | null;
|
|
68
|
-
/** What a write or the member's state taught: no writes yet,
|
|
69
|
-
block: 'notMoved' | 'restricted' | null;
|
|
73
|
+
/** What a write or the member's state taught: no writes yet, none for this member, or a pause (BRAKED). */
|
|
74
|
+
block: 'notMoved' | 'restricted' | 'braked' | null;
|
|
70
75
|
composer: Draft;
|
|
71
76
|
inline: InlineDraft | null;
|
|
72
77
|
report: ReportDraft | null;
|
|
@@ -82,6 +87,16 @@ export interface DiscussionUi {
|
|
|
82
87
|
* (§7.4.2), so the element does: the onboarding is not offered again while it lives.
|
|
83
88
|
*/
|
|
84
89
|
refusedAge: number | null;
|
|
90
|
+
/**
|
|
91
|
+
* M2 T9: the onboarding just finished with the art. 9 consent refused (`public_write`): the composer says once,
|
|
92
|
+
* in view, what the refusal leaves (writing in the public discussion). Not kept beyond this element.
|
|
93
|
+
*/
|
|
94
|
+
art9RefusedNote: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* M2 (§3.5): the live updates' session fell back to polling (live updates are off here, or the server cut the
|
|
97
|
+
* socket for good — 4501): the discussion says so once and keeps polling; it never opens the socket again itself.
|
|
98
|
+
*/
|
|
99
|
+
realtimeOff: boolean;
|
|
85
100
|
}
|
|
86
101
|
export interface DiscussionControllerOptions {
|
|
87
102
|
client: CommunityClient;
|
|
@@ -96,6 +111,11 @@ export interface DiscussionControllerOptions {
|
|
|
96
111
|
refusedAge?: number | null;
|
|
97
112
|
/** The onboarding's age band was refused: the element keeps it for its next discussions. */
|
|
98
113
|
onAgeRefused?(minAge: number): void;
|
|
114
|
+
/**
|
|
115
|
+
* M2 (§3.5, §3.10): the host's live-updates session factory (`createRealtimeSession` of
|
|
116
|
+
* `@blogmcp/sdk/community/realtime`). Absent: the head poll, as before.
|
|
117
|
+
*/
|
|
118
|
+
realtime?: DiscussionRealtime | null;
|
|
99
119
|
}
|
|
100
120
|
export interface DiscussionController {
|
|
101
121
|
readonly state: DiscussionUi;
|
|
@@ -135,10 +155,21 @@ export interface DiscussionController {
|
|
|
135
155
|
openReport(m: DiscussionMessage): void;
|
|
136
156
|
closeReport(): void;
|
|
137
157
|
submitReport(): Promise<void>;
|
|
138
|
-
|
|
158
|
+
/**
|
|
159
|
+
* The onboarding inline; `offerArt9` asks the art. 9 consent also of a member who refused it (`public_write`, M2 T9) —
|
|
160
|
+
* the give-consent link on their own message held until the consent.
|
|
161
|
+
*/
|
|
162
|
+
beginOnboarding(options?: {
|
|
163
|
+
offerArt9?: boolean;
|
|
164
|
+
}): void;
|
|
139
165
|
cancelOnboarding(): void;
|
|
140
166
|
/** Seconds a draft still waits (0 when it may go). */
|
|
141
167
|
waitLeft(draft: Draft): number;
|
|
168
|
+
/**
|
|
169
|
+
* M2 T10: the distinct `@handle`s one message of the viewer may carry (me/get's `caps.mentionsPerMessage`), or null
|
|
170
|
+
* when nothing is known to limit it (no member yet, an older kb-api, a module whose mentions notify nobody).
|
|
171
|
+
*/
|
|
172
|
+
mentionCap(): number | null;
|
|
142
173
|
dispose(): void;
|
|
143
174
|
}
|
|
144
175
|
export declare function createDiscussionController(o: DiscussionControllerOptions): DiscussionController;
|
package/dist/core/format.d.ts
CHANGED
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
import { type Lang } from './i18n';
|
|
6
6
|
/** An ISO timestamp as a date (and time); '' for anything that is no date. */
|
|
7
7
|
export declare function formatDate(lang: Lang, iso: string | null | undefined, withTime?: boolean): string;
|
|
8
|
+
/**
|
|
9
|
+
* A month as `profile/get`'s `memberSince` gives it (`YYYY-MM`, UTC) in the reader's language, in the form a date
|
|
10
|
+
* takes inside a sentence („Členem od října 2026", "Member since October 2026"): Intl formats the first of the month
|
|
11
|
+
* and the day is left out — a month on its own would be the nominative („říjen"). The value as it came when Intl has
|
|
12
|
+
* no words, '' for anything that is no month.
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatMonth(lang: Lang, ym: string | null | undefined): string;
|
|
8
15
|
/** Whether an ISO timestamp lies in the past (an appeal window, a sanction's end). */
|
|
9
16
|
export declare function isPast(iso: string | null | undefined, now?: number): boolean;
|
|
10
17
|
/**
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import { type AgeBand, type CommunityClient, type CommunityFailure, type CommunityRule, type CurrentLegalText, type MyState } from '@blogmcp/sdk/community';
|
|
2
|
-
import type { Lang } from './i18n';
|
|
1
|
+
import { type AgeBand, type Art9ConsentLayout, type Art9Refusal, type CommunityClient, type CommunityFailure, type CommunityRule, type CurrentLegalText, type MyState } from '@blogmcp/sdk/community';
|
|
2
|
+
import type { Lang, TextRef } from './i18n';
|
|
3
3
|
export type OnboardingStep = 'age' | 'rules' | 'art9' | 'profile';
|
|
4
4
|
export type OnboardingPhase = 'loading' | 'ready' | 'sending' | 'done' | 'failed' | 'refused';
|
|
5
|
+
/** One consent of the art. 9 step: a controller the text names (or the tenant, when it names none) and its tick. */
|
|
6
|
+
export interface Art9Consent {
|
|
7
|
+
/** The controller's registry ref from the text's `bodyJson`; empty for the tenant of a text that names none. */
|
|
8
|
+
readonly entity: string;
|
|
9
|
+
/** The name the reader sees; empty for the tenant of a text that names none (the step's own sentence then). */
|
|
10
|
+
readonly label: string;
|
|
11
|
+
accepted: boolean;
|
|
12
|
+
}
|
|
5
13
|
export interface OnboardingState {
|
|
6
14
|
/** `refused`: the age band is below the minimum — nothing was stored, the reader may go on reading. */
|
|
7
15
|
phase: OnboardingPhase;
|
|
@@ -12,10 +20,24 @@ export interface OnboardingState {
|
|
|
12
20
|
rules: CommunityRule[];
|
|
13
21
|
art9Text: CurrentLegalText | null;
|
|
14
22
|
art9Paragraphs: string[];
|
|
23
|
+
/** me/get's `settings.art9ConsentLayout` (absent: `joint`). */
|
|
24
|
+
art9Layout: Art9ConsentLayout;
|
|
25
|
+
/** me/get's `settings.art9Refusal` (absent: `read_only`). */
|
|
26
|
+
art9Refusal: Art9Refusal;
|
|
27
|
+
/**
|
|
28
|
+
* The consents the step asks for, each ticked on its own: one under `joint` (or a text naming fewer than two
|
|
29
|
+
* controllers), the text's two controllers under `split`. Empty while there is no art. 9 text.
|
|
30
|
+
*/
|
|
31
|
+
art9Controllers: Art9Consent[];
|
|
32
|
+
/** The reader chose „Nesouhlasím" (only where the refusal is offered). */
|
|
33
|
+
art9Refused: boolean;
|
|
34
|
+
/** The me/onboard kb-api took carried the refusal (the done note says what it leaves). */
|
|
35
|
+
art9RefusedSent: boolean;
|
|
15
36
|
/** The member accepted an older rules text; this one asks again. */
|
|
16
37
|
reconsent: boolean;
|
|
17
38
|
ageBand: AgeBand | null;
|
|
18
39
|
rulesAccepted: boolean;
|
|
40
|
+
/** Every consent of the step ticked (setting it ticks or unticks them all). */
|
|
19
41
|
art9Accepted: boolean;
|
|
20
42
|
displayName: string;
|
|
21
43
|
handle: string;
|
|
@@ -37,6 +59,15 @@ export interface OnboardingModel {
|
|
|
37
59
|
back(): void;
|
|
38
60
|
suggestedHandle(): string | null;
|
|
39
61
|
hasFieldError(field: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* The tenant takes a refusal of the art. 9 consent here (`art9Refusal = public_write`, not the give-consent flow): the
|
|
64
|
+
* step's lede then does not make writing depend on the consent (community.md §9.8 q8, art. 9(2)(a) — freely given).
|
|
65
|
+
*/
|
|
66
|
+
refusalOffered(): boolean;
|
|
67
|
+
/** The art. 9 step offers „Nesouhlasím" (`art9Refusal = public_write`, never in the give-consent flow). */
|
|
68
|
+
canRefuse(): boolean;
|
|
69
|
+
/** „Nesouhlasím": the step is answered without the consent; the next step, or — on the last one — `me/onboard`. */
|
|
70
|
+
refuse(): Promise<void>;
|
|
40
71
|
}
|
|
41
72
|
export interface OnboardingOptions {
|
|
42
73
|
client: Pick<CommunityClient, 'me' | 'legal'>;
|
|
@@ -47,6 +78,15 @@ export interface OnboardingOptions {
|
|
|
47
78
|
onSignIn(): void;
|
|
48
79
|
/** The age band was below the tenant's minimum (AGE_BELOW_MINIMUM): kb-api kept nothing, the element keeps this. */
|
|
49
80
|
onRefused?(minAge: number): void;
|
|
81
|
+
/**
|
|
82
|
+
* The give-consent flow („Moje komunita", M2 T9): the art. 9 step is asked also when `needs` does not name it — a
|
|
83
|
+
* member who refused it, or has not given it, where the tenant asks for it — and no refusal is offered.
|
|
84
|
+
*/
|
|
85
|
+
offerArt9?: boolean;
|
|
50
86
|
signal?: AbortSignal;
|
|
51
87
|
}
|
|
88
|
+
/** kb-api's issue code for a refusal the tenant does not take (`art9Refusal = read_only`, §3.8). */
|
|
89
|
+
export declare const ART9_REFUSAL_READ_ONLY = "art9_refusal_read_only";
|
|
90
|
+
/** The sentence a refusal of the onboarding shows: a refused refusal says the consent is needed to write. */
|
|
91
|
+
export declare function onboardingFailureText(failure: Pick<CommunityFailure, 'code' | 'until' | 'fields' | 'issueCodes'>, lang: Lang): TextRef;
|
|
52
92
|
export declare function createOnboarding(o: OnboardingOptions): OnboardingModel;
|
package/dist/core/outcomes.d.ts
CHANGED
|
@@ -20,7 +20,8 @@ export declare const COUNTDOWN_MAX_S = 120;
|
|
|
20
20
|
* - `onboard` the inline onboarding opens (ONBOARDING_REQUIRED);
|
|
21
21
|
* - `reload` the discussion is read again (the viewer's state changed: a sanction, a session);
|
|
22
22
|
* - `notMoved` the discussion does not take writes yet: one sentence instead of the composer;
|
|
23
|
-
* - `hide` discussions are switched off: the element renders nothing
|
|
23
|
+
* - `hide` discussions are switched off: the element renders nothing (`realtimeOff`: only live updates are —
|
|
24
|
+
* the element keeps polling and never hides the discussion for it);
|
|
24
25
|
* - `retry` nothing was decided (no answer, the ledger): the same write may go again as it is;
|
|
25
26
|
* - `show` anything else: the sentence, the text stays for the author to change.
|
|
26
27
|
*/
|
package/dist/core/panel.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<blogmcp-my-community>`'s brain (m1-contracts.md §7.4, §8.3, §10.4; community.md §5): the reader's
|
|
3
|
+
* „Moje komunita" — the statements of reasons about their content (the art. 17(3) fields, the appeal within
|
|
4
|
+
* its window, an open appeal's state), their reports, their notifications, the art. 9 consent's withdrawal (and,
|
|
5
|
+
* M2 T9, a refused one given after all — the onboarding's art. 9 step, opened here), their blocks, the export (a JSON download) and the profile's deletion with its grace and cancel.
|
|
6
|
+
*
|
|
7
|
+
* With a decision id it shows that one statement (the host's statement page). With a notifier's receipt it
|
|
8
|
+
* shows that notice's status and appeal — `notices/status`, `notices/appeal`: no session needed for that.
|
|
9
|
+
*/
|
|
10
|
+
import { type ShallowRef } from 'vue';
|
|
1
11
|
import { type AppealItem, type BlockEntry, type CommunityClient, type CommunityFailure, type DecisionSummary, type MemberExport, type MyState, type NoticeStatus, type NotificationItem, type ReportItem, type Statement } from '@blogmcp/sdk/community';
|
|
2
|
-
import type
|
|
12
|
+
import { type TextRef } from './i18n';
|
|
13
|
+
import { type OnboardingModel } from './onboarding';
|
|
3
14
|
export type LoadPhase = 'idle' | 'loading' | 'ready' | 'failed';
|
|
4
15
|
export interface AppealDraft {
|
|
5
16
|
body: string;
|
|
@@ -48,6 +59,8 @@ export interface PanelUi {
|
|
|
48
59
|
}
|
|
49
60
|
export interface PanelController {
|
|
50
61
|
readonly state: PanelUi;
|
|
62
|
+
/** The give-consent flow (the onboarding's art. 9 step), while it is open. */
|
|
63
|
+
readonly consent: ShallowRef<OnboardingModel | null>;
|
|
51
64
|
/** The member's sections (me/get and the lists). */
|
|
52
65
|
loadMember(): Promise<void>;
|
|
53
66
|
loadStatement(decisionId: string): Promise<void>;
|
|
@@ -59,6 +72,9 @@ export interface PanelController {
|
|
|
59
72
|
fileNoticeAppeal(): Promise<void>;
|
|
60
73
|
withdrawNoticeAppeal(): Promise<void>;
|
|
61
74
|
withdrawConsent(): Promise<boolean>;
|
|
75
|
+
/** A refused art. 9 consent (`acceptances.art9Refused`): opens its step to give it after all. */
|
|
76
|
+
giveConsent(): void;
|
|
77
|
+
closeConsent(): void;
|
|
62
78
|
unblock(memberId: string): Promise<void>;
|
|
63
79
|
editProfile(): void;
|
|
64
80
|
cancelProfile(): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type CommunityClient, type CommunityFailure, type CommunityMessageKey, type CommunityRule, type KnownAuthor } from '@blogmcp/sdk/community';
|
|
2
|
+
export type LoadPhase = 'idle' | 'loading' | 'ready' | 'failed' | 'signIn' | 'notFound';
|
|
3
|
+
export interface ProfileUi {
|
|
4
|
+
phase: LoadPhase;
|
|
5
|
+
failure: CommunityFailure | null;
|
|
6
|
+
author: KnownAuthor | null;
|
|
7
|
+
memberSince: string | null;
|
|
8
|
+
bio: string | null;
|
|
9
|
+
/** The trust level's catalogue key (`trust.<n>`), or null for a label this SDK does not know. */
|
|
10
|
+
trustKey: CommunityMessageKey | null;
|
|
11
|
+
}
|
|
12
|
+
export interface ProfileController {
|
|
13
|
+
readonly state: ProfileUi;
|
|
14
|
+
load(handle: string): Promise<void>;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
/** A handle as an attribute may give it (`@jana_n`, `Jana_N`): lower case, without the `@`; null for none. */
|
|
18
|
+
export declare function handleOf(value: unknown): string | null;
|
|
19
|
+
export declare function createProfile(o: {
|
|
20
|
+
client: CommunityClient;
|
|
21
|
+
}): ProfileController;
|
|
22
|
+
export interface WelcomeUi {
|
|
23
|
+
phase: 'idle' | 'loading' | 'ready';
|
|
24
|
+
rules: CommunityRule[];
|
|
25
|
+
/** The rules could not be read: the page still links them. */
|
|
26
|
+
rulesFailed: boolean;
|
|
27
|
+
/** The signed-in member's handle (the profile link), or null for a visitor and a reader who never joined. */
|
|
28
|
+
handle: string | null;
|
|
29
|
+
/** Nobody is signed in: the sign-in link takes the profile link's place. */
|
|
30
|
+
visitor: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface WelcomeController {
|
|
33
|
+
readonly state: WelcomeUi;
|
|
34
|
+
load(): Promise<void>;
|
|
35
|
+
dispose(): void;
|
|
36
|
+
}
|
|
37
|
+
export declare function createWelcome(o: {
|
|
38
|
+
client: CommunityClient;
|
|
39
|
+
lang: string;
|
|
40
|
+
}): WelcomeController;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser's half of web push (m2-contracts.md §3.4): the one module of the elements that touches the service
|
|
3
|
+
* worker and the PushManager (test/closed-paths.spec.ts lets `serviceWorker` appear here and nowhere else).
|
|
4
|
+
*
|
|
5
|
+
* The worker is registered only from `<blogmcp-member-settings>`, on the member's click („Zapnout upozornění"),
|
|
6
|
+
* never on page load; the worker's script is the host's route (`sw-path`, default `<site-base>/sw.js`, served from
|
|
7
|
+
* `@blogmcp/sdk/community/sw`). The subscription's keys go to kb-api through the SDK client only.
|
|
8
|
+
*
|
|
9
|
+
* Feature checks read the browser's globals on call (never on import), so a server render and a test can swap them.
|
|
10
|
+
*/
|
|
11
|
+
import { type PushUserAgentClass } from '@blogmcp/sdk/community';
|
|
12
|
+
/** What the browser can do about push, in the order the settings element asks. */
|
|
13
|
+
export type PushSupport =
|
|
14
|
+
/** Facebook's or Instagram's in-app browser: „Otevřít v prohlížeči" with the page's URL instead. */
|
|
15
|
+
'inApp'
|
|
16
|
+
/** iOS outside an installed web app (`navigator.standalone !== true`): the install guide instead. */
|
|
17
|
+
| 'iosInstall'
|
|
18
|
+
/** No service worker, PushManager or Notification: one sentence. */
|
|
19
|
+
| 'unsupported' | 'supported';
|
|
20
|
+
/** The navigator as far as push reads it (Safari's `standalone` included). */
|
|
21
|
+
interface PushNavigator {
|
|
22
|
+
readonly userAgent?: string;
|
|
23
|
+
readonly platform?: string;
|
|
24
|
+
readonly maxTouchPoints?: number;
|
|
25
|
+
readonly standalone?: boolean;
|
|
26
|
+
readonly serviceWorker?: ServiceWorkerContainer;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* iOS (an iPhone, an iPod, an iPad — which reports itself as a Mac with a touch screen): its browsers take web push
|
|
30
|
+
* only from a website installed to the home screen. A layout hint, never sent anywhere but as `userAgentClass`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isIos(n?: PushNavigator | null): boolean;
|
|
33
|
+
/** What `me/push/subscribe` is told this browser is (a class, never the user agent itself). */
|
|
34
|
+
export declare function userAgentClass(n?: PushNavigator | null): PushUserAgentClass;
|
|
35
|
+
/** What this browser can do about push (the in-app browser first, then iOS outside the home screen). */
|
|
36
|
+
export declare function pushSupport(): PushSupport;
|
|
37
|
+
/** The browser's notification permission (`default` where there is no Notification API). */
|
|
38
|
+
export declare function notificationPermission(): NotificationPermission;
|
|
39
|
+
/** Ask for the permission (only on the member's click); `denied` where it cannot be asked. */
|
|
40
|
+
export declare function requestNotificationPermission(): Promise<NotificationPermission>;
|
|
41
|
+
/** The worker's registration for this page (null where none is registered or it cannot be asked). */
|
|
42
|
+
export declare function currentRegistration(): Promise<ServiceWorkerRegistration | null>;
|
|
43
|
+
/** Register the host's worker script (the member's click). Throws what the browser throws. */
|
|
44
|
+
export declare function registerWorker(swPath: string): Promise<ServiceWorkerRegistration>;
|
|
45
|
+
/** The browser's current subscription of a registration, or null. */
|
|
46
|
+
export declare function currentSubscription(reg: ServiceWorkerRegistration | null): Promise<PushSubscription | null>;
|
|
47
|
+
/** base64url (the VAPID public key `me/push/vapid` sends) → the bytes `applicationServerKey` takes; null when malformed. */
|
|
48
|
+
export declare function base64UrlBytes(value: string): Uint8Array | null;
|
|
49
|
+
/** A subscription as `me/push/subscribe` takes it (`toJSON()`'s endpoint and keys), or null when one is missing. */
|
|
50
|
+
export declare function subscriptionInput(sub: PushSubscription): {
|
|
51
|
+
endpoint: string;
|
|
52
|
+
keys: {
|
|
53
|
+
p256dh: string;
|
|
54
|
+
auth: string;
|
|
55
|
+
};
|
|
56
|
+
} | null;
|
|
57
|
+
export interface StoredPush {
|
|
58
|
+
readonly memberId: string;
|
|
59
|
+
readonly keyId: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function storedPush(): StoredPush | null;
|
|
62
|
+
export declare function storePush(value: StoredPush | null): void;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The discussion's live updates (m2-contracts.md §3.5, §3.10): `<blogmcp-discussion>` takes a `realtime` PROPERTY —
|
|
3
|
+
* the session factory of `@blogmcp/sdk/community/realtime`, which the HOST imports and passes:
|
|
4
|
+
*
|
|
5
|
+
* import { createRealtimeSession } from '@blogmcp/sdk/community/realtime'
|
|
6
|
+
* mountDiscussion({ articleId, realtime: createRealtimeSession }) // or el.realtime = createRealtimeSession
|
|
7
|
+
*
|
|
8
|
+
* The element calls it with its own client and discussion store after the first `discussions/list`, and `stop()`s
|
|
9
|
+
* the session when it unmounts. The element never imports the realtime entry (nor `centrifuge`): a site that passes no
|
|
10
|
+
* factory ships no socket code, and the discussion polls (`pollDiscussionHead`) as before.
|
|
11
|
+
*
|
|
12
|
+
* The types here are the factory's shape as far as the element uses it, so `createRealtimeSession` fits as it is.
|
|
13
|
+
*/
|
|
14
|
+
import type { CommunityClient, DiscussionStore } from '@blogmcp/sdk/community';
|
|
15
|
+
/** `connecting`, `live`, `polling` (live updates are off or the server cut the socket for good), `stopped`. */
|
|
16
|
+
export type DiscussionRealtimeMode = 'connecting' | 'live' | 'polling' | 'stopped' | (string & {});
|
|
17
|
+
/** What the element calls the factory with. */
|
|
18
|
+
export interface DiscussionRealtimeOptions {
|
|
19
|
+
client: CommunityClient;
|
|
20
|
+
store: DiscussionStore;
|
|
21
|
+
/** The discussion's language, for the session's re-reads. */
|
|
22
|
+
languageCode: string;
|
|
23
|
+
/** Whether the discussion is seen now (the fallback polls only then). */
|
|
24
|
+
visible: () => boolean;
|
|
25
|
+
/** The element's poll interval, for the session's fallback poller (absent: the SDK's default). */
|
|
26
|
+
pollIntervalMs?: number;
|
|
27
|
+
onMode: (mode: DiscussionRealtimeMode) => void;
|
|
28
|
+
}
|
|
29
|
+
/** A running session, as far as the element uses it. */
|
|
30
|
+
export interface DiscussionRealtimeSession {
|
|
31
|
+
readonly mode: DiscussionRealtimeMode;
|
|
32
|
+
stop(): void;
|
|
33
|
+
}
|
|
34
|
+
/** `createRealtimeSession` of `@blogmcp/sdk/community/realtime`, or any function of its shape. */
|
|
35
|
+
export type DiscussionRealtime = (options: DiscussionRealtimeOptions) => DiscussionRealtimeSession;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type CommunityClient, type CommunityFailure, type MemberSettings, type ModuleInfo } from '@blogmcp/sdk/community';
|
|
2
|
+
import type { TextRef } from './i18n';
|
|
3
|
+
import { type PushSupport } from './push';
|
|
4
|
+
/** The six switches, in the order the page shows them. */
|
|
5
|
+
export declare const SETTING_KEYS: readonly ["notifyReply", "notifyMention", "notifyTopic", "pushEnabled", "digestEmail", "quietHours"];
|
|
6
|
+
export type SettingKey = (typeof SETTING_KEYS)[number];
|
|
7
|
+
export type SettingsPhase = 'idle' | 'loading' | 'ready' | 'failed' | 'signIn';
|
|
8
|
+
/** This browser's push: off, on, or on its way (`busy`), and what the page tells the member about it. */
|
|
9
|
+
export interface PushUi {
|
|
10
|
+
support: PushSupport;
|
|
11
|
+
/** `checking` until the browser's own subscription was looked at. */
|
|
12
|
+
status: 'checking' | 'off' | 'on' | 'busy';
|
|
13
|
+
/** `denied` the browser's permission; `refused` kb-api's (pushRefused); `reset` switch it on again. */
|
|
14
|
+
note: 'denied' | 'refused' | 'reset' | null;
|
|
15
|
+
failure: CommunityFailure | null;
|
|
16
|
+
}
|
|
17
|
+
export interface DigestUi {
|
|
18
|
+
/** An unsubscribe link brought the member here: the button is offered. */
|
|
19
|
+
offered: boolean;
|
|
20
|
+
sending: boolean;
|
|
21
|
+
outcome: 'unsubscribed' | 'staleLink' | null;
|
|
22
|
+
failure: CommunityFailure | null;
|
|
23
|
+
}
|
|
24
|
+
export interface SettingsUi {
|
|
25
|
+
phase: SettingsPhase;
|
|
26
|
+
failure: CommunityFailure | null;
|
|
27
|
+
module: ModuleInfo | null;
|
|
28
|
+
settings: MemberSettings | null;
|
|
29
|
+
saving: Partial<Record<SettingKey, boolean>>;
|
|
30
|
+
push: PushUi;
|
|
31
|
+
digest: DigestUi;
|
|
32
|
+
announcement: TextRef | null;
|
|
33
|
+
announceId: number;
|
|
34
|
+
}
|
|
35
|
+
export interface MemberSettingsController {
|
|
36
|
+
readonly state: SettingsUi;
|
|
37
|
+
load(): Promise<void>;
|
|
38
|
+
toggle(key: SettingKey, value: boolean): Promise<void>;
|
|
39
|
+
/** Whether this browser's push block is shown (the module's feature; never for a visitor). */
|
|
40
|
+
pushShown(): boolean;
|
|
41
|
+
enablePush(): Promise<void>;
|
|
42
|
+
disablePush(): Promise<void>;
|
|
43
|
+
unsubscribeDigest(): Promise<void>;
|
|
44
|
+
dispose(): void;
|
|
45
|
+
}
|
|
46
|
+
export interface MemberSettingsOptions {
|
|
47
|
+
client: CommunityClient;
|
|
48
|
+
/** The host's worker script (`<site-base>/sw.js`). */
|
|
49
|
+
swPath: string;
|
|
50
|
+
/** The digest's unsubscribe token this page's address carried (read and cleared by the element), or null. */
|
|
51
|
+
digestToken: string | null;
|
|
52
|
+
}
|
|
53
|
+
export declare function createMemberSettings(o: MemberSettingsOptions): MemberSettingsController;
|
package/dist/core/text.d.ts
CHANGED
|
@@ -5,11 +5,24 @@ export type TextSegment = {
|
|
|
5
5
|
readonly kind: 'link';
|
|
6
6
|
readonly text: string;
|
|
7
7
|
readonly href: string;
|
|
8
|
+
}
|
|
9
|
+
/** M2: an `@handle` with the link to the member's profile page on the host's own site (never a member's URL). */
|
|
10
|
+
| {
|
|
11
|
+
readonly kind: 'mention';
|
|
12
|
+
readonly text: string;
|
|
13
|
+
readonly href: string;
|
|
8
14
|
};
|
|
9
15
|
/** The rel every link to what a member wrote carries (user-generated, no referrer, no opener). */
|
|
10
16
|
export declare const UGC_LINK_REL = "nofollow ugc noopener noreferrer";
|
|
11
17
|
/** A member's text as text runs and links. */
|
|
12
18
|
export declare function linkify(text: string): TextSegment[];
|
|
19
|
+
/**
|
|
20
|
+
* A member's text as text runs, web-address links and `@handle` mentions (m2-contracts.md §3.3: „the element renders
|
|
21
|
+
* `@handle` as text with a link to `/u/{handle}`"). The mentions are the SDK's (kb-api's token rule), found only in the
|
|
22
|
+
* text between addresses — an address's `/@x` stays part of its link; `profileHref` builds the host's profile page
|
|
23
|
+
* (profilePath) and a handle it gives no page for stays text. Joining every segment's `text` gives the body back.
|
|
24
|
+
*/
|
|
25
|
+
export declare function linkifyWithMentions(text: string, profileHref: ((handle: string) => string | null) | null): TextSegment[];
|
|
13
26
|
/** Characters in code points, as kb-api counts a body (after NFC and trimming). */
|
|
14
27
|
export declare function codePointLength(text: string): number;
|
|
15
28
|
/** A body as kb-api will measure it: NFC, trimmed. */
|
package/dist/element.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export declare const DISCUSSION_ELEMENT_TAG = "blogmcp-discussion";
|
|
2
2
|
export declare const NOTICE_FORM_ELEMENT_TAG = "blogmcp-notice-form";
|
|
3
3
|
export declare const MY_COMMUNITY_ELEMENT_TAG = "blogmcp-my-community";
|
|
4
|
+
/** M2 (m2-contracts.md §3.10). */
|
|
5
|
+
export declare const NOTIFICATION_CENTRE_ELEMENT_TAG = "blogmcp-notification-centre";
|
|
6
|
+
export declare const BADGE_ELEMENT_TAG = "blogmcp-badge";
|
|
7
|
+
export declare const MEMBER_SETTINGS_ELEMENT_TAG = "blogmcp-member-settings";
|
|
8
|
+
export declare const PROFILE_ELEMENT_TAG = "blogmcp-profile";
|
|
9
|
+
export declare const WELCOME_ELEMENT_TAG = "blogmcp-welcome";
|
|
4
10
|
export interface DefineCommunityElementOptions {
|
|
5
11
|
/** Another tag name for the element. */
|
|
6
12
|
tag?: string;
|
|
@@ -14,6 +20,11 @@ export interface DefineCommunityElementsOptions {
|
|
|
14
20
|
discussion?: string;
|
|
15
21
|
noticeForm?: string;
|
|
16
22
|
myCommunity?: string;
|
|
23
|
+
notificationCentre?: string;
|
|
24
|
+
badge?: string;
|
|
25
|
+
memberSettings?: string;
|
|
26
|
+
profile?: string;
|
|
27
|
+
welcome?: string;
|
|
17
28
|
};
|
|
18
29
|
}
|
|
19
30
|
/** Register `<blogmcp-discussion>` (once; later calls are no-ops). Browser only. */
|
|
@@ -22,5 +33,15 @@ export declare function defineDiscussionElement(opts?: DefineCommunityElementOpt
|
|
|
22
33
|
export declare function defineNoticeFormElement(opts?: DefineCommunityElementOptions): void;
|
|
23
34
|
/** Register `<blogmcp-my-community>` (once). Browser only. */
|
|
24
35
|
export declare function defineMyCommunityElement(opts?: DefineCommunityElementOptions): void;
|
|
25
|
-
/** Register
|
|
36
|
+
/** Register `<blogmcp-notification-centre>` (once). Browser only. */
|
|
37
|
+
export declare function defineNotificationCentreElement(opts?: DefineCommunityElementOptions): void;
|
|
38
|
+
/** Register `<blogmcp-badge>` (once). Browser only. */
|
|
39
|
+
export declare function defineBadgeElement(opts?: DefineCommunityElementOptions): void;
|
|
40
|
+
/** Register `<blogmcp-member-settings>` (once). Browser only. */
|
|
41
|
+
export declare function defineMemberSettingsElement(opts?: DefineCommunityElementOptions): void;
|
|
42
|
+
/** Register `<blogmcp-profile>` (once). Browser only. */
|
|
43
|
+
export declare function defineProfileElement(opts?: DefineCommunityElementOptions): void;
|
|
44
|
+
/** Register `<blogmcp-welcome>` (once). Browser only. */
|
|
45
|
+
export declare function defineWelcomeElement(opts?: DefineCommunityElementOptions): void;
|
|
46
|
+
/** Register all eight (once). Browser only. */
|
|
26
47
|
export declare function defineCommunityElements(opts?: DefineCommunityElementsOptions): void;
|
package/dist/global.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `<script>` build: registers `<blogmcp-discussion>`, `<blogmcp-notice-form
|
|
3
|
-
*
|
|
2
|
+
* The `<script>` build: registers every element — `<blogmcp-discussion>`, `<blogmcp-notice-form>`,
|
|
3
|
+
* `<blogmcp-my-community>` and (M2) `<blogmcp-notification-centre>`, `<blogmcp-badge>`, `<blogmcp-member-settings>`,
|
|
4
|
+
* `<blogmcp-profile>`, `<blogmcp-welcome>` — with the script tag's own CSP nonce, and exposes
|
|
5
|
+
* `window.BlogmcpCommunity`. Live updates are not in it: a site that wants them bundles `@blogmcp/sdk/community/realtime`
|
|
6
|
+
* and sets the discussion's `realtime` property.
|
|
4
7
|
*/
|
|
5
8
|
import { defineCommunityElements } from './element';
|
|
6
|
-
import { mountDiscussion, mountMyCommunity, mountNoticeForm } from './mount';
|
|
9
|
+
import { mountBadge, mountDiscussion, mountMemberSettings, mountMyCommunity, mountNoticeForm, mountNotificationCentre, mountProfile, mountWelcome } from './mount';
|
|
7
10
|
import { VERSION } from './version';
|
|
8
|
-
export { defineCommunityElements, mountDiscussion, mountMyCommunity, mountNoticeForm, VERSION };
|
|
11
|
+
export { defineCommunityElements, mountDiscussion, mountMyCommunity, mountNoticeForm, mountNotificationCentre, mountBadge, mountMemberSettings, mountProfile, mountWelcome, VERSION, };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,13 +7,21 @@
|
|
|
7
7
|
* - `<blogmcp-discussion>` the discussion under an article;
|
|
8
8
|
* - `<blogmcp-notice-form>` the DSA notice form, for anyone;
|
|
9
9
|
* - `<blogmcp-my-community>` the reader's „Moje komunita", a statement page, a notifier's status page;
|
|
10
|
+
* - M2: `<blogmcp-notification-centre>` the notifications, `<blogmcp-badge>` the header's unread count,
|
|
11
|
+
* `<blogmcp-member-settings>` the switches, push and the digest's unsubscribe, `<blogmcp-profile>` a member's
|
|
12
|
+
* public profile, `<blogmcp-welcome>` the welcome page; the discussion's `realtime` property (live updates);
|
|
10
13
|
* - `defineCommunityElements()` and one `define…Element()` each — the custom elements;
|
|
11
14
|
* - `mountDiscussion(…)`, `mountNoticeForm(…)`, `mountMyCommunity(…)` — mount one from code;
|
|
12
15
|
* - `@blogmcp/community/vue`, `@blogmcp/community/react` — `<KbDiscussion>`, `<KbNoticeForm>`, `<KbMyCommunity>`;
|
|
13
16
|
* - `@blogmcp/community/global` — one `<script>` for sites without a bundler.
|
|
14
17
|
*/
|
|
15
|
-
export { defineCommunityElements, defineDiscussionElement, defineNoticeFormElement, defineMyCommunityElement, DISCUSSION_ELEMENT_TAG, NOTICE_FORM_ELEMENT_TAG, MY_COMMUNITY_ELEMENT_TAG, type DefineCommunityElementOptions, type DefineCommunityElementsOptions, } from './element';
|
|
16
|
-
export { mountDiscussion, mountNoticeForm, mountMyCommunity, type MountDiscussionOptions, type MountNoticeFormOptions, type MountMyCommunityOptions } from './mount';
|
|
18
|
+
export { defineCommunityElements, defineDiscussionElement, defineNoticeFormElement, defineMyCommunityElement, defineNotificationCentreElement, defineBadgeElement, defineMemberSettingsElement, defineProfileElement, defineWelcomeElement, DISCUSSION_ELEMENT_TAG, NOTICE_FORM_ELEMENT_TAG, MY_COMMUNITY_ELEMENT_TAG, NOTIFICATION_CENTRE_ELEMENT_TAG, BADGE_ELEMENT_TAG, MEMBER_SETTINGS_ELEMENT_TAG, PROFILE_ELEMENT_TAG, WELCOME_ELEMENT_TAG, type DefineCommunityElementOptions, type DefineCommunityElementsOptions, } from './element';
|
|
19
|
+
export { mountDiscussion, mountNoticeForm, mountMyCommunity, mountNotificationCentre, mountBadge, mountMemberSettings, mountProfile, mountWelcome, type MountDiscussionOptions, type MountNoticeFormOptions, type MountMyCommunityOptions, type MountNotificationCentreOptions, type MountBadgeOptions, type MountMemberSettingsOptions, type MountProfileOptions, type MountWelcomeOptions, } from './mount';
|
|
20
|
+
export { createNotificationCentre, type NotificationCentreController, type CentreUi } from './core/centre';
|
|
21
|
+
export { createBadge, badgeText, BADGE_INTERVAL_MS, type BadgeController, type BadgeOptions, type BadgeUi } from './core/badge';
|
|
22
|
+
export { createMemberSettings, SETTING_KEYS, type MemberSettingsController, type MemberSettingsOptions, type SettingsUi, type SettingKey } from './core/settings';
|
|
23
|
+
export { createProfile, createWelcome, type ProfileController, type WelcomeController } from './core/profile';
|
|
24
|
+
export type { DiscussionRealtime, DiscussionRealtimeOptions, DiscussionRealtimeSession, DiscussionRealtimeMode } from './core/realtime';
|
|
17
25
|
export { createDiscussionController, type DiscussionController, type DiscussionControllerOptions, type DiscussionUi, type ComposerMode, type Draft } from './core/discussion';
|
|
18
26
|
export { createNoticeForm, type NoticeFormController, type NoticeFormOptions, type NoticeFormUi } from './core/notice';
|
|
19
27
|
export { createPanel, type PanelController, type PanelOptions, type PanelUi } from './core/panel';
|