@hidemikimura/chit-ui 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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,39 @@
4
4
  バージョンは [Semantic Versioning](https://semver.org/lang/ja/) に従いますが、0.x の間は
5
5
  マイナー更新に破壊的変更が入ることがあります。
6
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
+
7
40
  ## 0.2.0 — 2026-09-19
8
41
 
9
42
  ### 追加
package/README.md CHANGED
@@ -310,6 +310,107 @@ chat.addEventListener('chat-home', (event) => {
310
310
  自前のボタンを置いてください(その場合 `home: false` のままで構いません)。読み上げ名は
311
311
  ロケールに応じて「最初に戻る」/「Back to the start」になります。
312
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
+
313
414
  ### 添付ボタン
314
415
 
315
416
  `open.input.attach` を `true` にすると、入力欄の左に添付ボタンが出ます。押すとファイル選択が
@@ -492,7 +593,8 @@ chit-ui {
492
593
  | `state` | `'closed' \| 'open' \| 'hidden'` | `'closed'` | 現在の状態 |
493
594
  | `theme` | `Theme` | `{}` | テーマ(部分指定可) |
494
595
  | `messages` | `Message[]` | `[]` | 描画する発言 |
495
- | `typing` | `boolean \| { html }` | `false` | 相手が入力中の表示 |
596
+ | `typing` | `boolean \| { html }` | `false` | 相手が入力中の表示。`loading` とは排他です |
597
+ | `loading` | `boolean` | `false` | 応答待ちの表示。`typing` とは排他で、`open.loading.auto` なら自動で切り替わります |
496
598
  | `busy` | `boolean` | `false` | 送信中。入力をロックします |
497
599
  | `inputDisabled` / `inputHidden` | `boolean` | `false` | 入力欄の無効化 / 非表示 |
498
600
  | `value` | `string` | `''` | 入力欄の内容 |
@@ -506,6 +608,8 @@ chit-ui {
506
608
  | `locale` | `string` | `<html lang>` | ラベルと時刻の言語 |
507
609
  | `labels` | `Partial<Labels>` | なし | UI 文字列の上書き |
508
610
 
611
+ `dragOffset`(`{ x, y } | null`)はドラッグで生じたずれです。読み書きできます。
612
+
509
613
  読み取り専用: `renderedState`、`device`(`'pc' \| 'mobile'`)、`hasUnseen`、`canSend`、
510
614
  `currentTheme`、`currentLabels`、`resolvedLocale`。
511
615
 
@@ -520,6 +624,7 @@ chit-ui {
520
624
  | `getMessageElement(id)` | その発言のコンテナ DOM(未描画なら `null`) |
521
625
  | `home()` | `chat-home` を発火します(ホームボタンと同じ合図) |
522
626
  | `openAttach()` | 添付のファイル選択を開きます(添付ボタンと同じ) |
627
+ | `resetPosition()` | ドラッグで動かした位置を忘れ、テーマの位置に戻します |
523
628
 
524
629
  ## イベント
525
630
 
@@ -540,6 +645,7 @@ chit-ui {
540
645
  | `chat-breakpoint-change` | PC / スマホの判定が変わった | `{ device }` | |
541
646
  | `chat-home` | ホームボタンが押された(または `home()`) | `{ trigger }` | |
542
647
  | `chat-attach` | 添付ファイルが選ばれた | `{ files }`(`File[]`) | |
648
+ | `chat-move` | ドラッグまたは矢印キーで動かされた | `{ target, position, offset, displacement }` | |
543
649
 
544
650
  `trigger` は `'user'`(クリックや Esc)か `'api'`(メソッドやプロパティ代入)です。
545
651
 
@@ -576,7 +682,7 @@ chat.addEventListener('chat-message-click', (event) => {
576
682
  `home-button` `attach-button` `attach-input`
577
683
  `header-actions` `close-button` `messages` `messages-inner` `message` `message-user`
578
684
  `message-assistant` `message-system` `bubble` `message-content` `avatar` `name` `meta` `time`
579
- `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`
580
686
 
581
687
  パーツ名・プロパティ名・イベント名・スロット名・CSS カスタムプロパティ名は公開 API として
582
688
  扱い、変更はメジャーバージョンでのみ行います。