@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
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* `<blogmcp-profile handle>`: a member's public profile (m2-contracts.md §3.2, §3.10) — the name and avatar, since
|
|
4
|
+
* when they are a member (a month), the bio as text, and the trust level as its label („Nový člen" … „Moderátor"),
|
|
5
|
+
* never its number. An unknown handle reads one line; a visitor gets the sign-in sentence (profiles are for signed-in
|
|
6
|
+
* readers, kb-api's rule).
|
|
7
|
+
*/
|
|
8
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
9
|
+
import { signInLink, type CommunityTransport } from '@blogmcp/sdk/community'
|
|
10
|
+
import { communityClientFor, siteBaseFor } from '../core/client'
|
|
11
|
+
import { formatMonth } from '../core/format'
|
|
12
|
+
import { documentLang, pickLang, type Lang } from '../core/i18n'
|
|
13
|
+
import { failureText } from '../core/outcomes'
|
|
14
|
+
import { createProfile, type ProfileController } from '../core/profile'
|
|
15
|
+
import AuthorAvatar from './AuthorAvatar.vue'
|
|
16
|
+
import { provideText, uid } from './context'
|
|
17
|
+
|
|
18
|
+
defineOptions({ inheritAttrs: false })
|
|
19
|
+
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
/** The member's handle (`jana_n`, an `@` in front is fine). */
|
|
22
|
+
handle?: string
|
|
23
|
+
apiBase?: string
|
|
24
|
+
siteBase?: string
|
|
25
|
+
lang?: string
|
|
26
|
+
routes?: string | Record<string, unknown>
|
|
27
|
+
signInHref?: string
|
|
28
|
+
transport?: CommunityTransport
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const lang = ref<Lang>(pickLang(props.lang, documentLang()))
|
|
32
|
+
const { t } = provideText(lang)
|
|
33
|
+
const id = uid('bcm-profile')
|
|
34
|
+
|
|
35
|
+
const siteBase = siteBaseFor(props.siteBase)
|
|
36
|
+
const client = siteBase === null ? null : communityClientFor(props.apiBase, props.transport, siteBase)
|
|
37
|
+
const ctl: ProfileController | null = client ? createProfile({ client }) : null
|
|
38
|
+
const state = ctl?.state ?? null
|
|
39
|
+
|
|
40
|
+
onMounted(() => void ctl?.load(props.handle ?? ''))
|
|
41
|
+
// A host that reuses the element for another member (client-side navigation) reads that one.
|
|
42
|
+
watch(
|
|
43
|
+
() => props.handle,
|
|
44
|
+
(next, before) => {
|
|
45
|
+
if (next !== before) void ctl?.load(next ?? '')
|
|
46
|
+
},
|
|
47
|
+
)
|
|
48
|
+
onBeforeUnmount(() => ctl?.dispose())
|
|
49
|
+
|
|
50
|
+
const since = computed(() => (state?.memberSince ? formatMonth(lang.value, state.memberSince) : ''))
|
|
51
|
+
const failure = computed(() => {
|
|
52
|
+
const f = state?.failure
|
|
53
|
+
if (!f) return ''
|
|
54
|
+
const r = failureText(f, lang.value)
|
|
55
|
+
return t(r.key, r.params)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
function signInHref(): string | null {
|
|
59
|
+
return signInLink(props.signInHref, typeof location === 'undefined' ? null : location.pathname)
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<section v-if="ctl && state" class="bcm bcm-profile" :lang="lang" :aria-labelledby="`${id}-title`">
|
|
65
|
+
<p v-if="state.phase === 'loading' || state.phase === 'idle'" class="bcm-muted" role="status">{{ t('common.loading') }}</p>
|
|
66
|
+
<p v-else-if="state.phase === 'notFound'" :id="`${id}-title`" class="bcm-note">{{ t('profile.notFound') }}</p>
|
|
67
|
+
<div v-else-if="state.phase === 'signIn'" class="bcm-row">
|
|
68
|
+
<p :id="`${id}-title`">{{ t('profile.signIn') }}</p>
|
|
69
|
+
<a v-if="signInHref()" class="bcm-btn bcm-primary" :href="signInHref() ?? undefined">{{ t('common.signIn') }}</a>
|
|
70
|
+
</div>
|
|
71
|
+
<div v-else-if="state.phase === 'failed'" class="bcm-banner" role="alert">
|
|
72
|
+
<span :id="`${id}-title`">{{ failure }}</span>
|
|
73
|
+
<button type="button" class="bcm-btn" @click="ctl.load(props.handle ?? '')">{{ t('common.retry') }}</button>
|
|
74
|
+
</div>
|
|
75
|
+
<template v-else-if="state.author && state.author.kind === 'member'">
|
|
76
|
+
<header class="bcm-profile-head">
|
|
77
|
+
<AuthorAvatar :author="state.author" />
|
|
78
|
+
<div class="bcm-msg-main">
|
|
79
|
+
<h2 :id="`${id}-title`">{{ state.author.displayName }}</h2>
|
|
80
|
+
<span class="bcm-handle">{{ state.author.handle }}</span>
|
|
81
|
+
</div>
|
|
82
|
+
</header>
|
|
83
|
+
<p v-if="state.trustKey"><span class="bcm-badge">{{ t(state.trustKey) }}</span></p>
|
|
84
|
+
<p v-if="since" class="bcm-muted">{{ t('profile.memberSince', { date: since }) }}</p>
|
|
85
|
+
<section v-if="state.bio" class="bcm-section" :aria-labelledby="`${id}-bio`">
|
|
86
|
+
<h3 :id="`${id}-bio`">{{ t('profile.bio') }}</h3>
|
|
87
|
+
<p class="bcm-text">{{ state.bio }}</p>
|
|
88
|
+
</section>
|
|
89
|
+
</template>
|
|
90
|
+
</section>
|
|
91
|
+
</template>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* `<blogmcp-welcome>`: the welcome page after joining (m2-contracts.md §3.10; the storefront's `/komunita/vitejte`) —
|
|
4
|
+
* the tenant's rules in summary (as the onboarding shows them, with the link to the rules page) and three links: the
|
|
5
|
+
* discussions, the settings, the member's own profile. A visitor gets the sign-in link in the profile's place.
|
|
6
|
+
*/
|
|
7
|
+
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
|
8
|
+
import { profilePath, signInLink, type CommunityTransport } from '@blogmcp/sdk/community'
|
|
9
|
+
import { parseRoutes, routesWithDefaults } from '../core/attrs'
|
|
10
|
+
import { communityClientFor, siteBaseFor } from '../core/client'
|
|
11
|
+
import { documentLang, pickLang, type Lang } from '../core/i18n'
|
|
12
|
+
import { createWelcome, type WelcomeController } from '../core/profile'
|
|
13
|
+
import { provideText, uid } from './context'
|
|
14
|
+
|
|
15
|
+
defineOptions({ inheritAttrs: false })
|
|
16
|
+
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
apiBase?: string
|
|
19
|
+
siteBase?: string
|
|
20
|
+
lang?: string
|
|
21
|
+
/** JSON (or an object): `rulesPath`, `discussionsPath`, `settingsPath`, `profilePath`. */
|
|
22
|
+
routes?: string | Record<string, unknown>
|
|
23
|
+
signInHref?: string
|
|
24
|
+
transport?: CommunityTransport
|
|
25
|
+
}>()
|
|
26
|
+
|
|
27
|
+
const lang = ref<Lang>(pickLang(props.lang, documentLang()))
|
|
28
|
+
const { t } = provideText(lang)
|
|
29
|
+
const id = uid('bcm-welcome')
|
|
30
|
+
|
|
31
|
+
const siteBase = siteBaseFor(props.siteBase)
|
|
32
|
+
const client = siteBase === null ? null : communityClientFor(props.apiBase, props.transport, siteBase)
|
|
33
|
+
const ctl: WelcomeController | null = client ? createWelcome({ client, lang: lang.value }) : null
|
|
34
|
+
const state = ctl?.state ?? null
|
|
35
|
+
const routes = computed(() => routesWithDefaults(parseRoutes(props.routes), null, siteBase ?? ''))
|
|
36
|
+
const ownProfile = computed(() => (state?.handle ? profilePath(routes.value.profilePath, state.handle) : null))
|
|
37
|
+
|
|
38
|
+
onMounted(() => void ctl?.load())
|
|
39
|
+
onBeforeUnmount(() => ctl?.dispose())
|
|
40
|
+
|
|
41
|
+
function signInHref(): string | null {
|
|
42
|
+
return signInLink(props.signInHref, typeof location === 'undefined' ? null : location.pathname)
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<template>
|
|
47
|
+
<section v-if="ctl && state" class="bcm bcm-welcome" :lang="lang" :aria-labelledby="`${id}-title`">
|
|
48
|
+
<h2 :id="`${id}-title`">{{ t('welcome.title') }}</h2>
|
|
49
|
+
<p>{{ t('welcome.lede') }}</p>
|
|
50
|
+
|
|
51
|
+
<p v-if="state.phase !== 'ready'" class="bcm-muted" role="status">{{ t('common.loading') }}</p>
|
|
52
|
+
<template v-else>
|
|
53
|
+
<section class="bcm-section" :aria-labelledby="`${id}-rules`">
|
|
54
|
+
<h3 :id="`${id}-rules`">{{ t('welcome.rules') }}</h3>
|
|
55
|
+
<ol v-if="state.rules.length" class="bcm-rules">
|
|
56
|
+
<li v-for="rule in state.rules" :key="rule.id">
|
|
57
|
+
<strong>{{ rule.title }}</strong>
|
|
58
|
+
<span v-if="rule.summary" class="bcm-hint">{{ rule.summary }}</span>
|
|
59
|
+
</li>
|
|
60
|
+
</ol>
|
|
61
|
+
<p><a :href="routes.rulesPath">{{ t('onboarding.rulesLink') }}</a></p>
|
|
62
|
+
</section>
|
|
63
|
+
|
|
64
|
+
<ul class="bcm-links">
|
|
65
|
+
<li><a class="bcm-btn" :href="routes.discussionsPath">{{ t('welcome.discussions') }}</a></li>
|
|
66
|
+
<li><a class="bcm-btn" :href="routes.settingsPath">{{ t('welcome.settings') }}</a></li>
|
|
67
|
+
<li v-if="ownProfile"><a class="bcm-btn" :href="ownProfile">{{ t('welcome.profile') }}</a></li>
|
|
68
|
+
<li v-else-if="state.visitor && signInHref()"><a class="bcm-btn bcm-primary" :href="signInHref() ?? undefined">{{ t('common.signIn') }}</a></li>
|
|
69
|
+
</ul>
|
|
70
|
+
</template>
|
|
71
|
+
</section>
|
|
72
|
+
</template>
|
package/src/ui/styles.css
CHANGED
|
@@ -220,6 +220,22 @@ span.bcm-react { cursor: default; }
|
|
|
220
220
|
.bcm-receipt { display: flex; flex-direction: column; gap: 8px; }
|
|
221
221
|
.bcm-turnstile { min-height: 0; }
|
|
222
222
|
|
|
223
|
+
/* ── M2: mentions, the badge, the centre, settings, profiles, the welcome page ── */
|
|
224
|
+
.bcm-mention { color: var(--bcm-accent); font-weight: 600; text-decoration: none; }
|
|
225
|
+
.bcm-mention:hover { text-decoration: underline; }
|
|
226
|
+
:host(blogmcp-badge) { display: inline-block; }
|
|
227
|
+
.bcm-badge-link {
|
|
228
|
+
display: inline-flex; align-items: center; justify-content: center; min-width: 1.5em; height: 1.5em; padding: 0 6px;
|
|
229
|
+
border-radius: 999px; background: var(--bcm-accent); color: var(--bcm-accent-fg); font-size: 0.8125em; font-weight: 700;
|
|
230
|
+
line-height: 1; text-decoration: none; font-variant-numeric: tabular-nums;
|
|
231
|
+
}
|
|
232
|
+
.bcm-switches { list-style: none; display: flex; flex-direction: column; gap: 10px; }
|
|
233
|
+
.bcm-switches li { display: flex; flex-direction: column; gap: 2px; }
|
|
234
|
+
.bcm-profile-head { display: flex; align-items: center; gap: 12px; }
|
|
235
|
+
.bcm-profile-head .bcm-avatar { width: 48px; height: 48px; font-size: 26px; }
|
|
236
|
+
.bcm-links { list-style: none; display: flex; flex-direction: column; gap: 8px; }
|
|
237
|
+
.bcm-url { overflow-wrap: anywhere; font-family: ui-monospace, monospace; font-size: 0.875em; }
|
|
238
|
+
|
|
223
239
|
/* ── dialogs (native <dialog>: the top layer, Esc, focus kept inside) ── */
|
|
224
240
|
.bcm-dialog {
|
|
225
241
|
border: 1px solid var(--bcm-line); border-radius: 14px; padding: 0;
|
package/src/vue.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `<KbDiscussion>`, `<KbNoticeForm>`, `<KbMyCommunity>`
|
|
2
|
+
* `<KbDiscussion>`, `<KbNoticeForm>`, `<KbMyCommunity>` and (M2) `<KbNotificationCentre>`, `<KbBadge>`,
|
|
3
|
+
* `<KbMemberSettings>`, `<KbProfile>`, `<KbWelcome>` for Vue / Nuxt: each mounts its element on the
|
|
3
4
|
* client, after hydration, and removes it on unmount. Each renders one empty `<div>` as the mount point —
|
|
4
5
|
* nothing else, on the server or the client — so the element sits where the component does and the page's
|
|
5
6
|
* markup is otherwise the site's alone.
|
|
@@ -12,7 +13,17 @@
|
|
|
12
13
|
import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch, type PropType } from 'vue'
|
|
13
14
|
import type { CommunityTransport } from '@blogmcp/sdk/community'
|
|
14
15
|
import type { CommunityRoutes } from './core/attrs'
|
|
15
|
-
import type {
|
|
16
|
+
import type { DiscussionRealtime } from './core/realtime'
|
|
17
|
+
import type {
|
|
18
|
+
MountBadgeOptions,
|
|
19
|
+
MountDiscussionOptions,
|
|
20
|
+
MountMemberSettingsOptions,
|
|
21
|
+
MountMyCommunityOptions,
|
|
22
|
+
MountNoticeFormOptions,
|
|
23
|
+
MountNotificationCentreOptions,
|
|
24
|
+
MountProfileOptions,
|
|
25
|
+
MountWelcomeOptions,
|
|
26
|
+
} from './mount'
|
|
16
27
|
|
|
17
28
|
type Mounter<O> = (o: O & { container: Element }) => () => void
|
|
18
29
|
|
|
@@ -60,6 +71,8 @@ export const KbDiscussion = defineComponent({
|
|
|
60
71
|
pollMs: Number,
|
|
61
72
|
nonce: String,
|
|
62
73
|
transport: Function as PropType<CommunityTransport>,
|
|
74
|
+
/** M2: `createRealtimeSession` of `@blogmcp/sdk/community/realtime`. */
|
|
75
|
+
realtime: Function as PropType<DiscussionRealtime>,
|
|
63
76
|
},
|
|
64
77
|
setup(props) {
|
|
65
78
|
return useMount<MountDiscussionOptions>(
|
|
@@ -113,4 +126,117 @@ export const KbMyCommunity = defineComponent({
|
|
|
113
126
|
},
|
|
114
127
|
})
|
|
115
128
|
|
|
116
|
-
export
|
|
129
|
+
export const KbNotificationCentre = defineComponent({
|
|
130
|
+
name: 'KbNotificationCentre',
|
|
131
|
+
props: {
|
|
132
|
+
apiBase: String,
|
|
133
|
+
siteBase: String,
|
|
134
|
+
lang: String,
|
|
135
|
+
signInHref: String,
|
|
136
|
+
routes: Object as PropType<CommunityRoutes>,
|
|
137
|
+
nonce: String,
|
|
138
|
+
transport: Function as PropType<CommunityTransport>,
|
|
139
|
+
},
|
|
140
|
+
setup(props) {
|
|
141
|
+
return useMount<MountNotificationCentreOptions>(
|
|
142
|
+
'notification-centre',
|
|
143
|
+
() => defined({ ...props }) as MountNotificationCentreOptions,
|
|
144
|
+
async () => (await import('./mount')).mountNotificationCentre as Mounter<MountNotificationCentreOptions>,
|
|
145
|
+
)
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
export const KbBadge = defineComponent({
|
|
150
|
+
name: 'KbBadge',
|
|
151
|
+
props: {
|
|
152
|
+
apiBase: String,
|
|
153
|
+
siteBase: String,
|
|
154
|
+
lang: String,
|
|
155
|
+
routes: Object as PropType<CommunityRoutes>,
|
|
156
|
+
pollMs: Number,
|
|
157
|
+
nonce: String,
|
|
158
|
+
transport: Function as PropType<CommunityTransport>,
|
|
159
|
+
},
|
|
160
|
+
setup(props) {
|
|
161
|
+
return useMount<MountBadgeOptions>(
|
|
162
|
+
'badge',
|
|
163
|
+
() => defined({ ...props }) as MountBadgeOptions,
|
|
164
|
+
async () => (await import('./mount')).mountBadge as Mounter<MountBadgeOptions>,
|
|
165
|
+
)
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
export const KbMemberSettings = defineComponent({
|
|
170
|
+
name: 'KbMemberSettings',
|
|
171
|
+
props: {
|
|
172
|
+
apiBase: String,
|
|
173
|
+
siteBase: String,
|
|
174
|
+
lang: String,
|
|
175
|
+
swPath: String,
|
|
176
|
+
signInHref: String,
|
|
177
|
+
routes: Object as PropType<CommunityRoutes>,
|
|
178
|
+
nonce: String,
|
|
179
|
+
transport: Function as PropType<CommunityTransport>,
|
|
180
|
+
},
|
|
181
|
+
setup(props) {
|
|
182
|
+
return useMount<MountMemberSettingsOptions>(
|
|
183
|
+
'member-settings',
|
|
184
|
+
() => defined({ ...props }) as MountMemberSettingsOptions,
|
|
185
|
+
async () => (await import('./mount')).mountMemberSettings as Mounter<MountMemberSettingsOptions>,
|
|
186
|
+
)
|
|
187
|
+
},
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
export const KbProfile = defineComponent({
|
|
191
|
+
name: 'KbProfile',
|
|
192
|
+
props: {
|
|
193
|
+
handle: { type: String, required: true },
|
|
194
|
+
apiBase: String,
|
|
195
|
+
siteBase: String,
|
|
196
|
+
lang: String,
|
|
197
|
+
signInHref: String,
|
|
198
|
+
routes: Object as PropType<CommunityRoutes>,
|
|
199
|
+
nonce: String,
|
|
200
|
+
transport: Function as PropType<CommunityTransport>,
|
|
201
|
+
},
|
|
202
|
+
setup(props) {
|
|
203
|
+
return useMount<MountProfileOptions>(
|
|
204
|
+
'profile',
|
|
205
|
+
() => defined({ ...props }) as MountProfileOptions,
|
|
206
|
+
async () => (await import('./mount')).mountProfile as Mounter<MountProfileOptions>,
|
|
207
|
+
)
|
|
208
|
+
},
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
export const KbWelcome = defineComponent({
|
|
212
|
+
name: 'KbWelcome',
|
|
213
|
+
props: {
|
|
214
|
+
apiBase: String,
|
|
215
|
+
siteBase: String,
|
|
216
|
+
lang: String,
|
|
217
|
+
signInHref: String,
|
|
218
|
+
routes: Object as PropType<CommunityRoutes>,
|
|
219
|
+
nonce: String,
|
|
220
|
+
transport: Function as PropType<CommunityTransport>,
|
|
221
|
+
},
|
|
222
|
+
setup(props) {
|
|
223
|
+
return useMount<MountWelcomeOptions>(
|
|
224
|
+
'welcome',
|
|
225
|
+
() => defined({ ...props }) as MountWelcomeOptions,
|
|
226
|
+
async () => (await import('./mount')).mountWelcome as Mounter<MountWelcomeOptions>,
|
|
227
|
+
)
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
export type {
|
|
232
|
+
MountDiscussionOptions,
|
|
233
|
+
MountNoticeFormOptions,
|
|
234
|
+
MountMyCommunityOptions,
|
|
235
|
+
MountNotificationCentreOptions,
|
|
236
|
+
MountBadgeOptions,
|
|
237
|
+
MountMemberSettingsOptions,
|
|
238
|
+
MountProfileOptions,
|
|
239
|
+
MountWelcomeOptions,
|
|
240
|
+
CommunityRoutes,
|
|
241
|
+
DiscussionRealtime,
|
|
242
|
+
}
|