@rt-tools/ui-kit-v2 0.13.1 → 0.14.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 +25 -5
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +45 -9
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2.mjs +2265 -664
- package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
- package/package.json +1 -1
- package/rt-tools-ui-kit-v2-0.14.0.tgz +0 -0
- package/src/lib/components/CONTEXT.md +1 -1
- package/src/lib/components/action-bar/rt-action-bar.component.scss +5 -0
- package/src/lib/components/autocomplete/rt-autocomplete.component.scss +8 -1
- package/src/lib/components/bottom-sheet/rt-bottom-sheet.component.scss +5 -0
- package/src/lib/components/button/CONTEXT.md +1 -1
- package/src/lib/components/button/rt-button.directive.scss +5 -7
- package/src/lib/components/calendar/CONTEXT.md +16 -2
- package/src/lib/components/calendar/rt-calendar.component.scss +81 -4
- package/src/lib/components/card/rt-card.component.scss +5 -0
- package/src/lib/components/checkbox/rt-checkbox.component.scss +5 -0
- package/src/lib/components/data-list/settings/rt-data-list-settings-aside.component.scss +1 -1
- package/src/lib/components/data-list/toolbar/rt-data-list-toolbar.component.scss +1 -1
- package/src/lib/components/data-table/cell/rt-data-table-cell.component.scss +1 -1
- package/src/lib/components/data-table/filter-cell/rt-data-table-filter-cell.component.scss +1 -1
- package/src/lib/components/data-table/rt-data-table.component.scss +1 -1
- package/src/lib/components/date-picker/CONTEXT.md +33 -14
- package/src/lib/components/date-picker/panel/rt-date-panel.component.scss +155 -0
- package/src/lib/components/date-picker/rt-date-picker.component.scss +18 -2
- package/src/lib/components/date-range/CONTEXT.md +53 -0
- package/src/lib/components/date-range/panel/rt-date-range-panel.component.scss +103 -0
- package/src/lib/components/date-range/rt-date-range.component.scss +120 -0
- package/src/lib/components/dialog/rt-dialog.component.scss +5 -0
- package/src/lib/components/empty-state/rt-empty-state.component.scss +5 -0
- package/src/lib/components/file-card/rt-file-card.component.scss +5 -0
- package/src/lib/components/file-drop/rt-file-drop.component.scss +5 -0
- package/src/lib/components/header/rt-header.component.scss +5 -0
- package/src/lib/components/icon-button/CONTEXT.md +1 -1
- package/src/lib/components/icon-button/rt-icon-button.component.scss +9 -29
- package/src/lib/components/input/rt-input.component.scss +7 -1
- package/src/lib/components/input-number/rt-input-number.component.scss +7 -1
- package/src/lib/components/markdown-text/rt-markdown-text.component.scss +5 -0
- package/src/lib/components/menu/rt-menu-item.component.scss +5 -0
- package/src/lib/components/message/rt-message.component.scss +5 -0
- package/src/lib/components/money-list/rt-money-list.component.scss +5 -0
- package/src/lib/components/multiselect/CONTEXT.md +12 -5
- package/src/lib/components/multiselect/rt-multiselect.component.scss +32 -1
- package/src/lib/components/note/rt-note.component.scss +5 -0
- package/src/lib/components/notifications-bell/rt-notifications-bell.component.scss +5 -0
- package/src/lib/components/pagination/rt-pagination.component.scss +6 -1
- package/src/lib/components/radio-button/rt-radio-button.component.scss +5 -0
- package/src/lib/components/section-nav/rt-section-nav.component.scss +5 -0
- package/src/lib/components/select/CONTEXT.md +10 -7
- package/src/lib/components/select/rt-select.component.scss +36 -1
- package/src/lib/components/skeleton/CONTEXT.md +14 -16
- package/src/lib/components/skeleton/rt-skeleton.component.scss +7 -1
- package/src/lib/components/skeleton-wrapper/CONTEXT.md +6 -6
- package/src/lib/components/split-button/rt-split-button.component.scss +6 -0
- package/src/lib/components/stepper/rt-stepper.component.scss +5 -0
- package/src/lib/components/table/rt-table.component.scss +12 -0
- package/src/lib/components/tag/CONTEXT.md +14 -15
- package/src/lib/components/tag/rt-tag.component.scss +6 -30
- package/src/lib/components/textarea/rt-textarea.component.scss +8 -1
- package/src/lib/components/thread-list/rt-thread-list.component.scss +5 -0
- package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +7 -6
- package/src/lib/components/toggle-switch/rt-toggle-switch.component.scss +5 -0
- package/src/rich-editor/lib/components/message-composer/CONTEXT.md +11 -1
- package/src/rich-editor/lib/components/message-composer/rt-message-composer.component.scss +78 -34
- package/src/styles/_mixins.scss +39 -0
- package/styles/tokens.css +30 -5
- package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +11 -5
- package/types/rt-tools-ui-kit-v2.d.ts +394 -109
- package/rt-tools-ui-kit-v2-0.13.1.tgz +0 -0
package/README.md
CHANGED
|
@@ -157,10 +157,10 @@ export const appConfig: ApplicationConfig = {
|
|
|
157
157
|
## Что внутри
|
|
158
158
|
|
|
159
159
|
**Компоненты** — 73 семейства: поля формы (`rt-input`, `rt-select`, `rt-multiselect`,
|
|
160
|
-
`rt-date-picker`, `rt-file-input`, `rt-rich-editor`, `rt-field`), таблица с
|
|
161
|
-
пагинацией, панель правки записи с маршрутом и защитой несохранённого,
|
|
162
|
-
календарь, шапка страницы с навигацией, тосты, просмотрщик фотографий,
|
|
163
|
-
(`rt-markdown-text`) и остальное.
|
|
160
|
+
`rt-date-picker`, `rt-date-range`, `rt-file-input`, `rt-rich-editor`, `rt-field`), таблица с
|
|
161
|
+
настройкой колонок и пагинацией, панель правки записи с маршрутом и защитой несохранённого,
|
|
162
|
+
диалоги, чат с композером, календарь, шапка страницы с навигацией, тосты, просмотрщик фотографий,
|
|
163
|
+
показ размеченного текста (`rt-markdown-text`) и остальное.
|
|
164
164
|
|
|
165
165
|
**Дизайн-система** — `src/styles`:
|
|
166
166
|
|
|
@@ -225,6 +225,27 @@ provideRtKitLabels({
|
|
|
225
225
|
доживает до рантайма) и то, что на них отвечают готовой строкой: подстановки вида `{{name}}`
|
|
226
226
|
переводчик делает сам. Подпись, которой он не дал, берётся английской — поштучно, не набором.
|
|
227
227
|
|
|
228
|
+
## Скругление одним входом
|
|
229
|
+
|
|
230
|
+
Каждый компонент с поверхностью принимает вход `radius` — шаг общей шкалы: `none`, `xs`, `sm`,
|
|
231
|
+
`ms`, `md`, `lg`, `xl`, `2xl`, `full`. Без входа компонент скруглён по макету, и умолчание у
|
|
232
|
+
каждого своё.
|
|
233
|
+
|
|
234
|
+
```html
|
|
235
|
+
<rt-card radius="none">…</rt-card>
|
|
236
|
+
<rt-input radius="full" />
|
|
237
|
+
<button rtButton label="Сохранить" radius="sm"></button>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Шаг ложится на хост атрибутом `data-rt-radius` и переназначает своё свойство главной поверхности.
|
|
241
|
+
Вложенный компонент его не наследует: скруглённая карточка не скругляет кнопки внутри.
|
|
242
|
+
Внутренние части — точка, значок, кольцо фокуса — держат своё скругление. Круглую кнопку для
|
|
243
|
+
всего приложения задаёт настройка кита `components.button.radius`.
|
|
244
|
+
|
|
245
|
+
Входа нет у подтверждения, всплывающего уведомления, подсказки и просмотра фото: их рисует
|
|
246
|
+
директива или сервис поверх страницы, и тега для шага у приложения нет. Все шаги всех компонентов
|
|
247
|
+
показаны на странице витрины `Foundation / Radius`.
|
|
248
|
+
|
|
228
249
|
## Настройка компонента снаружи
|
|
229
250
|
|
|
230
251
|
Компонент не берёт ступень шкалы там, где рисует себя: между ступенью и местом употребления
|
|
@@ -305,4 +326,3 @@ pnpm exec stylelint "projects/ui-kit-v2/**/*.scss"
|
|
|
305
326
|
- **Кит больше не настаивает на своём восклицательным знаком.** Таблица в карточном виде
|
|
306
327
|
перестала перебивать `min-width` приложения: приложению, которому нужен и горизонтальный
|
|
307
328
|
скролл, и карточный вид, остаётся сузить свой селектор до широкого экрана.
|
|
308
|
-
|
|
@@ -175,10 +175,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
175
175
|
}], propDecorators: { editorHost: [{ type: i0.ViewChild, args: ['editor', { isSignal: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], enterPressed: [{ type: i0.Output, args: ["enterPressed"] }] } });
|
|
176
176
|
|
|
177
177
|
const BEM_BLOCK$1 = 'rt-message-composer';
|
|
178
|
+
/** Текст в поле выше полутора строк — он перенёсся, и капсула берёт скругление высокой. */
|
|
179
|
+
function rtComposerWraps(node) {
|
|
180
|
+
const style = getComputedStyle(node);
|
|
181
|
+
const line = parseFloat(style.lineHeight) || parseFloat(style.fontSize) * 1.5;
|
|
182
|
+
const text = node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);
|
|
183
|
+
return text > line * 1.5;
|
|
184
|
+
}
|
|
178
185
|
/**
|
|
179
|
-
* Композер
|
|
180
|
-
*
|
|
181
|
-
* без data-access: наружу торчит только `submitted` с текстом и файлами.
|
|
186
|
+
* Композер сообщения — капсула: слева круглая кнопка вложения, по центру авто-растущая
|
|
187
|
+
* textarea, справа круглая кнопка отправки; вложения стоят внутри капсулы над строкой.
|
|
188
|
+
* Презентационный, без data-access: наружу торчит только `submitted` с текстом и файлами.
|
|
182
189
|
*
|
|
183
190
|
* Отправка — `Enter` (без Shift) или клик по иконке; `Shift+Enter` — перенос
|
|
184
191
|
* строки. Кнопка отправки активна, пока есть непустой текст или вложения.
|
|
@@ -186,13 +193,20 @@ const BEM_BLOCK$1 = 'rt-message-composer';
|
|
|
186
193
|
class RtMessageComposerComponent {
|
|
187
194
|
#formValue;
|
|
188
195
|
#t_chatPlaceholder;
|
|
196
|
+
/** Текст перенёсся на вторую строку — меряется по высоте textarea после отрисовки. */
|
|
197
|
+
#multiRow;
|
|
189
198
|
constructor() {
|
|
190
199
|
this.#t_chatPlaceholder = rtKitLabel('chatPlaceholder');
|
|
200
|
+
/** Текст перенёсся на вторую строку — меряется по высоте textarea после отрисовки. */
|
|
201
|
+
this.#multiRow = signal(false, /* @ts-ignore */
|
|
202
|
+
...(ngDevMode ? [{ debugName: "#multiRow" }] : /* istanbul ignore next */ []));
|
|
191
203
|
this.t = inject(RT_KIT_LABELS);
|
|
192
204
|
this.placeholderText = computed(() => this.placeholder() || this.#t_chatPlaceholder(), /* @ts-ignore */
|
|
193
205
|
...(ngDevMode ? [{ debugName: "placeholderText" }] : /* istanbul ignore next */ []));
|
|
194
206
|
this.fileInput = viewChild('fileEl', /* @ts-ignore */
|
|
195
207
|
...(ngDevMode ? [{ debugName: "fileInput" }] : /* istanbul ignore next */ []));
|
|
208
|
+
this.textInput = viewChild('textEl', /* @ts-ignore */
|
|
209
|
+
...(ngDevMode ? [{ debugName: "textInput" }] : /* istanbul ignore next */ []));
|
|
196
210
|
this.form = new FormGroup({
|
|
197
211
|
message: new FormControl('', { nonNullable: true }),
|
|
198
212
|
files: new FormControl([], { nonNullable: true }),
|
|
@@ -214,15 +228,25 @@ class RtMessageComposerComponent {
|
|
|
214
228
|
return hasText || hasFiles;
|
|
215
229
|
}, /* @ts-ignore */
|
|
216
230
|
...(ngDevMode ? [{ debugName: "canSend" }] : /* istanbul ignore next */ []));
|
|
231
|
+
/** Капсула выше одной строки: перенос текста, вложения или режим форматирования. */
|
|
232
|
+
this.tall = computed(() => this.#multiRow() || this.formatting() || (this.attachments() && this.files().length > 0), /* @ts-ignore */
|
|
233
|
+
...(ngDevMode ? [{ debugName: "tall" }] : /* istanbul ignore next */ []));
|
|
234
|
+
this.capsuleMods = computed(() => ({
|
|
235
|
+
tall: this.tall(),
|
|
236
|
+
disabled: this.disabled(),
|
|
237
|
+
}), /* @ts-ignore */
|
|
238
|
+
...(ngDevMode ? [{ debugName: "capsuleMods" }] : /* istanbul ignore next */ []));
|
|
217
239
|
/** Текст-подсказка textarea. Пусто — берётся переведённое умолчание. */
|
|
218
240
|
this.placeholder = input('', /* @ts-ignore */
|
|
219
241
|
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
220
242
|
/** Фильтр типов для file-input (`.pdf,.doc,...`). */
|
|
221
243
|
this.accept = input('', /* @ts-ignore */
|
|
222
244
|
...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
|
|
245
|
+
/** Строка под капсулой про Enter и Shift + Enter. */
|
|
246
|
+
this.hint = input(false, { ...(ngDevMode ? { debugName: "hint" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
223
247
|
/** Показывать кнопку вложения и список файлов. */
|
|
224
248
|
this.attachments = input(false, { ...(ngDevMode ? { debugName: "attachments" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
225
|
-
/** Отправка в процессе — блокирует submit
|
|
249
|
+
/** Отправка в процессе — блокирует submit, кнопка отправки крутит индикатор. */
|
|
226
250
|
this.sending = input(false, { ...(ngDevMode ? { debugName: "sending" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
227
251
|
/** Полная блокировка композера. */
|
|
228
252
|
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
@@ -256,6 +280,17 @@ class RtMessageComposerComponent {
|
|
|
256
280
|
this.form.enable({ emitEvent: false });
|
|
257
281
|
}
|
|
258
282
|
});
|
|
283
|
+
// Поле пересоздаётся при смене режима форматирования: наблюдатель идёт за текущим узлом.
|
|
284
|
+
effect((onCleanup) => {
|
|
285
|
+
const node = this.textInput()?.nativeElement;
|
|
286
|
+
if (!node || typeof ResizeObserver === 'undefined') {
|
|
287
|
+
this.#multiRow.set(false);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const observer = new ResizeObserver(() => this.#multiRow.set(rtComposerWraps(node)));
|
|
291
|
+
observer.observe(node);
|
|
292
|
+
onCleanup(() => observer.disconnect());
|
|
293
|
+
});
|
|
259
294
|
effect(() => {
|
|
260
295
|
const dropped = this.droppedFiles();
|
|
261
296
|
if (dropped !== null && dropped.length > 0 && this.attachments()) {
|
|
@@ -310,13 +345,13 @@ class RtMessageComposerComponent {
|
|
|
310
345
|
this.form.reset({ message: '', files: [], delta: null });
|
|
311
346
|
}
|
|
312
347
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtMessageComposerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
313
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtMessageComposerComponent, isStandalone: true, selector: "rt-message-composer", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, sending: { classPropertyName: "sending", publicName: "sending", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, formatting: { classPropertyName: "formatting", publicName: "formatting", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, minRows: { classPropertyName: "minRows", publicName: "minRows", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, droppedFiles: { classPropertyName: "droppedFiles", publicName: "droppedFiles", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, host: { classAttribute: "rt-message-composer" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container rtBlock=\"rt-message-composer\" [formGroup]=\"form\">\n
|
|
348
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtMessageComposerComponent, isStandalone: true, selector: "rt-message-composer", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, sending: { classPropertyName: "sending", publicName: "sending", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, formatting: { classPropertyName: "formatting", publicName: "formatting", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, minRows: { classPropertyName: "minRows", publicName: "minRows", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, droppedFiles: { classPropertyName: "droppedFiles", publicName: "droppedFiles", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted" }, host: { classAttribute: "rt-message-composer" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileEl"], descendants: true, isSignal: true }, { propertyName: "textInput", first: true, predicate: ["textEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container rtBlock=\"rt-message-composer\" [formGroup]=\"form\">\n <div rtElem=\"capsule\" qa-dataid=\"message-composer-capsule\" [rtMod]=\"capsuleMods()\">\n @if (attachments() && files().length) {\n <div rtElem=\"files\" qa-dataid=\"message-composer-files\">\n @for (file of files(); track $index) {\n <rt-file-card\n showRemove\n qa-dataid=\"message-composer-file\"\n size=\"sm\"\n [name]=\"file.name\"\n [sizeBytes]=\"file.size\"\n [disabled]=\"disabled() || sending()\"\n (removed)=\"removeFile($index)\" />\n }\n </div>\n }\n\n @if (formatting()) {\n <rt-rich-editor\n rtElem=\"rich\"\n qa-dataid=\"message-composer-rich\"\n formControlName=\"delta\"\n [placeholder]=\"placeholderText()\"\n [toolbar]=\"toolbar()\"\n (enterPressed)=\"submit()\" />\n }\n\n <div rtElem=\"row\">\n @if (attachments()) {\n <input\n #fileEl\n qa-dataid=\"message-composer-file-input\"\n type=\"file\"\n hidden\n multiple\n [attr.accept]=\"accept() || null\"\n (change)=\"onFilesPicked($event)\" />\n <rt-icon-button\n qa-dataid=\"message-composer-attach\"\n icon=\"paperclip\"\n iconColor=\"muted\"\n radius=\"full\"\n variant=\"ghost\"\n [ariaLabel]=\"t().chatAttachAria\"\n [tooltip]=\"t().chatAttachTooltip\"\n [disabled]=\"disabled() || sending()\"\n (clicked)=\"openPicker()\" />\n }\n\n @if (!formatting()) {\n <textarea\n #textEl\n rtElem=\"input\"\n qa-dataid=\"message-composer-input\"\n cdkTextareaAutosize\n formControlName=\"message\"\n [attr.aria-label]=\"t().chatComposerAria\"\n [placeholder]=\"placeholderText()\"\n [cdkAutosizeMinRows]=\"minRows()\"\n [cdkAutosizeMaxRows]=\"maxRows()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n }\n\n <rt-icon-button\n rtElem=\"send\"\n qa-dataid=\"message-composer-send\"\n icon=\"arrow-up\"\n radius=\"full\"\n variant=\"primary\"\n [ariaLabel]=\"t().chatSendAria\"\n [tooltip]=\"t().chatSendLabel\"\n [loading]=\"sending()\"\n [disabled]=\"!canSend()\"\n (clicked)=\"submit()\" />\n </div>\n </div>\n\n @if (hint()) {\n <p rtElem=\"hint\" qa-dataid=\"message-composer-hint\">{{ t().chatComposerHint }}</p>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-message-composer{--rt-message-composer-radius: var(--rt-radius-full);--rt-message-composer-tall-radius: var(--rt-radius-2xl);--rt-message-composer-border-width: var(--rt-border-width-thin);display:flex;flex-direction:column;gap:calc(var(--rt-space-1) * 1.5);inline-size:100%}.rt-message-composer__capsule{display:flex;flex-direction:column;padding:calc(var(--rt-space-1) * 1.5);border:var(--rt-message-composer-border-width) solid var(--rt-input-color-border);border-radius:var(--rt-message-composer-radius);background:var(--rt-input-color-bg);gap:calc(var(--rt-space-1) * 1.5)}.rt-message-composer__capsule:focus-within{border-color:var(--rt-input-color-border-focus);background:var(--rt-color-bg-surface);box-shadow:var(--rt-input-focus-shadow)}.rt-message-composer__capsule--tall{--rt-message-composer-radius: var(--rt-message-composer-tall-radius)}.rt-message-composer__capsule--disabled{background:var(--rt-input-color-bg-disabled)}.rt-message-composer__files{display:flex;flex-direction:column;gap:var(--rt-space-1)}.rt-message-composer__rich{inline-size:100%}.rt-message-composer__row{display:flex;align-items:flex-end;gap:var(--rt-space-2)}.rt-message-composer__input{box-sizing:content-box;flex:1 1 auto;border:0;margin:0;background:transparent;color:var(--rt-input-color-text);font:inherit;font-size:var(--rt-input-font-size);inline-size:100%;line-height:var(--rt-leading-normal);margin-inline-start:calc(var(--rt-space-1) * 1.5);min-inline-size:0;outline:0;padding-block:calc((var(--rt-control-height-md) - 1lh) / 2);resize:none;scrollbar-color:var(--rt-color-border-default) transparent;scrollbar-gutter:stable;scrollbar-width:thin}.rt-message-composer__input::placeholder{color:var(--rt-input-color-text-placeholder)}.rt-message-composer__input:disabled{cursor:not-allowed}.rt-message-composer__input:disabled::placeholder{color:var(--rt-color-text-disabled)}.rt-message-composer__send{margin-inline-start:auto}.rt-message-composer__hint{margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}}\n"], dependencies: [{ kind: "ngmodule", type:
|
|
314
349
|
// angular
|
|
315
350
|
ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type:
|
|
316
351
|
// cdk
|
|
317
352
|
CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "component", type:
|
|
318
353
|
// standalone components / directives
|
|
319
|
-
RtFileCardComponent, selector: "rt-file-card", inputs: ["name", "sizeBytes", "size", "showDownload", "showRemove", "showRename", "disabled"], outputs: ["download", "removed", "rename"] }, { kind: "component", type: RtIconButtonComponent, selector: "rt-icon-button", inputs: ["icon", "ariaLabel", "variant", "iconColor", "iconFill", "size", "iconSize", "
|
|
354
|
+
RtFileCardComponent, selector: "rt-file-card", inputs: ["name", "sizeBytes", "size", "showDownload", "showRemove", "showRename", "disabled"], outputs: ["download", "removed", "rename"] }, { kind: "component", type: RtIconButtonComponent, selector: "rt-icon-button", inputs: ["icon", "ariaLabel", "variant", "iconColor", "iconFill", "size", "iconSize", "type", "tooltip", "tabIndex", "loading", "disabled", "active", "indicator"], outputs: ["clicked"] }, { kind: "component", type: RtRichEditorComponent, selector: "rt-rich-editor", inputs: ["placeholder", "toolbar"], outputs: ["enterPressed"] }, { kind: "directive", type: BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
320
355
|
}
|
|
321
356
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtMessageComposerComponent, decorators: [{
|
|
322
357
|
type: Component,
|
|
@@ -331,10 +366,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
331
366
|
RtRichEditorComponent,
|
|
332
367
|
BlockDirective,
|
|
333
368
|
ElemDirective,
|
|
369
|
+
ModDirective,
|
|
334
370
|
], host: {
|
|
335
371
|
class: BEM_BLOCK$1,
|
|
336
|
-
}, template: "<ng-container rtBlock=\"rt-message-composer\" [formGroup]=\"form\">\n
|
|
337
|
-
}], ctorParameters: () => [], propDecorators: { fileInput: [{ type: i0.ViewChild, args: ['fileEl', { isSignal: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], sending: [{ type: i0.Input, args: [{ isSignal: true, alias: "sending", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], formatting: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatting", required: false }] }], toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], minRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRows", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], droppedFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedFiles", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
372
|
+
}, template: "<ng-container rtBlock=\"rt-message-composer\" [formGroup]=\"form\">\n <div rtElem=\"capsule\" qa-dataid=\"message-composer-capsule\" [rtMod]=\"capsuleMods()\">\n @if (attachments() && files().length) {\n <div rtElem=\"files\" qa-dataid=\"message-composer-files\">\n @for (file of files(); track $index) {\n <rt-file-card\n showRemove\n qa-dataid=\"message-composer-file\"\n size=\"sm\"\n [name]=\"file.name\"\n [sizeBytes]=\"file.size\"\n [disabled]=\"disabled() || sending()\"\n (removed)=\"removeFile($index)\" />\n }\n </div>\n }\n\n @if (formatting()) {\n <rt-rich-editor\n rtElem=\"rich\"\n qa-dataid=\"message-composer-rich\"\n formControlName=\"delta\"\n [placeholder]=\"placeholderText()\"\n [toolbar]=\"toolbar()\"\n (enterPressed)=\"submit()\" />\n }\n\n <div rtElem=\"row\">\n @if (attachments()) {\n <input\n #fileEl\n qa-dataid=\"message-composer-file-input\"\n type=\"file\"\n hidden\n multiple\n [attr.accept]=\"accept() || null\"\n (change)=\"onFilesPicked($event)\" />\n <rt-icon-button\n qa-dataid=\"message-composer-attach\"\n icon=\"paperclip\"\n iconColor=\"muted\"\n radius=\"full\"\n variant=\"ghost\"\n [ariaLabel]=\"t().chatAttachAria\"\n [tooltip]=\"t().chatAttachTooltip\"\n [disabled]=\"disabled() || sending()\"\n (clicked)=\"openPicker()\" />\n }\n\n @if (!formatting()) {\n <textarea\n #textEl\n rtElem=\"input\"\n qa-dataid=\"message-composer-input\"\n cdkTextareaAutosize\n formControlName=\"message\"\n [attr.aria-label]=\"t().chatComposerAria\"\n [placeholder]=\"placeholderText()\"\n [cdkAutosizeMinRows]=\"minRows()\"\n [cdkAutosizeMaxRows]=\"maxRows()\"\n (keydown)=\"onKeydown($event)\"></textarea>\n }\n\n <rt-icon-button\n rtElem=\"send\"\n qa-dataid=\"message-composer-send\"\n icon=\"arrow-up\"\n radius=\"full\"\n variant=\"primary\"\n [ariaLabel]=\"t().chatSendAria\"\n [tooltip]=\"t().chatSendLabel\"\n [loading]=\"sending()\"\n [disabled]=\"!canSend()\"\n (clicked)=\"submit()\" />\n </div>\n </div>\n\n @if (hint()) {\n <p rtElem=\"hint\" qa-dataid=\"message-composer-hint\">{{ t().chatComposerHint }}</p>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-message-composer{--rt-message-composer-radius: var(--rt-radius-full);--rt-message-composer-tall-radius: var(--rt-radius-2xl);--rt-message-composer-border-width: var(--rt-border-width-thin);display:flex;flex-direction:column;gap:calc(var(--rt-space-1) * 1.5);inline-size:100%}.rt-message-composer__capsule{display:flex;flex-direction:column;padding:calc(var(--rt-space-1) * 1.5);border:var(--rt-message-composer-border-width) solid var(--rt-input-color-border);border-radius:var(--rt-message-composer-radius);background:var(--rt-input-color-bg);gap:calc(var(--rt-space-1) * 1.5)}.rt-message-composer__capsule:focus-within{border-color:var(--rt-input-color-border-focus);background:var(--rt-color-bg-surface);box-shadow:var(--rt-input-focus-shadow)}.rt-message-composer__capsule--tall{--rt-message-composer-radius: var(--rt-message-composer-tall-radius)}.rt-message-composer__capsule--disabled{background:var(--rt-input-color-bg-disabled)}.rt-message-composer__files{display:flex;flex-direction:column;gap:var(--rt-space-1)}.rt-message-composer__rich{inline-size:100%}.rt-message-composer__row{display:flex;align-items:flex-end;gap:var(--rt-space-2)}.rt-message-composer__input{box-sizing:content-box;flex:1 1 auto;border:0;margin:0;background:transparent;color:var(--rt-input-color-text);font:inherit;font-size:var(--rt-input-font-size);inline-size:100%;line-height:var(--rt-leading-normal);margin-inline-start:calc(var(--rt-space-1) * 1.5);min-inline-size:0;outline:0;padding-block:calc((var(--rt-control-height-md) - 1lh) / 2);resize:none;scrollbar-color:var(--rt-color-border-default) transparent;scrollbar-gutter:stable;scrollbar-width:thin}.rt-message-composer__input::placeholder{color:var(--rt-input-color-text-placeholder)}.rt-message-composer__input:disabled{cursor:not-allowed}.rt-message-composer__input:disabled::placeholder{color:var(--rt-color-text-disabled)}.rt-message-composer__send{margin-inline-start:auto}.rt-message-composer__hint{margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}}\n"] }]
|
|
373
|
+
}], ctorParameters: () => [], propDecorators: { fileInput: [{ type: i0.ViewChild, args: ['fileEl', { isSignal: true }] }], textInput: [{ type: i0.ViewChild, args: ['textEl', { isSignal: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], sending: [{ type: i0.Input, args: [{ isSignal: true, alias: "sending", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], formatting: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatting", required: false }] }], toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], minRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "minRows", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], droppedFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "droppedFiles", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
|
|
338
374
|
|
|
339
375
|
/**
|
|
340
376
|
* Захватывает `<ng-template rtChatMessageActions let-message>` — содержимое «…»-меню
|
|
@@ -834,7 +870,7 @@ class RtChatComponent {
|
|
|
834
870
|
// Angular
|
|
835
871
|
CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type:
|
|
836
872
|
// standalone components / directives
|
|
837
|
-
RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "
|
|
873
|
+
RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "loading", "loadingIcon", "pressed"] }, { kind: "directive", type: RtConfirmDirective, selector: "[rtConfirm]", inputs: ["rtConfirm", "rtConfirmTitle", "rtConfirmLabel", "rtConfirmCancelLabel", "rtConfirmTone", "rtConfirmDisabled"], outputs: ["confirmed"], exportAs: ["rtConfirm"] }, { kind: "component", type: RtDeltaViewComponent, selector: "rt-delta-view", inputs: ["delta"] }, { kind: "component", type: RtFileCardComponent, selector: "rt-file-card", inputs: ["name", "sizeBytes", "size", "showDownload", "showRemove", "showRename", "disabled"], outputs: ["download", "removed", "rename"] }, { kind: "component", type: RtFileDropComponent, selector: "rt-file-drop", inputs: ["disabled", "overlayLabel", "zones", "accept"], outputs: ["filesDropped", "zoneFilesDropped", "draggingChange"] }, { kind: "component", type: RtIconButtonComponent, selector: "rt-icon-button", inputs: ["icon", "ariaLabel", "variant", "iconColor", "iconFill", "size", "iconSize", "type", "tooltip", "tabIndex", "loading", "disabled", "active", "indicator"], outputs: ["clicked"] }, { kind: "component", type: RtIconComponent, selector: "rt-icon", inputs: ["name", "size", "color", "fill", "rotate"] }, { kind: "component", type: RtMenuComponent, selector: "rt-menu", inputs: ["icon", "ariaLabel", "align", "panelClass", "size", "disabled"], outputs: ["openedChange"] }, { kind: "component", type: RtMessageComposerComponent, selector: "rt-message-composer", inputs: ["placeholder", "accept", "hint", "attachments", "sending", "disabled", "formatting", "toolbar", "minRows", "maxRows", "droppedFiles"], outputs: ["submitted"] }, { kind: "component", type: RtNoteComponent, selector: "rt-note" }, { kind: "component", type: RtSkeletonWrapperComponent, selector: "rt-skeleton-wrapper", inputs: ["width", "height", "shape", "size", "radius", "animation", "isLoading"] }, { kind: "component", type: RtSpinnerComponent, selector: "rt-spinner", inputs: ["diameter", "color"] }, { kind: "component", type: RtToolbarComponent, selector: "rt-toolbar", inputs: ["dense"] }, { kind: "directive", type: RtToolbarLeftDirective, selector: "[rtToolbarLeft]" }, { kind: "directive", type: RtToolbarRightDirective, selector: "[rtToolbarRight]" }, { kind: "directive", type: BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: RtChatStatusLabelPipe, name: "rtChatStatusLabel" }, { kind: "pipe", type: RtChatMessageHasActionsPipe, name: "rtChatMessageHasActions" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
838
874
|
}
|
|
839
875
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtChatComponent, decorators: [{
|
|
840
876
|
type: Component,
|