@hidemikimura/chit-ui 0.1.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.
- package/CHANGELOG.md +91 -0
- package/README.md +314 -11
- package/dist/chit-ui.iife.min.js +416 -94
- package/dist/chit-ui.iife.min.js.map +1 -1
- package/dist/chit-ui.min.js +407 -85
- package/dist/chit-ui.min.js.map +1 -1
- package/dist/types/bundle.d.ts +1 -0
- package/dist/types/chit-ui.d.ts +89 -4
- package/dist/types/controllers/composer-controller.d.ts +4 -0
- package/dist/types/controllers/drag-controller.d.ts +118 -0
- package/dist/types/events.d.ts +3 -0
- package/dist/types/global.d.ts +9 -1
- package/dist/types/i18n/labels.d.ts +16 -0
- package/dist/types/render/composer.d.ts +0 -1
- package/dist/types/render/message-list.d.ts +0 -1
- package/dist/types/theme/default-theme.d.ts +30 -1
- package/dist/types/themes/green.d.ts +16 -0
- package/dist/types/themes/index.d.ts +1 -0
- package/dist/types/types.d.ts +105 -4
- package/package.json +6 -1
- package/src/bundle.js +1 -0
- package/src/chit-ui.js +292 -4
- package/src/controllers/composer-controller.js +2 -0
- package/src/controllers/drag-controller.js +319 -0
- package/src/events.js +3 -0
- package/src/global.d.ts +9 -1
- package/src/i18n/labels.js +12 -0
- package/src/render/composer.js +58 -0
- package/src/render/launcher.js +9 -1
- package/src/render/message-list.js +40 -10
- package/src/render/message.js +13 -4
- package/src/render/panel.js +73 -11
- package/src/styles/composer.css.js +39 -0
- package/src/styles/host.css.js +2 -0
- package/src/styles/launcher.css.js +13 -0
- package/src/styles/message.css.js +168 -9
- package/src/styles/panel.css.js +44 -4
- package/src/theme/default-theme.js +37 -2
- package/src/theme/theme-to-css.js +5 -0
- package/src/themes/green.js +47 -0
- package/src/themes/index.js +15 -0
- package/src/types.js +38 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# 変更履歴
|
|
2
|
+
|
|
3
|
+
[Keep a Changelog](https://keepachangelog.com/ja/1.1.0/) にならい、新しい版を上に置きます。
|
|
4
|
+
バージョンは [Semantic Versioning](https://semver.org/lang/ja/) に従いますが、0.x の間は
|
|
5
|
+
マイナー更新に破壊的変更が入ることがあります。
|
|
6
|
+
|
|
7
|
+
## 0.3.0 — 2026-09-20
|
|
8
|
+
|
|
9
|
+
### 追加
|
|
10
|
+
|
|
11
|
+
- **応答待ちのローディング**。`loading` プロパティで、送信から返事までの間の表示を出せます。
|
|
12
|
+
見た目は `open.loading.style`(`'spinner'`(既定)/ `'dots'` / `'text'`)と `text` で
|
|
13
|
+
決められます。
|
|
14
|
+
相手が機械のとき「入力中」は実態と違うため、スピナーや文言を選べるようにしました。
|
|
15
|
+
- `open.loading.auto` を `true` にすると、`chat-submit` から相手側の発言が届くまで自動で
|
|
16
|
+
表示します。`timeout` を過ぎたら自分で引っ込みます。
|
|
17
|
+
- CSS パーツ `loading` `loading-text`、ラベル `loading`(ja / en)。`loading` は属性にも
|
|
18
|
+
反映されるので、ページ側の CSS から `chit-ui[loading]` で拾えます。
|
|
19
|
+
- **ドラッグで動かせるようになりました**。`closed.draggable` でランチャーを、
|
|
20
|
+
`open.draggable` でパネル(取っ手はタイトルバー)を動かせます。どちらも既定は無効です。
|
|
21
|
+
矢印キー(Shift で大きく)でも動かせ、画面の外には出られません。
|
|
22
|
+
- 閉じた状態と開いた状態は一緒に動きます。ドラッグが動かすのは位置そのものではなく
|
|
23
|
+
「テーマの位置からのずれ」で、これをウィジェット全体でひとつだけ持つためです。ランチャーを
|
|
24
|
+
動かしてから開けばパネルも同じだけずれ、その逆も同じです。
|
|
25
|
+
- 動かすと `chat-move`(`detail: { target, position, offset, displacement }`)が出ます。
|
|
26
|
+
ずれは `dragOffset` プロパティで読み書きでき、保存しておけば代入するだけで復元できます。
|
|
27
|
+
`resetPosition()` でテーマの位置に戻ります。ラベル `move`(ja / en)。
|
|
28
|
+
|
|
29
|
+
### 変更
|
|
30
|
+
|
|
31
|
+
- `loading` と `typing` を排他にしました。片方を `true` にすると、もう片方が `false` に
|
|
32
|
+
なります。どちらも会話の同じ「間」を指しているので、2 つ並べないためです。
|
|
33
|
+
- パネルの最大サイズをオフセットの 2 倍からの引き算ではなく、角から反対側の端までの余白で
|
|
34
|
+
計算するようにしました。以前の式は左右(上下)の余白が等しい前提だったため、ドラッグで
|
|
35
|
+
動かすとパネルが縮んでいきました。画面内に収める判定も、実測の大きさではなくテーマが
|
|
36
|
+
指定した大きさで行うようにしています(実測だと、縮んだ分だけさらに押し込めてしまうため)。
|
|
37
|
+
- 入力中インジケーターの行の高さをフォント任せ(`normal`)ではなく `1.5` と明示しました。
|
|
38
|
+
ローディングと同じ大きさに揃えるためで、環境によって 1〜2px 変わります。
|
|
39
|
+
|
|
40
|
+
## 0.2.0 — 2026-09-19
|
|
41
|
+
|
|
42
|
+
### 追加
|
|
43
|
+
|
|
44
|
+
- **吹き出しのしっぽ**。`open.bubble = { radius, tail }` で角丸としっぽ(`'none'` /
|
|
45
|
+
`'top'` / `'bottom'`)を指定できます。しっぽは根元を吹き出しの内側に潜り込ませて描くので、
|
|
46
|
+
角丸をいくつにしても継ぎ目が見えません。入力中インジケーターにも同じしっぽが付きます。
|
|
47
|
+
- **付属テーマ**。`@hidemikimura/chit-ui/themes.js` から `greenTheme` を読み込めます
|
|
48
|
+
(緑系メッセンジャー風、しっぽ付き)。ただの `Theme` オブジェクトなので、スプレッドで
|
|
49
|
+
好きに上書きできます。単一バンドルからは `window.ChitUI.greenTheme` です。
|
|
50
|
+
- **発言者の名前とアイコン**。`open.speaker.assistant` / `.user` に `name` と `avatar` を
|
|
51
|
+
書くと、その側の発言すべてに出ます。発言ごとの `name` / `avatar` が優先され、発言に `null`
|
|
52
|
+
を書くとテーマの指定を打ち消せます(続けての発言でアイコンを省く用途)。
|
|
53
|
+
- **タイトルバーのホームボタン**。`open.header.home: true` で閉じるボタンの手前に出ます。
|
|
54
|
+
押すと `chat-home` を発火するだけで、会話の巻き戻しは利用者側で行います。`home()` から
|
|
55
|
+
同じ合図を出せます。
|
|
56
|
+
- **タイトルバーの表示切り替え**。`open.header.visible: false` でタイトルバーごと消せます。
|
|
57
|
+
LIFF のように外側がタイトルを持つ画面で、タイトルが二重になるのを避けるためのものです。
|
|
58
|
+
`title` は表示されなくても `role="dialog"` の読み上げ名としては使われます。
|
|
59
|
+
- **添付ボタン**。`open.input.attach: true` で入力欄の左に出ます。`accept`(既定
|
|
60
|
+
`image/*,video/*`)と `multiple` はファイル選択にそのまま渡ります。選ばれたファイルは
|
|
61
|
+
`chat-attach` で受け取り、アップロードや表示は利用者側で行います。`openAttach()` から
|
|
62
|
+
同じダイアログを開けます。
|
|
63
|
+
- CSS カスタムプロパティ `--chit-bubble-radius`。
|
|
64
|
+
- CSS パーツ `header-title` `home-button` `attach-button` `attach-input`。
|
|
65
|
+
- ラベル `home` / `attach`(ja / en)。
|
|
66
|
+
|
|
67
|
+
### 変更
|
|
68
|
+
|
|
69
|
+
- 発言者アイコンの位置を行の下揃えから上揃えに変えました。名前の行(名前がなければ吹き出しの
|
|
70
|
+
1 行目)に並びます。下揃えだと時刻の横に来てしまい、何を示すアイコンか読み取りにくいためです。
|
|
71
|
+
- タイトルバーの画像と見出しを `[part~='header-title']` でひとまとめにしました。以前は
|
|
72
|
+
`logo` を指定すると画像が左端、タイトルが中央に離れて表示されていました。
|
|
73
|
+
- 長いタイトルは省略記号で切り詰めます。閉じるボタンが押し出されなくなりました。
|
|
74
|
+
|
|
75
|
+
### 削除
|
|
76
|
+
|
|
77
|
+
- `open.header.avatar`。型にはありましたが何も描画していませんでした。タイトルバーの画像は
|
|
78
|
+
`open.header.logo` ひとつです。
|
|
79
|
+
|
|
80
|
+
## 0.1.0 — 2026-09-18
|
|
81
|
+
|
|
82
|
+
最初の公開版。
|
|
83
|
+
|
|
84
|
+
- 3 つの状態(閉じた状態 / 開いた状態 / 非表示)と遷移アニメーション、`chat-*` イベント。
|
|
85
|
+
- 状態ごとのテーマ(色・画像・アニメーション・大きさ)。閉じた状態は PC とスマホで分けられます。
|
|
86
|
+
- 発言の中身は `text` / `html` / `template` / `element` / `component` の 5 形式。`component`
|
|
87
|
+
では LitElement を継承したコンポーネントをそのまま渡せます。
|
|
88
|
+
- どんな HTML を入れてもレイアウトが崩れないための封じ込め CSS。
|
|
89
|
+
- 入力欄(IME 対応、自動伸縮、文字数カウンタ)、ストリーミング表示、入力中インジケーター、
|
|
90
|
+
スクロール追従。
|
|
91
|
+
- npm パッケージ(ESM)と単一バンドル(ESM / IIFE)の両方。
|
package/README.md
CHANGED
|
@@ -52,6 +52,12 @@ npm install @hidemikimura/chit-ui lit
|
|
|
52
52
|
import '@hidemikimura/chit-ui'; // <chit-ui> を登録する
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
付属テーマは別のエントリから読み込みます(ウィジェット本体は付いてきません)。
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
import { greenTheme } from '@hidemikimura/chit-ui/themes.js';
|
|
59
|
+
```
|
|
60
|
+
|
|
55
61
|
タグ名を自分で決めたい場合は、登録しないエントリを使います。
|
|
56
62
|
|
|
57
63
|
```js
|
|
@@ -97,7 +103,7 @@ chat.messages = [
|
|
|
97
103
|
| 中身 | ○ | `text` / `html` / `template` / `element` / `component` のいずれか 1 つ |
|
|
98
104
|
| `props` | | `component` に渡すプロパティ |
|
|
99
105
|
| `time` | | ISO 文字列または `Date`。`formatTime` で表示を差し替えられます |
|
|
100
|
-
| `name` / `avatar` | |
|
|
106
|
+
| `name` / `avatar` | | 発言者名とアイコン画像 URL。テーマの `open.speaker` より優先され、`null` でその発言だけ打ち消せます |
|
|
101
107
|
| `status` | | `sending` / `sent` / `error` |
|
|
102
108
|
| `streaming` | | `true` の間はカーソルを出し、スクロールを追従させます |
|
|
103
109
|
| `meta` | | ライブラリは触りません。イベントでそのまま返ってきます |
|
|
@@ -206,6 +212,7 @@ chat.theme = {
|
|
|
206
212
|
open: {
|
|
207
213
|
width: 380, height: 600,
|
|
208
214
|
colors: { accent: '#2563eb', userBubble: '#2563eb' },
|
|
215
|
+
bubble: { radius: 14, tail: 'none' }, // 吹き出しの角丸としっぽ
|
|
209
216
|
header: { title: 'サポート' },
|
|
210
217
|
},
|
|
211
218
|
};
|
|
@@ -218,6 +225,285 @@ chat.theme = {
|
|
|
218
225
|
- スマホ幅では `open` は常に全画面です(`width` / `height` は無視されます)
|
|
219
226
|
- 実行中に差し替えると即座に反映されます(ダークモードの切り替えなど)
|
|
220
227
|
|
|
228
|
+
### 付属テーマ
|
|
229
|
+
|
|
230
|
+
見た目を一から決めたくないときは、ライブラリ同梱のプリセットをそのまま渡せます。
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
import { greenTheme } from '@hidemikimura/chit-ui/themes.js';
|
|
234
|
+
|
|
235
|
+
chat.theme = greenTheme;
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`greenTheme` は淡いブルーグレーの会話背景に、相手は白・自分は黄緑の吹き出し、しっぽは
|
|
239
|
+
上向き、という緑系メッセンジャーの配色です。特定のサービスのロゴや素材は含みません。
|
|
240
|
+
配色は Chit UI 独自のもので、読む必要のある文字と背景の組み合わせはすべて WCAG AA
|
|
241
|
+
(4.5:1)を満たしています。テストが全プリセットのコントラストを毎回検証します。
|
|
242
|
+
|
|
243
|
+
プリセットはただの `Theme` オブジェクトなので、上から重ねて調整できます。
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
chat.theme = { ...greenTheme, open: { ...greenTheme.open, width: 420 } };
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
`<script>` 1 本で使っている場合は、バンドルから同じ名前で取り出せます。
|
|
250
|
+
|
|
251
|
+
```js
|
|
252
|
+
const { greenTheme } = window.ChitUI; // IIFE 版
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### タイトルバー
|
|
256
|
+
|
|
257
|
+
`open.header` にタイトル文字列とロゴ画像を渡せます。
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
chat.theme = {
|
|
261
|
+
open: {
|
|
262
|
+
header: { title: 'ecx サポート', logo: '/logo.png' },
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
画像とタイトルは左側にひとまとまりで並び、右側に閉じるボタンが残ります。長いタイトルは
|
|
268
|
+
省略記号で切り詰められるので、閉じるボタンが押し出されることはありません。`title` は
|
|
269
|
+
`role="dialog"` の読み上げ名にも使われます(未指定なら「チャット」/「Chat」)。ロゴは
|
|
270
|
+
装飾扱い(`alt=""`)です。隣にタイトルがあり、画像に読み上げ名を重ねても冗長なためです。
|
|
271
|
+
|
|
272
|
+
バー全体を自分で描くなら `header-title` スロット、ボタンを足すなら `header-actions`
|
|
273
|
+
スロット、まるごと差し替えるなら `header` スロットを使ってください。
|
|
274
|
+
|
|
275
|
+
#### タイトルバーを消す
|
|
276
|
+
|
|
277
|
+
`header.visible` を `false` にすると、タイトルバーごと出しません。LINE の LIFF のように
|
|
278
|
+
外側のアプリが既にタイトルを持っている画面で、タイトルが二重に並ぶのを避けるための設定です。
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
chat.theme = { open: { header: { visible: false } } };
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
会話はパネルの上端から始まります。`title` を書いておけば、表示はされなくても
|
|
285
|
+
`role="dialog"` の読み上げ名としては使われるので、外側のタイトルと別の名前を付けられます。
|
|
286
|
+
|
|
287
|
+
閉じるボタンもバーごと消える点にご注意ください。Esc とランチャーのクリックでは閉じられますし、
|
|
288
|
+
LIFF のように外側が閉じる手段を持っているなら問題になりません。自前の閉じるボタンを置くなら
|
|
289
|
+
`footer` スロットか、発言の中のボタンから `chat.close()` を呼んでください。
|
|
290
|
+
|
|
291
|
+
#### ホームボタン
|
|
292
|
+
|
|
293
|
+
`header.home` を `true` にすると、閉じるボタンの手前にホームボタンが出ます。シナリオ型の
|
|
294
|
+
チャットで、会話を最初からやり直す入口を想定しています。
|
|
295
|
+
|
|
296
|
+
```js
|
|
297
|
+
chat.theme = { open: { header: { title: 'ecx サポート', home: true } } };
|
|
298
|
+
|
|
299
|
+
chat.addEventListener('chat-home', (event) => {
|
|
300
|
+
chat.messages = scenarioStart; // 巻き戻すのは利用者側
|
|
301
|
+
chat.typing = false;
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
押されても**ウィジェットは何も消しません**。`chat-home`(`detail: { trigger }`)を出すだけです。
|
|
306
|
+
`messages` の持ち主は利用者側なので、どこまで巻き戻すか、確認を挟むか、パネルを閉じるかは
|
|
307
|
+
そちらで決められます。コードから同じ合図を出すなら `chat.home()` です(`trigger` は `'api'`)。
|
|
308
|
+
|
|
309
|
+
見た目を変えるなら `::part(home-button)`、別のアイコンにしたいなら `header-actions` スロットに
|
|
310
|
+
自前のボタンを置いてください(その場合 `home: false` のままで構いません)。読み上げ名は
|
|
311
|
+
ロケールに応じて「最初に戻る」/「Back to the start」になります。
|
|
312
|
+
|
|
313
|
+
### ドラッグで動かす
|
|
314
|
+
|
|
315
|
+
ランチャー(閉じた状態)と、開いた状態のパネルを、読み手が動かせるようにできます。
|
|
316
|
+
どちらも既定は無効です。
|
|
317
|
+
|
|
318
|
+
```js
|
|
319
|
+
chat.theme = {
|
|
320
|
+
closed: { draggable: true }, // ランチャーをドラッグ
|
|
321
|
+
open: { draggable: true }, // パネルをタイトルバーでドラッグ
|
|
322
|
+
};
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
パネルの取っ手はタイトルバーです。バーの中のボタン(閉じる・ホーム)を押したときはドラッグに
|
|
326
|
+
なりません。タイトルバーを消している(`header.visible: false`)ときは掴む場所がないので
|
|
327
|
+
動かせません。スマホ幅ではパネルは全画面なので、パネルのドラッグは自動的に無効になります
|
|
328
|
+
(ランチャーは動かせます)。
|
|
329
|
+
|
|
330
|
+
矢印キーでも動かせます。ランチャーかタイトルバーにフォーカスして、矢印キーで 8px、
|
|
331
|
+
Shift と一緒なら 32px ずつです。ポインタが使えない人でも同じことができるようにするためで、
|
|
332
|
+
そのためタイトルバーは `draggable` のときだけフォーカスを受けます。
|
|
333
|
+
|
|
334
|
+
画面の外には出られません。端から 8px のところで止まります。ウィンドウの大きさが変わったときも
|
|
335
|
+
中に収まるように置き直します。
|
|
336
|
+
|
|
337
|
+
#### 閉じた状態と開いた状態は一緒に動きます
|
|
338
|
+
|
|
339
|
+
ドラッグが動かすのは「位置」ではなく「テーマの位置からどれだけずらしたか」(画面上の px)で、
|
|
340
|
+
このずれをウィジェット全体でひとつだけ持っています。そのため、
|
|
341
|
+
|
|
342
|
+
- ランチャーを動かしてから開くと、パネルも同じだけずれた位置に出ます
|
|
343
|
+
- パネルを動かしてから閉じると、ランチャーも同じだけずれた位置に戻ります
|
|
344
|
+
|
|
345
|
+
ランチャーとパネルは同じウィジェットの 2 つの姿なので、片方だけ元の場所に残るほうが不自然だと
|
|
346
|
+
考えてこうしています。それぞれの角(`closed.position` / `open.position`)や余白の違いは
|
|
347
|
+
そのまま保たれ、ずれだけが共有されます。
|
|
348
|
+
|
|
349
|
+
#### 動かした位置を覚える
|
|
350
|
+
|
|
351
|
+
ずれは `dragOffset` で読み書きできます。ページを開いている間だけ保持され、離したときに
|
|
352
|
+
`chat-move` が出ます。保存と復元は利用者側の仕事です(`localStorage` に入れるかどうかは
|
|
353
|
+
サイトの方針なので、ライブラリは決めません)。
|
|
354
|
+
|
|
355
|
+
```js
|
|
356
|
+
chat.addEventListener('chat-move', (event) => {
|
|
357
|
+
const { target, position, offset, displacement } = event.detail;
|
|
358
|
+
localStorage.setItem('chit-position', JSON.stringify(displacement));
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// 復元はずれを戻すだけ(閉じた状態・開いた状態の両方に効きます)
|
|
362
|
+
chat.dragOffset = JSON.parse(localStorage.getItem('chit-position') ?? 'null');
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
`displacement` が共有しているずれ、`offset` は実際に落ち着いた位置で、テーマと同じ意味
|
|
366
|
+
(`position` が指す角からの距離)です。`target` はどちらを掴んで動かしたかです。
|
|
367
|
+
`chat.resetPosition()`(= `chat.dragOffset = null`)でテーマの位置に戻ります。
|
|
368
|
+
|
|
369
|
+
動かしている間の位置は要素のインラインスタイルとして書かれるので、テーマよりもページ側の CSS
|
|
370
|
+
よりも優先されます。読み手が自分で動かした結果が、いちばん具体的な指定だからです。
|
|
371
|
+
|
|
372
|
+
### 応答待ちのローディング
|
|
373
|
+
|
|
374
|
+
送信してから返事が届くまでの間に出す表示です。`loading` プロパティで切り替えます。
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
chat.loading = true;
|
|
378
|
+
// …サーバーとやり取り…
|
|
379
|
+
chat.loading = false;
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
`open.loading` で見た目を決めます。既定はスピナーです。入力中インジケーターと同じ三点ドットだと
|
|
383
|
+
「誰かが書いている」という意味になってしまい、サーバーの応答待ちとは違うためです。相手が人間の
|
|
384
|
+
オペレーターなら `'dots'` を選べます。
|
|
385
|
+
|
|
386
|
+
```js
|
|
387
|
+
chat.theme = {
|
|
388
|
+
open: {
|
|
389
|
+
loading: {
|
|
390
|
+
auto: true, // 送信から次の発言まで自動で出す(既定 false)
|
|
391
|
+
style: 'spinner', // 'spinner'(既定)/ 'dots' / 'text'
|
|
392
|
+
text: '回答を作成しています', // 省略すると読み上げ名だけに使われます
|
|
393
|
+
timeout: 8000, // ms。0(既定)なら自分で消します
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
`auto: true` にすると、`chat-submit` が出た時点で表示し、相手側(`assistant` か `system`)の
|
|
400
|
+
発言が `messages` に増えた時点で消します。自分の発言を積んでも消えません。ストリーミングの
|
|
401
|
+
場合は空の吹き出しが現れた時点で消えます。送信をキャンセル(`preventDefault`)したときは
|
|
402
|
+
そもそも出ません。`timeout` を過ぎたら黙って引っ込むので、通信が返ってこないまま残り続ける
|
|
403
|
+
ことはありません。`chat.loading = false` でいつでも手で消せます。
|
|
404
|
+
|
|
405
|
+
入力中インジケーター(`typing`)と同じ位置に出ます。**この 2 つは同時には立ちません。**
|
|
406
|
+
`loading` を `true` にすると `typing` は `false` になり、その逆も同じです。どちらも会話の
|
|
407
|
+
同じ「間」を指していて(片方は人が書いている、もう片方はサーバーがまだ答えていない)、
|
|
408
|
+
2 つ並ぶと読み手に違いを考えさせてしまうためです。片方を `false` にしてももう片方は
|
|
409
|
+
そのままです。同じタイミングで両方に `true` を入れた場合は、後から書いたほうが残ります。
|
|
410
|
+
|
|
411
|
+
入力欄をロックするかどうかは別の話なので、必要なら `busy` も合わせて立ててください。
|
|
412
|
+
`loading` は属性にも反映されるので、ページ側の CSS から `chit-ui[loading]` で拾えます。
|
|
413
|
+
|
|
414
|
+
### 添付ボタン
|
|
415
|
+
|
|
416
|
+
`open.input.attach` を `true` にすると、入力欄の左に添付ボタンが出ます。押すとファイル選択が
|
|
417
|
+
開き、選ばれたファイルは `chat-attach` で渡ってきます。
|
|
418
|
+
|
|
419
|
+
```js
|
|
420
|
+
chat.theme = {
|
|
421
|
+
open: {
|
|
422
|
+
input: {
|
|
423
|
+
attach: true,
|
|
424
|
+
accept: 'image/*,video/*', // 既定。file input にそのまま渡ります
|
|
425
|
+
multiple: false, // 既定
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
chat.addEventListener('chat-attach', (event) => {
|
|
431
|
+
for (const file of event.detail.files) upload(file); // 送るのは利用者側
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
ウィジェットがやるのは選ばせるところまでです。アップロードもプレビューも発言の追加もしません。
|
|
436
|
+
`messages` の持ち主は利用者側で、バイト列の送り先もライブラリは知らないためです。選択後は
|
|
437
|
+
file input を空に戻すので、同じファイルを続けて選んでも毎回イベントが出ます。ダイアログを
|
|
438
|
+
閉じただけのときは何も起きません。
|
|
439
|
+
|
|
440
|
+
`busy` と `inputDisabled` の間はボタンも無効になります。コードから開くなら
|
|
441
|
+
`chat.openAttach()`、見た目を変えるなら `::part(attach-button)` です。自前の添付フローが
|
|
442
|
+
あるなら `attach: false` のまま `input-before` スロットに自分のボタンを置いてください。
|
|
443
|
+
|
|
444
|
+
### 発言者の名前とアイコン
|
|
445
|
+
|
|
446
|
+
`open.speaker` に書いておくと、その側の発言すべてに名前とアイコンが出ます。発言ごとに
|
|
447
|
+
書く必要はありません。
|
|
448
|
+
|
|
449
|
+
```js
|
|
450
|
+
chat.theme = {
|
|
451
|
+
open: {
|
|
452
|
+
speaker: {
|
|
453
|
+
assistant: { name: 'サポート', avatar: '/support.png' },
|
|
454
|
+
user: { name: null, avatar: null }, // 既定(何も出さない)
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
};
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
発言側の指定が勝ちます。担当者ごとに顔を変えるなら発言に書いてください。
|
|
461
|
+
|
|
462
|
+
```js
|
|
463
|
+
chat.messages = [
|
|
464
|
+
{ id: 'a', role: 'assistant', text: 'お待たせしました', name: '田中', avatar: '/tanaka.png' },
|
|
465
|
+
];
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
`null` を渡すとその発言だけテーマの指定を打ち消せます。同じ人が続けて話すときに、
|
|
469
|
+
2 件目以降のアイコンを省く使い方ができます。このときアイコンの場所は空けたまま残るので、
|
|
470
|
+
吹き出しの左端は揃います。
|
|
471
|
+
|
|
472
|
+
```js
|
|
473
|
+
chat.messages = [
|
|
474
|
+
{ id: 'a', role: 'assistant', text: '承知しました' },
|
|
475
|
+
{ id: 'b', role: 'assistant', text: '少々お待ちください', avatar: null, name: null },
|
|
476
|
+
];
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
`system` の発言は中央寄せの連絡行なので、名前もアイコンも出ません。会話の参加者ではなく
|
|
480
|
+
ウィジェットが会話について述べている行、という位置づけのためです。
|
|
481
|
+
|
|
482
|
+
### 吹き出しのしっぽ
|
|
483
|
+
|
|
484
|
+
`open.bubble` で吹き出しの角丸としっぽを決めます。
|
|
485
|
+
|
|
486
|
+
```js
|
|
487
|
+
chat.theme = { open: { bubble: { radius: 18, tail: 'top' } } };
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
| 値 | 意味 |
|
|
491
|
+
| --- | --- |
|
|
492
|
+
| `tail: 'none'`(既定) | しっぽなし。話し手側の角だけ小さく落とした形になります |
|
|
493
|
+
| `tail: 'top'` | 吹き出しの上寄りに三角のしっぽを付けます |
|
|
494
|
+
| `tail: 'bottom'` | 下寄りに付けます |
|
|
495
|
+
|
|
496
|
+
しっぽは話し手の側(相手は左、自分は右)に、その吹き出しと同じ色の葉のような形で描かれます。
|
|
497
|
+
根元は吹き出しの内側に潜り込ませてあるので、継ぎ目は吹き出しの地色に隠れます。角丸はどの角も
|
|
498
|
+
そのままで、角丸の値をいくつにしても隙間は出ません。付く高さは角丸に合わせて少し下げてあり、
|
|
499
|
+
縁がまっすぐになったところに根元が乗ります。入力中インジケーターにも同じしっぽが付きます。
|
|
500
|
+
|
|
501
|
+
しっぽを出すと、話し手側の角を落とす既定の形はなくなります。ひとつの吹き出しに話し手を示す印が
|
|
502
|
+
ふたつあると読みにくいためです。
|
|
503
|
+
|
|
504
|
+
しっぽの形は `clip-path: path()` で描いています。これに対応していないブラウザでは、変な形が
|
|
505
|
+
はみ出すよりはと考えて、しっぽを出さず既定の吹き出しのままにしています。
|
|
506
|
+
|
|
221
507
|
### 閉じた状態を自分で描く
|
|
222
508
|
|
|
223
509
|
`closed.component` に `LitElement` を継承したコンポーネント(またはタグ名)を渡すと、
|
|
@@ -275,7 +561,7 @@ chit-ui {
|
|
|
275
561
|
}
|
|
276
562
|
```
|
|
277
563
|
|
|
278
|
-
公開しているカスタムプロパティは次の
|
|
564
|
+
公開しているカスタムプロパティは次の 33 個です。
|
|
279
565
|
|
|
280
566
|
色: `--chit-color-bg` `--chit-color-text` `--chit-color-accent` `--chit-color-border`
|
|
281
567
|
`--chit-color-user-bg` `--chit-color-user-text` `--chit-color-assistant-bg`
|
|
@@ -287,6 +573,8 @@ chit-ui {
|
|
|
287
573
|
`--chit-launcher-offset-y` `--chit-launcher-bg` `--chit-launcher-text`
|
|
288
574
|
`--chit-launcher-shadow` `--chit-launcher-image`
|
|
289
575
|
|
|
576
|
+
吹き出し: `--chit-bubble-radius`
|
|
577
|
+
|
|
290
578
|
パネル: `--chit-panel-width` `--chit-panel-height` `--chit-panel-radius`
|
|
291
579
|
`--chit-panel-offset-x` `--chit-panel-offset-y` `--chit-panel-shadow`
|
|
292
580
|
`--chit-panel-bg-image`
|
|
@@ -305,7 +593,8 @@ chit-ui {
|
|
|
305
593
|
| `state` | `'closed' \| 'open' \| 'hidden'` | `'closed'` | 現在の状態 |
|
|
306
594
|
| `theme` | `Theme` | `{}` | テーマ(部分指定可) |
|
|
307
595
|
| `messages` | `Message[]` | `[]` | 描画する発言 |
|
|
308
|
-
| `typing` | `boolean \| { html }` | `false` |
|
|
596
|
+
| `typing` | `boolean \| { html }` | `false` | 相手が入力中の表示。`loading` とは排他です |
|
|
597
|
+
| `loading` | `boolean` | `false` | 応答待ちの表示。`typing` とは排他で、`open.loading.auto` なら自動で切り替わります |
|
|
309
598
|
| `busy` | `boolean` | `false` | 送信中。入力をロックします |
|
|
310
599
|
| `inputDisabled` / `inputHidden` | `boolean` | `false` | 入力欄の無効化 / 非表示 |
|
|
311
600
|
| `value` | `string` | `''` | 入力欄の内容 |
|
|
@@ -319,6 +608,8 @@ chit-ui {
|
|
|
319
608
|
| `locale` | `string` | `<html lang>` | ラベルと時刻の言語 |
|
|
320
609
|
| `labels` | `Partial<Labels>` | なし | UI 文字列の上書き |
|
|
321
610
|
|
|
611
|
+
`dragOffset`(`{ x, y } | null`)はドラッグで生じたずれです。読み書きできます。
|
|
612
|
+
|
|
322
613
|
読み取り専用: `renderedState`、`device`(`'pc' \| 'mobile'`)、`hasUnseen`、`canSend`、
|
|
323
614
|
`currentTheme`、`currentLabels`、`resolvedLocale`。
|
|
324
615
|
|
|
@@ -331,6 +622,9 @@ chit-ui {
|
|
|
331
622
|
| `focusInput()` / `clearInput()` | 入力欄の操作 |
|
|
332
623
|
| `scrollToBottom({ smooth })` | 最新の発言までスクロール。`smooth` 省略時はテーマの設定に従う |
|
|
333
624
|
| `getMessageElement(id)` | その発言のコンテナ DOM(未描画なら `null`) |
|
|
625
|
+
| `home()` | `chat-home` を発火します(ホームボタンと同じ合図) |
|
|
626
|
+
| `openAttach()` | 添付のファイル選択を開きます(添付ボタンと同じ) |
|
|
627
|
+
| `resetPosition()` | ドラッグで動かした位置を忘れ、テーマの位置に戻します |
|
|
334
628
|
|
|
335
629
|
## イベント
|
|
336
630
|
|
|
@@ -349,6 +643,9 @@ chit-ui {
|
|
|
349
643
|
| `chat-message-click` | 発言の中がクリックされた | `{ message, target, originalEvent }` | ○ |
|
|
350
644
|
| `chat-scroll-top` | 一覧が最上部に達した | `{}` | |
|
|
351
645
|
| `chat-breakpoint-change` | PC / スマホの判定が変わった | `{ device }` | |
|
|
646
|
+
| `chat-home` | ホームボタンが押された(または `home()`) | `{ trigger }` | |
|
|
647
|
+
| `chat-attach` | 添付ファイルが選ばれた | `{ files }`(`File[]`) | |
|
|
648
|
+
| `chat-move` | ドラッグまたは矢印キーで動かされた | `{ target, position, offset, displacement }` | |
|
|
352
649
|
|
|
353
650
|
`trigger` は `'user'`(クリックや Esc)か `'api'`(メソッドやプロパティ代入)です。
|
|
354
651
|
|
|
@@ -381,10 +678,11 @@ chat.addEventListener('chat-message-click', (event) => {
|
|
|
381
678
|
|
|
382
679
|
`::part()` で外部からスタイルを当てられます。
|
|
383
680
|
|
|
384
|
-
`launcher` `launcher-icon` `launcher-label` `panel` `header` `header-heading` `header-logo`
|
|
681
|
+
`launcher` `launcher-icon` `launcher-label` `panel` `header` `header-title` `header-heading` `header-logo`
|
|
682
|
+
`home-button` `attach-button` `attach-input`
|
|
385
683
|
`header-actions` `close-button` `messages` `messages-inner` `message` `message-user`
|
|
386
684
|
`message-assistant` `message-system` `bubble` `message-content` `avatar` `name` `meta` `time`
|
|
387
|
-
`status` `cursor` `typing` `to-latest` `composer` `input` `counter` `send-button` `spinner`
|
|
685
|
+
`status` `cursor` `typing` `loading` `loading-text` `to-latest` `composer` `input` `counter` `send-button` `spinner`
|
|
388
686
|
|
|
389
687
|
パーツ名・プロパティ名・イベント名・スロット名・CSS カスタムプロパティ名は公開 API として
|
|
390
688
|
扱い、変更はメジャーバージョンでのみ行います。
|
|
@@ -403,6 +701,9 @@ chat.addEventListener('chat-message-click', (event) => {
|
|
|
403
701
|
|
|
404
702
|
Chrome / Edge / Firefox / Safari の最新 2 バージョンと iOS Safari 16 以降。IE は非対応です。
|
|
405
703
|
|
|
704
|
+
吹き出しのしっぽだけは `clip-path: path()` を使っています。対応していないブラウザでは
|
|
705
|
+
しっぽを出さず、通常の吹き出しとして表示します(他の機能には影響しません)。
|
|
706
|
+
|
|
406
707
|
## 開発
|
|
407
708
|
|
|
408
709
|
```sh
|
|
@@ -422,18 +723,20 @@ IME の実挙動は合成イベントでは再現しきれないため、リリ
|
|
|
422
723
|
- macOS Safari + 日本語 IME: 変換確定の Enter で誤送信しないこと
|
|
423
724
|
- iOS Safari: パネルが全画面になり、キーボード表示中も入力欄が隠れないこと
|
|
424
725
|
- Android Chrome: 変換中の Enter で誤送信しないこと
|
|
726
|
+
- iOS Safari / Android Chrome: 添付ボタンからカメラとフォトライブラリが開けること
|
|
727
|
+
(`accept` はブラウザによって扱いが違うため)
|
|
425
728
|
|
|
426
|
-
|
|
729
|
+
### 公開
|
|
427
730
|
|
|
428
731
|
```sh
|
|
429
732
|
npm login
|
|
430
|
-
npm run check
|
|
431
|
-
npm publish
|
|
733
|
+
npm run check # typecheck + test + axe 監査
|
|
734
|
+
npm publish # prepublishOnly がビルドとテストを流し直します
|
|
432
735
|
```
|
|
433
736
|
|
|
434
|
-
`
|
|
435
|
-
|
|
436
|
-
|
|
737
|
+
`publishConfig` に `access: public` を入れてあるので `--access public` は不要です。
|
|
738
|
+
公開したら `git tag v0.2.0 && git push --tags` を忘れずに。変更点は
|
|
739
|
+
[CHANGELOG.md](./CHANGELOG.md) にまとめています。
|
|
437
740
|
|
|
438
741
|
## ライセンス
|
|
439
742
|
|