[[vue-mention]]を使って実装してみる。
## インストール
```console
$ bun add vue-mention@next floating-vue
warn: incorrect peer dependency "
[email protected]"
installed
[email protected]
installed
[email protected]
```
若干依存関係のズレが気になるが一旦続ける。
`main.ts`などに追加。
```ts
import 'floating-vue/dist/style.css'
```
import文を書くがエラーになる。
```ts
import { Mentionable } from "vue-mention";
```
## floating-vueのバージョンを変更
[[vue-mention]]の[[peer dependencies]]を確認すると、[[floating-vue]]のバージョンは2系になっている。
```json
"peerDependencies": {
"floating-vue": "^2.0.0-beta.1",
"vue": "^3.2"
},
```
実際のバージョンは遥か先の5.2.2。それは動かない。
> installed
[email protected]
バージョン指定して入れなおしてみる。
```console
bun add floating-vue@2
```
変わらず...
```error
Could not find a declaration file for module 'vue-mention'. '/home/tadashi-aikawa/git/github.com/tadashi-aikawa/fenice/node_modules/vue-mention/dist/vue-mention.es.js' implicitly has an 'any' type.
There are types at '/home/tadashi-aikawa/git/github.com/tadashi-aikawa/fenice/node_modules/vue-mention/dist/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'vue-mention' library may need to update its package.json or typings.
```
## @ts-expect-errorで無理やり回避する
[[vue-mention]]の`package.json`で`types`を追加すればエラーは回避できる。
```diff
"exports": {
".": {
"import": "./dist/vue-mention.es.js",
"require": "./dist/vue-mention.umd.js",
+ "types": "./dist/index.d.ts"
}
},
```
...が、これは微妙な方法なので[[@ts-expect-errorコメント]]で回避する。
```ts
// @ts-expect-error
import { Mentionable } from "vue-mention";
```
## 補完が表示されない undefined?
```ts
const members = ["ichiro", "jiro"]
```
以下のようにしてもうまく補完が表示されない。
```html
<Mentionable :keys="['@']" :items="members" offset="6">
<v-textarea
v-model="text"
style="width: 640px"
:rows="12"
@paste="handlePaste"
@keyup.ctrl.enter.exact="postMessage"
@keyup.meta.enter.exact="postMessage"
/>
</Mentionable>
```
同じ事象のIssueを発見したが、反応されてなさそう。。
<div class="link-card">
<div class="link-card-header">
<img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/>
<span class="link-card-site-name">GitHub</span>
</div>
<div class="link-card-body">
<div class="link-card-content">
<p class="link-card-title">Got @undefined in Vue3 · Issue #96 · Akryum/vue-mention</p>
<p class="link-card-description">Hi, I tried to add this on our project using Nuxt3. "vue-mention": "^2.0.0-alpha.3" and "floating-vue": "^2.0.0-beta.24", When I select ... </p>
</div>
<img src="https://opengraph.githubassets.com/1710c555d5afb2881d0902b17fc2b392b6606c20a28050a961d92f69e6e73ddc/Akryum/vue-mention/issues/96" class="link-card-image" />
</div>
<a href="https://github.com/Akryum/vue-mention/issues/96"></a>
</div>
よくよく確認したら `items` の値が間違ってた。`string[]`ではなく`{label: string, name: string}[]`だった。
## styleが適応されない
別途styleを設定する必要がありそう。[[Scoped CSS]]は使えなそうなので`main.css`に。
```css
/* v-mention */
.v-popper__popper .mention-item {
padding: 4px 10px;
border-radius: 4px;
}
.v-popper__popper .mention-selected {
color: white;
background: rgb(var(--v-theme-primary));
}
```
## 候補の見た目を変更する
テキストだけではなく画像も入れたい。`v-slot:item`を追加すればOK。
```html
<Mentionable :keys="['@']" :items="userSuggestions" offset="6">
<v-textarea
v-model="text"
style="width: 640px"
:rows="12"
@paste="handlePaste"
@keyup.ctrl.enter.exact="postMessage"
@keyup.meta.enter.exact="postMessage"
/>
<template v-slot:item="{ item }">
<div class="d-flex align-center ga-2" style="font-size: 16px">
<img :src="item.user.profile.image_24" />
<span style="font-weight: bold">
{{ item.user.real_name }}
</span>
<span class="username">
{{ item.user.name }}
</span>
</div>
</template>
<template v-slot:no-result> <div style="display: none" /></template>
</Mentionable>
```
`main.css`
```css
/* v-mention */
.v-popper__popper .mention-item {
padding: 4px 10px;
border-radius: 4px;
}
.v-popper__popper .mention-selected {
color: white;
background: rgb(var(--v-theme-primary));
}
.v-popper__popper .username {
color: gray;
}
.v-popper__popper .mention-selected .username {
color: white;
}
```