@rt-tools/ui-kit-v2 0.34.5 → 0.35.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/fesm2022/rt-tools-ui-kit-v2-ai-prompt-input.mjs +574 -0
- package/fesm2022/rt-tools-ui-kit-v2-ai-prompt-input.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs +62 -3
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs +2 -2
- package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +128 -20
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +2 -2
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs +163 -0
- package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2.mjs +2 -0
- package/package.json +9 -1
- package/src/lib/components/ai-prompt-input/CONTEXT.md +60 -0
- package/src/lib/components/ai-prompt-input/rt-ai-prompt-input.component.scss +113 -0
- package/src/lib/components/markdown-text/rt-markdown-text.component.scss +3 -0
- package/src/lib/components/thread-list/rt-thread-list.component.scss +19 -11
- package/src/lib/components/usage-ring/CONTEXT.md +33 -0
- package/src/lib/components/usage-ring/rt-usage-ring.component.scss +64 -0
- package/src/rich-editor/lib/components/ai-chat/CONTEXT.md +1 -1
- package/src/rich-editor/lib/components/ai-chat/answer/rt-ai-chat-answer.component.scss +1 -0
- package/src/rich-editor/lib/components/ai-chat/rt-ai-chat.component.scss +6 -0
- package/types/rt-tools-ui-kit-v2-ai-prompt-input.d.ts +193 -0
- package/types/rt-tools-ui-kit-v2-core.d.ts +4 -0
- package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +49 -3
- package/types/rt-tools-ui-kit-v2-usage-ring.d.ts +47 -0
- package/types/rt-tools-ui-kit-v2.d.ts +2 -0
|
@@ -44,7 +44,7 @@ var RtMarkdownTextComponent = class RtMarkdownTextComponent {
|
|
|
44
44
|
}],
|
|
45
45
|
ngImport: i0,
|
|
46
46
|
template: "<ng-container rtBlock=\"rt-markdown-text\">\n @for (item of blocks(); track $index) {\n <ng-container *ngTemplateOutlet=\"blockTpl; context: { $implicit: item }\" />\n }\n\n <ng-template #blockTpl let-item>\n @switch (item.kind) {\n @case (blockKind.Heading) {\n <div\n rtElem=\"heading\"\n qa-dataid=\"markdown-heading\"\n role=\"heading\"\n [attr.aria-level]=\"item.level\"\n [rtMod]=\"{ level: item.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </div>\n }\n @case (blockKind.List) {\n @if (item.ordered) {\n <ol rtElem=\"list\" qa-dataid=\"markdown-list\" [rtMod]=\"{ ordered: true }\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ol>\n } @else {\n <ul rtElem=\"list\" qa-dataid=\"markdown-list\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ul>\n }\n }\n @case (blockKind.Quote) {\n <blockquote rtElem=\"quote\" qa-dataid=\"markdown-quote\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </blockquote>\n }\n @case (blockKind.Code) {\n <pre rtElem=\"code\" qa-dataid=\"markdown-code\"><code>{{ item.code }}</code></pre>\n }\n @case (blockKind.Table) {\n <ng-container *ngTemplateOutlet=\"tableTpl; context: { $implicit: item }\" />\n }\n @default {\n <p rtElem=\"paragraph\" qa-dataid=\"markdown-paragraph\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </p>\n }\n }\n </ng-template>\n\n <ng-template #itemsTpl let-items>\n @for (point of items; track $index) {\n <li rtElem=\"item\" qa-dataid=\"markdown-item\" [rtMod]=\"{ level: point.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: point.content }\" />\n </li>\n }\n </ng-template>\n\n <ng-template #tableTpl let-item>\n <div rtElem=\"table-scroll\" qa-dataid=\"markdown-table-scroll\">\n <table rtElem=\"table\" qa-dataid=\"markdown-table\">\n <thead>\n <tr>\n @for (cell of item.head; track $index) {\n <th rtElem=\"head-cell\" qa-dataid=\"markdown-head-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of item.rows; track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td rtElem=\"cell\" qa-dataid=\"markdown-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </ng-template>\n\n <!--\n Ветки шаблона кусков пишутся без переносов, а форматтер отключён для них нарочно: перенос\n строки в разметке становится пробелом, и размеченный кусок отъезжает от соседнего знака —\n «жирно , а рядом».\n -->\n <!-- prettier-ignore -->\n <ng-template #inlineTpl let-nodes>@for (node of nodes; track $index) {@switch (node.kind) {@case (inlineKind.Strong) {<strong rtElem=\"strong\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></strong>}@case (inlineKind.Emphasis) {<em rtElem=\"emphasis\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></em>}@case (inlineKind.Strike) {<s rtElem=\"strike\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></s>}@case (inlineKind.Code) {<code rtElem=\"code-inline\" qa-dataid=\"markdown-code-inline\">{{ node.text }}</code>}@case (inlineKind.Link) {<a rtElem=\"link\" qa-dataid=\"markdown-link\" rel=\"noopener noreferrer\" target=\"_blank\" [href]=\"node.href\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></a>}@case (inlineKind.Break) {<br />}@default {{{ node.text }}}}}</ng-template>\n</ng-container>\n",
|
|
47
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-markdown-text{--rt-markdown-text-radius: var(--rt-radius-sm);--rt-markdown-text-border-width: var(--rt-border-width-thin);display:flex;min-width:0;max-width:100%;flex-direction:column;color:var(--rt-color-text-primary);font-family:var(--rt-font-family-sans);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-regular);gap:var(--rt-space-sm);letter-spacing:var(--rt-letter-spacing-wide);line-height:var(--rt-leading-snug)}.rt-markdown-text__heading{margin:0;color:var(--rt-color-text-primary);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__heading--level--1{font-size:var(--rt-text-lg)}.rt-markdown-text__heading--level--2{font-size:var(--rt-text-md)}.rt-markdown-text__heading--level--3,.rt-markdown-text__heading--level--4,.rt-markdown-text__heading--level--5,.rt-markdown-text__heading--level--6{font-size:var(--rt-text-sm)}.rt-markdown-text__paragraph{margin:0}.rt-markdown-text__list{padding-left:var(--rt-space-md);margin:0;list-style:disc}.rt-markdown-text__list--ordered{list-style:decimal}.rt-markdown-text__item--level--1{margin-left:var(--rt-space-md)}.rt-markdown-text__item--level--2{margin-left:var(--rt-space-lg)}.rt-markdown-text__quote{padding-left:var(--rt-space-sm);border-left:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);margin:0;color:var(--rt-color-text-muted)}.rt-markdown-text__code{max-width:100%;padding:var(--rt-space-sm);border-radius:var(--rt-markdown-text-radius);margin:0;background:var(--rt-color-bg-subtle);color:var(--rt-color-text-primary);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs);line-height:var(--rt-leading-snug);overflow-x:auto}.rt-markdown-text__code-inline{padding:0 var(--rt-space-2xs);border-radius:var(--rt-markdown-text-radius);background:var(--rt-color-bg-subtle);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs)}.rt-markdown-text__table-scroll{max-width:100%;overflow-x:auto}.rt-markdown-text__table{width:100%;border-collapse:collapse}.rt-markdown-text__head-cell,.rt-markdown-text__cell{padding:var(--rt-space-2xs) var(--rt-space-sm);border:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);text-align:left}.rt-markdown-text__head-cell{color:var(--rt-color-text-muted);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__strong{font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__emphasis{font-style:italic}.rt-markdown-text__strike{text-decoration:line-through}.rt-markdown-text__link{color:var(--rt-color-text-link);text-decoration:underline}.rt-markdown-text[data-rt-radius=none]{--rt-markdown-text-radius: var(--rt-radius-none)}.rt-markdown-text[data-rt-radius=xs]{--rt-markdown-text-radius: var(--rt-radius-xs)}.rt-markdown-text[data-rt-radius=sm]{--rt-markdown-text-radius: var(--rt-radius-sm)}.rt-markdown-text[data-rt-radius=ms]{--rt-markdown-text-radius: var(--rt-radius-ms)}.rt-markdown-text[data-rt-radius=md]{--rt-markdown-text-radius: var(--rt-radius-md)}.rt-markdown-text[data-rt-radius=lg]{--rt-markdown-text-radius: var(--rt-radius-lg)}.rt-markdown-text[data-rt-radius=xl]{--rt-markdown-text-radius: var(--rt-radius-xl)}.rt-markdown-text[data-rt-radius=\"2xl\"]{--rt-markdown-text-radius: var(--rt-radius-2xl)}.rt-markdown-text[data-rt-radius=full]{--rt-markdown-text-radius: var(--rt-radius-full)}}\n"],
|
|
47
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-markdown-text{--rt-markdown-text-radius: var(--rt-radius-sm);--rt-markdown-text-border-width: var(--rt-border-width-thin);display:flex;min-width:0;max-width:100%;flex-direction:column;color:var(--rt-color-text-primary);font-family:var(--rt-font-family-sans);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-regular);gap:var(--rt-space-sm);letter-spacing:var(--rt-letter-spacing-wide);line-height:var(--rt-leading-snug);overflow-wrap:anywhere}.rt-markdown-text__heading{margin:0;color:var(--rt-color-text-primary);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__heading--level--1{font-size:var(--rt-text-lg)}.rt-markdown-text__heading--level--2{font-size:var(--rt-text-md)}.rt-markdown-text__heading--level--3,.rt-markdown-text__heading--level--4,.rt-markdown-text__heading--level--5,.rt-markdown-text__heading--level--6{font-size:var(--rt-text-sm)}.rt-markdown-text__paragraph{margin:0}.rt-markdown-text__list{padding-left:var(--rt-space-md);margin:0;list-style:disc}.rt-markdown-text__list--ordered{list-style:decimal}.rt-markdown-text__item--level--1{margin-left:var(--rt-space-md)}.rt-markdown-text__item--level--2{margin-left:var(--rt-space-lg)}.rt-markdown-text__quote{padding-left:var(--rt-space-sm);border-left:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);margin:0;color:var(--rt-color-text-muted)}.rt-markdown-text__code{max-width:100%;padding:var(--rt-space-sm);border-radius:var(--rt-markdown-text-radius);margin:0;background:var(--rt-color-bg-subtle);color:var(--rt-color-text-primary);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs);line-height:var(--rt-leading-snug);overflow-x:auto}.rt-markdown-text__code-inline{padding:0 var(--rt-space-2xs);border-radius:var(--rt-markdown-text-radius);background:var(--rt-color-bg-subtle);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs)}.rt-markdown-text__table-scroll{max-width:100%;overflow-x:auto}.rt-markdown-text__table{width:100%;border-collapse:collapse}.rt-markdown-text__head-cell,.rt-markdown-text__cell{padding:var(--rt-space-2xs) var(--rt-space-sm);border:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);text-align:left}.rt-markdown-text__head-cell{color:var(--rt-color-text-muted);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__strong{font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__emphasis{font-style:italic}.rt-markdown-text__strike{text-decoration:line-through}.rt-markdown-text__link{color:var(--rt-color-text-link);text-decoration:underline}.rt-markdown-text[data-rt-radius=none]{--rt-markdown-text-radius: var(--rt-radius-none)}.rt-markdown-text[data-rt-radius=xs]{--rt-markdown-text-radius: var(--rt-radius-xs)}.rt-markdown-text[data-rt-radius=sm]{--rt-markdown-text-radius: var(--rt-radius-sm)}.rt-markdown-text[data-rt-radius=ms]{--rt-markdown-text-radius: var(--rt-radius-ms)}.rt-markdown-text[data-rt-radius=md]{--rt-markdown-text-radius: var(--rt-radius-md)}.rt-markdown-text[data-rt-radius=lg]{--rt-markdown-text-radius: var(--rt-radius-lg)}.rt-markdown-text[data-rt-radius=xl]{--rt-markdown-text-radius: var(--rt-radius-xl)}.rt-markdown-text[data-rt-radius=\"2xl\"]{--rt-markdown-text-radius: var(--rt-radius-2xl)}.rt-markdown-text[data-rt-radius=full]{--rt-markdown-text-radius: var(--rt-radius-full)}}\n"],
|
|
48
48
|
dependencies: [
|
|
49
49
|
{
|
|
50
50
|
kind: "directive",
|
|
@@ -102,7 +102,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
102
102
|
}],
|
|
103
103
|
host: { class: BEM_BLOCK },
|
|
104
104
|
template: "<ng-container rtBlock=\"rt-markdown-text\">\n @for (item of blocks(); track $index) {\n <ng-container *ngTemplateOutlet=\"blockTpl; context: { $implicit: item }\" />\n }\n\n <ng-template #blockTpl let-item>\n @switch (item.kind) {\n @case (blockKind.Heading) {\n <div\n rtElem=\"heading\"\n qa-dataid=\"markdown-heading\"\n role=\"heading\"\n [attr.aria-level]=\"item.level\"\n [rtMod]=\"{ level: item.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </div>\n }\n @case (blockKind.List) {\n @if (item.ordered) {\n <ol rtElem=\"list\" qa-dataid=\"markdown-list\" [rtMod]=\"{ ordered: true }\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ol>\n } @else {\n <ul rtElem=\"list\" qa-dataid=\"markdown-list\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ul>\n }\n }\n @case (blockKind.Quote) {\n <blockquote rtElem=\"quote\" qa-dataid=\"markdown-quote\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </blockquote>\n }\n @case (blockKind.Code) {\n <pre rtElem=\"code\" qa-dataid=\"markdown-code\"><code>{{ item.code }}</code></pre>\n }\n @case (blockKind.Table) {\n <ng-container *ngTemplateOutlet=\"tableTpl; context: { $implicit: item }\" />\n }\n @default {\n <p rtElem=\"paragraph\" qa-dataid=\"markdown-paragraph\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </p>\n }\n }\n </ng-template>\n\n <ng-template #itemsTpl let-items>\n @for (point of items; track $index) {\n <li rtElem=\"item\" qa-dataid=\"markdown-item\" [rtMod]=\"{ level: point.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: point.content }\" />\n </li>\n }\n </ng-template>\n\n <ng-template #tableTpl let-item>\n <div rtElem=\"table-scroll\" qa-dataid=\"markdown-table-scroll\">\n <table rtElem=\"table\" qa-dataid=\"markdown-table\">\n <thead>\n <tr>\n @for (cell of item.head; track $index) {\n <th rtElem=\"head-cell\" qa-dataid=\"markdown-head-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of item.rows; track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td rtElem=\"cell\" qa-dataid=\"markdown-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </ng-template>\n\n <!--\n Ветки шаблона кусков пишутся без переносов, а форматтер отключён для них нарочно: перенос\n строки в разметке становится пробелом, и размеченный кусок отъезжает от соседнего знака —\n «жирно , а рядом».\n -->\n <!-- prettier-ignore -->\n <ng-template #inlineTpl let-nodes>@for (node of nodes; track $index) {@switch (node.kind) {@case (inlineKind.Strong) {<strong rtElem=\"strong\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></strong>}@case (inlineKind.Emphasis) {<em rtElem=\"emphasis\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></em>}@case (inlineKind.Strike) {<s rtElem=\"strike\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></s>}@case (inlineKind.Code) {<code rtElem=\"code-inline\" qa-dataid=\"markdown-code-inline\">{{ node.text }}</code>}@case (inlineKind.Link) {<a rtElem=\"link\" qa-dataid=\"markdown-link\" rel=\"noopener noreferrer\" target=\"_blank\" [href]=\"node.href\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></a>}@case (inlineKind.Break) {<br />}@default {{{ node.text }}}}}</ng-template>\n</ng-container>\n",
|
|
105
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-markdown-text{--rt-markdown-text-radius: var(--rt-radius-sm);--rt-markdown-text-border-width: var(--rt-border-width-thin);display:flex;min-width:0;max-width:100%;flex-direction:column;color:var(--rt-color-text-primary);font-family:var(--rt-font-family-sans);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-regular);gap:var(--rt-space-sm);letter-spacing:var(--rt-letter-spacing-wide);line-height:var(--rt-leading-snug)}.rt-markdown-text__heading{margin:0;color:var(--rt-color-text-primary);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__heading--level--1{font-size:var(--rt-text-lg)}.rt-markdown-text__heading--level--2{font-size:var(--rt-text-md)}.rt-markdown-text__heading--level--3,.rt-markdown-text__heading--level--4,.rt-markdown-text__heading--level--5,.rt-markdown-text__heading--level--6{font-size:var(--rt-text-sm)}.rt-markdown-text__paragraph{margin:0}.rt-markdown-text__list{padding-left:var(--rt-space-md);margin:0;list-style:disc}.rt-markdown-text__list--ordered{list-style:decimal}.rt-markdown-text__item--level--1{margin-left:var(--rt-space-md)}.rt-markdown-text__item--level--2{margin-left:var(--rt-space-lg)}.rt-markdown-text__quote{padding-left:var(--rt-space-sm);border-left:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);margin:0;color:var(--rt-color-text-muted)}.rt-markdown-text__code{max-width:100%;padding:var(--rt-space-sm);border-radius:var(--rt-markdown-text-radius);margin:0;background:var(--rt-color-bg-subtle);color:var(--rt-color-text-primary);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs);line-height:var(--rt-leading-snug);overflow-x:auto}.rt-markdown-text__code-inline{padding:0 var(--rt-space-2xs);border-radius:var(--rt-markdown-text-radius);background:var(--rt-color-bg-subtle);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs)}.rt-markdown-text__table-scroll{max-width:100%;overflow-x:auto}.rt-markdown-text__table{width:100%;border-collapse:collapse}.rt-markdown-text__head-cell,.rt-markdown-text__cell{padding:var(--rt-space-2xs) var(--rt-space-sm);border:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);text-align:left}.rt-markdown-text__head-cell{color:var(--rt-color-text-muted);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__strong{font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__emphasis{font-style:italic}.rt-markdown-text__strike{text-decoration:line-through}.rt-markdown-text__link{color:var(--rt-color-text-link);text-decoration:underline}.rt-markdown-text[data-rt-radius=none]{--rt-markdown-text-radius: var(--rt-radius-none)}.rt-markdown-text[data-rt-radius=xs]{--rt-markdown-text-radius: var(--rt-radius-xs)}.rt-markdown-text[data-rt-radius=sm]{--rt-markdown-text-radius: var(--rt-radius-sm)}.rt-markdown-text[data-rt-radius=ms]{--rt-markdown-text-radius: var(--rt-radius-ms)}.rt-markdown-text[data-rt-radius=md]{--rt-markdown-text-radius: var(--rt-radius-md)}.rt-markdown-text[data-rt-radius=lg]{--rt-markdown-text-radius: var(--rt-radius-lg)}.rt-markdown-text[data-rt-radius=xl]{--rt-markdown-text-radius: var(--rt-radius-xl)}.rt-markdown-text[data-rt-radius=\"2xl\"]{--rt-markdown-text-radius: var(--rt-radius-2xl)}.rt-markdown-text[data-rt-radius=full]{--rt-markdown-text-radius: var(--rt-radius-full)}}\n"]
|
|
105
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-markdown-text{--rt-markdown-text-radius: var(--rt-radius-sm);--rt-markdown-text-border-width: var(--rt-border-width-thin);display:flex;min-width:0;max-width:100%;flex-direction:column;color:var(--rt-color-text-primary);font-family:var(--rt-font-family-sans);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-regular);gap:var(--rt-space-sm);letter-spacing:var(--rt-letter-spacing-wide);line-height:var(--rt-leading-snug);overflow-wrap:anywhere}.rt-markdown-text__heading{margin:0;color:var(--rt-color-text-primary);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__heading--level--1{font-size:var(--rt-text-lg)}.rt-markdown-text__heading--level--2{font-size:var(--rt-text-md)}.rt-markdown-text__heading--level--3,.rt-markdown-text__heading--level--4,.rt-markdown-text__heading--level--5,.rt-markdown-text__heading--level--6{font-size:var(--rt-text-sm)}.rt-markdown-text__paragraph{margin:0}.rt-markdown-text__list{padding-left:var(--rt-space-md);margin:0;list-style:disc}.rt-markdown-text__list--ordered{list-style:decimal}.rt-markdown-text__item--level--1{margin-left:var(--rt-space-md)}.rt-markdown-text__item--level--2{margin-left:var(--rt-space-lg)}.rt-markdown-text__quote{padding-left:var(--rt-space-sm);border-left:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);margin:0;color:var(--rt-color-text-muted)}.rt-markdown-text__code{max-width:100%;padding:var(--rt-space-sm);border-radius:var(--rt-markdown-text-radius);margin:0;background:var(--rt-color-bg-subtle);color:var(--rt-color-text-primary);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs);line-height:var(--rt-leading-snug);overflow-x:auto}.rt-markdown-text__code-inline{padding:0 var(--rt-space-2xs);border-radius:var(--rt-markdown-text-radius);background:var(--rt-color-bg-subtle);font-family:var(--rt-font-family-mono);font-size:var(--rt-text-2xs)}.rt-markdown-text__table-scroll{max-width:100%;overflow-x:auto}.rt-markdown-text__table{width:100%;border-collapse:collapse}.rt-markdown-text__head-cell,.rt-markdown-text__cell{padding:var(--rt-space-2xs) var(--rt-space-sm);border:var(--rt-markdown-text-border-width) solid var(--rt-color-border-default);text-align:left}.rt-markdown-text__head-cell{color:var(--rt-color-text-muted);font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__strong{font-weight:var(--rt-font-weight-semibold)}.rt-markdown-text__emphasis{font-style:italic}.rt-markdown-text__strike{text-decoration:line-through}.rt-markdown-text__link{color:var(--rt-color-text-link);text-decoration:underline}.rt-markdown-text[data-rt-radius=none]{--rt-markdown-text-radius: var(--rt-radius-none)}.rt-markdown-text[data-rt-radius=xs]{--rt-markdown-text-radius: var(--rt-radius-xs)}.rt-markdown-text[data-rt-radius=sm]{--rt-markdown-text-radius: var(--rt-radius-sm)}.rt-markdown-text[data-rt-radius=ms]{--rt-markdown-text-radius: var(--rt-radius-ms)}.rt-markdown-text[data-rt-radius=md]{--rt-markdown-text-radius: var(--rt-radius-md)}.rt-markdown-text[data-rt-radius=lg]{--rt-markdown-text-radius: var(--rt-radius-lg)}.rt-markdown-text[data-rt-radius=xl]{--rt-markdown-text-radius: var(--rt-radius-xl)}.rt-markdown-text[data-rt-radius=\"2xl\"]{--rt-markdown-text-radius: var(--rt-radius-2xl)}.rt-markdown-text[data-rt-radius=full]{--rt-markdown-text-radius: var(--rt-radius-full)}}\n"]
|
|
106
106
|
}]
|
|
107
107
|
}],
|
|
108
108
|
propDecorators: { text: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-markdown-text.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/markdown-text/rt-markdown-text.component.ts","../../../projects/ui-kit-v2/src/lib/components/markdown-text/rt-markdown-text.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { computed, input, ChangeDetectionStrategy, Component, InputSignal, Signal, ViewEncapsulation } from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { parseMarkdown } from '@rt-tools/ui-kit-v2/core';\nimport { ERtMarkdownBlock, ERtMarkdownInline, IRtMarkdownBlockNode } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\n\nconst BEM_BLOCK: string = 'rt-markdown-text';\n\n/**\n * Текст, написанный разметкой, показанный узлами.\n *\n * Перечень разметки зашит в разборщике и входом не задаётся: вход у компонента один — сам\n * текст. Настраивать нечего, значит нечем и ослабить.\n *\n * Присланная строка в страницу не отдаётся ни разу: компонент рисует дерево узлов, которое\n * вернул разбор, и другого пути у текста внутрь страницы нет. Поэтому сырой HTML, картинки и\n * адреса чужих схем показываются видимым текстом — узла для них разборщик не строит.\n *\n * Таблица рисуется своей разметкой, а не таблицей кита: та объявляет колонки заранее\n * директивами, а число столбцов здесь приходит из текста и заранее не известно никому.\n */\n@Component({\n selector: 'rt-markdown-text',\n templateUrl: './rt-markdown-text.component.html',\n styleUrl: './rt-markdown-text.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n NgTemplateOutlet,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMarkdownTextComponent {\n /** Роды блоков в шаблоне: сравнение идёт со значением перечисления, а не со строкой. */\n protected readonly blockKind: typeof ERtMarkdownBlock = ERtMarkdownBlock;\n\n /** Роды кусков строки в шаблоне. */\n protected readonly inlineKind: typeof ERtMarkdownInline = ERtMarkdownInline;\n\n protected readonly blocks: Signal<readonly IRtMarkdownBlockNode[]> = computed((): readonly IRtMarkdownBlockNode[] =>\n parseMarkdown(this.text())\n );\n\n public readonly text: InputSignal<string | null> = input.required<string | null>();\n}\n","<ng-container rtBlock=\"rt-markdown-text\">\n @for (item of blocks(); track $index) {\n <ng-container *ngTemplateOutlet=\"blockTpl; context: { $implicit: item }\" />\n }\n\n <ng-template #blockTpl let-item>\n @switch (item.kind) {\n @case (blockKind.Heading) {\n <div\n rtElem=\"heading\"\n qa-dataid=\"markdown-heading\"\n role=\"heading\"\n [attr.aria-level]=\"item.level\"\n [rtMod]=\"{ level: item.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </div>\n }\n @case (blockKind.List) {\n @if (item.ordered) {\n <ol rtElem=\"list\" qa-dataid=\"markdown-list\" [rtMod]=\"{ ordered: true }\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ol>\n } @else {\n <ul rtElem=\"list\" qa-dataid=\"markdown-list\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ul>\n }\n }\n @case (blockKind.Quote) {\n <blockquote rtElem=\"quote\" qa-dataid=\"markdown-quote\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </blockquote>\n }\n @case (blockKind.Code) {\n <pre rtElem=\"code\" qa-dataid=\"markdown-code\"><code>{{ item.code }}</code></pre>\n }\n @case (blockKind.Table) {\n <ng-container *ngTemplateOutlet=\"tableTpl; context: { $implicit: item }\" />\n }\n @default {\n <p rtElem=\"paragraph\" qa-dataid=\"markdown-paragraph\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </p>\n }\n }\n </ng-template>\n\n <ng-template #itemsTpl let-items>\n @for (point of items; track $index) {\n <li rtElem=\"item\" qa-dataid=\"markdown-item\" [rtMod]=\"{ level: point.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: point.content }\" />\n </li>\n }\n </ng-template>\n\n <ng-template #tableTpl let-item>\n <div rtElem=\"table-scroll\" qa-dataid=\"markdown-table-scroll\">\n <table rtElem=\"table\" qa-dataid=\"markdown-table\">\n <thead>\n <tr>\n @for (cell of item.head; track $index) {\n <th rtElem=\"head-cell\" qa-dataid=\"markdown-head-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of item.rows; track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td rtElem=\"cell\" qa-dataid=\"markdown-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </ng-template>\n\n <!--\n Ветки шаблона кусков пишутся без переносов, а форматтер отключён для них нарочно: перенос\n строки в разметке становится пробелом, и размеченный кусок отъезжает от соседнего знака —\n «жирно , а рядом».\n -->\n <!-- prettier-ignore -->\n <ng-template #inlineTpl let-nodes>@for (node of nodes; track $index) {@switch (node.kind) {@case (inlineKind.Strong) {<strong rtElem=\"strong\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></strong>}@case (inlineKind.Emphasis) {<em rtElem=\"emphasis\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></em>}@case (inlineKind.Strike) {<s rtElem=\"strike\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></s>}@case (inlineKind.Code) {<code rtElem=\"code-inline\" qa-dataid=\"markdown-code-inline\">{{ node.text }}</code>}@case (inlineKind.Link) {<a rtElem=\"link\" qa-dataid=\"markdown-link\" rel=\"noopener noreferrer\" target=\"_blank\" [href]=\"node.href\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></a>}@case (inlineKind.Break) {<br />}@default {{{ node.text }}}}}</ng-template>\n</ng-container>\n"],"mappings":";;;;;;;AASA,MAAM,YAAoB;AAiC1B,IAAa,0BAAb,MAAa,wBAAuB;CAlBpC,cAAA;EAoBuB,KAAA,YAAqC;EAGrC,KAAA,aAAuC;EAEvC,KAAA,SAAkD,eACjE,cAAc,KAAK,KAAI,CAAE,GAC5B,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAEe,KAAA,OAAmC,MAAM,SAAyB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACrF;CAZY;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAuB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAvB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAuB,cAAA;GAAA,UAAA;GAAA,QAAA,EAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA,EAAA;GAAA,MAAA,EAAA,gBAAA,mBAAA;GAAA,gBAAA,CAAA;IAAA,WAAA,GAAA;IAAA,QAAA,CAAA,UAAA,QAAA;GAAA,CAAA;GAAA,UAAA;GAAA,UC1CpC;GA0FA,QAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-markdown-text.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/markdown-text/rt-markdown-text.component.ts","../../../projects/ui-kit-v2/src/lib/components/markdown-text/rt-markdown-text.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { computed, input, ChangeDetectionStrategy, Component, InputSignal, Signal, ViewEncapsulation } from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { parseMarkdown } from '@rt-tools/ui-kit-v2/core';\nimport { ERtMarkdownBlock, ERtMarkdownInline, IRtMarkdownBlockNode } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\n\nconst BEM_BLOCK: string = 'rt-markdown-text';\n\n/**\n * Текст, написанный разметкой, показанный узлами.\n *\n * Перечень разметки зашит в разборщике и входом не задаётся: вход у компонента один — сам\n * текст. Настраивать нечего, значит нечем и ослабить.\n *\n * Присланная строка в страницу не отдаётся ни разу: компонент рисует дерево узлов, которое\n * вернул разбор, и другого пути у текста внутрь страницы нет. Поэтому сырой HTML, картинки и\n * адреса чужих схем показываются видимым текстом — узла для них разборщик не строит.\n *\n * Таблица рисуется своей разметкой, а не таблицей кита: та объявляет колонки заранее\n * директивами, а число столбцов здесь приходит из текста и заранее не известно никому.\n */\n@Component({\n selector: 'rt-markdown-text',\n templateUrl: './rt-markdown-text.component.html',\n styleUrl: './rt-markdown-text.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n NgTemplateOutlet,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMarkdownTextComponent {\n /** Роды блоков в шаблоне: сравнение идёт со значением перечисления, а не со строкой. */\n protected readonly blockKind: typeof ERtMarkdownBlock = ERtMarkdownBlock;\n\n /** Роды кусков строки в шаблоне. */\n protected readonly inlineKind: typeof ERtMarkdownInline = ERtMarkdownInline;\n\n protected readonly blocks: Signal<readonly IRtMarkdownBlockNode[]> = computed((): readonly IRtMarkdownBlockNode[] =>\n parseMarkdown(this.text())\n );\n\n public readonly text: InputSignal<string | null> = input.required<string | null>();\n}\n","<ng-container rtBlock=\"rt-markdown-text\">\n @for (item of blocks(); track $index) {\n <ng-container *ngTemplateOutlet=\"blockTpl; context: { $implicit: item }\" />\n }\n\n <ng-template #blockTpl let-item>\n @switch (item.kind) {\n @case (blockKind.Heading) {\n <div\n rtElem=\"heading\"\n qa-dataid=\"markdown-heading\"\n role=\"heading\"\n [attr.aria-level]=\"item.level\"\n [rtMod]=\"{ level: item.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </div>\n }\n @case (blockKind.List) {\n @if (item.ordered) {\n <ol rtElem=\"list\" qa-dataid=\"markdown-list\" [rtMod]=\"{ ordered: true }\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ol>\n } @else {\n <ul rtElem=\"list\" qa-dataid=\"markdown-list\">\n <ng-container *ngTemplateOutlet=\"itemsTpl; context: { $implicit: item.items }\" />\n </ul>\n }\n }\n @case (blockKind.Quote) {\n <blockquote rtElem=\"quote\" qa-dataid=\"markdown-quote\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </blockquote>\n }\n @case (blockKind.Code) {\n <pre rtElem=\"code\" qa-dataid=\"markdown-code\"><code>{{ item.code }}</code></pre>\n }\n @case (blockKind.Table) {\n <ng-container *ngTemplateOutlet=\"tableTpl; context: { $implicit: item }\" />\n }\n @default {\n <p rtElem=\"paragraph\" qa-dataid=\"markdown-paragraph\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: item.content }\" />\n </p>\n }\n }\n </ng-template>\n\n <ng-template #itemsTpl let-items>\n @for (point of items; track $index) {\n <li rtElem=\"item\" qa-dataid=\"markdown-item\" [rtMod]=\"{ level: point.levelName }\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: point.content }\" />\n </li>\n }\n </ng-template>\n\n <ng-template #tableTpl let-item>\n <div rtElem=\"table-scroll\" qa-dataid=\"markdown-table-scroll\">\n <table rtElem=\"table\" qa-dataid=\"markdown-table\">\n <thead>\n <tr>\n @for (cell of item.head; track $index) {\n <th rtElem=\"head-cell\" qa-dataid=\"markdown-head-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of item.rows; track $index) {\n <tr>\n @for (cell of row; track $index) {\n <td rtElem=\"cell\" qa-dataid=\"markdown-cell\">\n <ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: cell }\" />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n </ng-template>\n\n <!--\n Ветки шаблона кусков пишутся без переносов, а форматтер отключён для них нарочно: перенос\n строки в разметке становится пробелом, и размеченный кусок отъезжает от соседнего знака —\n «жирно , а рядом».\n -->\n <!-- prettier-ignore -->\n <ng-template #inlineTpl let-nodes>@for (node of nodes; track $index) {@switch (node.kind) {@case (inlineKind.Strong) {<strong rtElem=\"strong\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></strong>}@case (inlineKind.Emphasis) {<em rtElem=\"emphasis\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></em>}@case (inlineKind.Strike) {<s rtElem=\"strike\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></s>}@case (inlineKind.Code) {<code rtElem=\"code-inline\" qa-dataid=\"markdown-code-inline\">{{ node.text }}</code>}@case (inlineKind.Link) {<a rtElem=\"link\" qa-dataid=\"markdown-link\" rel=\"noopener noreferrer\" target=\"_blank\" [href]=\"node.href\"><ng-container *ngTemplateOutlet=\"inlineTpl; context: { $implicit: node.children }\" /></a>}@case (inlineKind.Break) {<br />}@default {{{ node.text }}}}}</ng-template>\n</ng-container>\n"],"mappings":";;;;;;;AASA,MAAM,YAAoB;AAiC1B,IAAa,0BAAb,MAAa,wBAAuB;CAlBpC,cAAA;EAoBuB,KAAA,YAAqC;EAGrC,KAAA,aAAuC;EAEvC,KAAA,SAAkD,eACjE,cAAc,KAAK,KAAI,CAAE,GAC5B,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAEe,KAAA,OAAmC,MAAM,SAAyB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACrF;CAZY;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAuB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAvB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAuB,cAAA;GAAA,UAAA;GAAA,QAAA,EAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA,EAAA;GAAA,MAAA,EAAA,gBAAA,mBAAA;GAAA,gBAAA,CAAA;IAAA,WAAA,GAAA;IAAA,QAAA,CAAA,UAAA,QAAA;GAAA,CAAA;GAAA,UAAA;GAAA,UC1CpC;GA0FA,QAAA,CAAA,uzGAAA;GAAA,cAAA;IAAA;KAAA,MAAA;KAAA,MD1DQ;KAAc,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACd;KAAa,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACb;KAAY,UAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACZ;KAAgB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;KAAA;IAAA;GAAA;GAAA,iBAAA,GAAA,wBAAA;GAAA,eAAA,GAAA,kBAAA;EAAA,CAAA;CAAA;;AAOX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAuB,YAAA,CAAA;EAlBnC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAkB,iBAGX,wBAAwB;GAAM,eAChC,kBAAkB;GAAI,SAC5B;IAEL;IACA;IACA;IACA;GACH;GAAA,gBACe,CAAC;IAAE,WAAW;IAAmB,QAAQ,CAAC,QAAQ;GAAC,CAAE;GAAC,MAChE,EACF,OAAO,UACV;GAAA,UAAA;GAAA,QAAA,CAAA,uzGAAA;EAAA,CAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injector, Pipe, TemplateRef, ViewEncapsulation, afterNextRender, afterRenderEffect, booleanAttribute, computed, contentChild, effect, forwardRef, inject, input, model, numberAttribute, output, signal, viewChild } from "@angular/core";
|
|
3
3
|
import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
|
|
4
|
-
import { RT_KIT_LABELS, RT_KIT_LOCALE, RtAiRunStatusComponent, RtButtonDirective, RtConfirmDirective, RtCopyValueComponent, RtDeltaViewComponent, RtEmptyStateComponent, RtFileCardComponent, RtFileDropComponent, RtFormControlBase, RtIconButtonComponent, RtIconComponent, RtMarkdownTextComponent, RtMenuComponent, RtMenuItemComponent, RtMessageComponent, RtNoteComponent, RtPromptSuggestionComponent, RtServiceLogoComponent, RtSkeletonWrapperComponent, RtSpinnerComponent, RtThreadListComponent, RtThreadListRowActionsDirective, RtThreadListRowDirective, RtToolbarComponent, RtToolbarLeftDirective, RtToolbarRightDirective, coerceQuillDeltaOutput, fileNameFromUrl, markdownToPlainText, rtKitLabel, rtMatchParts } from "@rt-tools/ui-kit-v2";
|
|
4
|
+
import { RT_KIT_LABELS, RT_KIT_LOCALE, RtAiPromptInputComponent, RtAiRunStatusComponent, RtButtonDirective, RtConfirmDirective, RtCopyValueComponent, RtDeltaViewComponent, RtEmptyStateComponent, RtFileCardComponent, RtFileDropComponent, RtFormControlBase, RtIconButtonComponent, RtIconComponent, RtMarkdownTextComponent, RtMenuComponent, RtMenuItemComponent, RtMessageComponent, RtNoteComponent, RtPromptSuggestionComponent, RtServiceLogoComponent, RtSkeletonWrapperComponent, RtSpinnerComponent, RtThreadListComponent, RtThreadListRowActionsDirective, RtThreadListRowDirective, RtToolbarComponent, RtToolbarLeftDirective, RtToolbarRightDirective, coerceQuillDeltaOutput, fileNameFromUrl, markdownToPlainText, rtKitLabel, rtMatchParts } from "@rt-tools/ui-kit-v2";
|
|
5
5
|
import { CdkTextareaAutosize } from "@angular/cdk/text-field";
|
|
6
6
|
import { takeUntilDestroyed, toSignal } from "@angular/core/rxjs-interop";
|
|
7
7
|
import * as i1 from "@angular/forms";
|
|
@@ -2239,7 +2239,7 @@ var RtAiChatAnswerComponent = class RtAiChatAnswerComponent {
|
|
|
2239
2239
|
},
|
|
2240
2240
|
ngImport: i0,
|
|
2241
2241
|
template: "<ng-container rtBlock=\"rt-ai-chat-answer\">\n @if (message().run; as run) {\n <rt-ai-run-status\n qa-dataid=\"ai-chat-run\"\n [state]=\"run.state\"\n [label]=\"run.label\"\n [meta]=\"run.meta ?? ''\"\n [steps]=\"run.steps ?? []\"\n [(expanded)]=\"expanded\" />\n }\n @if (message().text) {\n <rt-markdown-text rtElem=\"text\" qa-dataid=\"ai-chat-answer-text\" [text]=\"message().text\" />\n }\n @if (extra(); as extraTemplate) {\n <ng-container [ngTemplateOutlet]=\"extraTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message() }\" />\n }\n @if (isWritten()) {\n <div rtElem=\"feedback\" qa-dataid=\"ai-chat-feedback\">\n @if (copyable()) {\n <rt-ai-chat-copy [text]=\"plainText()\" />\n }\n <rt-icon-button\n qa-dataid=\"ai-chat-like\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"thumb-up\"\n [active]=\"message().feedback === 'liked'\"\n [ariaLabel]=\"t().aiLike\"\n [tooltip]=\"t().aiLike\"\n (clicked)=\"feedbackChange.emit('liked')\" />\n <rt-icon-button\n qa-dataid=\"ai-chat-dislike\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"thumb-down\"\n [active]=\"message().feedback === 'disliked'\"\n [ariaLabel]=\"t().aiDislike\"\n [tooltip]=\"t().aiDislike\"\n (clicked)=\"feedbackChange.emit('disliked')\" />\n </div>\n }\n</ng-container>\n",
|
|
2242
|
-
styles: ["@layer rt-kit.components{.rt-ai-chat-answer{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat-answer__feedback{display:flex;gap:var(--rt-space-xs)}}\n"],
|
|
2242
|
+
styles: ["@layer rt-kit.components{.rt-ai-chat-answer{display:flex;min-width:0;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat-answer__feedback{display:flex;gap:var(--rt-space-xs)}}\n"],
|
|
2243
2243
|
dependencies: [
|
|
2244
2244
|
{
|
|
2245
2245
|
kind: "directive",
|
|
@@ -2347,7 +2347,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2347
2347
|
"[attr.data-id]": "message().id"
|
|
2348
2348
|
},
|
|
2349
2349
|
template: "<ng-container rtBlock=\"rt-ai-chat-answer\">\n @if (message().run; as run) {\n <rt-ai-run-status\n qa-dataid=\"ai-chat-run\"\n [state]=\"run.state\"\n [label]=\"run.label\"\n [meta]=\"run.meta ?? ''\"\n [steps]=\"run.steps ?? []\"\n [(expanded)]=\"expanded\" />\n }\n @if (message().text) {\n <rt-markdown-text rtElem=\"text\" qa-dataid=\"ai-chat-answer-text\" [text]=\"message().text\" />\n }\n @if (extra(); as extraTemplate) {\n <ng-container [ngTemplateOutlet]=\"extraTemplate\" [ngTemplateOutletContext]=\"{ $implicit: message() }\" />\n }\n @if (isWritten()) {\n <div rtElem=\"feedback\" qa-dataid=\"ai-chat-feedback\">\n @if (copyable()) {\n <rt-ai-chat-copy [text]=\"plainText()\" />\n }\n <rt-icon-button\n qa-dataid=\"ai-chat-like\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"thumb-up\"\n [active]=\"message().feedback === 'liked'\"\n [ariaLabel]=\"t().aiLike\"\n [tooltip]=\"t().aiLike\"\n (clicked)=\"feedbackChange.emit('liked')\" />\n <rt-icon-button\n qa-dataid=\"ai-chat-dislike\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"thumb-down\"\n [active]=\"message().feedback === 'disliked'\"\n [ariaLabel]=\"t().aiDislike\"\n [tooltip]=\"t().aiDislike\"\n (clicked)=\"feedbackChange.emit('disliked')\" />\n </div>\n }\n</ng-container>\n",
|
|
2350
|
-
styles: ["@layer rt-kit.components{.rt-ai-chat-answer{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat-answer__feedback{display:flex;gap:var(--rt-space-xs)}}\n"]
|
|
2350
|
+
styles: ["@layer rt-kit.components{.rt-ai-chat-answer{display:flex;min-width:0;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat-answer__feedback{display:flex;gap:var(--rt-space-xs)}}\n"]
|
|
2351
2351
|
}]
|
|
2352
2352
|
}],
|
|
2353
2353
|
propDecorators: {
|
|
@@ -2448,7 +2448,7 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2448
2448
|
this.#forceScroll = false;
|
|
2449
2449
|
this.#injector = inject(Injector);
|
|
2450
2450
|
this.#clipboard = inject(Clipboard);
|
|
2451
|
-
this.composer = viewChild(
|
|
2451
|
+
this.composer = viewChild(RtAiPromptInputComponent, ...ngDevMode ? [{ debugName: "composer" }] : /* istanbul ignore next */ []);
|
|
2452
2452
|
this.backButton = viewChild("back", {
|
|
2453
2453
|
...ngDevMode ? { debugName: "backButton" } : /* istanbul ignore next */ {},
|
|
2454
2454
|
read: ElementRef
|
|
@@ -2461,6 +2461,7 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2461
2461
|
this.emptyTitleText = computed(() => this.emptyTitle() || this.t().aiEmptyTitle, ...ngDevMode ? [{ debugName: "emptyTitleText" }] : /* istanbul ignore next */ []);
|
|
2462
2462
|
this.emptyDescriptionText = computed(() => this.emptyDescription() || this.t().aiEmptyText, ...ngDevMode ? [{ debugName: "emptyDescriptionText" }] : /* istanbul ignore next */ []);
|
|
2463
2463
|
this.disclaimerText = computed(() => this.disclaimer() ?? this.t().aiDisclaimer, ...ngDevMode ? [{ debugName: "disclaimerText" }] : /* istanbul ignore next */ []);
|
|
2464
|
+
this.disclaimerAbove = computed(() => this.disclaimerPosition() === "above", ...ngDevMode ? [{ debugName: "disclaimerAbove" }] : /* istanbul ignore next */ []);
|
|
2464
2465
|
this.headerIconSign = computed(() => this.headerIconPreset() === "material" ? "material" : null, ...ngDevMode ? [{ debugName: "headerIconSign" }] : /* istanbul ignore next */ []);
|
|
2465
2466
|
this.hasThreads = computed(() => this.threads() !== null, ...ngDevMode ? [{ debugName: "hasThreads" }] : /* istanbul ignore next */ []);
|
|
2466
2467
|
this.isThreadColumn = computed(() => this.fullScreen() && this.hasThreads(), ...ngDevMode ? [{ debugName: "isThreadColumn" }] : /* istanbul ignore next */ []);
|
|
@@ -2487,6 +2488,12 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2487
2488
|
this.emptyDescription = input("", ...ngDevMode ? [{ debugName: "emptyDescription" }] : /* istanbul ignore next */ []);
|
|
2488
2489
|
this.placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
|
|
2489
2490
|
this.disclaimer = input(null, ...ngDevMode ? [{ debugName: "disclaimer" }] : /* istanbul ignore next */ []);
|
|
2491
|
+
this.disclaimerPosition = input("below", ...ngDevMode ? [{ debugName: "disclaimerPosition" }] : /* istanbul ignore next */ []);
|
|
2492
|
+
this.model = input("", ...ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []);
|
|
2493
|
+
this.effort = input("", ...ngDevMode ? [{ debugName: "effort" }] : /* istanbul ignore next */ []);
|
|
2494
|
+
this.mode = input("", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
|
|
2495
|
+
this.usage = input(null, ...ngDevMode ? [{ debugName: "usage" }] : /* istanbul ignore next */ []);
|
|
2496
|
+
this.usageHint = input("", ...ngDevMode ? [{ debugName: "usageHint" }] : /* istanbul ignore next */ []);
|
|
2490
2497
|
this.sending = input(false, {
|
|
2491
2498
|
...ngDevMode ? { debugName: "sending" } : /* istanbul ignore next */ {},
|
|
2492
2499
|
transform: booleanAttribute
|
|
@@ -2541,6 +2548,7 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2541
2548
|
this.searchThreads = output();
|
|
2542
2549
|
this.loadMoreThreads = output();
|
|
2543
2550
|
this.feedbackChange = output();
|
|
2551
|
+
this.controlPicked = output();
|
|
2544
2552
|
afterRenderEffect(() => {
|
|
2545
2553
|
this.messages();
|
|
2546
2554
|
this.error();
|
|
@@ -2698,6 +2706,48 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2698
2706
|
isRequired: false,
|
|
2699
2707
|
transformFunction: null
|
|
2700
2708
|
},
|
|
2709
|
+
disclaimerPosition: {
|
|
2710
|
+
classPropertyName: "disclaimerPosition",
|
|
2711
|
+
publicName: "disclaimerPosition",
|
|
2712
|
+
isSignal: true,
|
|
2713
|
+
isRequired: false,
|
|
2714
|
+
transformFunction: null
|
|
2715
|
+
},
|
|
2716
|
+
model: {
|
|
2717
|
+
classPropertyName: "model",
|
|
2718
|
+
publicName: "model",
|
|
2719
|
+
isSignal: true,
|
|
2720
|
+
isRequired: false,
|
|
2721
|
+
transformFunction: null
|
|
2722
|
+
},
|
|
2723
|
+
effort: {
|
|
2724
|
+
classPropertyName: "effort",
|
|
2725
|
+
publicName: "effort",
|
|
2726
|
+
isSignal: true,
|
|
2727
|
+
isRequired: false,
|
|
2728
|
+
transformFunction: null
|
|
2729
|
+
},
|
|
2730
|
+
mode: {
|
|
2731
|
+
classPropertyName: "mode",
|
|
2732
|
+
publicName: "mode",
|
|
2733
|
+
isSignal: true,
|
|
2734
|
+
isRequired: false,
|
|
2735
|
+
transformFunction: null
|
|
2736
|
+
},
|
|
2737
|
+
usage: {
|
|
2738
|
+
classPropertyName: "usage",
|
|
2739
|
+
publicName: "usage",
|
|
2740
|
+
isSignal: true,
|
|
2741
|
+
isRequired: false,
|
|
2742
|
+
transformFunction: null
|
|
2743
|
+
},
|
|
2744
|
+
usageHint: {
|
|
2745
|
+
classPropertyName: "usageHint",
|
|
2746
|
+
publicName: "usageHint",
|
|
2747
|
+
isSignal: true,
|
|
2748
|
+
isRequired: false,
|
|
2749
|
+
transformFunction: null
|
|
2750
|
+
},
|
|
2701
2751
|
sending: {
|
|
2702
2752
|
classPropertyName: "sending",
|
|
2703
2753
|
publicName: "sending",
|
|
@@ -2831,7 +2881,8 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2831
2881
|
deleteThread: "deleteThread",
|
|
2832
2882
|
searchThreads: "searchThreads",
|
|
2833
2883
|
loadMoreThreads: "loadMoreThreads",
|
|
2834
|
-
feedbackChange: "feedbackChange"
|
|
2884
|
+
feedbackChange: "feedbackChange",
|
|
2885
|
+
controlPicked: "controlPicked"
|
|
2835
2886
|
},
|
|
2836
2887
|
host: { classAttribute: "rt-ai-chat" },
|
|
2837
2888
|
queries: [{
|
|
@@ -2845,7 +2896,7 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2845
2896
|
{
|
|
2846
2897
|
propertyName: "composer",
|
|
2847
2898
|
first: true,
|
|
2848
|
-
predicate:
|
|
2899
|
+
predicate: RtAiPromptInputComponent,
|
|
2849
2900
|
descendants: true,
|
|
2850
2901
|
isSignal: true
|
|
2851
2902
|
},
|
|
@@ -2866,8 +2917,8 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
2866
2917
|
}
|
|
2867
2918
|
],
|
|
2868
2919
|
ngImport: i0,
|
|
2869
|
-
template: "<ng-container rtBlock=\"rt-ai-chat\">\n @if (isThreadColumn()) {\n <aside rtElem=\"thread-column\" qa-dataid=\"ai-chat-thread-column\" [attr.aria-label]=\"t().aiThreads\">\n <div rtElem=\"column-head\">\n <span rtElem=\"column-title\">{{ t().aiThreads }}</span>\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n </div>\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n </aside>\n }\n\n <section rtElem=\"conversation\" qa-dataid=\"ai-chat\" [attr.aria-label]=\"titleText()\">\n <header rtElem=\"header\" [attr.data-rt-icon-preset]=\"headerIconSign()\">\n @if (isThreadPage()) {\n <rt-icon-button\n #back\n qa-dataid=\"ai-chat-back\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"arrow-left\"\n [ariaLabel]=\"t().aiBackToChat\"\n [tooltip]=\"t().aiBackToChat\"\n (clicked)=\"onToggleThreads()\" />\n }\n\n <div rtElem=\"heading\">\n <span rtElem=\"title\" qa-dataid=\"ai-chat-title\">\n @if (!isThreadPage()) {\n <rt-icon name=\"sparkle\" size=\"sm\" color=\"primary\" aria-hidden=\"true\" />\n }\n {{ isThreadPage() ? t().aiThreads : titleText() }}\n </span>\n @if (!isThreadPage() && subtitle()) {\n <span rtElem=\"subtitle\" qa-dataid=\"ai-chat-subtitle\">{{ subtitle() }}</span>\n }\n </div>\n\n <div rtElem=\"actions\">\n @if (fullScreenable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-full-screen\"\n size=\"sm\"\n iconSize=\"sm\"\n [icon]=\"fullScreen() ? 'window-minimize' : 'fullscreen'\"\n [active]=\"fullScreen()\"\n [ariaLabel]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n [tooltip]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n (clicked)=\"onToggleFullScreen()\" />\n }\n @if (hasThreads() && !isThreadPage() && !isThreadColumn()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-threads\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"history\"\n [ariaLabel]=\"t().aiThreads\"\n [tooltip]=\"t().aiThreads\"\n (clicked)=\"onToggleThreads()\" />\n }\n @if (!isThreadColumn()) {\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n }\n @if (closable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-close\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"close\"\n [ariaLabel]=\"t().aiClose\"\n [tooltip]=\"t().aiClose\"\n (clicked)=\"closed.emit()\" />\n }\n </div>\n </header>\n\n @if (isThreadPage()) {\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n } @else {\n <div #feed rtElem=\"feed\" qa-dataid=\"ai-chat-feed\" aria-live=\"polite\" (scroll)=\"onFeedScroll()\">\n @if (loading() && !messages().length) {\n <rt-spinner rtElem=\"spinner\" appearance=\"arc\" [diameter]=\"32\" />\n } @else if (isEmpty()) {\n <div rtElem=\"empty\" qa-dataid=\"ai-chat-empty\">\n <rt-empty-state icon=\"comments\" [title]=\"emptyTitleText()\" [description]=\"emptyDescriptionText()\" />\n @if (suggestions().length) {\n <div rtElem=\"suggestions\">\n @for (suggestion of suggestions(); track suggestion) {\n <rt-prompt-suggestion\n qa-dataid=\"ai-chat-suggestion\"\n [label]=\"suggestion\"\n [disabled]=\"sending()\"\n (picked)=\"onSuggestion($event)\" />\n }\n </div>\n }\n </div>\n }\n\n @for (message of messages(); track message.id) {\n @if (message.role === 'user') {\n <div rtElem=\"question\" qa-dataid=\"ai-chat-question\">\n <div rtElem=\"bubble\">\n <span rtElem=\"author\">{{ t().aiYou }}</span>\n <p rtElem=\"bubble-text\">{{ message.text }}</p>\n @if (message.time) {\n <span rtElem=\"time\">{{ message.time }}</span>\n }\n </div>\n @if (copyable() && message.text) {\n <div rtElem=\"question-actions\" qa-dataid=\"ai-chat-question-actions\">\n <rt-ai-chat-copy [text]=\"message.text\" />\n </div>\n }\n </div>\n } @else {\n <rt-ai-chat-answer\n qa-dataid=\"ai-chat-answer\"\n [message]=\"message\"\n [copyable]=\"copyable()\"\n [extra]=\"extraTemplate()?.templateRef ?? null\"\n [expanded]=\"openRuns().has(message.id)\"\n (expandedChange)=\"onToggleRun(message.id, $event)\"\n (feedbackChange)=\"onFeedback(message, $event)\" />\n }\n }\n\n @if (error(); as runError) {\n <div rtElem=\"error\" qa-dataid=\"ai-chat-error\" role=\"alert\">\n <rt-message severity=\"danger\">{{ runError.message }}</rt-message>\n @if (runError.referenceId) {\n <rt-copy-value [label]=\"t().aiReference\" [value]=\"runError.referenceId\" [copyLabel]=\"t().aiCopyReference\" />\n }\n @if (runError.retryable) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"ai-chat-retry\"\n appearance=\"text\"\n icon=\"sync\"\n size=\"sm\"\n [label]=\"t().aiRetry\"\n [attr.aria-label]=\"t().aiRetry\"\n [disabled]=\"sending()\"\n (click)=\"retry.emit()\"></button>\n }\n </div>\n }\n </div>\n\n <rt-message-composer\n rtElem=\"composer\"\n qa-dataid=\"ai-chat-composer\"\n stoppable\n [placeholder]=\"placeholder()\"\n [sending]=\"sending()\"\n [(text)]=\"draft\"\n (submitted)=\"onSubmitted($event)\"\n (stopped)=\"onStop()\" />\n\n @if (disclaimerText()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\">{{ disclaimerText() }}</p>\n }\n }\n </section>\n</ng-container>\n\n<ng-template #newThreadButton>\n <rt-icon-button\n qa-dataid=\"ai-chat-new-thread\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"ico-plus\"\n [disabled]=\"sending()\"\n [ariaLabel]=\"t().aiNewThread\"\n [tooltip]=\"t().aiNewThread\"\n (clicked)=\"onNewThread()\" />\n</ng-template>\n\n<ng-template #threadList>\n <ng-container rtBlock=\"rt-ai-chat\">\n <rt-thread-list\n rtElem=\"threads\"\n qa-dataid=\"ai-chat-thread-list\"\n [rows]=\"threadRows()\"\n [activeId]=\"activeThreadId()\"\n [searchPlaceholder]=\"t().aiSearchThreads\"\n [emptyText]=\"threadsEmptyText()\"\n [emptyPreviewIcons]=\"emptyPreviewIcons()\"\n [loading]=\"threadsLoading()\"\n [fetching]=\"threadsFetching()\"\n [hasMore]=\"threadsHasMore()\"\n (selectRow)=\"onSelectThread($event)\"\n (searchChange)=\"onSearchThreads($event)\"\n (loadMore)=\"loadMoreThreads.emit()\">\n <ng-template let-row [rtThreadListRow]=\"threadRows()\">\n <span rtElem=\"thread-title\" qa-dataid=\"ai-chat-thread-title\" [attr.title]=\"row.title\">\n @for (part of row.titleParts; track $index) {\n <span rtElem=\"thread-part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n <span rtElem=\"thread-meta\">\n @if (row.unreadCount) {\n <span rtElem=\"thread-unread\" qa-dataid=\"ai-chat-thread-unread\">{{ row.unreadCount }}</span>\n }\n @if (row.time) {\n <span rtElem=\"thread-time\">{{ row.time }}</span>\n }\n </span>\n </ng-template>\n <ng-template let-row [rtThreadListRowActions]=\"threadRows()\">\n @if (threadMenu()) {\n <rt-menu qa-dataid=\"ai-chat-thread-menu\" icon=\"ellipsis-v\" triggerSize=\"xs\" size=\"sm\" [ariaLabel]=\"t().uiMoreActions\">\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-copy-id\"\n icon=\"copy\"\n [label]=\"t().aiCopyThreadId\"\n (selected)=\"onCopyThreadId(row.id)\" />\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-delete\"\n icon=\"trash\"\n danger\n [label]=\"t().uiRemove\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n (selected)=\"deleteThread.emit(row.id)\" />\n </rt-menu>\n } @else {\n <rt-icon-button\n qa-dataid=\"ai-chat-delete-thread\"\n size=\"xs\"\n iconSize=\"sm\"\n icon=\"trash\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n [ariaLabel]=\"t().aiDeleteThread\"\n [tooltip]=\"t().aiDeleteThread\"\n (clicked)=\"deleteThread.emit(row.id)\" />\n }\n </ng-template>\n </rt-thread-list>\n </ng-container>\n</ng-template>\n",
|
|
2870
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-ai-chat{--rt-ai-chat-bubble-radius: var(--rt-radius-xl);--rt-ai-chat-column-border-width: var(--rt-border-width-thin);--rt-ai-chat-column-width: 280px;--rt-ai-chat-content-max-width: 100%;--rt-ai-chat-match-bg: var(--rt-yellow-400);--rt-ai-chat-match-color: var(--rt-neutral-950);--rt-ai-chat-match-radius: var(--rt-radius-xs);--rt-ai-chat-unread-radius: var(--rt-radius-full);display:flex;overflow:hidden;background:var(--rt-color-bg-surface);block-size:100%;color:var(--rt-color-text-primary);min-block-size:0}.rt-ai-chat__thread-column{display:flex;flex:none;flex-direction:column;border-inline-end:var(--rt-ai-chat-column-border-width) solid var(--rt-color-border-default);inline-size:var(--rt-ai-chat-column-width)}.rt-ai-chat__column-head{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__column-title{font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__conversation{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0}.rt-ai-chat__header{display:flex;flex:none;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__heading{display:flex;flex:1 1 auto;flex-direction:column;min-inline-size:0}.rt-ai-chat__title{display:inline-flex;align-items:center;font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__subtitle{overflow:hidden;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__actions{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__feed{display:flex;flex:1 1 auto;flex-direction:column;font-size:var(--rt-text-sm);gap:var(--rt-space-md);min-block-size:0;overflow-y:auto;padding-block:var(--rt-space-md);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__spinner{align-self:center;margin:auto}.rt-ai-chat__empty{display:flex;flex-direction:column;justify-content:center;gap:var(--rt-space-lg);margin-block:auto}.rt-ai-chat__suggestions{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat__question{display:flex;flex-direction:column;align-items:flex-end;gap:var(--rt-space-2xs)}.rt-ai-chat__question-actions{display:flex;gap:var(--rt-space-xs)}.rt-ai-chat__bubble{display:flex;flex-direction:column;padding:var(--rt-space-sm) var(--rt-space-md);border-radius:var(--rt-ai-chat-bubble-radius);background:var(--rt-color-bg-subtle);gap:var(--rt-space-2xs);max-inline-size:80%}.rt-ai-chat__author,.rt-ai-chat__time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__author{font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__bubble-text{margin:0;line-height:var(--rt-leading-normal);overflow-wrap:anywhere;white-space:pre-wrap}.rt-ai-chat__error{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-ai-chat__error rt-message{align-self:stretch}.rt-ai-chat__composer{box-sizing:border-box;flex:none;padding-block:var(--rt-space-sm) 0;padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__disclaimer{flex:none;margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);padding-block:var(--rt-space-xs) var(--rt-space-sm);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2);text-align:center}.rt-ai-chat__threads{flex:1 1 auto;min-block-size:0}.rt-ai-chat__thread-title{overflow:hidden;min-inline-size:0;text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__thread-part--match{border-radius:var(--rt-ai-chat-match-radius);background:var(--rt-ai-chat-match-bg);color:var(--rt-ai-chat-match-color)}.rt-ai-chat__thread-meta{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__thread-unread{border-radius:var(--rt-ai-chat-unread-radius);background:var(--rt-color-action-primary);color:var(--rt-color-text-inverse);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-semibold);line-height:18px;padding-inline:6px}.rt-ai-chat__thread-time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}}\n"],
|
|
2920
|
+
template: "<ng-container rtBlock=\"rt-ai-chat\">\n @if (isThreadColumn()) {\n <aside rtElem=\"thread-column\" qa-dataid=\"ai-chat-thread-column\" [attr.aria-label]=\"t().aiThreads\">\n <div rtElem=\"column-head\">\n <span rtElem=\"column-title\">{{ t().aiThreads }}</span>\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n </div>\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n </aside>\n }\n\n <section rtElem=\"conversation\" qa-dataid=\"ai-chat\" [attr.aria-label]=\"titleText()\">\n <header rtElem=\"header\" [attr.data-rt-icon-preset]=\"headerIconSign()\">\n @if (isThreadPage()) {\n <rt-icon-button\n #back\n qa-dataid=\"ai-chat-back\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"arrow-left\"\n [ariaLabel]=\"t().aiBackToChat\"\n [tooltip]=\"t().aiBackToChat\"\n (clicked)=\"onToggleThreads()\" />\n }\n\n <div rtElem=\"heading\">\n <span rtElem=\"title\" qa-dataid=\"ai-chat-title\">\n @if (!isThreadPage()) {\n <rt-icon name=\"sparkle\" size=\"sm\" color=\"primary\" aria-hidden=\"true\" />\n }\n {{ isThreadPage() ? t().aiThreads : titleText() }}\n </span>\n @if (!isThreadPage() && subtitle()) {\n <span rtElem=\"subtitle\" qa-dataid=\"ai-chat-subtitle\">{{ subtitle() }}</span>\n }\n </div>\n\n <div rtElem=\"actions\">\n @if (fullScreenable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-full-screen\"\n size=\"sm\"\n iconSize=\"sm\"\n [icon]=\"fullScreen() ? 'window-minimize' : 'fullscreen'\"\n [active]=\"fullScreen()\"\n [ariaLabel]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n [tooltip]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n (clicked)=\"onToggleFullScreen()\" />\n }\n @if (hasThreads() && !isThreadPage() && !isThreadColumn()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-threads\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"history\"\n [ariaLabel]=\"t().aiThreads\"\n [tooltip]=\"t().aiThreads\"\n (clicked)=\"onToggleThreads()\" />\n }\n @if (!isThreadColumn()) {\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n }\n @if (closable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-close\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"close\"\n [ariaLabel]=\"t().aiClose\"\n [tooltip]=\"t().aiClose\"\n (clicked)=\"closed.emit()\" />\n }\n </div>\n </header>\n\n @if (isThreadPage()) {\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n } @else {\n <div #feed rtElem=\"feed\" qa-dataid=\"ai-chat-feed\" aria-live=\"polite\" (scroll)=\"onFeedScroll()\">\n @if (loading() && !messages().length) {\n <rt-spinner rtElem=\"spinner\" appearance=\"arc\" [diameter]=\"32\" />\n } @else if (isEmpty()) {\n <div rtElem=\"empty\" qa-dataid=\"ai-chat-empty\">\n <rt-empty-state icon=\"comments\" [title]=\"emptyTitleText()\" [description]=\"emptyDescriptionText()\" />\n @if (suggestions().length) {\n <div rtElem=\"suggestions\">\n @for (suggestion of suggestions(); track suggestion) {\n <rt-prompt-suggestion\n qa-dataid=\"ai-chat-suggestion\"\n [label]=\"suggestion\"\n [disabled]=\"sending()\"\n (picked)=\"onSuggestion($event)\" />\n }\n </div>\n }\n </div>\n }\n\n @for (message of messages(); track message.id) {\n @if (message.role === 'user') {\n <div rtElem=\"question\" qa-dataid=\"ai-chat-question\">\n <div rtElem=\"bubble\">\n <span rtElem=\"author\">{{ t().aiYou }}</span>\n <p rtElem=\"bubble-text\">{{ message.text }}</p>\n @if (message.time) {\n <span rtElem=\"time\">{{ message.time }}</span>\n }\n </div>\n @if (copyable() && message.text) {\n <div rtElem=\"question-actions\" qa-dataid=\"ai-chat-question-actions\">\n <rt-ai-chat-copy [text]=\"message.text\" />\n </div>\n }\n </div>\n } @else {\n <rt-ai-chat-answer\n qa-dataid=\"ai-chat-answer\"\n [message]=\"message\"\n [copyable]=\"copyable()\"\n [extra]=\"extraTemplate()?.templateRef ?? null\"\n [expanded]=\"openRuns().has(message.id)\"\n (expandedChange)=\"onToggleRun(message.id, $event)\"\n (feedbackChange)=\"onFeedback(message, $event)\" />\n }\n }\n\n @if (error(); as runError) {\n <div rtElem=\"error\" qa-dataid=\"ai-chat-error\" role=\"alert\">\n <rt-message severity=\"danger\">{{ runError.message }}</rt-message>\n @if (runError.referenceId) {\n <rt-copy-value [label]=\"t().aiReference\" [value]=\"runError.referenceId\" [copyLabel]=\"t().aiCopyReference\" />\n }\n @if (runError.retryable) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"ai-chat-retry\"\n appearance=\"text\"\n icon=\"sync\"\n size=\"sm\"\n [label]=\"t().aiRetry\"\n [attr.aria-label]=\"t().aiRetry\"\n [disabled]=\"sending()\"\n (click)=\"retry.emit()\"></button>\n }\n </div>\n }\n </div>\n\n @if (disclaimerText() && disclaimerAbove()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\" [rtMod]=\"{ above: true }\">{{ disclaimerText() }}</p>\n }\n\n <rt-ai-prompt-input\n rtElem=\"composer\"\n qa-dataid=\"ai-chat-composer\"\n stoppable\n hint=\"\"\n [placeholder]=\"placeholder()\"\n [model]=\"model()\"\n [effort]=\"effort()\"\n [mode]=\"mode()\"\n [usage]=\"usage()\"\n [usageHint]=\"usageHint()\"\n [sending]=\"sending()\"\n [(text)]=\"draft\"\n (submitted)=\"onSubmitted($event)\"\n (stopped)=\"onStop()\"\n (controlPicked)=\"controlPicked.emit($event)\" />\n\n @if (disclaimerText() && !disclaimerAbove()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\">{{ disclaimerText() }}</p>\n }\n }\n </section>\n</ng-container>\n\n<ng-template #newThreadButton>\n <rt-icon-button\n qa-dataid=\"ai-chat-new-thread\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"ico-plus\"\n [disabled]=\"sending()\"\n [ariaLabel]=\"t().aiNewThread\"\n [tooltip]=\"t().aiNewThread\"\n (clicked)=\"onNewThread()\" />\n</ng-template>\n\n<ng-template #threadList>\n <ng-container rtBlock=\"rt-ai-chat\">\n <rt-thread-list\n rtElem=\"threads\"\n qa-dataid=\"ai-chat-thread-list\"\n [rows]=\"threadRows()\"\n [activeId]=\"activeThreadId()\"\n [searchPlaceholder]=\"t().aiSearchThreads\"\n [emptyText]=\"threadsEmptyText()\"\n [emptyPreviewIcons]=\"emptyPreviewIcons()\"\n [loading]=\"threadsLoading()\"\n [fetching]=\"threadsFetching()\"\n [hasMore]=\"threadsHasMore()\"\n (selectRow)=\"onSelectThread($event)\"\n (searchChange)=\"onSearchThreads($event)\"\n (loadMore)=\"loadMoreThreads.emit()\">\n <ng-template let-row [rtThreadListRow]=\"threadRows()\">\n <span rtElem=\"thread-title\" qa-dataid=\"ai-chat-thread-title\" [attr.title]=\"row.title\">\n @for (part of row.titleParts; track $index) {\n <span rtElem=\"thread-part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n <span rtElem=\"thread-meta\">\n @if (row.unreadCount) {\n <span rtElem=\"thread-unread\" qa-dataid=\"ai-chat-thread-unread\">{{ row.unreadCount }}</span>\n }\n @if (row.time) {\n <span rtElem=\"thread-time\">{{ row.time }}</span>\n }\n </span>\n </ng-template>\n <ng-template let-row [rtThreadListRowActions]=\"threadRows()\">\n @if (threadMenu()) {\n <rt-menu qa-dataid=\"ai-chat-thread-menu\" icon=\"ellipsis-v\" triggerSize=\"xs\" size=\"sm\" [ariaLabel]=\"t().uiMoreActions\">\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-copy-id\"\n icon=\"copy\"\n [label]=\"t().aiCopyThreadId\"\n (selected)=\"onCopyThreadId(row.id)\" />\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-delete\"\n icon=\"trash\"\n danger\n [label]=\"t().uiRemove\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n (selected)=\"deleteThread.emit(row.id)\" />\n </rt-menu>\n } @else {\n <rt-icon-button\n qa-dataid=\"ai-chat-delete-thread\"\n size=\"xs\"\n iconSize=\"sm\"\n icon=\"trash\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n [ariaLabel]=\"t().aiDeleteThread\"\n [tooltip]=\"t().aiDeleteThread\"\n (clicked)=\"deleteThread.emit(row.id)\" />\n }\n </ng-template>\n </rt-thread-list>\n </ng-container>\n</ng-template>\n",
|
|
2921
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-ai-chat{--rt-ai-chat-bubble-radius: var(--rt-radius-xl);--rt-ai-chat-column-border-width: var(--rt-border-width-thin);--rt-ai-chat-column-width: 280px;--rt-ai-chat-content-max-width: 100%;--rt-ai-chat-match-bg: var(--rt-yellow-400);--rt-ai-chat-match-color: var(--rt-neutral-950);--rt-ai-chat-match-radius: var(--rt-radius-xs);--rt-ai-chat-unread-radius: var(--rt-radius-full);display:flex;overflow:hidden;background:var(--rt-color-bg-surface);block-size:100%;color:var(--rt-color-text-primary);min-block-size:0}.rt-ai-chat__thread-column{display:flex;flex:none;flex-direction:column;border-inline-end:var(--rt-ai-chat-column-border-width) solid var(--rt-color-border-default);inline-size:var(--rt-ai-chat-column-width)}.rt-ai-chat__column-head{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__column-title{font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__conversation{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0}.rt-ai-chat__header{display:flex;flex:none;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__heading{display:flex;flex:1 1 auto;flex-direction:column;min-inline-size:0}.rt-ai-chat__title{display:inline-flex;align-items:center;font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__subtitle{overflow:hidden;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__actions{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__feed{display:flex;flex:1 1 auto;flex-direction:column;font-size:var(--rt-text-sm);gap:var(--rt-space-md);min-block-size:0;overflow-y:auto;overscroll-behavior:contain;padding-block:var(--rt-space-md);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__spinner{align-self:center;margin:auto}.rt-ai-chat__empty{display:flex;flex-direction:column;justify-content:center;gap:var(--rt-space-lg);margin-block:auto}.rt-ai-chat__suggestions{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat__question{display:flex;flex-direction:column;align-items:flex-end;gap:var(--rt-space-2xs)}.rt-ai-chat__question-actions{display:flex;gap:var(--rt-space-xs)}.rt-ai-chat__bubble{display:flex;flex-direction:column;padding:var(--rt-space-sm) var(--rt-space-md);border-radius:var(--rt-ai-chat-bubble-radius);background:var(--rt-color-bg-subtle);gap:var(--rt-space-2xs);max-inline-size:80%}.rt-ai-chat__author,.rt-ai-chat__time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__author{font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__bubble-text{margin:0;line-height:var(--rt-leading-normal);overflow-wrap:anywhere;white-space:pre-wrap}.rt-ai-chat__error{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-ai-chat__error rt-message{align-self:stretch}.rt-ai-chat__composer{box-sizing:border-box;flex:none;padding-block:var(--rt-space-sm) 0;padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__disclaimer{flex:none;margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);padding-block:var(--rt-space-xs) var(--rt-space-sm);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2);text-align:center}.rt-ai-chat__disclaimer--above{padding-block:var(--rt-space-sm) 0}.rt-ai-chat__threads{flex:1 1 auto;min-block-size:0}.rt-ai-chat__thread-title{overflow:hidden;min-inline-size:0;text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__thread-part--match{border-radius:var(--rt-ai-chat-match-radius);background:var(--rt-ai-chat-match-bg);color:var(--rt-ai-chat-match-color)}.rt-ai-chat__thread-meta{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__thread-unread{border-radius:var(--rt-ai-chat-unread-radius);background:var(--rt-color-action-primary);color:var(--rt-color-text-inverse);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-semibold);line-height:18px;padding-inline:6px}.rt-ai-chat__thread-time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}}\n"],
|
|
2871
2922
|
dependencies: [
|
|
2872
2923
|
{
|
|
2873
2924
|
kind: "directive",
|
|
@@ -3048,27 +3099,32 @@ var RtAiChatComponent = class RtAiChatComponent {
|
|
|
3048
3099
|
},
|
|
3049
3100
|
{
|
|
3050
3101
|
kind: "component",
|
|
3051
|
-
type:
|
|
3052
|
-
selector: "rt-
|
|
3102
|
+
type: RtAiPromptInputComponent,
|
|
3103
|
+
selector: "rt-ai-prompt-input",
|
|
3053
3104
|
inputs: [
|
|
3054
3105
|
"placeholder",
|
|
3055
|
-
"accept",
|
|
3056
3106
|
"hint",
|
|
3107
|
+
"hintPosition",
|
|
3057
3108
|
"attachments",
|
|
3109
|
+
"accept",
|
|
3110
|
+
"model",
|
|
3111
|
+
"effort",
|
|
3112
|
+
"mode",
|
|
3113
|
+
"usage",
|
|
3114
|
+
"usageHint",
|
|
3115
|
+
"usageWarnAt",
|
|
3058
3116
|
"sending",
|
|
3059
3117
|
"stoppable",
|
|
3060
3118
|
"disabled",
|
|
3061
|
-
"formatting",
|
|
3062
|
-
"toolbar",
|
|
3063
3119
|
"minRows",
|
|
3064
3120
|
"maxRows",
|
|
3065
|
-
"droppedFiles",
|
|
3066
3121
|
"text"
|
|
3067
3122
|
],
|
|
3068
3123
|
outputs: [
|
|
3069
|
-
"submitted",
|
|
3070
3124
|
"textChange",
|
|
3071
|
-
"
|
|
3125
|
+
"submitted",
|
|
3126
|
+
"stopped",
|
|
3127
|
+
"controlPicked"
|
|
3072
3128
|
]
|
|
3073
3129
|
},
|
|
3074
3130
|
{
|
|
@@ -3157,7 +3213,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3157
3213
|
RtMenuComponent,
|
|
3158
3214
|
RtMenuItemComponent,
|
|
3159
3215
|
RtMessageComponent,
|
|
3160
|
-
|
|
3216
|
+
RtAiPromptInputComponent,
|
|
3161
3217
|
RtPromptSuggestionComponent,
|
|
3162
3218
|
RtSpinnerComponent,
|
|
3163
3219
|
RtThreadListComponent,
|
|
@@ -3165,15 +3221,15 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3165
3221
|
RtThreadListRowDirective
|
|
3166
3222
|
],
|
|
3167
3223
|
host: { class: BEM_BLOCK },
|
|
3168
|
-
template: "<ng-container rtBlock=\"rt-ai-chat\">\n @if (isThreadColumn()) {\n <aside rtElem=\"thread-column\" qa-dataid=\"ai-chat-thread-column\" [attr.aria-label]=\"t().aiThreads\">\n <div rtElem=\"column-head\">\n <span rtElem=\"column-title\">{{ t().aiThreads }}</span>\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n </div>\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n </aside>\n }\n\n <section rtElem=\"conversation\" qa-dataid=\"ai-chat\" [attr.aria-label]=\"titleText()\">\n <header rtElem=\"header\" [attr.data-rt-icon-preset]=\"headerIconSign()\">\n @if (isThreadPage()) {\n <rt-icon-button\n #back\n qa-dataid=\"ai-chat-back\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"arrow-left\"\n [ariaLabel]=\"t().aiBackToChat\"\n [tooltip]=\"t().aiBackToChat\"\n (clicked)=\"onToggleThreads()\" />\n }\n\n <div rtElem=\"heading\">\n <span rtElem=\"title\" qa-dataid=\"ai-chat-title\">\n @if (!isThreadPage()) {\n <rt-icon name=\"sparkle\" size=\"sm\" color=\"primary\" aria-hidden=\"true\" />\n }\n {{ isThreadPage() ? t().aiThreads : titleText() }}\n </span>\n @if (!isThreadPage() && subtitle()) {\n <span rtElem=\"subtitle\" qa-dataid=\"ai-chat-subtitle\">{{ subtitle() }}</span>\n }\n </div>\n\n <div rtElem=\"actions\">\n @if (fullScreenable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-full-screen\"\n size=\"sm\"\n iconSize=\"sm\"\n [icon]=\"fullScreen() ? 'window-minimize' : 'fullscreen'\"\n [active]=\"fullScreen()\"\n [ariaLabel]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n [tooltip]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n (clicked)=\"onToggleFullScreen()\" />\n }\n @if (hasThreads() && !isThreadPage() && !isThreadColumn()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-threads\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"history\"\n [ariaLabel]=\"t().aiThreads\"\n [tooltip]=\"t().aiThreads\"\n (clicked)=\"onToggleThreads()\" />\n }\n @if (!isThreadColumn()) {\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n }\n @if (closable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-close\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"close\"\n [ariaLabel]=\"t().aiClose\"\n [tooltip]=\"t().aiClose\"\n (clicked)=\"closed.emit()\" />\n }\n </div>\n </header>\n\n @if (isThreadPage()) {\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n } @else {\n <div #feed rtElem=\"feed\" qa-dataid=\"ai-chat-feed\" aria-live=\"polite\" (scroll)=\"onFeedScroll()\">\n @if (loading() && !messages().length) {\n <rt-spinner rtElem=\"spinner\" appearance=\"arc\" [diameter]=\"32\" />\n } @else if (isEmpty()) {\n <div rtElem=\"empty\" qa-dataid=\"ai-chat-empty\">\n <rt-empty-state icon=\"comments\" [title]=\"emptyTitleText()\" [description]=\"emptyDescriptionText()\" />\n @if (suggestions().length) {\n <div rtElem=\"suggestions\">\n @for (suggestion of suggestions(); track suggestion) {\n <rt-prompt-suggestion\n qa-dataid=\"ai-chat-suggestion\"\n [label]=\"suggestion\"\n [disabled]=\"sending()\"\n (picked)=\"onSuggestion($event)\" />\n }\n </div>\n }\n </div>\n }\n\n @for (message of messages(); track message.id) {\n @if (message.role === 'user') {\n <div rtElem=\"question\" qa-dataid=\"ai-chat-question\">\n <div rtElem=\"bubble\">\n <span rtElem=\"author\">{{ t().aiYou }}</span>\n <p rtElem=\"bubble-text\">{{ message.text }}</p>\n @if (message.time) {\n <span rtElem=\"time\">{{ message.time }}</span>\n }\n </div>\n @if (copyable() && message.text) {\n <div rtElem=\"question-actions\" qa-dataid=\"ai-chat-question-actions\">\n <rt-ai-chat-copy [text]=\"message.text\" />\n </div>\n }\n </div>\n } @else {\n <rt-ai-chat-answer\n qa-dataid=\"ai-chat-answer\"\n [message]=\"message\"\n [copyable]=\"copyable()\"\n [extra]=\"extraTemplate()?.templateRef ?? null\"\n [expanded]=\"openRuns().has(message.id)\"\n (expandedChange)=\"onToggleRun(message.id, $event)\"\n (feedbackChange)=\"onFeedback(message, $event)\" />\n }\n }\n\n @if (error(); as runError) {\n <div rtElem=\"error\" qa-dataid=\"ai-chat-error\" role=\"alert\">\n <rt-message severity=\"danger\">{{ runError.message }}</rt-message>\n @if (runError.referenceId) {\n <rt-copy-value [label]=\"t().aiReference\" [value]=\"runError.referenceId\" [copyLabel]=\"t().aiCopyReference\" />\n }\n @if (runError.retryable) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"ai-chat-retry\"\n appearance=\"text\"\n icon=\"sync\"\n size=\"sm\"\n [label]=\"t().aiRetry\"\n [attr.aria-label]=\"t().aiRetry\"\n [disabled]=\"sending()\"\n (click)=\"retry.emit()\"></button>\n }\n </div>\n }\n </div>\n\n <rt-message-composer\n rtElem=\"composer\"\n qa-dataid=\"ai-chat-composer\"\n stoppable\n [placeholder]=\"placeholder()\"\n [sending]=\"sending()\"\n [(text)]=\"draft\"\n (submitted)=\"onSubmitted($event)\"\n (stopped)=\"onStop()\" />\n\n @if (disclaimerText()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\">{{ disclaimerText() }}</p>\n }\n }\n </section>\n</ng-container>\n\n<ng-template #newThreadButton>\n <rt-icon-button\n qa-dataid=\"ai-chat-new-thread\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"ico-plus\"\n [disabled]=\"sending()\"\n [ariaLabel]=\"t().aiNewThread\"\n [tooltip]=\"t().aiNewThread\"\n (clicked)=\"onNewThread()\" />\n</ng-template>\n\n<ng-template #threadList>\n <ng-container rtBlock=\"rt-ai-chat\">\n <rt-thread-list\n rtElem=\"threads\"\n qa-dataid=\"ai-chat-thread-list\"\n [rows]=\"threadRows()\"\n [activeId]=\"activeThreadId()\"\n [searchPlaceholder]=\"t().aiSearchThreads\"\n [emptyText]=\"threadsEmptyText()\"\n [emptyPreviewIcons]=\"emptyPreviewIcons()\"\n [loading]=\"threadsLoading()\"\n [fetching]=\"threadsFetching()\"\n [hasMore]=\"threadsHasMore()\"\n (selectRow)=\"onSelectThread($event)\"\n (searchChange)=\"onSearchThreads($event)\"\n (loadMore)=\"loadMoreThreads.emit()\">\n <ng-template let-row [rtThreadListRow]=\"threadRows()\">\n <span rtElem=\"thread-title\" qa-dataid=\"ai-chat-thread-title\" [attr.title]=\"row.title\">\n @for (part of row.titleParts; track $index) {\n <span rtElem=\"thread-part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n <span rtElem=\"thread-meta\">\n @if (row.unreadCount) {\n <span rtElem=\"thread-unread\" qa-dataid=\"ai-chat-thread-unread\">{{ row.unreadCount }}</span>\n }\n @if (row.time) {\n <span rtElem=\"thread-time\">{{ row.time }}</span>\n }\n </span>\n </ng-template>\n <ng-template let-row [rtThreadListRowActions]=\"threadRows()\">\n @if (threadMenu()) {\n <rt-menu qa-dataid=\"ai-chat-thread-menu\" icon=\"ellipsis-v\" triggerSize=\"xs\" size=\"sm\" [ariaLabel]=\"t().uiMoreActions\">\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-copy-id\"\n icon=\"copy\"\n [label]=\"t().aiCopyThreadId\"\n (selected)=\"onCopyThreadId(row.id)\" />\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-delete\"\n icon=\"trash\"\n danger\n [label]=\"t().uiRemove\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n (selected)=\"deleteThread.emit(row.id)\" />\n </rt-menu>\n } @else {\n <rt-icon-button\n qa-dataid=\"ai-chat-delete-thread\"\n size=\"xs\"\n iconSize=\"sm\"\n icon=\"trash\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n [ariaLabel]=\"t().aiDeleteThread\"\n [tooltip]=\"t().aiDeleteThread\"\n (clicked)=\"deleteThread.emit(row.id)\" />\n }\n </ng-template>\n </rt-thread-list>\n </ng-container>\n</ng-template>\n",
|
|
3169
|
-
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-ai-chat{--rt-ai-chat-bubble-radius: var(--rt-radius-xl);--rt-ai-chat-column-border-width: var(--rt-border-width-thin);--rt-ai-chat-column-width: 280px;--rt-ai-chat-content-max-width: 100%;--rt-ai-chat-match-bg: var(--rt-yellow-400);--rt-ai-chat-match-color: var(--rt-neutral-950);--rt-ai-chat-match-radius: var(--rt-radius-xs);--rt-ai-chat-unread-radius: var(--rt-radius-full);display:flex;overflow:hidden;background:var(--rt-color-bg-surface);block-size:100%;color:var(--rt-color-text-primary);min-block-size:0}.rt-ai-chat__thread-column{display:flex;flex:none;flex-direction:column;border-inline-end:var(--rt-ai-chat-column-border-width) solid var(--rt-color-border-default);inline-size:var(--rt-ai-chat-column-width)}.rt-ai-chat__column-head{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__column-title{font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__conversation{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0}.rt-ai-chat__header{display:flex;flex:none;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__heading{display:flex;flex:1 1 auto;flex-direction:column;min-inline-size:0}.rt-ai-chat__title{display:inline-flex;align-items:center;font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__subtitle{overflow:hidden;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__actions{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__feed{display:flex;flex:1 1 auto;flex-direction:column;font-size:var(--rt-text-sm);gap:var(--rt-space-md);min-block-size:0;overflow-y:auto;padding-block:var(--rt-space-md);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__spinner{align-self:center;margin:auto}.rt-ai-chat__empty{display:flex;flex-direction:column;justify-content:center;gap:var(--rt-space-lg);margin-block:auto}.rt-ai-chat__suggestions{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat__question{display:flex;flex-direction:column;align-items:flex-end;gap:var(--rt-space-2xs)}.rt-ai-chat__question-actions{display:flex;gap:var(--rt-space-xs)}.rt-ai-chat__bubble{display:flex;flex-direction:column;padding:var(--rt-space-sm) var(--rt-space-md);border-radius:var(--rt-ai-chat-bubble-radius);background:var(--rt-color-bg-subtle);gap:var(--rt-space-2xs);max-inline-size:80%}.rt-ai-chat__author,.rt-ai-chat__time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__author{font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__bubble-text{margin:0;line-height:var(--rt-leading-normal);overflow-wrap:anywhere;white-space:pre-wrap}.rt-ai-chat__error{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-ai-chat__error rt-message{align-self:stretch}.rt-ai-chat__composer{box-sizing:border-box;flex:none;padding-block:var(--rt-space-sm) 0;padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__disclaimer{flex:none;margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);padding-block:var(--rt-space-xs) var(--rt-space-sm);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2);text-align:center}.rt-ai-chat__threads{flex:1 1 auto;min-block-size:0}.rt-ai-chat__thread-title{overflow:hidden;min-inline-size:0;text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__thread-part--match{border-radius:var(--rt-ai-chat-match-radius);background:var(--rt-ai-chat-match-bg);color:var(--rt-ai-chat-match-color)}.rt-ai-chat__thread-meta{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__thread-unread{border-radius:var(--rt-ai-chat-unread-radius);background:var(--rt-color-action-primary);color:var(--rt-color-text-inverse);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-semibold);line-height:18px;padding-inline:6px}.rt-ai-chat__thread-time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}}\n"]
|
|
3224
|
+
template: "<ng-container rtBlock=\"rt-ai-chat\">\n @if (isThreadColumn()) {\n <aside rtElem=\"thread-column\" qa-dataid=\"ai-chat-thread-column\" [attr.aria-label]=\"t().aiThreads\">\n <div rtElem=\"column-head\">\n <span rtElem=\"column-title\">{{ t().aiThreads }}</span>\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n </div>\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n </aside>\n }\n\n <section rtElem=\"conversation\" qa-dataid=\"ai-chat\" [attr.aria-label]=\"titleText()\">\n <header rtElem=\"header\" [attr.data-rt-icon-preset]=\"headerIconSign()\">\n @if (isThreadPage()) {\n <rt-icon-button\n #back\n qa-dataid=\"ai-chat-back\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"arrow-left\"\n [ariaLabel]=\"t().aiBackToChat\"\n [tooltip]=\"t().aiBackToChat\"\n (clicked)=\"onToggleThreads()\" />\n }\n\n <div rtElem=\"heading\">\n <span rtElem=\"title\" qa-dataid=\"ai-chat-title\">\n @if (!isThreadPage()) {\n <rt-icon name=\"sparkle\" size=\"sm\" color=\"primary\" aria-hidden=\"true\" />\n }\n {{ isThreadPage() ? t().aiThreads : titleText() }}\n </span>\n @if (!isThreadPage() && subtitle()) {\n <span rtElem=\"subtitle\" qa-dataid=\"ai-chat-subtitle\">{{ subtitle() }}</span>\n }\n </div>\n\n <div rtElem=\"actions\">\n @if (fullScreenable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-full-screen\"\n size=\"sm\"\n iconSize=\"sm\"\n [icon]=\"fullScreen() ? 'window-minimize' : 'fullscreen'\"\n [active]=\"fullScreen()\"\n [ariaLabel]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n [tooltip]=\"fullScreen() ? t().aiExitFullScreen : t().aiFullScreen\"\n (clicked)=\"onToggleFullScreen()\" />\n }\n @if (hasThreads() && !isThreadPage() && !isThreadColumn()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-threads\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"history\"\n [ariaLabel]=\"t().aiThreads\"\n [tooltip]=\"t().aiThreads\"\n (clicked)=\"onToggleThreads()\" />\n }\n @if (!isThreadColumn()) {\n <ng-container [ngTemplateOutlet]=\"newThreadButton\" />\n }\n @if (closable()) {\n <rt-icon-button\n qa-dataid=\"ai-chat-close\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"close\"\n [ariaLabel]=\"t().aiClose\"\n [tooltip]=\"t().aiClose\"\n (clicked)=\"closed.emit()\" />\n }\n </div>\n </header>\n\n @if (isThreadPage()) {\n <ng-container [ngTemplateOutlet]=\"threadList\" />\n } @else {\n <div #feed rtElem=\"feed\" qa-dataid=\"ai-chat-feed\" aria-live=\"polite\" (scroll)=\"onFeedScroll()\">\n @if (loading() && !messages().length) {\n <rt-spinner rtElem=\"spinner\" appearance=\"arc\" [diameter]=\"32\" />\n } @else if (isEmpty()) {\n <div rtElem=\"empty\" qa-dataid=\"ai-chat-empty\">\n <rt-empty-state icon=\"comments\" [title]=\"emptyTitleText()\" [description]=\"emptyDescriptionText()\" />\n @if (suggestions().length) {\n <div rtElem=\"suggestions\">\n @for (suggestion of suggestions(); track suggestion) {\n <rt-prompt-suggestion\n qa-dataid=\"ai-chat-suggestion\"\n [label]=\"suggestion\"\n [disabled]=\"sending()\"\n (picked)=\"onSuggestion($event)\" />\n }\n </div>\n }\n </div>\n }\n\n @for (message of messages(); track message.id) {\n @if (message.role === 'user') {\n <div rtElem=\"question\" qa-dataid=\"ai-chat-question\">\n <div rtElem=\"bubble\">\n <span rtElem=\"author\">{{ t().aiYou }}</span>\n <p rtElem=\"bubble-text\">{{ message.text }}</p>\n @if (message.time) {\n <span rtElem=\"time\">{{ message.time }}</span>\n }\n </div>\n @if (copyable() && message.text) {\n <div rtElem=\"question-actions\" qa-dataid=\"ai-chat-question-actions\">\n <rt-ai-chat-copy [text]=\"message.text\" />\n </div>\n }\n </div>\n } @else {\n <rt-ai-chat-answer\n qa-dataid=\"ai-chat-answer\"\n [message]=\"message\"\n [copyable]=\"copyable()\"\n [extra]=\"extraTemplate()?.templateRef ?? null\"\n [expanded]=\"openRuns().has(message.id)\"\n (expandedChange)=\"onToggleRun(message.id, $event)\"\n (feedbackChange)=\"onFeedback(message, $event)\" />\n }\n }\n\n @if (error(); as runError) {\n <div rtElem=\"error\" qa-dataid=\"ai-chat-error\" role=\"alert\">\n <rt-message severity=\"danger\">{{ runError.message }}</rt-message>\n @if (runError.referenceId) {\n <rt-copy-value [label]=\"t().aiReference\" [value]=\"runError.referenceId\" [copyLabel]=\"t().aiCopyReference\" />\n }\n @if (runError.retryable) {\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"ai-chat-retry\"\n appearance=\"text\"\n icon=\"sync\"\n size=\"sm\"\n [label]=\"t().aiRetry\"\n [attr.aria-label]=\"t().aiRetry\"\n [disabled]=\"sending()\"\n (click)=\"retry.emit()\"></button>\n }\n </div>\n }\n </div>\n\n @if (disclaimerText() && disclaimerAbove()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\" [rtMod]=\"{ above: true }\">{{ disclaimerText() }}</p>\n }\n\n <rt-ai-prompt-input\n rtElem=\"composer\"\n qa-dataid=\"ai-chat-composer\"\n stoppable\n hint=\"\"\n [placeholder]=\"placeholder()\"\n [model]=\"model()\"\n [effort]=\"effort()\"\n [mode]=\"mode()\"\n [usage]=\"usage()\"\n [usageHint]=\"usageHint()\"\n [sending]=\"sending()\"\n [(text)]=\"draft\"\n (submitted)=\"onSubmitted($event)\"\n (stopped)=\"onStop()\"\n (controlPicked)=\"controlPicked.emit($event)\" />\n\n @if (disclaimerText() && !disclaimerAbove()) {\n <p rtElem=\"disclaimer\" qa-dataid=\"ai-chat-disclaimer\">{{ disclaimerText() }}</p>\n }\n }\n </section>\n</ng-container>\n\n<ng-template #newThreadButton>\n <rt-icon-button\n qa-dataid=\"ai-chat-new-thread\"\n size=\"sm\"\n iconSize=\"sm\"\n icon=\"ico-plus\"\n [disabled]=\"sending()\"\n [ariaLabel]=\"t().aiNewThread\"\n [tooltip]=\"t().aiNewThread\"\n (clicked)=\"onNewThread()\" />\n</ng-template>\n\n<ng-template #threadList>\n <ng-container rtBlock=\"rt-ai-chat\">\n <rt-thread-list\n rtElem=\"threads\"\n qa-dataid=\"ai-chat-thread-list\"\n [rows]=\"threadRows()\"\n [activeId]=\"activeThreadId()\"\n [searchPlaceholder]=\"t().aiSearchThreads\"\n [emptyText]=\"threadsEmptyText()\"\n [emptyPreviewIcons]=\"emptyPreviewIcons()\"\n [loading]=\"threadsLoading()\"\n [fetching]=\"threadsFetching()\"\n [hasMore]=\"threadsHasMore()\"\n (selectRow)=\"onSelectThread($event)\"\n (searchChange)=\"onSearchThreads($event)\"\n (loadMore)=\"loadMoreThreads.emit()\">\n <ng-template let-row [rtThreadListRow]=\"threadRows()\">\n <span rtElem=\"thread-title\" qa-dataid=\"ai-chat-thread-title\" [attr.title]=\"row.title\">\n @for (part of row.titleParts; track $index) {\n <span rtElem=\"thread-part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n <span rtElem=\"thread-meta\">\n @if (row.unreadCount) {\n <span rtElem=\"thread-unread\" qa-dataid=\"ai-chat-thread-unread\">{{ row.unreadCount }}</span>\n }\n @if (row.time) {\n <span rtElem=\"thread-time\">{{ row.time }}</span>\n }\n </span>\n </ng-template>\n <ng-template let-row [rtThreadListRowActions]=\"threadRows()\">\n @if (threadMenu()) {\n <rt-menu qa-dataid=\"ai-chat-thread-menu\" icon=\"ellipsis-v\" triggerSize=\"xs\" size=\"sm\" [ariaLabel]=\"t().uiMoreActions\">\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-copy-id\"\n icon=\"copy\"\n [label]=\"t().aiCopyThreadId\"\n (selected)=\"onCopyThreadId(row.id)\" />\n <rt-menu-item\n qa-dataid=\"ai-chat-thread-delete\"\n icon=\"trash\"\n danger\n [label]=\"t().uiRemove\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n (selected)=\"deleteThread.emit(row.id)\" />\n </rt-menu>\n } @else {\n <rt-icon-button\n qa-dataid=\"ai-chat-delete-thread\"\n size=\"xs\"\n iconSize=\"sm\"\n icon=\"trash\"\n [disabled]=\"sending() && row.id === activeThreadId()\"\n [ariaLabel]=\"t().aiDeleteThread\"\n [tooltip]=\"t().aiDeleteThread\"\n (clicked)=\"deleteThread.emit(row.id)\" />\n }\n </ng-template>\n </rt-thread-list>\n </ng-container>\n</ng-template>\n",
|
|
3225
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-ai-chat{--rt-ai-chat-bubble-radius: var(--rt-radius-xl);--rt-ai-chat-column-border-width: var(--rt-border-width-thin);--rt-ai-chat-column-width: 280px;--rt-ai-chat-content-max-width: 100%;--rt-ai-chat-match-bg: var(--rt-yellow-400);--rt-ai-chat-match-color: var(--rt-neutral-950);--rt-ai-chat-match-radius: var(--rt-radius-xs);--rt-ai-chat-unread-radius: var(--rt-radius-full);display:flex;overflow:hidden;background:var(--rt-color-bg-surface);block-size:100%;color:var(--rt-color-text-primary);min-block-size:0}.rt-ai-chat__thread-column{display:flex;flex:none;flex-direction:column;border-inline-end:var(--rt-ai-chat-column-border-width) solid var(--rt-color-border-default);inline-size:var(--rt-ai-chat-column-width)}.rt-ai-chat__column-head{display:flex;align-items:center;justify-content:space-between;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__column-title{font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__conversation{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0}.rt-ai-chat__header{display:flex;flex:none;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);gap:var(--rt-space-xs)}.rt-ai-chat__heading{display:flex;flex:1 1 auto;flex-direction:column;min-inline-size:0}.rt-ai-chat__title{display:inline-flex;align-items:center;font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__subtitle{overflow:hidden;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__actions{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__feed{display:flex;flex:1 1 auto;flex-direction:column;font-size:var(--rt-text-sm);gap:var(--rt-space-md);min-block-size:0;overflow-y:auto;overscroll-behavior:contain;padding-block:var(--rt-space-md);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__spinner{align-self:center;margin:auto}.rt-ai-chat__empty{display:flex;flex-direction:column;justify-content:center;gap:var(--rt-space-lg);margin-block:auto}.rt-ai-chat__suggestions{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-ai-chat__question{display:flex;flex-direction:column;align-items:flex-end;gap:var(--rt-space-2xs)}.rt-ai-chat__question-actions{display:flex;gap:var(--rt-space-xs)}.rt-ai-chat__bubble{display:flex;flex-direction:column;padding:var(--rt-space-sm) var(--rt-space-md);border-radius:var(--rt-ai-chat-bubble-radius);background:var(--rt-color-bg-subtle);gap:var(--rt-space-2xs);max-inline-size:80%}.rt-ai-chat__author,.rt-ai-chat__time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug)}.rt-ai-chat__author{font-weight:var(--rt-font-weight-semibold)}.rt-ai-chat__bubble-text{margin:0;line-height:var(--rt-leading-normal);overflow-wrap:anywhere;white-space:pre-wrap}.rt-ai-chat__error{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-ai-chat__error rt-message{align-self:stretch}.rt-ai-chat__composer{box-sizing:border-box;flex:none;padding-block:var(--rt-space-sm) 0;padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2)}.rt-ai-chat__disclaimer{flex:none;margin:0;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);line-height:var(--rt-leading-snug);padding-block:var(--rt-space-xs) var(--rt-space-sm);padding-inline:max(var(--rt-space-md),(100% - var(--rt-ai-chat-content-max-width)) / 2);text-align:center}.rt-ai-chat__disclaimer--above{padding-block:var(--rt-space-sm) 0}.rt-ai-chat__threads{flex:1 1 auto;min-block-size:0}.rt-ai-chat__thread-title{overflow:hidden;min-inline-size:0;text-overflow:ellipsis;white-space:nowrap}.rt-ai-chat__thread-part--match{border-radius:var(--rt-ai-chat-match-radius);background:var(--rt-ai-chat-match-bg);color:var(--rt-ai-chat-match-color)}.rt-ai-chat__thread-meta{display:flex;flex:none;align-items:center;gap:var(--rt-space-xs)}.rt-ai-chat__thread-unread{border-radius:var(--rt-ai-chat-unread-radius);background:var(--rt-color-action-primary);color:var(--rt-color-text-inverse);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-semibold);line-height:18px;padding-inline:6px}.rt-ai-chat__thread-time{color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}}\n"]
|
|
3170
3226
|
}]
|
|
3171
3227
|
}],
|
|
3172
3228
|
ctorParameters: () => [],
|
|
3173
3229
|
propDecorators: {
|
|
3174
3230
|
composer: [{
|
|
3175
3231
|
type: i0.ViewChild,
|
|
3176
|
-
args: [i0.forwardRef(() =>
|
|
3232
|
+
args: [i0.forwardRef(() => RtAiPromptInputComponent), { isSignal: true }]
|
|
3177
3233
|
}],
|
|
3178
3234
|
backButton: [{
|
|
3179
3235
|
type: i0.ViewChild,
|
|
@@ -3254,6 +3310,54 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3254
3310
|
required: false
|
|
3255
3311
|
}]
|
|
3256
3312
|
}],
|
|
3313
|
+
disclaimerPosition: [{
|
|
3314
|
+
type: i0.Input,
|
|
3315
|
+
args: [{
|
|
3316
|
+
isSignal: true,
|
|
3317
|
+
alias: "disclaimerPosition",
|
|
3318
|
+
required: false
|
|
3319
|
+
}]
|
|
3320
|
+
}],
|
|
3321
|
+
model: [{
|
|
3322
|
+
type: i0.Input,
|
|
3323
|
+
args: [{
|
|
3324
|
+
isSignal: true,
|
|
3325
|
+
alias: "model",
|
|
3326
|
+
required: false
|
|
3327
|
+
}]
|
|
3328
|
+
}],
|
|
3329
|
+
effort: [{
|
|
3330
|
+
type: i0.Input,
|
|
3331
|
+
args: [{
|
|
3332
|
+
isSignal: true,
|
|
3333
|
+
alias: "effort",
|
|
3334
|
+
required: false
|
|
3335
|
+
}]
|
|
3336
|
+
}],
|
|
3337
|
+
mode: [{
|
|
3338
|
+
type: i0.Input,
|
|
3339
|
+
args: [{
|
|
3340
|
+
isSignal: true,
|
|
3341
|
+
alias: "mode",
|
|
3342
|
+
required: false
|
|
3343
|
+
}]
|
|
3344
|
+
}],
|
|
3345
|
+
usage: [{
|
|
3346
|
+
type: i0.Input,
|
|
3347
|
+
args: [{
|
|
3348
|
+
isSignal: true,
|
|
3349
|
+
alias: "usage",
|
|
3350
|
+
required: false
|
|
3351
|
+
}]
|
|
3352
|
+
}],
|
|
3353
|
+
usageHint: [{
|
|
3354
|
+
type: i0.Input,
|
|
3355
|
+
args: [{
|
|
3356
|
+
isSignal: true,
|
|
3357
|
+
alias: "usageHint",
|
|
3358
|
+
required: false
|
|
3359
|
+
}]
|
|
3360
|
+
}],
|
|
3257
3361
|
sending: [{
|
|
3258
3362
|
type: i0.Input,
|
|
3259
3363
|
args: [{
|
|
@@ -3438,6 +3542,10 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
3438
3542
|
feedbackChange: [{
|
|
3439
3543
|
type: i0.Output,
|
|
3440
3544
|
args: ["feedbackChange"]
|
|
3545
|
+
}],
|
|
3546
|
+
controlPicked: [{
|
|
3547
|
+
type: i0.Output,
|
|
3548
|
+
args: ["controlPicked"]
|
|
3441
3549
|
}]
|
|
3442
3550
|
}
|
|
3443
3551
|
});
|