@rt-tools/ui-kit-v2 0.14.0 → 0.15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rt-tools/ui-kit-v2",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Yauheni Krumin",
6
6
  "type": "module",
Binary file
@@ -18,13 +18,15 @@
18
18
  | `attachments` | `boolean` | `false` |
19
19
  | `accept` | `string` | `''` |
20
20
  | `sending` / `disabled` | `boolean` | `false` |
21
+ | `stoppable` | `boolean` | `false` |
22
+ | `text` (model) | `string` | `''` |
21
23
  | `formatting` | `boolean` | `false` |
22
24
  | `hint` | `boolean` | `false` |
23
25
  | `toolbar` | `TRtRichEditorToolbar` | `'full'` |
24
26
  | `minRows` / `maxRows` | `number` | 1 / 6 |
25
27
  | `droppedFiles` | `File[] \| null` | `null` |
26
28
 
27
- Выход: `submitted` — `{ text, delta?, files }`.
29
+ Выходы: `submitted` — `{ text, delta?, files }`; `stopped` — клик по «Стоп». Метод: `focus()`.
28
30
 
29
31
  ## Главное, что нужно знать
30
32
 
@@ -32,6 +34,18 @@
32
34
  вложенный файл разблокирует отправку и без текста. Во время `sending` поле и кнопка заблокированы —
33
35
  иначе второе сообщение ушло бы поверх ещё не доставленного.
34
36
 
37
+ **`stoppable` меняет смысл `sending` только для того, кто его включил.** При обоих флагах стрелку
38
+ сменяет «Стоп», форма не блокируется, а `submit` отказывает по `canSend`, не трогая черновик:
39
+ следующий вопрос набирается, пока идёт ответ. `rt-chat` и прочие потребители без флага получают
40
+ прежнюю блокировку.
41
+
42
+ **`text` — модель черновика, а не CVA.** У композера своя форма с файлами; потребителю нужно задать,
43
+ прочитать и очистить текст, а не встроить поле в чужую форму. Синхронизация двусторонняя: эффект
44
+ пишет модель в контрол, `valueChanges` контрола — в модель; сброс после отправки обнуляет обе.
45
+
46
+ **`focus()` в режиме форматирования идёт через `RtRichEditorComponent.focus`.** Узел Quill появляется
47
+ после динамического импорта; до него вызов ничего не делает.
48
+
35
49
  **Enter отправляет, Shift+Enter переносит строку.** Набор во время IME-композиции игнорируется.
36
50
 
37
51
  **`droppedFiles` — вход, а не выход.** Файлы, брошенные в область
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { AfterViewInit, OnDestroy, Signal, ElementRef, WritableSignal, InputSignal, OutputEmitterRef, InputSignalWithTransform, TemplateRef, PipeTransform } from '@angular/core';
2
+ import { AfterViewInit, OnDestroy, Signal, ElementRef, WritableSignal, InputSignal, OutputEmitterRef, InputSignalWithTransform, ModelSignal, TemplateRef, PipeTransform } from '@angular/core';
3
3
  import { RtFormControlBase, IQuillDelta, TRtKitLabelMap } from '@rt-tools/ui-kit-v2';
4
4
  import { BooleanInput, NumberInput } from '@angular/cdk/coercion';
5
5
  import { FormGroup, FormControl } from '@angular/forms';
@@ -32,6 +32,8 @@ declare class RtRichEditorComponent extends RtFormControlBase<IQuillDelta | null
32
32
  readonly enterPressed: OutputEmitterRef<void>;
33
33
  readonly displayText: Signal<string>;
34
34
  ngAfterViewInit(): Promise<void>;
35
+ /** Ставит фокус в редактор; до загрузки Quill ничего не делает. */
36
+ focus(): void;
35
37
  ngOnDestroy(): void;
36
38
  writeValue(value: IQuillDelta | null): void;
37
39
  setDisabledState(isDisabled: boolean): void;
@@ -70,6 +72,9 @@ interface IComposerFormShape {
70
72
  *
71
73
  * Отправка — `Enter` (без Shift) или клик по иконке; `Shift+Enter` — перенос
72
74
  * строки. Кнопка отправки активна, пока есть непустой текст или вложения.
75
+ *
76
+ * Со `stoppable` во время `sending` вместо стрелки стоит кнопка «Стоп», а поле
77
+ * остаётся открытым: следующий вопрос набирается, пока идёт ответ.
73
78
  */
74
79
  declare class RtMessageComposerComponent {
75
80
  #private;
@@ -77,12 +82,15 @@ declare class RtMessageComposerComponent {
77
82
  protected readonly placeholderText: Signal<string>;
78
83
  protected readonly fileInput: Signal<ElementRef<HTMLInputElement> | undefined>;
79
84
  protected readonly textInput: Signal<ElementRef<HTMLTextAreaElement> | undefined>;
85
+ protected readonly richEditor: Signal<RtRichEditorComponent | undefined>;
80
86
  protected readonly form: FormGroup<IComposerFormShape>;
81
87
  protected readonly files: Signal<readonly File[]>;
82
88
  /** Отправка доступна: есть контент (текст/delta/файлы), композер не занят. */
83
89
  protected readonly canSend: Signal<boolean>;
84
90
  /** Капсула выше одной строки: перенос текста, вложения или режим форматирования. */
85
91
  protected readonly tall: Signal<boolean>;
92
+ /** Идёт ответ, который можно остановить: вместо стрелки — «Стоп», поле открыто. */
93
+ protected readonly isStoppable: Signal<boolean>;
86
94
  protected readonly capsuleMods: Signal<Record<string, boolean>>;
87
95
  /** Текст-подсказка textarea. Пусто — берётся переведённое умолчание. */
88
96
  readonly placeholder: InputSignal<string>;
@@ -94,6 +102,11 @@ declare class RtMessageComposerComponent {
94
102
  readonly attachments: InputSignalWithTransform<boolean, BooleanInput>;
95
103
  /** Отправка в процессе — блокирует submit, кнопка отправки крутит индикатор. */
96
104
  readonly sending: InputSignalWithTransform<boolean, BooleanInput>;
105
+ /**
106
+ * Ответ на сообщение можно остановить. Во время `sending` стрелку сменяет кнопка
107
+ * «Стоп», а поле не блокируется; без входа `sending` блокирует поле, как раньше.
108
+ */
109
+ readonly stoppable: InputSignalWithTransform<boolean, BooleanInput>;
97
110
  /** Полная блокировка композера. */
98
111
  readonly disabled: InputSignalWithTransform<boolean, BooleanInput>;
99
112
  /** Rich-режим: вместо textarea — Quill-редактор, отправка уходит delta-каналом. */
@@ -112,14 +125,21 @@ declare class RtMessageComposerComponent {
112
125
  readonly droppedFiles: InputSignal<File[] | null>;
113
126
  /** Отправка сообщения: текст + файлы (последние — только при `attachments`). */
114
127
  readonly submitted: OutputEmitterRef<IRtMessageComposer.SubmitPayload>;
128
+ /** Черновик поля без форматирования: задаётся снаружи, правки уходят наружу, после отправки пуст. */
129
+ readonly text: ModelSignal<string>;
130
+ /** Клик по кнопке «Стоп» во время ответа, который можно остановить. */
131
+ readonly stopped: OutputEmitterRef<void>;
115
132
  constructor();
133
+ /** Ставит фокус в поле: в textarea, а в режиме форматирования — в rich-редактор. */
134
+ focus(): void;
116
135
  protected onKeydown(event: KeyboardEvent): void;
136
+ protected stop(): void;
117
137
  protected openPicker(): void;
118
138
  protected onFilesPicked(event: Event): void;
119
139
  protected removeFile(index: number): void;
120
140
  protected submit(): void;
121
141
  static ɵfac: i0.ɵɵFactoryDeclaration<RtMessageComposerComponent, never>;
122
- static ɵcmp: i0.ɵɵComponentDeclaration<RtMessageComposerComponent, "rt-message-composer", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "sending": { "alias": "sending"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "formatting": { "alias": "formatting"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "minRows": { "alias": "minRows"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "droppedFiles": { "alias": "droppedFiles"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; }, never, never, true, never>;
142
+ static ɵcmp: i0.ɵɵComponentDeclaration<RtMessageComposerComponent, "rt-message-composer", never, { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "attachments": { "alias": "attachments"; "required": false; "isSignal": true; }; "sending": { "alias": "sending"; "required": false; "isSignal": true; }; "stoppable": { "alias": "stoppable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "formatting": { "alias": "formatting"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "minRows": { "alias": "minRows"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "droppedFiles": { "alias": "droppedFiles"; "required": false; "isSignal": true; }; "text": { "alias": "text"; "required": false; "isSignal": true; }; }, { "submitted": "submitted"; "text": "textChange"; "stopped": "stopped"; }, never, never, true, never>;
123
143
  }
124
144
 
125
145
  /**
@@ -460,6 +460,8 @@ declare const RT_KIT_LABELS_EN: {
460
460
  readonly chatStatusRead: "Read";
461
461
  readonly chatStatusSending: "Sending";
462
462
  readonly chatStatusSent: "Delivered";
463
+ readonly chatStopAria: "Stop the answer";
464
+ readonly chatStopLabel: "Stop";
463
465
  readonly chatTitle: "Chat";
464
466
  readonly counterDecrease: "Decrease";
465
467
  readonly counterIncrease: "Increase";
Binary file